<commit_before>use error::{Error, Result};
use variable::{VariableMap, Value, varname_prefix};
use pattern::Pattern;
use regex::{Regex, Captures};
use std::collections::HashMap;
use std::cmp::max;
use std::fmt::{self, Display, Formatter};
use MatchRange;
use explain::{Recorder, Explainer};

// The different kinds of directives we support.
enum Directive {
    Check(Pattern),
    SameLn(Pattern),
    NextLn(Pattern),
    Unordered(Pattern),
    Not(Pattern),
    Regex(String, String),
}

// Regular expression matching a directive.
// The match groups are:
//
// 1. Keyword.
// 2. Rest of line / pattern.
//
const DIRECTIVE_RX: &'static str = r"\b(check|sameln|nextln|unordered|not|regex):\s+(.*)";

impl Directive {
    /// Create a new directive from a `DIRECTIVE_RX` match.
    fn new(caps: Captures) -> Result<Directive> {
        let cmd = caps.at(1).expect("group 1 must match");
        let rest = caps.at(2).expect("group 2 must match");

        if cmd == "regex" {
            return Directive::regex(rest);
        }

        // All other commands are followed by a pattern.
        let pat = try!(rest.parse());

        match cmd {
            "check" => Ok(Directive::Check(pat)),
            "sameln" => Ok(Directive::SameLn(pat)),
            "nextln" => Ok(Directive::NextLn(pat)),
            "unordered" => Ok(Directive::Unordered(pat)),
            "not" => {
                if !pat.defs().is_empty() {
                    let msg = format!("can't define variables '$({}=...' in not: {}",
                                      pat.defs()[0],
                                      rest);
                    Err(Error::DuplicateDef(msg))
                } else {
                    Ok(Directive::Not(pat))
                }
            }
            _ => panic!("unexpected command {} in regex match", cmd),
        }
    }

    /// Create a `regex:` directive from a `VAR=...` string.
    fn regex(rest: &str) -> Result<Directive> {
        let varlen = varname_prefix(rest);
        if varlen == 0 {
            return Err(Error::Syntax(format!("invalid variable name in regex: {}", rest)));
        }
        let var = rest[0..varlen].to_string();
        if !rest[varlen..].starts_with("=") {
            return Err(Error::Syntax(format!("expected '=' after variable '{}' in regex: {}",
                                             var,
                                             rest)));
        }
        Ok(Directive::Regex(var, rest[varlen + 1..].to_string()))
    }
}

/// Builder for constructing a `Checker` instance.
pub struct CheckerBuilder {
    directives: Vec<Directive>,
    linerx: Regex,
}

impl CheckerBuilder {
    /// Create a new, blank `CheckerBuilder`.
    pub fn new() -> CheckerBuilder {
        CheckerBuilder {
            directives: Vec::new(),
            linerx: Regex::new(DIRECTIVE_RX).unwrap(),
        }
    }

    /// Add a potential directive line.
    ///
    /// Returns true if this is a a directive with one of the known prefixes.
    /// Returns false if no known directive was found.
    /// Returns an error if there is a problem with the directive.
    pub fn directive(&mut self, l: &str) -> Result<bool> {
        match self.linerx.captures(l) {
            Some(caps) => {
                self.directives.push(try!(Directive::new(caps)));
                Ok(true)
            }
            None => Ok(false),
        }
    }

    /// Add multiple directives.
    ///
    /// The text is split into lines that are added individually as potential directives.
    /// This method can be used to parse a whole test file containing multiple directives.
    pub fn text(&mut self, t: &str) -> Result<&mut Self> {
        for caps in self.linerx.captures_iter(t) {
            self.directives.push(try!(Directive::new(caps)));
        }
        Ok(self)
    }

    /// Get the finished `Checker`.
    pub fn finish(&mut self) -> Checker {
        // Move directives into the new checker, leaving `self.directives` empty and ready for
        // building a new checker.
        Checker::new(self.directives.split_off(0))
    }
}

/// Verify a list of directives against a test input.
///
/// Use a `CheckerBuilder` to construct a `Checker`. Then use the `test` method to verify the list
/// of directives against a test input.
pub struct Checker {
    directives: Vec<Directive>,
}

impl Checker {
    fn new(directives: Vec<Directive>) -> Checker {
        Checker { directives: directives }
    }

    /// An empty checker contains no directives, and will match any input string.
    pub fn is_empty(&self) -> bool {
        self.directives.is_empty()
    }

    /// Verify directives against the input text.
    ///
    /// This returns `true` if the text matches all the directives, `false` if it doesn't.
    /// An error is only returned if there is a problem with the directives.
    pub fn check(&self, text: &str, vars: &VariableMap) -> Result<bool> {
        self.run(text, vars, &mut ())
    }

    /// Explain how directives are matched against the input text.
    pub fn explain(&self, text: &str, vars: &VariableMap) -> Result<(bool, String)> {
        let mut expl = Explainer::new(text);
        let success = try!(self.run(text, vars, &mut expl));
        expl.finish();
        Ok((success, expl.to_string()))
    }

    fn run(&self, text: &str, vars: &VariableMap, recorder: &mut Recorder) -> Result<bool> {
        let mut state = State::new(text, vars, recorder);

        // For each pending `not:` check, store (begin-offset, regex).
        let mut nots = Vec::new();

        for (dct_idx, dct) in self.directives.iter().enumerate() {
            let (pat, range) = match *dct {
                Directive::Check(ref pat) => (pat, state.check()),
                Directive::SameLn(ref pat) => (pat, state.sameln()),
                Directive::NextLn(ref pat) => (pat, state.nextln()),
                Directive::Unordered(ref pat) => (pat, state.unordered(pat)),
                Directive::Not(ref pat) => {
                    // Resolve `not:` directives immediately to get the right variable values, but
                    // don't match it until we know the end of the range.
                    //
                    // The `not:` directives test the same range as `unordered:` directives. In
                    // particular, if they refer to defined variables, their range is restricted to
                    // the text following the match that defined the variable.
                    nots.push((dct_idx, state.unordered_begin(pat), try!(pat.resolve(&state))));
                    continue;
                }
                Directive::Regex(ref var, ref rx) => {
                    state.vars.insert(var.clone(),
                                      VarDef {
                                          value: Value::Regex(rx.clone()),
                                          offset: 0,
                                      });
                    continue;
                }
            };
            // Check if `pat` matches in `range`.
            state.recorder.directive(dct_idx);
            if let Some((match_begin, match_end)) = try!(state.match_positive(pat, range)) {
                if let &Directive::Unordered(_) = dct {
                    // This was an unordered unordered match.
                    // Keep track of the largest matched position, but leave `last_ordered` alone.
                    state.max_match = max(state.max_match, match_end);
                } else {
                    // Ordered match.
                    state.last_ordered = match_end;
                    state.max_match = match_end;

                    // Verify any pending `not:` directives now that we know their range.
                    for (not_idx, not_begin, rx) in nots.drain(..) {
                        state.recorder.directive(not_idx);
                        if let Some((s, e)) = rx.find(&text[not_begin..match_begin]) {
                            // Matched `not:` pattern.
                            state.recorder.matched_not(rx.as_str(), (not_begin + s, not_begin + e));
                            return Ok(false);
                        } else {
                            state.recorder.missed_not(rx.as_str(), (not_begin, match_begin));
                        }
                    }
                }
            } else {
                // No match!
                return Ok(false);
            }
        }

        // Verify any pending `not:` directives after the last ordered directive.
        for (not_idx, not_begin, rx) in nots.drain(..) {
            state.recorder.directive(not_idx);
            if let Some(_) = rx.find(&text[not_begin..]) {
                // Matched `not:` pattern.
                // TODO: Use matched range for an error message.
                return Ok(false);
            }
        }

        Ok(true)
    }
}

/// A local definition of a variable.
pub struct VarDef {
    /// The value given to the variable.
    value: Value,
    /// Offset in input text from where the variable is available.
    offset: usize,
}

struct State<'a> {
    text: &'a str,
    env_vars: &'a VariableMap,
    recorder: &'a mut Recorder,

    vars: HashMap<String, VarDef>,
    // Offset after the last ordered match. This does not include recent unordered matches.
    last_ordered: usize,
    // Largest offset following a positive match, including unordered matches.
    max_match: usize,
}

impl<'a> State<'a> {
    fn new(text: &'a str, env_vars: &'a VariableMap, recorder: &'a mut Recorder) -> State<'a> {
        State {
            text: text,
            env_vars: env_vars,
            recorder: recorder,
            vars: HashMap::new(),
            last_ordered: 0,
            max_match: 0,
        }
    }

    // Get the offset following the match that defined `var`, or 0 if var is an environment
    // variable or unknown.
    fn def_offset(&self, var: &str) -> usize {
        self.vars.get(var).map(|&VarDef { offset, .. }| offset).unwrap_or(0)
    }

    // Get the offset of the beginning of the next line after `pos`.
    fn bol(&self, pos: usize) -> usize {
        if let Some(offset) = self.text[pos..].find('\n') {
            pos + offset + 1
        } else {
            self.text.len()
        }
    }

    // Get the range in text to be matched by a `check:`.
    fn check(&self) -> MatchRange {
        (self.max_match, self.text.len())
    }

    // Get the range in text to be matched by a `sameln:`.
    fn sameln(&self) -> MatchRange {
        let b = self.max_match;
        let e = self.bol(b);
        (b, e)
    }

    // Get the range in text to be matched by a `nextln:`.
    fn nextln(&self) -> MatchRange {
        let b = self.bol(self.max_match);
        let e = self.bol(b);
        (b, e)
    }

    // Get the beginning of the range in text to be matched by a `unordered:` or `not:` directive.
    // The unordered directive must match after the directives that define the variables used.
    fn unordered_begin(&self, pat: &Pattern) -> usize {
        let mut from = self.last_ordered;
        for part in pat.parts() {
            if let Some(var) = part.ref_var() {
                from = max(from, self.def_offset(var));
            }
        }
        from
    }

    // Get the range in text to be matched by a `unordered:` directive.
    fn unordered(&self, pat: &Pattern) -> MatchRange {
        (self.unordered_begin(pat), self.text.len())
    }

    // Search for `pat` in `range`, return the range matched.
    // After a positive match, update variable definitions, if any.
    fn match_positive(&mut self, pat: &Pattern, range: MatchRange) -> Result<Option<MatchRange>> {
        let rx = try!(pat.resolve(self));
        let txt = &self.text[range.0..range.1];
        let defs = pat.defs();
        let matched_range = if defs.is_empty() {
            // Pattern defines no variables. Fastest search is `find`.
            rx.find(txt)
        } else {
            // We need the captures to define variables.
            rx.captures(txt).map(|caps| {
                let matched_range = caps.pos(0).expect("whole expression must match");
                for var in defs {
                    let txtval = caps.name(var).unwrap_or("");
                    self.recorder.defined_var(var, txtval);
                    let vardef = VarDef {
                        value: Value::Text(txtval.to_string()),
                        // This offset is the end of the whole matched pattern, not just the text
                        // defining the variable.
                        offset: range.0 + matched_range.1,
                    };
                    self.vars.insert(var.clone(), vardef);
                }
                matched_range
            })
        };
        Ok(if let Some((b, e)) = matched_range {
            let r = (range.0 + b, range.0 + e);
            self.recorder.matched_check(rx.as_str(), r);
            Some(r)
        } else {
            self.recorder.missed_check(rx.as_str(), range);
            None
        })
    }
}

impl<'a> VariableMap for State<'a> {
    fn lookup(&self, varname: &str) -> Option<Value> {
        // First look for a local define.
        if let Some(&VarDef { ref value, .. }) = self.vars.get(varname) {
            Some(value.clone())
        } else {
            // No local, maybe an environment variable?
            self.env_vars.lookup(varname)
        }
    }
}

impl Display for Directive {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use self::Directive::*;
        match *self {
            Check(ref pat) => writeln!(f, "check: {}", pat),
            SameLn(ref pat) => writeln!(f, "sameln: {}", pat),
            NextLn(ref pat) => writeln!(f, "nextln: {}", pat),
            Unordered(ref pat) => writeln!(f, "unordered: {}", pat),
            Not(ref pat) => writeln!(f, "not: {}", pat),
            Regex(ref var, ref rx) => writeln!(f, "regex: {}={}", var, rx),
        }
    }
}

impl Display for Checker {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        for (idx, dir) in self.directives.iter().enumerate() {
            try!(write!(f, "#{} {}", idx, dir));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::CheckerBuilder;
    use error::Error;

    fn e2s(e: Error) -> String {
        e.to_string()
    }

    #[test]
    fn directive() {
        let mut b = CheckerBuilder::new();

        assert_eq!(b.directive("not here: more text").map_err(e2s), Ok(false));
        assert_eq!(b.directive("not here: regex: X=more text").map_err(e2s),
                   Ok(true));
        assert_eq!(b.directive("regex: X = tommy").map_err(e2s),
                   Err("expected '=' after variable 'X' in regex: X = tommy".to_string()));
        assert_eq!(b.directive("[arm]not:    patt $x $(y) here").map_err(e2s),
                   Ok(true));
        assert_eq!(b.directive("[x86]sameln: $x $(y=[^]]*) there").map_err(e2s),
                   Ok(true));

        let c = b.finish();
        assert_eq!(c.to_string(),
                   "#0 regex: X=more text\n#1 not: patt $(x) $(y) here\n#2 sameln: $(x) \
                    $(y=[^]]*) there\n");
    }
}
<commit_msg>Idiomatic impl of unordered_begin.<commit_after>use error::{Error, Result};
use variable::{VariableMap, Value, varname_prefix};
use pattern::Pattern;
use regex::{Regex, Captures};
use std::collections::HashMap;
use std::cmp::max;
use std::fmt::{self, Display, Formatter};
use MatchRange;
use explain::{Recorder, Explainer};

// The different kinds of directives we support.
enum Directive {
    Check(Pattern),
    SameLn(Pattern),
    NextLn(Pattern),
    Unordered(Pattern),
    Not(Pattern),
    Regex(String, String),
}

// Regular expression matching a directive.
// The match groups are:
//
// 1. Keyword.
// 2. Rest of line / pattern.
//
const DIRECTIVE_RX: &'static str = r"\b(check|sameln|nextln|unordered|not|regex):\s+(.*)";

impl Directive {
    /// Create a new directive from a `DIRECTIVE_RX` match.
    fn new(caps: Captures) -> Result<Directive> {
        let cmd = caps.at(1).expect("group 1 must match");
        let rest = caps.at(2).expect("group 2 must match");

        if cmd == "regex" {
            return Directive::regex(rest);
        }

        // All other commands are followed by a pattern.
        let pat = try!(rest.parse());

        match cmd {
            "check" => Ok(Directive::Check(pat)),
            "sameln" => Ok(Directive::SameLn(pat)),
            "nextln" => Ok(Directive::NextLn(pat)),
            "unordered" => Ok(Directive::Unordered(pat)),
            "not" => {
                if !pat.defs().is_empty() {
                    let msg = format!("can't define variables '$({}=...' in not: {}",
                                      pat.defs()[0],
                                      rest);
                    Err(Error::DuplicateDef(msg))
                } else {
                    Ok(Directive::Not(pat))
                }
            }
            _ => panic!("unexpected command {} in regex match", cmd),
        }
    }

    /// Create a `regex:` directive from a `VAR=...` string.
    fn regex(rest: &str) -> Result<Directive> {
        let varlen = varname_prefix(rest);
        if varlen == 0 {
            return Err(Error::Syntax(format!("invalid variable name in regex: {}", rest)));
        }
        let var = rest[0..varlen].to_string();
        if !rest[varlen..].starts_with("=") {
            return Err(Error::Syntax(format!("expected '=' after variable '{}' in regex: {}",
                                             var,
                                             rest)));
        }
        Ok(Directive::Regex(var, rest[varlen + 1..].to_string()))
    }
}

/// Builder for constructing a `Checker` instance.
pub struct CheckerBuilder {
    directives: Vec<Directive>,
    linerx: Regex,
}

impl CheckerBuilder {
    /// Create a new, blank `CheckerBuilder`.
    pub fn new() -> CheckerBuilder {
        CheckerBuilder {
            directives: Vec::new(),
            linerx: Regex::new(DIRECTIVE_RX).unwrap(),
        }
    }

    /// Add a potential directive line.
    ///
    /// Returns true if this is a a directive with one of the known prefixes.
    /// Returns false if no known directive was found.
    /// Returns an error if there is a problem with the directive.
    pub fn directive(&mut self, l: &str) -> Result<bool> {
        match self.linerx.captures(l) {
            Some(caps) => {
                self.directives.push(try!(Directive::new(caps)));
                Ok(true)
            }
            None => Ok(false),
        }
    }

    /// Add multiple directives.
    ///
    /// The text is split into lines that are added individually as potential directives.
    /// This method can be used to parse a whole test file containing multiple directives.
    pub fn text(&mut self, t: &str) -> Result<&mut Self> {
        for caps in self.linerx.captures_iter(t) {
            self.directives.push(try!(Directive::new(caps)));
        }
        Ok(self)
    }

    /// Get the finished `Checker`.
    pub fn finish(&mut self) -> Checker {
        // Move directives into the new checker, leaving `self.directives` empty and ready for
        // building a new checker.
        Checker::new(self.directives.split_off(0))
    }
}

/// Verify a list of directives against a test input.
///
/// Use a `CheckerBuilder` to construct a `Checker`. Then use the `test` method to verify the list
/// of directives against a test input.
pub struct Checker {
    directives: Vec<Directive>,
}

impl Checker {
    fn new(directives: Vec<Directive>) -> Checker {
        Checker { directives: directives }
    }

    /// An empty checker contains no directives, and will match any input string.
    pub fn is_empty(&self) -> bool {
        self.directives.is_empty()
    }

    /// Verify directives against the input text.
    ///
    /// This returns `true` if the text matches all the directives, `false` if it doesn't.
    /// An error is only returned if there is a problem with the directives.
    pub fn check(&self, text: &str, vars: &VariableMap) -> Result<bool> {
        self.run(text, vars, &mut ())
    }

    /// Explain how directives are matched against the input text.
    pub fn explain(&self, text: &str, vars: &VariableMap) -> Result<(bool, String)> {
        let mut expl = Explainer::new(text);
        let success = try!(self.run(text, vars, &mut expl));
        expl.finish();
        Ok((success, expl.to_string()))
    }

    fn run(&self, text: &str, vars: &VariableMap, recorder: &mut Recorder) -> Result<bool> {
        let mut state = State::new(text, vars, recorder);

        // For each pending `not:` check, store (begin-offset, regex).
        let mut nots = Vec::new();

        for (dct_idx, dct) in self.directives.iter().enumerate() {
            let (pat, range) = match *dct {
                Directive::Check(ref pat) => (pat, state.check()),
                Directive::SameLn(ref pat) => (pat, state.sameln()),
                Directive::NextLn(ref pat) => (pat, state.nextln()),
                Directive::Unordered(ref pat) => (pat, state.unordered(pat)),
                Directive::Not(ref pat) => {
                    // Resolve `not:` directives immediately to get the right variable values, but
                    // don't match it until we know the end of the range.
                    //
                    // The `not:` directives test the same range as `unordered:` directives. In
                    // particular, if they refer to defined variables, their range is restricted to
                    // the text following the match that defined the variable.
                    nots.push((dct_idx, state.unordered_begin(pat), try!(pat.resolve(&state))));
                    continue;
                }
                Directive::Regex(ref var, ref rx) => {
                    state.vars.insert(var.clone(),
                                      VarDef {
                                          value: Value::Regex(rx.clone()),
                                          offset: 0,
                                      });
                    continue;
                }
            };
            // Check if `pat` matches in `range`.
            state.recorder.directive(dct_idx);
            if let Some((match_begin, match_end)) = try!(state.match_positive(pat, range)) {
                if let &Directive::Unordered(_) = dct {
                    // This was an unordered unordered match.
                    // Keep track of the largest matched position, but leave `last_ordered` alone.
                    state.max_match = max(state.max_match, match_end);
                } else {
                    // Ordered match.
                    state.last_ordered = match_end;
                    state.max_match = match_end;

                    // Verify any pending `not:` directives now that we know their range.
                    for (not_idx, not_begin, rx) in nots.drain(..) {
                        state.recorder.directive(not_idx);
                        if let Some((s, e)) = rx.find(&text[not_begin..match_begin]) {
                            // Matched `not:` pattern.
                            state.recorder.matched_not(rx.as_str(), (not_begin + s, not_begin + e));
                            return Ok(false);
                        } else {
                            state.recorder.missed_not(rx.as_str(), (not_begin, match_begin));
                        }
                    }
                }
            } else {
                // No match!
                return Ok(false);
            }
        }

        // Verify any pending `not:` directives after the last ordered directive.
        for (not_idx, not_begin, rx) in nots.drain(..) {
            state.recorder.directive(not_idx);
            if let Some(_) = rx.find(&text[not_begin..]) {
                // Matched `not:` pattern.
                // TODO: Use matched range for an error message.
                return Ok(false);
            }
        }

        Ok(true)
    }
}

/// A local definition of a variable.
pub struct VarDef {
    /// The value given to the variable.
    value: Value,
    /// Offset in input text from where the variable is available.
    offset: usize,
}

struct State<'a> {
    text: &'a str,
    env_vars: &'a VariableMap,
    recorder: &'a mut Recorder,

    vars: HashMap<String, VarDef>,
    // Offset after the last ordered match. This does not include recent unordered matches.
    last_ordered: usize,
    // Largest offset following a positive match, including unordered matches.
    max_match: usize,
}

impl<'a> State<'a> {
    fn new(text: &'a str, env_vars: &'a VariableMap, recorder: &'a mut Recorder) -> State<'a> {
        State {
            text: text,
            env_vars: env_vars,
            recorder: recorder,
            vars: HashMap::new(),
            last_ordered: 0,
            max_match: 0,
        }
    }

    // Get the offset following the match that defined `var`, or 0 if var is an environment
    // variable or unknown.
    fn def_offset(&self, var: &str) -> usize {
        self.vars.get(var).map(|&VarDef { offset, .. }| offset).unwrap_or(0)
    }

    // Get the offset of the beginning of the next line after `pos`.
    fn bol(&self, pos: usize) -> usize {
        if let Some(offset) = self.text[pos..].find('\n') {
            pos + offset + 1
        } else {
            self.text.len()
        }
    }

    // Get the range in text to be matched by a `check:`.
    fn check(&self) -> MatchRange {
        (self.max_match, self.text.len())
    }

    // Get the range in text to be matched by a `sameln:`.
    fn sameln(&self) -> MatchRange {
        let b = self.max_match;
        let e = self.bol(b);
        (b, e)
    }

    // Get the range in text to be matched by a `nextln:`.
    fn nextln(&self) -> MatchRange {
        let b = self.bol(self.max_match);
        let e = self.bol(b);
        (b, e)
    }

    // Get the beginning of the range in text to be matched by a `unordered:` or `not:` directive.
    // The unordered directive must match after the directives that define the variables used.
    fn unordered_begin(&self, pat: &Pattern) -> usize {
        pat.parts()
            .iter()
            .filter_map(|part| part.ref_var())
            .map(|var| self.def_offset(var))
            .fold(self.last_ordered, max)
    }

    // Get the range in text to be matched by a `unordered:` directive.
    fn unordered(&self, pat: &Pattern) -> MatchRange {
        (self.unordered_begin(pat), self.text.len())
    }

    // Search for `pat` in `range`, return the range matched.
    // After a positive match, update variable definitions, if any.
    fn match_positive(&mut self, pat: &Pattern, range: MatchRange) -> Result<Option<MatchRange>> {
        let rx = try!(pat.resolve(self));
        let txt = &self.text[range.0..range.1];
        let defs = pat.defs();
        let matched_range = if defs.is_empty() {
            // Pattern defines no variables. Fastest search is `find`.
            rx.find(txt)
        } else {
            // We need the captures to define variables.
            rx.captures(txt).map(|caps| {
                let matched_range = caps.pos(0).expect("whole expression must match");
                for var in defs {
                    let txtval = caps.name(var).unwrap_or("");
                    self.recorder.defined_var(var, txtval);
                    let vardef = VarDef {
                        value: Value::Text(txtval.to_string()),
                        // This offset is the end of the whole matched pattern, not just the text
                        // defining the variable.
                        offset: range.0 + matched_range.1,
                    };
                    self.vars.insert(var.clone(), vardef);
                }
                matched_range
            })
        };
        Ok(if let Some((b, e)) = matched_range {
            let r = (range.0 + b, range.0 + e);
            self.recorder.matched_check(rx.as_str(), r);
            Some(r)
        } else {
            self.recorder.missed_check(rx.as_str(), range);
            None
        })
    }
}

impl<'a> VariableMap for State<'a> {
    fn lookup(&self, varname: &str) -> Option<Value> {
        // First look for a local define.
        if let Some(&VarDef { ref value, .. }) = self.vars.get(varname) {
            Some(value.clone())
        } else {
            // No local, maybe an environment variable?
            self.env_vars.lookup(varname)
        }
    }
}

impl Display for Directive {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        use self::Directive::*;
        match *self {
            Check(ref pat) => writeln!(f, "check: {}", pat),
            SameLn(ref pat) => writeln!(f, "sameln: {}", pat),
            NextLn(ref pat) => writeln!(f, "nextln: {}", pat),
            Unordered(ref pat) => writeln!(f, "unordered: {}", pat),
            Not(ref pat) => writeln!(f, "not: {}", pat),
            Regex(ref var, ref rx) => writeln!(f, "regex: {}={}", var, rx),
        }
    }
}

impl Display for Checker {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        for (idx, dir) in self.directives.iter().enumerate() {
            try!(write!(f, "#{} {}", idx, dir));
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::CheckerBuilder;
    use error::Error;

    fn e2s(e: Error) -> String {
        e.to_string()
    }

    #[test]
    fn directive() {
        let mut b = CheckerBuilder::new();

        assert_eq!(b.directive("not here: more text").map_err(e2s), Ok(false));
        assert_eq!(b.directive("not here: regex: X=more text").map_err(e2s),
                   Ok(true));
        assert_eq!(b.directive("regex: X = tommy").map_err(e2s),
                   Err("expected '=' after variable 'X' in regex: X = tommy".to_string()));
        assert_eq!(b.directive("[arm]not:    patt $x $(y) here").map_err(e2s),
                   Ok(true));
        assert_eq!(b.directive("[x86]sameln: $x $(y=[^]]*) there").map_err(e2s),
                   Ok(true));

        let c = b.finish();
        assert_eq!(c.to_string(),
                   "#0 regex: X=more text\n#1 not: patt $(x) $(y) here\n#2 sameln: $(x) \
                    $(y=[^]]*) there\n");
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use io;
use libc::{self, c_int};
use mem;
use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use sys::fd::FileDesc;
use sys::{cvt, cvt_r};

////////////////////////////////////////////////////////////////////////////////
// Anonymous pipes
////////////////////////////////////////////////////////////////////////////////

pub struct AnonPipe(FileDesc);

pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
    weak! { fn pipe2(*mut c_int, c_int) -> c_int }
    static INVALID: AtomicBool = ATOMIC_BOOL_INIT;

    let mut fds = [0; 2];

    // Unfortunately the only known way right now to create atomically set the
    // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in
    // 2.6.27, however, and because we support 2.6.18 we must detect this
    // support dynamically.
    if cfg!(any(target_os = "dragonfly",
                target_os = "freebsd",
                target_os = "linux",
                target_os = "netbsd",
                target_os = "openbsd")) &&
       !INVALID.load(Ordering::SeqCst)
    {

        if let Some(pipe) = pipe2.get() {
            // Note that despite calling a glibc function here we may still
            // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
            // emulate on older kernels, so if you happen to be running on
            // an older kernel you may see `pipe2` as a symbol but still not
            // see the syscall.
            match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
                Ok(_) => {
                    return Ok((AnonPipe(FileDesc::new(fds[0])),
                               AnonPipe(FileDesc::new(fds[1]))));
                }
                Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
                    INVALID.store(true, Ordering::SeqCst);
                }
                Err(e) => return Err(e),
            }
        }
    }
    cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;

    let fd0 = FileDesc::new(fds[0]);
    let fd1 = FileDesc::new(fds[1]);
    fd0.set_cloexec()?;
    fd1.set_cloexec()?;
    Ok((AnonPipe(fd0), AnonPipe(fd1)))
}

impl AnonPipe {
    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    pub fn fd(&self) -> &FileDesc { &self.0 }
    pub fn into_fd(self) -> FileDesc { self.0 }
}

pub fn read2(p1: AnonPipe,
             v1: &mut Vec<u8>,
             p2: AnonPipe,
             v2: &mut Vec<u8>) -> io::Result<()> {

    // Set both pipes into nonblocking mode as we're gonna be reading from both
    // in the `select` loop below, and we wouldn't want one to block the other!
    let p1 = p1.into_fd();
    let p2 = p2.into_fd();
    p1.set_nonblocking(true)?;
    p2.set_nonblocking(true)?;

    let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
    fds[0].fd = p1.raw();
    fds[0].events = libc::POLLIN;
    fds[1].fd = p2.raw();
    fds[1].events = libc::POLLIN;
    loop {
        // wait for either pipe to become readable using `poll`
        cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;

        // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
        // EAGAIN. If we hit EOF, then this will happen because the underlying
        // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
        // this case we flip the other fd back into blocking mode and read
        // whatever's leftover on that file descriptor.
        let read = |fd: &FileDesc, dst: &mut Vec<u8>| {
            match fd.read_to_end(dst) {
                Ok(_) => Ok(true),
                Err(e) => {
                    if e.raw_os_error() == Some(libc::EWOULDBLOCK) ||
                       e.raw_os_error() == Some(libc::EAGAIN) {
                        Ok(false)
                    } else {
                        Err(e)
                    }
                }
            }
        };
        if fds[0].revents != 0 && read(&p1, v1)? {
            p2.set_nonblocking(false)?;
            return p2.read_to_end(v2).map(|_| ());
        }
        if fds[1].revents != 0 && read(&p2, v2)? {
            p1.set_nonblocking(false)?;
            return p1.read_to_end(v1).map(|_| ());
        }
    }
}
<commit_msg>Rollup merge of #50726 - udoprog:read2-inner-fn, r=alexcrichton<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use io;
use libc::{self, c_int};
use mem;
use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
use sys::fd::FileDesc;
use sys::{cvt, cvt_r};

////////////////////////////////////////////////////////////////////////////////
// Anonymous pipes
////////////////////////////////////////////////////////////////////////////////

pub struct AnonPipe(FileDesc);

pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
    weak! { fn pipe2(*mut c_int, c_int) -> c_int }
    static INVALID: AtomicBool = ATOMIC_BOOL_INIT;

    let mut fds = [0; 2];

    // Unfortunately the only known way right now to create atomically set the
    // CLOEXEC flag is to use the `pipe2` syscall on Linux. This was added in
    // 2.6.27, however, and because we support 2.6.18 we must detect this
    // support dynamically.
    if cfg!(any(target_os = "dragonfly",
                target_os = "freebsd",
                target_os = "linux",
                target_os = "netbsd",
                target_os = "openbsd")) &&
       !INVALID.load(Ordering::SeqCst)
    {

        if let Some(pipe) = pipe2.get() {
            // Note that despite calling a glibc function here we may still
            // get ENOSYS. Glibc has `pipe2` since 2.9 and doesn't try to
            // emulate on older kernels, so if you happen to be running on
            // an older kernel you may see `pipe2` as a symbol but still not
            // see the syscall.
            match cvt(unsafe { pipe(fds.as_mut_ptr(), libc::O_CLOEXEC) }) {
                Ok(_) => {
                    return Ok((AnonPipe(FileDesc::new(fds[0])),
                               AnonPipe(FileDesc::new(fds[1]))));
                }
                Err(ref e) if e.raw_os_error() == Some(libc::ENOSYS) => {
                    INVALID.store(true, Ordering::SeqCst);
                }
                Err(e) => return Err(e),
            }
        }
    }
    cvt(unsafe { libc::pipe(fds.as_mut_ptr()) })?;

    let fd0 = FileDesc::new(fds[0]);
    let fd1 = FileDesc::new(fds[1]);
    fd0.set_cloexec()?;
    fd1.set_cloexec()?;
    Ok((AnonPipe(fd0), AnonPipe(fd1)))
}

impl AnonPipe {
    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    pub fn fd(&self) -> &FileDesc { &self.0 }
    pub fn into_fd(self) -> FileDesc { self.0 }
}

pub fn read2(p1: AnonPipe,
             v1: &mut Vec<u8>,
             p2: AnonPipe,
             v2: &mut Vec<u8>) -> io::Result<()> {

    // Set both pipes into nonblocking mode as we're gonna be reading from both
    // in the `select` loop below, and we wouldn't want one to block the other!
    let p1 = p1.into_fd();
    let p2 = p2.into_fd();
    p1.set_nonblocking(true)?;
    p2.set_nonblocking(true)?;

    let mut fds: [libc::pollfd; 2] = unsafe { mem::zeroed() };
    fds[0].fd = p1.raw();
    fds[0].events = libc::POLLIN;
    fds[1].fd = p2.raw();
    fds[1].events = libc::POLLIN;
    loop {
        // wait for either pipe to become readable using `poll`
        cvt_r(|| unsafe { libc::poll(fds.as_mut_ptr(), 2, -1) })?;

        if fds[0].revents != 0 && read(&p1, v1)? {
            p2.set_nonblocking(false)?;
            return p2.read_to_end(v2).map(|_| ());
        }
        if fds[1].revents != 0 && read(&p2, v2)? {
            p1.set_nonblocking(false)?;
            return p1.read_to_end(v1).map(|_| ());
        }
    }

    // Read as much as we can from each pipe, ignoring EWOULDBLOCK or
    // EAGAIN. If we hit EOF, then this will happen because the underlying
    // reader will return Ok(0), in which case we'll see `Ok` ourselves. In
    // this case we flip the other fd back into blocking mode and read
    // whatever's leftover on that file descriptor.
    fn read(fd: &FileDesc, dst: &mut Vec<u8>) -> Result<bool, io::Error> {
        match fd.read_to_end(dst) {
            Ok(_) => Ok(true),
            Err(e) => {
                if e.raw_os_error() == Some(libc::EWOULDBLOCK) ||
                   e.raw_os_error() == Some(libc::EAGAIN) {
                    Ok(false)
                } else {
                    Err(e)
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(stage0)]
use prelude::v1::*;

use ops::{Add, Sub, Mul, Div};
use sys::time::SteadyTime;

const NANOS_PER_SEC: u32 = 1_000_000_000;
const NANOS_PER_MILLI: u32 = 1_000_000;
const MILLIS_PER_SEC: u64 = 1_000;

/// A duration type to represent a span of time, typically used for system
/// timeouts.
///
/// Each duration is composed of a number of seconds and nanosecond precision.
/// APIs binding a system timeout will typically round up the nanosecond
/// precision if the underlying system does not support that level of precision.
///
/// Durations implement many common traits, including `Add`, `Sub`, and other
/// ops traits. Currently a duration may only be inspected for its number of
/// seconds and its nanosecond precision.
///
/// # Examples
///
/// ```
/// #![feature(duration)]
/// use std::time::Duration;
///
/// let five_seconds = Duration::new(5, 0);
/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
///
/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
///
/// let ten_millis = Duration::from_millis(10);
/// ```
#[stable(feature = "duration", since = "1.3.0")]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct Duration {
    secs: u64,
    nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
}

impl Duration {
    /// Crates a new `Duration` from the specified number of seconds and
    /// additional nanosecond precision.
    ///
    /// If the nanoseconds is greater than 1 billion (the number of nanoseconds
    /// in a second), then it will carry over into the seconds provided.
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn new(secs: u64, nanos: u32) -> Duration {
        let secs = secs + (nanos / NANOS_PER_SEC) as u64;
        let nanos = nanos % NANOS_PER_SEC;
        Duration { secs: secs, nanos: nanos }
    }

    /// Runs a closure, returning the duration of time it took to run the
    /// closure.
    #[unstable(feature = "duration_span",
               reason = "unsure if this is the right API or whether it should \
                         wait for a more general \"moment in time\" \
                         abstraction")]
    pub fn span<F>(f: F) -> Duration where F: FnOnce() {
        let start = SteadyTime::now();
        f();
        &SteadyTime::now() - &start
    }

    /// Creates a new `Duration` from the specified number of seconds.
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn from_secs(secs: u64) -> Duration {
        Duration { secs: secs, nanos: 0 }
    }

    /// Creates a new `Duration` from the specified number of milliseconds.
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn from_millis(millis: u64) -> Duration {
        let secs = millis / MILLIS_PER_SEC;
        let nanos = ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI;
        Duration { secs: secs, nanos: nanos }
    }

    /// Returns the number of whole seconds represented by this duration.
    ///
    /// The extra precision represented by this duration is ignored (e.g. extra
    /// nanoseconds are not represented in the returned value).
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn as_secs(&self) -> u64 { self.secs }

    #[deprecated(reason = "renamed to `as_secs`", since = "1.3.0")]
    #[unstable(feature = "duration_deprecated")]
    /// Returns the number of whole seconds represented by this duration.
    ///
    /// The extra precision represented by this duration is ignored (e.g. extra
    /// nanoseconds are not represented in the returned value).
    pub fn secs(&self) -> u64 { self.as_secs() }

    /// Returns the nanosecond precision represented by this duration.
    ///
    /// This method does **not** return the length of the duration when
    /// represented by nanoseconds. The returned number always represents a
    /// fractional portion of a second (e.g. it is less than one billion).
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn subsec_nanos(&self) -> u32 { self.nanos }

    #[deprecated(reason = "renamed to `subsec_nanos`", since = "1.3.0")]
    #[unstable(feature = "duration_deprecated")]
    /// Returns the nanosecond precision represented by this duration.
    ///
    /// This method does **not** return the length of the duration when
    /// represented by nanoseconds. The returned number always represents a
    /// fractional portion of a second (e.g. it is less than one billion).
    pub fn extra_nanos(&self) -> u32 { self.subsec_nanos() }
}

impl Add for Duration {
    type Output = Duration;

    fn add(self, rhs: Duration) -> Duration {
        let mut secs = self.secs.checked_add(rhs.secs)
                           .expect("overflow when adding durations");
        let mut nanos = self.nanos + rhs.nanos;
        if nanos >= NANOS_PER_SEC {
            nanos -= NANOS_PER_SEC;
            secs = secs.checked_add(1).expect("overflow when adding durations");
        }
        debug_assert!(nanos < NANOS_PER_SEC);
        Duration { secs: secs, nanos: nanos }
    }
}

impl Sub for Duration {
    type Output = Duration;

    fn sub(self, rhs: Duration) -> Duration {
        let mut secs = self.secs.checked_sub(rhs.secs)
                           .expect("overflow when subtracting durations");
        let nanos = if self.nanos >= rhs.nanos {
            self.nanos - rhs.nanos
        } else {
            secs = secs.checked_sub(1)
                       .expect("overflow when subtracting durations");
            self.nanos + NANOS_PER_SEC - rhs.nanos
        };
        debug_assert!(nanos < NANOS_PER_SEC);
        Duration { secs: secs, nanos: nanos }
    }
}

impl Mul<u32> for Duration {
    type Output = Duration;

    fn mul(self, rhs: u32) -> Duration {
        // Multiply nanoseconds as u64, because it cannot overflow that way.
        let total_nanos = self.nanos as u64 * rhs as u64;
        let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
        let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
        let secs = self.secs.checked_mul(rhs as u64)
                       .and_then(|s| s.checked_add(extra_secs))
                       .expect("overflow when multiplying duration");
        debug_assert!(nanos < NANOS_PER_SEC);
        Duration { secs: secs, nanos: nanos }
    }
}

impl Div<u32> for Duration {
    type Output = Duration;

    fn div(self, rhs: u32) -> Duration {
        let secs = self.secs / (rhs as u64);
        let carry = self.secs - secs * (rhs as u64);
        let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
        let nanos = self.nanos / rhs + (extra_nanos as u32);
        debug_assert!(nanos < NANOS_PER_SEC);
        Duration { secs: secs, nanos: nanos }
    }
}

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

    #[test]
    fn creation() {
        assert!(Duration::from_secs(1) != Duration::from_secs(0));
        assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
                   Duration::from_secs(3));
        assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
                   Duration::new(4, 10 * 1_000_000));
        assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
    }

    #[test]
    fn secs() {
        assert_eq!(Duration::new(0, 0).as_secs(), 0);
        assert_eq!(Duration::from_secs(1).as_secs(), 1);
        assert_eq!(Duration::from_millis(999).as_secs(), 0);
        assert_eq!(Duration::from_millis(1001).as_secs(), 1);
    }

    #[test]
    fn nanos() {
        assert_eq!(Duration::new(0, 0).subsec_nanos(), 0);
        assert_eq!(Duration::new(0, 5).subsec_nanos(), 5);
        assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1);
        assert_eq!(Duration::from_secs(1).subsec_nanos(), 0);
        assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000);
        assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000);
    }

    #[test]
    fn add() {
        assert_eq!(Duration::new(0, 0) + Duration::new(0, 1),
                   Duration::new(0, 1));
        assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001),
                   Duration::new(1, 1));
    }

    #[test]
    fn sub() {
        assert_eq!(Duration::new(0, 1) - Duration::new(0, 0),
                   Duration::new(0, 1));
        assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000),
                   Duration::new(0, 1));
        assert_eq!(Duration::new(1, 0) - Duration::new(0, 1),
                   Duration::new(0, 999_999_999));
    }

    #[test] #[should_panic]
    fn sub_bad1() {
        Duration::new(0, 0) - Duration::new(0, 1);
    }

    #[test] #[should_panic]
    fn sub_bad2() {
        Duration::new(0, 0) - Duration::new(1, 0);
    }

    #[test]
    fn mul() {
        assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2));
        assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3));
        assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
        assert_eq!(Duration::new(0, 500_000_001) * 4000,
                   Duration::new(2000, 4000));
    }

    #[test]
    fn div() {
        assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
        assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
        assert_eq!(Duration::new(99, 999_999_000) / 100,
                   Duration::new(0, 999_999_990));
    }
}
<commit_msg>Fix doc test<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(stage0)]
use prelude::v1::*;

use ops::{Add, Sub, Mul, Div};
use sys::time::SteadyTime;

const NANOS_PER_SEC: u32 = 1_000_000_000;
const NANOS_PER_MILLI: u32 = 1_000_000;
const MILLIS_PER_SEC: u64 = 1_000;

/// A duration type to represent a span of time, typically used for system
/// timeouts.
///
/// Each duration is composed of a number of seconds and nanosecond precision.
/// APIs binding a system timeout will typically round up the nanosecond
/// precision if the underlying system does not support that level of precision.
///
/// Durations implement many common traits, including `Add`, `Sub`, and other
/// ops traits. Currently a duration may only be inspected for its number of
/// seconds and its nanosecond precision.
///
/// # Examples
///
/// ```
/// use std::time::Duration;
///
/// let five_seconds = Duration::new(5, 0);
/// let five_seconds_and_five_nanos = five_seconds + Duration::new(0, 5);
///
/// assert_eq!(five_seconds_and_five_nanos.as_secs(), 5);
/// assert_eq!(five_seconds_and_five_nanos.subsec_nanos(), 5);
///
/// let ten_millis = Duration::from_millis(10);
/// ```
#[stable(feature = "duration", since = "1.3.0")]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct Duration {
    secs: u64,
    nanos: u32, // Always 0 <= nanos < NANOS_PER_SEC
}

impl Duration {
    /// Crates a new `Duration` from the specified number of seconds and
    /// additional nanosecond precision.
    ///
    /// If the nanoseconds is greater than 1 billion (the number of nanoseconds
    /// in a second), then it will carry over into the seconds provided.
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn new(secs: u64, nanos: u32) -> Duration {
        let secs = secs + (nanos / NANOS_PER_SEC) as u64;
        let nanos = nanos % NANOS_PER_SEC;
        Duration { secs: secs, nanos: nanos }
    }

    /// Runs a closure, returning the duration of time it took to run the
    /// closure.
    #[unstable(feature = "duration_span",
               reason = "unsure if this is the right API or whether it should \
                         wait for a more general \"moment in time\" \
                         abstraction")]
    pub fn span<F>(f: F) -> Duration where F: FnOnce() {
        let start = SteadyTime::now();
        f();
        &SteadyTime::now() - &start
    }

    /// Creates a new `Duration` from the specified number of seconds.
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn from_secs(secs: u64) -> Duration {
        Duration { secs: secs, nanos: 0 }
    }

    /// Creates a new `Duration` from the specified number of milliseconds.
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn from_millis(millis: u64) -> Duration {
        let secs = millis / MILLIS_PER_SEC;
        let nanos = ((millis % MILLIS_PER_SEC) as u32) * NANOS_PER_MILLI;
        Duration { secs: secs, nanos: nanos }
    }

    /// Returns the number of whole seconds represented by this duration.
    ///
    /// The extra precision represented by this duration is ignored (e.g. extra
    /// nanoseconds are not represented in the returned value).
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn as_secs(&self) -> u64 { self.secs }

    #[deprecated(reason = "renamed to `as_secs`", since = "1.3.0")]
    #[unstable(feature = "duration_deprecated")]
    /// Returns the number of whole seconds represented by this duration.
    ///
    /// The extra precision represented by this duration is ignored (e.g. extra
    /// nanoseconds are not represented in the returned value).
    pub fn secs(&self) -> u64 { self.as_secs() }

    /// Returns the nanosecond precision represented by this duration.
    ///
    /// This method does **not** return the length of the duration when
    /// represented by nanoseconds. The returned number always represents a
    /// fractional portion of a second (e.g. it is less than one billion).
    #[stable(feature = "duration", since = "1.3.0")]
    pub fn subsec_nanos(&self) -> u32 { self.nanos }

    #[deprecated(reason = "renamed to `subsec_nanos`", since = "1.3.0")]
    #[unstable(feature = "duration_deprecated")]
    /// Returns the nanosecond precision represented by this duration.
    ///
    /// This method does **not** return the length of the duration when
    /// represented by nanoseconds. The returned number always represents a
    /// fractional portion of a second (e.g. it is less than one billion).
    pub fn extra_nanos(&self) -> u32 { self.subsec_nanos() }
}

impl Add for Duration {
    type Output = Duration;

    fn add(self, rhs: Duration) -> Duration {
        let mut secs = self.secs.checked_add(rhs.secs)
                           .expect("overflow when adding durations");
        let mut nanos = self.nanos + rhs.nanos;
        if nanos >= NANOS_PER_SEC {
            nanos -= NANOS_PER_SEC;
            secs = secs.checked_add(1).expect("overflow when adding durations");
        }
        debug_assert!(nanos < NANOS_PER_SEC);
        Duration { secs: secs, nanos: nanos }
    }
}

impl Sub for Duration {
    type Output = Duration;

    fn sub(self, rhs: Duration) -> Duration {
        let mut secs = self.secs.checked_sub(rhs.secs)
                           .expect("overflow when subtracting durations");
        let nanos = if self.nanos >= rhs.nanos {
            self.nanos - rhs.nanos
        } else {
            secs = secs.checked_sub(1)
                       .expect("overflow when subtracting durations");
            self.nanos + NANOS_PER_SEC - rhs.nanos
        };
        debug_assert!(nanos < NANOS_PER_SEC);
        Duration { secs: secs, nanos: nanos }
    }
}

impl Mul<u32> for Duration {
    type Output = Duration;

    fn mul(self, rhs: u32) -> Duration {
        // Multiply nanoseconds as u64, because it cannot overflow that way.
        let total_nanos = self.nanos as u64 * rhs as u64;
        let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
        let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
        let secs = self.secs.checked_mul(rhs as u64)
                       .and_then(|s| s.checked_add(extra_secs))
                       .expect("overflow when multiplying duration");
        debug_assert!(nanos < NANOS_PER_SEC);
        Duration { secs: secs, nanos: nanos }
    }
}

impl Div<u32> for Duration {
    type Output = Duration;

    fn div(self, rhs: u32) -> Duration {
        let secs = self.secs / (rhs as u64);
        let carry = self.secs - secs * (rhs as u64);
        let extra_nanos = carry * (NANOS_PER_SEC as u64) / (rhs as u64);
        let nanos = self.nanos / rhs + (extra_nanos as u32);
        debug_assert!(nanos < NANOS_PER_SEC);
        Duration { secs: secs, nanos: nanos }
    }
}

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

    #[test]
    fn creation() {
        assert!(Duration::from_secs(1) != Duration::from_secs(0));
        assert_eq!(Duration::from_secs(1) + Duration::from_secs(2),
                   Duration::from_secs(3));
        assert_eq!(Duration::from_millis(10) + Duration::from_secs(4),
                   Duration::new(4, 10 * 1_000_000));
        assert_eq!(Duration::from_millis(4000), Duration::new(4, 0));
    }

    #[test]
    fn secs() {
        assert_eq!(Duration::new(0, 0).as_secs(), 0);
        assert_eq!(Duration::from_secs(1).as_secs(), 1);
        assert_eq!(Duration::from_millis(999).as_secs(), 0);
        assert_eq!(Duration::from_millis(1001).as_secs(), 1);
    }

    #[test]
    fn nanos() {
        assert_eq!(Duration::new(0, 0).subsec_nanos(), 0);
        assert_eq!(Duration::new(0, 5).subsec_nanos(), 5);
        assert_eq!(Duration::new(0, 1_000_000_001).subsec_nanos(), 1);
        assert_eq!(Duration::from_secs(1).subsec_nanos(), 0);
        assert_eq!(Duration::from_millis(999).subsec_nanos(), 999 * 1_000_000);
        assert_eq!(Duration::from_millis(1001).subsec_nanos(), 1 * 1_000_000);
    }

    #[test]
    fn add() {
        assert_eq!(Duration::new(0, 0) + Duration::new(0, 1),
                   Duration::new(0, 1));
        assert_eq!(Duration::new(0, 500_000_000) + Duration::new(0, 500_000_001),
                   Duration::new(1, 1));
    }

    #[test]
    fn sub() {
        assert_eq!(Duration::new(0, 1) - Duration::new(0, 0),
                   Duration::new(0, 1));
        assert_eq!(Duration::new(0, 500_000_001) - Duration::new(0, 500_000_000),
                   Duration::new(0, 1));
        assert_eq!(Duration::new(1, 0) - Duration::new(0, 1),
                   Duration::new(0, 999_999_999));
    }

    #[test] #[should_panic]
    fn sub_bad1() {
        Duration::new(0, 0) - Duration::new(0, 1);
    }

    #[test] #[should_panic]
    fn sub_bad2() {
        Duration::new(0, 0) - Duration::new(1, 0);
    }

    #[test]
    fn mul() {
        assert_eq!(Duration::new(0, 1) * 2, Duration::new(0, 2));
        assert_eq!(Duration::new(1, 1) * 3, Duration::new(3, 3));
        assert_eq!(Duration::new(0, 500_000_001) * 4, Duration::new(2, 4));
        assert_eq!(Duration::new(0, 500_000_001) * 4000,
                   Duration::new(2000, 4000));
    }

    #[test]
    fn div() {
        assert_eq!(Duration::new(0, 1) / 2, Duration::new(0, 0));
        assert_eq!(Duration::new(1, 1) / 3, Duration::new(0, 333_333_333));
        assert_eq!(Duration::new(99, 999_999_000) / 100,
                   Duration::new(0, 999_999_990));
    }
}
<|endoftext|>


<commit_before>use crate::fmt;
use crate::ops::Try;

use super::super::{DoubleEndedIterator, FusedIterator, Iterator};
use super::Map;

/// An iterator that maps each element to an iterator, and yields the elements
/// of the produced iterators.
///
/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flat_map`]: trait.Iterator.html#method.flat_map
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct FlatMap<I, U: IntoIterator, F> {
    inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>,
}
impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
    pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
        FlatMap { inner: FlattenCompat::new(iter.map(f)) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Clone, U, F: Clone> Clone for FlatMap<I, U, F>
where
    U: Clone + IntoIterator<IntoIter: Clone>,
{
    fn clone(&self) -> Self {
        FlatMap { inner: self.inner.clone() }
    }
}

#[stable(feature = "core_impl_debug", since = "1.9.0")]
impl<I: fmt::Debug, U, F> fmt::Debug for FlatMap<I, U, F>
where
    U: IntoIterator<IntoIter: fmt::Debug>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FlatMap").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        self.inner.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.fold(init, fold)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
    U: IntoIterator<IntoIter: DoubleEndedIterator>,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        self.inner.next_back()
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.rfold(init, fold)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
where
    I: FusedIterator,
    U: IntoIterator,
    F: FnMut(I::Item) -> U,
{
}

/// An iterator that flattens one level of nesting in an iterator of things
/// that can be turned into iterators.
///
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flatten`]: trait.Iterator.html#method.flatten
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub struct Flatten<I: Iterator<Item: IntoIterator>> {
    inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
}

impl<I: Iterator<Item: IntoIterator>> Flatten<I> {
    pub(in super::super) fn new(iter: I) -> Flatten<I> {
        Flatten { inner: FlattenCompat::new(iter) }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> fmt::Debug for Flatten<I>
where
    I: fmt::Debug + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: fmt::Debug + Iterator,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Flatten").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Clone for Flatten<I>
where
    I: Clone + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Clone + Iterator,
{
    fn clone(&self) -> Self {
        Flatten { inner: self.inner.clone() }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Iterator for Flatten<I>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        self.inner.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.fold(init, fold)
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> DoubleEndedIterator for Flatten<I>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        self.inner.next_back()
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.rfold(init, fold)
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> FusedIterator for Flatten<I>
where
    I: FusedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
}

/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
/// this type.
#[derive(Clone, Debug)]
struct FlattenCompat<I, U> {
    iter: I,
    frontiter: Option<U>,
    backiter: Option<U>,
}
impl<I, U> FlattenCompat<I, U> {
    /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
    fn new(iter: I) -> FlattenCompat<I, U> {
        FlattenCompat { iter, frontiter: None, backiter: None }
    }
}

impl<I, U> Iterator for FlattenCompat<I, U>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.frontiter {
                if let elt @ Some(_) = inner.next() {
                    return elt;
                }
            }
            match self.iter.next() {
                None => return self.backiter.as_mut()?.next(),
                Some(inner) => self.frontiter = Some(inner.into_iter()),
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let lo = flo.saturating_add(blo);
        match (self.iter.size_hint(), fhi, bhi) {
            ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
            _ => (lo, None),
        }
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            frontiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_fold(acc, &mut *fold);
                *frontiter = Some(mid);
                r
            }
        }

        if let Some(ref mut front) = self.frontiter {
            init = front.try_fold(init, &mut fold)?;
        }
        self.frontiter = None;

        init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
        self.frontiter = None;

        if let Some(ref mut back) = self.backiter {
            init = back.try_fold(init, &mut fold)?;
        }
        self.backiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: Iterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.fold(acc, &mut *fold)
        }

        self.frontiter
            .into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .fold(init, flatten(fold))
    }
}

impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.backiter {
                if let elt @ Some(_) = inner.next_back() {
                    return elt;
                }
            }
            match self.iter.next_back() {
                None => return self.frontiter.as_mut()?.next_back(),
                next => self.backiter = next.map(IntoIterator::into_iter),
            }
        }
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            backiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a
        where
            T::IntoIter: DoubleEndedIterator,
        {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_rfold(acc, &mut *fold);
                *backiter = Some(mid);
                r
            }
        }

        if let Some(ref mut back) = self.backiter {
            init = back.try_rfold(init, &mut fold)?;
        }
        self.backiter = None;

        init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
        self.backiter = None;

        if let Some(ref mut front) = self.frontiter {
            init = front.try_rfold(init, &mut fold)?;
        }
        self.frontiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: DoubleEndedIterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.rfold(acc, &mut *fold)
        }

        self.frontiter
            .into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .rfold(init, flatten(fold))
    }
}
<commit_msg>Fuse FlattenCompat's inner iterator<commit_after>use crate::fmt;
use crate::ops::Try;

use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator};
use super::Map;

/// An iterator that maps each element to an iterator, and yields the elements
/// of the produced iterators.
///
/// This `struct` is created by the [`flat_map`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flat_map`]: trait.Iterator.html#method.flat_map
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct FlatMap<I, U: IntoIterator, F> {
    inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>,
}
impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
    pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
        FlatMap { inner: FlattenCompat::new(iter.map(f)) }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Clone, U, F: Clone> Clone for FlatMap<I, U, F>
where
    U: Clone + IntoIterator<IntoIter: Clone>,
{
    fn clone(&self) -> Self {
        FlatMap { inner: self.inner.clone() }
    }
}

#[stable(feature = "core_impl_debug", since = "1.9.0")]
impl<I: fmt::Debug, U, F> fmt::Debug for FlatMap<I, U, F>
where
    U: IntoIterator<IntoIter: fmt::Debug>,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("FlatMap").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        self.inner.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.fold(init, fold)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
where
    F: FnMut(I::Item) -> U,
    U: IntoIterator<IntoIter: DoubleEndedIterator>,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        self.inner.next_back()
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.rfold(init, fold)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
where
    I: FusedIterator,
    U: IntoIterator,
    F: FnMut(I::Item) -> U,
{
}

/// An iterator that flattens one level of nesting in an iterator of things
/// that can be turned into iterators.
///
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
/// documentation for more.
///
/// [`flatten`]: trait.Iterator.html#method.flatten
/// [`Iterator`]: trait.Iterator.html
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "iterator_flatten", since = "1.29.0")]
pub struct Flatten<I: Iterator<Item: IntoIterator>> {
    inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
}

impl<I: Iterator<Item: IntoIterator>> Flatten<I> {
    pub(in super::super) fn new(iter: I) -> Flatten<I> {
        Flatten { inner: FlattenCompat::new(iter) }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> fmt::Debug for Flatten<I>
where
    I: fmt::Debug + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: fmt::Debug + Iterator,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Flatten").field("inner", &self.inner).finish()
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Clone for Flatten<I>
where
    I: Clone + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Clone + Iterator,
{
    fn clone(&self) -> Self {
        Flatten { inner: self.inner.clone() }
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> Iterator for Flatten<I>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        self.inner.next()
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.inner.size_hint()
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_fold(init, fold)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.fold(init, fold)
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> DoubleEndedIterator for Flatten<I>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        self.inner.next_back()
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        self.inner.try_rfold(init, fold)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        self.inner.rfold(init, fold)
    }
}

#[stable(feature = "iterator_flatten", since = "1.29.0")]
impl<I, U> FusedIterator for Flatten<I>
where
    I: FusedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
}

/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
/// this type.
#[derive(Clone, Debug)]
struct FlattenCompat<I, U> {
    iter: Fuse<I>,
    frontiter: Option<U>,
    backiter: Option<U>,
}
impl<I, U> FlattenCompat<I, U>
where
    I: Iterator,
{
    /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
    fn new(iter: I) -> FlattenCompat<I, U> {
        FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None }
    }
}

impl<I, U> Iterator for FlattenCompat<I, U>
where
    I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: Iterator,
{
    type Item = U::Item;

    #[inline]
    fn next(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.frontiter {
                if let elt @ Some(_) = inner.next() {
                    return elt;
                }
            }
            match self.iter.next() {
                None => return self.backiter.as_mut()?.next(),
                Some(inner) => self.frontiter = Some(inner.into_iter()),
            }
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
        let lo = flo.saturating_add(blo);
        match (self.iter.size_hint(), fhi, bhi) {
            ((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
            _ => (lo, None),
        }
    }

    #[inline]
    fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            frontiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_fold(acc, &mut *fold);
                *frontiter = Some(mid);
                r
            }
        }

        if let Some(ref mut front) = self.frontiter {
            init = front.try_fold(init, &mut fold)?;
        }
        self.frontiter = None;

        init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
        self.frontiter = None;

        if let Some(ref mut back) = self.backiter {
            init = back.try_fold(init, &mut fold)?;
        }
        self.backiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: Iterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.fold(acc, &mut *fold)
        }

        self.frontiter
            .into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .fold(init, flatten(fold))
    }
}

impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
where
    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
    U: DoubleEndedIterator,
{
    #[inline]
    fn next_back(&mut self) -> Option<U::Item> {
        loop {
            if let Some(ref mut inner) = self.backiter {
                if let elt @ Some(_) = inner.next_back() {
                    return elt;
                }
            }
            match self.iter.next_back() {
                None => return self.frontiter.as_mut()?.next_back(),
                next => self.backiter = next.map(IntoIterator::into_iter),
            }
        }
    }

    #[inline]
    fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
    where
        Self: Sized,
        Fold: FnMut(Acc, Self::Item) -> R,
        R: Try<Ok = Acc>,
    {
        #[inline]
        fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
            backiter: &'a mut Option<T::IntoIter>,
            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
        ) -> impl FnMut(Acc, T) -> R + 'a
        where
            T::IntoIter: DoubleEndedIterator,
        {
            move |acc, x| {
                let mut mid = x.into_iter();
                let r = mid.try_rfold(acc, &mut *fold);
                *backiter = Some(mid);
                r
            }
        }

        if let Some(ref mut back) = self.backiter {
            init = back.try_rfold(init, &mut fold)?;
        }
        self.backiter = None;

        init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
        self.backiter = None;

        if let Some(ref mut front) = self.frontiter {
            init = front.try_rfold(init, &mut fold)?;
        }
        self.frontiter = None;

        Try::from_ok(init)
    }

    #[inline]
    fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
    where
        Fold: FnMut(Acc, Self::Item) -> Acc,
    {
        #[inline]
        fn flatten<U: DoubleEndedIterator, Acc>(
            fold: &mut impl FnMut(Acc, U::Item) -> Acc,
        ) -> impl FnMut(Acc, U) -> Acc + '_ {
            move |acc, iter| iter.rfold(acc, &mut *fold)
        }

        self.frontiter
            .into_iter()
            .chain(self.iter.map(IntoIterator::into_iter))
            .chain(self.backiter)
            .rfold(init, flatten(fold))
    }
}
<|endoftext|>


<commit_before>//! Densely numbered entity references as set keys.

use entity::{EntityRef, Keys};
use std::marker::PhantomData;

/// A set of `K` for densely indexed entity references.
///
/// The `EntitySet` data structure uses the dense index space to implement a set with a bitvector.
/// Like `EntityMap`, an `EntitySet` is used to associate secondary information with entities.
#[derive(Debug, Clone)]
pub struct EntitySet<K>
where
    K: EntityRef,
{
    elems: Vec<u8>,
    len: usize,
    unused: PhantomData<K>,
}

/// Shared `EntitySet` implementation for all value types.
impl<K> EntitySet<K>
where
    K: EntityRef,
{
    /// Create a new empty set.
    pub fn new() -> Self {
        EntitySet {
            elems: Vec::new(),
            len: 0,
            unused: PhantomData,
        }
    }

    /// Get the element at `k` if it exists.
    pub fn contains(&self, k: K) -> bool {
        let index = k.index();
        debug_assert!(index < self.len);
        (self.elems[index / 8] & (1 << (index % 8))) != 0
    }

    /// Is this set completely empty?
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    /// Remove all entries from this set.
    pub fn clear(&mut self) {
        self.len = 0;
        self.elems.clear()
    }

    /// Iterate over all the keys in this set.
    pub fn keys(&self) -> Keys<K> {
        Keys::new(self.len)
    }

    /// Resize the set to have `n` entries by adding default entries as needed.
    pub fn resize(&mut self, n: usize) {
        if n < self.len {
            self.elems.truncate((n + 7) / 8)
        } else {
            // TODO: Is there a better way to grow/resize/etc.?
            let additional = (n - self.len + 7) / 8;
            self.elems.reserve(additional);
            for _ in 0..additional {
                self.elems.push(0)
            }
        }
        self.len = n
    }

    /// Insert the element at `k`.
    pub fn insert(&mut self, k: K) -> bool {
        let index = k.index();
        if index >= self.len {
            self.resize(index + 1)
        }
        let result = !self.contains(k);
        self.elems[index / 8] |= 1 << (index % 8);
        result
    }
}

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

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let r2 = E(2);
        let mut m = EntitySet::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);
        assert!(m.is_empty());

        m.insert(r2);
        m.insert(r1);

        assert!(!m.contains(r0));
        assert!(m.contains(r1));
        assert!(m.contains(r2));
        assert!(!m.is_empty());

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [r0, r1, r2]);

        m.resize(20);
        assert!(!m.contains(E(3)));
        assert!(!m.contains(E(4)));
        assert!(!m.contains(E(8)));
        assert!(!m.contains(E(15)));
        assert!(!m.contains(E(19)));

        m.insert(E(8));
        m.insert(E(15));
        assert!(!m.contains(E(3)));
        assert!(!m.contains(E(4)));
        assert!(m.contains(E(8)));
        assert!(!m.contains(E(9)));
        assert!(!m.contains(E(14)));
        assert!(m.contains(E(15)));
        assert!(!m.contains(E(16)));
        assert!(!m.contains(E(19)));

        m.clear();
        assert!(m.is_empty());
    }
}
<commit_msg>Use Vec::resize.<commit_after>//! Densely numbered entity references as set keys.

use entity::{EntityRef, Keys};
use std::marker::PhantomData;

/// A set of `K` for densely indexed entity references.
///
/// The `EntitySet` data structure uses the dense index space to implement a set with a bitvector.
/// Like `EntityMap`, an `EntitySet` is used to associate secondary information with entities.
#[derive(Debug, Clone)]
pub struct EntitySet<K>
where
    K: EntityRef,
{
    elems: Vec<u8>,
    len: usize,
    unused: PhantomData<K>,
}

/// Shared `EntitySet` implementation for all value types.
impl<K> EntitySet<K>
where
    K: EntityRef,
{
    /// Create a new empty set.
    pub fn new() -> Self {
        EntitySet {
            elems: Vec::new(),
            len: 0,
            unused: PhantomData,
        }
    }

    /// Get the element at `k` if it exists.
    pub fn contains(&self, k: K) -> bool {
        let index = k.index();
        debug_assert!(index < self.len);
        (self.elems[index / 8] & (1 << (index % 8))) != 0
    }

    /// Is this set completely empty?
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    /// Remove all entries from this set.
    pub fn clear(&mut self) {
        self.len = 0;
        self.elems.clear()
    }

    /// Iterate over all the keys in this set.
    pub fn keys(&self) -> Keys<K> {
        Keys::new(self.len)
    }

    /// Resize the set to have `n` entries by adding default entries as needed.
    pub fn resize(&mut self, n: usize) {
        self.elems.resize((n + 7) / 8, 0);
        self.len = n
    }

    /// Insert the element at `k`.
    pub fn insert(&mut self, k: K) -> bool {
        let index = k.index();
        if index >= self.len {
            self.resize(index + 1)
        }
        let result = !self.contains(k);
        self.elems[index / 8] |= 1 << (index % 8);
        result
    }
}

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

    // `EntityRef` impl for testing.
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct E(u32);

    impl EntityRef for E {
        fn new(i: usize) -> Self {
            E(i as u32)
        }
        fn index(self) -> usize {
            self.0 as usize
        }
    }

    #[test]
    fn basic() {
        let r0 = E(0);
        let r1 = E(1);
        let r2 = E(2);
        let mut m = EntitySet::new();

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, []);
        assert!(m.is_empty());

        m.insert(r2);
        m.insert(r1);

        assert!(!m.contains(r0));
        assert!(m.contains(r1));
        assert!(m.contains(r2));
        assert!(!m.is_empty());

        let v: Vec<E> = m.keys().collect();
        assert_eq!(v, [r0, r1, r2]);

        m.resize(20);
        assert!(!m.contains(E(3)));
        assert!(!m.contains(E(4)));
        assert!(!m.contains(E(8)));
        assert!(!m.contains(E(15)));
        assert!(!m.contains(E(19)));

        m.insert(E(8));
        m.insert(E(15));
        assert!(!m.contains(E(3)));
        assert!(!m.contains(E(4)));
        assert!(m.contains(E(8)));
        assert!(!m.contains(E(9)));
        assert!(!m.contains(E(14)));
        assert!(m.contains(E(15)));
        assert!(!m.contains(E(16)));
        assert!(!m.contains(E(19)));

        m.clear();
        assert!(m.is_empty());
    }
}
<|endoftext|>