<commit_before>//! This module contains traits that are usable with the `#[derive(...)].`
//! macros in [`clap_derive`].

use crate::{App, ArgMatches, Error};

use std::ffi::OsString;

/// Parse command-line arguments into `Self`.
///
/// The primary one-stop-shop trait used to create an instance of a `clap`
/// [`App`], conduct the parsing, and turn the resulting [`ArgMatches`] back
/// into concrete instance of the user struct.
///
/// This trait is primarily a convenience on top of [`FromArgMatches`] +
/// [`IntoApp`] which uses those two underlying traits to build the two
/// fundamental functions `parse` which uses the `std::env::args_os` iterator,
/// and `parse_from` which allows the consumer to supply the iterator (along
/// with fallible options for each).
///
/// See also [`Subcommand`] and [`Args`].
///
/// # Examples
///
/// The following example creates a `Context` struct that would be used
/// throughout the application representing the normalized values coming from
/// the CLI.
///
/// ```rust
/// # use clap::{Clap};
/// /// My super CLI
/// #[derive(Clap)]
/// #[clap(name = "demo")]
/// struct Context {
///     /// More verbose output
///     #[clap(long)]
///     verbose: bool,
///     /// An optional name
///     #[clap(short, long)]
///     name: Option<String>,
/// }
/// ```
///
/// The equivalent [`App`] struct + `From` implementation:
///
/// ```rust
/// # use clap::{App, Arg, ArgMatches};
/// App::new("demo")
///     .about("My super CLI")
///     .arg(Arg::new("verbose")
///         .long("verbose")
///         .about("More verbose output"))
///     .arg(Arg::new("name")
///         .long("name")
///         .short('n')
///         .about("An optional name")
///         .takes_value(true));
///
/// struct Context {
///     verbose: bool,
///     name: Option<String>,
/// }
///
/// impl From<ArgMatches> for Context {
///     fn from(m: ArgMatches) -> Self {
///         Context {
///             verbose: m.is_present("verbose"),
///             name: m.value_of("name").map(|n| n.to_owned()),
///         }
///     }
/// }
/// ```
///
pub trait Clap: FromArgMatches + IntoApp + Sized {
    /// Parse from `std::env::args_os()`, exit on error
    fn parse() -> Self {
        let matches = <Self as IntoApp>::into_app().get_matches();
        <Self as FromArgMatches>::from_arg_matches(&matches).expect("IntoApp validated everything")
    }

    /// Parse from `std::env::args_os()`, return Err on error.
    fn try_parse() -> Result<Self, Error> {
        let matches = <Self as IntoApp>::into_app().try_get_matches()?;
        Ok(<Self as FromArgMatches>::from_arg_matches(&matches)
            .expect("IntoApp validated everything"))
    }

    /// Parse from iterator, exit on error
    fn parse_from<I, T>(itr: I) -> Self
    where
        I: IntoIterator<Item = T>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        T: Into<OsString> + Clone,
    {
        let matches = <Self as IntoApp>::into_app().get_matches_from(itr);
        <Self as FromArgMatches>::from_arg_matches(&matches).expect("IntoApp validated everything")
    }

    /// Parse from iterator, return Err on error.
    fn try_parse_from<I, T>(itr: I) -> Result<Self, Error>
    where
        I: IntoIterator<Item = T>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        T: Into<OsString> + Clone,
    {
        let matches = <Self as IntoApp>::into_app().try_get_matches_from(itr)?;
        Ok(<Self as FromArgMatches>::from_arg_matches(&matches)
            .expect("IntoApp validated everything"))
    }

    /// Update from iterator, exit on error
    fn update_from<I, T>(&mut self, itr: I)
    where
        I: IntoIterator<Item = T>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        T: Into<OsString> + Clone,
    {
        // TODO find a way to get partial matches
        let matches = <Self as IntoApp>::into_app_for_update().get_matches_from(itr);
        <Self as FromArgMatches>::update_from_arg_matches(self, &matches);
    }

    /// Update from iterator, return Err on error.
    fn try_update_from<I, T>(&mut self, itr: I) -> Result<(), Error>
    where
        I: IntoIterator<Item = T>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        T: Into<OsString> + Clone,
    {
        let matches = <Self as IntoApp>::into_app_for_update().try_get_matches_from(itr)?;
        <Self as FromArgMatches>::update_from_arg_matches(self, &matches);
        Ok(())
    }
}

/// Build an [`App`] relevant for a user-defined container.
pub trait IntoApp: Sized {
    /// Build an [`App`] that can instantiate `Self`.
    ///
    /// See [`FromArgMatches::from_arg_matches`] for instantiating `Self`.
    fn into_app<'help>() -> App<'help>;
    /// Build an [`App`] that can update `self`.
    ///
    /// See [`FromArgMatches::update_from_arg_matches`] for updating `self`.
    fn into_app_for_update<'help>() -> App<'help>;
}

/// Converts an instance of [`ArgMatches`] to a user-defined container.
pub trait FromArgMatches: Sized {
    /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed.
    ///
    /// Motivation: If our application had two CLI options, `--name
    /// <STRING>` and the flag `--debug`, we may create a struct as follows:
    ///
    /// ```no_run
    /// struct Context {
    ///     name: String,
    ///     debug: bool
    /// }
    /// ```
    ///
    /// We then need to convert the `ArgMatches` that `clap` generated into our struct.
    /// `from_arg_matches` serves as the equivalent of:
    ///
    /// ```no_run
    /// # use clap::ArgMatches;
    /// # struct Context {
    /// #   name: String,
    /// #   debug: bool
    /// # }
    /// impl From<ArgMatches> for Context {
    ///    fn from(m: ArgMatches) -> Self {
    ///        Context {
    ///            name: m.value_of("name").unwrap().to_string(),
    ///            debug: m.is_present("debug"),
    ///        }
    ///    }
    /// }
    /// ```
    fn from_arg_matches(matches: &ArgMatches) -> Option<Self>;

    /// Assign values from `ArgMatches` to `self`.
    fn update_from_arg_matches(&mut self, matches: &ArgMatches);
}

/// Parse arguments into a user-defined container.
///
/// Implementing this trait lets a parent container delegate argument parsing behavior to `Self`.
/// with:
/// - `#[clap(flatten)] args: ChildArgs`: Attribute can only be used with struct fields that impl
///   `Args`.
/// - `Variant(ChildArgs)`: No attribute is used with enum variants that impl `Args`.
///
///
/// # Example
///
/// ```rust
/// #[derive(clap::Clap)]
/// struct Args {
///     #[clap(flatten)]
///     logging: LogArgs,
/// }
///
/// #[derive(clap::Args)]
/// struct LogArgs {
///     #[clap(long, short = 'v', parse(from_occurrences))]
///     verbose: i8,
/// }
/// ```
pub trait Args: FromArgMatches + Sized {
    /// Append to [`App`] so it can instantiate `Self`.
    ///
    /// See also [`IntoApp`].
    fn augment_args(app: App<'_>) -> App<'_>;
    /// Append to [`App`] so it can update `self`.
    ///
    /// This is used to implement `#[clap(flatten)]`
    ///
    /// See also [`IntoApp`].
    fn augment_args_for_update(app: App<'_>) -> App<'_>;
}

/// Parse a sub-command into a user-defined enum.
///
/// Implementing this trait let's a parent container delegate subcommand behavior to `Self`.
/// with:
/// - `#[clap(subcommand)] field: SubCmd`: Attribute can be used with either struct fields or enum
///   variants that impl `Subcommand`.
/// - `#[clap(flatten)] Variant(SubCmd)`: Attribute can only be used with enum variants that impl
///   `Subcommand`.
///
/// # Example
///
/// ```rust
/// #[derive(clap::Clap)]
/// struct Args {
///     #[clap(subcommand)]
///     action: Action,
/// }
///
/// #[derive(clap::Subcommand)]
/// enum Action {
///     Add,
///     Remove,
/// }
/// ```
pub trait Subcommand: FromArgMatches + Sized {
    /// Append to [`App`] so it can instantiate `Self`.
    ///
    /// See also [`IntoApp`].
    fn augment_subcommands(app: App<'_>) -> App<'_>;
    /// Append to [`App`] so it can update `self`.
    ///
    /// This is used to implement `#[clap(flatten)]`
    ///
    /// See also [`IntoApp`].
    fn augment_subcommands_for_update(app: App<'_>) -> App<'_>;
    /// Test whether `Self` can parse a specific subcommand
    fn has_subcommand(name: &str) -> bool;
}

/// Parse arguments into enums.
///
/// When deriving [`Clap`], a field whose type implements `ArgEnum` can have the attribute
/// `#[clap(arg_enum)]`.  In addition to parsing, help and error messages may report possible
/// variants.
///
/// # Example
///
/// ```rust
/// #[derive(clap::Clap)]
/// struct Args {
///     #[clap(arg_enum)]
///     level: Level,
/// }
///
/// #[derive(clap::ArgEnum)]
/// enum Level {
///     Debug,
///     Info,
///     Warning,
///     Error,
/// }
/// ```
pub trait ArgEnum: Sized {
    /// All possible argument choices, in display order.
    const VARIANTS: &'static [&'static str];

    /// Parse an argument into `Self`.
    fn from_str(input: &str, case_insensitive: bool) -> Result<Self, String>;

    /// The canonical argument value.
    ///
    /// The value is `None` for skipped variants.
    fn as_arg(&self) -> Option<&'static str>;
}

impl<T: Clap> Clap for Box<T> {
    fn parse() -> Self {
        Box::new(<T as Clap>::parse())
    }

    fn try_parse() -> Result<Self, Error> {
        <T as Clap>::try_parse().map(Box::new)
    }

    fn parse_from<I, It>(itr: I) -> Self
    where
        I: IntoIterator<Item = It>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        It: Into<OsString> + Clone,
    {
        Box::new(<T as Clap>::parse_from(itr))
    }

    fn try_parse_from<I, It>(itr: I) -> Result<Self, Error>
    where
        I: IntoIterator<Item = It>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        It: Into<OsString> + Clone,
    {
        <T as Clap>::try_parse_from(itr).map(Box::new)
    }
}

impl<T: IntoApp> IntoApp for Box<T> {
    fn into_app<'help>() -> App<'help> {
        <T as IntoApp>::into_app()
    }
    fn into_app_for_update<'help>() -> App<'help> {
        <T as IntoApp>::into_app_for_update()
    }
}

impl<T: FromArgMatches> FromArgMatches for Box<T> {
    fn from_arg_matches(matches: &ArgMatches) -> Option<Self> {
        <T as FromArgMatches>::from_arg_matches(matches).map(Box::new)
    }
    fn update_from_arg_matches(&mut self, matches: &ArgMatches) {
        <T as FromArgMatches>::update_from_arg_matches(self, matches)
    }
}

impl<T: Args> Args for Box<T> {
    fn augment_args(app: App<'_>) -> App<'_> {
        <T as Args>::augment_args(app)
    }
    fn augment_args_for_update(app: App<'_>) -> App<'_> {
        <T as Args>::augment_args_for_update(app)
    }
}

impl<T: Subcommand> Subcommand for Box<T> {
    fn augment_subcommands(app: App<'_>) -> App<'_> {
        <T as Subcommand>::augment_subcommands(app)
    }
    fn augment_subcommands_for_update(app: App<'_>) -> App<'_> {
        <T as Subcommand>::augment_subcommands_for_update(app)
    }
    fn has_subcommand(name: &str) -> bool {
        <T as Subcommand>::has_subcommand(name)
    }
}
<commit_msg>fix typo<commit_after>//! This module contains traits that are usable with the `#[derive(...)].`
//! macros in [`clap_derive`].

use crate::{App, ArgMatches, Error};

use std::ffi::OsString;

/// Parse command-line arguments into `Self`.
///
/// The primary one-stop-shop trait used to create an instance of a `clap`
/// [`App`], conduct the parsing, and turn the resulting [`ArgMatches`] back
/// into concrete instance of the user struct.
///
/// This trait is primarily a convenience on top of [`FromArgMatches`] +
/// [`IntoApp`] which uses those two underlying traits to build the two
/// fundamental functions `parse` which uses the `std::env::args_os` iterator,
/// and `parse_from` which allows the consumer to supply the iterator (along
/// with fallible options for each).
///
/// See also [`Subcommand`] and [`Args`].
///
/// # Examples
///
/// The following example creates a `Context` struct that would be used
/// throughout the application representing the normalized values coming from
/// the CLI.
///
/// ```rust
/// # use clap::{Clap};
/// /// My super CLI
/// #[derive(Clap)]
/// #[clap(name = "demo")]
/// struct Context {
///     /// More verbose output
///     #[clap(long)]
///     verbose: bool,
///     /// An optional name
///     #[clap(short, long)]
///     name: Option<String>,
/// }
/// ```
///
/// The equivalent [`App`] struct + `From` implementation:
///
/// ```rust
/// # use clap::{App, Arg, ArgMatches};
/// App::new("demo")
///     .about("My super CLI")
///     .arg(Arg::new("verbose")
///         .long("verbose")
///         .about("More verbose output"))
///     .arg(Arg::new("name")
///         .long("name")
///         .short('n')
///         .about("An optional name")
///         .takes_value(true));
///
/// struct Context {
///     verbose: bool,
///     name: Option<String>,
/// }
///
/// impl From<ArgMatches> for Context {
///     fn from(m: ArgMatches) -> Self {
///         Context {
///             verbose: m.is_present("verbose"),
///             name: m.value_of("name").map(|n| n.to_owned()),
///         }
///     }
/// }
/// ```
///
pub trait Clap: FromArgMatches + IntoApp + Sized {
    /// Parse from `std::env::args_os()`, exit on error
    fn parse() -> Self {
        let matches = <Self as IntoApp>::into_app().get_matches();
        <Self as FromArgMatches>::from_arg_matches(&matches).expect("IntoApp validated everything")
    }

    /// Parse from `std::env::args_os()`, return Err on error.
    fn try_parse() -> Result<Self, Error> {
        let matches = <Self as IntoApp>::into_app().try_get_matches()?;
        Ok(<Self as FromArgMatches>::from_arg_matches(&matches)
            .expect("IntoApp validated everything"))
    }

    /// Parse from iterator, exit on error
    fn parse_from<I, T>(itr: I) -> Self
    where
        I: IntoIterator<Item = T>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        T: Into<OsString> + Clone,
    {
        let matches = <Self as IntoApp>::into_app().get_matches_from(itr);
        <Self as FromArgMatches>::from_arg_matches(&matches).expect("IntoApp validated everything")
    }

    /// Parse from iterator, return Err on error.
    fn try_parse_from<I, T>(itr: I) -> Result<Self, Error>
    where
        I: IntoIterator<Item = T>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        T: Into<OsString> + Clone,
    {
        let matches = <Self as IntoApp>::into_app().try_get_matches_from(itr)?;
        Ok(<Self as FromArgMatches>::from_arg_matches(&matches)
            .expect("IntoApp validated everything"))
    }

    /// Update from iterator, exit on error
    fn update_from<I, T>(&mut self, itr: I)
    where
        I: IntoIterator<Item = T>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        T: Into<OsString> + Clone,
    {
        // TODO find a way to get partial matches
        let matches = <Self as IntoApp>::into_app_for_update().get_matches_from(itr);
        <Self as FromArgMatches>::update_from_arg_matches(self, &matches);
    }

    /// Update from iterator, return Err on error.
    fn try_update_from<I, T>(&mut self, itr: I) -> Result<(), Error>
    where
        I: IntoIterator<Item = T>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        T: Into<OsString> + Clone,
    {
        let matches = <Self as IntoApp>::into_app_for_update().try_get_matches_from(itr)?;
        <Self as FromArgMatches>::update_from_arg_matches(self, &matches);
        Ok(())
    }
}

/// Build an [`App`] relevant for a user-defined container.
pub trait IntoApp: Sized {
    /// Build an [`App`] that can instantiate `Self`.
    ///
    /// See [`FromArgMatches::from_arg_matches`] for instantiating `Self`.
    fn into_app<'help>() -> App<'help>;
    /// Build an [`App`] that can update `self`.
    ///
    /// See [`FromArgMatches::update_from_arg_matches`] for updating `self`.
    fn into_app_for_update<'help>() -> App<'help>;
}

/// Converts an instance of [`ArgMatches`] to a user-defined container.
pub trait FromArgMatches: Sized {
    /// Instantiate `Self` from [`ArgMatches`], parsing the arguments as needed.
    ///
    /// Motivation: If our application had two CLI options, `--name
    /// <STRING>` and the flag `--debug`, we may create a struct as follows:
    ///
    /// ```no_run
    /// struct Context {
    ///     name: String,
    ///     debug: bool
    /// }
    /// ```
    ///
    /// We then need to convert the `ArgMatches` that `clap` generated into our struct.
    /// `from_arg_matches` serves as the equivalent of:
    ///
    /// ```no_run
    /// # use clap::ArgMatches;
    /// # struct Context {
    /// #   name: String,
    /// #   debug: bool
    /// # }
    /// impl From<ArgMatches> for Context {
    ///    fn from(m: ArgMatches) -> Self {
    ///        Context {
    ///            name: m.value_of("name").unwrap().to_string(),
    ///            debug: m.is_present("debug"),
    ///        }
    ///    }
    /// }
    /// ```
    fn from_arg_matches(matches: &ArgMatches) -> Option<Self>;

    /// Assign values from `ArgMatches` to `self`.
    fn update_from_arg_matches(&mut self, matches: &ArgMatches);
}

/// Parse arguments into a user-defined container.
///
/// Implementing this trait lets a parent container delegate argument parsing behavior to `Self`.
/// with:
/// - `#[clap(flatten)] args: ChildArgs`: Attribute can only be used with struct fields that impl
///   `Args`.
/// - `Variant(ChildArgs)`: No attribute is used with enum variants that impl `Args`.
///
///
/// # Example
///
/// ```rust
/// #[derive(clap::Clap)]
/// struct Args {
///     #[clap(flatten)]
///     logging: LogArgs,
/// }
///
/// #[derive(clap::Args)]
/// struct LogArgs {
///     #[clap(long, short = 'v', parse(from_occurrences))]
///     verbose: i8,
/// }
/// ```
pub trait Args: FromArgMatches + Sized {
    /// Append to [`App`] so it can instantiate `Self`.
    ///
    /// See also [`IntoApp`].
    fn augment_args(app: App<'_>) -> App<'_>;
    /// Append to [`App`] so it can update `self`.
    ///
    /// This is used to implement `#[clap(flatten)]`
    ///
    /// See also [`IntoApp`].
    fn augment_args_for_update(app: App<'_>) -> App<'_>;
}

/// Parse a sub-command into a user-defined enum.
///
/// Implementing this trait lets a parent container delegate subcommand behavior to `Self`.
/// with:
/// - `#[clap(subcommand)] field: SubCmd`: Attribute can be used with either struct fields or enum
///   variants that impl `Subcommand`.
/// - `#[clap(flatten)] Variant(SubCmd)`: Attribute can only be used with enum variants that impl
///   `Subcommand`.
///
/// # Example
///
/// ```rust
/// #[derive(clap::Clap)]
/// struct Args {
///     #[clap(subcommand)]
///     action: Action,
/// }
///
/// #[derive(clap::Subcommand)]
/// enum Action {
///     Add,
///     Remove,
/// }
/// ```
pub trait Subcommand: FromArgMatches + Sized {
    /// Append to [`App`] so it can instantiate `Self`.
    ///
    /// See also [`IntoApp`].
    fn augment_subcommands(app: App<'_>) -> App<'_>;
    /// Append to [`App`] so it can update `self`.
    ///
    /// This is used to implement `#[clap(flatten)]`
    ///
    /// See also [`IntoApp`].
    fn augment_subcommands_for_update(app: App<'_>) -> App<'_>;
    /// Test whether `Self` can parse a specific subcommand
    fn has_subcommand(name: &str) -> bool;
}

/// Parse arguments into enums.
///
/// When deriving [`Clap`], a field whose type implements `ArgEnum` can have the attribute
/// `#[clap(arg_enum)]`.  In addition to parsing, help and error messages may report possible
/// variants.
///
/// # Example
///
/// ```rust
/// #[derive(clap::Clap)]
/// struct Args {
///     #[clap(arg_enum)]
///     level: Level,
/// }
///
/// #[derive(clap::ArgEnum)]
/// enum Level {
///     Debug,
///     Info,
///     Warning,
///     Error,
/// }
/// ```
pub trait ArgEnum: Sized {
    /// All possible argument choices, in display order.
    const VARIANTS: &'static [&'static str];

    /// Parse an argument into `Self`.
    fn from_str(input: &str, case_insensitive: bool) -> Result<Self, String>;

    /// The canonical argument value.
    ///
    /// The value is `None` for skipped variants.
    fn as_arg(&self) -> Option<&'static str>;
}

impl<T: Clap> Clap for Box<T> {
    fn parse() -> Self {
        Box::new(<T as Clap>::parse())
    }

    fn try_parse() -> Result<Self, Error> {
        <T as Clap>::try_parse().map(Box::new)
    }

    fn parse_from<I, It>(itr: I) -> Self
    where
        I: IntoIterator<Item = It>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        It: Into<OsString> + Clone,
    {
        Box::new(<T as Clap>::parse_from(itr))
    }

    fn try_parse_from<I, It>(itr: I) -> Result<Self, Error>
    where
        I: IntoIterator<Item = It>,
        // TODO (@CreepySkeleton): discover a way to avoid cloning here
        It: Into<OsString> + Clone,
    {
        <T as Clap>::try_parse_from(itr).map(Box::new)
    }
}

impl<T: IntoApp> IntoApp for Box<T> {
    fn into_app<'help>() -> App<'help> {
        <T as IntoApp>::into_app()
    }
    fn into_app_for_update<'help>() -> App<'help> {
        <T as IntoApp>::into_app_for_update()
    }
}

impl<T: FromArgMatches> FromArgMatches for Box<T> {
    fn from_arg_matches(matches: &ArgMatches) -> Option<Self> {
        <T as FromArgMatches>::from_arg_matches(matches).map(Box::new)
    }
    fn update_from_arg_matches(&mut self, matches: &ArgMatches) {
        <T as FromArgMatches>::update_from_arg_matches(self, matches)
    }
}

impl<T: Args> Args for Box<T> {
    fn augment_args(app: App<'_>) -> App<'_> {
        <T as Args>::augment_args(app)
    }
    fn augment_args_for_update(app: App<'_>) -> App<'_> {
        <T as Args>::augment_args_for_update(app)
    }
}

impl<T: Subcommand> Subcommand for Box<T> {
    fn augment_subcommands(app: App<'_>) -> App<'_> {
        <T as Subcommand>::augment_subcommands(app)
    }
    fn augment_subcommands_for_update(app: App<'_>) -> App<'_> {
        <T as Subcommand>::augment_subcommands_for_update(app)
    }
    fn has_subcommand(name: &str) -> bool {
        <T as Subcommand>::has_subcommand(name)
    }
}
<|endoftext|>


<commit_before>use memchr::memchr;
use memchr::memchr2;

use email::EmailScanner;
use scanner::Scanner;
use url::UrlScanner;

/// A link found in the input text.
#[derive(Debug)]
pub struct Link<'t> {
    text: &'t str,
    start: usize,
    end: usize,
    kind: LinkKind,
}

impl<'t> Link<'t> {
    /// The start index of the link within the input text.
    #[inline]
    pub fn start(&self) -> usize {
        self.start
    }

    /// The end index of the link.
    #[inline]
    pub fn end(&self) -> usize {
        self.end
    }

    /// Get the link text as a `str`.
    #[inline]
    pub fn as_str(&self) -> &'t str {
        &self.text[self.start..self.end]
    }

    /// The type of the link.
    #[inline]
    pub fn kind(&self) -> &LinkKind {
        &self.kind
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum LinkKind {
    /// URL links like "http://example.org".
    Url,
    /// E-mail links like "foo@example.org"
    Email,
    /// Users should not exhaustively match this enum, because more link types
    /// may be added in the future.
    #[doc(hidden)]
    __Nonexhaustive,
}

/// A configured link finder.
pub struct LinkFinder {
    email: bool,
    email_domain_must_have_dot: bool,
    url: bool,
}

/// Iterator for finding links.
pub struct Links<'t> {
    text: &'t str,
    rewind: usize,

    trigger_finder: Box<Fn(&[u8]) -> Option<usize>>,
    email_scanner: EmailScanner,
    url_scanner: UrlScanner,
}

impl LinkFinder {
    /// Create a new link finder with the default options for finding all kinds
    /// of links.
    ///
    /// If you only want to find a certain kind of links, use the `kinds` method.
    pub fn new() -> LinkFinder {
        LinkFinder {
            email: true,
            email_domain_must_have_dot: true,
            url: true,
        }
    }

    /// Require the domain parts of email addresses to have at least one dot.
    /// Use `false` to also find addresses such as `root@localhost`.
    pub fn email_domain_must_have_dot(&mut self, value: bool) -> &mut LinkFinder {
        self.email_domain_must_have_dot = value;
        self
    }

    /// Restrict the kinds of links that should be found to the specified ones.
    pub fn kinds(&mut self, kinds: &[LinkKind]) -> &mut LinkFinder {
        self.email = false;
        self.url = false;
        for kind in kinds {
            match *kind {
                LinkKind::Email => self.email = true,
                LinkKind::Url => self.url = true,
                _ => {}
            }
        }
        self
    }

    /// Find links in the specified input text.
    ///
    /// Returns an `Iterator` which only scans when `next` is called (lazy).
    pub fn links<'t>(&self, text: &'t str) -> Links<'t> {
        Links::new(text, self.url, self.email, self.email_domain_must_have_dot)
    }
}

impl<'t> Links<'t> {
    fn new(text: &'t str, url: bool, email: bool, email_domain_must_have_dot: bool) -> Links<'t> {
        let url_scanner = UrlScanner {};
        let email_scanner = EmailScanner { domain_must_have_dot: email_domain_must_have_dot };
        let trigger_finder: Box<Fn(&[u8]) -> Option<usize>> = match (url, email) {
            (true, true) => Box::new(|s| memchr2(b':', b'@', s)),
            (true, false) => Box::new(|s| memchr(b':', s)),
            (false, true) => Box::new(|s| memchr(b'@', s)),
            (false, false) => Box::new(|_| None),
        };
        Links {
            text: text,
            rewind: 0,
            trigger_finder: trigger_finder,
            email_scanner: email_scanner,
            url_scanner: url_scanner,
        }
    }
}

impl<'t> Iterator for Links<'t> {
    type Item = Link<'t>;

    fn next(&mut self) -> Option<Link<'t>> {
        let slice = &self.text[self.rewind..];

        let mut find_from = 0;
        while let Some(i) = (self.trigger_finder)(slice[find_from..].as_bytes()) {
            let trigger = slice.as_bytes()[find_from + i];
            let (scanner, kind): (&Scanner, LinkKind) = match trigger {
                b':' => (&self.url_scanner, LinkKind::Url),
                b'@' => (&self.email_scanner, LinkKind::Email),
                _ => panic!("TODO"),
            };
            if let Some(range) = scanner.scan(slice, find_from + i) {
                let start = self.rewind + range.start;
                let end = self.rewind + range.end;
                self.rewind = end;
                let link = Link {
                    text: &self.text,
                    start: start,
                    end: end,
                    kind: kind,
                };
                return Some(link);
            } else {
                // The scanner didn't find anything. But there could be more
                // trigger characters later, so continue the search.
                find_from += i + 1;
            }
        }

        return None;
    }
}
<commit_msg>Replace TODO by unreachable!<commit_after>use memchr::memchr;
use memchr::memchr2;

use email::EmailScanner;
use scanner::Scanner;
use url::UrlScanner;

/// A link found in the input text.
#[derive(Debug)]
pub struct Link<'t> {
    text: &'t str,
    start: usize,
    end: usize,
    kind: LinkKind,
}

impl<'t> Link<'t> {
    /// The start index of the link within the input text.
    #[inline]
    pub fn start(&self) -> usize {
        self.start
    }

    /// The end index of the link.
    #[inline]
    pub fn end(&self) -> usize {
        self.end
    }

    /// Get the link text as a `str`.
    #[inline]
    pub fn as_str(&self) -> &'t str {
        &self.text[self.start..self.end]
    }

    /// The type of the link.
    #[inline]
    pub fn kind(&self) -> &LinkKind {
        &self.kind
    }
}

#[derive(Debug, Eq, PartialEq)]
pub enum LinkKind {
    /// URL links like "http://example.org".
    Url,
    /// E-mail links like "foo@example.org"
    Email,
    /// Users should not exhaustively match this enum, because more link types
    /// may be added in the future.
    #[doc(hidden)]
    __Nonexhaustive,
}

/// A configured link finder.
pub struct LinkFinder {
    email: bool,
    email_domain_must_have_dot: bool,
    url: bool,
}

/// Iterator for finding links.
pub struct Links<'t> {
    text: &'t str,
    rewind: usize,

    trigger_finder: Box<Fn(&[u8]) -> Option<usize>>,
    email_scanner: EmailScanner,
    url_scanner: UrlScanner,
}

impl LinkFinder {
    /// Create a new link finder with the default options for finding all kinds
    /// of links.
    ///
    /// If you only want to find a certain kind of links, use the `kinds` method.
    pub fn new() -> LinkFinder {
        LinkFinder {
            email: true,
            email_domain_must_have_dot: true,
            url: true,
        }
    }

    /// Require the domain parts of email addresses to have at least one dot.
    /// Use `false` to also find addresses such as `root@localhost`.
    pub fn email_domain_must_have_dot(&mut self, value: bool) -> &mut LinkFinder {
        self.email_domain_must_have_dot = value;
        self
    }

    /// Restrict the kinds of links that should be found to the specified ones.
    pub fn kinds(&mut self, kinds: &[LinkKind]) -> &mut LinkFinder {
        self.email = false;
        self.url = false;
        for kind in kinds {
            match *kind {
                LinkKind::Email => self.email = true,
                LinkKind::Url => self.url = true,
                _ => {}
            }
        }
        self
    }

    /// Find links in the specified input text.
    ///
    /// Returns an `Iterator` which only scans when `next` is called (lazy).
    pub fn links<'t>(&self, text: &'t str) -> Links<'t> {
        Links::new(text, self.url, self.email, self.email_domain_must_have_dot)
    }
}

impl<'t> Links<'t> {
    fn new(text: &'t str, url: bool, email: bool, email_domain_must_have_dot: bool) -> Links<'t> {
        let url_scanner = UrlScanner {};
        let email_scanner = EmailScanner { domain_must_have_dot: email_domain_must_have_dot };
        let trigger_finder: Box<Fn(&[u8]) -> Option<usize>> = match (url, email) {
            (true, true) => Box::new(|s| memchr2(b':', b'@', s)),
            (true, false) => Box::new(|s| memchr(b':', s)),
            (false, true) => Box::new(|s| memchr(b'@', s)),
            (false, false) => Box::new(|_| None),
        };
        Links {
            text: text,
            rewind: 0,
            trigger_finder: trigger_finder,
            email_scanner: email_scanner,
            url_scanner: url_scanner,
        }
    }
}

impl<'t> Iterator for Links<'t> {
    type Item = Link<'t>;

    fn next(&mut self) -> Option<Link<'t>> {
        let slice = &self.text[self.rewind..];

        let mut find_from = 0;
        while let Some(i) = (self.trigger_finder)(slice[find_from..].as_bytes()) {
            let trigger = slice.as_bytes()[find_from + i];
            let (scanner, kind): (&Scanner, LinkKind) = match trigger {
                b':' => (&self.url_scanner, LinkKind::Url),
                b'@' => (&self.email_scanner, LinkKind::Email),
                _ => unreachable!(),
            };
            if let Some(range) = scanner.scan(slice, find_from + i) {
                let start = self.rewind + range.start;
                let end = self.rewind + range.end;
                self.rewind = end;
                let link = Link {
                    text: &self.text,
                    start: start,
                    end: end,
                    kind: kind,
                };
                return Some(link);
            } else {
                // The scanner didn't find anything. But there could be more
                // trigger characters later, so continue the search.
                find_from += i + 1;
            }
        }

        return None;
    }
}
<|endoftext|>


<commit_before>extern crate env_logger;
extern crate getopts;
#[macro_use]
extern crate log;
extern crate rustfmt_nightly as rustfmt;

use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;

use getopts::{Matches, Options};

use rustfmt::{run, Input};
use rustfmt::config;

fn prune_files<'a>(files: Vec<&'a str>) -> Vec<&'a str> {
    let prefixes: Vec<_> = files
        .iter()
        .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs"))
        .map(|f| &f[..f.len() - 6])
        .collect();

    let mut pruned_prefixes = vec![];
    for p1 in prefixes.into_iter() {
        let mut include = true;
        if !p1.starts_with("src/bin/") {
            for p2 in pruned_prefixes.iter() {
                if p1.starts_with(p2) {
                    include = false;
                    break;
                }
            }
        }
        if include {
            pruned_prefixes.push(p1);
        }
    }
    debug!("prefixes: {:?}", pruned_prefixes);

    files
        .into_iter()
        .filter(|f| {
            let mut include = true;
            if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") {
                return true;
            }
            for pp in pruned_prefixes.iter() {
                if f.starts_with(pp) {
                    include = false;
                    break;
                }
            }
            include
        })
        .collect()
}

fn git_diff(commits: String) -> String {
    let mut cmd = Command::new("git");
    cmd.arg("diff");
    if commits != "0" {
        cmd.arg(format!("HEAD~{}", commits));
    }
    let output = cmd.output().expect("Couldn't execute `git diff`");
    String::from_utf8_lossy(&output.stdout).into_owned()
}

fn get_files(input: &str) -> Vec<&str> {
    input
        .lines()
        .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs"))
        .map(|line| &line[6..])
        .collect()
}

fn fmt_files(files: &[&str]) -> i32 {
    let (config, _) = config::Config::from_resolved_toml_path(Path::new("."))
        .unwrap_or_else(|_| (config::Config::default(), None));

    let mut exit_code = 0;
    for file in files {
        let summary = run(Input::File(PathBuf::from(file)), &config);
        if !summary.has_no_errors() {
            exit_code = 1;
        }
    }
    exit_code
}

fn uncommitted_files() -> Vec<String> {
    let mut cmd = Command::new("git");
    cmd.arg("ls-files");
    cmd.arg("--others");
    cmd.arg("--modified");
    cmd.arg("--exclude-standard");
    let output = cmd.output().expect("Couldn't execute Git");
    let stdout = String::from_utf8_lossy(&output.stdout);
    stdout
        .lines()
        .filter(|s| s.ends_with(".rs"))
        .map(|s| s.to_owned())
        .collect()
}

fn check_uncommitted() {
    let uncommitted = uncommitted_files();
    debug!("uncommitted files: {:?}", uncommitted);
    if !uncommitted.is_empty() {
        println!("Found untracked changes:");
        for f in uncommitted.iter() {
            println!("  {}", f);
        }
        println!("Commit your work, or run with `-u`.");
        println!("Exiting.");
        std::process::exit(1);
    }
}

fn make_opts() -> Options {
    let mut opts = Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("c", "check", "check only, don't format (unimplemented)");
    opts.optflag("u", "uncommitted", "format uncommitted files");
    opts
}

struct Config {
    commits: String,
    uncommitted: bool,
    check: bool,
}

impl Config {
    fn from_args(matches: &Matches, opts: &Options) -> Config {
        // `--help` display help message and quit
        if matches.opt_present("h") {
            let message = format!(
                "\nusage: {} <commits> [options]\n\n\
                 commits: number of commits to format, default: 1",
                env::args_os().next().unwrap().to_string_lossy()
            );
            println!("{}", opts.usage(&message));
            std::process::exit(0);
        }

        let mut config = Config {
            commits: "1".to_owned(),
            uncommitted: false,
            check: false,
        };

        if matches.opt_present("c") {
            config.check = true;
            unimplemented!();
        }

        if matches.opt_present("u") {
            config.uncommitted = true;
        }

        if matches.free.len() > 1 {
            panic!("unknown arguments, use `-h` for usage");
        }
        if matches.free.len() == 1 {
            let commits = matches.free[0].trim();
            if let Err(_) = u32::from_str(&commits) {
                panic!("Couldn't parse number of commits");
            }
            config.commits = commits.to_owned();
        }

        config
    }
}

fn main() {
    let _ = env_logger::init();

    let opts = make_opts();
    let matches = opts.parse(env::args().skip(1))
        .expect("Couldn't parse command line");
    let config = Config::from_args(&matches, &opts);

    if !config.uncommitted {
        check_uncommitted();
    }

    let stdout = git_diff(config.commits);
    let files = get_files(&stdout);
    debug!("files: {:?}", files);
    let files = prune_files(files);
    debug!("pruned files: {:?}", files);
    let exit_code = fmt_files(&files);
    std::process::exit(exit_code);
}
<commit_msg>Cargo clippy<commit_after>extern crate env_logger;
extern crate getopts;
#[macro_use]
extern crate log;
extern crate rustfmt_nightly as rustfmt;

use std::env;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;

use getopts::{Matches, Options};

use rustfmt::{run, Input};
use rustfmt::config;

fn prune_files(files: Vec<&str>) -> Vec<&str> {
    let prefixes: Vec<_> = files
        .iter()
        .filter(|f| f.ends_with("mod.rs") || f.ends_with("lib.rs"))
        .map(|f| &f[..f.len() - 6])
        .collect();

    let mut pruned_prefixes = vec![];
    for p1 in prefixes {
        let mut include = true;
        if !p1.starts_with("src/bin/") {
            for p2 in &pruned_prefixes {
                if p1.starts_with(p2) {
                    include = false;
                    break;
                }
            }
        }
        if include {
            pruned_prefixes.push(p1);
        }
    }
    debug!("prefixes: {:?}", pruned_prefixes);

    files
        .into_iter()
        .filter(|f| {
            let mut include = true;
            if f.ends_with("mod.rs") || f.ends_with("lib.rs") || f.starts_with("src/bin/") {
                return true;
            }
            for pp in &pruned_prefixes {
                if f.starts_with(pp) {
                    include = false;
                    break;
                }
            }
            include
        })
        .collect()
}

fn git_diff(commits: &str) -> String {
    let mut cmd = Command::new("git");
    cmd.arg("diff");
    if commits != "0" {
        cmd.arg(format!("HEAD~{}", commits));
    }
    let output = cmd.output().expect("Couldn't execute `git diff`");
    String::from_utf8_lossy(&output.stdout).into_owned()
}

fn get_files(input: &str) -> Vec<&str> {
    input
        .lines()
        .filter(|line| line.starts_with("+++ b/") && line.ends_with(".rs"))
        .map(|line| &line[6..])
        .collect()
}

fn fmt_files(files: &[&str]) -> i32 {
    let (config, _) = config::Config::from_resolved_toml_path(Path::new("."))
        .unwrap_or_else(|_| (config::Config::default(), None));

    let mut exit_code = 0;
    for file in files {
        let summary = run(Input::File(PathBuf::from(file)), &config);
        if !summary.has_no_errors() {
            exit_code = 1;
        }
    }
    exit_code
}

fn uncommitted_files() -> Vec<String> {
    let mut cmd = Command::new("git");
    cmd.arg("ls-files");
    cmd.arg("--others");
    cmd.arg("--modified");
    cmd.arg("--exclude-standard");
    let output = cmd.output().expect("Couldn't execute Git");
    let stdout = String::from_utf8_lossy(&output.stdout);
    stdout
        .lines()
        .filter(|s| s.ends_with(".rs"))
        .map(|s| s.to_owned())
        .collect()
}

fn check_uncommitted() {
    let uncommitted = uncommitted_files();
    debug!("uncommitted files: {:?}", uncommitted);
    if !uncommitted.is_empty() {
        println!("Found untracked changes:");
        for f in &uncommitted {
            println!("  {}", f);
        }
        println!("Commit your work, or run with `-u`.");
        println!("Exiting.");
        std::process::exit(1);
    }
}

fn make_opts() -> Options {
    let mut opts = Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("c", "check", "check only, don't format (unimplemented)");
    opts.optflag("u", "uncommitted", "format uncommitted files");
    opts
}

struct Config {
    commits: String,
    uncommitted: bool,
    check: bool,
}

impl Config {
    fn from_args(matches: &Matches, opts: &Options) -> Config {
        // `--help` display help message and quit
        if matches.opt_present("h") {
            let message = format!(
                "\nusage: {} <commits> [options]\n\n\
                 commits: number of commits to format, default: 1",
                env::args_os().next().unwrap().to_string_lossy()
            );
            println!("{}", opts.usage(&message));
            std::process::exit(0);
        }

        let mut config = Config {
            commits: "1".to_owned(),
            uncommitted: false,
            check: false,
        };

        if matches.opt_present("c") {
            config.check = true;
            unimplemented!();
        }

        if matches.opt_present("u") {
            config.uncommitted = true;
        }

        if matches.free.len() > 1 {
            panic!("unknown arguments, use `-h` for usage");
        }
        if matches.free.len() == 1 {
            let commits = matches.free[0].trim();
            if u32::from_str(commits).is_err() {
                panic!("Couldn't parse number of commits");
            }
            config.commits = commits.to_owned();
        }

        config
    }
}

fn main() {
    let _ = env_logger::init();

    let opts = make_opts();
    let matches = opts.parse(env::args().skip(1))
        .expect("Couldn't parse command line");
    let config = Config::from_args(&matches, &opts);

    if !config.uncommitted {
        check_uncommitted();
    }

    let stdout = git_diff(&config.commits);
    let files = get_files(&stdout);
    debug!("files: {:?}", files);
    let files = prune_files(files);
    debug!("pruned files: {:?}", files);
    let exit_code = fmt_files(&files);
    std::process::exit(exit_code);
}
<|endoftext|>


<commit_before>//! A slow, but clear reference implementation of SeaHash.
//!
//! # Specification
//!
//! The input buffer is padded with null bytes until the length is divisible by 8.
//!
//! We start out with state
//!
//! ```notest
//! a = 0x16f11fe89b0d677c
//! b = 0xb480a793d8e6c86c
//! c = 0x6fe2e5aaf078ebc9
//! d = 0x14f994a4c5259381
//! ```
//!
//! If a seed is given, each of the initial state component are modularly multiplied by the seed.
//!
//! From the stream, we read one 64-bit block (in little-endian) at a time.  This number, `n`,
//! determines the new state by:
//!
//! ```notest
//! a' = b
//! b' = c
//! c' = d
//! d  = g(a ⊕ n)
//! ```
//!
//! `g(x)` is defined as `g(x) = j(h(j(x)))` with `h(x) = (x ≫ 32) ≫ (x ≫ 60)` and `j(x) ≡ px (mod
//! 2^64)` with `p = 0x7ed0e9fa0d94a33`.
//!
//! Let the final state be `(x, y, z, w)`. Then the final result is given by `H = g(x ⊕ y ⊕ z ⊕ w ⊕
//! l)` where `l` is the number of bytes in the original buffer.

use helper;

/// Read an integer in little-endian.
fn read_int(int: &[u8]) -> u64 {
    debug_assert!(int.len() <= 8, "The buffer length of the integer must be less than or equal to \
                  the one of an u64.");

    // Start at 0.
    let mut x = 0;
    for &i in int.iter().rev() {
        // Shift up a byte.
        x <<= 8;
        // Set the lower byte.
        x |= i as u64;
    }

    x
}

/// A hash state.
struct State {
    /// The `a` substate.
    a: u64,
    /// The `b` substate.
    b: u64,
    /// The `c` substate.
    c: u64,
    /// The `d` substate.
    d: u64,
}

impl State {
    /// Write a 64-bit integer to the state.
    fn write_u64(&mut self, x: u64) {
        let mut a = self.a;

        // Mix `x` into `a`.
        a = helper::diffuse(a ^ x);

        //  Rotate around.
        //  _______________________
        // |                       v
        // a <---- b <---- c <---- d
        self.a = self.b;
        self.b = self.c;
        self.c = self.d;
        self.d = a;
    }

    /// Calculate the final hash.
    fn finish(self, total: usize) -> u64 {
        // Even though XORing is commutative, it doesn't matter, because the state vector's initial
        // components are mutually distinct, and thus swapping even and odd chunks will affect the
        // result, because it is sensitive to the initial condition. To add discreteness, we
        // diffuse.
        helper::diffuse(
            self.a ^ self.b ^ self.c ^ self.d
            // We XOR in the number of written bytes to make it zero-sensitive when excessive bytes
            // are written (0u32.0u8 ≠ 0u16.0u8).
            ^ total as u64
        )
    }

    /// Create a new state with some initial values (seed).
    fn with_seeds(k1: u64, k2: u64, k3: u64, k4: u64) -> State {
        State {
            // These values are randomly generated.
            a: k1,
            b: k2,
            c: k3,
            d: k4,
        }
    }
}

/// A reference implementation of SeaHash.
///
/// This is bloody slow when compared to the optimized version. This is because SeaHash was
/// specifically designed to take all sorts of hardware and software hacks into account to achieve
/// maximal performance, but this makes code significantly less readable. As such, this version has
/// only one goal: to make the algorithm readable and understandable.
pub fn hash(buf: &[u8]) -> u64 {
    hash_seeded(
        buf,
        0x16f11fe89b0d677c,
        0xb480a793d8e6c86c,
        0x6fe2e5aaf078ebc9,
        0x14f994a4c5259381
    )
}

/// The seeded version of the reference implementation.
pub fn hash_seeded(buf: &[u8], k1: u64, k2: u64, k3: u64, k4: u64) -> u64 {
    // Initialize the state.
    let mut state = State::with_seeds(k1, k2, k3, k4);

    // Partition the rounded down buffer into chunks of 8 bytes, and iterate over them. The last
    // block might not be 8 bytes long.
    for int in buf.chunks(8) {
        // Read the chunk into an integer and write into the state.
        state.write_u64(read_int(int));
    }

    // Finish the hash state and return the final value.
    state.finish(buf.len())
}

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

    #[test]
    fn shakespear() {
        assert_eq!(hash(b"to be or not to be"), 1988685042348123509);
    }
}
<commit_msg>Fix typo in SeaHash docs.<commit_after>//! A slow, but clear reference implementation of SeaHash.
//!
//! # Specification
//!
//! The input buffer is padded with null bytes until the length is divisible by 8.
//!
//! We start out with state
//!
//! ```notest
//! a = 0x16f11fe89b0d677c
//! b = 0xb480a793d8e6c86c
//! c = 0x6fe2e5aaf078ebc9
//! d = 0x14f994a4c5259381
//! ```
//!
//! If a seed is given, each of the initial state component are modularly multiplied by the seed.
//!
//! From the stream, we read one 64-bit block (in little-endian) at a time.  This number, `n`,
//! determines the new state by:
//!
//! ```notest
//! a' = b
//! b' = c
//! c' = d
//! d' = g(a ⊕ n)
//! ```
//!
//! `g(x)` is defined as `g(x) = j(h(j(x)))` with `h(x) = (x ≫ 32) ≫ (x ≫ 60)` and `j(x) ≡ px (mod
//! 2^64)` with `p = 0x7ed0e9fa0d94a33`.
//!
//! Let the final state be `(x, y, z, w)`. Then the final result is given by `H = g(x ⊕ y ⊕ z ⊕ w ⊕
//! l)` where `l` is the number of bytes in the original buffer.

use helper;

/// Read an integer in little-endian.
fn read_int(int: &[u8]) -> u64 {
    debug_assert!(int.len() <= 8, "The buffer length of the integer must be less than or equal to \
                  the one of an u64.");

    // Start at 0.
    let mut x = 0;
    for &i in int.iter().rev() {
        // Shift up a byte.
        x <<= 8;
        // Set the lower byte.
        x |= i as u64;
    }

    x
}

/// A hash state.
struct State {
    /// The `a` substate.
    a: u64,
    /// The `b` substate.
    b: u64,
    /// The `c` substate.
    c: u64,
    /// The `d` substate.
    d: u64,
}

impl State {
    /// Write a 64-bit integer to the state.
    fn write_u64(&mut self, x: u64) {
        let mut a = self.a;

        // Mix `x` into `a`.
        a = helper::diffuse(a ^ x);

        //  Rotate around.
        //  _______________________
        // |                       v
        // a <---- b <---- c <---- d
        self.a = self.b;
        self.b = self.c;
        self.c = self.d;
        self.d = a;
    }

    /// Calculate the final hash.
    fn finish(self, total: usize) -> u64 {
        // Even though XORing is commutative, it doesn't matter, because the state vector's initial
        // components are mutually distinct, and thus swapping even and odd chunks will affect the
        // result, because it is sensitive to the initial condition. To add discreteness, we
        // diffuse.
        helper::diffuse(
            self.a ^ self.b ^ self.c ^ self.d
            // We XOR in the number of written bytes to make it zero-sensitive when excessive bytes
            // are written (0u32.0u8 ≠ 0u16.0u8).
            ^ total as u64
        )
    }

    /// Create a new state with some initial values (seed).
    fn with_seeds(k1: u64, k2: u64, k3: u64, k4: u64) -> State {
        State {
            // These values are randomly generated.
            a: k1,
            b: k2,
            c: k3,
            d: k4,
        }
    }
}

/// A reference implementation of SeaHash.
///
/// This is bloody slow when compared to the optimized version. This is because SeaHash was
/// specifically designed to take all sorts of hardware and software hacks into account to achieve
/// maximal performance, but this makes code significantly less readable. As such, this version has
/// only one goal: to make the algorithm readable and understandable.
pub fn hash(buf: &[u8]) -> u64 {
    hash_seeded(
        buf,
        0x16f11fe89b0d677c,
        0xb480a793d8e6c86c,
        0x6fe2e5aaf078ebc9,
        0x14f994a4c5259381
    )
}

/// The seeded version of the reference implementation.
pub fn hash_seeded(buf: &[u8], k1: u64, k2: u64, k3: u64, k4: u64) -> u64 {
    // Initialize the state.
    let mut state = State::with_seeds(k1, k2, k3, k4);

    // Partition the rounded down buffer into chunks of 8 bytes, and iterate over them. The last
    // block might not be 8 bytes long.
    for int in buf.chunks(8) {
        // Read the chunk into an integer and write into the state.
        state.write_u64(read_int(int));
    }

    // Finish the hash state and return the final value.
    state.finish(buf.len())
}

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

    #[test]
    fn shakespear() {
        assert_eq!(hash(b"to be or not to be"), 1988685042348123509);
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate kappa_lisp;
use kappa_lisp::{init, run_new, run, Env};
use kappa_lisp::util::*;

#[test]
fn test_atom(){
    assert_eq!(run_new("1"), Ok(kint(1)));
    assert_eq!(run_new("()"), Ok(knil()));
    assert_eq!(run_new(("t")), Ok(ksym("t")));
    assert_eq!(run_new("\"string\""), Ok(kstr("string".to_string())));
}
// TODO: test `function`

#[test]
fn test_progn(){
    assert_eq!(run_new("(progn 1 2)"), Ok(kint(2)));
    assert_eq!(run_new("(progn (+ 1 2) (+ 2 3))"), Ok(kint(5)));
}

#[test]
fn test_lambda(){
    assert_eq!(run_new(("(lambda (x) x)")), Ok(kproc(klambda(klist!(ksym("x")),
                                                                           klist!(ksym("progn"), ksym("x"))))));
    assert_eq!(run_new("((lambda (x) (+ x x)) 1)"), Ok(kint(2)))
}

#[test]
fn test_fset(){
    let mut env = Env::new();
    init(&mut env).unwrap();
    assert_eq!(run(&mut env, "(fset 'add2 (lambda (x) (+ x 2)))"), Ok(knil()));
    assert_eq!(run(&mut env, "(add2 2)"), Ok(kint(4)));
}

#[test]
fn test_set() {
    let mut env = Env::new();
    init(&mut env).unwrap();
    assert_eq!(run(&mut env, "(set 'foo (+ 1 2 3))"), Ok(knil()));
    assert_eq!(run(&mut env, "foo"), Ok(kint(6)));

}

#[test]
fn test_if() {
    assert_eq!(run_new("(if () 1 2)"), Ok(kint(2)));
    assert_eq!(run_new("(if 1 1 2)"), Ok(kint(1)));
}
<commit_msg>more tests against if<commit_after>#[macro_use]
extern crate kappa_lisp;
use kappa_lisp::{init, run_new, run, Env};
use kappa_lisp::util::*;

#[test]
fn test_atom(){
    assert_eq!(run_new("1"), Ok(kint(1)));
    assert_eq!(run_new("()"), Ok(knil()));
    assert_eq!(run_new(("t")), Ok(ksym("t")));
    assert_eq!(run_new("\"string\""), Ok(kstr("string".to_string())));
}
// TODO: test `function`

#[test]
fn test_progn(){
    assert_eq!(run_new("(progn 1 2)"), Ok(kint(2)));
    assert_eq!(run_new("(progn (+ 1 2) (+ 2 3))"), Ok(kint(5)));
}

#[test]
fn test_lambda(){
    assert_eq!(run_new(("(lambda (x) x)")), Ok(kproc(klambda(klist!(ksym("x")),
                                                                           klist!(ksym("progn"), ksym("x"))))));
    assert_eq!(run_new("((lambda (x) (+ x x)) 1)"), Ok(kint(2)))
}

#[test]
fn test_fset(){
    let mut env = Env::new();
    init(&mut env).unwrap();
    assert_eq!(run(&mut env, "(fset 'add2 (lambda (x) (+ x 2)))"), Ok(knil()));
    assert_eq!(run(&mut env, "(add2 2)"), Ok(kint(4)));
}

#[test]
fn test_set() {
    let mut env = Env::new();
    init(&mut env).unwrap();
    assert_eq!(run(&mut env, "(set 'foo (+ 1 2 3))"), Ok(knil()));
    assert_eq!(run(&mut env, "foo"), Ok(kint(6)));
}

#[test]
fn test_if() {
    assert_eq!(run_new("(if () 1 2)"), Ok(kint(2)));
    assert_eq!(run_new("(if 1 1 2)"), Ok(kint(1)));
    assert_eq!(run_new("(if 1 1)"), Ok(kint(1)));
    assert_eq!(run_new("(if nil 1)"), Ok(knil()));
}
<|endoftext|>


<commit_before>///! Basic CSS block layout.

use style::{StyledNode, Display};
use css::Value::{Keyword, Length};
use css::Unit::Px;
use std::default::Default;

pub use self::BoxType::{AnonymousBlock, InlineNode, BlockNode};

// CSS box model. All sizes are in px.

#[derive(Clone, Copy, Default, Debug)]
pub struct Rect {
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
}

#[derive(Clone, Copy, Default, Debug)]
pub struct Dimensions {
    /// Position of the content area relative to the document origin:
    pub content: Rect,
    // Surrounding edges:
    pub padding: EdgeSizes,
    pub border: EdgeSizes,
    pub margin: EdgeSizes,
}

#[derive(Clone, Copy, Default, Debug)]
pub struct EdgeSizes {
    pub left: f32,
    pub right: f32,
    pub top: f32,
    pub bottom: f32,
}

/// A node in the layout tree.
pub struct LayoutBox<'a> {
    pub dimensions: Dimensions,
    pub box_type: BoxType<'a>,
    pub children: Vec<LayoutBox<'a>>,
}

pub enum BoxType<'a> {
    BlockNode(&'a StyledNode<'a>),
    InlineNode(&'a StyledNode<'a>),
    AnonymousBlock,
}

impl<'a> LayoutBox<'a> {
    fn new(box_type: BoxType) -> LayoutBox {
        LayoutBox {
            box_type: box_type,
            dimensions: Default::default(),
            children: Vec::new(),
        }
    }

    fn get_style_node(&self) -> &'a StyledNode<'a> {
        match self.box_type {
            BlockNode(node) | InlineNode(node) => node,
            AnonymousBlock => panic!("Anonymous block box has no style node")
        }
    }
}

/// Transform a style tree into a layout tree.
pub fn layout_tree<'a>(node: &'a StyledNode<'a>, mut containing_block: Dimensions) -> LayoutBox<'a> {
    // The layout algorithm expects the container height to start at 0.
    // TODO: Save the initial containing block height, for calculating percent heights.
    containing_block.content.height = 0.0;

    let mut root_box = build_layout_tree(node);
    root_box.layout(containing_block);
    root_box
}

/// Build the tree of LayoutBoxes, but don't perform any layout calculations yet.
fn build_layout_tree<'a>(style_node: &'a StyledNode<'a>) -> LayoutBox<'a> {
    // Create the root box.
    let mut root = LayoutBox::new(match style_node.display() {
        Display::Block => BlockNode(style_node),
        Display::Inline => InlineNode(style_node),
        Display::None => panic!("Root node has display: none.")
    });

    // Create the descendant boxes.
    for child in &style_node.children {
        match child.display() {
            Display::Block => root.children.push(build_layout_tree(child)),
            Display::Inline => root.get_inline_container().children.push(build_layout_tree(child)),
            Display::None => {} // Don't lay out nodes with `display: none;`
        }
    }
    root
}

impl<'a> LayoutBox<'a> {
    /// Lay out a box and its descendants.
    fn layout(&mut self, containing_block: Dimensions) {
        match self.box_type {
            BlockNode(_) => self.layout_block(containing_block),
            InlineNode(_) => {} // TODO
            AnonymousBlock => {} // TODO
        }
    }

    /// Lay out a block-level element and its descendants.
    fn layout_block(&mut self, containing_block: Dimensions) {
        // Child width can depend on parent width, so we need to calculate this box's width before
        // laying out its children.
        self.calculate_block_width(containing_block);

        // Determine where the box is located within its container.
        self.calculate_block_position(containing_block);

        // Recursively lay out the children of this box.
        self.layout_block_children();

        // Parent height can depend on child height, so `calculate_height` must be called after the
        // children are laid out.
        self.calculate_block_height();
    }

    /// Calculate the width of a block-level non-replaced element in normal flow.
    ///
    /// http://www.w3.org/TR/CSS2/visudet.html#blockwidth
    ///
    /// Sets the horizontal margin/padding/border dimensions, and the `width`.
    fn calculate_block_width(&mut self, containing_block: Dimensions) {
        let style = self.get_style_node();

        // `width` has initial value `auto`.
        let auto = Keyword("auto".to_string());
        let mut width = style.value("width").unwrap_or(auto.clone());

        // margin, border, and padding have initial value 0.
        let zero = Length(0.0, Px);

        let mut margin_left = style.lookup("margin-left", "margin", &zero);
        let mut margin_right = style.lookup("margin-right", "margin", &zero);

        let border_left = style.lookup("border-left-width", "border-width", &zero);
        let border_right = style.lookup("border-right-width", "border-width", &zero);

        let padding_left = style.lookup("padding-left", "padding", &zero);
        let padding_right = style.lookup("padding-right", "padding", &zero);

        let total = sum([&margin_left, &margin_right, &border_left, &border_right,
                         &padding_left, &padding_right, &width].iter().map(|v| v.to_px()));

        // If width is not auto and the total is wider than the container, treat auto margins as 0.
        if width != auto && total > containing_block.content.width {
            if margin_left == auto {
                margin_left = Length(0.0, Px);
            }
            if margin_right == auto {
                margin_right = Length(0.0, Px);
            }
        }

        // Adjust used values so that the above sum equals `containing_block.width`.
        // Each arm of the `match` should increase the total width by exactly `underflow`,
        // and afterward all values should be absolute lengths in px.
        let underflow = containing_block.content.width - total;

        match (width == auto, margin_left == auto, margin_right == auto) {
            // If the values are overconstrained, calculate margin_right.
            (false, false, false) => {
                margin_right = Length(margin_right.to_px() + underflow, Px);
            }

            // If exactly one size is auto, its used value follows from the equality.
            (false, false, true) => { margin_right = Length(underflow, Px); }
            (false, true, false) => { margin_left  = Length(underflow, Px); }

            // If width is set to auto, any other auto values become 0.
            (true, _, _) => {
                if margin_left == auto { margin_left = Length(0.0, Px); }
                if margin_right == auto { margin_right = Length(0.0, Px); }

                if underflow >= 0.0 {
                    // Expand width to fill the underflow.
                    width = Length(underflow, Px);
                } else {
                    // Width can't be negative. Adjust the right margin instead.
                    width = Length(0.0, Px);
                    margin_right = Length(margin_right.to_px() + underflow, Px);
                }
            }

            // If margin-left and margin-right are both auto, their used values are equal.
            (false, true, true) => {
                margin_left = Length(underflow / 2.0, Px);
                margin_right = Length(underflow / 2.0, Px);
            }
        }

        let d = &mut self.dimensions;
        d.content.width = width.to_px();

        d.padding.left = padding_left.to_px();
        d.padding.right = padding_right.to_px();

        d.border.left = border_left.to_px();
        d.border.right = border_right.to_px();

        d.margin.left = margin_left.to_px();
        d.margin.right = margin_right.to_px();
    }

    /// Finish calculating the block's edge sizes, and position it within its containing block.
    ///
    /// http://www.w3.org/TR/CSS2/visudet.html#normal-block
    ///
    /// Sets the vertical margin/padding/border dimensions, and the `x`, `y` values.
    fn calculate_block_position(&mut self, containing_block: Dimensions) {
        let style = self.get_style_node();
        let d = &mut self.dimensions;

        // margin, border, and padding have initial value 0.
        let zero = Length(0.0, Px);

        // If margin-top or margin-bottom is `auto`, the used value is zero.
        d.margin.top = style.lookup("margin-top", "margin", &zero).to_px();
        d.margin.bottom = style.lookup("margin-bottom", "margin", &zero).to_px();

        d.border.top = style.lookup("border-top-width", "border-width", &zero).to_px();
        d.border.bottom = style.lookup("border-bottom-width", "border-width", &zero).to_px();

        d.padding.top = style.lookup("padding-top", "padding", &zero).to_px();
        d.padding.bottom = style.lookup("padding-bottom", "padding", &zero).to_px();

        d.content.x = containing_block.content.x +
                      d.margin.left + d.border.left + d.padding.left;

        // Position the box below all the previous boxes in the container.
        d.content.y = containing_block.content.height + containing_block.content.y +
                      d.margin.top + d.border.top + d.padding.top;
    }

    /// Lay out the block's children within its content area.
    ///
    /// Sets `self.dimensions.height` to the total content height.
    fn layout_block_children(&mut self) {
        let d = &mut self.dimensions;
        for child in &mut self.children {
            child.layout(*d);
            // Increment the height so each child is laid out below the previous one.
            d.content.height = d.content.height + child.dimensions.margin_box().height;
        }
    }

    /// Height of a block-level non-replaced element in normal flow with overflow visible.
    fn calculate_block_height(&mut self) {
        // If the height is set to an explicit length, use that exact length.
        // Otherwise, just keep the value set by `layout_block_children`.
        if let Some(Length(h, Px)) = self.get_style_node().value("height") {
            self.dimensions.content.height = h;
        }
    }

    /// Where a new inline child should go.
    fn get_inline_container(&mut self) -> &mut LayoutBox<'a> {
        match self.box_type {
            InlineNode(_) | AnonymousBlock => self,
            BlockNode(_) => {
                // If we've just generated an anonymous block box, keep using it.
                // Otherwise, create a new one.
                match self.children.last() {
                    Some(&LayoutBox { box_type: AnonymousBlock,..}) => {}
                    _ => self.children.push(LayoutBox::new(AnonymousBlock))
                }
                self.children.last_mut().unwrap()
            }
        }
    }
}

impl Rect {
    pub fn expanded_by(self, edge: EdgeSizes) -> Rect {
        Rect {
            x: self.x - edge.left,
            y: self.y - edge.top,
            width: self.width + edge.left + edge.right,
            height: self.height + edge.top + edge.bottom,
        }
    }
}

impl Dimensions {
    /// The area covered by the content area plus its padding.
    pub fn padding_box(self) -> Rect {
        self.content.expanded_by(self.padding)
    }
    /// The area covered by the content area plus padding and borders.
    pub fn border_box(self) -> Rect {
        self.padding_box().expanded_by(self.border)
    }
    /// The area covered by the content area plus padding, borders, and margin.
    pub fn margin_box(self) -> Rect {
        self.border_box().expanded_by(self.margin)
    }
}

fn sum<I>(iter: I) -> f32 where I: Iterator<Item=f32> {
    iter.fold(0., |a, b| a + b)
}
<commit_msg>Identical match arm bodies<commit_after>///! Basic CSS block layout.

use style::{StyledNode, Display};
use css::Value::{Keyword, Length};
use css::Unit::Px;
use std::default::Default;

pub use self::BoxType::{AnonymousBlock, InlineNode, BlockNode};

// CSS box model. All sizes are in px.

#[derive(Clone, Copy, Default, Debug)]
pub struct Rect {
    pub x: f32,
    pub y: f32,
    pub width: f32,
    pub height: f32,
}

#[derive(Clone, Copy, Default, Debug)]
pub struct Dimensions {
    /// Position of the content area relative to the document origin:
    pub content: Rect,
    // Surrounding edges:
    pub padding: EdgeSizes,
    pub border: EdgeSizes,
    pub margin: EdgeSizes,
}

#[derive(Clone, Copy, Default, Debug)]
pub struct EdgeSizes {
    pub left: f32,
    pub right: f32,
    pub top: f32,
    pub bottom: f32,
}

/// A node in the layout tree.
pub struct LayoutBox<'a> {
    pub dimensions: Dimensions,
    pub box_type: BoxType<'a>,
    pub children: Vec<LayoutBox<'a>>,
}

pub enum BoxType<'a> {
    BlockNode(&'a StyledNode<'a>),
    InlineNode(&'a StyledNode<'a>),
    AnonymousBlock,
}

impl<'a> LayoutBox<'a> {
    fn new(box_type: BoxType) -> LayoutBox {
        LayoutBox {
            box_type: box_type,
            dimensions: Default::default(),
            children: Vec::new(),
        }
    }

    fn get_style_node(&self) -> &'a StyledNode<'a> {
        match self.box_type {
            BlockNode(node) | InlineNode(node) => node,
            AnonymousBlock => panic!("Anonymous block box has no style node")
        }
    }
}

/// Transform a style tree into a layout tree.
pub fn layout_tree<'a>(node: &'a StyledNode<'a>, mut containing_block: Dimensions) -> LayoutBox<'a> {
    // The layout algorithm expects the container height to start at 0.
    // TODO: Save the initial containing block height, for calculating percent heights.
    containing_block.content.height = 0.0;

    let mut root_box = build_layout_tree(node);
    root_box.layout(containing_block);
    root_box
}

/// Build the tree of LayoutBoxes, but don't perform any layout calculations yet.
fn build_layout_tree<'a>(style_node: &'a StyledNode<'a>) -> LayoutBox<'a> {
    // Create the root box.
    let mut root = LayoutBox::new(match style_node.display() {
        Display::Block => BlockNode(style_node),
        Display::Inline => InlineNode(style_node),
        Display::None => panic!("Root node has display: none.")
    });

    // Create the descendant boxes.
    for child in &style_node.children {
        match child.display() {
            Display::Block => root.children.push(build_layout_tree(child)),
            Display::Inline => root.get_inline_container().children.push(build_layout_tree(child)),
            Display::None => {} // Don't lay out nodes with `display: none;`
        }
    }
    root
}

impl<'a> LayoutBox<'a> {
    /// Lay out a box and its descendants.
    fn layout(&mut self, containing_block: Dimensions) {
        match self.box_type {
            BlockNode(_) => self.layout_block(containing_block),
            InlineNode(_) | AnonymousBlock => {} // TODO
        }
    }

    /// Lay out a block-level element and its descendants.
    fn layout_block(&mut self, containing_block: Dimensions) {
        // Child width can depend on parent width, so we need to calculate this box's width before
        // laying out its children.
        self.calculate_block_width(containing_block);

        // Determine where the box is located within its container.
        self.calculate_block_position(containing_block);

        // Recursively lay out the children of this box.
        self.layout_block_children();

        // Parent height can depend on child height, so `calculate_height` must be called after the
        // children are laid out.
        self.calculate_block_height();
    }

    /// Calculate the width of a block-level non-replaced element in normal flow.
    ///
    /// http://www.w3.org/TR/CSS2/visudet.html#blockwidth
    ///
    /// Sets the horizontal margin/padding/border dimensions, and the `width`.
    fn calculate_block_width(&mut self, containing_block: Dimensions) {
        let style = self.get_style_node();

        // `width` has initial value `auto`.
        let auto = Keyword("auto".to_string());
        let mut width = style.value("width").unwrap_or(auto.clone());

        // margin, border, and padding have initial value 0.
        let zero = Length(0.0, Px);

        let mut margin_left = style.lookup("margin-left", "margin", &zero);
        let mut margin_right = style.lookup("margin-right", "margin", &zero);

        let border_left = style.lookup("border-left-width", "border-width", &zero);
        let border_right = style.lookup("border-right-width", "border-width", &zero);

        let padding_left = style.lookup("padding-left", "padding", &zero);
        let padding_right = style.lookup("padding-right", "padding", &zero);

        let total = sum([&margin_left, &margin_right, &border_left, &border_right,
                         &padding_left, &padding_right, &width].iter().map(|v| v.to_px()));

        // If width is not auto and the total is wider than the container, treat auto margins as 0.
        if width != auto && total > containing_block.content.width {
            if margin_left == auto {
                margin_left = Length(0.0, Px);
            }
            if margin_right == auto {
                margin_right = Length(0.0, Px);
            }
        }

        // Adjust used values so that the above sum equals `containing_block.width`.
        // Each arm of the `match` should increase the total width by exactly `underflow`,
        // and afterward all values should be absolute lengths in px.
        let underflow = containing_block.content.width - total;

        match (width == auto, margin_left == auto, margin_right == auto) {
            // If the values are overconstrained, calculate margin_right.
            (false, false, false) => {
                margin_right = Length(margin_right.to_px() + underflow, Px);
            }

            // If exactly one size is auto, its used value follows from the equality.
            (false, false, true) => { margin_right = Length(underflow, Px); }
            (false, true, false) => { margin_left  = Length(underflow, Px); }

            // If width is set to auto, any other auto values become 0.
            (true, _, _) => {
                if margin_left == auto { margin_left = Length(0.0, Px); }
                if margin_right == auto { margin_right = Length(0.0, Px); }

                if underflow >= 0.0 {
                    // Expand width to fill the underflow.
                    width = Length(underflow, Px);
                } else {
                    // Width can't be negative. Adjust the right margin instead.
                    width = Length(0.0, Px);
                    margin_right = Length(margin_right.to_px() + underflow, Px);
                }
            }

            // If margin-left and margin-right are both auto, their used values are equal.
            (false, true, true) => {
                margin_left = Length(underflow / 2.0, Px);
                margin_right = Length(underflow / 2.0, Px);
            }
        }

        let d = &mut self.dimensions;
        d.content.width = width.to_px();

        d.padding.left = padding_left.to_px();
        d.padding.right = padding_right.to_px();

        d.border.left = border_left.to_px();
        d.border.right = border_right.to_px();

        d.margin.left = margin_left.to_px();
        d.margin.right = margin_right.to_px();
    }

    /// Finish calculating the block's edge sizes, and position it within its containing block.
    ///
    /// http://www.w3.org/TR/CSS2/visudet.html#normal-block
    ///
    /// Sets the vertical margin/padding/border dimensions, and the `x`, `y` values.
    fn calculate_block_position(&mut self, containing_block: Dimensions) {
        let style = self.get_style_node();
        let d = &mut self.dimensions;

        // margin, border, and padding have initial value 0.
        let zero = Length(0.0, Px);

        // If margin-top or margin-bottom is `auto`, the used value is zero.
        d.margin.top = style.lookup("margin-top", "margin", &zero).to_px();
        d.margin.bottom = style.lookup("margin-bottom", "margin", &zero).to_px();

        d.border.top = style.lookup("border-top-width", "border-width", &zero).to_px();
        d.border.bottom = style.lookup("border-bottom-width", "border-width", &zero).to_px();

        d.padding.top = style.lookup("padding-top", "padding", &zero).to_px();
        d.padding.bottom = style.lookup("padding-bottom", "padding", &zero).to_px();

        d.content.x = containing_block.content.x +
                      d.margin.left + d.border.left + d.padding.left;

        // Position the box below all the previous boxes in the container.
        d.content.y = containing_block.content.height + containing_block.content.y +
                      d.margin.top + d.border.top + d.padding.top;
    }

    /// Lay out the block's children within its content area.
    ///
    /// Sets `self.dimensions.height` to the total content height.
    fn layout_block_children(&mut self) {
        let d = &mut self.dimensions;
        for child in &mut self.children {
            child.layout(*d);
            // Increment the height so each child is laid out below the previous one.
            d.content.height = d.content.height + child.dimensions.margin_box().height;
        }
    }

    /// Height of a block-level non-replaced element in normal flow with overflow visible.
    fn calculate_block_height(&mut self) {
        // If the height is set to an explicit length, use that exact length.
        // Otherwise, just keep the value set by `layout_block_children`.
        if let Some(Length(h, Px)) = self.get_style_node().value("height") {
            self.dimensions.content.height = h;
        }
    }

    /// Where a new inline child should go.
    fn get_inline_container(&mut self) -> &mut LayoutBox<'a> {
        match self.box_type {
            InlineNode(_) | AnonymousBlock => self,
            BlockNode(_) => {
                // If we've just generated an anonymous block box, keep using it.
                // Otherwise, create a new one.
                match self.children.last() {
                    Some(&LayoutBox { box_type: AnonymousBlock,..}) => {}
                    _ => self.children.push(LayoutBox::new(AnonymousBlock))
                }
                self.children.last_mut().unwrap()
            }
        }
    }
}

impl Rect {
    pub fn expanded_by(self, edge: EdgeSizes) -> Rect {
        Rect {
            x: self.x - edge.left,
            y: self.y - edge.top,
            width: self.width + edge.left + edge.right,
            height: self.height + edge.top + edge.bottom,
        }
    }
}

impl Dimensions {
    /// The area covered by the content area plus its padding.
    pub fn padding_box(self) -> Rect {
        self.content.expanded_by(self.padding)
    }
    /// The area covered by the content area plus padding and borders.
    pub fn border_box(self) -> Rect {
        self.padding_box().expanded_by(self.border)
    }
    /// The area covered by the content area plus padding, borders, and margin.
    pub fn margin_box(self) -> Rect {
        self.border_box().expanded_by(self.margin)
    }
}

fn sum<I>(iter: I) -> f32 where I: Iterator<Item=f32> {
    iter.fold(0., |a, b| a + b)
}
<|endoftext|>


<commit_before>//! Logging functionality
//!
//! This module defines a logging implementation for the `log`
//! crate published by the Rust developer.
//!

use log::*;
use std::path::Path;
use std::fs;
use std::io;
use term::{self, ToStyle};
use std::io::Write;
use std::sync::Mutex;
use std::ops::DerefMut;

/// Returns a builder that can enable the logger globally.
pub fn with_loglevel(lvl: LogLevelFilter) -> Builder<'static> {
    Builder {
        lvl: lvl,
        logfile: None,
        stdout: true,
    }
}

/// A builder type to easily configure the logger.
pub struct Builder<'a> {
    lvl: LogLevelFilter,
    logfile: Option<&'a Path>,
    stdout: bool,
}

#[allow(dead_code)]
impl<'a> Builder<'a> {
    /// Enables logging into the given file
    pub fn with_logfile<'b>(self, path: &'b Path) -> Builder<'b> {
        Builder {
            lvl: self.lvl,
            logfile: Some(path),
            stdout: self.stdout,
        }
    }

    /// Disables logging to stdout (which is enabled by default)
    pub fn without_stdout(self) -> Builder<'a> {
        Builder {
            lvl: self.lvl,
            logfile: self.logfile,
            stdout: false,
        }
    }

    /// Creates the `Logger` from the given configuration and enables it
    /// globally. Any log messages generated before this method is called,
    /// will be ignored.
    ///
    /// # Failures
    /// - Returns an `Err` if the a logfile was specified, but it could not be
    /// opened in write-append-create mode.
    /// - Returns an `Err` with kind `AlreadyExists` if this method is called
    /// more than once in one running program.
    pub fn enable(self) -> io::Result<()> {
        // Try to open the logfile in write-append mode, if any was specified
        let file = match self.logfile {
            Some(path) => {
                Some(try!(fs::OpenOptions::new()
                    .write(true)
                    .append(true)
                    .create(true)
                    .open(path)))
            },
            None => None,
        };

        set_logger(|filter| {
            filter.set(self.lvl);
            Box::new(Logger {
                level_filter: filter,
                logfile: file.map(|f| Mutex::new(f)),
                stdout: self.stdout,
            })
        }).map_err(|_| io::Error::new(
            io::ErrorKind::AlreadyExists,
            "method 'enable' was called more than once!"
            )
        )
    }
}

/// Type to do the actual logging. You don't need to interact with it directly:
/// Use macros and functions of the `log` crate.
struct Logger {
    level_filter: MaxLogLevelFilter,
    logfile: Option<Mutex<fs::File>>,
    stdout: bool,
}

impl Log for Logger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.level_filter.get()
    }

    fn log(&self, record: &LogRecord) {
        // Early return if the message won't be printed
        if !self.enabled(record.metadata()) {
            return;
        }

        // Prepare module path (remove crate name & add "::" if missing)
        let pos = record.target().find("::");
        let mod_path = match pos {
            None => "::",
            Some(pos) => &record.target()[pos ..],
        };

        // Ignore the leading 'src/' in the file path
        let src_file = &record.location().file()[4 ..];

        // If a logfile is specified (file logging is enabled)
        if let Some(ref file) = self.logfile {
            // Aquire a lock on the file to log into file. We may unwrap here
            // because it will just panic if a thread paniced before, while
            // holding the lock. It's very unlikely (maybe even impossible)
            // that the thread will panic during the `write!`. And if it
            // happens we want to propagate the panic to all threads.
            // We ignore the result of `write!`, because: What else should we
            // do? ;)
            let _ = write!(file.lock().unwrap().deref_mut(),
                "[{level: <5}][{module} @ {file}:{line}]> {msg}",
                level = record.level(),
                module = mod_path,
                file = src_file,
                line = record.location().line(),
                msg = record.args());
        }

        // If logging to stdout is enabled
        if self.stdout {
            let (lvl_col, msg_col) = get_colors(record.level());

            println!("[{level: <5}][{module} @ {file}:{line}]{delim} {msg}",
                level = lvl_col.paint(record.level()),
                module = mod_path,
                file = term::Color::Blue.paint(src_file),
                line = record.location().line(),
                delim = term::Color::White.paint("$"),
                msg = msg_col.paint(record.args()));
        }
    }
}

fn get_colors(lvl: LogLevel) -> (term::Style, term::Style) {
    use term::{Attr, ToStyle};
    use term::Color::*;
    use log::LogLevel::*;

    // Style for the user's message
    let msg_col = match lvl {
        Error   => Attr::Bold   .fg(Red),
        Warn    => Attr::Plain  .fg(Yellow),
        Info    => Attr::Plain  .fg(White),
        Debug   => Attr::Plain  .fg(NotSet),
        Trace   => Attr::Dim    .fg(NotSet),
    };

    // Color for the first info field: The log level
    let lvl_col = match lvl {
        Error   => Attr::Bold   .fg(Red),
        Warn    => Attr::Plain  .fg(Yellow),
        Info    => Attr::Plain  .fg(White),
        Debug   => Attr::Plain  .fg(NotSet),
        Trace   => Attr::Dim    .fg(NotSet),
    };

    (lvl_col, msg_col)
}
<commit_msg>Add a line break in logfile<commit_after>//! Logging functionality
//!
//! This module defines a logging implementation for the `log`
//! crate published by the Rust developer.
//!

use log::*;
use std::path::Path;
use std::fs;
use std::io;
use term::{self, ToStyle};
use std::io::Write;
use std::sync::Mutex;
use std::ops::DerefMut;

/// Returns a builder that can enable the logger globally.
pub fn with_loglevel(lvl: LogLevelFilter) -> Builder<'static> {
    Builder {
        lvl: lvl,
        logfile: None,
        stdout: true,
    }
}

/// A builder type to easily configure the logger.
pub struct Builder<'a> {
    lvl: LogLevelFilter,
    logfile: Option<&'a Path>,
    stdout: bool,
}

#[allow(dead_code)]
impl<'a> Builder<'a> {
    /// Enables logging into the given file
    pub fn with_logfile<'b>(self, path: &'b Path) -> Builder<'b> {
        Builder {
            lvl: self.lvl,
            logfile: Some(path),
            stdout: self.stdout,
        }
    }

    /// Disables logging to stdout (which is enabled by default)
    pub fn without_stdout(self) -> Builder<'a> {
        Builder {
            lvl: self.lvl,
            logfile: self.logfile,
            stdout: false,
        }
    }

    /// Creates the `Logger` from the given configuration and enables it
    /// globally. Any log messages generated before this method is called,
    /// will be ignored.
    ///
    /// # Failures
    /// - Returns an `Err` if the a logfile was specified, but it could not be
    /// opened in write-append-create mode.
    /// - Returns an `Err` with kind `AlreadyExists` if this method is called
    /// more than once in one running program.
    pub fn enable(self) -> io::Result<()> {
        // Try to open the logfile in write-append mode, if any was specified
        let file = match self.logfile {
            Some(path) => {
                Some(try!(fs::OpenOptions::new()
                    .write(true)
                    .append(true)
                    .create(true)
                    .open(path)))
            },
            None => None,
        };

        set_logger(|filter| {
            filter.set(self.lvl);
            Box::new(Logger {
                level_filter: filter,
                logfile: file.map(|f| Mutex::new(f)),
                stdout: self.stdout,
            })
        }).map_err(|_| io::Error::new(
            io::ErrorKind::AlreadyExists,
            "method 'enable' was called more than once!"
            )
        )
    }
}

/// Type to do the actual logging. You don't need to interact with it directly:
/// Use macros and functions of the `log` crate.
struct Logger {
    level_filter: MaxLogLevelFilter,
    logfile: Option<Mutex<fs::File>>,
    stdout: bool,
}

impl Log for Logger {
    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.level_filter.get()
    }

    fn log(&self, record: &LogRecord) {
        // Early return if the message won't be printed
        if !self.enabled(record.metadata()) {
            return;
        }

        // Prepare module path (remove crate name & add "::" if missing)
        let pos = record.target().find("::");
        let mod_path = match pos {
            None => "::",
            Some(pos) => &record.target()[pos ..],
        };

        // Ignore the leading 'src/' in the file path
        let src_file = &record.location().file()[4 ..];

        // If a logfile is specified (file logging is enabled)
        if let Some(ref file) = self.logfile {
            // Aquire a lock on the file to log into file. We may unwrap here
            // because it will just panic if a thread paniced before, while
            // holding the lock. It's very unlikely (maybe even impossible)
            // that the thread will panic during the `write!`. And if it
            // happens we want to propagate the panic to all threads.
            // We ignore the result of `write!`, because: What else should we
            // do? ;)
            let _ = write!(file.lock().unwrap().deref_mut(),
                "[{level: <5}][{module} @ {file}:{line}]> {msg}\n",
                level = record.level(),
                module = mod_path,
                file = src_file,
                line = record.location().line(),
                msg = record.args());
        }

        // If logging to stdout is enabled
        if self.stdout {
            let (lvl_col, msg_col) = get_colors(record.level());

            println!("[{level: <5}][{module} @ {file}:{line}]{delim} {msg}",
                level = lvl_col.paint(record.level()),
                module = mod_path,
                file = term::Color::Blue.paint(src_file),
                line = record.location().line(),
                delim = term::Color::White.paint("$"),
                msg = msg_col.paint(record.args()));
        }
    }
}

fn get_colors(lvl: LogLevel) -> (term::Style, term::Style) {
    use term::{Attr, ToStyle};
    use term::Color::*;
    use log::LogLevel::*;

    // Style for the user's message
    let msg_col = match lvl {
        Error   => Attr::Bold   .fg(Red),
        Warn    => Attr::Plain  .fg(Yellow),
        Info    => Attr::Plain  .fg(White),
        Debug   => Attr::Plain  .fg(NotSet),
        Trace   => Attr::Dim    .fg(NotSet),
    };

    // Color for the first info field: The log level
    let lvl_col = match lvl {
        Error   => Attr::Bold   .fg(Red),
        Warn    => Attr::Plain  .fg(Yellow),
        Info    => Attr::Plain  .fg(White),
        Debug   => Attr::Plain  .fg(NotSet),
        Trace   => Attr::Dim    .fg(NotSet),
    };

    (lvl_col, msg_col)
}
<|endoftext|>