#![warn(missing_docs)]
use failure;
pub fn new() -> Output {
Output::default()
}
#[derive(Default, Clone)]
pub struct Output {
inner: Arc<Mutex<InnerOutput>>,
}
#[derive(Default, Clone)]
struct InnerOutput {
targets: Vec<Target>,
#[cfg(feature = "log")]
log_level: Option<log::Level>,
}
impl Output {
pub fn add_target(self, target: Target) -> Result<Self, Error> {
{
let mut o = self.inner.lock().map_err(|e| Error::sync_error(&e))?;
o.targets.push(target);
}
Ok(self)
}
#[cfg(feature = "log")]
pub fn use_as_logger(self, level: log::Level) -> Result<Self, Error> {
{
let mut o = self.inner.lock().map_err(|e| Error::sync_error(&e))?;
o.log_level = Some(level);
}
log::set_boxed_logger(Box::new(self.clone()))?;
log::set_max_level(level.to_level_filter());
Ok(self)
}
}
#[test]
fn assert_output_is_sync_and_send() {
fn assert_both<T: Send + Sync>() {}
assert_both::<Output>();
}
use std::sync::{Arc, Mutex};
#[derive(Clone)]
pub struct Target {
inner: InnerTarget,
}
impl Target {
pub(crate) fn human(f: human::Formatter) -> Self {
Target {
inner: InnerTarget::Human(Arc::new(Mutex::new(f))),
}
}
pub(crate) fn json(f: json::Formatter) -> Self {
Target {
inner: InnerTarget::Json(Arc::new(Mutex::new(f))),
}
}
}
#[derive(Clone)]
enum InnerTarget {
Human(Arc<Mutex<human::Formatter>>),
Json(Arc<Mutex<json::Formatter>>),
}
mod error;
pub use crate::error::Error;
impl Output {
pub fn print<O: Render>(&self, item: O) -> Result<(), Error> {
let mut o = self.inner.lock().map_err(|e| Error::sync_error(&e))?;
for target in &mut o.targets {
match &target.inner {
InnerTarget::Human(fmt) => {
let mut fmt = fmt.lock().map_err(|e| Error::sync_error(&e))?;
item.render_for_humans(&mut *fmt)?;
fmt.write("\n")?;
}
InnerTarget::Json(fmt) => {
let mut fmt = fmt.lock().map_err(|e| Error::sync_error(&e))?;
item.render_json(&mut *fmt)?;
fmt.write_separator()?;
}
}
}
Ok(())
}
pub fn flush(&self) -> Result<(), Error> {
let o = self.inner.lock().map_err(|e| Error::sync_error(&e))?;
for target in &o.targets {
match &target.inner {
InnerTarget::Human(fmt) => {
let fmt = fmt.lock().map_err(|e| Error::sync_error(&e))?;
fmt.flush()?;
}
InnerTarget::Json(fmt) => {
let fmt = fmt.lock().map_err(|e| Error::sync_error(&e))?;
fmt.flush()?;
}
}
}
Ok(())
}
}
pub trait Render {
fn render_for_humans(&self, fmt: &mut human::Formatter) -> Result<(), Error>;
fn render_json(&self, fmt: &mut json::Formatter) -> Result<(), Error>;
}
impl<'a, T> Render for &'a T
where
T: Render,
{
fn render_for_humans(&self, fmt: &mut human::Formatter) -> Result<(), Error> {
(*self).render_for_humans(fmt)
}
fn render_json(&self, fmt: &mut json::Formatter) -> Result<(), Error> {
(*self).render_json(fmt)
}
}
impl<'a> Render for &'a str {
fn render_for_humans(&self, fmt: &mut human::Formatter) -> Result<(), Error> {
fmt.write(self.as_bytes())?;
Ok(())
}
fn render_json(&self, fmt: &mut json::Formatter) -> Result<(), Error> {
fmt.write(&self)?;
Ok(())
}
}
impl<'a> Render for String {
fn render_for_humans(&self, fmt: &mut human::Formatter) -> Result<(), Error> {
fmt.write(self.as_bytes())?;
Ok(())
}
fn render_json(&self, fmt: &mut json::Formatter) -> Result<(), Error> {
fmt.write(&self)?;
Ok(())
}
}
pub mod components;
pub mod human;
pub mod json;
#[cfg(feature = "log")]
mod logging;
mod test_buffer;