<commit_before>//! Extension methods for `Stream` based on record-by-record transformation.

use Data;
use dataflow::{Stream, Scope};
use dataflow::channels::pact::Pipeline;
use dataflow::operators::binary::Binary;

use dataflow::channels::message::Content;

/// Extension trait for `Stream`.
pub trait Reclock<S: Scope, D: Data> {
    /// Delays records until an input is observed on the `clock` input.
    ///
    /// #Examples
    ///
    /// ```
    /// use timely::dataflow::operators::{ToStream, Delay, Inspect, Map, Reclock, Capture};
    /// use timely::dataflow::operators::capture::Extract;
    /// // use timely::dataflow::channels::pact::Pipeline;
    /// use timely::progress::timestamp::RootTimestamp;
    ///
    /// let captured = timely::example(|scope| {
    ///     let data = (0..10).to_stream(scope)
    ///                       .delay(|x,t| RootTimestamp::new(*x));
    ///
    ///     let clock = vec![3, 5, 8].into_iter()
    ///                              .to_stream(scope)
    ///                              .delay(|x,t| RootTimestamp::new(*x))
    ///                              .map(|_| ());
    ///
    ///     data.reclock(&clock)
    ///         .inspect_batch(|t,xs| println!("time: {:?}, data: {:?}", t, xs))
    ///         .capture()
    /// });
    ///
    /// let extracted = captured.extract();
    /// assert_eq!(extracted.len(), 3);
    /// assert_eq!(extracted[0], (RootTimestamp::new(3), vec![0,1,2,3]));
    /// assert_eq!(extracted[1], (RootTimestamp::new(5), vec![4,5]));
    /// assert_eq!(extracted[2], (RootTimestamp::new(8), vec![6,7,8]));
    /// ```
    fn reclock(&self, clock: &Stream<S, ()>) -> Stream<S, D>;
}

impl<S: Scope, D: Data> Reclock<S, D> for Stream<S, D> {
    fn reclock(&self, clock: &Stream<S, ()>) -> Stream<S, D> {

        let mut stash = vec![];

        self.binary_notify(clock, Pipeline, Pipeline, "Reclock", vec![], move |input1, input2, output, notificator| {

            while let Some((time, data)) = input1.next() {
                stash.push((time.time(), ::std::mem::replace(data, Content::Typed(vec![]))));
            }

            while let Some((time, _data)) = input2.next() {
                notificator.notify_at(time);
            }

            while let Some((cap, _)) = notificator.next() {
                let time = cap.time();
                let mut session = output.session(&cap);
                for &mut (ref t, ref mut data) in &mut stash {
                    if t.le(&time) {
                        session.give_content(data);
                    }
                }
                stash.retain(|x| !x.0.le(&time));
            }

        })

    }
}
<commit_msg>added comments<commit_after>//! Extension methods for `Stream` based on record-by-record transformation.

use Data;
use dataflow::{Stream, Scope};
use dataflow::channels::pact::Pipeline;
use dataflow::operators::binary::Binary;

use dataflow::channels::message::Content;

/// Extension trait for reclocking a stream.
pub trait Reclock<S: Scope, D: Data> {
    /// Delays records until an input is observed on the `clock` input.
    ///
    /// The source stream is buffered until a record is seen on the clock input,
    /// at which point a notification is requested and all data with time less
    /// or equal to the clock time are sent. This method does not ensure that all
    /// workers receive the same clock records, which can be accomplished with
    /// `broadcast`.
    ///
    /// #Examples
    ///
    /// ```
    /// use timely::dataflow::operators::{ToStream, Delay, Map, Reclock, Capture};
    /// use timely::dataflow::operators::capture::Extract;
    /// use timely::progress::timestamp::RootTimestamp;
    ///
    /// let captured = timely::example(|scope| {
    ///
    ///     // produce data 0..10 at times 0..10.
    ///     let data = (0..10).to_stream(scope)
    ///                       .delay(|x,t| RootTimestamp::new(*x));
    ///
    ///     // product clock ticks at three times.
    ///     let clock = vec![3, 5, 8].into_iter()
    ///                              .to_stream(scope)
    ///                              .delay(|x,t| RootTimestamp::new(*x))
    ///                              .map(|_| ());
    ///
    ///     // reclock the data.
    ///     data.reclock(&clock)
    ///         .capture()
    /// });
    ///
    /// let extracted = captured.extract();
    /// assert_eq!(extracted.len(), 3);
    /// assert_eq!(extracted[0], (RootTimestamp::new(3), vec![0,1,2,3]));
    /// assert_eq!(extracted[1], (RootTimestamp::new(5), vec![4,5]));
    /// assert_eq!(extracted[2], (RootTimestamp::new(8), vec![6,7,8]));
    /// ```
    fn reclock(&self, clock: &Stream<S, ()>) -> Stream<S, D>;
}

impl<S: Scope, D: Data> Reclock<S, D> for Stream<S, D> {
    fn reclock(&self, clock: &Stream<S, ()>) -> Stream<S, D> {

        let mut stash = vec![];

        self.binary_notify(clock, Pipeline, Pipeline, "Reclock", vec![], move |input1, input2, output, notificator| {

            // stash each data input with its timestamp.
            while let Some((time, data)) = input1.next() {
                stash.push((time.time(), ::std::mem::replace(data, Content::Typed(vec![]))));
            }

            // request notification at time, to flush stash.
            while let Some((time, _data)) = input2.next() {
                notificator.notify_at(time);
            }

            // each time with complete stash can be flushed.
            while let Some((cap, _)) = notificator.next() {
                let time = cap.time();
                let mut session = output.session(&cap);
                for &mut (ref t, ref mut data) in &mut stash {
                    if t.le(&time) {
                        session.give_content(data);
                    }
                }
                stash.retain(|x| !x.0.le(&time));
            }
        })
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::collections::{HashMap, HashSet};

use autocxx_parser::IncludeCppConfig;

use crate::{conversion::api::Api, types::QualifiedName};

use super::{deps::HasDependencies, fun::FnPhase};

/// This is essentially mark-and-sweep garbage collection of the
/// [Api]s that we've discovered. Why do we do this, you might wonder?
/// It seems a bit strange given that we pass an explicit allowlist
/// to bindgen.
/// There are two circumstances under which we want to discard
/// some of the APIs we encounter parsing the bindgen.
/// 1) We simplify some struct to be non-POD. In this case, we'll
///    discard all the fields within it. Those fields can be, and
///    in fact often _are_, stuff which we have trouble converting
///    e.g. std::string or std::string::value_type or
///    my_derived_thing<std::basic_string::value_type> or some
///    other permutation. In such cases, we want to discard those
///    field types with prejudice.
/// 2) block! may be used to ban certain APIs. This often eliminates
///    some methods from a given struct/class. In which case, we
///    don't care about the other parameter types passed into those
///    APIs either.
pub(crate) fn filter_apis_by_following_edges_from_allowlist(
    mut apis: Vec<Api<FnPhase>>,
    config: &IncludeCppConfig,
) -> Vec<Api<FnPhase>> {
    let mut todos: Vec<QualifiedName> = apis
        .iter()
        .filter(|api| {
            let tnforal = api.typename_for_allowlist();
            config.is_on_allowlist(&tnforal.to_cpp_name())
        })
        .map(Api::name)
        .cloned()
        .collect();
    let mut by_typename: HashMap<QualifiedName, Vec<Api<FnPhase>>> = HashMap::new();
    for api in apis.drain(..) {
        let tn = api.name().clone();
        by_typename.entry(tn).or_default().push(api);
    }
    let mut done = HashSet::new();
    let mut output = Vec::new();
    while !todos.is_empty() {
        let todo = todos.remove(0);
        if done.contains(&todo) {
            continue;
        }
        if let Some(mut these_apis) = by_typename.remove(&todo) {
            todos.extend(these_apis.iter().flat_map(|api| api.deps().cloned()));
            output.append(&mut these_apis);
        } // otherwise, probably an intrinsic e.g. uint32_t.
        done.insert(todo);
    }
    output
}
<commit_msg>Remove use of Vec<Api>::drain.<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::collections::{HashMap, HashSet};

use autocxx_parser::IncludeCppConfig;

use crate::{conversion::api::Api, types::QualifiedName};

use super::{deps::HasDependencies, fun::FnPhase};

/// This is essentially mark-and-sweep garbage collection of the
/// [Api]s that we've discovered. Why do we do this, you might wonder?
/// It seems a bit strange given that we pass an explicit allowlist
/// to bindgen.
/// There are two circumstances under which we want to discard
/// some of the APIs we encounter parsing the bindgen.
/// 1) We simplify some struct to be non-POD. In this case, we'll
///    discard all the fields within it. Those fields can be, and
///    in fact often _are_, stuff which we have trouble converting
///    e.g. std::string or std::string::value_type or
///    my_derived_thing<std::basic_string::value_type> or some
///    other permutation. In such cases, we want to discard those
///    field types with prejudice.
/// 2) block! may be used to ban certain APIs. This often eliminates
///    some methods from a given struct/class. In which case, we
///    don't care about the other parameter types passed into those
///    APIs either.
pub(crate) fn filter_apis_by_following_edges_from_allowlist(
    apis: Vec<Api<FnPhase>>,
    config: &IncludeCppConfig,
) -> Vec<Api<FnPhase>> {
    let mut todos: Vec<QualifiedName> = apis
        .iter()
        .filter(|api| {
            let tnforal = api.typename_for_allowlist();
            config.is_on_allowlist(&tnforal.to_cpp_name())
        })
        .map(Api::name)
        .cloned()
        .collect();
    let mut by_typename: HashMap<QualifiedName, Vec<Api<FnPhase>>> = HashMap::new();
    for api in apis.into_iter() {
        let tn = api.name().clone();
        by_typename.entry(tn).or_default().push(api);
    }
    let mut done = HashSet::new();
    let mut output = Vec::new();
    while !todos.is_empty() {
        let todo = todos.remove(0);
        if done.contains(&todo) {
            continue;
        }
        if let Some(mut these_apis) = by_typename.remove(&todo) {
            todos.extend(these_apis.iter().flat_map(|api| api.deps().cloned()));
            output.append(&mut these_apis);
        } // otherwise, probably an intrinsic e.g. uint32_t.
        done.insert(todo);
    }
    output
}
<|endoftext|>


<commit_before>use std::env::var_os;

use getopts;

use output::Colours;
use output::{Grid, Details, GridDetails};
use output::column::{Columns, TimeTypes, SizeFormat};
use output::file_name::Classify;
use options::{FileFilter, DirAction, Misfire};
use term::dimensions;
use fs::feature::xattr;

/// The **view** contains all information about how to format output.
#[derive(PartialEq, Debug, Clone)]
pub struct View {
    pub mode: Mode,
    pub colours: Colours,
    pub classify: Classify,
}

/// The **mode** is the “type” of output.
#[derive(PartialEq, Debug, Clone)]
pub enum Mode {
    Details(Details),
    Grid(Grid),
    GridDetails(GridDetails),
    Lines,
}

impl View {

    /// Determine which view to use and all of that view’s arguments.
    pub fn deduce(matches: &getopts::Matches, filter: FileFilter, dir_action: DirAction) -> Result<View, Misfire> {
        use options::misfire::Misfire::*;

        let colour_scale = || {
            matches.opt_present("color-scale") || matches.opt_present("colour-scale")
        };

        let long = || {
            if matches.opt_present("across") && !matches.opt_present("grid") {
                Err(Useless("across", true, "long"))
            }
            else if matches.opt_present("oneline") {
                Err(Useless("oneline", true, "long"))
            }
            else {
                let term_colours = TerminalColours::deduce(matches)?;
                let colours = match term_colours {
                    TerminalColours::Always    => Colours::colourful(colour_scale()),
                    TerminalColours::Never     => Colours::plain(),
                    TerminalColours::Automatic => {
                        if dimensions().is_some() {
                            Colours::colourful(colour_scale())
                        }
                        else {
                            Colours::plain()
                        }
                    },
                };

                let details = Details {
                    columns: Some(Columns::deduce(matches)?),
                    header: matches.opt_present("header"),
                    recurse: dir_action.recurse_options(),
                    filter: filter.clone(),
                    xattr: xattr::ENABLED && matches.opt_present("extended"),
                };

                let classify = Classify::deduce(matches);

                Ok(View { mode: Mode::Details(details), colours, classify })
            }
        };

        let long_options_scan = || {
            for option in &[ "binary", "bytes", "inode", "links", "header", "blocks", "time", "group" ] {
                if matches.opt_present(option) {
                    return Err(Useless(option, false, "long"));
                }
            }

            if cfg!(feature="git") && matches.opt_present("git") {
                Err(Useless("git", false, "long"))
            }
            else if matches.opt_present("level") && !matches.opt_present("recurse") && !matches.opt_present("tree") {
                Err(Useless2("level", "recurse", "tree"))
            }
            else if xattr::ENABLED && matches.opt_present("extended") {
                Err(Useless("extended", false, "long"))
            }
            else {
                Ok(())
            }
        };

        let other_options_scan = || {
            let classify     = Classify::deduce(matches);
            let term_colours = TerminalColours::deduce(matches)?;
            let term_width   = TerminalWidth::deduce()?;

            if let Some(&width) = term_width.as_ref() {
                let colours = match term_colours {
                    TerminalColours::Always     |
                    TerminalColours::Automatic  => Colours::colourful(colour_scale()),
                    TerminalColours::Never      => Colours::plain(),
                };

                if matches.opt_present("oneline") {
                    if matches.opt_present("across") {
                        Err(Useless("across", true, "oneline"))
                    }
                    else {
                        Ok(View { mode: Mode::Lines, colours, classify })
                    }
                }
                else if matches.opt_present("tree") {
                    let details = Details {
                        columns: None,
                        header: false,
                        recurse: dir_action.recurse_options(),
                        filter: filter.clone(),  // TODO: clone
                        xattr: false,
                    };

                    Ok(View { mode: Mode::Details(details), colours, classify })
                }
                else {
                    let grid = Grid {
                        across: matches.opt_present("across"),
                        console_width: width,
                    };

                    Ok(View { mode: Mode::Grid(grid), colours, classify })
                }
            }
            else {
                // If the terminal width couldn’t be matched for some reason, such
                // as the program’s stdout being connected to a file, then
                // fallback to the lines view.

                let colours = match term_colours {
                    TerminalColours::Always    => Colours::colourful(colour_scale()),
                    TerminalColours::Never | TerminalColours::Automatic => Colours::plain(),
                };

                if matches.opt_present("tree") {
                    let details = Details {
                        columns: None,
                        header: false,
                        recurse: dir_action.recurse_options(),
                        filter: filter.clone(),
                        xattr: false,
                    };

                    Ok(View { mode: Mode::Details(details), colours, classify })
                }
                else {
                    Ok(View { mode: Mode::Lines, colours, classify })
                }
            }
        };

        if matches.opt_present("long") {
            let view = long()?;
            if matches.opt_present("grid") {
                if let View { colours: _, classify: _, mode: Mode::Details(details) } = view {
                    let others = other_options_scan()?;
                    match others.mode {
                        Mode::Grid(grid) => return Ok(View { mode: Mode::GridDetails(GridDetails { grid: grid, details: details }), colours: others.colours, classify: others.classify }),
                        _                => return Ok(others),
                    };
                }
                else {
                    unreachable!()
                }
            }
            else {
                return Ok(view);
            }
        }

        long_options_scan()?;

        other_options_scan()
    }
}

/// The width of the terminal requested by the user.
#[derive(PartialEq, Debug)]
enum TerminalWidth {

    /// The user requested this specific number of columns.
    Set(usize),

    /// The terminal was found to have this number of columns.
    Terminal(usize),

    /// The user didn’t request any particular terminal width.
    Unset,
}

impl TerminalWidth {

    /// Determine a requested terminal width from the command-line arguments.
    ///
    /// Returns an error if a requested width doesn’t parse to an integer.
    fn deduce() -> Result<TerminalWidth, Misfire> {
        if let Some(columns) = var_os("COLUMNS").and_then(|s| s.into_string().ok()) {
            match columns.parse() {
                Ok(width)  => Ok(TerminalWidth::Set(width)),
                Err(e)     => Err(Misfire::FailedParse(e)),
            }
        }
        else if let Some((width, _)) = dimensions() {
            Ok(TerminalWidth::Terminal(width))
        }
        else {
            Ok(TerminalWidth::Unset)
        }
    }

    fn as_ref(&self) -> Option<&usize> {
        match *self {
            TerminalWidth::Set(ref width)
            | TerminalWidth::Terminal(ref width)    => Some(width),
            TerminalWidth::Unset                    => None,
        }
    }
}

impl Columns {
    fn deduce(matches: &getopts::Matches) -> Result<Columns, Misfire> {
        Ok(Columns {
            size_format: SizeFormat::deduce(matches)?,
            time_types:  TimeTypes::deduce(matches)?,
            inode:  matches.opt_present("inode"),
            links:  matches.opt_present("links"),
            blocks: matches.opt_present("blocks"),
            group:  matches.opt_present("group"),
            git:    cfg!(feature="git") && matches.opt_present("git"),
        })
    }
}

impl SizeFormat {

    /// Determine which file size to use in the file size column based on
    /// the user’s options.
    ///
    /// The default mode is to use the decimal prefixes, as they are the
    /// most commonly-understood, and don’t involve trying to parse large
    /// strings of digits in your head. Changing the format to anything else
    /// involves the `--binary` or `--bytes` flags, and these conflict with
    /// each other.
    fn deduce(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
        let binary = matches.opt_present("binary");
        let bytes  = matches.opt_present("bytes");

        match (binary, bytes) {
            (true,  true )  => Err(Misfire::Conflict("binary", "bytes")),
            (true,  false)  => Ok(SizeFormat::BinaryBytes),
            (false, true )  => Ok(SizeFormat::JustBytes),
            (false, false)  => Ok(SizeFormat::DecimalBytes),
        }
    }
}

impl TimeTypes {

    /// Determine which of a file’s time fields should be displayed for it
    /// based on the user’s options.
    ///
    /// There are two separate ways to pick which fields to show: with a
    /// flag (such as `--modified`) or with a parameter (such as
    /// `--time=modified`). An error is signaled if both ways are used.
    ///
    /// It’s valid to show more than one column by passing in more than one
    /// option, but passing *no* options means that the user just wants to
    /// see the default set.
    fn deduce(matches: &getopts::Matches) -> Result<TimeTypes, Misfire> {
        let possible_word = matches.opt_str("time");
        let modified = matches.opt_present("modified");
        let created  = matches.opt_present("created");
        let accessed = matches.opt_present("accessed");

        if let Some(word) = possible_word {
            if modified {
                return Err(Misfire::Useless("modified", true, "time"));
            }
            else if created {
                return Err(Misfire::Useless("created", true, "time"));
            }
            else if accessed {
                return Err(Misfire::Useless("accessed", true, "time"));
            }

            static TIMES: &[& str] = &["modified", "accessed", "created"];
            match &*word {
                "mod" | "modified"  => Ok(TimeTypes { accessed: false, modified: true,  created: false }),
                "acc" | "accessed"  => Ok(TimeTypes { accessed: true,  modified: false, created: false }),
                "cr"  | "created"   => Ok(TimeTypes { accessed: false, modified: false, created: true  }),
                otherwise           => Err(Misfire::bad_argument("time", otherwise, TIMES))
            }
        }
        else if modified || created || accessed {
            Ok(TimeTypes { accessed, modified, created })
        }
        else {
            Ok(TimeTypes::default())
        }
    }
}

/// Under what circumstances we should display coloured, rather than plain,
/// output to the terminal.
///
/// By default, we want to display the colours when stdout can display them.
/// Turning them on when output is going to, say, a pipe, would make programs
/// such as `grep` or `more` not work properly. So the `Automatic` mode does
/// this check and only displays colours when they can be truly appreciated.
#[derive(PartialEq, Debug)]
enum TerminalColours {

    /// Display them even when output isn’t going to a terminal.
    Always,

    /// Display them when output is going to a terminal, but not otherwise.
    Automatic,

    /// Never display them, even when output is going to a terminal.
    Never,
}

impl Default for TerminalColours {
    fn default() -> TerminalColours {
        TerminalColours::Automatic
    }
}

impl TerminalColours {

    /// Determine which terminal colour conditions to use.
    fn deduce(matches: &getopts::Matches) -> Result<TerminalColours, Misfire> {
        const COLOURS: &[&str] = &["always", "auto", "never"];

        if let Some(word) = matches.opt_str("color").or_else(|| matches.opt_str("colour")) {
            match &*word {
                "always"              => Ok(TerminalColours::Always),
                "auto" | "automatic"  => Ok(TerminalColours::Automatic),
                "never"               => Ok(TerminalColours::Never),
                otherwise             => Err(Misfire::bad_argument("color", otherwise, COLOURS))
            }
        }
        else {
            Ok(TerminalColours::default())
        }
    }
}

impl Classify {
    fn deduce(matches: &getopts::Matches) -> Classify {
        if matches.opt_present("classify") { Classify::AddFileIndicators }
                                      else { Classify::JustFilenames }
    }
}
<commit_msg>Extract common classify<commit_after>use std::env::var_os;

use getopts;

use output::Colours;
use output::{Grid, Details, GridDetails};
use output::column::{Columns, TimeTypes, SizeFormat};
use output::file_name::Classify;
use options::{FileFilter, DirAction, Misfire};
use term::dimensions;
use fs::feature::xattr;

/// The **view** contains all information about how to format output.
#[derive(PartialEq, Debug, Clone)]
pub struct View {
    pub mode: Mode,
    pub colours: Colours,
    pub classify: Classify,
}

/// The **mode** is the “type” of output.
#[derive(PartialEq, Debug, Clone)]
pub enum Mode {
    Details(Details),
    Grid(Grid),
    GridDetails(GridDetails),
    Lines,
}

impl View {

    /// Determine which view to use and all of that view’s arguments.
    pub fn deduce(matches: &getopts::Matches, filter: FileFilter, dir_action: DirAction) -> Result<View, Misfire> {
        use options::misfire::Misfire::*;

        let classify = Classify::deduce(matches);

        let colour_scale = || {
            matches.opt_present("color-scale") || matches.opt_present("colour-scale")
        };

        let long = || {
            if matches.opt_present("across") && !matches.opt_present("grid") {
                Err(Useless("across", true, "long"))
            }
            else if matches.opt_present("oneline") {
                Err(Useless("oneline", true, "long"))
            }
            else {
                let term_colours = TerminalColours::deduce(matches)?;
                let colours = match term_colours {
                    TerminalColours::Always    => Colours::colourful(colour_scale()),
                    TerminalColours::Never     => Colours::plain(),
                    TerminalColours::Automatic => {
                        if dimensions().is_some() {
                            Colours::colourful(colour_scale())
                        }
                        else {
                            Colours::plain()
                        }
                    },
                };

                let details = Details {
                    columns: Some(Columns::deduce(matches)?),
                    header: matches.opt_present("header"),
                    recurse: dir_action.recurse_options(),
                    filter: filter.clone(),
                    xattr: xattr::ENABLED && matches.opt_present("extended"),
                };

                Ok(View { mode: Mode::Details(details), colours, classify })
            }
        };

        let long_options_scan = || {
            for option in &[ "binary", "bytes", "inode", "links", "header", "blocks", "time", "group" ] {
                if matches.opt_present(option) {
                    return Err(Useless(option, false, "long"));
                }
            }

            if cfg!(feature="git") && matches.opt_present("git") {
                Err(Useless("git", false, "long"))
            }
            else if matches.opt_present("level") && !matches.opt_present("recurse") && !matches.opt_present("tree") {
                Err(Useless2("level", "recurse", "tree"))
            }
            else if xattr::ENABLED && matches.opt_present("extended") {
                Err(Useless("extended", false, "long"))
            }
            else {
                Ok(())
            }
        };

        let other_options_scan = || {
            let term_colours = TerminalColours::deduce(matches)?;
            let term_width   = TerminalWidth::deduce()?;

            if let Some(&width) = term_width.as_ref() {
                let colours = match term_colours {
                    TerminalColours::Always     |
                    TerminalColours::Automatic  => Colours::colourful(colour_scale()),
                    TerminalColours::Never      => Colours::plain(),
                };

                if matches.opt_present("oneline") {
                    if matches.opt_present("across") {
                        Err(Useless("across", true, "oneline"))
                    }
                    else {
                        Ok(View { mode: Mode::Lines, colours, classify })
                    }
                }
                else if matches.opt_present("tree") {
                    let details = Details {
                        columns: None,
                        header: false,
                        recurse: dir_action.recurse_options(),
                        filter: filter.clone(),  // TODO: clone
                        xattr: false,
                    };

                    Ok(View { mode: Mode::Details(details), colours, classify })
                }
                else {
                    let grid = Grid {
                        across: matches.opt_present("across"),
                        console_width: width,
                    };

                    Ok(View { mode: Mode::Grid(grid), colours, classify })
                }
            }
            else {
                // If the terminal width couldn’t be matched for some reason, such
                // as the program’s stdout being connected to a file, then
                // fallback to the lines view.

                let colours = match term_colours {
                    TerminalColours::Always    => Colours::colourful(colour_scale()),
                    TerminalColours::Never | TerminalColours::Automatic => Colours::plain(),
                };

                if matches.opt_present("tree") {
                    let details = Details {
                        columns: None,
                        header: false,
                        recurse: dir_action.recurse_options(),
                        filter: filter.clone(),
                        xattr: false,
                    };

                    Ok(View { mode: Mode::Details(details), colours, classify })
                }
                else {
                    Ok(View { mode: Mode::Lines, colours, classify })
                }
            }
        };

        if matches.opt_present("long") {
            let view = long()?;
            if matches.opt_present("grid") {
                if let View { colours: _, classify: _, mode: Mode::Details(details) } = view {
                    let others = other_options_scan()?;
                    match others.mode {
                        Mode::Grid(grid) => return Ok(View { mode: Mode::GridDetails(GridDetails { grid: grid, details: details }), colours: others.colours, classify: others.classify }),
                        _                => return Ok(others),
                    };
                }
                else {
                    unreachable!()
                }
            }
            else {
                return Ok(view);
            }
        }

        long_options_scan()?;

        other_options_scan()
    }
}

/// The width of the terminal requested by the user.
#[derive(PartialEq, Debug)]
enum TerminalWidth {

    /// The user requested this specific number of columns.
    Set(usize),

    /// The terminal was found to have this number of columns.
    Terminal(usize),

    /// The user didn’t request any particular terminal width.
    Unset,
}

impl TerminalWidth {

    /// Determine a requested terminal width from the command-line arguments.
    ///
    /// Returns an error if a requested width doesn’t parse to an integer.
    fn deduce() -> Result<TerminalWidth, Misfire> {
        if let Some(columns) = var_os("COLUMNS").and_then(|s| s.into_string().ok()) {
            match columns.parse() {
                Ok(width)  => Ok(TerminalWidth::Set(width)),
                Err(e)     => Err(Misfire::FailedParse(e)),
            }
        }
        else if let Some((width, _)) = dimensions() {
            Ok(TerminalWidth::Terminal(width))
        }
        else {
            Ok(TerminalWidth::Unset)
        }
    }

    fn as_ref(&self) -> Option<&usize> {
        match *self {
            TerminalWidth::Set(ref width)
            | TerminalWidth::Terminal(ref width)    => Some(width),
            TerminalWidth::Unset                    => None,
        }
    }
}

impl Columns {
    fn deduce(matches: &getopts::Matches) -> Result<Columns, Misfire> {
        Ok(Columns {
            size_format: SizeFormat::deduce(matches)?,
            time_types:  TimeTypes::deduce(matches)?,
            inode:  matches.opt_present("inode"),
            links:  matches.opt_present("links"),
            blocks: matches.opt_present("blocks"),
            group:  matches.opt_present("group"),
            git:    cfg!(feature="git") && matches.opt_present("git"),
        })
    }
}

impl SizeFormat {

    /// Determine which file size to use in the file size column based on
    /// the user’s options.
    ///
    /// The default mode is to use the decimal prefixes, as they are the
    /// most commonly-understood, and don’t involve trying to parse large
    /// strings of digits in your head. Changing the format to anything else
    /// involves the `--binary` or `--bytes` flags, and these conflict with
    /// each other.
    fn deduce(matches: &getopts::Matches) -> Result<SizeFormat, Misfire> {
        let binary = matches.opt_present("binary");
        let bytes  = matches.opt_present("bytes");

        match (binary, bytes) {
            (true,  true )  => Err(Misfire::Conflict("binary", "bytes")),
            (true,  false)  => Ok(SizeFormat::BinaryBytes),
            (false, true )  => Ok(SizeFormat::JustBytes),
            (false, false)  => Ok(SizeFormat::DecimalBytes),
        }
    }
}

impl TimeTypes {

    /// Determine which of a file’s time fields should be displayed for it
    /// based on the user’s options.
    ///
    /// There are two separate ways to pick which fields to show: with a
    /// flag (such as `--modified`) or with a parameter (such as
    /// `--time=modified`). An error is signaled if both ways are used.
    ///
    /// It’s valid to show more than one column by passing in more than one
    /// option, but passing *no* options means that the user just wants to
    /// see the default set.
    fn deduce(matches: &getopts::Matches) -> Result<TimeTypes, Misfire> {
        let possible_word = matches.opt_str("time");
        let modified = matches.opt_present("modified");
        let created  = matches.opt_present("created");
        let accessed = matches.opt_present("accessed");

        if let Some(word) = possible_word {
            if modified {
                return Err(Misfire::Useless("modified", true, "time"));
            }
            else if created {
                return Err(Misfire::Useless("created", true, "time"));
            }
            else if accessed {
                return Err(Misfire::Useless("accessed", true, "time"));
            }

            static TIMES: &[& str] = &["modified", "accessed", "created"];
            match &*word {
                "mod" | "modified"  => Ok(TimeTypes { accessed: false, modified: true,  created: false }),
                "acc" | "accessed"  => Ok(TimeTypes { accessed: true,  modified: false, created: false }),
                "cr"  | "created"   => Ok(TimeTypes { accessed: false, modified: false, created: true  }),
                otherwise           => Err(Misfire::bad_argument("time", otherwise, TIMES))
            }
        }
        else if modified || created || accessed {
            Ok(TimeTypes { accessed, modified, created })
        }
        else {
            Ok(TimeTypes::default())
        }
    }
}

/// Under what circumstances we should display coloured, rather than plain,
/// output to the terminal.
///
/// By default, we want to display the colours when stdout can display them.
/// Turning them on when output is going to, say, a pipe, would make programs
/// such as `grep` or `more` not work properly. So the `Automatic` mode does
/// this check and only displays colours when they can be truly appreciated.
#[derive(PartialEq, Debug)]
enum TerminalColours {

    /// Display them even when output isn’t going to a terminal.
    Always,

    /// Display them when output is going to a terminal, but not otherwise.
    Automatic,

    /// Never display them, even when output is going to a terminal.
    Never,
}

impl Default for TerminalColours {
    fn default() -> TerminalColours {
        TerminalColours::Automatic
    }
}

impl TerminalColours {

    /// Determine which terminal colour conditions to use.
    fn deduce(matches: &getopts::Matches) -> Result<TerminalColours, Misfire> {
        const COLOURS: &[&str] = &["always", "auto", "never"];

        if let Some(word) = matches.opt_str("color").or_else(|| matches.opt_str("colour")) {
            match &*word {
                "always"              => Ok(TerminalColours::Always),
                "auto" | "automatic"  => Ok(TerminalColours::Automatic),
                "never"               => Ok(TerminalColours::Never),
                otherwise             => Err(Misfire::bad_argument("color", otherwise, COLOURS))
            }
        }
        else {
            Ok(TerminalColours::default())
        }
    }
}

impl Classify {
    fn deduce(matches: &getopts::Matches) -> Classify {
        if matches.opt_present("classify") { Classify::AddFileIndicators }
                                      else { Classify::JustFilenames }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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(any(feature = "force-inprocess", not(target_os = "macos")))]
mod incrementor {
    pub struct Incrementor {
        last_value: u64,
    }

    impl Incrementor {
        pub fn new() -> Incrementor {
            Incrementor {
                last_value: 0
            }
        }

        pub fn increment(&mut self) -> u64 {
            self.last_value += 1;
            self.last_value
        }
    }
}

#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
                                                target_os = "freebsd")))]
mod unix;
#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
                                                target_os = "freebsd")))]
mod os {
    pub use super::unix::*;
}

#[cfg(all(not(feature = "force-inprocess"), target_os = "macos"))]
mod macos;
#[cfg(all(not(feature = "force-inprocess"), target_os = "macos"))]
mod os {
    pub use super::macos::*;
}

#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
mod inprocess;
#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
mod os {
    pub use super::inprocess::*;
}

pub use self::os::{OsIpcChannel, OsIpcOneShotServer, OsIpcReceiver, OsIpcReceiverSet};
pub use self::os::{OsIpcSelectionResult, OsIpcSender, OsIpcSharedMemory};
pub use self::os::{OsOpaqueIpcChannel, channel};

#[cfg(test)]
mod test;
<commit_msg>Cleanup: Drop platform conditional on `Incrementor` helper<commit_after>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

mod incrementor {
    pub struct Incrementor {
        last_value: u64,
    }

    impl Incrementor {
        pub fn new() -> Incrementor {
            Incrementor {
                last_value: 0
            }
        }

        pub fn increment(&mut self) -> u64 {
            self.last_value += 1;
            self.last_value
        }
    }
}

#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
                                                target_os = "freebsd")))]
mod unix;
#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
                                                target_os = "freebsd")))]
mod os {
    pub use super::unix::*;
}

#[cfg(all(not(feature = "force-inprocess"), target_os = "macos"))]
mod macos;
#[cfg(all(not(feature = "force-inprocess"), target_os = "macos"))]
mod os {
    pub use super::macos::*;
}

#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
mod inprocess;
#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
mod os {
    pub use super::inprocess::*;
}

pub use self::os::{OsIpcChannel, OsIpcOneShotServer, OsIpcReceiver, OsIpcReceiverSet};
pub use self::os::{OsIpcSelectionResult, OsIpcSender, OsIpcSharedMemory};
pub use self::os::{OsOpaqueIpcChannel, channel};

#[cfg(test)]
mod test;
<|endoftext|>


<commit_before>#[cfg(test)]
pub mod mocks;

#[cfg(test)]
mod spec_tests;

use crate::{
    cart::Cart,
    ppu::{control_register::IncrementAmount, write_latch::LatchState},
};
use std::cell::Cell;

pub trait IVram {
    fn write_ppu_addr(&self, latch_state: LatchState);
    fn write_ppu_data<C: Cart>(&mut self, val: u8, inc_amount: IncrementAmount, cart: &mut C);
    fn read_ppu_data<C: Cart>(&self, inc_amount: IncrementAmount, cart: &C) -> u8;
    fn ppu_data<C: Cart>(&self, cart: &C) -> u8;
    fn read<C: Cart>(&self, addr: u16, cart: &C) -> u8;
    fn read_palette(&self, addr: u16) -> u8;
    fn addr(&self) -> u16;
    fn scroll_write(&self, latch_state: LatchState);
    fn control_write(&self, val: u8);
    fn coarse_x_increment(&self);
    fn fine_y_increment(&self);
    fn copy_horizontal_pos_to_addr(&self);
    fn copy_vertical_pos_to_addr(&self);
    fn fine_x(&self) -> u8;
}

pub struct Vram {
    address: Cell<u16>,
    name_tables: [u8; 0x1000],
    palette: [u8; 0x20],
    ppu_data_buffer: Cell<u8>,
    t: Cell<u16>,
    fine_x: Cell<u8>,
}

impl Vram {
    pub fn new() -> Self {
        Vram {
            address: Cell::new(0),
            name_tables: [0; 0x1000],
            palette: [0; 0x20],
            ppu_data_buffer: Cell::new(0),
            t: Cell::new(0),
            fine_x: Cell::new(0),
        }
    }
}

impl IVram for Vram {
    fn write_ppu_addr(&self, latch_state: LatchState) {
        // Addresses greater than 0x3fff are mirrored down
        match latch_state {
            LatchState::FirstWrite(val) => {
                // t: ..FEDCBA ........ = d: ..FEDCBA
                // t: .X...... ........ = 0
                let t = self.t.get() & 0b1000_0000_1111_1111;
                self.t.set(((val as u16 & 0b0011_1111) << 8) | t)
            }
            LatchState::SecondWrite(val) => {
                // t: ....... HGFEDCBA = d: HGFEDCBA
                // v                   = t
                let t = val as u16 | (self.t.get() & 0b0111_1111_0000_0000);
                self.t.set(t);
                self.address.set(t);
            }
        }
    }

    fn write_ppu_data<C: Cart>(&mut self, val: u8, inc_amount: IncrementAmount, cart: &mut C) {
        let addr = self.address.get();

        if addr < 0x2000 {
            cart.write_chr(addr, val);
        } else if addr < 0x3f00 {
            self.name_tables[addr as usize & 0x0fff] = val;
        } else if addr < 0x4000 {
            let addr = addr as usize & 0x1f;
            // Certain sprite addresses are mirrored back into background addresses
            let addr = match addr & 0xf {
                0x0 => 0x0,
                0x4 => 0x4,
                0x8 => 0x8,
                0xc => 0xc,
                _ => addr,
            };
            self.palette[addr] = val;
        }

        match inc_amount {
            IncrementAmount::One => self.address.set(self.address.get() + 1),
            IncrementAmount::ThirtyTwo => self.address.set(self.address.get() + 32),
        }
    }

    fn read_ppu_data<C: Cart>(&self, inc_amount: IncrementAmount, cart: &C) -> u8 {
        let val = self.ppu_data(cart);
        match inc_amount {
            IncrementAmount::One => self.address.set(self.address.get() + 1),
            IncrementAmount::ThirtyTwo => self.address.set(self.address.get() + 32),
        }
        val
    }

    fn ppu_data<C: Cart>(&self, cart: &C) -> u8 {
        let addr = self.address.get();
        let val = self.read(addr, cart);

        // When reading while the VRAM address is in the range 0-$3EFF (i.e., before the palettes),
        // the read will return the contents of an internal read buffer. This internal buffer is
        // updated only when reading PPUDATA, and so is preserved across frames. After the CPU reads
        // and gets the contents of the internal buffer, the PPU will immediately update the
        // internal buffer with the byte at the current VRAM address
        if addr < 0x3f00 {
            let buffered_val = self.ppu_data_buffer.get();
            self.ppu_data_buffer.set(val);
            buffered_val
        } else {
            val
        }
    }

    fn read<C: Cart>(&self, addr: u16, cart: &C) -> u8 {
        if addr < 0x2000 {
            cart.read_chr(addr)
        } else if addr < 0x3f00 {
            self.name_tables[addr as usize & 0x0fff]
        } else if addr < 0x4000 {
            let addr = addr & 0x1f;
            self.read_palette(addr)
        } else {
            panic!("Invalid vram read")
        }
    }

    fn read_palette(&self, addr: u16) -> u8 {
        // Certain sprite addresses are mirrored back into background addresses
        let addr = match addr & 0xf {
            0x0 => 0x0,
            0x4 => 0x4,
            0x8 => 0x8,
            0xc => 0xc,
            _ => addr,
        };
        self.palette[addr as usize]
    }

    fn addr(&self) -> u16 {
        self.address.get()
    }

    fn scroll_write(&self, latch_state: LatchState) {
        match latch_state {
            LatchState::FirstWrite(val) => {
                // t: ....... ...HGFED = d: HGFED...
                let t = self.t.get() & 0b_1111_1111_1110_0000;
                self.t.set(((val as u16 & 0b_1111_1000) >> 3) | t);

                //x:              CBA = d: .....CBA
                self.fine_x.set(val & 0b_0000_0111);
            }
            LatchState::SecondWrite(val) => {
                // t: CBA..HG FED..... = d: HGFEDCBA
                let t = self.t.get() & 0b_0000_1100_0001_1111;
                let cba_mask = (val as u16 & 0b_0000_0111) << 12;
                let hgfed_mask = (val as u16 & 0b_1111_1000) << 2;
                self.t.set((cba_mask | hgfed_mask) | t);
            }
        }
    }

    fn control_write(&self, val: u8) {
        // t: ...BA.. ........ = d: ......BA
        let t = self.t.get() & 0b0111_0011_1111_1111;
        let new_t = ((val as u16 & 0b0011) << 10) | t;
        self.t.set(new_t);
    }

    fn coarse_x_increment(&self) {
        let v = self.address.get();

        // The coarse X component of v needs to be incremented when the next tile is reached. Bits
        // 0-4 are incremented, with overflow toggling bit 10. This means that bits 0-4 count from 0
        // to 31 across a single nametable, and bit 10 selects the current nametable horizontally.
        let v = if v & 0x001F == 31 {
            // set coarse X = 0 and switch horizontal nametable
            (v & !0x001F) ^ 0x0400
        } else {
            // increment coarse X
            v + 1
        };

        self.address.set(v);
    }

    fn fine_y_increment(&self) {
        let v = self.address.get();

        let v = if v & 0x7000 != 0x7000 {
            // if fine Y < 7, increment fine Y
            v + 0x1000
        } else {
            // if fine Y = 0...
            let v = v & !0x7000;

            // let y = coarse Y
            let mut y = (v & 0x03E0) >> 5;
            let v = if y == 29 {
                // set coarse Y to 0
                y = 0;

                // switch vertical nametable
                v ^ 0x0800
            } else if y == 31 {
                // set coarse Y = 0, nametable not switched
                y = 0;
                v
            } else {
                // increment coarse Y
                y += 1;
                v
            };

            // put coarse Y back into v
            (v & !0x03E0) | (y << 5)
        };

        self.address.set(v);
    }

    fn copy_horizontal_pos_to_addr(&self) {
        // At dot 257 of each scanline, if rendering is enabled, the PPU copies all bits related to
        // horizontal position from t to v:
        // v: ....F.. ...EDCBA = t: ....F.. ...EDCBA
        let v = self.address.get() & 0b0111_1011_1110_0000;
        self.address.set((self.t.get() & 0b0000_0100_0001_1111) | v)
    }

    fn copy_vertical_pos_to_addr(&self) {
        // During dots 280 to 304 of the pre-render scanline (end of vblank), if rendering is
        // enabled, at the end of vblank, shortly after the horizontal bits are copied from t to v
        // at dot 257, the PPU will repeatedly copy the vertical bits from t to v from dots 280 to
        // 304, completing the full initialization of v from t:
        // v: IHGF.ED CBA..... = t: IHGF.ED CBA.....
        let v = self.address.get() & 0b0000_0100_0001_1111;
        self.address.set((self.t.get() & 0b0111_1011_1110_0000) | v)
    }

    fn fine_x(&self) -> u8 {
        self.fine_x.get()
    }
}
<commit_msg>Used unchecked array access where safe<commit_after>#[cfg(test)]
pub mod mocks;

#[cfg(test)]
mod spec_tests;

use crate::{
    cart::Cart,
    ppu::{control_register::IncrementAmount, write_latch::LatchState},
};
use std::cell::Cell;

pub trait IVram {
    fn write_ppu_addr(&self, latch_state: LatchState);
    fn write_ppu_data<C: Cart>(&mut self, val: u8, inc_amount: IncrementAmount, cart: &mut C);
    fn read_ppu_data<C: Cart>(&self, inc_amount: IncrementAmount, cart: &C) -> u8;
    fn ppu_data<C: Cart>(&self, cart: &C) -> u8;
    fn read<C: Cart>(&self, addr: u16, cart: &C) -> u8;
    fn read_palette(&self, addr: u16) -> u8;
    fn addr(&self) -> u16;
    fn scroll_write(&self, latch_state: LatchState);
    fn control_write(&self, val: u8);
    fn coarse_x_increment(&self);
    fn fine_y_increment(&self);
    fn copy_horizontal_pos_to_addr(&self);
    fn copy_vertical_pos_to_addr(&self);
    fn fine_x(&self) -> u8;
}

pub struct Vram {
    address: Cell<u16>,
    name_tables: [u8; 0x1000],
    palette: [u8; 0x20],
    ppu_data_buffer: Cell<u8>,
    t: Cell<u16>,
    fine_x: Cell<u8>,
}

impl Vram {
    pub fn new() -> Self {
        Vram {
            address: Cell::new(0),
            name_tables: [0; 0x1000],
            palette: [0; 0x20],
            ppu_data_buffer: Cell::new(0),
            t: Cell::new(0),
            fine_x: Cell::new(0),
        }
    }
}

impl IVram for Vram {
    fn write_ppu_addr(&self, latch_state: LatchState) {
        // Addresses greater than 0x3fff are mirrored down
        match latch_state {
            LatchState::FirstWrite(val) => {
                // t: ..FEDCBA ........ = d: ..FEDCBA
                // t: .X...... ........ = 0
                let t = self.t.get() & 0b1000_0000_1111_1111;
                self.t.set(((val as u16 & 0b0011_1111) << 8) | t)
            }
            LatchState::SecondWrite(val) => {
                // t: ....... HGFEDCBA = d: HGFEDCBA
                // v                   = t
                let t = val as u16 | (self.t.get() & 0b0111_1111_0000_0000);
                self.t.set(t);
                self.address.set(t);
            }
        }
    }

    fn write_ppu_data<C: Cart>(&mut self, val: u8, inc_amount: IncrementAmount, cart: &mut C) {
        let addr = self.address.get();

        if addr < 0x2000 {
            cart.write_chr(addr, val);
        } else if addr < 0x3f00 {
            unsafe {
                // Safe unchecked access since the AND will normalize to a valid index
                *self.name_tables.get_unchecked_mut(addr as usize & 0x0fff) = val;
            }
        } else if addr < 0x4000 {
            let addr = addr as usize & 0x1f;
            // Certain sprite addresses are mirrored back into background addresses
            let addr = match addr & 0xf {
                0x0 => 0x0,
                0x4 => 0x4,
                0x8 => 0x8,
                0xc => 0xc,
                _ => addr,
            };
            unsafe {
                // Safe unchecked access since the AND will normalize to a valid index
                *self.palette.get_unchecked_mut(addr) = val;
            }
        }

        match inc_amount {
            IncrementAmount::One => self.address.set(self.address.get() + 1),
            IncrementAmount::ThirtyTwo => self.address.set(self.address.get() + 32),
        }
    }

    fn read_ppu_data<C: Cart>(&self, inc_amount: IncrementAmount, cart: &C) -> u8 {
        let val = self.ppu_data(cart);
        match inc_amount {
            IncrementAmount::One => self.address.set(self.address.get() + 1),
            IncrementAmount::ThirtyTwo => self.address.set(self.address.get() + 32),
        }
        val
    }

    fn ppu_data<C: Cart>(&self, cart: &C) -> u8 {
        let addr = self.address.get();
        let val = self.read(addr, cart);

        // When reading while the VRAM address is in the range 0-$3EFF (i.e., before the palettes),
        // the read will return the contents of an internal read buffer. This internal buffer is
        // updated only when reading PPUDATA, and so is preserved across frames. After the CPU reads
        // and gets the contents of the internal buffer, the PPU will immediately update the
        // internal buffer with the byte at the current VRAM address
        if addr < 0x3f00 {
            let buffered_val = self.ppu_data_buffer.get();
            self.ppu_data_buffer.set(val);
            buffered_val
        } else {
            val
        }
    }

    fn read<C: Cart>(&self, addr: u16, cart: &C) -> u8 {
        if addr < 0x2000 {
            cart.read_chr(addr)
        } else if addr < 0x3f00 {
            unsafe {
                // Safe unchecked access since the AND will normalize to a valid index
                *self.name_tables.get_unchecked(addr as usize & 0x0fff)
            }
        } else if addr < 0x4000 {
            let addr = addr & 0x1f;
            self.read_palette(addr)
        } else {
            panic!("Invalid vram read")
        }
    }

    fn read_palette(&self, addr: u16) -> u8 {
        // Certain sprite addresses are mirrored back into background addresses
        let addr = match addr & 0xf {
            0x0 => 0x0,
            0x4 => 0x4,
            0x8 => 0x8,
            0xc => 0xc,
            _ => addr,
        };
        unsafe {
            // Safe unchecked access since the AND will normalize to a valid index
            *self.palette.get_unchecked(addr as usize)
        }
    }

    fn addr(&self) -> u16 {
        self.address.get()
    }

    fn scroll_write(&self, latch_state: LatchState) {
        match latch_state {
            LatchState::FirstWrite(val) => {
                // t: ....... ...HGFED = d: HGFED...
                let t = self.t.get() & 0b_1111_1111_1110_0000;
                self.t.set(((val as u16 & 0b_1111_1000) >> 3) | t);

                //x:              CBA = d: .....CBA
                self.fine_x.set(val & 0b_0000_0111);
            }
            LatchState::SecondWrite(val) => {
                // t: CBA..HG FED..... = d: HGFEDCBA
                let t = self.t.get() & 0b_0000_1100_0001_1111;
                let cba_mask = (val as u16 & 0b_0000_0111) << 12;
                let hgfed_mask = (val as u16 & 0b_1111_1000) << 2;
                self.t.set((cba_mask | hgfed_mask) | t);
            }
        }
    }

    fn control_write(&self, val: u8) {
        // t: ...BA.. ........ = d: ......BA
        let t = self.t.get() & 0b0111_0011_1111_1111;
        let new_t = ((val as u16 & 0b0011) << 10) | t;
        self.t.set(new_t);
    }

    fn coarse_x_increment(&self) {
        let v = self.address.get();

        // The coarse X component of v needs to be incremented when the next tile is reached. Bits
        // 0-4 are incremented, with overflow toggling bit 10. This means that bits 0-4 count from 0
        // to 31 across a single nametable, and bit 10 selects the current nametable horizontally.
        let v = if v & 0x001F == 31 {
            // set coarse X = 0 and switch horizontal nametable
            (v & !0x001F) ^ 0x0400
        } else {
            // increment coarse X
            v + 1
        };

        self.address.set(v);
    }

    fn fine_y_increment(&self) {
        let v = self.address.get();

        let v = if v & 0x7000 != 0x7000 {
            // if fine Y < 7, increment fine Y
            v + 0x1000
        } else {
            // if fine Y = 0...
            let v = v & !0x7000;

            // let y = coarse Y
            let mut y = (v & 0x03E0) >> 5;
            let v = if y == 29 {
                // set coarse Y to 0
                y = 0;

                // switch vertical nametable
                v ^ 0x0800
            } else if y == 31 {
                // set coarse Y = 0, nametable not switched
                y = 0;
                v
            } else {
                // increment coarse Y
                y += 1;
                v
            };

            // put coarse Y back into v
            (v & !0x03E0) | (y << 5)
        };

        self.address.set(v);
    }

    fn copy_horizontal_pos_to_addr(&self) {
        // At dot 257 of each scanline, if rendering is enabled, the PPU copies all bits related to
        // horizontal position from t to v:
        // v: ....F.. ...EDCBA = t: ....F.. ...EDCBA
        let v = self.address.get() & 0b0111_1011_1110_0000;
        self.address.set((self.t.get() & 0b0000_0100_0001_1111) | v)
    }

    fn copy_vertical_pos_to_addr(&self) {
        // During dots 280 to 304 of the pre-render scanline (end of vblank), if rendering is
        // enabled, at the end of vblank, shortly after the horizontal bits are copied from t to v
        // at dot 257, the PPU will repeatedly copy the vertical bits from t to v from dots 280 to
        // 304, completing the full initialization of v from t:
        // v: IHGF.ED CBA..... = t: IHGF.ED CBA.....
        let v = self.address.get() & 0b0000_0100_0001_1111;
        self.address.set((self.t.get() & 0b0111_1011_1110_0000) | v)
    }

    fn fine_x(&self) -> u8 {
        self.fine_x.get()
    }
}
<|endoftext|>


<commit_before>use game_map::RoomId;
use direction::Direction;
use game_state::{GameState, GameMode};
use command::{CommandProcessor, HelpInfo};
use items::Item;
use platform;
use util;

const PAUSE_MS: u64 = 2500;

#[derive(Debug)]
pub enum PrimaryCommand {
  Go(Direction),
  Inventory,
  Look,
  Quit,
}

impl CommandProcessor<PrimaryCommand> for PrimaryCommand {
  fn get_help() -> Vec<HelpInfo> {
    HelpInfo::list(vec![
      ('n', "go north"),
      ('s', "go south"),
      ('e', "go east"),
      ('w', "go west"),
      ('u', "go up"),
      ('d', "go down"),
      ('i', "inventory/buy provisions"),
      ('l', "look around"),
      ('q', "quit"),
    ])
  }

  fn from_char(c: char) -> Option<PrimaryCommand> {
    match c {
      'n' => Some(PrimaryCommand::Go(Direction::North)),
      's' => Some(PrimaryCommand::Go(Direction::South)),
      'e' => Some(PrimaryCommand::Go(Direction::East)),
      'w' => Some(PrimaryCommand::Go(Direction::West)),
      'u' => Some(PrimaryCommand::Go(Direction::Up)),
      'd' => Some(PrimaryCommand::Go(Direction::Down)),
      'i' => Some(PrimaryCommand::Inventory),
      'l' => Some(PrimaryCommand::Look),
      'q' => Some(PrimaryCommand::Quit),
      _ => None,
    }
  }
}

impl<'a> GameState<'a> {
  fn print_status_report(&self) {
    println!("{}, your strength is {}.", self.player_name, self.strength);
    self.print_wealth();
    if self.food > 0 {
      println!("Your provisions sack holds {} unit{} of food.",
               self.food, if self.food == 1 { "" } else { "s" });
    }
    if self.suit {
      println!("You are wearing armor.");
    }
    let item_names = self.get_item_names();
    if item_names.len() > 0 {
      println!("You are carrying {}.",
               util::friendly_join(self.get_item_names()));
    }
  }

  fn get_item_names(&self) -> Vec<&str> {
    let mut items = Vec::new();
    if self.axe { items.push(Item::Axe.as_str()) }
    if self.sword { items.push(Item::Sword.as_str()) }
    if self.amulet { items.push(Item::Amulet.as_str()) }
    items
  }

  pub fn tick_primary_mode(&mut self) {
    if self.show_desc {
      match self.curr_room {
        RoomId::Lift => {
          println!("You have entered the lift...");
          platform::sleep(PAUSE_MS);
          println!("It slowly descends...");
          platform::sleep(PAUSE_MS);
          self.curr_room = RoomId::RearVestibule;
          return;
        },
        RoomId::Exit => {
          println!("\nYou've done it!!");
          platform::sleep(PAUSE_MS);
          println!("That was the exit from the castle.");
          platform::sleep(PAUSE_MS);
          println!("\nYou have succeeded, {}!", self.player_name);
          println!("\nYou managed to get out of the castle.");
          platform::sleep(PAUSE_MS);
          println!("\nWell done!");
          platform::sleep(PAUSE_MS);
          self.finish_game();
          return;
        },
        _ => {
          platform::clear_screen();
          self.print_status_report();
          println!("");
          if self.curr_room != RoomId::Entrance && !self.light {
            println!("It is too dark to see anything.");
          } else {
            platform::writeln_with_wrapping(
              self.map.room(self.curr_room).description
            );
          }
          println!("");
        }
      }
      self.show_desc = false;
    }

    if let Some(cmd) = PrimaryCommand::get() {
      match cmd {
        PrimaryCommand::Go(dir) => {
          if let Some(room) = self.map.room(self.curr_room).get_exit(dir) {
            self.curr_room = room;
            self.show_desc = true;
          } else {
            println!("You can't go that way.");
          }
        },
        PrimaryCommand::Inventory => { self.set_mode(GameMode::Inventory) },
        PrimaryCommand::Look => { self.show_desc = true }
        PrimaryCommand::Quit => { self.finish_game() }
      }
    };
  }
}
<commit_msg>More verbosity improvements.<commit_after>use game_map::RoomId;
use direction::Direction;
use game_state::{GameState, GameMode};
use command::{CommandProcessor, HelpInfo};
use items::Item;
use platform;
use util;

use self::PrimaryCommand::*;

const PAUSE_MS: u64 = 2500;

#[derive(Debug)]
pub enum PrimaryCommand {
  Go(Direction),
  Inventory,
  Look,
  Quit,
}

impl CommandProcessor<PrimaryCommand> for PrimaryCommand {
  fn get_help() -> Vec<HelpInfo> {
    HelpInfo::list(vec![
      ('n', "go north"),
      ('s', "go south"),
      ('e', "go east"),
      ('w', "go west"),
      ('u', "go up"),
      ('d', "go down"),
      ('i', "inventory/buy provisions"),
      ('l', "look around"),
      ('q', "quit"),
    ])
  }

  fn from_char(c: char) -> Option<PrimaryCommand> {
    match c {
      'n' => Some(Go(Direction::North)),
      's' => Some(Go(Direction::South)),
      'e' => Some(Go(Direction::East)),
      'w' => Some(Go(Direction::West)),
      'u' => Some(Go(Direction::Up)),
      'd' => Some(Go(Direction::Down)),
      'i' => Some(Inventory),
      'l' => Some(Look),
      'q' => Some(Quit),
      _ => None,
    }
  }
}

impl<'a> GameState<'a> {
  fn print_status_report(&self) {
    println!("{}, your strength is {}.", self.player_name, self.strength);
    self.print_wealth();
    if self.food > 0 {
      println!("Your provisions sack holds {} unit{} of food.",
               self.food, if self.food == 1 { "" } else { "s" });
    }
    if self.suit {
      println!("You are wearing armor.");
    }
    let item_names = self.get_item_names();
    if item_names.len() > 0 {
      println!("You are carrying {}.",
               util::friendly_join(self.get_item_names()));
    }
  }

  fn get_item_names(&self) -> Vec<&str> {
    let mut items = Vec::new();
    if self.axe { items.push(Item::Axe.as_str()) }
    if self.sword { items.push(Item::Sword.as_str()) }
    if self.amulet { items.push(Item::Amulet.as_str()) }
    items
  }

  pub fn tick_primary_mode(&mut self) {
    if self.show_desc {
      match self.curr_room {
        RoomId::Lift => {
          println!("You have entered the lift...");
          platform::sleep(PAUSE_MS);
          println!("It slowly descends...");
          platform::sleep(PAUSE_MS);
          self.curr_room = RoomId::RearVestibule;
          return;
        },
        RoomId::Exit => {
          println!("\nYou've done it!!");
          platform::sleep(PAUSE_MS);
          println!("That was the exit from the castle.");
          platform::sleep(PAUSE_MS);
          println!("\nYou have succeeded, {}!", self.player_name);
          println!("\nYou managed to get out of the castle.");
          platform::sleep(PAUSE_MS);
          println!("\nWell done!");
          platform::sleep(PAUSE_MS);
          self.finish_game();
          return;
        },
        _ => {
          platform::clear_screen();
          self.print_status_report();
          println!("");
          if self.curr_room != RoomId::Entrance && !self.light {
            println!("It is too dark to see anything.");
          } else {
            platform::writeln_with_wrapping(
              self.map.room(self.curr_room).description
            );
          }
          println!("");
        }
      }
      self.show_desc = false;
    }

    if let Some(cmd) = PrimaryCommand::get() {
      match cmd {
        Go(dir) => {
          if let Some(room) = self.map.room(self.curr_room).get_exit(dir) {
            self.curr_room = room;
            self.show_desc = true;
          } else {
            println!("You can't go that way.");
          }
        },
        Inventory => { self.set_mode(GameMode::Inventory) },
        Look => { self.show_desc = true }
        Quit => { self.finish_game() }
      }
    };
  }
}
<|endoftext|>


<commit_before>use std::io::Cursor;
use FromCursor;
use types::CBytes;

/// A server authentication challenge.
#[derive(Debug)]
pub struct BodyResAuthChallenge {
    pub data: CBytes
}

impl FromCursor for BodyResAuthChallenge {
    fn from_cursor(mut cursor: &mut Cursor<Vec<u8>>) -> BodyResAuthChallenge {
        BodyResAuthChallenge {
            data: CBytes::from_cursor(&mut cursor)
        }
    }
}
<commit_msg>Fix comment<commit_after>use std::io::Cursor;
use FromCursor;
use types::CBytes;

/// Server authentication challenge.
#[derive(Debug)]
pub struct BodyResAuthChallenge {
    pub data: CBytes
}

impl FromCursor for BodyResAuthChallenge {
    fn from_cursor(mut cursor: &mut Cursor<Vec<u8>>) -> BodyResAuthChallenge {
        BodyResAuthChallenge {
            data: CBytes::from_cursor(&mut cursor)
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::vec::IntoIter;
use rand::{Rand, Rng};
use super::super::symbol_tables::ST;
use super::super::balanced_search_trees::RedBlackBST;

#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
pub struct Point2D {
    pub x: f64,
    pub y: f64
}

impl Point2D {
    pub fn new(x: f64, y: f64) -> Point2D {
        Point2D { x: x, y: y }
    }

    pub fn distance_to<T: AsRef<Point2D>>(&self, that: T) -> f64 {
        self.distance_squared_to(that).sqrt()
    }

    pub fn distance_squared_to<T: AsRef<Point2D>>(&self, that: T) -> f64 {
        (self.x - that.as_ref().x).powi(2) + (self.y - that.as_ref().y).powi(2)
    }
}

impl fmt::Display for Point2D {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

impl AsRef<Point2D> for Point2D {
    fn as_ref(&self) -> &Point2D {
        &self
    }
}

impl Rand for Point2D {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Point2D {
            x: rng.next_f64(),
            y: rng.next_f64()
        }
    }
}

#[test]
fn test_point2d() {
    let p1 = Point2D::new(0.0, 0.0);
    let p2 = Point2D::new(1.0, 1.0);

    // maybe bad :(
    assert_eq!(p1.distance_to(p2), (2.0f64).sqrt());
}

#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
/// Implementation of 2D axis-aligned rectangle
pub struct RectHV {
    pub xmin: f64,
    pub ymin: f64,
    pub xmax: f64,
    pub ymax: f64
}

impl RectHV {
    pub fn new(xmin: f64, ymin: f64, xmax: f64, ymax: f64) -> RectHV {
        RectHV { xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax }
    }

    pub fn width(&self) -> f64 {
        self.xmax - self.xmin
    }

    pub fn height(&self) -> f64 {
        self.ymax - self.ymin
    }

    pub fn contains<T: AsRef<Point2D>>(&self, p: T) -> bool {
        let p = p.as_ref();
        p.x >= self.xmin && p.y >= self.ymin &&
            p.x <= self.xmax && p.y <= self.ymax
    }

    /// does this axis-aligned rectangle intersect that one?
    pub fn intersects<T: AsRef<RectHV>>(&self, that: T) -> bool {
        let that = that.as_ref();
        self.xmax >= that.xmin && self.ymax >= that.ymin &&
            that.xmax >= self.xmin && that.ymax >= self.ymin
    }

    /// distance from p to closest point on this axis-aligned rectangle
    pub fn distance_to<T: AsRef<Point2D>>(&self, p: T) -> f64 {
        self.distance_squared_to(p).sqrt()
    }

    /// distance squared from p to closest point on this axis-aligned rectangle
    pub fn distance_squared_to<T: AsRef<Point2D>>(&self, p: T) -> f64 {
        let p = p.as_ref();
        let mut dx = 0.0;
        let mut dy = 0.0;
        if p.x < self.xmin {
            dx = p.x - self.xmin;
        } else if p.x > self.xmax {
            dx = p.x - self.xmax;
        }
        if p.y < self.ymin {
            dy = p.y - self.ymin;
        } else if p.y > self.ymax {
            dy = p.y - self.ymax;
        }
        dx.powi(2) + dy.powi(2)
    }
}

impl fmt::Display for RectHV {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}, {}] x [{}, {}]", self.xmin, self.xmax, self.ymin, self.ymax)
    }
}

impl AsRef<RectHV> for RectHV {
    fn as_ref(&self) -> &RectHV {
        &self
    }
}

#[test]
fn test_rect() {
    let r1 = RectHV::new(0.0, 0.0, 1.1, 1.1);
    let r2 = RectHV::new(1.2, 2.0, 3.1, 4.1);
    assert!(!r1.intersects(r2));
}

/// represents a set of points in the unit square
/// implemented using RedBlackBST
pub struct PointSet {
    pset: RedBlackBST<Point2D, ()>
}

impl PointSet {
    pub fn new() -> PointSet {
        PointSet { pset: RedBlackBST::new() }
    }

    pub fn size(&self) -> usize {
        self.pset.size()
    }

    pub fn insert(&mut self, p: Point2D) {
        if !self.pset.contains(&p) {
            self.pset.put(p, ())
        }
    }

    pub fn contains<T: AsRef<Point2D>>(&self, p: T) -> bool {
        self.pset.contains(p.as_ref())
    }

    pub fn range_search<T: AsRef<RectHV>>(&self, rect: T) -> IntoIter<&Point2D> {
        let mut result = Vec::new();
        for p in self.pset.keys() {
            if rect.as_ref().contains(p) {
                result.push(p);
            }
        }
        result.into_iter()
    }

    pub fn range_count<T: AsRef<RectHV>>(&self, rect: T) -> usize {
        self.range_search(rect).count()
    }

    pub fn nearest<T: AsRef<Point2D>>(&self, p: T) -> Option<&Point2D> {
        // Ord :(
        self.pset.keys().min_by(|q| (q.distance_squared_to(p.as_ref()) * 10000.0) as u64)
    }
}

#[test]
fn test_point_set() {
    use rand::thread_rng;

    let mut rng = thread_rng();
    let mut ps = PointSet::new();
    for _ in 0 .. 100 {
        ps.insert(rng.gen())
    }
    assert_eq!(ps.size(), 100);

    assert!(ps.nearest(Point2D::new(0.5, 0.5)).is_some());
    assert!(ps.range_search(RectHV::new(0.4, 0.4, 0.6, 0.6)).count() > 0);
}
<commit_msg>geometric_search/primitive: fix rounding error in PointSet::nearest()<commit_after>use std::fmt;
use std::vec::IntoIter;
use std::f64;
use rand::{Rand, Rng};
use super::super::symbol_tables::ST;
use super::super::balanced_search_trees::RedBlackBST;

#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
pub struct Point2D {
    pub x: f64,
    pub y: f64
}

impl Point2D {
    pub fn new(x: f64, y: f64) -> Point2D {
        Point2D { x: x, y: y }
    }

    pub fn distance_to<T: AsRef<Point2D>>(&self, that: T) -> f64 {
        self.distance_squared_to(that).sqrt()
    }

    pub fn distance_squared_to<T: AsRef<Point2D>>(&self, that: T) -> f64 {
        (self.x - that.as_ref().x).powi(2) + (self.y - that.as_ref().y).powi(2)
    }
}

impl fmt::Display for Point2D {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

impl AsRef<Point2D> for Point2D {
    fn as_ref(&self) -> &Point2D {
        &self
    }
}

impl Rand for Point2D {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Point2D {
            x: rng.next_f64(),
            y: rng.next_f64()
        }
    }
}

#[test]
fn test_point2d() {
    let p1 = Point2D::new(0.0, 0.0);
    let p2 = Point2D::new(1.0, 1.0);

    // maybe bad :(
    assert_eq!(p1.distance_to(p2), (2.0f64).sqrt());
}

#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
/// Implementation of 2D axis-aligned rectangle
pub struct RectHV {
    pub xmin: f64,
    pub ymin: f64,
    pub xmax: f64,
    pub ymax: f64
}

impl RectHV {
    pub fn new(xmin: f64, ymin: f64, xmax: f64, ymax: f64) -> RectHV {
        RectHV { xmin: xmin, ymin: ymin, xmax: xmax, ymax: ymax }
    }

    pub fn width(&self) -> f64 {
        self.xmax - self.xmin
    }

    pub fn height(&self) -> f64 {
        self.ymax - self.ymin
    }

    pub fn contains<T: AsRef<Point2D>>(&self, p: T) -> bool {
        let p = p.as_ref();
        p.x >= self.xmin && p.y >= self.ymin &&
            p.x <= self.xmax && p.y <= self.ymax
    }

    /// does this axis-aligned rectangle intersect that one?
    pub fn intersects<T: AsRef<RectHV>>(&self, that: T) -> bool {
        let that = that.as_ref();
        self.xmax >= that.xmin && self.ymax >= that.ymin &&
            that.xmax >= self.xmin && that.ymax >= self.ymin
    }

    /// distance from p to closest point on this axis-aligned rectangle
    pub fn distance_to<T: AsRef<Point2D>>(&self, p: T) -> f64 {
        self.distance_squared_to(p).sqrt()
    }

    /// distance squared from p to closest point on this axis-aligned rectangle
    pub fn distance_squared_to<T: AsRef<Point2D>>(&self, p: T) -> f64 {
        let p = p.as_ref();
        let mut dx = 0.0;
        let mut dy = 0.0;
        if p.x < self.xmin {
            dx = p.x - self.xmin;
        } else if p.x > self.xmax {
            dx = p.x - self.xmax;
        }
        if p.y < self.ymin {
            dy = p.y - self.ymin;
        } else if p.y > self.ymax {
            dy = p.y - self.ymax;
        }
        dx.powi(2) + dy.powi(2)
    }
}

impl fmt::Display for RectHV {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}, {}] x [{}, {}]", self.xmin, self.xmax, self.ymin, self.ymax)
    }
}

impl AsRef<RectHV> for RectHV {
    fn as_ref(&self) -> &RectHV {
        &self
    }
}

#[test]
fn test_rect() {
    let r1 = RectHV::new(0.0, 0.0, 1.1, 1.1);
    let r2 = RectHV::new(1.2, 2.0, 3.1, 4.1);
    assert!(!r1.intersects(r2));
}

/// represents a set of points in the unit square
/// implemented using RedBlackBST
pub struct PointSet {
    pset: RedBlackBST<Point2D, ()>
}

impl PointSet {
    pub fn new() -> PointSet {
        PointSet { pset: RedBlackBST::new() }
    }

    pub fn size(&self) -> usize {
        self.pset.size()
    }

    pub fn insert(&mut self, p: Point2D) {
        if !self.pset.contains(&p) {
            self.pset.put(p, ())
        }
    }

    pub fn contains<T: AsRef<Point2D>>(&self, p: T) -> bool {
        self.pset.contains(p.as_ref())
    }

    pub fn range_search<T: AsRef<RectHV>>(&self, rect: T) -> IntoIter<&Point2D> {
        let mut result = Vec::new();
        for p in self.pset.keys() {
            if rect.as_ref().contains(p) {
                result.push(p);
            }
        }
        result.into_iter()
    }

    pub fn range_count<T: AsRef<RectHV>>(&self, rect: T) -> usize {
        self.range_search(rect).count()
    }

    pub fn nearest<T: AsRef<Point2D>>(&self, p: T) -> Option<&Point2D> {
        // Ord :(
        let mut min_distance = f64::MAX;
        let mut result = None;
        for q in self.pset.keys() {
            let dist = p.as_ref().distance_to(q);
            if dist < min_distance {
                result = Some(q);
                min_distance = dist;
            }
        }
        result
    }
}

#[test]
fn test_point_set() {
    use rand::thread_rng;

    let mut rng = thread_rng();
    let mut ps = PointSet::new();
    for _ in 0 .. 100 {
        ps.insert(rng.gen())
    }
    assert_eq!(ps.size(), 100);

    assert!(ps.nearest(Point2D::new(0.5, 0.5)).is_some());
    assert!(ps.range_search(RectHV::new(0.4, 0.4, 0.6, 0.6)).count() > 0);
}
<|endoftext|>


<commit_before>use crate::{
    api::{ColorProxy, Error, LilaVariant},
    indexer::IndexerOpt,
    model::{GameId, Speed, UserName},
};
use chrono::{DateTime, Utc};
use futures_util::stream::{Stream, StreamExt as _, TryStreamExt as _};
use serde::Deserialize;
use serde_with::{
    serde_as, DisplayFromStr, FromInto, SpaceSeparator, StringWithSeparator, TimestampMilliSeconds,
};
use shakmaty::{fen::Fen, san::San, Color};
use std::io;
use tokio::io::AsyncBufReadExt as _;
use tokio_stream::wrappers::LinesStream;
use tokio_util::io::StreamReader;

pub struct Lila {
    client: reqwest::Client,
    opt: IndexerOpt,
}

impl Lila {
    pub fn new(opt: IndexerOpt) -> Lila {
        Lila {
            client: reqwest::Client::builder().build().expect("reqwest client"),
            opt,
        }
    }

    pub async fn user_games(
        &self,
        user: &UserName,
    ) -> Result<impl Stream<Item = Result<Game, Error>>, Error> {
        let stream = self
            .client
            .get(format!(
                "{}/api/games/user/{}?sort=dateAsc&ongoing=true",
                self.opt.lila, user
            ))
            .header("Accept", "application/x-ndjson")
            .send()
            .await
            .and_then(|r| r.error_for_status())
            .map_err(|err| Error::IndexerRequestError(err))?
            .bytes_stream()
            .map_err(|err| io::Error::new(io::ErrorKind::Other, err));

        Ok(Box::pin(
            LinesStream::new(StreamReader::new(stream).lines()).filter_map(|line| async move {
                match line {
                    Ok(line) if line.is_empty() => None,
                    Ok(line) => Some(
                        serde_json::from_str::<Game>(&line)
                            .map_err(|err| Error::IndexerStreamError(err.into())),
                    ),
                    Err(err) => Some(Err(Error::IndexerStreamError(err))),
                }
            }),
        ))
    }
}

#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Game {
    #[serde_as(as = "DisplayFromStr")]
    pub id: GameId,
    pub rated: bool,
    #[serde_as(as = "TimestampMilliSeconds")]
    pub created_at: DateTime<Utc>,
    #[serde_as(as = "TimestampMilliSeconds")]
    pub last_move_at: DateTime<Utc>,
    pub status: Status,
    pub variant: LilaVariant,
    pub players: Players,
    pub speed: Speed,
    #[serde_as(as = "StringWithSeparator::<SpaceSeparator, San>")]
    pub moves: Vec<San>,
    #[serde_as(as = "Option<FromInto<ColorProxy>>")]
    #[serde(default)]
    pub winner: Option<Color>,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub initial_fen: Option<Fen>,
}

impl Game {
    pub fn user_name(&self, color: Color) -> Option<&UserName> {
        self.players.by_color(color).user.as_ref().map(|u| &u.name)
    }
}

#[derive(Debug, Deserialize)]
pub struct Players {
    pub white: Player,
    pub black: Player,
}

impl Players {
    fn by_color(&self, color: Color) -> &Player {
        match color {
            Color::White => &self.white,
            Color::Black => &self.black,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Player {
    #[serde(default)]
    pub user: Option<User>,
    #[serde(default)]
    pub rating: Option<u16>,
}

#[serde_as]
#[derive(Debug, Deserialize)]
pub struct User {
    #[serde_as(as = "DisplayFromStr")]
    pub name: UserName,
}

#[derive(Debug, Deserialize, Copy, Clone)]
#[serde(rename_all = "camelCase")]
pub enum Status {
    Created,
    Started,
    Aborted,
    Mate,
    Resign,
    Stalemate,
    Timeout,
    Draw,
    #[serde(rename = "outoftime")]
    OutOfTime,
    Cheat,
    NoStart,
    UnknownFinish,
    VariantEnd,
}

impl Status {
    pub fn is_ongoing(self) -> bool {
        matches!(self, Status::Created | Status::Started)
    }

    pub fn is_unindexable(self) -> bool {
        matches!(
            self,
            Status::UnknownFinish | Status::NoStart | Status::Aborted
        )
    }
}
<commit_msg>allow debugging indexer stream errors<commit_after>use crate::{
    api::{ColorProxy, Error, LilaVariant},
    indexer::IndexerOpt,
    model::{GameId, Speed, UserName},
};
use chrono::{DateTime, Utc};
use futures_util::stream::{Stream, StreamExt as _, TryStreamExt as _};
use serde::Deserialize;
use serde_with::{
    serde_as, DisplayFromStr, FromInto, SpaceSeparator, StringWithSeparator, TimestampMilliSeconds,
};
use shakmaty::{fen::Fen, san::San, Color};
use std::io;
use tokio::io::AsyncBufReadExt as _;
use tokio_stream::wrappers::LinesStream;
use tokio_util::io::StreamReader;

pub struct Lila {
    client: reqwest::Client,
    opt: IndexerOpt,
}

impl Lila {
    pub fn new(opt: IndexerOpt) -> Lila {
        Lila {
            client: reqwest::Client::builder().build().expect("reqwest client"),
            opt,
        }
    }

    pub async fn user_games(
        &self,
        user: &UserName,
    ) -> Result<impl Stream<Item = Result<Game, Error>>, Error> {
        let stream = self
            .client
            .get(format!(
                "{}/api/games/user/{}?sort=dateAsc&ongoing=true",
                self.opt.lila, user
            ))
            .header("Accept", "application/x-ndjson")
            .send()
            .await
            .and_then(|r| r.error_for_status())
            .map_err(|err| Error::IndexerRequestError(err))?
            .bytes_stream()
            .map_err(|err| io::Error::new(io::ErrorKind::Other, err));

        Ok(Box::pin(
            LinesStream::new(StreamReader::new(stream).lines()).filter_map(|line| async move {
                match line {
                    Ok(line) if line.is_empty() => None,
                    Ok(line) => Some(
                        serde_json::from_str::<Game>(&line)
                            .map_err(|err| {
                                let err = Error::IndexerStreamError(err.into());
                                log::error!("{}: {:?}", err, line);
                                err
                            })
                    ),
                    Err(err) => Some(Err(Error::IndexerStreamError(err))),
                }
            }),
        ))
    }
}

#[serde_as]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Game {
    #[serde_as(as = "DisplayFromStr")]
    pub id: GameId,
    pub rated: bool,
    #[serde_as(as = "TimestampMilliSeconds")]
    pub created_at: DateTime<Utc>,
    #[serde_as(as = "TimestampMilliSeconds")]
    pub last_move_at: DateTime<Utc>,
    pub status: Status,
    pub variant: LilaVariant,
    pub players: Players,
    pub speed: Speed,
    #[serde_as(as = "StringWithSeparator::<SpaceSeparator, San>")]
    pub moves: Vec<San>,
    #[serde_as(as = "Option<FromInto<ColorProxy>>")]
    #[serde(default)]
    pub winner: Option<Color>,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default)]
    pub initial_fen: Option<Fen>,
}

impl Game {
    pub fn user_name(&self, color: Color) -> Option<&UserName> {
        self.players.by_color(color).user.as_ref().map(|u| &u.name)
    }
}

#[derive(Debug, Deserialize)]
pub struct Players {
    pub white: Player,
    pub black: Player,
}

impl Players {
    fn by_color(&self, color: Color) -> &Player {
        match color {
            Color::White => &self.white,
            Color::Black => &self.black,
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct Player {
    #[serde(default)]
    pub user: Option<User>,
    #[serde(default)]
    pub rating: Option<u16>,
}

#[serde_as]
#[derive(Debug, Deserialize)]
pub struct User {
    #[serde_as(as = "DisplayFromStr")]
    pub name: UserName,
}

#[derive(Debug, Deserialize, Copy, Clone)]
#[serde(rename_all = "camelCase")]
pub enum Status {
    Created,
    Started,
    Aborted,
    Mate,
    Resign,
    Stalemate,
    Timeout,
    Draw,
    #[serde(rename = "outoftime")]
    OutOfTime,
    Cheat,
    NoStart,
    UnknownFinish,
    VariantEnd,
}

impl Status {
    pub fn is_ongoing(self) -> bool {
        matches!(self, Status::Created | Status::Started)
    }

    pub fn is_unindexable(self) -> bool {
        matches!(
            self,
            Status::UnknownFinish | Status::NoStart | Status::Aborted
        )
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
#[macro_use]
extern crate rosrust;

use rosrust::Ros;
use std::{env, thread, time};

rosmsg_include!();

fn main() {
    env_logger::init().unwrap();

    let args: Vec<_> = env::args().collect();

    if args.len() != 3 {
        println!("usage: client X Y");
        return;
    }

    let a = args[1].parse::<i64>().unwrap();
    let b = args[2].parse::<i64>().unwrap();

    let ros = Ros::new("add_two_ints_client").unwrap();
    let client = ros.client::<msg::roscpp_tutorials::TwoInts>("add_two_ints")
        .unwrap();

    // Sync approach
    println!(
        "{} + {} = {}",
        a,
        b,
        client
            .req(&msg::roscpp_tutorials::TwoIntsReq { a, b })
            .unwrap()
            .unwrap()
            .sum
    );

    // Async approach
    let retval = client.req_async(msg::roscpp_tutorials::TwoIntsReq { a, b });
    println!("{} + {} = {}", a, b, retval.read().unwrap().unwrap().sum);

    thread::sleep(time::Duration::from_secs(1));
}
<commit_msg>Update client example<commit_after>extern crate env_logger;
#[macro_use]
extern crate rosrust;

use rosrust::Ros;
use std::{env, time};

rosmsg_include!();

fn main() {
    env_logger::init().unwrap();

    let args: Vec<_> = env::args().collect();

    if args.len() != 3 {
        println!("usage: client X Y");
        return;
    }

    let a = args[1].parse::<i64>().unwrap();
    let b = args[2].parse::<i64>().unwrap();

    let ros = Ros::new("add_two_ints_client").unwrap();

    ros.wait_for_service("add_two_ints", Some(time::Duration::from_secs(10)))
        .unwrap();

    let client = ros.client::<msg::roscpp_tutorials::TwoInts>("add_two_ints")
        .unwrap();

    // Sync approach
    println!(
        "{} + {} = {}",
        a,
        b,
        client
            .req(&msg::roscpp_tutorials::TwoIntsReq { a, b })
            .unwrap()
            .unwrap()
            .sum
    );

    // Async approach
    let retval = client.req_async(msg::roscpp_tutorials::TwoIntsReq { a, b });
    println!("{} + {} = {}", a, b, retval.read().unwrap().unwrap().sum);
}
<|endoftext|>


<commit_before>use std::collections::HashSet;

fn main() {
    let mut a: HashSet<i32> = vec!(1i32, 2, 3).into_iter().collect();
    let mut b: HashSet<i32> = vec!(2i32, 3, 4).into_iter().collect();

    assert!(a.insert(4));
    assert!(a.contains(&4));

    // `HashSet::insert()` returns false if
    // there was a value already present.
    assert!(b.insert(4), "Value 4 is already in set B!");
    // FIXME ^ Comment out this line

    b.insert(5);

    // If a collection's element type implements `Debug`,
    // then the collection implements `Debug`.
    // It usually prints its elements in the format `[elem1, elem2, ...]`
    println!("A: {:?}", a);
    println!("B: {:?}", b);

    // Print [1, 2, 3, 4, 5] in arbitrary order
    println!("Union: {:?}", a.union(&b).collect::<Vec<&i32>>());

    // This should print [1]
    println!("Difference: {:?}", a.difference(&b).collect::<Vec<&i32>>());

    // Print [2, 3, 4] in arbitrary order.
    println!("Intersection: {:?}", a.intersection(&b).collect::<Vec<&i32>>());

    // Print [1, 5]
    println!("Symmetric Difference: {:?}",
             a.symmetric_difference(&b).collect::<Vec<&i32>>());
}

<commit_msg>Translate: examples/std/hash/hashset/hashset.rs<commit_after>use std::collections::HashSet;

fn main() {
    let mut a: HashSet<i32> = vec!(1i32, 2, 3).into_iter().collect();
    let mut b: HashSet<i32> = vec!(2i32, 3, 4).into_iter().collect();

    assert!(a.insert(4));
    assert!(a.contains(&4));

    // 如果值已经存在，那么 `HashSet::insert()` 返回 false。
    assert!(b.insert(4), "Value 4 is already in set B!");
    // 改正 ^ 将此行注释掉。

    b.insert(5);

    // 若一个组合的元素类型实现了 `Debug`，那么该组合也就实现了 `Debug`。
    // 这通常将元素打印成这样的格式 `[dlem1, elem2, ...]
    println!("A: {:?}", a);
    println!("B: {:?}", b);

    // 乱序打印 [1, 2, 3, 4, 5]。
    println!("Union: {:?}", a.union(&b).collect::<Vec<&i32>>());

    // 这将会打印出 [1]
    println!("Difference: {:?}", a.difference(&b).collect::<Vec<&i32>>());

    // 乱序打印 [2, 3, 4]。
    println!("Intersection: {:?}", a.intersection(&b).collect::<Vec<&i32>>());

    // 打印 [1, 5]
    println!("Symmetric Difference: {:?}",
             a.symmetric_difference(&b).collect::<Vec<&i32>>());
}

<|endoftext|>


<commit_before>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use model::*;
use std::gc::Gc;

pub fn check(cx: &ExtCtxt, model: AttributeArray, attr: Attribute) -> AttributeArray
{
  let meta_item = attr.node.value;
  match_meta_item(cx, model, &meta_item)
}

fn match_meta_item(cx: &ExtCtxt,
  model: AttributeArray,
  meta_item: &Gc<MetaItem>) -> AttributeArray
{
  let meta_name = meta_item_name(meta_item.node.clone());
  let mut attr_exists = false;
  let model = model.move_iter().map(|info|
    if info.name == meta_name {
      attr_exists = true;
      match_model(cx, info, meta_item)
    } else {
      info
    }
  ).collect();
  if !attr_exists {
    unknown_attribute(cx, meta_name, meta_item.span);
  }
  model
}

fn meta_item_name(meta_item: MetaItem_) -> InternedString
{
  match meta_item {
    MetaWord(name) |
    MetaList(name, _) |
    MetaNameValue(name, _) => name
  }
}

fn match_model(cx: &ExtCtxt, info: AttributeInfo, meta_item: &Gc<MetaItem>) -> AttributeInfo
{
  let model = match (info.model, meta_item.node.clone()) {
    (UnitValue(value), MetaWord(_)) => UnitValue(match_value(cx, value, meta_item.span)),
    (KeyValue(mlit), MetaNameValue(_, lit)) => KeyValue(match_lit(cx, mlit, lit)),
    (SubAttribute(dict), MetaList(_, list)) => SubAttribute(match_sub_attributes(cx, dict, list)),
    (model, _) => model_mismatch(cx, model, meta_item)
  };
  AttributeInfo { name: info.name, desc: info.desc, model: model }
}

fn match_value(cx: &ExtCtxt, value: AttributeValue<()>, span: Span) -> AttributeValue<()>
{
  value.update(cx, (), span)
}

fn match_lit(cx: &ExtCtxt, mlit: AttributeLitModel, lit: Lit) -> AttributeLitModel
{
  let sp = lit.span;
  match (mlit, lit.node.clone()) {
    (MLitStr(value), LitStr(s, style)) => MLitStr(value.update(cx, (s, style), sp)),
    (MLitBinary(value), LitBinary(val)) => MLitBinary(value.update(cx, val, sp)),
    (MLitByte(value), LitByte(val)) => MLitByte(value.update(cx, val, sp)),
    (MLitChar(value), LitChar(val)) => MLitChar(value.update(cx, val, sp)),
    (MLitInt(value), LitInt(val, ty)) => MLitInt(value.update(cx, (val, ty), sp)),
    (MLitFloat(value), LitFloat(val, ty)) => MLitFloat(value.update(cx, (val, ty), sp)),
    (MLitFloatUnsuffixed(value), LitFloatUnsuffixed(val)) => MLitFloatUnsuffixed(value.update(cx, val, sp)),
    (MLitNil(value), LitNil) => MLitNil(value.update(cx, (), sp)),
    (MLitBool(value), LitBool(val)) => MLitBool(value.update(cx, val, sp)),
    (mlit, _) => lit_mismatch(cx, mlit, lit)
  }
}

fn match_sub_attributes(cx: &ExtCtxt, model: AttributeArray, meta_items: Vec<Gc<MetaItem>>) -> AttributeArray
{
  meta_items.iter().fold(model, |model, meta_item| match_meta_item(cx, model, meta_item))
}

fn model_mismatch(cx: &ExtCtxt, model: AttributeModel, meta_item: &Gc<MetaItem>) -> AttributeModel
{
  cx.span_err(meta_item.span, "Model mismatch.");
  model
}

fn lit_mismatch(cx: &ExtCtxt, mlit: AttributeLitModel, lit: Lit) -> AttributeLitModel
{
  let mlit_printer = mlit.to_lit_printer();
  let lit_printer = lit_to_lit_printer(&lit.node);
  cx.span_err(lit.span,
    format!("Expected {} literal (e.g. `key = {}`) but got {} literal (e.g. `key = {}`).",
      mlit_printer.type_to_str(), mlit_printer.type_example_to_str(),
      lit_printer.type_to_str(), lit_printer.type_example_to_str()).as_slice());
  mlit
}

fn unknown_attribute(cx: &ExtCtxt, _meta_name: InternedString, span: Span)
{
  cx.span_err(span, "Unknown attribute.");
  // model.doc_approaching_results(cx, context, meta_name, span);
}
<commit_msg>[ModelChecker] Add a check_all function.<commit_after>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use model::*;
use std::gc::Gc;

pub fn check_all(cx: &ExtCtxt, model: AttributeArray, attr: Vec<Attribute>) -> AttributeArray
{
  attributes.move_iter().fold(
    model, |model, attr| check(cx, model, attr)
  )
}

pub fn check(cx: &ExtCtxt, model: AttributeArray, attr: Attribute) -> AttributeArray
{
  let meta_item = attr.node.value;
  match_meta_item(cx, model, &meta_item)
}

fn match_meta_item(cx: &ExtCtxt,
  model: AttributeArray,
  meta_item: &Gc<MetaItem>) -> AttributeArray
{
  let meta_name = meta_item_name(meta_item.node.clone());
  let mut attr_exists = false;
  let model = model.move_iter().map(|info|
    if info.name == meta_name {
      attr_exists = true;
      match_model(cx, info, meta_item)
    } else {
      info
    }
  ).collect();
  if !attr_exists {
    unknown_attribute(cx, meta_name, meta_item.span);
  }
  model
}

fn meta_item_name(meta_item: MetaItem_) -> InternedString
{
  match meta_item {
    MetaWord(name) |
    MetaList(name, _) |
    MetaNameValue(name, _) => name
  }
}

fn match_model(cx: &ExtCtxt, info: AttributeInfo, meta_item: &Gc<MetaItem>) -> AttributeInfo
{
  let model = match (info.model, meta_item.node.clone()) {
    (UnitValue(value), MetaWord(_)) => UnitValue(match_value(cx, value, meta_item.span)),
    (KeyValue(mlit), MetaNameValue(_, lit)) => KeyValue(match_lit(cx, mlit, lit)),
    (SubAttribute(dict), MetaList(_, list)) => SubAttribute(match_sub_attributes(cx, dict, list)),
    (model, _) => model_mismatch(cx, model, meta_item)
  };
  AttributeInfo { name: info.name, desc: info.desc, model: model }
}

fn match_value(cx: &ExtCtxt, value: AttributeValue<()>, span: Span) -> AttributeValue<()>
{
  value.update(cx, (), span)
}

fn match_lit(cx: &ExtCtxt, mlit: AttributeLitModel, lit: Lit) -> AttributeLitModel
{
  let sp = lit.span;
  match (mlit, lit.node.clone()) {
    (MLitStr(value), LitStr(s, style)) => MLitStr(value.update(cx, (s, style), sp)),
    (MLitBinary(value), LitBinary(val)) => MLitBinary(value.update(cx, val, sp)),
    (MLitByte(value), LitByte(val)) => MLitByte(value.update(cx, val, sp)),
    (MLitChar(value), LitChar(val)) => MLitChar(value.update(cx, val, sp)),
    (MLitInt(value), LitInt(val, ty)) => MLitInt(value.update(cx, (val, ty), sp)),
    (MLitFloat(value), LitFloat(val, ty)) => MLitFloat(value.update(cx, (val, ty), sp)),
    (MLitFloatUnsuffixed(value), LitFloatUnsuffixed(val)) => MLitFloatUnsuffixed(value.update(cx, val, sp)),
    (MLitNil(value), LitNil) => MLitNil(value.update(cx, (), sp)),
    (MLitBool(value), LitBool(val)) => MLitBool(value.update(cx, val, sp)),
    (mlit, _) => lit_mismatch(cx, mlit, lit)
  }
}

fn match_sub_attributes(cx: &ExtCtxt, model: AttributeArray, meta_items: Vec<Gc<MetaItem>>) -> AttributeArray
{
  meta_items.iter().fold(model, |model, meta_item| match_meta_item(cx, model, meta_item))
}

fn model_mismatch(cx: &ExtCtxt, model: AttributeModel, meta_item: &Gc<MetaItem>) -> AttributeModel
{
  cx.span_err(meta_item.span, "Model mismatch.");
  model
}

fn lit_mismatch(cx: &ExtCtxt, mlit: AttributeLitModel, lit: Lit) -> AttributeLitModel
{
  let mlit_printer = mlit.to_lit_printer();
  let lit_printer = lit_to_lit_printer(&lit.node);
  cx.span_err(lit.span,
    format!("Expected {} literal (e.g. `key = {}`) but got {} literal (e.g. `key = {}`).",
      mlit_printer.type_to_str(), mlit_printer.type_example_to_str(),
      lit_printer.type_to_str(), lit_printer.type_example_to_str()).as_slice());
  mlit
}

fn unknown_attribute(cx: &ExtCtxt, _meta_name: InternedString, span: Span)
{
  cx.span_err(span, "Unknown attribute.");
  // model.doc_approaching_results(cx, context, meta_name, span);
}
<|endoftext|>