<commit_before>use std::fmt;
use std::error::Error as StdError;
use std::io::{Error as IoError, Read};
use std::fs::File;
use std::path::Path;
use std::result::Result as StdResult;
use std::time::Duration;

// TODO: ADD DOCS!!!

const UTF8_BOM: &'static str = "\u{feff}";

#[derive(Debug)]
enum State {
    Pos,
    Time,
    Text,
}

#[derive(Debug)]
pub struct Subtitle {
    pub pos: usize,
    pub start_time: Duration,
    pub end_time: Duration,
    pub text: String,
}

pub fn parse(source: &str) -> Result<Vec<Subtitle>> {
    let source = source.trim_left_matches(UTF8_BOM).trim().lines();

    let mut result = Vec::new();

    let mut state = State::Pos;

    let mut pos: Option<usize> = None;
    let mut start_time: Option<Duration> = None;
    let mut end_time: Option<Duration> = None;
    let mut text: Option<String> = None;

    macro_rules! push_subtitle {
        ($pos:ident) => (
            result.push(Subtitle {
                pos: $pos,
                start_time: match start_time {
                    Some(val) => val,
                    None => return Err(Error::MissingStartTime),
                },
                end_time: match end_time {
                    Some(val) => val,
                    None => return Err(Error::MissingEndTime),
                },
                text: match text {
                    Some(val) => val,
                    None => return Err(Error::MissingText),
                }
            });
        )
    }

    for line in source {
        match state {
            State::Pos => {
                if let Some(ps) = pos {
                    push_subtitle!(ps);
                    start_time = None;
                    end_time = None;
                    text = None;
                }
                pos = Some(line.parse::<usize>().map_err(|_| Error::BadPosition)?);
                state = State::Time;
            }
            State::Time => {
                let mut parts = line.split("-->");
                start_time = match parts.next() {
                    Some(v) => Some(duration_from_str(v)?),
                    None => None,
                };
                end_time = match parts.next() {
                    Some(v) => Some(duration_from_str(v)?),
                    None => None,
                };
                if parts.next().is_some() {
                    return Err(Error::BadTime);
                }
                state = State::Text;
            }
            State::Text => {
                if line.is_empty() {
                    state = State::Pos;
                } else {
                    if let Some(ref mut txt) = text {
                        txt.push('\n');
                        txt.push_str(line);
                    } else {
                        text = Some(line.to_string());
                    }
                }
            }
        }
    }
    if let Some(ps) = pos {
        push_subtitle!(ps);
    }

    Ok(result)
}

pub fn read_from_file<P: AsRef<Path>>(path: P) -> Result<Vec<Subtitle>> {
    let mut file = File::open(path).map_err(|err| Error::OpenFile(err))?;
    let mut buf = String::new();
    file.read_to_string(&mut buf).map_err(|err| Error::ReadFile(err))?;
    parse(&buf)
}

/// Alias for std result
pub type Result<T> = StdResult<T, Error>;

/// Describes all errors that may occur
pub enum Error {
    /// An error when parsing subtitle position
    BadPosition,
    /// An error when parsing subtitle time
    BadTime,
    /// Unsupported subtitle time format
    BadTimeFormat,
    /// Subtitle start time is missing
    MissingStartTime,
    /// Subtitle end time is missing
    MissingEndTime,
    /// Subtitle text is missing
    MissingText,
    /// Unable to open a file
    OpenFile(IoError),
    /// Unable to subtitles from a file
    ReadFile(IoError),
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::BadPosition => "Invalid subtitle position",
            Error::BadTime => "Invalid subtitle time",
            Error::BadTimeFormat => "Invalid subtitle time format",
            Error::MissingStartTime => "Subtitle start time is missing",
            Error::MissingEndTime => "Subtitle end time is missing",
            Error::MissingText => "Subtitle text is missing",
            Error::OpenFile(ref err) => err.description(),
            Error::ReadFile(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::OpenFile(ref err) => Some(err),
            Error::ReadFile(ref err) => Some(err),
            _ => None,
        }
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
        write!(out, "{}", self.description())
    }
}

impl fmt::Display for Error {
    fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
        write!(out, "{}", self.description())
    }
}

macro_rules! parse_time_part {
    ($part:expr) => {{
        match $part {
            Some(val) => {
                val.trim().parse::<u64>().map_err(|_| Error::BadTime)?
            },
            None => {
                return Err(Error::BadTimeFormat);
            }
        }
    }}
}

fn duration_from_str(time: &str) -> Result<Duration> {
    let mut time = time.split(",");
    let (hours, mut minutes, mut seconds) = match time.next() {
        Some(val) => {
            let mut parts = val.split(":");
            let result = (
                parse_time_part!(parts.next()),
                parse_time_part!(parts.next()),
                parse_time_part!(parts.next()),
            );
            if parts.next().is_some() {
                return Err(Error::BadTimeFormat);
            }
            result
        },
        None => {
            return Err(Error::BadTimeFormat);
        }
    };
    let mut milliseconds = parse_time_part!(time.next());
    if time.next().is_some() {
        return Err(Error::BadTimeFormat);
    }
    minutes += hours * 60;
    seconds += minutes * 60;
    milliseconds += seconds * 1000;
    Ok(Duration::new(milliseconds, 0))
}

#[cfg(test)]
mod tests {
    use std::time::Duration;
    use ::{Result, UTF8_BOM, parse, read_from_file};

    #[test]
    fn it_works() {
        let source_without_bom = "1
00:00:58,392 --> 00:01:02,563
The war had all but ground to a halt
in the blink of an eye.

2
00:01:04,565 --> 00:01:08,986
Lucian, the most feared and ruthless
leader ever to rule the Lycan clan...

3
00:01:09,070 --> 00:01:11,656
...had finally been killed.

652
01:53:02,325 --> 01:53:06,162
Soon, Marcus will take the throne.
";
        let source_with_bom = format!("{}{}", UTF8_BOM, source_without_bom);

        fn assert_it_works(data: &str) -> Result<()> {
            let result = parse(&data)?;
            assert_eq!(result.len(), 4);
            assert_eq!(result[0].pos, 1);
            assert_eq!(result[0].start_time, Duration::new(58392, 0));
            assert_eq!(result[0].end_time, Duration::new(62563, 0));
            assert_eq!(result[0].text, "The war had all but ground to a halt\nin the blink of an eye.");
            assert_eq!(result[1].pos, 2);
            assert_eq!(result[1].start_time, Duration::new(64565, 0));
            assert_eq!(result[1].end_time, Duration::new(68986, 0));
            assert_eq!(result[1].text, "Lucian, the most feared and ruthless\nleader ever to rule the Lycan clan...");
            assert_eq!(result[2].pos, 3);
            assert_eq!(result[2].start_time, Duration::new(69070, 0));
            assert_eq!(result[2].end_time, Duration::new(71656, 0));
            assert_eq!(result[2].text, "...had finally been killed.");
            assert_eq!(result[3].pos, 652);
            assert_eq!(result[3].start_time, Duration::new(6782325, 0));
            assert_eq!(result[3].end_time, Duration::new(6786162, 0));
            assert_eq!(result[3].text, "Soon, Marcus will take the throne.");
            Ok(())
        }

        assert_it_works(&source_without_bom).expect("Failed to parse UTF-8 source without BOM");
        assert_it_works(&source_with_bom).expect("Failed to parse UTF-8 source with BOM");
        let empty = parse("").unwrap();
        assert_eq!(empty.len(), 0);
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle position")]
    fn it_fails_with_bad_position() {
        parse("bad position").unwrap();
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle time")]
    fn it_fails_with_bad_start_time() {
        parse("1\nbad time").unwrap();
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle time")]
    fn it_fails_with_bad_end_time() {
        parse("1\n00:00:58,392 --> bad end time").unwrap();
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle time format")]
    fn it_fails_with_bad_time_format() {
        parse("1\n00:00:00:00").unwrap();
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle time")]
    fn it_fails_with_extra_time() {
        parse("1\n00:00:58,392 --> 00:01:02,563 -> 00:01:02,563").unwrap();
    }

    #[test]
    #[should_panic(expected = "Subtitle start time is missing")]
    fn it_fails_with_missing_start_time() {
        parse("1").unwrap();
    }

    #[test]
    #[should_panic(expected = "Subtitle end time is missing")]
    fn it_fails_with_missing_end_time() {
        parse("1\n00:00:58,392").unwrap();
    }

    #[test]
    #[should_panic(expected = "Subtitle text is missing")]
    fn it_fails_with_missing_text() {
        parse("1\n00:00:58,392 --> 00:01:02,563").unwrap();
    }

    #[test]
    #[should_panic(expected = "entity not found")]
    fn read_from_file_failed() {
        read_from_file("/file/does/not/exist").unwrap();
    }

    #[test]
    fn read_from_file_success() {
        let result = read_from_file("./data/underworld.srt").unwrap();
        assert_eq!(result.len(), 706);

        let first = result.first().unwrap();
        assert_eq!(first.pos, 1);
        assert_eq!(first.start_time, Duration::new(58392, 0));
        assert_eq!(first.end_time, Duration::new(61478, 0));
        assert_eq!(first.text, "Война закончилась в мгновение ока.");

        let last = result.last().unwrap();
        assert_eq!(last.pos, 706);
        assert_eq!(last.start_time, Duration::new(6801628, 0));
        assert_eq!(last.end_time, Duration::new(6804381, 0));
        assert_eq!(last.text, "... будет объявлена охота.");
    }
}
<commit_msg>Added docs<commit_after>//! A library for reading [SRT Subtitles][1].
//!
//! # Examples
//!
//! ## Reading from string
//!
//! ```
//! use srtparse::parse;
//! let subtitles = parse("1\n00:00:01,100 --> 00:00:02,120\nHello!").unwrap();
//! println("{:?}", subtitles);
//! ```
//!
//! ## Reading from file
//!
//! ```
//! use srtparse::read_from_file;
//! let subtitles = read_from_file("./data/underworld.srt").unwrap();
//! println!("{:?}", subtitles[0]);
//! ```
//!
//! [1]: https://matroska.org/technical/specs/subtitles/srt.html
#![warn(missing_docs)]
use std::fmt;
use std::error::Error as StdError;
use std::io::{Error as IoError, Read};
use std::fs::File;
use std::path::Path;
use std::result::Result as StdResult;
use std::time::Duration;

const UTF8_BOM: &'static str = "\u{feff}";

#[derive(Debug)]
enum State {
    Pos,
    Time,
    Text,
}

/// A subtitle item
#[derive(Debug)]
pub struct Subtitle {
    /// A number indicating which subtitle it is in the sequence
    pub pos: usize,
    /// The time that the subtitle should appear
    pub start_time: Duration,
    /// The time that the subtitle should disappear
    pub end_time: Duration,
    /// The subtitle itself
    pub text: String,
}

/// Read subtitles from a string
pub fn parse(source: &str) -> Result<Vec<Subtitle>> {
    let source = source.trim_left_matches(UTF8_BOM).trim().lines();

    let mut result = Vec::new();

    let mut state = State::Pos;

    let mut pos: Option<usize> = None;
    let mut start_time: Option<Duration> = None;
    let mut end_time: Option<Duration> = None;
    let mut text: Option<String> = None;

    macro_rules! push_subtitle {
        ($pos:ident) => (
            result.push(Subtitle {
                pos: $pos,
                start_time: match start_time {
                    Some(val) => val,
                    None => return Err(Error::MissingStartTime),
                },
                end_time: match end_time {
                    Some(val) => val,
                    None => return Err(Error::MissingEndTime),
                },
                text: match text {
                    Some(val) => val,
                    None => return Err(Error::MissingText),
                }
            });
        )
    }

    for line in source {
        match state {
            State::Pos => {
                if let Some(ps) = pos {
                    push_subtitle!(ps);
                    start_time = None;
                    end_time = None;
                    text = None;
                }
                pos = Some(line.parse::<usize>().map_err(|_| Error::BadPosition)?);
                state = State::Time;
            }
            State::Time => {
                let mut parts = line.split("-->");
                start_time = match parts.next() {
                    Some(v) => Some(duration_from_str(v)?),
                    None => None,
                };
                end_time = match parts.next() {
                    Some(v) => Some(duration_from_str(v)?),
                    None => None,
                };
                if parts.next().is_some() {
                    return Err(Error::BadTime);
                }
                state = State::Text;
            }
            State::Text => {
                if line.is_empty() {
                    state = State::Pos;
                } else {
                    if let Some(ref mut txt) = text {
                        txt.push('\n');
                        txt.push_str(line);
                    } else {
                        text = Some(line.to_string());
                    }
                }
            }
        }
    }
    if let Some(ps) = pos {
        push_subtitle!(ps);
    }

    Ok(result)
}

/// Read subtitles from a file
pub fn read_from_file<P: AsRef<Path>>(path: P) -> Result<Vec<Subtitle>> {
    let mut file = File::open(path).map_err(|err| Error::OpenFile(err))?;
    let mut buf = String::new();
    file.read_to_string(&mut buf).map_err(|err| Error::ReadFile(err))?;
    parse(&buf)
}

/// Alias for std result
pub type Result<T> = StdResult<T, Error>;

/// Describes all errors that may occur
pub enum Error {
    /// An error when parsing subtitle position
    BadPosition,
    /// An error when parsing subtitle time
    BadTime,
    /// Unsupported subtitle time format
    BadTimeFormat,
    /// Subtitle start time is missing
    MissingStartTime,
    /// Subtitle end time is missing
    MissingEndTime,
    /// Subtitle text is missing
    MissingText,
    /// Unable to open a file
    OpenFile(IoError),
    /// Unable to subtitles from a file
    ReadFile(IoError),
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Error::BadPosition => "Invalid subtitle position",
            Error::BadTime => "Invalid subtitle time",
            Error::BadTimeFormat => "Invalid subtitle time format",
            Error::MissingStartTime => "Subtitle start time is missing",
            Error::MissingEndTime => "Subtitle end time is missing",
            Error::MissingText => "Subtitle text is missing",
            Error::OpenFile(ref err) => err.description(),
            Error::ReadFile(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::OpenFile(ref err) => Some(err),
            Error::ReadFile(ref err) => Some(err),
            _ => None,
        }
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
        write!(out, "{}", self.description())
    }
}

impl fmt::Display for Error {
    fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
        write!(out, "{}", self.description())
    }
}

macro_rules! parse_time_part {
    ($part:expr) => {{
        match $part {
            Some(val) => {
                val.trim().parse::<u64>().map_err(|_| Error::BadTime)?
            },
            None => {
                return Err(Error::BadTimeFormat);
            }
        }
    }}
}

fn duration_from_str(time: &str) -> Result<Duration> {
    let mut time = time.split(",");
    let (hours, mut minutes, mut seconds) = match time.next() {
        Some(val) => {
            let mut parts = val.split(":");
            let result = (
                parse_time_part!(parts.next()),
                parse_time_part!(parts.next()),
                parse_time_part!(parts.next()),
            );
            if parts.next().is_some() {
                return Err(Error::BadTimeFormat);
            }
            result
        },
        None => {
            return Err(Error::BadTimeFormat);
        }
    };
    let mut milliseconds = parse_time_part!(time.next());
    if time.next().is_some() {
        return Err(Error::BadTimeFormat);
    }
    minutes += hours * 60;
    seconds += minutes * 60;
    milliseconds += seconds * 1000;
    Ok(Duration::new(milliseconds, 0))
}

#[cfg(test)]
mod tests {
    use std::time::Duration;
    use ::{Result, UTF8_BOM, parse, read_from_file};

    #[test]
    fn it_works() {
        let source_without_bom = "1
00:00:58,392 --> 00:01:02,563
The war had all but ground to a halt
in the blink of an eye.

2
00:01:04,565 --> 00:01:08,986
Lucian, the most feared and ruthless
leader ever to rule the Lycan clan...

3
00:01:09,070 --> 00:01:11,656
...had finally been killed.

652
01:53:02,325 --> 01:53:06,162
Soon, Marcus will take the throne.
";
        let source_with_bom = format!("{}{}", UTF8_BOM, source_without_bom);

        fn assert_it_works(data: &str) -> Result<()> {
            let result = parse(&data)?;
            assert_eq!(result.len(), 4);
            assert_eq!(result[0].pos, 1);
            assert_eq!(result[0].start_time, Duration::new(58392, 0));
            assert_eq!(result[0].end_time, Duration::new(62563, 0));
            assert_eq!(result[0].text, "The war had all but ground to a halt\nin the blink of an eye.");
            assert_eq!(result[1].pos, 2);
            assert_eq!(result[1].start_time, Duration::new(64565, 0));
            assert_eq!(result[1].end_time, Duration::new(68986, 0));
            assert_eq!(result[1].text, "Lucian, the most feared and ruthless\nleader ever to rule the Lycan clan...");
            assert_eq!(result[2].pos, 3);
            assert_eq!(result[2].start_time, Duration::new(69070, 0));
            assert_eq!(result[2].end_time, Duration::new(71656, 0));
            assert_eq!(result[2].text, "...had finally been killed.");
            assert_eq!(result[3].pos, 652);
            assert_eq!(result[3].start_time, Duration::new(6782325, 0));
            assert_eq!(result[3].end_time, Duration::new(6786162, 0));
            assert_eq!(result[3].text, "Soon, Marcus will take the throne.");
            Ok(())
        }

        assert_it_works(&source_without_bom).expect("Failed to parse UTF-8 source without BOM");
        assert_it_works(&source_with_bom).expect("Failed to parse UTF-8 source with BOM");
        let empty = parse("").unwrap();
        assert_eq!(empty.len(), 0);
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle position")]
    fn it_fails_with_bad_position() {
        parse("bad position").unwrap();
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle time")]
    fn it_fails_with_bad_start_time() {
        parse("1\nbad time").unwrap();
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle time")]
    fn it_fails_with_bad_end_time() {
        parse("1\n00:00:58,392 --> bad end time").unwrap();
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle time format")]
    fn it_fails_with_bad_time_format() {
        parse("1\n00:00:00:00").unwrap();
    }

    #[test]
    #[should_panic(expected = "Invalid subtitle time")]
    fn it_fails_with_extra_time() {
        parse("1\n00:00:58,392 --> 00:01:02,563 -> 00:01:02,563").unwrap();
    }

    #[test]
    #[should_panic(expected = "Subtitle start time is missing")]
    fn it_fails_with_missing_start_time() {
        parse("1").unwrap();
    }

    #[test]
    #[should_panic(expected = "Subtitle end time is missing")]
    fn it_fails_with_missing_end_time() {
        parse("1\n00:00:58,392").unwrap();
    }

    #[test]
    #[should_panic(expected = "Subtitle text is missing")]
    fn it_fails_with_missing_text() {
        parse("1\n00:00:58,392 --> 00:01:02,563").unwrap();
    }

    #[test]
    #[should_panic(expected = "entity not found")]
    fn read_from_file_failed() {
        read_from_file("/file/does/not/exist").unwrap();
    }

    #[test]
    fn read_from_file_success() {
        let result = read_from_file("./data/underworld.srt").unwrap();
        assert_eq!(result.len(), 706);

        let first = result.first().unwrap();
        assert_eq!(first.pos, 1);
        assert_eq!(first.start_time, Duration::new(58392, 0));
        assert_eq!(first.end_time, Duration::new(61478, 0));
        assert_eq!(first.text, "Война закончилась в мгновение ока.");

        let last = result.last().unwrap();
        assert_eq!(last.pos, 706);
        assert_eq!(last.start_time, Duration::new(6801628, 0));
        assert_eq!(last.end_time, Duration::new(6804381, 0));
        assert_eq!(last.text, "... будет объявлена охота.");
    }
}
<|endoftext|>


<commit_before>//! `sled` is a high-performance embedded database with
//! an API that is similar to a `BTreeMap<[u8], [u8]>`,
//! but with several additional capabilities for
//! assisting creators of stateful systems.
//!
//! It is fully thread-safe, and all operations are
//! atomic. Multiple `Tree`s are supported with the
//! [`Db::open_tree`](struct.Db.html#method.open_tree) method.
//!
//! ACID transactions involving reads and writes to
//! multiple items are supported with the
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! method. Transactions may also operate over
//! multiple `Tree`s (see
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! docs for more info).
//!
//! Users may also subscribe to updates on individual
//! `Tree`s by using the
//! [`Tree::watch_prefix`](struct.Tree.html#method.watch_prefix)
//! method, which returns a blocking `Iterator` over
//! updates to keys that begin with the provided
//! prefix. You may supply an empty prefix to subscribe
//! to everything.
//!
//! [Merge operators](https://github.com/spacejam/sled/wiki/merge-operators)
//! (aka read-modify-write operators) are supported. A
//! merge operator is a function that specifies
//! how new data can be merged into an existing value
//! without requiring both a read and a write.
//! Using the
//! [`Tree::merge`](struct.Tree.html#method.merge)
//! method, you may "push" data to a `Tree` value
//! and have the provided merge operator combine
//! it with the existing value, if there was one.
//! They are set on a per-`Tree` basis, and essentially
//! allow any sort of data structure to be built
//! using merges as an atomic high-level operation.
//!
//! `sled` is built by experienced database engineers
//! who think users should spend less time tuning and
//! working against high-friction APIs. Expect
//! significant ergonomic and performance improvements
//! over time. Most surprises are bugs, so please
//! [let us know](mailto:t@jujit.su?subject=sled%20sucks!!!) if something
//! is high friction.
//!
//! # Examples
//!
//! ```
//! use sled::Db;
//!
//! let t = Db::open("my_db").unwrap();
//!
//! // insert and get
//! t.insert(b"yo!", b"v1");
//! assert_eq!(&t.get(b"yo!").unwrap().unwrap(), b"v1");
//!
//! // Atomic compare-and-swap.
//! t.compare_and_swap(
//!     b"yo!",      // key
//!     Some(b"v1"), // old value, None for not present
//!     Some(b"v2"), // new value, None for delete
//! )
//! .unwrap();
//!
//! // Iterates over key-value pairs, starting at the given key.
//! let scan_key: &[u8] = b"a non-present key before yo!";
//! let mut iter = t.range(scan_key..);
//! assert_eq!(&iter.next().unwrap().unwrap().0, b"yo!");
//! assert_eq!(iter.next(), None);
//!
//! t.remove(b"yo!");
//! assert_eq!(t.get(b"yo!"), Ok(None));
//! ```
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/spacejam/sled/master/art/tree_face_anti-transphobia.png"
)]
#![cfg_attr(test, deny(warnings))]
#![deny(
    missing_docs,
    future_incompatible,
    nonstandard_style,
    rust_2018_idioms,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unused_qualifications
)]
#![deny(
    // clippy::else_if_without_else,
    // clippy::float_arithmetic,
    // clippy::indexing_slicing,
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_precision_loss,
    clippy::cast_sign_loss,
    clippy::checked_conversions,
    clippy::decimal_literal_representation,
    clippy::doc_markdown,
    clippy::empty_enum,
    clippy::expl_impl_clone_on_copy,
    clippy::explicit_into_iter_loop,
    clippy::explicit_iter_loop,
    clippy::explicit_iter_loop,
    clippy::fallible_impl_from,
    clippy::filter_map,
    clippy::filter_map_next,
    clippy::find_map,
    clippy::get_unwrap,
    clippy::if_not_else,
    clippy::inline_always,
    clippy::invalid_upcast_comparisons,
    clippy::items_after_statements,
    clippy::map_flatten,
    clippy::match_same_arms,
    clippy::maybe_infinite_iter,
    clippy::mem_forget,
    clippy::missing_const_for_fn,
    clippy::replace_consts,
    clippy::shadow_reuse,
    clippy::shadow_same,
    clippy::shadow_unrelated,
    clippy::used_underscore_binding,
)]

#[cfg(feature = "failpoints")]
use fail::fail_point;

macro_rules! maybe_fail {
    ($e:expr) => {
        #[cfg(feature = "failpoints")]
        fail_point!($e, |_| Err(Error::FailPoint));
    };
}

mod batch;
mod binary_search;
mod config;
mod context;
mod db;
mod dll;
mod frag;
mod histogram;
mod iter;
mod ivec;
mod lazy;
mod lru;
mod meta;
mod metrics;
mod node;
mod oneshot;
mod pagecache;
mod pagetable;
mod prefix;
mod result;
mod stack;
mod subscription;
mod sys_limits;
mod threadpool;
mod transaction;
mod tree;
mod vecset;

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod flusher;

#[cfg(feature = "event_log")]
/// The event log helps debug concurrency issues.
pub mod event_log;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

const DEFAULT_TREE_ID: &[u8] = b"__sled__default";

/// hidden re-export of items for testing purposes
#[doc(hidden)]
pub use {
    self::{
        config::RunningConfig,
        lazy::Lazy,
        pagecache::{
            constants::{
                MAX_SPACE_AMPLIFICATION, MINIMUM_ITEMS_PER_SEGMENT,
                MSG_HEADER_LEN, SEG_HEADER_LEN,
            },
            DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn, PageCache, PageId,
            SegmentMode,
        },
        pagetable::PAGETABLE_NODE_SZ,
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::Config,
    db::Db,
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::{
        abort, ConflictableTransactionError, ConflictableTransactionResult,
        TransactionError, TransactionResult, Transactional, TransactionalTree,
    },
    tree::{CompareAndSwapError, CompareAndSwapResult, Tree},
};

use {
    self::{
        binary_search::binary_search_lub,
        config::StorageParameters,
        context::Context,
        frag::Frag,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, measure, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        pagetable::PageTable,
        result::CasResult,
        stack::{node_from_frag_vec, Stack, StackIter},
        subscription::Subscriptions,
        tree::TreeInner,
        vecset::VecSet,
    },
    bincode::{deserialize, serialize},
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    serde::{Deserialize, Serialize},
    std::{
        collections::BTreeMap,
        convert::TryFrom,
        fmt::{self, Debug},
        io::{Read, Write},
        sync::{
            atomic::{
                AtomicI64 as AtomicLsn, AtomicU64, AtomicUsize,
                Ordering::{Acquire, Relaxed, Release, SeqCst},
            },
            Arc,
        },
    },
};

fn crc32(buf: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(buf);
    hasher.finalize()
}

type TreePtr<'g> = pagecache::PagePtr<'g>;

#[cfg(any(test, feature = "lock_free_delays"))]
mod debug_delay;

#[cfg(any(test, feature = "lock_free_delays"))]
use debug_delay::debug_delay;

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully eliminated by the compiler in non-test code.
#[cfg(not(any(test, feature = "lock_free_delays")))]
const fn debug_delay() {}

/// A fast map that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastMap8<K, V> = std::collections::HashMap<
    K,
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// A fast set that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastSet8<V> = std::collections::HashSet<
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// Allows arbitrary logic to be injected into mere operations of the
/// `PageCache`.
pub type MergeOperator = fn(
    key: &[u8],
    last_value: Option<&[u8]>,
    new_merge: &[u8],
) -> Option<Vec<u8>>;
<commit_msg>Add a large number of additional clippy lints<commit_after>//! `sled` is a high-performance embedded database with
//! an API that is similar to a `BTreeMap<[u8], [u8]>`,
//! but with several additional capabilities for
//! assisting creators of stateful systems.
//!
//! It is fully thread-safe, and all operations are
//! atomic. Multiple `Tree`s are supported with the
//! [`Db::open_tree`](struct.Db.html#method.open_tree) method.
//!
//! ACID transactions involving reads and writes to
//! multiple items are supported with the
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! method. Transactions may also operate over
//! multiple `Tree`s (see
//! [`Tree::transaction`](struct.Tree.html#method.transaction)
//! docs for more info).
//!
//! Users may also subscribe to updates on individual
//! `Tree`s by using the
//! [`Tree::watch_prefix`](struct.Tree.html#method.watch_prefix)
//! method, which returns a blocking `Iterator` over
//! updates to keys that begin with the provided
//! prefix. You may supply an empty prefix to subscribe
//! to everything.
//!
//! [Merge operators](https://github.com/spacejam/sled/wiki/merge-operators)
//! (aka read-modify-write operators) are supported. A
//! merge operator is a function that specifies
//! how new data can be merged into an existing value
//! without requiring both a read and a write.
//! Using the
//! [`Tree::merge`](struct.Tree.html#method.merge)
//! method, you may "push" data to a `Tree` value
//! and have the provided merge operator combine
//! it with the existing value, if there was one.
//! They are set on a per-`Tree` basis, and essentially
//! allow any sort of data structure to be built
//! using merges as an atomic high-level operation.
//!
//! `sled` is built by experienced database engineers
//! who think users should spend less time tuning and
//! working against high-friction APIs. Expect
//! significant ergonomic and performance improvements
//! over time. Most surprises are bugs, so please
//! [let us know](mailto:t@jujit.su?subject=sled%20sucks!!!) if something
//! is high friction.
//!
//! # Examples
//!
//! ```
//! use sled::Db;
//!
//! let t = Db::open("my_db").unwrap();
//!
//! // insert and get
//! t.insert(b"yo!", b"v1");
//! assert_eq!(&t.get(b"yo!").unwrap().unwrap(), b"v1");
//!
//! // Atomic compare-and-swap.
//! t.compare_and_swap(
//!     b"yo!",      // key
//!     Some(b"v1"), // old value, None for not present
//!     Some(b"v2"), // new value, None for delete
//! )
//! .unwrap();
//!
//! // Iterates over key-value pairs, starting at the given key.
//! let scan_key: &[u8] = b"a non-present key before yo!";
//! let mut iter = t.range(scan_key..);
//! assert_eq!(&iter.next().unwrap().unwrap().0, b"yo!");
//! assert_eq!(iter.next(), None);
//!
//! t.remove(b"yo!");
//! assert_eq!(t.get(b"yo!"), Ok(None));
//! ```
#![doc(
    html_logo_url = "https://raw.githubusercontent.com/spacejam/sled/master/art/tree_face_anti-transphobia.png"
)]
#![cfg_attr(test, deny(warnings))]
#![deny(
    missing_docs,
    future_incompatible,
    nonstandard_style,
    rust_2018_idioms,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unused_qualifications
)]
#![deny(
    // clippy::else_if_without_else,
    // clippy::float_arithmetic,
    // clippy::indexing_slicing,
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
    clippy::cast_possible_wrap,
    clippy::cast_precision_loss,
    clippy::cast_sign_loss,
    clippy::checked_conversions,
    clippy::decimal_literal_representation,
    clippy::doc_markdown,
    clippy::empty_enum,
    clippy::expl_impl_clone_on_copy,
    clippy::explicit_into_iter_loop,
    clippy::explicit_iter_loop,
    clippy::explicit_iter_loop,
    clippy::fallible_impl_from,
    clippy::filter_map,
    clippy::filter_map_next,
    clippy::find_map,
    clippy::get_unwrap,
    clippy::if_not_else,
    clippy::inline_always,
    clippy::invalid_upcast_comparisons,
    clippy::items_after_statements,
    clippy::map_flatten,
    clippy::match_same_arms,
    clippy::maybe_infinite_iter,
    clippy::mem_forget,
    // clippy::missing_const_for_fn,
    // clippy::missing_docs_in_private_items,
    // clippy::module_name_repetitions,
    // clippy::multiple_crate_versions,
    clippy::multiple_inherent_impl,
    clippy::mut_mut,
    clippy::needless_borrow,
    clippy::needless_continue,
    clippy::needless_pass_by_value,
    clippy::non_ascii_literal,
    clippy::option_map_unwrap_or,
    clippy::option_map_unwrap_or_else,
    clippy::path_buf_push_overwrite,
    clippy::print_stdout,
    clippy::pub_enum_variant_names,
    clippy::redundant_closure_for_method_calls,
    clippy::replace_consts,
    clippy::result_map_unwrap_or_else,
    clippy::shadow_reuse,
    clippy::shadow_same,
    clippy::shadow_unrelated,
    clippy::single_match_else,
    clippy::string_add,
    clippy::string_add_assign,
    clippy::type_repetition_in_bounds,
    clippy::unicode_not_nfc,
    // clippy::unimplemented,
    clippy::unseparated_literal_suffix,
    clippy::used_underscore_binding,
    clippy::wildcard_dependencies,
    // clippy::wildcard_enum_match_arm,
    clippy::wrong_pub_self_convention,
)]

#[cfg(feature = "failpoints")]
use fail::fail_point;

macro_rules! maybe_fail {
    ($e:expr) => {
        #[cfg(feature = "failpoints")]
        fail_point!($e, |_| Err(Error::FailPoint));
    };
}

mod batch;
mod binary_search;
mod config;
mod context;
mod db;
mod dll;
mod frag;
mod histogram;
mod iter;
mod ivec;
mod lazy;
mod lru;
mod meta;
mod metrics;
mod node;
mod oneshot;
mod pagecache;
mod pagetable;
mod prefix;
mod result;
mod stack;
mod subscription;
mod sys_limits;
mod threadpool;
mod transaction;
mod tree;
mod vecset;

#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
mod flusher;

#[cfg(feature = "event_log")]
/// The event log helps debug concurrency issues.
pub mod event_log;

#[cfg(feature = "measure_allocs")]
mod measure_allocs;

#[cfg(feature = "measure_allocs")]
#[global_allocator]
static ALLOCATOR: measure_allocs::TrackingAllocator =
    measure_allocs::TrackingAllocator;

const DEFAULT_TREE_ID: &[u8] = b"__sled__default";

/// hidden re-export of items for testing purposes
#[doc(hidden)]
pub use {
    self::{
        config::RunningConfig,
        lazy::Lazy,
        pagecache::{
            constants::{
                MAX_SPACE_AMPLIFICATION, MINIMUM_ITEMS_PER_SEGMENT,
                MSG_HEADER_LEN, SEG_HEADER_LEN,
            },
            DiskPtr, Log, LogKind, LogOffset, LogRead, Lsn, PageCache, PageId,
            SegmentMode,
        },
        pagetable::PAGETABLE_NODE_SZ,
    },
    crossbeam_epoch::{pin, Atomic, Guard, Owned, Shared},
};

pub use self::{
    batch::Batch,
    config::Config,
    db::Db,
    iter::Iter,
    ivec::IVec,
    result::{Error, Result},
    subscription::{Event, Subscriber},
    transaction::{
        abort, ConflictableTransactionError, ConflictableTransactionResult,
        TransactionError, TransactionResult, Transactional, TransactionalTree,
    },
    tree::{CompareAndSwapError, CompareAndSwapResult, Tree},
};

use {
    self::{
        binary_search::binary_search_lub,
        config::StorageParameters,
        context::Context,
        frag::Frag,
        histogram::Histogram,
        lru::Lru,
        meta::Meta,
        metrics::{clock, measure, Measure, M},
        node::{Data, Node},
        oneshot::{OneShot, OneShotFiller},
        pagetable::PageTable,
        result::CasResult,
        stack::{node_from_frag_vec, Stack, StackIter},
        subscription::Subscriptions,
        tree::TreeInner,
        vecset::VecSet,
    },
    bincode::{deserialize, serialize},
    crossbeam_utils::{Backoff, CachePadded},
    log::{debug, error, trace, warn},
    pagecache::RecoveryGuard,
    parking_lot::{Condvar, Mutex, RwLock},
    serde::{Deserialize, Serialize},
    std::{
        collections::BTreeMap,
        convert::TryFrom,
        fmt::{self, Debug},
        io::{Read, Write},
        sync::{
            atomic::{
                AtomicI64 as AtomicLsn, AtomicU64, AtomicUsize,
                Ordering::{Acquire, Relaxed, Release, SeqCst},
            },
            Arc,
        },
    },
};

fn crc32(buf: &[u8]) -> u32 {
    let mut hasher = crc32fast::Hasher::new();
    hasher.update(buf);
    hasher.finalize()
}

type TreePtr<'g> = pagecache::PagePtr<'g>;

#[cfg(any(test, feature = "lock_free_delays"))]
mod debug_delay;

#[cfg(any(test, feature = "lock_free_delays"))]
use debug_delay::debug_delay;

/// This function is useful for inducing random jitter into our atomic
/// operations, shaking out more possible interleavings quickly. It gets
/// fully eliminated by the compiler in non-test code.
#[cfg(not(any(test, feature = "lock_free_delays")))]
const fn debug_delay() {}

/// A fast map that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastMap8<K, V> = std::collections::HashMap<
    K,
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// A fast set that is not resistant to collision attacks. Works
/// on 8 bytes at a time.
pub(crate) type FastSet8<V> = std::collections::HashSet<
    V,
    std::hash::BuildHasherDefault<fxhash::FxHasher64>,
>;

/// Allows arbitrary logic to be injected into mere operations of the
/// `PageCache`.
pub type MergeOperator = fn(
    key: &[u8],
    last_value: Option<&[u8]>,
    new_merge: &[u8],
) -> Option<Vec<u8>>;
<|endoftext|>


<commit_before>//! Functional Reactive Programming library for Rust
//!
//! Frappe is a concurrent Event-Driven FRP library. It aims to provide a simple, efficient and
//! Rust-idiomatic way to write interactive applications in a declarative way.
//!
//! See each module documentation for more details.
#![warn(missing_docs)]
#![cfg_attr(feature = "nightly", feature(async_await))]

#[macro_use]
mod helpers;
pub mod futures;
mod lift;
pub mod signal;
pub mod stream;
mod sync;
pub mod types;

pub use crate::signal::Signal;
pub use crate::stream::{Sink, Stream};
<commit_msg>feature flag async_await no longer needed on rust 1.39<commit_after>//! Functional Reactive Programming library for Rust
//!
//! Frappe is a concurrent Event-Driven FRP library. It aims to provide a simple, efficient and
//! Rust-idiomatic way to write interactive applications in a declarative way.
//!
//! See each module documentation for more details.
#![warn(missing_docs)]

#[macro_use]
mod helpers;
pub mod futures;
mod lift;
pub mod signal;
pub mod stream;
mod sync;
pub mod types;

pub use crate::signal::Signal;
pub use crate::stream::{Sink, Stream};
<|endoftext|>


<commit_before>//! Multi-producer multi-consumer channels for message passing.
//!
//! Crossbeam's channels are an alternative to the [`std::sync::mpsc`] channels provided by the
//! standard library. They are an improvement in terms of performance, ergonomics, and features.
//!
//! Here's a quick example:
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! // Create a channel of unbounded capacity.
//! let (s, r) = channel::unbounded();
//!
//! // Send a message into the channel.
//! s.send("Hello world!");
//!
//! // Receive the message from the channel.
//! assert_eq!(r.recv(), Some("Hello world!"));
//! ```
//!
//! # Types of channels
//!
//! A channel can be created by calling [`bounded`] or [`unbounded`]. The former creates a channel
//! of bounded capacity (i.e. there is a limit to how many messages it can hold), while the latter
//! creates a channel of unbounded capacity (i.e. it can contain an arbitrary number of messages).
//!
//! Both functions return two handles: a sender and a receiver. Senders and receivers represent
//! two opposite sides of a channel. Messages are sent into the channel using senders and received
//! using receivers.
//!
//! Creating an unbounded channel:
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! // Create an unbounded channel.
//! let (s, r) = channel::unbounded();
//!
//! // Can send any number of messages into the channel without blocking.
//! for i in 0..1000 {
//!     s.send(i);
//! }
//! ```
//!
//! Creating a bounded channel:
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! // Create a channel that can hold at most 5 messages at a time.
//! let (s, r) = channel::bounded(5);
//!
//! // Can only send 5 messages without blocking.
//! for i in 0..5 {
//!     s.send(i);
//! }
//!
//! // Another call to `send` would block because the channel is full.
//! // s.send(5);
//! ```
//!
//! A rather special case is a bounded, zero-capacity channel. This kind of channel cannot hold any
//! messages at all! In order to send a message through the channel, a sending thread and a
//! receiving thread have to pair up at the same time:
//!
//! ```
//! use std::thread;
//! use crossbeam_channel as channel;
//!
//! // Create a zero-capacity channel.
//! let (s, r) = channel::bounded(0);
//!
//! // Spawn a thread that sends a message into the channel.
//! // Sending blocks until a receive operation appears on the other side.
//! thread::spawn(move || s.send("Hi!"));
//!
//! // Receive the message.
//! // Receiving blocks until a send operation appears on the other side.
//! assert_eq!(r.recv(), Some("Hi!"));
//! ```
//!
//! # Sharing channels
//!
//! Senders and receivers can be either shared by reference or cloned and then sent to other
//! threads. There can be multiple senders and multiple receivers associated with the same channel.
//!
//! Sharing by reference:
//!
//! ```
//! # extern crate crossbeam_channel;
//! extern crate crossbeam;
//! # fn main() {
//! use crossbeam_channel as channel;
//!
//! let (s, r) = channel::unbounded();
//!
//! crossbeam::scope(|scope| {
//!     // Spawn a thread that sends one message and then receives one.
//!     scope.spawn(|| {
//!         s.send(1);
//!         r.recv().unwrap();
//!     });
//!
//!     // Spawn another thread that does the same thing.
//!     scope.spawn(|| {
//!         s.send(2);
//!         r.recv().unwrap();
//!     });
//! });
//!
//! # }
//! ```
//!
//! Sharing by cloning:
//!
//! ```
//! use std::thread;
//! use crossbeam_channel as channel;
//!
//! let (s1, r1) = channel::unbounded();
//! let (s2, r2) = (s1.clone(), r1.clone());
//!
//! // Spawn a thread that sends one message and then receives one.
//! thread::spawn(move || {
//!     s1.send(1);
//!     r1.recv().unwrap();
//! });
//!
//! // Spawn another thread that receives a message and then sends one.
//! thread::spawn(move || {
//!     r2.recv().unwrap();
//!     s2.send(2);
//! });
//! ```
//!
//! # Closing channels
//!
//! When all senders associated with a channel get dropped, the channel becomes closed. No more
//! messages can be sent, but any remaining messages can still be received. Receive operations on a
//! closed channel never block, even if the channel is empty.
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! let (s, r) = channel::unbounded();
//! s.send(1);
//! s.send(2);
//! s.send(3);
//!
//! // The only sender is dropped, closing the channel.
//! drop(s);
//!
//! // The remaining messages can be received.
//! assert_eq!(r.recv(), Some(1));
//! assert_eq!(r.recv(), Some(2));
//! assert_eq!(r.recv(), Some(3));
//!
//! // There are no more messages in the channel.
//! assert!(r.is_empty());
//!
//! // Note that calling `r.recv()` will not block.
//! // Instead, `None` is returned immediately.
//! assert_eq!(r.recv(), None);
//! ```
//!
//! # Blocking and non-blocking operations
//!
//! Sending a message into a full bounded channel will block until an empty slot in the channel
//! becomes available. Sending into an unbounded channel never blocks because there is always
//! enough space in it. Zero-capacity channels are always empty, and sending blocks until a receive
//! operation appears on the other side of the channel.
//!
//! Receiving from an empty channel blocks until a message is sent into the channel or the channel
//! becomes closed. Zero-capacity channels are always empty, and receiving blocks until a send
//! operation appears on the other side of the channel or it becomes closed.
//!
//! There is also a non-blocking method [`try_recv`], which receives a message if it is immediately
//! available, or returns `None` otherwise.
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! let (s, r) = channel::bounded(1);
//!
//! // Send a message into the channel.
//! s.send("foo");
//!
//! // This call would block because the channel is full.
//! // s.send("bar");
//!
//! // Receive the message.
//! assert_eq!(r.recv(), Some("foo"));
//!
//! // This call would block because the channel is empty.
//! // r.recv();
//!
//! // Try receiving a message without blocking.
//! assert_eq!(r.try_recv(), None);
//!
//! // Close the channel.
//! drop(s);
//!
//! // This call doesn't block because the channel is now closed.
//! assert_eq!(r.recv(), None);
//! ```
//!
//! For greater control over blocking, consider using the [`select!`] macro.
//!
//! # Iteration
//!
//! A channel is a special kind of iterator, where items can be dynamically produced by senders and
//! consumed by receivers. Indeed, [`Receiver`] implements the [`Iterator`] trait, and calling
//! [`next`] is equivalent to calling [`recv`].
//!
//! ```
//! use std::thread;
//! use crossbeam_channel as channel;
//!
//! let (s, r) = channel::unbounded();
//!
//! thread::spawn(move || {
//!     s.send(1);
//!     s.send(2);
//!     s.send(3);
//!     // `s` was moved into the closure so now it gets dropped,
//!     // thus closing the channel.
//! });
//!
//! // Collect all messages from the channel.
//! //
//! // Note that the call to `collect` blocks until the channel becomes
//! // closed and empty, i.e. until `r.next()` returns `None`.
//! let v: Vec<_> = r.collect();
//! assert_eq!(v, [1, 2, 3]);
//! ```
//!
//! # Select
//!
//! The [`select!`] macro allows declaring a set of channel operations and blocking until any one
//! of them becomes ready. Finally, one of the operations is executed. If multiple operations
//! are ready at the same time, a random one is chosen. It is also possible to declare a `default`
//! case that gets executed if none of the operations are initially ready.
//!
//! An example of receiving a message from two channels, whichever becomes ready first:
//!
//! ```
//! # #[macro_use]
//! # extern crate crossbeam_channel;
//! # fn main() {
//! use std::thread;
//! use crossbeam_channel as channel;
//!
//! let (s1, r1) = channel::unbounded();
//! let (s2, r2) = channel::unbounded();
//!
//! thread::spawn(move || s1.send("foo"));
//! thread::spawn(move || s2.send("bar"));
//!
//! // Only one of these two receive operations will be executed.
//! select! {
//!     recv(r1, msg) => assert_eq!(msg, Some("foo")),
//!     recv(r2, msg) => assert_eq!(msg, Some("bar")),
//! }
//! # }
//! ```
//!
//! For more details, take a look at the documentation for [`select!`].
//!
//! If you need to dynamically add cases rather than define them statically inside the macro, use
//! [`Select`] instead.
//!
//! [`std::sync::mpsc`]: https://doc.rust-lang.org/std/sync/mpsc/index.html
//! [`unbounded`]: fn.unbounded.html
//! [`bounded`]: fn.bounded.html
//! [`send`]: struct.Sender.html#method.send
//! [`try_recv`]: struct.Receiver.html#method.try_recv
//! [`recv`]: struct.Receiver.html#method.recv
//! [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
//! [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
//! [`select!`]: macro.select.html
//! [`Select`]: struct.Select.html
//! [`Sender`]: struct.Sender.html
//! [`Receiver`]: struct.Receiver.html

extern crate crossbeam_epoch;
extern crate crossbeam_utils;
extern crate rand;
extern crate parking_lot;

mod flavors;

#[doc(hidden)]
pub mod internal;

pub use internal::channel::{Receiver, Sender};
pub use internal::channel::{bounded, unbounded};
pub use internal::channel::{after, tick};
pub use internal::select::Select;
<commit_msg>Docs: clarify cloning<commit_after>//! Multi-producer multi-consumer channels for message passing.
//!
//! Crossbeam's channels are an alternative to the [`std::sync::mpsc`] channels provided by the
//! standard library. They are an improvement in terms of performance, ergonomics, and features.
//!
//! Here's a quick example:
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! // Create a channel of unbounded capacity.
//! let (s, r) = channel::unbounded();
//!
//! // Send a message into the channel.
//! s.send("Hello world!");
//!
//! // Receive the message from the channel.
//! assert_eq!(r.recv(), Some("Hello world!"));
//! ```
//!
//! # Types of channels
//!
//! A channel can be created by calling [`bounded`] or [`unbounded`]. The former creates a channel
//! of bounded capacity (i.e. there is a limit to how many messages it can hold), while the latter
//! creates a channel of unbounded capacity (i.e. it can contain an arbitrary number of messages).
//!
//! Both functions return two handles: a sender and a receiver. Senders and receivers represent
//! two opposite sides of a channel. Messages are sent into the channel using senders and received
//! using receivers.
//!
//! Creating an unbounded channel:
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! // Create an unbounded channel.
//! let (s, r) = channel::unbounded();
//!
//! // Can send any number of messages into the channel without blocking.
//! for i in 0..1000 {
//!     s.send(i);
//! }
//! ```
//!
//! Creating a bounded channel:
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! // Create a channel that can hold at most 5 messages at a time.
//! let (s, r) = channel::bounded(5);
//!
//! // Can only send 5 messages without blocking.
//! for i in 0..5 {
//!     s.send(i);
//! }
//!
//! // Another call to `send` would block because the channel is full.
//! // s.send(5);
//! ```
//!
//! A rather special case is a bounded, zero-capacity channel. This kind of channel cannot hold any
//! messages at all! In order to send a message through the channel, a sending thread and a
//! receiving thread have to pair up at the same time:
//!
//! ```
//! use std::thread;
//! use crossbeam_channel as channel;
//!
//! // Create a zero-capacity channel.
//! let (s, r) = channel::bounded(0);
//!
//! // Spawn a thread that sends a message into the channel.
//! // Sending blocks until a receive operation appears on the other side.
//! thread::spawn(move || s.send("Hi!"));
//!
//! // Receive the message.
//! // Receiving blocks until a send operation appears on the other side.
//! assert_eq!(r.recv(), Some("Hi!"));
//! ```
//!
//! # Sharing channels
//!
//! Senders and receivers can be either shared by reference or cloned and then sent to other
//! threads. There can be multiple senders and multiple receivers associated with the same channel.
//!
//! Sharing by reference:
//!
//! ```
//! # extern crate crossbeam_channel;
//! extern crate crossbeam;
//! # fn main() {
//! use crossbeam_channel as channel;
//!
//! let (s, r) = channel::unbounded();
//!
//! crossbeam::scope(|scope| {
//!     // Spawn a thread that sends one message and then receives one.
//!     scope.spawn(|| {
//!         s.send(1);
//!         r.recv().unwrap();
//!     });
//!
//!     // Spawn another thread that does the same thing.
//!     scope.spawn(|| {
//!         s.send(2);
//!         r.recv().unwrap();
//!     });
//! });
//!
//! # }
//! ```
//!
//! Sharing by cloning:
//!
//! ```
//! use std::thread;
//! use crossbeam_channel as channel;
//!
//! let (s1, r1) = channel::unbounded();
//! let (s2, r2) = (s1.clone(), r1.clone());
//!
//! // Spawn a thread that sends one message and then receives one.
//! thread::spawn(move || {
//!     s1.send(1);
//!     r1.recv().unwrap();
//! });
//!
//! // Spawn another thread that receives a message and then sends one.
//! thread::spawn(move || {
//!     r2.recv().unwrap();
//!     s2.send(2);
//! });
//! ```
//!
//! Note that cloning only creates a new reference to the same sending or receiving side. Cloning
//! does not create a new channel.
//!
//! # Closing channels
//!
//! When all senders associated with a channel get dropped, the channel becomes closed. No more
//! messages can be sent, but any remaining messages can still be received. Receive operations on a
//! closed channel never block, even if the channel is empty.
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! let (s, r) = channel::unbounded();
//! s.send(1);
//! s.send(2);
//! s.send(3);
//!
//! // The only sender is dropped, closing the channel.
//! drop(s);
//!
//! // The remaining messages can be received.
//! assert_eq!(r.recv(), Some(1));
//! assert_eq!(r.recv(), Some(2));
//! assert_eq!(r.recv(), Some(3));
//!
//! // There are no more messages in the channel.
//! assert!(r.is_empty());
//!
//! // Note that calling `r.recv()` will not block.
//! // Instead, `None` is returned immediately.
//! assert_eq!(r.recv(), None);
//! ```
//!
//! # Blocking and non-blocking operations
//!
//! Sending a message into a full bounded channel will block until an empty slot in the channel
//! becomes available. Sending into an unbounded channel never blocks because there is always
//! enough space in it. Zero-capacity channels are always empty, and sending blocks until a receive
//! operation appears on the other side of the channel.
//!
//! Receiving from an empty channel blocks until a message is sent into the channel or the channel
//! becomes closed. Zero-capacity channels are always empty, and receiving blocks until a send
//! operation appears on the other side of the channel or it becomes closed.
//!
//! There is also a non-blocking method [`try_recv`], which receives a message if it is immediately
//! available, or returns `None` otherwise.
//!
//! ```
//! use crossbeam_channel as channel;
//!
//! let (s, r) = channel::bounded(1);
//!
//! // Send a message into the channel.
//! s.send("foo");
//!
//! // This call would block because the channel is full.
//! // s.send("bar");
//!
//! // Receive the message.
//! assert_eq!(r.recv(), Some("foo"));
//!
//! // This call would block because the channel is empty.
//! // r.recv();
//!
//! // Try receiving a message without blocking.
//! assert_eq!(r.try_recv(), None);
//!
//! // Close the channel.
//! drop(s);
//!
//! // This call doesn't block because the channel is now closed.
//! assert_eq!(r.recv(), None);
//! ```
//!
//! For greater control over blocking, consider using the [`select!`] macro.
//!
//! # Iteration
//!
//! A channel is a special kind of iterator, where items can be dynamically produced by senders and
//! consumed by receivers. Indeed, [`Receiver`] implements the [`Iterator`] trait, and calling
//! [`next`] is equivalent to calling [`recv`].
//!
//! ```
//! use std::thread;
//! use crossbeam_channel as channel;
//!
//! let (s, r) = channel::unbounded();
//!
//! thread::spawn(move || {
//!     s.send(1);
//!     s.send(2);
//!     s.send(3);
//!     // `s` was moved into the closure so now it gets dropped,
//!     // thus closing the channel.
//! });
//!
//! // Collect all messages from the channel.
//! //
//! // Note that the call to `collect` blocks until the channel becomes
//! // closed and empty, i.e. until `r.next()` returns `None`.
//! let v: Vec<_> = r.collect();
//! assert_eq!(v, [1, 2, 3]);
//! ```
//!
//! # Select
//!
//! The [`select!`] macro allows declaring a set of channel operations and blocking until any one
//! of them becomes ready. Finally, one of the operations is executed. If multiple operations
//! are ready at the same time, a random one is chosen. It is also possible to declare a `default`
//! case that gets executed if none of the operations are initially ready.
//!
//! An example of receiving a message from two channels, whichever becomes ready first:
//!
//! ```
//! # #[macro_use]
//! # extern crate crossbeam_channel;
//! # fn main() {
//! use std::thread;
//! use crossbeam_channel as channel;
//!
//! let (s1, r1) = channel::unbounded();
//! let (s2, r2) = channel::unbounded();
//!
//! thread::spawn(move || s1.send("foo"));
//! thread::spawn(move || s2.send("bar"));
//!
//! // Only one of these two receive operations will be executed.
//! select! {
//!     recv(r1, msg) => assert_eq!(msg, Some("foo")),
//!     recv(r2, msg) => assert_eq!(msg, Some("bar")),
//! }
//! # }
//! ```
//!
//! For more details, take a look at the documentation for [`select!`].
//!
//! If you need to dynamically add cases rather than define them statically inside the macro, use
//! [`Select`] instead.
//!
//! [`std::sync::mpsc`]: https://doc.rust-lang.org/std/sync/mpsc/index.html
//! [`unbounded`]: fn.unbounded.html
//! [`bounded`]: fn.bounded.html
//! [`send`]: struct.Sender.html#method.send
//! [`try_recv`]: struct.Receiver.html#method.try_recv
//! [`recv`]: struct.Receiver.html#method.recv
//! [`next`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#tymethod.next
//! [`Iterator`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html
//! [`select!`]: macro.select.html
//! [`Select`]: struct.Select.html
//! [`Sender`]: struct.Sender.html
//! [`Receiver`]: struct.Receiver.html

extern crate crossbeam_epoch;
extern crate crossbeam_utils;
extern crate rand;
extern crate parking_lot;

mod flavors;

#[doc(hidden)]
pub mod internal;

pub use internal::channel::{Receiver, Sender};
pub use internal::channel::{bounded, unbounded};
pub use internal::channel::{after, tick};
pub use internal::select::Select;
<|endoftext|>


<commit_before>#![allow(unstable)]

#[derive(Clone, Show, PartialEq)]
pub struct Error;

pub type ParseResult<O, I> = Result<(O, I), Error>;

pub trait Stream {
    type Item;
    fn uncons(self) -> ParseResult<<Self as Stream>::Item, Self>;
}

impl  Stream for I {
    type Item = ::Item;
    fn uncons(mut self) -> ParseResult<::Item, I> {
        match self.next() {
            Some(x) => Ok((x, self)),
            None => Err(Error)
        }
    }
}

impl <'a> Stream for &'a str {
    type Item = char;
    fn uncons(self) -> ParseResult<char, &'a str> {
        match self.slice_shift_char() {
            Some(x) => Ok(x),
            None => Err(Error)
        }
    }
}

impl <'a, T> Stream for &'a [T] {
    type Item = &'a T;
    fn uncons(self) -> ParseResult<&'a T, &'a [T]> {
        match self {
            [ref x, rest..] => Ok((x, rest)),
            [] => Err(Error)
        }
    }
}

pub trait Parser {
    type Input: Clone + Stream;
    type Output;
    fn parse(&mut self, input: <Self as Parser>::Input) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input>;
}
impl <'a, I, O, P> Parser for &'a mut P
    where I: Clone + Stream, P: Parser<Input=I, Output=O> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        (*self).parse(input)
    }
}

pub fn char<'a, I>(input: I) -> ParseResult<char, I>
    where I: Stream<Item=char> + Clone {
    input.uncons()
}

pub struct ManyAppend<'a, O: 'a, P: Parser<Output=O> + 'a> {
    parser: P,
    vec: &'a mut Vec<O>
}
impl <'a, O, P: Parser<Output=O> + 'a> Parser for ManyAppend<'a, O, P> {
    type Input =
::Input;
    type Output = ();
    fn parse(&mut self, mut input:
::Input) -> ParseResult<(),
::Input> {
        loop {
            match self.parser.parse(input.clone()) {
                Ok((x, rest)) => {
                    self.vec.push(x);
                    input = rest;
                }
                Err(_) => break
            }
        }
        Ok(((), input))
    }
}

pub fn many_append<'a, O, P: Parser<Output=O>>(parser: P, vec: &'a mut Vec<O>) -> ManyAppend<'a, O, P> {
    ManyAppend { parser: parser, vec: vec }
}

#[derive(Clone)]
pub struct Many
 {
    parser: P
}
impl
 Parser for Many
 {
    type Input =
::Input;
    type Output = Vec<
::Output>;
    fn parse(&mut self, input:
::Input) -> ParseResult<Vec<
::Output>,
::Input> {
        let mut result = Vec::new();
        let ((), input) = try!(many_append(&mut self.parser, &mut result).parse(input));
        Ok((result, input))
    }
}
pub fn many
(p: P) -> Many
 {
    Many { parser: p }
}

pub fn many1<'a, P: Clone + 'a>(mut p: P) -> Box<Parser<Input=
::Input, Output=Vec<
::Output>> + 'a>
    where P: Parser {
    Box::new(FnParser(move |&mut:input| {
        let (first, input) = try!(p.parse(input));
        let mut result = vec![first];
        let ((), input) = try!(many_append(&mut p, &mut result).parse(input));
        Ok((result, input))
    }))
}

#[derive(Clone)]
pub struct SepBy
 {
    parser: P,
    separator: S
}
impl
 Parser for SepBy

    where P: Parser, S: Parser<Input=
::Input> {

    type Input =
::Input;
    type Output = Vec<
::Output>;
    fn parse(&mut self, mut input:
::Input) -> ParseResult<Vec<
::Output>,
::Input> {
        let mut result = Vec::new();
        match self.parser.parse(input.clone()) {
            Ok((x, rest)) => {
                result.push(x);
                input = rest;
            }
            Err(_) => return Ok((result, input))
        }
        let rest = FnParser(|input| {
            let mut env = Env::new(input);
            try!(env.with(&mut self.separator));
            let v = try!(env.with(&mut self.parser));
            env.result(v)
        });
        let ((), input) = try!(many_append(rest, &mut result).parse(input));
        Ok((result, input))
    }
}
pub fn sep_by
(parser: P, separator: S) -> SepBy
 {
    SepBy { parser: parser, separator: separator }
}

impl <'a, I: Clone + Stream, O> Parser for Box<FnMut(I) -> ParseResult<O, I> + 'a> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        self(input)
    }
}

#[derive(Clone)]
struct FnParser<'a, I: Stream, O, F: FnMut(I) -> ParseResult<O, I>>(F);

impl <'a, I, O, F> Parser for FnParser<'a, I, O, F>
    where I: Clone + Stream, F: FnMut(I) -> ParseResult<O, I> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        (self.0)(input)
    }
}

impl <'a, I, O> Parser for fn (I) -> ParseResult<O, I>
    where I: Clone + Stream {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        self(input)
    }
}

#[derive(Clone)]
pub struct Satisfy { pred: Pred }

impl <'a, I, Pred> Parser for Satisfy
    where I: Stream<Item=char> + Clone, Pred: FnMut(char) -> bool {

    type Input = I;
    type Output = char;
    fn parse(&mut self, input: I) -> ParseResult<char, I> {
        match input.uncons() {
            Ok((c, s)) => {
                if (self.pred)(c) { Ok((c, s)) }
                else { Err(Error) }
            }
            Err(err) => Err(err)
        }
    }
}

pub fn satisfy(pred: Pred) -> Satisfy
    where I: Stream + Clone, Pred: FnMut(char) -> bool {
    Satisfy { pred: pred }
}

pub fn space() -> Satisfy bool>
    where I: Stream + Clone {
    satisfy(CharExt::is_whitespace as fn (char) -> bool)
}

#[derive(Clone)]
pub struct StringP<'a, I> { s: &'a str }
impl <'a, 'b, I> Parser for StringP<'b, I>
    where I: Stream<Item=char> + Clone {
    type Input = I;
    type Output = &'b str;
    fn parse(&mut self, mut input: I) -> ParseResult<&'b str, I> {
        for c in self.s.chars() {
            match input.uncons() {
                Ok((other, rest)) => {
                    if c != other { return Err(Error);  }
                    input = rest;
                }
                Err(err) => return Err(err)
            }
        }
        Ok((self.s, input))
    }
}

pub fn string(s: &str) -> StringP
    where I: Stream + Clone {
    StringP { s: s }
}

#[derive(Clone)]
pub struct AndThen<P1, P2>(P1, P2);
impl  Parser for AndThen<P1, P2>
    where I: Clone + Stream, P1: Parser<Input=I, Output=A>, P2: Parser<Input=I, Output=B> {

    type Input = I;
    type Output = (A, B);
    fn parse(&mut self, input: I) -> ParseResult<(A, B), I> {
        let (a, rest) = try!(self.0.parse(input));
        let (b, rest) = try!(self.1.parse(rest));
        Ok(((a, b), rest))
    }
}
pub fn and_then<P1, P2>(p1: P1, p2: P2) -> AndThen<P1, P2>
    where P1: Parser, P2: Parser {
    AndThen(p1, p2)
}

#[derive(Clone)]
pub struct Optional
(P);
impl
 Parser for Optional

    where P: Parser {
    type Input =
::Input;
    type Output = Option<
::Output>;
    fn parse(&mut self, input:
::Input) -> ParseResult<Option<
::Output>,
::Input> {
        match self.0.parse(input.clone()) {
            Ok((x, rest)) => Ok((Some(x), rest)),
            Err(_) => Ok((None, input))
        }
    }
}
pub fn optional
(parser: P) -> Optional
 {
    Optional(parser)
}

pub struct Env {
    input: I
}

impl  Env {
    pub fn new(input: I) -> Env {
        Env { input: input }
    }

    pub fn with
(&mut self, mut parser: P) -> Result<O, Error>
        where P: Parser<Input=I, Output=O> {
        let (o, rest) = try!(parser.parse(self.input.clone()));
        self.input = rest;
        Ok(o)
    }

    pub fn result<O>(self, output: O) -> ParseResult<O, I> {
        Ok((output, self.input))
    }
}

pub fn digit<'a, I>(input: I) -> ParseResult<char, I>
    where I: Stream<Item=char> + Clone {
    match input.uncons() {
        Ok((c, rest)) => {
            if c.is_digit(10) { Ok((c, rest)) }
            else { Err(Error) }
        }
        Err(err) => Err(err)
    }
}

pub struct With<P1, P2>(P1, P2) where P1: Parser, P2: Parser;
impl  Parser for With<P1, P2>
    where I: Clone + Stream, P1: Parser<Input=I>, P2: Parser<Input=I> {

    type Input = I;
    type Output = <P2 as Parser>::Output;
    fn parse(&mut self, input: I) -> ParseResult<<Self as Parser>::Output, I> {
        let ((_, b), rest) = try!((&mut self.0).and_then(&mut self.1).parse(input));
        Ok((b, rest))
    }
}
pub struct Skip<P1, P2>(P1, P2) where P1: Parser, P2: Parser;
impl  Parser for Skip<P1, P2>
    where I: Clone + Stream, P1: Parser<Input=I>, P2: Parser<Input=I> {

    type Input = I;
    type Output = <P1 as Parser>::Output;
    fn parse(&mut self, input: I) -> ParseResult<<Self as Parser>::Output, I> {
        let ((a, _), rest) = try!((&mut self.0).and_then(&mut self.1).parse(input));
        Ok((a, rest))
    }
}

pub trait ParserExt : Parser + Sized {
    fn and_then<P2>(self, p: P2) -> AndThen<Self, P2>
        where P2: Parser {
        and_then(self, p)
    }
    fn with<P2>(self, p: P2) -> With<Self, P2>
        where P2: Parser {
        With(self, p)
    }
    fn skip<P2>(self, p: P2) -> Skip<Self, P2>
        where P2: Parser {
        Skip(self, p)
    }
}

impl
 ParserExt for P { }

#[cfg(test)]
mod tests {
    use super::*;

    fn integer<'a, I>(input: I) -> ParseResult<i64, I>
        where I: Stream<Item=char> + Clone {
        let mut env = Env::new(input);
        let chars = try!(env.with(many(digit as fn(_) -> _)));
        let mut n = 0;
        for &c in chars.iter() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        env.result(n)
    }

    #[test]
    fn test_integer() {
        assert_eq!((integer as fn(_) -> _).parse("123"), Ok((123i64, "")));
    }
    #[test]
    fn list() {
        let mut p = sep_by(integer as fn(_) -> _, satisfy(|c| c == ','));
        assert_eq!(p.parse("123,4,56"), Ok((vec![123, 4, 56], "")));
    }
    #[test]
    fn iterator() {
        let result = (integer as fn(_) -> _).parse("123".chars())
            .map(|(i, mut iter)| (i, iter.next()));
        assert_eq!(result, Ok((123i64, None)));
    }
    #[test]
    fn field() {
        let word = many(satisfy(|c| c.is_alphanumeric()));
        let word2 = many(satisfy(|c| c.is_alphanumeric()));
        let spaces = many(space());
        let c_decl = word
            .skip(spaces.clone())
            .skip(satisfy(|c| c == ':'))
            .skip(spaces)
            .and_then(word2)
            .parse("x: int");
        assert_eq!(c_decl, Ok(((vec!['x'], vec!['i', 'n', 't']), "")));
    }
}
<commit_msg>Changd many1 implementation to not used Boz<Parser> which caused ICE<commit_after>#![allow(unstable)]

#[derive(Clone, Show, PartialEq)]
pub struct Error;

pub type ParseResult<O, I> = Result<(O, I), Error>;

pub trait Stream {
    type Item;
    fn uncons(self) -> ParseResult<<Self as Stream>::Item, Self>;
}

impl  Stream for I {
    type Item = ::Item;
    fn uncons(mut self) -> ParseResult<::Item, I> {
        match self.next() {
            Some(x) => Ok((x, self)),
            None => Err(Error)
        }
    }
}

impl <'a> Stream for &'a str {
    type Item = char;
    fn uncons(self) -> ParseResult<char, &'a str> {
        match self.slice_shift_char() {
            Some(x) => Ok(x),
            None => Err(Error)
        }
    }
}

impl <'a, T> Stream for &'a [T] {
    type Item = &'a T;
    fn uncons(self) -> ParseResult<&'a T, &'a [T]> {
        match self {
            [ref x, rest..] => Ok((x, rest)),
            [] => Err(Error)
        }
    }
}

pub trait Parser {
    type Input: Clone + Stream;
    type Output;
    fn parse(&mut self, input: <Self as Parser>::Input) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input>;
}
impl <'a, I, O, P> Parser for &'a mut P
    where I: Clone + Stream, P: Parser<Input=I, Output=O> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        (*self).parse(input)
    }
}

pub fn char<'a, I>(input: I) -> ParseResult<char, I>
    where I: Stream<Item=char> + Clone {
    input.uncons()
}

pub struct ManyAppend<'a, O: 'a, P: Parser<Output=O> + 'a> {
    parser: P,
    vec: &'a mut Vec<O>
}
impl <'a, O, P: Parser<Output=O> + 'a> Parser for ManyAppend<'a, O, P> {
    type Input =
::Input;
    type Output = ();
    fn parse(&mut self, mut input:
::Input) -> ParseResult<(),
::Input> {
        loop {
            match self.parser.parse(input.clone()) {
                Ok((x, rest)) => {
                    self.vec.push(x);
                    input = rest;
                }
                Err(_) => break
            }
        }
        Ok(((), input))
    }
}

pub fn many_append<'a, O, P: Parser<Output=O>>(parser: P, vec: &'a mut Vec<O>) -> ManyAppend<'a, O, P> {
    ManyAppend { parser: parser, vec: vec }
}

#[derive(Clone)]
pub struct Many
 {
    parser: P
}
impl
 Parser for Many
 {
    type Input =
::Input;
    type Output = Vec<
::Output>;
    fn parse(&mut self, input:
::Input) -> ParseResult<Vec<
::Output>,
::Input> {
        let mut result = Vec::new();
        let ((), input) = try!(many_append(&mut self.parser, &mut result).parse(input));
        Ok((result, input))
    }
}
pub fn many
(p: P) -> Many
 {
    Many { parser: p }
}

pub struct Many1
(P);
impl
 Parser for Many1
 {
    type Input =
::Input;
    type Output = Vec<
::Output>;
    fn parse(&mut self, input:
::Input) -> ParseResult<Vec<
::Output>,
::Input> {
        let (first, input) = try!(self.0.parse(input));
        let mut result = vec![first];
        let ((), input) = try!(many_append(&mut self.0, &mut result).parse(input));
        Ok((result, input))
    }
}
pub fn many1
(p: P) -> Many1

    where P: Parser {
    Many1(p)
}

#[derive(Clone)]
pub struct SepBy
 {
    parser: P,
    separator: S
}
impl
 Parser for SepBy

    where P: Parser, S: Parser<Input=
::Input> {

    type Input =
::Input;
    type Output = Vec<
::Output>;
    fn parse(&mut self, mut input:
::Input) -> ParseResult<Vec<
::Output>,
::Input> {
        let mut result = Vec::new();
        match self.parser.parse(input.clone()) {
            Ok((x, rest)) => {
                result.push(x);
                input = rest;
            }
            Err(_) => return Ok((result, input))
        }
        let rest = FnParser(|input| {
            let mut env = Env::new(input);
            try!(env.with(&mut self.separator));
            let v = try!(env.with(&mut self.parser));
            env.result(v)
        });
        let ((), input) = try!(many_append(rest, &mut result).parse(input));
        Ok((result, input))
    }
}
pub fn sep_by
(parser: P, separator: S) -> SepBy
 {
    SepBy { parser: parser, separator: separator }
}

impl <'a, I: Clone + Stream, O> Parser for Box<FnMut(I) -> ParseResult<O, I> + 'a> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        self(input)
    }
}

#[derive(Clone)]
struct FnParser<'a, I: Stream, O, F: FnMut(I) -> ParseResult<O, I>>(F);

impl <'a, I, O, F> Parser for FnParser<'a, I, O, F>
    where I: Clone + Stream, F: FnMut(I) -> ParseResult<O, I> {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        (self.0)(input)
    }
}

impl <'a, I, O> Parser for fn (I) -> ParseResult<O, I>
    where I: Clone + Stream {
    type Input = I;
    type Output = O;
    fn parse(&mut self, input: I) -> ParseResult<O, I> {
        self(input)
    }
}

#[derive(Clone)]
pub struct Satisfy { pred: Pred }

impl <'a, I, Pred> Parser for Satisfy
    where I: Stream<Item=char> + Clone, Pred: FnMut(char) -> bool {

    type Input = I;
    type Output = char;
    fn parse(&mut self, input: I) -> ParseResult<char, I> {
        match input.uncons() {
            Ok((c, s)) => {
                if (self.pred)(c) { Ok((c, s)) }
                else { Err(Error) }
            }
            Err(err) => Err(err)
        }
    }
}

pub fn satisfy(pred: Pred) -> Satisfy
    where I: Stream + Clone, Pred: FnMut(char) -> bool {
    Satisfy { pred: pred }
}

pub fn space() -> Satisfy bool>
    where I: Stream + Clone {
    satisfy(CharExt::is_whitespace as fn (char) -> bool)
}

#[derive(Clone)]
pub struct StringP<'a, I> { s: &'a str }
impl <'a, 'b, I> Parser for StringP<'b, I>
    where I: Stream<Item=char> + Clone {
    type Input = I;
    type Output = &'b str;
    fn parse(&mut self, mut input: I) -> ParseResult<&'b str, I> {
        for c in self.s.chars() {
            match input.uncons() {
                Ok((other, rest)) => {
                    if c != other { return Err(Error);  }
                    input = rest;
                }
                Err(err) => return Err(err)
            }
        }
        Ok((self.s, input))
    }
}

pub fn string(s: &str) -> StringP
    where I: Stream + Clone {
    StringP { s: s }
}

#[derive(Clone)]
pub struct AndThen<P1, P2>(P1, P2);
impl  Parser for AndThen<P1, P2>
    where I: Clone + Stream, P1: Parser<Input=I, Output=A>, P2: Parser<Input=I, Output=B> {

    type Input = I;
    type Output = (A, B);
    fn parse(&mut self, input: I) -> ParseResult<(A, B), I> {
        let (a, rest) = try!(self.0.parse(input));
        let (b, rest) = try!(self.1.parse(rest));
        Ok(((a, b), rest))
    }
}
pub fn and_then<P1, P2>(p1: P1, p2: P2) -> AndThen<P1, P2>
    where P1: Parser, P2: Parser {
    AndThen(p1, p2)
}

#[derive(Clone)]
pub struct Optional
(P);
impl
 Parser for Optional

    where P: Parser {
    type Input =
::Input;
    type Output = Option<
::Output>;
    fn parse(&mut self, input:
::Input) -> ParseResult<Option<
::Output>,
::Input> {
        match self.0.parse(input.clone()) {
            Ok((x, rest)) => Ok((Some(x), rest)),
            Err(_) => Ok((None, input))
        }
    }
}
pub fn optional
(parser: P) -> Optional
 {
    Optional(parser)
}

pub struct Env {
    input: I
}

impl  Env {
    pub fn new(input: I) -> Env {
        Env { input: input }
    }

    pub fn with
(&mut self, mut parser: P) -> Result<O, Error>
        where P: Parser<Input=I, Output=O> {
        let (o, rest) = try!(parser.parse(self.input.clone()));
        self.input = rest;
        Ok(o)
    }

    pub fn result<O>(self, output: O) -> ParseResult<O, I> {
        Ok((output, self.input))
    }
}

pub fn digit<'a, I>(input: I) -> ParseResult<char, I>
    where I: Stream<Item=char> + Clone {
    match input.uncons() {
        Ok((c, rest)) => {
            if c.is_digit(10) { Ok((c, rest)) }
            else { Err(Error) }
        }
        Err(err) => Err(err)
    }
}

pub struct With<P1, P2>(P1, P2) where P1: Parser, P2: Parser;
impl  Parser for With<P1, P2>
    where I: Clone + Stream, P1: Parser<Input=I>, P2: Parser<Input=I> {

    type Input = I;
    type Output = <P2 as Parser>::Output;
    fn parse(&mut self, input: I) -> ParseResult<<Self as Parser>::Output, I> {
        let ((_, b), rest) = try!((&mut self.0).and_then(&mut self.1).parse(input));
        Ok((b, rest))
    }
}
pub struct Skip<P1, P2>(P1, P2) where P1: Parser, P2: Parser;
impl  Parser for Skip<P1, P2>
    where I: Clone + Stream, P1: Parser<Input=I>, P2: Parser<Input=I> {

    type Input = I;
    type Output = <P1 as Parser>::Output;
    fn parse(&mut self, input: I) -> ParseResult<<Self as Parser>::Output, I> {
        let ((a, _), rest) = try!((&mut self.0).and_then(&mut self.1).parse(input));
        Ok((a, rest))
    }
}

pub trait ParserExt : Parser + Sized {
    fn and_then<P2>(self, p: P2) -> AndThen<Self, P2>
        where P2: Parser {
        and_then(self, p)
    }
    fn with<P2>(self, p: P2) -> With<Self, P2>
        where P2: Parser {
        With(self, p)
    }
    fn skip<P2>(self, p: P2) -> Skip<Self, P2>
        where P2: Parser {
        Skip(self, p)
    }
}

impl
 ParserExt for P { }

#[cfg(test)]
mod tests {
    use super::*;

    fn integer<'a, I>(input: I) -> ParseResult<i64, I>
        where I: Stream<Item=char> + Clone {
        let mut env = Env::new(input);
        let chars = try!(env.with(many(digit as fn(_) -> _)));
        let mut n = 0;
        for &c in chars.iter() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        env.result(n)
    }

    #[test]
    fn test_integer() {
        assert_eq!((integer as fn(_) -> _).parse("123"), Ok((123i64, "")));
    }
    #[test]
    fn list() {
        let mut p = sep_by(integer as fn(_) -> _, satisfy(|c| c == ','));
        assert_eq!(p.parse("123,4,56"), Ok((vec![123, 4, 56], "")));
    }
    #[test]
    fn iterator() {
        let result = (integer as fn(_) -> _).parse("123".chars())
            .map(|(i, mut iter)| (i, iter.next()));
        assert_eq!(result, Ok((123i64, None)));
    }
    #[test]
    fn field() {
        let word = many(satisfy(|c| c.is_alphanumeric()));
        let word2 = many(satisfy(|c| c.is_alphanumeric()));
        let spaces = many(space());
        let c_decl = word
            .skip(spaces.clone())
            .skip(satisfy(|c| c == ':'))
            .skip(spaces)
            .and_then(word2)
            .parse("x: int");
        assert_eq!(c_decl, Ok(((vec!['x'], vec!['i', 'n', 't']), "")));
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! Tutil is a toolbox for developing command line applications in Rust,
//! influenced by the [TTY library][tty] for Ruby. It provides modules for
//! common tasks such as colourisation, gathering information from the user,
//! confirmation prompts, and querying the system and terminal. It is not
//! intended to be a command line argument parser, rather, it is intended to be
//! a plumbing library for common tasks.
//!
//! This documentation is written in British English, however the API is
//! completely written in US English to match the design of the Rust standard
//! library and most crates in circulation. If you do find something in the API
//! that is written in British English file a [bug report][br] or submit a
//! [pull request][pr] correcting the spelling.
//!
//! [tty]: http://peter-murach.github.io/tty/
//! [br]: https://github.com/SShrike/tutil/issues
//! [pr]: https://github.com/SShrike/tutil/pulls

#![doc(html_root_url = "https://shrike.me/tutil/")]

#![cfg_attr(feature = "lints", feature(plugin))]
#![cfg_attr(feature = "lints", plugin(clippy))]

#![cfg_attr(feature = "lints", allow(doc_markdown))]
#![cfg_attr(feature = "lints", allow(needless_return))]

#![warn(missing_docs)]
#![warn(trivial_casts, trivial_numeric_casts)]
#![warn(unused_extern_crates, unused_qualifications)]

#[cfg(unix)]
extern crate libc;

#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate kernel32;

pub mod crayon;
pub mod screen;
<commit_msg>Fix the link to tty<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! Tutil is a toolbox for developing command line applications in Rust,
//! influenced by the [TTY library][tty] for Ruby. It provides modules for
//! common tasks such as colourisation, gathering information from the user,
//! confirmation prompts, and querying the system and terminal. It is not
//! intended to be a command line argument parser, rather, it is intended to be
//! a plumbing library for common tasks.
//!
//! This documentation is written in British English, however the API is
//! completely written in US English to match the design of the Rust standard
//! library and most crates in circulation. If you do find something in the API
//! that is written in British English file a [bug report][br] or submit a
//! [pull request][pr] correcting the spelling.
//!
//! [tty]: http://piotrmurach.github.io/tty/
//! [br]: https://github.com/SShrike/tutil/issues
//! [pr]: https://github.com/SShrike/tutil/pulls

#![doc(html_root_url = "https://shrike.me/tutil/")]

#![cfg_attr(feature = "lints", feature(plugin))]
#![cfg_attr(feature = "lints", plugin(clippy))]

#![cfg_attr(feature = "lints", allow(doc_markdown))]
#![cfg_attr(feature = "lints", allow(needless_return))]

#![warn(missing_docs)]
#![warn(trivial_casts, trivial_numeric_casts)]
#![warn(unused_extern_crates, unused_qualifications)]

#[cfg(unix)]
extern crate libc;

#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate kernel32;

pub mod crayon;
pub mod screen;
<|endoftext|>