batch_run 1.2.0

Batch runner for arbitrary Rust files within current project
Documentation
//! Configuration for the batch runner.

use crate::result::{BatchError, BatchResult, ConfigError};
use std::env;
use termcolor::{Buffer, ColorChoice, StandardStream, WriteColor};

/// Main configuration struct.
///
/// This could be set by the user when creating a batch runner, if the default configuration
/// is for some reason not appropriate.
///
/// Configuration describes two desitions:
/// - what to do when there's no expected output for some entry - this is guided by [`Update`] enum;
/// - what to do with the runner output - this is configured using [`WriterBuilder`] struct.
///
/// For convinient methods of creating `Config`, see [`Config::from_env`], [`Config::new`] and [`Config::with_buffer`].
pub struct Config<W: WriteColor> {
    update_mode: Update,
    writer: WriterBuilder<W>,
}

impl Config<StandardStream> {
    /// Default method of creating config struct.
    ///
    /// In this case, the following configuration is assumed:
    /// - update mode is taken from the BATCH_RUN environment variable,
    /// - output is written directly on screen.
    pub fn from_env() -> BatchResult<Self> {
        Ok(Self {
            update_mode: Update::env()?,
            writer: WriterBuilder::default(),
        })
    }
}
impl<W: WriteColor> Config<W> {

    /// Explicit constructor for `Config`.
    pub fn new(update_mode: Update, writer: WriterBuilder<W>) -> Self {
        Self { update_mode, writer }
    }

    pub fn with_buffer(self) -> Config<Buffer> {
        Config {
            update_mode: self.update_mode,
            writer: WriterBuilder::buffer(),
        }
    }

    pub fn with_stderr_no_color(self) -> Config<StandardStream> {
        Config {
            update_mode: self.update_mode,
            writer: WriterBuilder::no_color(),
        }
    }
        
    pub fn update_mode(&self) -> Update {
        self.update_mode
    }

    pub fn writer(&self) -> &WriterBuilder<W> {
        &self.writer
    }
}

/// Update mode for entries without expected output.
///
/// By default, this is set from the BATCH_RUN environment variable.
/// Value "wip" corresponds to [Wip] mode.
/// Value "overwrite" corresponds to [Overwrite] mode.
/// Otherwise, the [BatchError] is returned.
///
/// [Wip]: self::Update::Wip
/// [Overwrite]: self::Update::Overwrite
/// [BatchError]: crate::result::BatchError
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum Update {
    /// Actual output will be written to "./wip".
    Wip,
    /// Actual output will be written directly into the snapshot.
    Overwrite,
}

impl Update {
    fn env() -> BatchResult<Self> {
        let var = match env::var_os("BATCH_RUN") {
            Some(var) => var,
            None => return Ok(Update::Wip),
        };

        match var.as_os_str().to_str() {
            Some("wip") => Ok(Update::Wip),
            Some("overwrite") => Ok(Update::Overwrite),
            _ => Err(BatchError::ConfigError(ConfigError::UpdateEnvVar(var))),
        }
    }
}

pub struct WriterBuilder<W: WriteColor>(Box<dyn Fn() -> W>);

impl<W: WriteColor> WriterBuilder<W> {
    pub fn new<F: Fn() -> W + 'static>(inner: F) -> Self
    where
        W: 'static,
    {
        Self(Box::new(inner))
    }
    pub(crate) fn build(&self) -> W {
        self.0()
    }
}

impl Default for WriterBuilder<StandardStream> {
    fn default() -> Self {
        Self(Box::new(|| StandardStream::stderr(ColorChoice::Always)))
    }
}

impl WriterBuilder<Buffer> {
    pub fn buffer() -> Self {
        Self(Box::new(crate::term::buf))
    }
}

impl WriterBuilder<StandardStream> {
    pub fn no_color() -> Self {
        Self(Box::new(|| StandardStream::stderr(ColorChoice::Never)))
    }
}