use std::io::prelude::*;
use std::io;
use std::fmt;
use termcolor::{Color, ColorSpec, Buffer, WriteColor};
use chrono::{DateTime, Utc};
use chrono::format::Item;
pub struct Formatter {
buf: Buffer,
}
pub(crate) struct StyledFormatter<W> {
buf: W,
spec: ColorSpec,
}
pub(crate) struct Timestamp(DateTime<Utc>);
impl Formatter {
pub(crate) fn new(buf: Buffer) -> Self {
Formatter {
buf: buf,
}
}
pub(crate) fn color(&mut self, color: Color) -> StyledFormatter<&mut Buffer> {
let mut spec = ColorSpec::new();
spec.set_fg(Some(color));
StyledFormatter {
buf: &mut self.buf,
spec: spec
}
}
pub(crate) fn timestamp(&self) -> Timestamp {
Timestamp(Utc::now())
}
pub(crate) fn as_ref(&self) -> &Buffer {
&self.buf
}
pub(crate) fn clear(&mut self) {
self.buf.clear()
}
}
impl Write for Formatter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.buf.write(buf)
}
fn flush(&mut self) -> io::Result<()> {
self.buf.flush()
}
}
impl<W> Write for StyledFormatter<W>
where W: WriteColor
{
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.buf.set_color(&self.spec)?;
let write = self.buf.write(buf);
let reset = self.buf.reset();
write.and_then(|w| reset.map(|_| w))
}
fn flush(&mut self) -> io::Result<()> {
self.buf.flush()
}
}
impl fmt::Debug for Formatter{
fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result {
f.debug_struct("Formatter").finish()
}
}
impl fmt::Display for Timestamp{
fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result {
const ITEMS: &'static [Item<'static>] = {
use chrono::format::Item::*;
use chrono::format::Numeric::*;
use chrono::format::Fixed::*;
use chrono::format::Pad::*;
&[
Numeric(Year, Zero),
Literal("-"),
Numeric(Month, Zero),
Literal("-"),
Numeric(Day, Zero),
Literal("T"),
Numeric(Hour, Zero),
Literal(":"),
Numeric(Minute, Zero),
Literal(":"),
Numeric(Second, Zero),
Fixed(TimezoneOffsetZ),
]
};
self.0.format_with_items(ITEMS.iter().cloned()).fmt(f)
}
}