<commit_before>//! Unix terminal formatter and drain for slog-rs
//!
//! ```
//! #[macro_use]
//! extern crate slog;
//! extern crate slog_term;
//!
//! use slog::*;
//!
//! fn main() {
//!     let root = Logger::root(slog_term::streamer().build().fuse(), o!("build-id" => "8dfljdf"));
//! }
//! ```
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate slog_stream;
extern crate isatty;
extern crate ansi_term;
extern crate chrono;

use std::{io, fmt, sync};

use ansi_term::Colour;
use isatty::{stderr_isatty, stdout_isatty};

use slog::Record;
use slog::ser;
use slog::{Level, OwnedKeyValueList};
use slog_stream::Format as StreamFormat;
use slog_stream::{Decorator, RecordDecorator, Streamer, AsyncStreamer};

/// Formatting mode
pub enum FormatMode {
    /// Compact logging format
    Compact,
    /// Full logging format
    Full,
}

/// Full formatting with optional color support
pub struct Format<D: Decorator> {
    mode: FormatMode,
    decorator: D,
    history: sync::Mutex<Vec<usize>>,
}

impl<D: Decorator> Format<D> {
    /// New Format format that prints using color
    pub fn new(mode: FormatMode, d: D) -> Self {
        Format {
            decorator: d,
            mode: mode,
            history: sync::Mutex::new(vec![]),
        }
    }

    fn print_msg_header(&self,
                        io: &mut io::Write,
                        rd: &D::RecordDecorator,
                        info: &Record)
                        -> io::Result<()> {
        let ts = chrono::Local::now();
        try!(rd.fmt_timestamp(io, format_args!("{} ", ts.format("%b %d %H:%M:%S%.3f"))));
        try!(rd.fmt_level(io, format_args!("{} ", info.level().as_short_str())));

        try!(rd.fmt_msg(io, format_args!("{}", info.msg())));
        Ok(())
    }
    fn format_full(&self,
                   io: &mut io::Write,
                   info: &Record,
                   logger_values: &OwnedKeyValueList)
                   -> io::Result<()> {

        let r_decorator = self.decorator.decorate(info);

        try!(self.print_msg_header(io, &r_decorator, info));
        let mut serializer = Serializer::new(io, r_decorator);

        for &(ref k, ref v) in logger_values.iter() {
            try!(serializer.print_comma());
            try!(v.serialize(info, k, &mut serializer));
        }

        for &(k, v) in info.values() {
            try!(serializer.print_comma());
            try!(v.serialize(info, k, &mut serializer));
        }
        let (mut io, _decorator_r) = serializer.finish();

        let _ = try!(write!(io, "\n"));

        Ok(())
    }

    fn format_compact(&self,
                      io: &mut io::Write,
                      info: &Record,
                      logger_values: &OwnedKeyValueList)
                      -> io::Result<()> {

        let r_decorator = self.decorator.decorate(info);
        let mut ser = Serializer::new(io, r_decorator);

        let indent = try!(self.format_recurse(&mut ser, info, logger_values));

        try!(self.print_indent(&mut ser.io, indent));

        try!(self.print_msg_header(&mut ser.io, &ser.decorator, info));

        for &(k, v) in info.values() {
            try!(ser.print_comma());
            try!(v.serialize(info, k, &mut ser));
        }
        try!(write!(&mut ser.io, "\n"));

        Ok(())
    }

    fn print_indent<W: io::Write>(&self, io: &mut W, indent: usize) -> io::Result<()> {
        for _ in 0..indent {
            try!(write!(io, "  "));
        }
        Ok(())
    }

    // record in the history, and check if should print
    // given set of values
    fn should_print(&self, address: usize, indent: usize) -> bool {
        let mut history = self.history.lock().unwrap();
        if history.len() <= indent {
            debug_assert_eq!(history.len(), indent);
            history.push(address);
            true
        } else {
            let should = history[indent] != address;
            history[indent] = address;
            should
        }
    }

    fn format_recurse<W: io::Write>(&self,
                                    ser: &mut Serializer<W, D::RecordDecorator>,
                                    info: &slog::Record,
                                    logger_values: &slog::OwnedKeyValueList)
                                    -> io::Result<usize> {
        let mut indent = if logger_values.parent().is_none() {
            0
        } else {
            try!(self.format_recurse(ser, info, logger_values.parent().as_ref().unwrap()))
        };

        if !logger_values.values().is_empty() {
            if self.should_print(logger_values.values() as *const _ as usize, indent) {
                try!(self.print_indent(&mut ser.io, indent));
                let mut clean = true;
                for &(ref k, ref v) in logger_values.values() {
                    if !clean {
                        try!(ser.print_comma());
                    }
                    try!(v.serialize(info, k, ser));
                    clean = false;
                }
                try!(write!(&mut ser.io, "\n"));
            }
            indent += 1
        }

        Ok(indent)
    }
}

fn severity_to_color(lvl: Level) -> u8 {
    match lvl {
        Level::Critical => 1,
        Level::Error => 9,
        Level::Warning => 3,
        Level::Info => 2,
        Level::Debug => 6,
        Level::Trace => 4,
    }
}

/// Decorator that can colors things
pub struct ColorDecorator {
    use_color: bool,
}

impl ColorDecorator {
    /// New decorator that does color records
    pub fn new_colored() -> Self {
        ColorDecorator { use_color: true }
    }
    /// New decorator that does not color records
    pub fn new_plain() -> Self {
        ColorDecorator { use_color: true }
    }
}

/// Decorator that colors things
pub struct ColorRecordDecorator {
    level_color: Option<Colour>,
    key_style: Option<ansi_term::Style>,
}

impl Decorator for ColorDecorator {
    type RecordDecorator = ColorRecordDecorator;

    fn decorate(&self, record: &Record) -> ColorRecordDecorator {
        if self.use_color {
            ColorRecordDecorator {
                level_color: Some(Colour::Fixed(severity_to_color(record.level()))),
                key_style: Some(ansi_term::Style::new().bold()),
            }
        } else {
            ColorRecordDecorator {
                level_color: None,
                key_style: None,
            }
        }
    }
}

impl RecordDecorator for ColorRecordDecorator {
    fn fmt_level(&self, io: &mut io::Write, args: fmt::Arguments) -> io::Result<()> {
        if let Some(level_color) = self.level_color {
            write!(io, "{}", level_color.paint(format!("{}", args)))
        } else {
            io.write_fmt(args)
        }
    }

    fn fmt_msg(&self, io: &mut io::Write, args: fmt::Arguments) -> io::Result<()> {
        if let Some(key_style) = self.key_style {
            write!(io, "{}", key_style.paint(format!("{}", args)))
        } else {
            io.write_fmt(args)
        }
    }

    fn fmt_key(&self, io: &mut io::Write, args: fmt::Arguments) -> io::Result<()> {
        self.fmt_msg(io, args)
    }
}

struct Serializer<W, D: RecordDecorator> {
    io: W,
    decorator: D,
}

impl<W: io::Write, D: RecordDecorator> Serializer<W, D> {
    fn new(io: W, d: D) -> Self {
        Serializer {
            io: io,
            decorator: d,
        }
    }

    fn print_comma(&mut self) -> io::Result<()> {
        try!(self.decorator.fmt_separator(&mut self.io, format_args!(", ")));
        Ok(())
    }

    fn finish(self) -> (W, D) {
        (self.io, self.decorator)
    }
}

macro_rules! s(
    ($s:expr, $k:expr, $v:expr) => {
        try!($s.decorator.fmt_key(&mut $s.io, format_args!("{}", $k)));
        try!($s.decorator.fmt_separator(&mut $s.io, format_args!(": ")));
        try!($s.decorator.fmt_value(&mut $s.io, format_args!("{}", $v)));
    };
);

impl<W: io::Write, D: RecordDecorator> slog::ser::Serializer for Serializer<W, D> {
    fn emit_none(&mut self, key: &str) -> ser::Result {
        s!(self, key, "None");
        Ok(())
    }
    fn emit_unit(&mut self, key: &str) -> ser::Result {
        s!(self, key, "()");
        Ok(())
    }

    fn emit_bool(&mut self, key: &str, val: bool) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }

    fn emit_char(&mut self, key: &str, val: char) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }

    fn emit_usize(&mut self, key: &str, val: usize) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_isize(&mut self, key: &str, val: isize) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }

    fn emit_u8(&mut self, key: &str, val: u8) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_i8(&mut self, key: &str, val: i8) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_u16(&mut self, key: &str, val: u16) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_i16(&mut self, key: &str, val: i16) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_u32(&mut self, key: &str, val: u32) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_i32(&mut self, key: &str, val: i32) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_f32(&mut self, key: &str, val: f32) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_u64(&mut self, key: &str, val: u64) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_i64(&mut self, key: &str, val: i64) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_f64(&mut self, key: &str, val: f64) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_str(&mut self, key: &str, val: &str) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }

}

impl<D: Decorator + Send + Sync> StreamFormat for Format<D> {
    fn format(&self,
              io: &mut io::Write,
              info: &Record,
              logger_values: &OwnedKeyValueList)
              -> io::Result<()> {
        match self.mode {
            FormatMode::Compact => self.format_compact(io, info, logger_values),
            FormatMode::Full => self.format_full(io, info, logger_values),
        }
    }
}

/// Streamer builder
pub struct StreamerBuilder {
    color: Option<bool>, // None = auto
    stdout: bool,
    async: bool,
    mode: FormatMode,
}

impl StreamerBuilder {
    /// New `StreamerBuilder`
    pub fn new() -> Self {
        StreamerBuilder {
            color: None,
            stdout: true,
            async: false,
            mode: FormatMode::Full,
        }
    }

    /// Force colored output
    pub fn color(mut self) -> Self {
        self.color = Some(true);
        self
    }

    /// Force plain output
    pub fn plain(mut self) -> Self {
        self.color = Some(false);
        self
    }

    /// Auto detect color (default)
    pub fn auto_color(mut self) -> Self {
        self.color = None;
        self
    }

    /// Output to stderr
    pub fn stderr(mut self) -> Self {
        self.stdout = false;
        self
    }

    /// Output to stdout (default)
    pub fn stdout(mut self) -> Self {
        self.stdout = true;
        self
    }

    /// Output using full mode
    pub fn full(mut self) -> Self {
        self.mode = FormatMode::Full;
        self
    }

    /// Output using compact mode (default)
    pub fn compact(mut self) -> Self {
        self.mode = FormatMode::Compact;
        self
    }

    /// Use asynchronous streamer
    pub fn async(mut self) -> Self {
        self.async = true;
        self
    }

    /// Use synchronous streamer (default)
    pub fn sync(mut self) -> Self {
        self.async = false;
        self
    }

    /// Build the streamer
    pub fn build(self) -> Box<slog::Drain<Error=io::Error>> {
        let color = self.color.unwrap_or(if self.stdout {
            stdout_isatty()
        } else {
            stderr_isatty()
        });

        let format = Format::new(self.mode, ColorDecorator { use_color: color });
        let io = if self.stdout {
            Box::new(io::stdout()) as Box<io::Write + Send>
        } else {
            Box::new(io::stderr()) as Box<io::Write + Send>
        };

        if self.async {
            Box::new(AsyncStreamer::new(io, format))
        } else {
            Box::new(Streamer::new(io, format))
        }
    }
}

/// Build `Streamer`/`AsyncStreamer`
pub fn streamer() -> StreamerBuilder {
    StreamerBuilder::new()
}
<commit_msg>Hide `slog_term` non-builder construction.<commit_after>//! Unix terminal formatter and drain for slog-rs
//!
//! ```
//! #[macro_use]
//! extern crate slog;
//! extern crate slog_term;
//!
//! use slog::*;
//!
//! fn main() {
//!     let root = Logger::root(slog_term::streamer().build().fuse(), o!("build-id" => "8dfljdf"));
//! }
//! ```
#![warn(missing_docs)]

#[macro_use]
extern crate slog;
extern crate slog_stream;
extern crate isatty;
extern crate ansi_term;
extern crate chrono;

use std::{io, fmt, sync};

use ansi_term::Colour;
use isatty::{stderr_isatty, stdout_isatty};

use slog::Record;
use slog::ser;
use slog::{Level, OwnedKeyValueList};
use slog_stream::Format as StreamFormat;
use slog_stream::{Decorator, RecordDecorator, Streamer, AsyncStreamer};

/// Formatting mode
enum FormatMode {
    /// Compact logging format
    Compact,
    /// Full logging format
    Full,
}

/// Full formatting with optional color support
pub struct Format<D: Decorator> {
    mode: FormatMode,
    decorator: D,
    history: sync::Mutex<Vec<usize>>,
}

impl<D: Decorator> Format<D> {
    /// New Format format that prints using color
    fn new(mode: FormatMode, d: D) -> Self {
        Format {
            decorator: d,
            mode: mode,
            history: sync::Mutex::new(vec![]),
        }
    }

    fn print_msg_header(&self,
                        io: &mut io::Write,
                        rd: &D::RecordDecorator,
                        info: &Record)
                        -> io::Result<()> {
        let ts = chrono::Local::now();
        try!(rd.fmt_timestamp(io, format_args!("{} ", ts.format("%b %d %H:%M:%S%.3f"))));
        try!(rd.fmt_level(io, format_args!("{} ", info.level().as_short_str())));

        try!(rd.fmt_msg(io, format_args!("{}", info.msg())));
        Ok(())
    }
    fn format_full(&self,
                   io: &mut io::Write,
                   info: &Record,
                   logger_values: &OwnedKeyValueList)
                   -> io::Result<()> {

        let r_decorator = self.decorator.decorate(info);

        try!(self.print_msg_header(io, &r_decorator, info));
        let mut serializer = Serializer::new(io, r_decorator);

        for &(ref k, ref v) in logger_values.iter() {
            try!(serializer.print_comma());
            try!(v.serialize(info, k, &mut serializer));
        }

        for &(k, v) in info.values() {
            try!(serializer.print_comma());
            try!(v.serialize(info, k, &mut serializer));
        }
        let (mut io, _decorator_r) = serializer.finish();

        let _ = try!(write!(io, "\n"));

        Ok(())
    }

    fn format_compact(&self,
                      io: &mut io::Write,
                      info: &Record,
                      logger_values: &OwnedKeyValueList)
                      -> io::Result<()> {

        let r_decorator = self.decorator.decorate(info);
        let mut ser = Serializer::new(io, r_decorator);

        let indent = try!(self.format_recurse(&mut ser, info, logger_values));

        try!(self.print_indent(&mut ser.io, indent));

        try!(self.print_msg_header(&mut ser.io, &ser.decorator, info));

        for &(k, v) in info.values() {
            try!(ser.print_comma());
            try!(v.serialize(info, k, &mut ser));
        }
        try!(write!(&mut ser.io, "\n"));

        Ok(())
    }

    fn print_indent<W: io::Write>(&self, io: &mut W, indent: usize) -> io::Result<()> {
        for _ in 0..indent {
            try!(write!(io, "  "));
        }
        Ok(())
    }

    // record in the history, and check if should print
    // given set of values
    fn should_print(&self, address: usize, indent: usize) -> bool {
        let mut history = self.history.lock().unwrap();
        if history.len() <= indent {
            debug_assert_eq!(history.len(), indent);
            history.push(address);
            true
        } else {
            let should = history[indent] != address;
            history[indent] = address;
            should
        }
    }

    fn format_recurse<W: io::Write>(&self,
                                    ser: &mut Serializer<W, D::RecordDecorator>,
                                    info: &slog::Record,
                                    logger_values: &slog::OwnedKeyValueList)
                                    -> io::Result<usize> {
        let mut indent = if logger_values.parent().is_none() {
            0
        } else {
            try!(self.format_recurse(ser, info, logger_values.parent().as_ref().unwrap()))
        };

        if !logger_values.values().is_empty() {
            if self.should_print(logger_values.values() as *const _ as usize, indent) {
                try!(self.print_indent(&mut ser.io, indent));
                let mut clean = true;
                for &(ref k, ref v) in logger_values.values() {
                    if !clean {
                        try!(ser.print_comma());
                    }
                    try!(v.serialize(info, k, ser));
                    clean = false;
                }
                try!(write!(&mut ser.io, "\n"));
            }
            indent += 1
        }

        Ok(indent)
    }
}

fn severity_to_color(lvl: Level) -> u8 {
    match lvl {
        Level::Critical => 1,
        Level::Error => 9,
        Level::Warning => 3,
        Level::Info => 2,
        Level::Debug => 6,
        Level::Trace => 4,
    }
}

/// Decorator that can colors things
pub struct ColorDecorator {
    use_color: bool,
}

impl ColorDecorator {
    /// New decorator that does color records
    pub fn new_colored() -> Self {
        ColorDecorator { use_color: true }
    }
    /// New decorator that does not color records
    pub fn new_plain() -> Self {
        ColorDecorator { use_color: true }
    }
}

/// Decorator that colors things
pub struct ColorRecordDecorator {
    level_color: Option<Colour>,
    key_style: Option<ansi_term::Style>,
}

impl Decorator for ColorDecorator {
    type RecordDecorator = ColorRecordDecorator;

    fn decorate(&self, record: &Record) -> ColorRecordDecorator {
        if self.use_color {
            ColorRecordDecorator {
                level_color: Some(Colour::Fixed(severity_to_color(record.level()))),
                key_style: Some(ansi_term::Style::new().bold()),
            }
        } else {
            ColorRecordDecorator {
                level_color: None,
                key_style: None,
            }
        }
    }
}

impl RecordDecorator for ColorRecordDecorator {
    fn fmt_level(&self, io: &mut io::Write, args: fmt::Arguments) -> io::Result<()> {
        if let Some(level_color) = self.level_color {
            write!(io, "{}", level_color.paint(format!("{}", args)))
        } else {
            io.write_fmt(args)
        }
    }

    fn fmt_msg(&self, io: &mut io::Write, args: fmt::Arguments) -> io::Result<()> {
        if let Some(key_style) = self.key_style {
            write!(io, "{}", key_style.paint(format!("{}", args)))
        } else {
            io.write_fmt(args)
        }
    }

    fn fmt_key(&self, io: &mut io::Write, args: fmt::Arguments) -> io::Result<()> {
        self.fmt_msg(io, args)
    }
}

struct Serializer<W, D: RecordDecorator> {
    io: W,
    decorator: D,
}

impl<W: io::Write, D: RecordDecorator> Serializer<W, D> {
    fn new(io: W, d: D) -> Self {
        Serializer {
            io: io,
            decorator: d,
        }
    }

    fn print_comma(&mut self) -> io::Result<()> {
        try!(self.decorator.fmt_separator(&mut self.io, format_args!(", ")));
        Ok(())
    }

    fn finish(self) -> (W, D) {
        (self.io, self.decorator)
    }
}

macro_rules! s(
    ($s:expr, $k:expr, $v:expr) => {
        try!($s.decorator.fmt_key(&mut $s.io, format_args!("{}", $k)));
        try!($s.decorator.fmt_separator(&mut $s.io, format_args!(": ")));
        try!($s.decorator.fmt_value(&mut $s.io, format_args!("{}", $v)));
    };
);

impl<W: io::Write, D: RecordDecorator> slog::ser::Serializer for Serializer<W, D> {
    fn emit_none(&mut self, key: &str) -> ser::Result {
        s!(self, key, "None");
        Ok(())
    }
    fn emit_unit(&mut self, key: &str) -> ser::Result {
        s!(self, key, "()");
        Ok(())
    }

    fn emit_bool(&mut self, key: &str, val: bool) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }

    fn emit_char(&mut self, key: &str, val: char) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }

    fn emit_usize(&mut self, key: &str, val: usize) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_isize(&mut self, key: &str, val: isize) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }

    fn emit_u8(&mut self, key: &str, val: u8) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_i8(&mut self, key: &str, val: i8) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_u16(&mut self, key: &str, val: u16) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_i16(&mut self, key: &str, val: i16) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_u32(&mut self, key: &str, val: u32) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_i32(&mut self, key: &str, val: i32) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_f32(&mut self, key: &str, val: f32) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_u64(&mut self, key: &str, val: u64) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_i64(&mut self, key: &str, val: i64) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_f64(&mut self, key: &str, val: f64) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_str(&mut self, key: &str, val: &str) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> ser::Result {
        s!(self, key, val);
        Ok(())
    }

}

impl<D: Decorator + Send + Sync> StreamFormat for Format<D> {
    fn format(&self,
              io: &mut io::Write,
              info: &Record,
              logger_values: &OwnedKeyValueList)
              -> io::Result<()> {
        match self.mode {
            FormatMode::Compact => self.format_compact(io, info, logger_values),
            FormatMode::Full => self.format_full(io, info, logger_values),
        }
    }
}

/// Streamer builder
pub struct StreamerBuilder {
    color: Option<bool>, // None = auto
    stdout: bool,
    async: bool,
    mode: FormatMode,
}

impl StreamerBuilder {
    /// New `StreamerBuilder`
    pub fn new() -> Self {
        StreamerBuilder {
            color: None,
            stdout: true,
            async: false,
            mode: FormatMode::Full,
        }
    }

    /// Force colored output
    pub fn color(mut self) -> Self {
        self.color = Some(true);
        self
    }

    /// Force plain output
    pub fn plain(mut self) -> Self {
        self.color = Some(false);
        self
    }

    /// Auto detect color (default)
    pub fn auto_color(mut self) -> Self {
        self.color = None;
        self
    }

    /// Output to stderr
    pub fn stderr(mut self) -> Self {
        self.stdout = false;
        self
    }

    /// Output to stdout (default)
    pub fn stdout(mut self) -> Self {
        self.stdout = true;
        self
    }

    /// Output using full mode
    pub fn full(mut self) -> Self {
        self.mode = FormatMode::Full;
        self
    }

    /// Output using compact mode (default)
    pub fn compact(mut self) -> Self {
        self.mode = FormatMode::Compact;
        self
    }

    /// Use asynchronous streamer
    pub fn async(mut self) -> Self {
        self.async = true;
        self
    }

    /// Use synchronous streamer (default)
    pub fn sync(mut self) -> Self {
        self.async = false;
        self
    }

    /// Build the streamer
    pub fn build(self) -> Box<slog::Drain<Error=io::Error>> {
        let color = self.color.unwrap_or(if self.stdout {
            stdout_isatty()
        } else {
            stderr_isatty()
        });

        let format = Format::new(self.mode, ColorDecorator { use_color: color });
        let io = if self.stdout {
            Box::new(io::stdout()) as Box<io::Write + Send>
        } else {
            Box::new(io::stderr()) as Box<io::Write + Send>
        };

        if self.async {
            Box::new(AsyncStreamer::new(io, format))
        } else {
            Box::new(Streamer::new(io, format))
        }
    }
}

/// Build `Streamer`/`AsyncStreamer`
pub fn streamer() -> StreamerBuilder {
    StreamerBuilder::new()
}
<|endoftext|>


<commit_before>use self::StartsWithStateInternal::*;

/// Automaton describes types that behave as a finite automaton.
///
/// All implementators of this trait are represented by *byte based* automata.
/// Stated differently, all transitions in the automata correspond to a single
/// byte in the input.
///
/// This implementation choice is important for a couple reasons:
///
/// 1. The set of possible transitions in each node is small, which may make
///    efficient memory usage easier.
/// 2. The finite state transducers in this crate are all byte based, so any
///    automata used on them must also be byte based.
///
/// In practice, this does present somewhat of a problem, for example, if
/// you're storing UTF-8 encoded strings in a finite state transducer. Consider
/// using a `Levenshtein` automaton, which accepts a query string and an edit
/// distance. The edit distance should apply to some notion of *character*,
/// which could be represented by at least 1-4 bytes in a UTF-8 encoding (for
/// some definition of "character"). Therefore, the automaton must have UTF-8
/// decoding built into it. This can be tricky to implement, so you may find
/// the [`utf8-ranges`](https://crates.io/crates/utf8-ranges) crate useful.
pub trait Automaton {
    /// The type of the state used in the automaton.
    type State;

    /// Returns a single start state for this automaton.
    ///
    /// This method should always return the same value for each
    /// implementation.
    fn start(&self) -> Self::State;

    /// Returns true if and only if `state` is a match state.
    fn is_match(&self, state: &Self::State) -> bool;

    /// Returns true if and only if `state` can lead to a match in zero or more
    /// steps.
    ///
    /// If this returns `false`, then no sequence of inputs from this state
    /// should ever produce a match. If this does not follow, then those match
    /// states may never be reached. In other words, behavior may be incorrect.
    ///
    /// If this returns `true` even when no match is possible, then behavior
    /// will be correct, but callers may be forced to do additional work.
    fn can_match(&self, _state: &Self::State) -> bool {
        true
    }

    /// Returns true if and only if `state` matches and must match no matter what
    /// steps are taken.
    ///
    /// If this returns `true`, then every sequence of inputs from this state
    /// produces a match. If this does not follow, then those match states may
    /// never be reached. In other words, behavior may be incorrect.
    ///
    /// If this returns `false` even when every sequence of inputs will lead to
    /// a match, then behavior will be correct, but callers may be forced to do
    /// additional work.
    fn must_match(&self, _state: &Self::State) -> bool {
        false
    }

    /// Return the next state given `state` and an input.
    fn accept(&self, state: &Self::State, byte: u8) -> Self::State;

    /// Returns an automaton that matches the strings that start with something
    /// this automaton matches.
    fn starts_with(self) -> StartsWith<Self> where Self: Sized {
        StartsWith(self)
    }

    /// Returns an automaton that matches the strings matched by either this or
    /// the other automaton.
    fn union<Rhs: Automaton>(self, rhs: Rhs) -> Union<Self, Rhs> where Self: Sized {
        Union(self, rhs)
    }

    /// Returns an automaton that matches the strings matched by both this and
    /// the other automaton.
    fn intersection<Rhs: Automaton>(self, rhs: Rhs) -> Intersection<Self, Rhs> where Self: Sized {
        Intersection(self, rhs)
    }

    /// Returns an automaton that matches the strings not matched by this automaton.
    fn complement(self) -> Complement<Self> where Self: Sized {
        Complement(self)
    }
}

impl<'a, T: Automaton> Automaton for &'a T {
    type State = T::State;

    fn start(&self) -> Self::State {
        (*self).start()
    }

    fn is_match(&self, state: &Self::State) -> bool {
        (*self).is_match(state)
    }

    fn can_match(&self, state: &Self::State) -> bool {
        (*self).can_match(state)
    }

    fn must_match(&self, state: &Self::State) -> bool {
        (*self).must_match(state)
    }

    fn accept(&self, state: &Self::State, byte: u8) -> Self::State {
        (*self).accept(state, byte)
    }
}

/// An automaton that always matches.
///
/// This is useful in a generic context as a way to express that no automaton
/// should be used.
pub struct AlwaysMatch;

impl Automaton for AlwaysMatch {
    type State = ();

    fn start(&self) -> () { () }
    fn is_match(&self, _: &()) -> bool { true }
    fn can_match(&self, _: &()) -> bool { true }
    fn must_match(&self, _: &()) -> bool { true }
    fn accept(&self, _: &(), _: u8) -> () { () }
}

/// An automaton that matches and string that begins with something that the
/// wrapped automaton matches.
pub struct StartsWith<A>(A);

/// The `Automaton` state for `StartsWith<A>`.
pub struct StartsWithState<A: Automaton>(StartsWithStateInternal<A>);

enum StartsWithStateInternal<A: Automaton> {
    Done,
    Running(A::State)
}

impl<A: Automaton> Automaton for StartsWith<A> {
    type State = StartsWithState<A>;
    fn start(&self) -> StartsWithState<A> {
        StartsWithState({
            let inner = self.0.start();
            if self.0.is_match(&inner) {
                Done
            } else {
                Running(inner)
            }
        })
    }

    fn is_match(&self, state: &StartsWithState<A>) -> bool {
        match state.0 {
            Done => true,
            Running(_) => false
        }
    }

    fn can_match(&self, state: &StartsWithState<A>) -> bool {
        match state.0 {
            Done => true,
            Running(ref inner) => self.0.can_match(inner)
        }
    }

    fn must_match(&self, state: &StartsWithState<A>) -> bool {
        match state.0 {
            Done => true,
            Running(_) => false
        }
    }

    fn accept(&self, state: &StartsWithState<A>, byte: u8) -> StartsWithState<A> {
        StartsWithState(
            match state.0 {
                Done => Done,
                Running(ref inner) => {
                    let next_inner = self.0.accept(inner, byte);
                    if self.0.is_match(&next_inner) {
                        Done
                    } else {
                        Running(next_inner)
                    }
                }
            }
        )
    }
}

/// An automaton that matches when one of its component automata match.
pub struct Union<A, B>(A, B);

/// The `Automaton` state for `Union<A, B>`.
pub struct UnionState<A: Automaton, B: Automaton>(A::State, B::State);

impl<A: Automaton, B: Automaton> Automaton for Union<A, B> {
    type State = UnionState<A, B>;

    fn start(&self) -> UnionState<A, B> {
        UnionState(
            self.0.start(),
            self.1.start()
        )
    }

    fn is_match(&self, state: &UnionState<A, B>) -> bool {
        self.0.is_match(&state.0) || self.1.is_match(&state.1)
    }

    fn can_match(&self, state: &UnionState<A, B>) -> bool {
        self.0.can_match(&state.0) || self.1.can_match(&state.1)
    }

    fn must_match(&self, state: &UnionState<A, B>) -> bool {
        self.0.must_match(&state.0) || self.1.must_match(&state.1)
    }

    fn accept(&self, state: &UnionState<A, B>, byte: u8) -> UnionState<A, B> {
        UnionState(
            self.0.accept(&state.0, byte),
            self.1.accept(&state.1, byte)
        )
    }
}

/// An automaton that matches when both of its component automata match.
pub struct Intersection<A, B>(A, B);

/// The `Automaton` state for `Intersection<A, B>`.
pub struct IntersectionState<A: Automaton, B: Automaton>(A::State, B::State);

impl<A: Automaton, B: Automaton> Automaton for Intersection<A, B> {
    type State = IntersectionState<A, B>;

    fn start(&self) -> IntersectionState<A, B> {
        IntersectionState(
            self.0.start(),
            self.1.start()
        )
    }

    fn is_match(&self, state: &IntersectionState<A, B>) -> bool {
        self.0.is_match(&state.0) && self.1.is_match(&state.1)
    }

    fn can_match(&self, state: &IntersectionState<A, B>) -> bool {
        self.0.can_match(&state.0) && self.1.can_match(&state.1)
    }

    fn must_match(&self, state: &IntersectionState<A, B>) -> bool {
        self.0.must_match(&state.0) && self.1.must_match(&state.1)
    }

    fn accept(&self, state: &IntersectionState<A, B>, byte: u8) -> IntersectionState<A, B> {
        IntersectionState(
            self.0.accept(&state.0, byte),
            self.1.accept(&state.1, byte)
        )
    }
}

/// An automaton that matches exactly when the automaton it wraps does not.
pub struct Complement<A>(A);

/// The `Automaton` state for `Complement<A>`.
pub struct ComplementState<A: Automaton>(A::State);

impl<A: Automaton> Automaton for Complement<A> {
    type State = ComplementState<A>;

    fn start(&self) -> ComplementState<A> {
        ComplementState(self.0.start())
    }

    fn is_match(&self, state: &ComplementState<A>) -> bool {
        !self.0.is_match(&state.0)
    }

    fn can_match(&self, state: &ComplementState<A>) -> bool {
        !self.0.must_match(&state.0)
    }

    fn must_match(&self, state: &ComplementState<A>) -> bool {
        !self.0.can_match(&state.0)
    }

    fn accept(&self, state: &ComplementState<A>, byte: u8) -> ComplementState<A> {
        ComplementState(self.0.accept(&state.0, byte))
    }
}
<commit_msg>Rename must_match to will_always_match<commit_after>use self::StartsWithStateInternal::*;

/// Automaton describes types that behave as a finite automaton.
///
/// All implementators of this trait are represented by *byte based* automata.
/// Stated differently, all transitions in the automata correspond to a single
/// byte in the input.
///
/// This implementation choice is important for a couple reasons:
///
/// 1. The set of possible transitions in each node is small, which may make
///    efficient memory usage easier.
/// 2. The finite state transducers in this crate are all byte based, so any
///    automata used on them must also be byte based.
///
/// In practice, this does present somewhat of a problem, for example, if
/// you're storing UTF-8 encoded strings in a finite state transducer. Consider
/// using a `Levenshtein` automaton, which accepts a query string and an edit
/// distance. The edit distance should apply to some notion of *character*,
/// which could be represented by at least 1-4 bytes in a UTF-8 encoding (for
/// some definition of "character"). Therefore, the automaton must have UTF-8
/// decoding built into it. This can be tricky to implement, so you may find
/// the [`utf8-ranges`](https://crates.io/crates/utf8-ranges) crate useful.
pub trait Automaton {
    /// The type of the state used in the automaton.
    type State;

    /// Returns a single start state for this automaton.
    ///
    /// This method should always return the same value for each
    /// implementation.
    fn start(&self) -> Self::State;

    /// Returns true if and only if `state` is a match state.
    fn is_match(&self, state: &Self::State) -> bool;

    /// Returns true if and only if `state` can lead to a match in zero or more
    /// steps.
    ///
    /// If this returns `false`, then no sequence of inputs from this state
    /// should ever produce a match. If this does not follow, then those match
    /// states may never be reached. In other words, behavior may be incorrect.
    ///
    /// If this returns `true` even when no match is possible, then behavior
    /// will be correct, but callers may be forced to do additional work.
    fn can_match(&self, _state: &Self::State) -> bool {
        true
    }

    /// Returns true if and only if `state` matches and must match no matter what
    /// steps are taken.
    ///
    /// If this returns `true`, then every sequence of inputs from this state
    /// produces a match. If this does not follow, then those match states may
    /// never be reached. In other words, behavior may be incorrect.
    ///
    /// If this returns `false` even when every sequence of inputs will lead to
    /// a match, then behavior will be correct, but callers may be forced to do
    /// additional work.
    fn will_always_match(&self, _state: &Self::State) -> bool {
        false
    }

    /// Return the next state given `state` and an input.
    fn accept(&self, state: &Self::State, byte: u8) -> Self::State;

    /// Returns an automaton that matches the strings that start with something
    /// this automaton matches.
    fn starts_with(self) -> StartsWith<Self> where Self: Sized {
        StartsWith(self)
    }

    /// Returns an automaton that matches the strings matched by either this or
    /// the other automaton.
    fn union<Rhs: Automaton>(self, rhs: Rhs) -> Union<Self, Rhs> where Self: Sized {
        Union(self, rhs)
    }

    /// Returns an automaton that matches the strings matched by both this and
    /// the other automaton.
    fn intersection<Rhs: Automaton>(self, rhs: Rhs) -> Intersection<Self, Rhs> where Self: Sized {
        Intersection(self, rhs)
    }

    /// Returns an automaton that matches the strings not matched by this automaton.
    fn complement(self) -> Complement<Self> where Self: Sized {
        Complement(self)
    }
}

impl<'a, T: Automaton> Automaton for &'a T {
    type State = T::State;

    fn start(&self) -> Self::State {
        (*self).start()
    }

    fn is_match(&self, state: &Self::State) -> bool {
        (*self).is_match(state)
    }

    fn can_match(&self, state: &Self::State) -> bool {
        (*self).can_match(state)
    }

    fn will_always_match(&self, state: &Self::State) -> bool {
        (*self).will_always_match(state)
    }

    fn accept(&self, state: &Self::State, byte: u8) -> Self::State {
        (*self).accept(state, byte)
    }
}

/// An automaton that always matches.
///
/// This is useful in a generic context as a way to express that no automaton
/// should be used.
pub struct AlwaysMatch;

impl Automaton for AlwaysMatch {
    type State = ();

    fn start(&self) -> () { () }
    fn is_match(&self, _: &()) -> bool { true }
    fn can_match(&self, _: &()) -> bool { true }
    fn will_always_match(&self, _: &()) -> bool { true }
    fn accept(&self, _: &(), _: u8) -> () { () }
}

/// An automaton that matches and string that begins with something that the
/// wrapped automaton matches.
pub struct StartsWith<A>(A);

/// The `Automaton` state for `StartsWith<A>`.
pub struct StartsWithState<A: Automaton>(StartsWithStateInternal<A>);

enum StartsWithStateInternal<A: Automaton> {
    Done,
    Running(A::State)
}

impl<A: Automaton> Automaton for StartsWith<A> {
    type State = StartsWithState<A>;
    fn start(&self) -> StartsWithState<A> {
        StartsWithState({
            let inner = self.0.start();
            if self.0.is_match(&inner) {
                Done
            } else {
                Running(inner)
            }
        })
    }

    fn is_match(&self, state: &StartsWithState<A>) -> bool {
        match state.0 {
            Done => true,
            Running(_) => false
        }
    }

    fn can_match(&self, state: &StartsWithState<A>) -> bool {
        match state.0 {
            Done => true,
            Running(ref inner) => self.0.can_match(inner)
        }
    }

    fn will_always_match(&self, state: &StartsWithState<A>) -> bool {
        match state.0 {
            Done => true,
            Running(_) => false
        }
    }

    fn accept(&self, state: &StartsWithState<A>, byte: u8) -> StartsWithState<A> {
        StartsWithState(
            match state.0 {
                Done => Done,
                Running(ref inner) => {
                    let next_inner = self.0.accept(inner, byte);
                    if self.0.is_match(&next_inner) {
                        Done
                    } else {
                        Running(next_inner)
                    }
                }
            }
        )
    }
}

/// An automaton that matches when one of its component automata match.
pub struct Union<A, B>(A, B);

/// The `Automaton` state for `Union<A, B>`.
pub struct UnionState<A: Automaton, B: Automaton>(A::State, B::State);

impl<A: Automaton, B: Automaton> Automaton for Union<A, B> {
    type State = UnionState<A, B>;

    fn start(&self) -> UnionState<A, B> {
        UnionState(
            self.0.start(),
            self.1.start()
        )
    }

    fn is_match(&self, state: &UnionState<A, B>) -> bool {
        self.0.is_match(&state.0) || self.1.is_match(&state.1)
    }

    fn can_match(&self, state: &UnionState<A, B>) -> bool {
        self.0.can_match(&state.0) || self.1.can_match(&state.1)
    }

    fn will_always_match(&self, state: &UnionState<A, B>) -> bool {
        self.0.will_always_match(&state.0) || self.1.will_always_match(&state.1)
    }

    fn accept(&self, state: &UnionState<A, B>, byte: u8) -> UnionState<A, B> {
        UnionState(
            self.0.accept(&state.0, byte),
            self.1.accept(&state.1, byte)
        )
    }
}

/// An automaton that matches when both of its component automata match.
pub struct Intersection<A, B>(A, B);

/// The `Automaton` state for `Intersection<A, B>`.
pub struct IntersectionState<A: Automaton, B: Automaton>(A::State, B::State);

impl<A: Automaton, B: Automaton> Automaton for Intersection<A, B> {
    type State = IntersectionState<A, B>;

    fn start(&self) -> IntersectionState<A, B> {
        IntersectionState(
            self.0.start(),
            self.1.start()
        )
    }

    fn is_match(&self, state: &IntersectionState<A, B>) -> bool {
        self.0.is_match(&state.0) && self.1.is_match(&state.1)
    }

    fn can_match(&self, state: &IntersectionState<A, B>) -> bool {
        self.0.can_match(&state.0) && self.1.can_match(&state.1)
    }

    fn will_always_match(&self, state: &IntersectionState<A, B>) -> bool {
        self.0.will_always_match(&state.0) && self.1.will_always_match(&state.1)
    }

    fn accept(&self, state: &IntersectionState<A, B>, byte: u8) -> IntersectionState<A, B> {
        IntersectionState(
            self.0.accept(&state.0, byte),
            self.1.accept(&state.1, byte)
        )
    }
}

/// An automaton that matches exactly when the automaton it wraps does not.
pub struct Complement<A>(A);

/// The `Automaton` state for `Complement<A>`.
pub struct ComplementState<A: Automaton>(A::State);

impl<A: Automaton> Automaton for Complement<A> {
    type State = ComplementState<A>;

    fn start(&self) -> ComplementState<A> {
        ComplementState(self.0.start())
    }

    fn is_match(&self, state: &ComplementState<A>) -> bool {
        !self.0.is_match(&state.0)
    }

    fn can_match(&self, state: &ComplementState<A>) -> bool {
        !self.0.will_always_match(&state.0)
    }

    fn will_always_match(&self, state: &ComplementState<A>) -> bool {
        !self.0.can_match(&state.0)
    }

    fn accept(&self, state: &ComplementState<A>, byte: u8) -> ComplementState<A> {
        ComplementState(self.0.accept(&state.0, byte))
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::fs;
use std::io::{stdout, stderr, Write};
use std::process::exit;
use coreutils::ArgParser;
use extra::io::fail;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{mkdir} */ r#"
NAME
    mkdir - make directories

SYNOPSIS
    mkdir [ -h | --help ] DIRECTORIES...

DESCRIPTION
    The mkdir utility creates the directories named as operands.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag("h", "help");
    parser.initialize(env::args());

    if parser.args.is_empty() {
        fail("No arguments. Use --help to see the usage.", &mut stderr);
    }

    if parser.flagged(&'h') || parser.flagged("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    for ref path in &parser.args {
        fs::create_dir(path).try(&mut stderr);
    }
}
<commit_msg>Make `mkdir --help` print the help message without needing arguments<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::fs;
use std::io::{stdout, stderr, Write};
use std::process::exit;
use coreutils::ArgParser;
use extra::io::fail;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{mkdir} */ r#"
NAME
    mkdir - make directories

SYNOPSIS
    mkdir [ -h | --help ] DIRECTORIES...

DESCRIPTION
    The mkdir utility creates the directories named as operands.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag("h", "help");
    parser.initialize(env::args());

    if parser.flagged(&'h') || parser.flagged("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }
    if parser.args.is_empty() {
        fail("No arguments. Use --help to see the usage.", &mut stderr);
    }

    for ref path in &parser.args {
        fs::create_dir(path).try(&mut stderr);
    }
}
<|endoftext|>


<commit_before>use collectors;
use events;
use std::sync::mpsc::{channel, Sender};
use std::thread;
use std::mem;
use std::sync;
use std::sync::atomic;
use log;

pub enum Item {
    Done,
    Emit(events::Event)
}

pub struct PipelineRef {
    chan: sync::Mutex<Sender<Item>>,
    filter: log::LogLevelFilter
}

static PIPELINE: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;

pub struct Pipeline {
    chan: Sender<Item>,
    worker: Option<thread::JoinHandle<()>>
}

impl Drop for Pipeline {
    fn drop(&mut self) {
        self.chan.send(Item::Done).is_ok();
        let thread = mem::replace(&mut self.worker, None);
        if let Some(handle) = thread {
            handle.join().is_ok();
        }
    }
}

pub fn is_enabled(level: log::LogLevel) -> bool {
    let p = PIPELINE.load(atomic::Ordering::Relaxed) as *const PipelineRef;
    if p != 0 as *const PipelineRef {
        unsafe {
            (*p).filter >= level
        }
    } else {
        false
    }
}

pub fn emit(event: events::Event) {
    let p = PIPELINE.load(atomic::Ordering::Relaxed) as *const PipelineRef;
    if p != 0 as *const PipelineRef {
        unsafe {
            (*p).chan.lock().unwrap().send(Item::Emit(event)).is_ok();
        }
    }
}

pub fn init<T: collectors::Collector + Send + 'static>(collector: T, level: log::LogLevel) -> Pipeline {
    let (tx, rx) = channel::<Item>();
    let pr = Box::new(PipelineRef {
            chan: sync::Mutex::new(tx.clone()),
            filter: level.to_log_level_filter()
        });

    PIPELINE.store(unsafe { mem::transmute::<Box<PipelineRef>, *const PipelineRef>(pr) } as usize, atomic::Ordering::SeqCst);

    let coll = collector;
    let child = thread::spawn(move|| {
        loop {
            let done = match rx.recv().unwrap() {
                Item::Done => true,
                Item::Emit(payload) => {
                    if let Err(e) = coll.dispatch(&vec![payload]) {
                        error!("Could not dispatch events: {}", e);
                    }
                    false
                }
            };

            if done {
                break;
            }
        }
    });

    Pipeline {
         worker: Some(child),
         chan: tx
    }
}

#[cfg(test)]
mod tests {
    use pipeline;
    use collectors::silent::SilentCollector;
    use log;

    #[test]
    fn info_is_enabled_at_info() {
        let _flush = pipeline::init(SilentCollector::new(), log::LogLevel::Info);
        assert!(pipeline::is_enabled(log::LogLevel::Info));
    }

    #[test]
    fn warn_is_enabled_at_info() {
        let _flush = pipeline::init(SilentCollector::new(), log::LogLevel::Info);
        assert!(pipeline::is_enabled(log::LogLevel::Warn));
    }

    #[test]
    fn debug_is_disabled_at_info() {
        let _flush = pipeline::init(SilentCollector::new(), log::LogLevel::Info);
        assert!(!pipeline::is_enabled(log::LogLevel::Debug));
    }
}<commit_msg>Minor refactor<commit_after>use collectors;
use events;
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;
use std::mem;
use std::sync;
use std::sync::atomic;
use log;

pub enum Item {
    Done,
    Emit(events::Event)
}

pub struct PipelineRef {
    chan: sync::Mutex<Sender<Item>>,
    filter: log::LogLevelFilter
}

static PIPELINE: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;

pub struct Pipeline {
    chan: Sender<Item>,
    worker: Option<thread::JoinHandle<()>>
}

impl Drop for Pipeline {
    fn drop(&mut self) {
        self.chan.send(Item::Done).is_ok();
        let thread = mem::replace(&mut self.worker, None);
        if let Some(handle) = thread {
            handle.join().is_ok();
        }
    }
}

pub fn is_enabled(level: log::LogLevel) -> bool {
    let p = PIPELINE.load(atomic::Ordering::Relaxed) as *const PipelineRef;
    if p != 0 as *const PipelineRef {
        unsafe {
            (*p).filter >= level
        }
    } else {
        false
    }
}

pub fn emit(event: events::Event) {
    let p = PIPELINE.load(atomic::Ordering::Relaxed) as *const PipelineRef;
    if p != 0 as *const PipelineRef {
        unsafe {
            (*p).chan.lock().unwrap().send(Item::Emit(event)).is_ok();
        }
    }
}

pub fn init<T: collectors::Collector + Send + 'static>(collector: T, level: log::LogLevel) -> Pipeline {
    let (tx, rx) = channel::<Item>();
    let pr = Box::new(PipelineRef {
            chan: sync::Mutex::new(tx.clone()),
            filter: level.to_log_level_filter()
        });

    PIPELINE.store(unsafe { mem::transmute::<Box<PipelineRef>, *const PipelineRef>(pr) } as usize, atomic::Ordering::SeqCst);

    let child = start_pump(collector, rx);

    Pipeline {
         worker: Some(child),
         chan: tx
    }
}

fn start_pump<T: collectors::Collector + Send + 'static>(collector: T, rx: Receiver<Item>) -> thread::JoinHandle<()> {
    let coll = collector;
    thread::spawn(move|| {
        loop {
            let done = match rx.recv().unwrap() {
                Item::Done => true,
                Item::Emit(payload) => {
                    if let Err(e) = coll.dispatch(&vec![payload]) {
                        error!("Could not dispatch events: {}", e);
                    }
                    false
                }
            };

            if done {
                break;
            }
        }
    })
}

#[cfg(test)]
mod tests {
    use pipeline;
    use collectors::silent::SilentCollector;
    use log;

    #[test]
    fn info_is_enabled_at_info() {
        let _flush = pipeline::init(SilentCollector::new(), log::LogLevel::Info);
        assert!(pipeline::is_enabled(log::LogLevel::Info));
    }

    #[test]
    fn warn_is_enabled_at_info() {
        let _flush = pipeline::init(SilentCollector::new(), log::LogLevel::Info);
        assert!(pipeline::is_enabled(log::LogLevel::Warn));
    }

    #[test]
    fn debug_is_disabled_at_info() {
        let _flush = pipeline::init(SilentCollector::new(), log::LogLevel::Info);
        assert!(!pipeline::is_enabled(log::LogLevel::Debug));
    }
}<|endoftext|>


<commit_before>/// We now can iterate over v while adding more to v but
///   1. We don't have a mechanism to continue iterating over the newly
///      added elements, but we could do this with a queue, if need be.
///
///   2. We were required to add create a copy, which may or may not be good.
fn iter_and_append() {
    let mut my_string = "Hello, String!".to_string();

    // Allocate a buffer
    let mut res = String::new();
    for ch in my_string.chars() {
        if ch == 'l' {
            res.push('!');
        }
    }

    my_string = my_string + &res;
    println!("{}", my_string);
}

/// For such a small example, you may find a functional approach better.
/// Which you choose is mostly up to personal preference.  Differences between
/// the functinoal approach and using a loop start to become noticable once
/// you need to modify 'global state'.  We will discuss that shortly, but
/// here is the first example, rewritten using `chain` with a `filter_map`.

fn iter_and_append_f() {
    let mut my_string = "Hello, String!".to_string();
    let mut new_string = String::new();

    new_string = my_string.chars().chain(
        my_string.chars().filter_map(
            |c| match c {
                'l' => Some('!'),
                _ => None
            }
        )
    ).collect();

    println!("{}", new_string);
}

/// Suppose you need to remove an element while iterating.
/// You can do the reverse swap-pop method. Do however note
/// that you will not preserve ordering while.
/// This also only works for iterators that give you
/// access to indices.

fn remove_evens() {
    // We iterate backwards for a few reaons:
    //   1. When we swap, we swap with an element
    //      that we have already processed.
    //   2. Pop is more efficient than removing
    //      an element from the beginning
    //   3. Popping reduces `v.len()` as we iterate
    //      which would require for use to compensate
    //      the index `i` after every removal if we
    //      iterated from 0..v.len();
    let mut v = vec![5,2,3,6,9];

    for i in (0..v.len()).rev() {
        if v[i] % 2 == 0 {
            v.swap_remove(i);
        }
    }

    println!("{:?}", v);
}

/// As before, you may find such a simple example easier to
/// handle using `filter` (I certainly would recommend this).

fn remove_vowels() {
    let mut my_string = "Hello, String!".to_string();
    let mut res = String::new();

    res = my_string.chars().filter(
        |&c| match c {
            'a' | 'e' | 'i' | 'o' | 'u'
               => false,
            _  => true,
        }
    ).collect();

    println!("{}", res);
}

fn main() {
    iter_and_append();
    iter_and_append_f();
    remove_evens();
    remove_vowels();
}<commit_msg>Add passing a reference<commit_after>/// We now can iterate over v while adding more to v but
///   1. We don't have a mechanism to continue iterating over the newly
///      added elements, but we could do this with a queue, if need be.
///
///   2. We were required to add create a copy, which may or may not be good.
fn iter_and_append() {
    let mut my_string = "Hello, String!".to_string();

    // Allocate a buffer
    let mut res = String::new();
    for ch in my_string.chars() {
        if ch == 'l' {
            res.push('!');
        }
    }

    my_string = my_string + &res;
    println!("{}", my_string);
}

/// For such a small example, you may find a functional approach better.
/// Which you choose is mostly up to personal preference.  Differences between
/// the functinoal approach and using a loop start to become noticable once
/// you need to modify 'global state'.  We will discuss that shortly, but
/// here is the first example, rewritten using `chain` with a `filter_map`.

fn iter_and_append_f() {
    let mut my_string = "Hello, String!".to_string();
    let mut new_string = String::new();

    new_string = my_string.chars().chain(
        my_string.chars().filter_map(
            |c| match c {
                'l' => Some('!'),
                _ => None
            }
        )
    ).collect();

    println!("{}", new_string);
}

/// Suppose you need to remove an element while iterating.
/// You can do the reverse swap-pop method. Do however note
/// that you will not preserve ordering while.
/// This also only works for iterators that give you
/// access to indices.

fn remove_evens() {
    // We iterate backwards for a few reaons:
    //   1. When we swap, we swap with an element
    //      that we have already processed.
    //   2. Pop is more efficient than removing
    //      an element from the beginning
    //   3. Popping reduces `v.len()` as we iterate
    //      which would require for use to compensate
    //      the index `i` after every removal if we
    //      iterated from 0..v.len();
    let mut v = vec![5,2,3,6,9];

    for i in (0..v.len()).rev() {
        if v[i] % 2 == 0 {
            v.swap_remove(i);
        }
    }

    println!("{:?}", v);
}

/// As before, you may find such a simple example easier to
/// handle using `filter` (I certainly would recommend this).

fn remove_vowels() {
    let mut my_string = "Hello, String!".to_string();
    let mut res = String::new();

    res = my_string.chars().filter(
        |&c| match c {
            'a' | 'e' | 'i' | 'o' | 'u'
               => false,
            _  => true,
        }
    ).collect();

    println!("{}", res);
}

///
/// Passing a reference
///

trait Ring {
    fn is_prime(self) -> bool;
}

impl Ring for u8 {
    fn is_prime(self) -> bool {
        if self < 2 {
            return false
        }

        for n in 2..self {
            if self % n == 0 {
                return false
            }
        }

        true
    }
}

fn remove_primes(v: &Vec<u8>) -> Vec<u8> {
    v.iter().filter(|&u| !u.is_prime()).cloned().collect::<Vec<u8>>()
}

fn main() {
    iter_and_append();
    iter_and_append_f();
    remove_evens();
    remove_vowels();

    let my_vec: Vec<u8> = vec![1,2,3,4,5,6,7,8,9,10,11,12];

    println!("{:?}", my_vec);
    println!("{:?}", remove_primes(&my_vec));
}<|endoftext|>


<commit_before>// (C)opyleft 2013-2019 Frank Denis

//! Bloom filter for Rust
//!
//! This is a simple but fast Bloom filter implementation, that requires only
//! 2 hash functions, generated with SipHash-1-3 using randomized keys.
//!

#![crate_name = "bloomfilter"]
#![crate_type = "rlib"]
#![warn(non_camel_case_types, non_upper_case_globals, unused_qualifications)]
#![allow(clippy::unreadable_literal, clippy::bool_comparison)]

use bit_vec::BitVec;
use rand::prelude::*;
use siphasher::sip::SipHasher13;
use std::cmp;
use std::f64;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;

#[cfg(test)]
use rand::Rng;

/// Bloom filter structure
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Bloom<T: ?Sized> {
    bitmap: BitVec,
    bitmap_bits: u64,
    k_num: u32,
    sips: [SipHasher13; 2],

    _phantom: PhantomData<T>,
}

impl<T: ?Sized> Bloom<T> {
    /// Create a new bloom filter structure.
    /// bitmap_size is the size in bytes (not bits) that will be allocated in memory
    /// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: usize, items_count: usize) -> Self {
        assert!(bitmap_size > 0 && items_count > 0);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Self::optimal_k_num(bitmap_bits, items_count);
        let bitmap = BitVec::from_elem(bitmap_bits as usize, false);
        let sips = [Self::sip_new(), Self::sip_new()];
        Self {
            bitmap,
            bitmap_bits,
            k_num,
            sips,
            _phantom: PhantomData,
        }
    }

    /// Create a new bloom filter structure.
    /// items_count is an estimation of the maximum number of items to store.
    /// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: usize, fp_p: f64) -> Self {
        let bitmap_size = Self::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

    /// Create a bloom filter structure with an existing state.
    /// The state is assumed to be retrieved from an existing bloom filter.
    pub fn from_existing(
        bitmap: &[u8],
        bitmap_bits: u64,
        k_num: u32,
        sip_keys: [(u64, u64); 2],
    ) -> Self {
        let sips = [
            SipHasher13::new_with_keys(sip_keys[0].0, sip_keys[0].1),
            SipHasher13::new_with_keys(sip_keys[1].0, sip_keys[1].1),
        ];
        Self {
            bitmap: BitVec::from_bytes(bitmap),
            bitmap_bits,
            k_num,
            sips,
            _phantom: PhantomData,
        }
    }

    /// Compute a recommended bitmap size for items_count items
    /// and a fp_p rate of false positives.
    /// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: usize, fp_p: f64) -> usize {
        assert!(items_count > 0);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = f64::consts::LN_2;
        let log2_2 = log2 * log2;
        ((items_count as f64) * f64::ln(fp_p) / (-8.0 * log2_2)).ceil() as usize
    }

    /// Record the presence of an item.
    pub fn set(&mut self, item: &T)
    where
        T: Hash,
    {
        let mut hashes = [0u64, 0u64];
        for k_i in 0..self.k_num {
            let bit_offset = (self.bloom_hash(&mut hashes, &item, k_i) % self.bitmap_bits) as usize;
            self.bitmap.set(bit_offset, true);
        }
    }

    /// Check if an item is present in the set.
    /// There can be false positives, but no false negatives.
    pub fn check(&self, item: &T) -> bool
    where
        T: Hash,
    {
        let mut hashes = [0u64, 0u64];
        for k_i in 0..self.k_num {
            let bit_offset = (self.bloom_hash(&mut hashes, &item, k_i) % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                return false;
            }
        }
        true
    }

    /// Record the presence of an item in the set,
    /// and return the previous state of this item.
    pub fn check_and_set(&mut self, item: &T) -> bool
    where
        T: Hash,
    {
        let mut hashes = [0u64, 0u64];
        let mut found = true;
        for k_i in 0..self.k_num {
            let bit_offset = (self.bloom_hash(&mut hashes, &item, k_i) % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    /// Return the bitmap as a vector of bytes
    pub fn bitmap(&self) -> Vec<u8> {
        self.bitmap.to_bytes()
    }

    /// Return the number of bits in the filter
    pub fn number_of_bits(&self) -> u64 {
        self.bitmap_bits
    }

    /// Return the number of hash functions used for `check` and `set`
    pub fn number_of_hash_functions(&self) -> u32 {
        self.k_num
    }

    /// Return the keys used by the sip hasher
    pub fn sip_keys(&self) -> [(u64, u64); 2] {
        [self.sips[0].keys(), self.sips[1].keys()]
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: usize) -> u32 {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * f64::ln(2.0f64)).ceil() as u32;
        cmp::max(k_num, 1)
    }

    fn bloom_hash(&self, hashes: &mut [u64; 2], item: &T, k_i: u32) -> u64
    where
        T: Hash,
    {
        if k_i < 2 {
            let sip = &mut self.sips[k_i as usize].clone();
            item.hash(sip);
            let hash = sip.finish();
            hashes[k_i as usize] = hash;
            hash
        } else {
            (hashes[0] as u128).wrapping_add((k_i as u128).wrapping_mul(hashes[1] as u128)) as u64
                % 0xffffffffffffffc5
        }
    }

    /// Clear all of the bits in the filter, removing all keys from the set
    pub fn clear(&mut self) {
        self.bitmap.clear()
    }

    fn sip_new() -> SipHasher13 {
        let mut rng = thread_rng();
        SipHasher13::new_with_keys(rng.gen(), rng.gen())
    }
}

#[test]
fn bloom_test_set() {
    let mut rng = thread_rng();
    let mut bloom = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    assert!(bloom.check(&key) == false);
    bloom.set(&key);
    assert!(bloom.check(&key) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut rng = thread_rng();
    let mut bloom = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    assert!(bloom.check_and_set(&key) == false);
    assert!(bloom.check_and_set(&key) == true);
}

#[test]
fn bloom_test_clear() {
    let mut rng = thread_rng();
    let mut bloom = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    bloom.set(&key);
    assert!(bloom.check(&key) == true);
    bloom.clear();
    assert!(bloom.check(&key) == false);
}

#[test]
fn bloom_test_load() {
    let mut rng = thread_rng();
    let mut original = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    original.set(&key);
    assert!(original.check(&key) == true);

    let cloned = Bloom::from_existing(
        &original.bitmap(),
        original.number_of_bits(),
        original.number_of_hash_functions(),
        original.sip_keys(),
    );
    assert!(cloned.check(&key) == true);
}

#[cfg(feature = "serde")]
fn bloom_test_serde() {
    let mut rng = thread_rng();
    let mut original = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    original.set(&key);
    assert!(original.check(&key) == true);
    let serialized = serde_json::to_string(&original).unwrap();
    let deserialized: Bloom<Vec<u8>> = serde_json::from_str(&serialized).unwrap();
    assert!(deserialized.check(&key));
}
<commit_msg>Add Clone & Debug traits<commit_after>// (C)opyleft 2013-2019 Frank Denis

//! Bloom filter for Rust
//!
//! This is a simple but fast Bloom filter implementation, that requires only
//! 2 hash functions, generated with SipHash-1-3 using randomized keys.
//!

#![crate_name = "bloomfilter"]
#![crate_type = "rlib"]
#![warn(non_camel_case_types, non_upper_case_globals, unused_qualifications)]
#![allow(clippy::unreadable_literal, clippy::bool_comparison)]

use bit_vec::BitVec;
use rand::prelude::*;
use siphasher::sip::SipHasher13;
use std::cmp;
use std::f64;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;

#[cfg(test)]
use rand::Rng;

/// Bloom filter structure
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[derive(Clone, Debug)]
pub struct Bloom<T: ?Sized> {
    bitmap: BitVec,
    bitmap_bits: u64,
    k_num: u32,
    sips: [SipHasher13; 2],

    _phantom: PhantomData<T>,
}

impl<T: ?Sized> Bloom<T> {
    /// Create a new bloom filter structure.
    /// bitmap_size is the size in bytes (not bits) that will be allocated in memory
    /// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: usize, items_count: usize) -> Self {
        assert!(bitmap_size > 0 && items_count > 0);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Self::optimal_k_num(bitmap_bits, items_count);
        let bitmap = BitVec::from_elem(bitmap_bits as usize, false);
        let sips = [Self::sip_new(), Self::sip_new()];
        Self {
            bitmap,
            bitmap_bits,
            k_num,
            sips,
            _phantom: PhantomData,
        }
    }

    /// Create a new bloom filter structure.
    /// items_count is an estimation of the maximum number of items to store.
    /// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: usize, fp_p: f64) -> Self {
        let bitmap_size = Self::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

    /// Create a bloom filter structure with an existing state.
    /// The state is assumed to be retrieved from an existing bloom filter.
    pub fn from_existing(
        bitmap: &[u8],
        bitmap_bits: u64,
        k_num: u32,
        sip_keys: [(u64, u64); 2],
    ) -> Self {
        let sips = [
            SipHasher13::new_with_keys(sip_keys[0].0, sip_keys[0].1),
            SipHasher13::new_with_keys(sip_keys[1].0, sip_keys[1].1),
        ];
        Self {
            bitmap: BitVec::from_bytes(bitmap),
            bitmap_bits,
            k_num,
            sips,
            _phantom: PhantomData,
        }
    }

    /// Compute a recommended bitmap size for items_count items
    /// and a fp_p rate of false positives.
    /// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: usize, fp_p: f64) -> usize {
        assert!(items_count > 0);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = f64::consts::LN_2;
        let log2_2 = log2 * log2;
        ((items_count as f64) * f64::ln(fp_p) / (-8.0 * log2_2)).ceil() as usize
    }

    /// Record the presence of an item.
    pub fn set(&mut self, item: &T)
    where
        T: Hash,
    {
        let mut hashes = [0u64, 0u64];
        for k_i in 0..self.k_num {
            let bit_offset = (self.bloom_hash(&mut hashes, &item, k_i) % self.bitmap_bits) as usize;
            self.bitmap.set(bit_offset, true);
        }
    }

    /// Check if an item is present in the set.
    /// There can be false positives, but no false negatives.
    pub fn check(&self, item: &T) -> bool
    where
        T: Hash,
    {
        let mut hashes = [0u64, 0u64];
        for k_i in 0..self.k_num {
            let bit_offset = (self.bloom_hash(&mut hashes, &item, k_i) % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                return false;
            }
        }
        true
    }

    /// Record the presence of an item in the set,
    /// and return the previous state of this item.
    pub fn check_and_set(&mut self, item: &T) -> bool
    where
        T: Hash,
    {
        let mut hashes = [0u64, 0u64];
        let mut found = true;
        for k_i in 0..self.k_num {
            let bit_offset = (self.bloom_hash(&mut hashes, &item, k_i) % self.bitmap_bits) as usize;
            if self.bitmap.get(bit_offset).unwrap() == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    /// Return the bitmap as a vector of bytes
    pub fn bitmap(&self) -> Vec<u8> {
        self.bitmap.to_bytes()
    }

    /// Return the number of bits in the filter
    pub fn number_of_bits(&self) -> u64 {
        self.bitmap_bits
    }

    /// Return the number of hash functions used for `check` and `set`
    pub fn number_of_hash_functions(&self) -> u32 {
        self.k_num
    }

    /// Return the keys used by the sip hasher
    pub fn sip_keys(&self) -> [(u64, u64); 2] {
        [self.sips[0].keys(), self.sips[1].keys()]
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: usize) -> u32 {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * f64::ln(2.0f64)).ceil() as u32;
        cmp::max(k_num, 1)
    }

    fn bloom_hash(&self, hashes: &mut [u64; 2], item: &T, k_i: u32) -> u64
    where
        T: Hash,
    {
        if k_i < 2 {
            let sip = &mut self.sips[k_i as usize].clone();
            item.hash(sip);
            let hash = sip.finish();
            hashes[k_i as usize] = hash;
            hash
        } else {
            (hashes[0] as u128).wrapping_add((k_i as u128).wrapping_mul(hashes[1] as u128)) as u64
                % 0xffffffffffffffc5
        }
    }

    /// Clear all of the bits in the filter, removing all keys from the set
    pub fn clear(&mut self) {
        self.bitmap.clear()
    }

    fn sip_new() -> SipHasher13 {
        let mut rng = thread_rng();
        SipHasher13::new_with_keys(rng.gen(), rng.gen())
    }
}

#[test]
fn bloom_test_set() {
    let mut rng = thread_rng();
    let mut bloom = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    assert!(bloom.check(&key) == false);
    bloom.set(&key);
    assert!(bloom.check(&key) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut rng = thread_rng();
    let mut bloom = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    assert!(bloom.check_and_set(&key) == false);
    assert!(bloom.check_and_set(&key) == true);
}

#[test]
fn bloom_test_clear() {
    let mut rng = thread_rng();
    let mut bloom = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    bloom.set(&key);
    assert!(bloom.check(&key) == true);
    bloom.clear();
    assert!(bloom.check(&key) == false);
}

#[test]
fn bloom_test_load() {
    let mut rng = thread_rng();
    let mut original = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    original.set(&key);
    assert!(original.check(&key) == true);

    let cloned = Bloom::from_existing(
        &original.bitmap(),
        original.number_of_bits(),
        original.number_of_hash_functions(),
        original.sip_keys(),
    );
    assert!(cloned.check(&key) == true);
}

#[cfg(feature = "serde")]
fn bloom_test_serde() {
    let mut rng = thread_rng();
    let mut original = Bloom::new(10, 80);
    let mut key = vec![0u8, 16];
    rng.fill_bytes(&mut key);
    original.set(&key);
    assert!(original.check(&key) == true);
    let serialized = serde_json::to_string(&original).unwrap();
    let deserialized: Bloom<Vec<u8>> = serde_json::from_str(&serialized).unwrap();
    assert!(deserialized.check(&key));
}
<|endoftext|>


<commit_before>/// Character level parsers

use internal::{IResult, Needed};
use traits::{AsChar, InputIter, InputLength, Slice};
use std::ops::RangeFrom;
use traits::{need_more, AtEof};

/// matches one of the provided characters
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
/// named!(simple<char>, one_of!(&b"abc"[..]));
/// assert_eq!(simple(b"a123"), Ok((&b"123"[..], 'a')));
///
/// named!(a_or_b<&str, char>, one_of!("ab汉"));
/// assert_eq!(a_or_b("汉jiosfe"), Ok(("jiosfe", '汉')));
/// # }
/// ```
#[macro_export]
macro_rules! one_of (
  ($i:expr, $inp: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::FindToken;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        (c, $inp.find_token(c))
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::OneOf::<u32>))),
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

/// matches anything but the provided characters
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,ErrorKind};
/// # fn main() {
/// named!(no_letter_a<char>, none_of!(&b"abc"[..]));
/// assert_eq!(no_letter_a(b"123"), Ok((&b"23"[..], '1')));
///
/// named!(err_on_single_quote<char>, none_of!(&b"'"[..]));
/// assert_eq!(err_on_single_quote(b"'jiosfe"), Err(Err::Error(error_position!(&b"'jiosfe"[..], ErrorKind::NoneOf))));
/// # }
/// ```
#[macro_export]
macro_rules! none_of (
  ($i:expr, $inp: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::FindToken;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        (c, !$inp.find_token(c))
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::NoneOf::<u32>))),
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,ErrorKind};
/// # fn main() {
/// named!(match_letter_a<char>, char!('a'));
/// assert_eq!(match_letter_a(b"abc"), Ok((&b"bc"[..],'a')));
///
/// assert_eq!(match_letter_a(b"123cdef"), Err(Err::Error(error_position!(&b"123cdef"[..], ErrorKind::Char))));
/// # }
/// ```
#[macro_export]
macro_rules! char (
  ($i:expr, $c: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        (c, c.as_char() == $c)
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => {
          let e: $crate::ErrorKind<u32> = $crate::ErrorKind::Char;
          Err(Err::Error($crate::Context::Code($i, e)))
        },
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

named!(#[doc="Matches a newline character '\\n'"], pub newline<char>, char!('\n'));

named!(#[doc="Matches a tab character '\\t'"], pub tab<char>, char!('\t'));

/// matches one byte as a character. Note that the input type will
/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers.
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::anychar;
/// # fn main() {
/// assert_eq!(anychar("abc"), Ok(("bc",'a')));
/// # }
/// ```
pub fn anychar<T>(input: T) -> IResult<T, char>
where
  T: InputIter + InputLength + Slice<RangeFrom<usize>> + AtEof,
  <T as InputIter>::Item: AsChar,
{
  let mut it = input.iter_indices();
  match it.next() {
    None => need_more(input, Needed::Size(1)),
    Some((_, c)) => {
      match it.next() {
        None => Ok((input.slice(input.input_len()..), c.as_char())),
        Some((idx, _)) => Ok((input.slice(idx..), c.as_char())),
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use internal::Err;
  use util::ErrorKind;

  #[test]
  fn one_of() {
    named!(f<char>, one_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a),Ok((&b"bcd"[..], 'a')));

    let b = &b"cde"[..];
    assert_eq!(f(b), Err(Err::Error(error_position!(b, ErrorKind::OneOf))));

    named!(utf8(&str) -> char,
      one_of!("+\u{FF0B}"));

    assert!(utf8("+").is_ok());
    assert!(utf8("\u{FF0B}").is_ok());
  }

  #[test]
  fn none_of() {
    named!(f<char>, none_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::NoneOf))));

    let b = &b"cde"[..];
    assert_eq!(f(b),Ok((&b"de"[..], 'c')));
  }

  #[test]
  fn char() {
    named!(f<char>, char!('c'));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));

    let b = &b"cde"[..];
    assert_eq!(f(b),Ok((&b"de"[..], 'c')));
  }

  #[test]
  fn char_str() {
    named!(f<&str, char>, char!('c'));

    let a = &"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));

    let b = &"cde"[..];
    assert_eq!(f(b),Ok((&"de"[..], 'c')));
  }

  #[test]
  fn anychar_str() {
    use super::anychar;
    assert_eq!(anychar("Ә"), Ok(("", 'Ә')));
  }
}
<commit_msg>clone the item since AsChar will consume it<commit_after>/// Character level parsers

use internal::{IResult, Needed};
use traits::{AsChar, InputIter, InputLength, Slice};
use std::ops::RangeFrom;
use traits::{need_more, AtEof};

/// matches one of the provided characters
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
/// named!(simple<char>, one_of!(&b"abc"[..]));
/// assert_eq!(simple(b"a123"), Ok((&b"123"[..], 'a')));
///
/// named!(a_or_b<&str, char>, one_of!("ab汉"));
/// assert_eq!(a_or_b("汉jiosfe"), Ok(("jiosfe", '汉')));
/// # }
/// ```
#[macro_export]
macro_rules! one_of (
  ($i:expr, $inp: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::FindToken;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        (c, $inp.find_token(c))
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::OneOf::<u32>))),
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

/// matches anything but the provided characters
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,ErrorKind};
/// # fn main() {
/// named!(no_letter_a<char>, none_of!(&b"abc"[..]));
/// assert_eq!(no_letter_a(b"123"), Ok((&b"23"[..], '1')));
///
/// named!(err_on_single_quote<char>, none_of!(&b"'"[..]));
/// assert_eq!(err_on_single_quote(b"'jiosfe"), Err(Err::Error(error_position!(&b"'jiosfe"[..], ErrorKind::NoneOf))));
/// # }
/// ```
#[macro_export]
macro_rules! none_of (
  ($i:expr, $inp: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::FindToken;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        (c, !$inp.find_token(c))
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => Err(Err::Error(error_position!($i, $crate::ErrorKind::NoneOf::<u32>))),
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::{Err,ErrorKind};
/// # fn main() {
/// named!(match_letter_a<char>, char!('a'));
/// assert_eq!(match_letter_a(b"abc"), Ok((&b"bc"[..],'a')));
///
/// assert_eq!(match_letter_a(b"123cdef"), Err(Err::Error(error_position!(&b"123cdef"[..], ErrorKind::Char))));
/// # }
/// ```
#[macro_export]
macro_rules! char (
  ($i:expr, $c: expr) => (
    {
      use ::std::result::Result::*;
      use ::std::option::Option::*;
      use $crate::{Err,Needed};

      use $crate::Slice;
      use $crate::AsChar;
      use $crate::InputIter;

      match ($i).iter_elements().next().map(|c| {
        let b = c.clone().as_char() == $c;
        (c, b)
      }) {
        None             => $crate::need_more($i, Needed::Size(1)),
        Some((_, false)) => {
          let e: $crate::ErrorKind<u32> = $crate::ErrorKind::Char;
          Err(Err::Error($crate::Context::Code($i, e)))
        },
        //the unwrap should be safe here
        Some((c, true))  => Ok(( $i.slice(c.len()..), $i.iter_elements().next().unwrap().as_char() ))
      }
    }
  );
);

named!(#[doc="Matches a newline character '\\n'"], pub newline<char>, char!('\n'));

named!(#[doc="Matches a tab character '\\t'"], pub tab<char>, char!('\t'));

/// matches one byte as a character. Note that the input type will
/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers.
///
/// # Example
/// ```
/// # #[macro_use] extern crate nom;
/// # use nom::anychar;
/// # fn main() {
/// assert_eq!(anychar("abc"), Ok(("bc",'a')));
/// # }
/// ```
pub fn anychar<T>(input: T) -> IResult<T, char>
where
  T: InputIter + InputLength + Slice<RangeFrom<usize>> + AtEof,
  <T as InputIter>::Item: AsChar,
{
  let mut it = input.iter_indices();
  match it.next() {
    None => need_more(input, Needed::Size(1)),
    Some((_, c)) => {
      match it.next() {
        None => Ok((input.slice(input.input_len()..), c.as_char())),
        Some((idx, _)) => Ok((input.slice(idx..), c.as_char())),
      }
    }
  }
}

#[cfg(test)]
mod tests {
  use internal::Err;
  use util::ErrorKind;

  #[test]
  fn one_of() {
    named!(f<char>, one_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a),Ok((&b"bcd"[..], 'a')));

    let b = &b"cde"[..];
    assert_eq!(f(b), Err(Err::Error(error_position!(b, ErrorKind::OneOf))));

    named!(utf8(&str) -> char,
      one_of!("+\u{FF0B}"));

    assert!(utf8("+").is_ok());
    assert!(utf8("\u{FF0B}").is_ok());
  }

  #[test]
  fn none_of() {
    named!(f<char>, none_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::NoneOf))));

    let b = &b"cde"[..];
    assert_eq!(f(b),Ok((&b"de"[..], 'c')));
  }

  #[test]
  fn char() {
    named!(f<char>, char!('c'));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));

    let b = &b"cde"[..];
    assert_eq!(f(b),Ok((&b"de"[..], 'c')));
  }

  #[test]
  fn char_str() {
    named!(f<&str, char>, char!('c'));

    let a = &"abcd"[..];
    assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));

    let b = &"cde"[..];
    assert_eq!(f(b),Ok((&"de"[..], 'c')));
  }

  #[test]
  fn anychar_str() {
    use super::anychar;
    assert_eq!(anychar("Ә"), Ok(("", 'Ә')));
  }
}
<|endoftext|>