<commit_before>// Copyright 2018 Syn Developers
//
// 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.

//! Parsing interface for parsing a token stream into a syntax tree node.
//!
//! Parsing in Syn is built on parser functions that take in a [`Cursor`] and
//! produce a [`PResult<T>`] where `T` is some syntax tree node. `Cursor` is a
//! cheaply copyable cursor over a range of tokens in a token stream, and
//! `PResult` is a result that packages together a parsed syntax tree node `T`
//! with a stream of remaining unparsed tokens after `T` represented as another
//! `Cursor`, or an [`Error`] if parsing failed.
//!
//! [`Cursor`]: ../buffer/index.html
//! [`PResult<T>`]: type.PResult.html
//! [`Error`]: struct.Error.html
//!
//! This `Cursor`- and `PResult`-based interface is convenient for parser
//! combinators and parser implementations, but not necessarily when you just
//! have some tokens that you want to parse. For that we expose the following
//! two entry points.
//!
//! ## The `syn::parse*` functions
//!
//! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve
//! as an entry point for parsing syntax tree nodes that can be parsed in an
//! obvious default way. These functions can return any syntax tree node that
//! implements the [`Synom`] trait, which includes most types in Syn.
//!
//! [`syn::parse`]: ../fn.parse.html
//! [`syn::parse2`]: ../fn.parse2.html
//! [`syn::parse_str`]: ../fn.parse_str.html
//! [`Synom`]: trait.Synom.html
//!
//! ```
//! use syn::Type;
//!
//! # fn run_parser() -> Result<(), syn::synom::Error> {
//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?;
//! #     Ok(())
//! # }
//! #
//! # fn main() {
//! #     run_parser().unwrap();
//! # }
//! ```
//!
//! The [`parse_quote!`] macro also uses this approach.
//!
//! [`parse_quote!`]: ../macro.parse_quote.html
//!
//! ## The `Parser` trait
//!
//! Some types can be parsed in several ways depending on context. For example
//! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like
//! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`]
//! may or may not allow trailing punctuation, and parsing it the wrong way
//! would either reject valid input or accept invalid input.
//!
//! [`Attribute`]: ../struct.Attribute.html
//! [`Punctuated`]: ../punctuated/index.html
//!
//! The `Synom` trait is not implemented in these cases because there is no good
//! behavior to consider the default.
//!
//! ```ignore
//! // Can't parse `Punctuated` without knowing whether trailing punctuation
//! // should be allowed in this context.
//! let path: Punctuated<PathSegment, Token![::]> = syn::parse(tokens)?;
//! ```
//!
//! In these cases the types provide a choice of parser functions rather than a
//! single `Synom` implementation, and those parser functions can be invoked
//! through the [`Parser`] trait.
//!
//! [`Parser`]: trait.Parser.html
//!
//! ```
//! # #[macro_use]
//! # extern crate syn;
//! #
//! # extern crate proc_macro2;
//! # use proc_macro2::TokenStream;
//! #
//! use syn::synom::Parser;
//! use syn::punctuated::Punctuated;
//! use syn::{PathSegment, Expr, Attribute};
//!
//! # fn run_parsers() -> Result<(), syn::synom::Error> {
//! #     let tokens = TokenStream::new().into();
//! // Parse a nonempty sequence of path segments separated by `::` punctuation
//! // with no trailing punctuation.
//! let parser = Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty;
//! let path = parser.parse(tokens)?;
//!
//! #     let tokens = TokenStream::new().into();
//! // Parse a possibly empty sequence of expressions terminated by commas with
//! // an optional trailing punctuation.
//! let parser = Punctuated::<Expr, Token![,]>::parse_terminated;
//! let args = parser.parse(tokens)?;
//!
//! #     let tokens = TokenStream::new().into();
//! // Parse zero or more outer attributes but not inner attributes.
//! named!(outer_attrs -> Vec<Attribute>, many0!(Attribute::old_parse_outer));
//! let attrs = outer_attrs.parse(tokens)?;
//! #
//! #     Ok(())
//! # }
//! #
//! # fn main() {}
//! ```
//!
//! # Implementing a parser function
//!
//! Parser functions are usually implemented using the [`nom`]-style parser
//! combinator macros provided by Syn, but may also be implemented without
//! macros be using the low-level [`Cursor`] API directly.
//!
//! [`nom`]: https://github.com/Geal/nom
//!
//! The following parser combinator macros are available and a `Synom` parsing
//! example is provided for each one.
//!
//! - [`alt!`](../macro.alt.html)
//! - [`braces!`](../macro.braces.html)
//! - [`brackets!`](../macro.brackets.html)
//! - [`call!`](../macro.call.html)
//! - [`cond!`](../macro.cond.html)
//! - [`cond_reduce!`](../macro.cond_reduce.html)
//! - [`custom_keyword!`](../macro.custom_keyword.html)
//! - [`do_parse!`](../macro.do_parse.html)
//! - [`epsilon!`](../macro.epsilon.html)
//! - [`input_end!`](../macro.input_end.html)
//! - [`keyword!`](../macro.keyword.html)
//! - [`many0!`](../macro.many0.html)
//! - [`map!`](../macro.map.html)
//! - [`not!`](../macro.not.html)
//! - [`option!`](../macro.option.html)
//! - [`parens!`](../macro.parens.html)
//! - [`punct!`](../macro.punct.html)
//! - [`reject!`](../macro.reject.html)
//! - [`switch!`](../macro.switch.html)
//! - [`syn!`](../macro.syn.html)
//! - [`tuple!`](../macro.tuple.html)
//! - [`value!`](../macro.value.html)
//!
//! *This module is available if Syn is built with the `"parsing"` feature.*

use std::cell::Cell;
use std::rc::Rc;
use std::str::FromStr;

#[cfg(all(
    not(all(target_arch = "wasm32", target_os = "unknown")),
    feature = "proc-macro"
))]
use proc_macro;
use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};

use error::parse_error;
pub use error::{Error, PResult};

use buffer::{Cursor, TokenBuffer};
use parse::{Parse, ParseBuffer, ParseStream, Result};

/// Parsing interface implemented by all types that can be parsed in a default
/// way from a token stream.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This trait is available if Syn is built with the `"parsing"` feature.*
pub trait Synom: Sized {
    fn parse(input: Cursor) -> PResult<Self>;

    /// A short name of the type being parsed.
    ///
    /// The description should only be used for a simple name.  It should not
    /// contain newlines or sentence-ending punctuation, to facilitate embedding in
    /// larger user-facing strings.  Syn will use this description when building
    /// error messages about parse failures.
    ///
    /// # Examples
    ///
    /// ```
    /// # use syn::buffer::Cursor;
    /// # use syn::synom::{Synom, PResult};
    /// #
    /// struct ExprMacro {
    ///     // ...
    /// }
    ///
    /// impl Synom for ExprMacro {
    /// #   fn parse(input: Cursor) -> PResult<Self> { unimplemented!() }
    ///     // fn parse(...) -> ... { ... }
    ///
    ///     fn description() -> Option<&'static str> {
    ///         // Will result in messages like
    ///         //
    ///         //     "failed to parse macro invocation expression: $reason"
    ///         Some("macro invocation expression")
    ///     }
    /// }
    /// ```
    fn description() -> Option<&'static str> {
        None
    }
}

impl<T: Parse> Synom for T {
    fn parse(input: Cursor) -> PResult<Self> {
        let unexpected = Rc::new(Cell::new(None));
        let state = ParseBuffer::new(Span::call_site(), input, unexpected);
        let node = <T as Parse>::parse(&state)?;
        state.check_unexpected()?;
        Ok((node, state.cursor()))
    }
}

impl Parse for TokenStream {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| Ok((cursor.token_stream(), Cursor::empty())))
    }
}

impl Parse for TokenTree {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.token_tree() {
            Some((tt, rest)) => Ok((tt, rest)),
            None => Err(cursor.error("expected token tree")),
        })
    }
}

impl Parse for Group {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| {
            for delim in &[Delimiter::Parenthesis, Delimiter::Brace, Delimiter::Bracket] {
                if let Some((inside, span, rest)) = cursor.group(*delim) {
                    let mut group = Group::new(*delim, inside.token_stream());
                    group.set_span(span);
                    return Ok((group, rest));
                }
            }
            Err(cursor.error("expected group token"))
        })
    }
}

impl Parse for Punct {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.punct() {
            Some((punct, rest)) => Ok((punct, rest)),
            None => Err(cursor.error("expected punctuation token")),
        })
    }
}

impl Parse for Literal {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.literal() {
            Some((literal, rest)) => Ok((literal, rest)),
            None => Err(cursor.error("expected literal token")),
        })
    }
}

/// Parser that can parse Rust tokens into a particular syntax tree node.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This trait is available if Syn is built with the `"parsing"` feature.*
pub trait Parser: Sized {
    type Output;

    /// Parse a proc-macro2 token stream into the chosen syntax tree node.
    fn parse2(self, tokens: TokenStream) -> Result<Self::Output>;

    /// Parse tokens of source code into the chosen syntax tree node.
    ///
    /// *This method is available if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", target_os = "unknown")),
        feature = "proc-macro"
    ))]
    fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output> {
        self.parse2(proc_macro2::TokenStream::from(tokens))
    }

    /// Parse a string of Rust code into the chosen syntax tree node.
    ///
    /// # Hygiene
    ///
    /// Every span in the resulting syntax tree will be set to resolve at the
    /// macro call site.
    fn parse_str(self, s: &str) -> Result<Self::Output> {
        self.parse2(proc_macro2::TokenStream::from_str(s)?)
    }
}

impl<F, T> Parser for F
where
    F: FnOnce(ParseStream) -> Result<T>,
{
    type Output = T;

    fn parse2(self, tokens: TokenStream) -> Result<T> {
        let buf = TokenBuffer::new2(tokens);
        let unexpected = Rc::new(Cell::new(None));
        let state = ParseBuffer::new(Span::call_site(), buf.begin(), unexpected);
        let node = self(&state)?;
        state.check_unexpected()?;
        Ok(node)
    }
}

/// Extension traits that are made available within the `call!` parser.
///
/// *This module is available if Syn is built with the `"parsing"` feature.*
pub mod ext {
    use super::*;
    use proc_macro2::Ident;

    use parse::{ParseStream, Result};

    /// Additional parsing methods for `Ident`.
    ///
    /// This trait is sealed and cannot be implemented for types outside of Syn.
    ///
    /// *This trait is available if Syn is built with the `"parsing"` feature.*
    pub trait IdentExt: Sized + private::Sealed {
        /// Parses any identifier including keywords.
        ///
        /// This is useful when parsing a DSL which allows Rust keywords as
        /// identifiers.
        ///
        /// ```rust
        /// #[macro_use]
        /// extern crate syn;
        ///
        /// use syn::Ident;
        ///
        /// // Parses input that looks like `name = NAME` where `NAME` can be
        /// // any identifier.
        /// //
        /// // Examples:
        /// //
        /// //     name = anything
        /// //     name = impl
        /// named!(parse_dsl -> Ident, do_parse!(
        ///     custom_keyword!(name) >>
        ///     punct!(=) >>
        ///     name: call!(Ident::parse_any) >>
        ///     (name)
        /// ));
        /// #
        /// # fn main() {}
        /// ```
        fn parse_any(input: Cursor) -> PResult<Self>;

        fn parse_any2(input: ParseStream) -> Result<Self>;
    }

    impl IdentExt for Ident {
        fn parse_any(input: Cursor) -> PResult<Self> {
            input.ident().map_or_else(parse_error, Ok)
        }

        fn parse_any2(input: ParseStream) -> Result<Self> {
            input.step_cursor(|cursor| match cursor.ident() {
                Some((ident, rest)) => Ok((ident, rest)),
                None => Err(cursor.error("expected ident")),
            })
        }
    }

    mod private {
        use proc_macro2::Ident;

        pub trait Sealed {}

        impl Sealed for Ident {}
    }
}
<commit_msg>Check for incomplete parse in Parser trait<commit_after>// Copyright 2018 Syn Developers
//
// 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.

//! Parsing interface for parsing a token stream into a syntax tree node.
//!
//! Parsing in Syn is built on parser functions that take in a [`Cursor`] and
//! produce a [`PResult<T>`] where `T` is some syntax tree node. `Cursor` is a
//! cheaply copyable cursor over a range of tokens in a token stream, and
//! `PResult` is a result that packages together a parsed syntax tree node `T`
//! with a stream of remaining unparsed tokens after `T` represented as another
//! `Cursor`, or an [`Error`] if parsing failed.
//!
//! [`Cursor`]: ../buffer/index.html
//! [`PResult<T>`]: type.PResult.html
//! [`Error`]: struct.Error.html
//!
//! This `Cursor`- and `PResult`-based interface is convenient for parser
//! combinators and parser implementations, but not necessarily when you just
//! have some tokens that you want to parse. For that we expose the following
//! two entry points.
//!
//! ## The `syn::parse*` functions
//!
//! The [`syn::parse`], [`syn::parse2`], and [`syn::parse_str`] functions serve
//! as an entry point for parsing syntax tree nodes that can be parsed in an
//! obvious default way. These functions can return any syntax tree node that
//! implements the [`Synom`] trait, which includes most types in Syn.
//!
//! [`syn::parse`]: ../fn.parse.html
//! [`syn::parse2`]: ../fn.parse2.html
//! [`syn::parse_str`]: ../fn.parse_str.html
//! [`Synom`]: trait.Synom.html
//!
//! ```
//! use syn::Type;
//!
//! # fn run_parser() -> Result<(), syn::synom::Error> {
//! let t: Type = syn::parse_str("std::collections::HashMap<String, Value>")?;
//! #     Ok(())
//! # }
//! #
//! # fn main() {
//! #     run_parser().unwrap();
//! # }
//! ```
//!
//! The [`parse_quote!`] macro also uses this approach.
//!
//! [`parse_quote!`]: ../macro.parse_quote.html
//!
//! ## The `Parser` trait
//!
//! Some types can be parsed in several ways depending on context. For example
//! an [`Attribute`] can be either "outer" like `#[...]` or "inner" like
//! `#![...]` and parsing the wrong one would be a bug. Similarly [`Punctuated`]
//! may or may not allow trailing punctuation, and parsing it the wrong way
//! would either reject valid input or accept invalid input.
//!
//! [`Attribute`]: ../struct.Attribute.html
//! [`Punctuated`]: ../punctuated/index.html
//!
//! The `Synom` trait is not implemented in these cases because there is no good
//! behavior to consider the default.
//!
//! ```ignore
//! // Can't parse `Punctuated` without knowing whether trailing punctuation
//! // should be allowed in this context.
//! let path: Punctuated<PathSegment, Token![::]> = syn::parse(tokens)?;
//! ```
//!
//! In these cases the types provide a choice of parser functions rather than a
//! single `Synom` implementation, and those parser functions can be invoked
//! through the [`Parser`] trait.
//!
//! [`Parser`]: trait.Parser.html
//!
//! ```
//! # #[macro_use]
//! # extern crate syn;
//! #
//! # extern crate proc_macro2;
//! # use proc_macro2::TokenStream;
//! #
//! use syn::synom::Parser;
//! use syn::punctuated::Punctuated;
//! use syn::{PathSegment, Expr, Attribute};
//!
//! # fn run_parsers() -> Result<(), syn::synom::Error> {
//! #     let tokens = TokenStream::new().into();
//! // Parse a nonempty sequence of path segments separated by `::` punctuation
//! // with no trailing punctuation.
//! let parser = Punctuated::<PathSegment, Token![::]>::parse_separated_nonempty;
//! let path = parser.parse(tokens)?;
//!
//! #     let tokens = TokenStream::new().into();
//! // Parse a possibly empty sequence of expressions terminated by commas with
//! // an optional trailing punctuation.
//! let parser = Punctuated::<Expr, Token![,]>::parse_terminated;
//! let args = parser.parse(tokens)?;
//!
//! #     let tokens = TokenStream::new().into();
//! // Parse zero or more outer attributes but not inner attributes.
//! named!(outer_attrs -> Vec<Attribute>, many0!(Attribute::old_parse_outer));
//! let attrs = outer_attrs.parse(tokens)?;
//! #
//! #     Ok(())
//! # }
//! #
//! # fn main() {}
//! ```
//!
//! # Implementing a parser function
//!
//! Parser functions are usually implemented using the [`nom`]-style parser
//! combinator macros provided by Syn, but may also be implemented without
//! macros be using the low-level [`Cursor`] API directly.
//!
//! [`nom`]: https://github.com/Geal/nom
//!
//! The following parser combinator macros are available and a `Synom` parsing
//! example is provided for each one.
//!
//! - [`alt!`](../macro.alt.html)
//! - [`braces!`](../macro.braces.html)
//! - [`brackets!`](../macro.brackets.html)
//! - [`call!`](../macro.call.html)
//! - [`cond!`](../macro.cond.html)
//! - [`cond_reduce!`](../macro.cond_reduce.html)
//! - [`custom_keyword!`](../macro.custom_keyword.html)
//! - [`do_parse!`](../macro.do_parse.html)
//! - [`epsilon!`](../macro.epsilon.html)
//! - [`input_end!`](../macro.input_end.html)
//! - [`keyword!`](../macro.keyword.html)
//! - [`many0!`](../macro.many0.html)
//! - [`map!`](../macro.map.html)
//! - [`not!`](../macro.not.html)
//! - [`option!`](../macro.option.html)
//! - [`parens!`](../macro.parens.html)
//! - [`punct!`](../macro.punct.html)
//! - [`reject!`](../macro.reject.html)
//! - [`switch!`](../macro.switch.html)
//! - [`syn!`](../macro.syn.html)
//! - [`tuple!`](../macro.tuple.html)
//! - [`value!`](../macro.value.html)
//!
//! *This module is available if Syn is built with the `"parsing"` feature.*

use std::cell::Cell;
use std::rc::Rc;
use std::str::FromStr;

#[cfg(all(
    not(all(target_arch = "wasm32", target_os = "unknown")),
    feature = "proc-macro"
))]
use proc_macro;
use proc_macro2::{self, Delimiter, Group, Literal, Punct, Span, TokenStream, TokenTree};

use error::parse_error;
pub use error::{Error, PResult};

use buffer::{Cursor, TokenBuffer};
use parse::{Parse, ParseBuffer, ParseStream, Result};

/// Parsing interface implemented by all types that can be parsed in a default
/// way from a token stream.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This trait is available if Syn is built with the `"parsing"` feature.*
pub trait Synom: Sized {
    fn parse(input: Cursor) -> PResult<Self>;

    /// A short name of the type being parsed.
    ///
    /// The description should only be used for a simple name.  It should not
    /// contain newlines or sentence-ending punctuation, to facilitate embedding in
    /// larger user-facing strings.  Syn will use this description when building
    /// error messages about parse failures.
    ///
    /// # Examples
    ///
    /// ```
    /// # use syn::buffer::Cursor;
    /// # use syn::synom::{Synom, PResult};
    /// #
    /// struct ExprMacro {
    ///     // ...
    /// }
    ///
    /// impl Synom for ExprMacro {
    /// #   fn parse(input: Cursor) -> PResult<Self> { unimplemented!() }
    ///     // fn parse(...) -> ... { ... }
    ///
    ///     fn description() -> Option<&'static str> {
    ///         // Will result in messages like
    ///         //
    ///         //     "failed to parse macro invocation expression: $reason"
    ///         Some("macro invocation expression")
    ///     }
    /// }
    /// ```
    fn description() -> Option<&'static str> {
        None
    }
}

impl<T: Parse> Synom for T {
    fn parse(input: Cursor) -> PResult<Self> {
        let unexpected = Rc::new(Cell::new(None));
        let state = ParseBuffer::new(Span::call_site(), input, unexpected);
        let node = <T as Parse>::parse(&state)?;
        state.check_unexpected()?;
        Ok((node, state.cursor()))
    }
}

impl Parse for TokenStream {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| Ok((cursor.token_stream(), Cursor::empty())))
    }
}

impl Parse for TokenTree {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.token_tree() {
            Some((tt, rest)) => Ok((tt, rest)),
            None => Err(cursor.error("expected token tree")),
        })
    }
}

impl Parse for Group {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| {
            for delim in &[Delimiter::Parenthesis, Delimiter::Brace, Delimiter::Bracket] {
                if let Some((inside, span, rest)) = cursor.group(*delim) {
                    let mut group = Group::new(*delim, inside.token_stream());
                    group.set_span(span);
                    return Ok((group, rest));
                }
            }
            Err(cursor.error("expected group token"))
        })
    }
}

impl Parse for Punct {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.punct() {
            Some((punct, rest)) => Ok((punct, rest)),
            None => Err(cursor.error("expected punctuation token")),
        })
    }
}

impl Parse for Literal {
    fn parse(input: ParseStream) -> Result<Self> {
        input.step_cursor(|cursor| match cursor.literal() {
            Some((literal, rest)) => Ok((literal, rest)),
            None => Err(cursor.error("expected literal token")),
        })
    }
}

/// Parser that can parse Rust tokens into a particular syntax tree node.
///
/// Refer to the [module documentation] for details about parsing in Syn.
///
/// [module documentation]: index.html
///
/// *This trait is available if Syn is built with the `"parsing"` feature.*
pub trait Parser: Sized {
    type Output;

    /// Parse a proc-macro2 token stream into the chosen syntax tree node.
    fn parse2(self, tokens: TokenStream) -> Result<Self::Output>;

    /// Parse tokens of source code into the chosen syntax tree node.
    ///
    /// *This method is available if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", target_os = "unknown")),
        feature = "proc-macro"
    ))]
    fn parse(self, tokens: proc_macro::TokenStream) -> Result<Self::Output> {
        self.parse2(proc_macro2::TokenStream::from(tokens))
    }

    /// Parse a string of Rust code into the chosen syntax tree node.
    ///
    /// # Hygiene
    ///
    /// Every span in the resulting syntax tree will be set to resolve at the
    /// macro call site.
    fn parse_str(self, s: &str) -> Result<Self::Output> {
        self.parse2(proc_macro2::TokenStream::from_str(s)?)
    }
}

impl<F, T> Parser for F
where
    F: FnOnce(ParseStream) -> Result<T>,
{
    type Output = T;

    fn parse2(self, tokens: TokenStream) -> Result<T> {
        let buf = TokenBuffer::new2(tokens);
        let unexpected = Rc::new(Cell::new(None));
        let state = ParseBuffer::new(Span::call_site(), buf.begin(), unexpected);
        let node = self(&state)?;
        state.check_unexpected()?;
        if state.is_empty() {
            Ok(node)
        } else {
            Err(state.error("unexpected token"))
        }
    }
}

/// Extension traits that are made available within the `call!` parser.
///
/// *This module is available if Syn is built with the `"parsing"` feature.*
pub mod ext {
    use super::*;
    use proc_macro2::Ident;

    use parse::{ParseStream, Result};

    /// Additional parsing methods for `Ident`.
    ///
    /// This trait is sealed and cannot be implemented for types outside of Syn.
    ///
    /// *This trait is available if Syn is built with the `"parsing"` feature.*
    pub trait IdentExt: Sized + private::Sealed {
        /// Parses any identifier including keywords.
        ///
        /// This is useful when parsing a DSL which allows Rust keywords as
        /// identifiers.
        ///
        /// ```rust
        /// #[macro_use]
        /// extern crate syn;
        ///
        /// use syn::Ident;
        ///
        /// // Parses input that looks like `name = NAME` where `NAME` can be
        /// // any identifier.
        /// //
        /// // Examples:
        /// //
        /// //     name = anything
        /// //     name = impl
        /// named!(parse_dsl -> Ident, do_parse!(
        ///     custom_keyword!(name) >>
        ///     punct!(=) >>
        ///     name: call!(Ident::parse_any) >>
        ///     (name)
        /// ));
        /// #
        /// # fn main() {}
        /// ```
        fn parse_any(input: Cursor) -> PResult<Self>;

        fn parse_any2(input: ParseStream) -> Result<Self>;
    }

    impl IdentExt for Ident {
        fn parse_any(input: Cursor) -> PResult<Self> {
            input.ident().map_or_else(parse_error, Ok)
        }

        fn parse_any2(input: ParseStream) -> Result<Self> {
            input.step_cursor(|cursor| match cursor.ident() {
                Some((ident, rest)) => Ok((ident, rest)),
                None => Err(cursor.error("expected ident")),
            })
        }
    }

    mod private {
        use proc_macro2::Ident;

        pub trait Sealed {}

        impl Sealed for Ident {}
    }
}
<|endoftext|>


<commit_before>use crate::callback::CallbackSubscription;
use crate::callback::SubscribableCallback;
use crate::result;
use crate::result::TockResult;
use crate::result::TockValue;
use crate::syscalls;
use core::cell::Cell;
use core::isize;

const DRIVER_NUMBER: usize = 0x00000;

mod command_nr {
    pub const IS_DRIVER_AVAILABLE: usize = 0;
    pub const GET_CLOCK_FREQUENCY: usize = 1;
    pub const GET_CLOCK_VALUE: usize = 2;
    pub const STOP_ALARM: usize = 3;
    pub const SET_ALARM: usize = 4;
}

mod subscribe_nr {
    pub const SUBSCRIBE_CALLBACK: usize = 0;
}

pub fn sleep(duration: Duration) {
    let expired = Cell::new(false);
    let mut with_callback = with_callback(|_, _| expired.set(true));

    let mut timer = with_callback.init().unwrap();
    timer.set_alarm(duration).unwrap();

    syscalls::yieldk_for(|| expired.get());
}

pub fn with_callback<CB>(callback: CB) -> WithCallback<CB> {
    WithCallback {
        callback,
        clock_frequency: ClockFrequency { hz: 0 },
    }
}

pub struct WithCallback<CB> {
    callback: CB,
    clock_frequency: ClockFrequency,
}

impl<CB: FnMut(ClockValue, Alarm)> SubscribableCallback for WithCallback<CB> {
    fn call_rust(&mut self, clock_value: usize, alarm_id: usize, _: usize) {
        (self.callback)(
            ClockValue {
                num_ticks: clock_value as isize,
                clock_frequency: self.clock_frequency,
            },
            Alarm { alarm_id },
        );
    }
}

impl<CB> WithCallback<CB>
where
    Self: SubscribableCallback,
{
    pub fn init(&mut self) -> TockResult<Timer, TimerError> {
        let num_notifications =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::IS_DRIVER_AVAILABLE, 0, 0) };

        if num_notifications < 1 {
            return Err(TockValue::Expected(TimerError::NotSupported));
        }

        let clock_frequency =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::GET_CLOCK_FREQUENCY, 0, 0) };

        if clock_frequency < 1 {
            return Err(TockValue::Expected(TimerError::ErroneousClockFrequency(
                clock_frequency,
            )));
        }

        let clock_frequency = ClockFrequency {
            hz: clock_frequency as usize,
        };
        self.clock_frequency = clock_frequency;

        let subscription =
            syscalls::subscribe(DRIVER_NUMBER, subscribe_nr::SUBSCRIBE_CALLBACK, self);

        match subscription {
            Ok(subscription) => Ok(Timer {
                num_notifications: num_notifications as usize,
                clock_frequency,
                subscription,
            }),
            Err(result::ENOMEM) => Err(TockValue::Expected(TimerError::SubscriptionFailed)),
            Err(unexpected) => Err(TockValue::Unexpected(unexpected)),
        }
    }
}

pub struct Timer<'a> {
    num_notifications: usize,
    clock_frequency: ClockFrequency,
    #[allow(dead_code)] // Used in drop
    subscription: CallbackSubscription<'a>,
}

#[derive(Copy, Clone, Debug)]
pub enum TimerError {
    NotSupported,
    ErroneousClockFrequency(isize),
    SubscriptionFailed,
}

impl<'a> Timer<'a> {
    pub fn num_notifications(&self) -> usize {
        self.num_notifications
    }

    pub fn clock_frequency(&self) -> ClockFrequency {
        self.clock_frequency
    }

    pub fn get_current_clock(&self) -> ClockValue {
        let num_ticks =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::GET_CLOCK_VALUE, 0, 0) };

        ClockValue {
            num_ticks,
            clock_frequency: self.clock_frequency,
        }
    }

    pub fn stop_alarm(&mut self, alarm: Alarm) -> TockResult<(), StopAlarmError> {
        let return_code =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::STOP_ALARM, alarm.alarm_id, 0) };

        match return_code {
            result::SUCCESS => Ok(()),
            result::EALREADY => Err(TockValue::Expected(StopAlarmError::AlreadyDisabled)),
            unexpected => Err(TockValue::Unexpected(unexpected)),
        }
    }

    pub fn set_alarm(&mut self, duration: Duration) -> TockResult<Alarm, SetAlarmError> {
        let now = self.get_current_clock();
        let alarm_instant =
            now.num_ticks() as usize + (duration.ms() as usize * self.clock_frequency.hz()) / 1000;

        let alarm_id =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::SET_ALARM, alarm_instant, 0) };

        match alarm_id {
            _ if alarm_id >= 0 => Ok(Alarm {
                alarm_id: alarm_id as usize,
            }),
            result::ENOMEM => Err(TockValue::Expected(SetAlarmError::NoMemoryAvailable)),
            unexpected => Err(TockValue::Unexpected(unexpected)),
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct ClockFrequency {
    hz: usize,
}

impl ClockFrequency {
    pub fn hz(&self) -> usize {
        self.hz
    }
}

#[derive(Copy, Clone, Debug)]
pub struct ClockValue {
    num_ticks: isize,
    clock_frequency: ClockFrequency,
}

impl ClockValue {
    pub fn num_ticks(&self) -> isize {
        self.num_ticks
    }

    pub fn ms(&self) -> isize {
        if self.num_ticks.abs() < isize::MAX / 1000 {
            (1000 * self.num_ticks) / self.clock_frequency.hz() as isize
        } else {
            1000 * (self.num_ticks / self.clock_frequency.hz() as isize)
        }
    }
}

pub struct Alarm {
    alarm_id: usize,
}

impl Alarm {
    pub fn alarm_id(&self) -> usize {
        self.alarm_id
    }
}

#[derive(Clone, Copy, Debug)]
pub enum StopAlarmError {
    AlreadyDisabled,
}

#[derive(Clone, Copy, Debug)]
pub enum SetAlarmError {
    NoMemoryAvailable,
}

#[derive(Copy, Clone, Debug)]
pub struct Duration {
    ms: isize,
}

impl Duration {
    pub fn from_ms(ms: isize) -> Duration {
        Duration { ms }
    }

    pub fn ms(&self) -> isize {
        self.ms
    }
}
<commit_msg>Enhance the timer interface.<commit_after>use crate::callback::CallbackSubscription;
use crate::callback::SubscribableCallback;
use crate::result;
use crate::result::TockResult;
use crate::result::TockValue;
use crate::syscalls;
use core::cell::Cell;
use core::isize;
use core::ops::{Add, AddAssign, Sub};

const DRIVER_NUMBER: usize = 0x00000;

mod command_nr {
    pub const IS_DRIVER_AVAILABLE: usize = 0;
    pub const GET_CLOCK_FREQUENCY: usize = 1;
    pub const GET_CLOCK_VALUE: usize = 2;
    pub const STOP_ALARM: usize = 3;
    pub const SET_ALARM: usize = 4;
}

mod subscribe_nr {
    pub const SUBSCRIBE_CALLBACK: usize = 0;
}

pub fn sleep(duration: Duration<isize>) {
    let expired = Cell::new(false);
    let mut with_callback = with_callback(|_, _| expired.set(true));

    let mut timer = with_callback.init().unwrap();
    timer.set_alarm(duration).unwrap();

    syscalls::yieldk_for(|| expired.get());
}

pub fn with_callback<CB>(callback: CB) -> WithCallback<CB> {
    WithCallback {
        callback,
        clock_frequency: ClockFrequency { hz: 0 },
    }
}

pub struct WithCallback<CB> {
    callback: CB,
    clock_frequency: ClockFrequency,
}

impl<CB: FnMut(ClockValue, Alarm)> SubscribableCallback for WithCallback<CB> {
    fn call_rust(&mut self, clock_value: usize, alarm_id: usize, _: usize) {
        (self.callback)(
            ClockValue {
                num_ticks: clock_value as isize,
                clock_frequency: self.clock_frequency,
            },
            Alarm { alarm_id },
        );
    }
}

impl<CB> WithCallback<CB>
where
    Self: SubscribableCallback,
{
    pub fn init(&mut self) -> TockResult<Timer, TimerError> {
        let num_notifications =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::IS_DRIVER_AVAILABLE, 0, 0) };

        if num_notifications < 1 {
            return Err(TockValue::Expected(TimerError::NotSupported));
        }

        let clock_frequency =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::GET_CLOCK_FREQUENCY, 0, 0) };

        if clock_frequency < 1 {
            return Err(TockValue::Expected(TimerError::ErroneousClockFrequency(
                clock_frequency,
            )));
        }

        let clock_frequency = ClockFrequency {
            hz: clock_frequency as usize,
        };
        self.clock_frequency = clock_frequency;

        let subscription =
            syscalls::subscribe(DRIVER_NUMBER, subscribe_nr::SUBSCRIBE_CALLBACK, self);

        match subscription {
            Ok(subscription) => Ok(Timer {
                num_notifications: num_notifications as usize,
                clock_frequency,
                subscription,
            }),
            Err(result::ENOMEM) => Err(TockValue::Expected(TimerError::SubscriptionFailed)),
            Err(unexpected) => Err(TockValue::Unexpected(unexpected)),
        }
    }
}

pub struct Timer<'a> {
    num_notifications: usize,
    clock_frequency: ClockFrequency,
    #[allow(dead_code)] // Used in drop
    subscription: CallbackSubscription<'a>,
}

#[derive(Copy, Clone, Debug)]
pub enum TimerError {
    NotSupported,
    ErroneousClockFrequency(isize),
    SubscriptionFailed,
}

impl<'a> Timer<'a> {
    pub fn num_notifications(&self) -> usize {
        self.num_notifications
    }

    pub fn clock_frequency(&self) -> ClockFrequency {
        self.clock_frequency
    }

    pub fn get_current_clock(&self) -> ClockValue {
        let num_ticks =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::GET_CLOCK_VALUE, 0, 0) };

        ClockValue {
            num_ticks,
            clock_frequency: self.clock_frequency,
        }
    }

    pub fn stop_alarm(&mut self, alarm: Alarm) -> TockResult<(), StopAlarmError> {
        let return_code =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::STOP_ALARM, alarm.alarm_id, 0) };

        match return_code {
            result::SUCCESS => Ok(()),
            result::EALREADY => Err(TockValue::Expected(StopAlarmError::AlreadyDisabled)),
            unexpected => Err(TockValue::Unexpected(unexpected)),
        }
    }

    pub fn set_alarm(&mut self, duration: Duration<isize>) -> TockResult<Alarm, SetAlarmError> {
        let now = self.get_current_clock();
        let alarm_instant =
            now.num_ticks() as usize + (duration.ms() as usize * self.clock_frequency.hz()) / 1000;

        let alarm_id =
            unsafe { syscalls::command(DRIVER_NUMBER, command_nr::SET_ALARM, alarm_instant, 0) };

        match alarm_id {
            _ if alarm_id >= 0 => Ok(Alarm {
                alarm_id: alarm_id as usize,
            }),
            result::ENOMEM => Err(TockValue::Expected(SetAlarmError::NoMemoryAvailable)),
            unexpected => Err(TockValue::Unexpected(unexpected)),
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct ClockFrequency {
    hz: usize,
}

impl ClockFrequency {
    pub fn hz(&self) -> usize {
        self.hz
    }
}

#[derive(Copy, Clone, Debug)]
pub struct ClockValue {
    num_ticks: isize,
    clock_frequency: ClockFrequency,
}

impl ClockValue {
    pub fn num_ticks(&self) -> isize {
        self.num_ticks
    }

    pub fn ms(&self) -> isize {
        if self.num_ticks.abs() < isize::MAX / 1000 {
            (1000 * self.num_ticks) / self.clock_frequency.hz() as isize
        } else {
            1000 * (self.num_ticks / self.clock_frequency.hz() as isize)
        }
    }

    pub fn ms_f64(&self) -> f64 {
        1000.0 * (self.num_ticks as f64) / (self.clock_frequency.hz() as f64)
    }
}

pub struct Alarm {
    alarm_id: usize,
}

impl Alarm {
    pub fn alarm_id(&self) -> usize {
        self.alarm_id
    }
}

#[derive(Clone, Copy, Debug)]
pub enum StopAlarmError {
    AlreadyDisabled,
}

#[derive(Clone, Copy, Debug)]
pub enum SetAlarmError {
    NoMemoryAvailable,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Duration<T> {
    ms: T,
}

impl<T> Duration<T> {
    pub const fn from_ms(ms: T) -> Duration<T> {
        Duration { ms }
    }
}

impl<T> Duration<T>
where
    T: Copy,
{
    pub fn ms(&self) -> T {
        self.ms
    }
}

impl<T> Sub for Duration<T>
where
    T: Sub<Output = T>,
{
    type Output = Duration<T>;

    fn sub(self, other: Duration<T>) -> Duration<T> {
        Duration {
            ms: self.ms - other.ms,
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct Timestamp<T> {
    ms: T,
}

impl<T> Timestamp<T> {
    pub const fn from_ms(ms: T) -> Timestamp<T> {
        Timestamp { ms }
    }
}

impl<T> Timestamp<T>
where
    T: Copy,
{
    pub fn ms(&self) -> T {
        self.ms
    }
}

impl Timestamp<isize> {
    pub fn from_clock_value(value: ClockValue) -> Timestamp<isize> {
        Timestamp { ms: value.ms() }
    }
}

impl Timestamp<f64> {
    pub fn from_clock_value(value: ClockValue) -> Timestamp<f64> {
        Timestamp { ms: value.ms_f64() }
    }
}

impl<T> Sub for Timestamp<T>
where
    T: Sub<Output = T>,
{
    type Output = Duration<T>;

    fn sub(self, other: Timestamp<T>) -> Duration<T> {
        Duration::from_ms(self.ms - other.ms)
    }
}

impl<T> Add<Duration<T>> for Timestamp<T>
where
    T: Copy + Add<Output = T>,
{
    type Output = Timestamp<T>;

    fn add(self, duration: Duration<T>) -> Timestamp<T> {
        Timestamp {
            ms: self.ms + duration.ms(),
        }
    }
}

impl<T> AddAssign<Duration<T>> for Timestamp<T>
where
    T: Copy + AddAssign,
{
    fn add_assign(&mut self, duration: Duration<T>) {
        self.ms += duration.ms();
    }
}
<|endoftext|>


<commit_before>use std::time::{SystemTime, Duration, UNIX_EPOCH};

pub struct Timer {
    start_mark: u64,
    stop_mark: u64,
    paused_mark: u64,
    running: bool,
    paused: bool,
}

impl Timer {
    pub fn new() -> Self {
        Timer {
            start_mark: 0,
            stop_mark: 0,
            paused_mark: 0,
            running: false,
            paused: false,
        }
    }

    pub fn start(&mut self) {
        if self.running {
            return;
        }
        self.start_mark = precise_time_ns();
        /*
        unsafe {
            self.start_mark = sdl2::sys::timer::SDL_GetTicks();
        }
        */
        self.stop_mark = 0;
        self.paused_mark = 0;
        self.running = true;
        self.paused = false;
    }

    pub fn stop(&mut self) {
        if !self.running {
            return;
        }
        self.stop_mark = precise_time_ns();
        /*
        unsafe {
            self.stop_mark = sdl2::sys::timer::SDL_GetTicks();
        }
        */
        self.running = false;
        self.paused = false;
    }

    pub fn restart(&mut self) {
        self.stop();
        self.start();
    }

    pub fn pause(&mut self) {
        if !self.running || self.paused {
            return;
        }
        self.paused_mark = precise_time_ns() - self.start_mark;
        /*
        unsafe {
            self.paused_mark = sdl2::sys::timer::SDL_GetTicks() - self.start_mark;
        }
        */
        self.running = false;
        self.paused = true;
    }

    pub fn unpause(&mut self) {
        if self.running || !self.paused {
            return;
        }
        self.start_mark = precise_time_ns() - self.paused_mark;
        /*
        unsafe {
            self.start_mark = sdl2::sys::timer::SDL_GetTicks() - self.paused_mark;
        }
        */
        self.paused_mark = 0;
        self.running = true;
        self.paused = false;
    }

    pub fn is_running(&mut self) -> bool {
        self.running
    }

    pub fn is_paused(&mut self) -> bool {
        self.paused
    }

    pub fn delta(&mut self) -> u64 {
        if self.running {
            return self.current_time();
        }

        if self.paused {
            return self.paused_mark;
        }

        if self.start_mark == 0 {
            return 0;
        }

        return self.stop_mark - self.start_mark;
    }

    pub fn delta_ms(&mut self) -> f64 {
        self.delta() as f64 / 1_000_000.0
    }

    pub fn delta_s(&mut self) -> f64 {
        self.delta() as f64 / 1_000_000_000.0
    }

    pub fn current_time(&mut self) -> u64 {
        return precise_time_ns() - self.start_mark;
        /*
        unsafe {
            return sdl2::sys::timer::SDL_GetTicks() - self.start_mark;
        }
        */
    }

}

pub fn precise_time_ns() -> u64 {
    let start = SystemTime::now();
    let since_epoch = start.duration_since(UNIX_EPOCH).expect("Moving back in time. This should not happen.");
    return since_epoch.as_nanos() as u64;
}<commit_msg>Added a wasm32 version of the nanoseconds stuff. Still need to work out the sdl2, and stb:image stuff<commit_after>#[cfg(not(target_arch = "wasm32"))]
use std::time::{SystemTime, Duration, UNIX_EPOCH};
#[cfg(target_arch = "wasm32")]
use stdweb::web::Date;

pub struct Timer {
    start_mark: u64,
    stop_mark: u64,
    paused_mark: u64,
    running: bool,
    paused: bool,
}

impl Timer {
    pub fn new() -> Self {
        Timer {
            start_mark: 0,
            stop_mark: 0,
            paused_mark: 0,
            running: false,
            paused: false,
        }
    }

    pub fn start(&mut self) {
        if self.running {
            return;
        }
        self.start_mark = precise_time_ns();
        /*
        unsafe {
            self.start_mark = sdl2::sys::timer::SDL_GetTicks();
        }
        */
        self.stop_mark = 0;
        self.paused_mark = 0;
        self.running = true;
        self.paused = false;
    }

    pub fn stop(&mut self) {
        if !self.running {
            return;
        }
        self.stop_mark = precise_time_ns();
        /*
        unsafe {
            self.stop_mark = sdl2::sys::timer::SDL_GetTicks();
        }
        */
        self.running = false;
        self.paused = false;
    }

    pub fn restart(&mut self) {
        self.stop();
        self.start();
    }

    pub fn pause(&mut self) {
        if !self.running || self.paused {
            return;
        }
        self.paused_mark = precise_time_ns() - self.start_mark;
        /*
        unsafe {
            self.paused_mark = sdl2::sys::timer::SDL_GetTicks() - self.start_mark;
        }
        */
        self.running = false;
        self.paused = true;
    }

    pub fn unpause(&mut self) {
        if self.running || !self.paused {
            return;
        }
        self.start_mark = precise_time_ns() - self.paused_mark;
        /*
        unsafe {
            self.start_mark = sdl2::sys::timer::SDL_GetTicks() - self.paused_mark;
        }
        */
        self.paused_mark = 0;
        self.running = true;
        self.paused = false;
    }

    pub fn is_running(&mut self) -> bool {
        self.running
    }

    pub fn is_paused(&mut self) -> bool {
        self.paused
    }

    pub fn delta(&mut self) -> u64 {
        if self.running {
            return self.current_time();
        }

        if self.paused {
            return self.paused_mark;
        }

        if self.start_mark == 0 {
            return 0;
        }

        return self.stop_mark - self.start_mark;
    }

    pub fn delta_ms(&mut self) -> f64 {
        self.delta() as f64 / 1_000_000.0
    }

    pub fn delta_s(&mut self) -> f64 {
        self.delta() as f64 / 1_000_000_000.0
    }

    pub fn current_time(&mut self) -> u64 {
        return precise_time_ns() - self.start_mark;
        /*
        unsafe {
            return sdl2::sys::timer::SDL_GetTicks() - self.start_mark;
        }
        */
    }

}

#[cfg(not(target_arch = "wasm32"))]
pub fn precise_time_ns() -> u64 {
    let start = SystemTime::now();
    let since_epoch = start.duration_since(UNIX_EPOCH).expect("Moving back in time. This should not happen.");
    return since_epoch.as_nanos() as u64;
}

#[cfg(target_arch = "wasm32")]
pub fn precise_time_ns() -> u64 {
    // Date::now() is in milliseconds so we convert it to nanoseconds
    return (Date::now() * 1000) as u64
}<|endoftext|>


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

use std::io;
use std::fmt;
use std::error::Error;
use std::borrow::Cow;
use std::fmt::Display;
use std::ops::{Div, Mul, Rem};

use nix;
use term;
use dbus;
use serde;

use consts::SECTOR_SIZE;

pub type StratisResult<T> = Result<T, StratisError>;

// macros for unsigned operations on Sectors and Bytes
macro_rules! unsigned_div {
    ($t: ty, $T: ident) => {
        impl Div<$t> for $T {
            type Output = $T;
            fn div(self, rhs: $t) -> $T {
                $T(self.0 / rhs as u64)
            }
        }
    }
}

macro_rules! unsigned_mul {
    ($t: ty, $T: ident) => {
        impl Mul<$t> for $T {
            type Output = $T;
            fn mul(self, rhs: $t) -> $T {
                $T(self.0 * rhs as u64)
            }
        }

        impl Mul<$T> for $t {
            type Output = $T;
            fn mul(self, rhs: $T) -> $T {
                $T(self as u64 * rhs.0)
            }
        }
    }
}

macro_rules! unsigned_rem {
    ($t: ty, $T: ident) => {
        impl Rem<$t> for $T {
            type Output = $T;
            fn rem(self, rhs: $t) -> $T {
                $T(self.0 % rhs as u64)
            }
        }
    }
}

custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Bytes(pub u64);
}

impl Bytes {
    /// Return the number of Sectors fully contained in these bytes.
    pub fn sectors(self) -> Sectors {
        Sectors(self.0 / SECTOR_SIZE as u64)
    }
}

unsigned_mul!(u64, Bytes);
unsigned_mul!(u32, Bytes);
unsigned_mul!(u16, Bytes);
unsigned_mul!(u8, Bytes);
unsigned_mul!(usize, Bytes);

impl Display for Bytes {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{} bytes", self.0)
    }
}

// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(pub u64);
}

impl Sectors {
    /// The number of bytes in these sectors.
    pub fn bytes(&self) -> Bytes {
        Bytes(self.0 * SECTOR_SIZE as u64)
    }
}

unsigned_div!(u64, Sectors);
unsigned_div!(u32, Sectors);
unsigned_div!(u16, Sectors);
unsigned_div!(u8, Sectors);
unsigned_div!(usize, Sectors);

unsigned_mul!(u64, Sectors);
unsigned_mul!(u32, Sectors);
unsigned_mul!(u16, Sectors);
unsigned_mul!(u8, Sectors);
unsigned_mul!(usize, Sectors);

unsigned_rem!(u64, Sectors);
unsigned_rem!(u32, Sectors);
unsigned_rem!(u16, Sectors);
unsigned_rem!(u8, Sectors);
unsigned_rem!(usize, Sectors);

impl Display for Sectors {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{} sectors", self.0)
    }
}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

// An error type for errors generated within Stratis
//
#[derive(Debug)]
pub struct InternalError(pub Cow<'static, str>);

impl fmt::Display for InternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.0)
    }
}

impl Error for InternalError {
    fn description(&self) -> &str {
        &self.0
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum StratisError {
    Stratis(InternalError),
    Io(io::Error),
    Nix(nix::Error),
    Dbus(dbus::Error),
    Term(term::Error),
}

impl fmt::Display for StratisError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StratisError::Stratis(ref err) => write!(f, "Stratis error: {}", err.0),
            StratisError::Io(ref err) => write!(f, "IO error: {}", err),
            StratisError::Nix(ref err) => write!(f, "Nix error: {}", err.errno().desc()),
            StratisError::Dbus(ref err) => {
                write!(f, "Dbus error: {}", err.message().unwrap_or("Unknown"))
            }
            StratisError::Term(ref err) => write!(f, "Term error: {}", err),
        }
    }
}

impl Error for StratisError {
    fn description(&self) -> &str {
        match *self {
            StratisError::Stratis(ref err) => &err.0,
            StratisError::Io(ref err) => err.description(),
            StratisError::Nix(ref err) => err.errno().desc(),
            StratisError::Dbus(ref err) => err.message().unwrap_or("D-Bus Error"),
            StratisError::Term(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            StratisError::Stratis(ref err) => Some(err),
            StratisError::Io(ref err) => Some(err),
            StratisError::Nix(ref err) => Some(err),
            StratisError::Dbus(ref err) => Some(err),
            StratisError::Term(ref err) => Some(err),
        }
    }
}

impl From<InternalError> for StratisError {
    fn from(err: InternalError) -> StratisError {
        StratisError::Stratis(err)
    }
}

impl From<io::Error> for StratisError {
    fn from(err: io::Error) -> StratisError {
        StratisError::Io(err)
    }
}

impl From<nix::Error> for StratisError {
    fn from(err: nix::Error) -> StratisError {
        StratisError::Nix(err)
    }
}

impl From<dbus::Error> for StratisError {
    fn from(err: dbus::Error) -> StratisError {
        StratisError::Dbus(err)
    }
}

impl From<term::Error> for StratisError {
    fn from(err: term::Error) -> StratisError {
        StratisError::Term(err)
    }
}
<commit_msg>Implement AddAssign for Bytes and Sectors.<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::fmt;
use std::error::Error;
use std::borrow::Cow;
use std::fmt::Display;
use std::ops::{Div, Mul, Rem};

use nix;
use term;
use dbus;
use serde;

use consts::SECTOR_SIZE;

pub type StratisResult<T> = Result<T, StratisError>;

// macros for unsigned operations on Sectors and Bytes
macro_rules! unsigned_div {
    ($t: ty, $T: ident) => {
        impl Div<$t> for $T {
            type Output = $T;
            fn div(self, rhs: $t) -> $T {
                $T(self.0 / rhs as u64)
            }
        }
    }
}

macro_rules! unsigned_mul {
    ($t: ty, $T: ident) => {
        impl Mul<$t> for $T {
            type Output = $T;
            fn mul(self, rhs: $t) -> $T {
                $T(self.0 * rhs as u64)
            }
        }

        impl Mul<$T> for $t {
            type Output = $T;
            fn mul(self, rhs: $T) -> $T {
                $T(self as u64 * rhs.0)
            }
        }
    }
}

macro_rules! unsigned_rem {
    ($t: ty, $T: ident) => {
        impl Rem<$t> for $T {
            type Output = $T;
            fn rem(self, rhs: $t) -> $T {
                $T(self.0 % rhs as u64)
            }
        }
    }
}

custom_derive! {
    #[derive(NewtypeAdd, NewtypeAddAssign,
             NewtypeDeref,
             NewtypeFrom,
             NewtypeSub,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Bytes(pub u64);
}

impl Bytes {
    /// Return the number of Sectors fully contained in these bytes.
    pub fn sectors(self) -> Sectors {
        Sectors(self.0 / SECTOR_SIZE as u64)
    }
}

unsigned_mul!(u64, Bytes);
unsigned_mul!(u32, Bytes);
unsigned_mul!(u16, Bytes);
unsigned_mul!(u8, Bytes);
unsigned_mul!(usize, Bytes);

impl Display for Bytes {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{} bytes", self.0)
    }
}

// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeAdd, NewtypeAddAssign,
             NewtypeDeref,
             NewtypeFrom,
             NewtypeSub,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(pub u64);
}

impl Sectors {
    /// The number of bytes in these sectors.
    pub fn bytes(&self) -> Bytes {
        Bytes(self.0 * SECTOR_SIZE as u64)
    }
}

unsigned_div!(u64, Sectors);
unsigned_div!(u32, Sectors);
unsigned_div!(u16, Sectors);
unsigned_div!(u8, Sectors);
unsigned_div!(usize, Sectors);

unsigned_mul!(u64, Sectors);
unsigned_mul!(u32, Sectors);
unsigned_mul!(u16, Sectors);
unsigned_mul!(u8, Sectors);
unsigned_mul!(usize, Sectors);

unsigned_rem!(u64, Sectors);
unsigned_rem!(u32, Sectors);
unsigned_rem!(u16, Sectors);
unsigned_rem!(u8, Sectors);
unsigned_rem!(usize, Sectors);

impl Display for Sectors {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{} sectors", self.0)
    }
}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

// An error type for errors generated within Stratis
//
#[derive(Debug)]
pub struct InternalError(pub Cow<'static, str>);

impl fmt::Display for InternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.0)
    }
}

impl Error for InternalError {
    fn description(&self) -> &str {
        &self.0
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum StratisError {
    Stratis(InternalError),
    Io(io::Error),
    Nix(nix::Error),
    Dbus(dbus::Error),
    Term(term::Error),
}

impl fmt::Display for StratisError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            StratisError::Stratis(ref err) => write!(f, "Stratis error: {}", err.0),
            StratisError::Io(ref err) => write!(f, "IO error: {}", err),
            StratisError::Nix(ref err) => write!(f, "Nix error: {}", err.errno().desc()),
            StratisError::Dbus(ref err) => {
                write!(f, "Dbus error: {}", err.message().unwrap_or("Unknown"))
            }
            StratisError::Term(ref err) => write!(f, "Term error: {}", err),
        }
    }
}

impl Error for StratisError {
    fn description(&self) -> &str {
        match *self {
            StratisError::Stratis(ref err) => &err.0,
            StratisError::Io(ref err) => err.description(),
            StratisError::Nix(ref err) => err.errno().desc(),
            StratisError::Dbus(ref err) => err.message().unwrap_or("D-Bus Error"),
            StratisError::Term(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            StratisError::Stratis(ref err) => Some(err),
            StratisError::Io(ref err) => Some(err),
            StratisError::Nix(ref err) => Some(err),
            StratisError::Dbus(ref err) => Some(err),
            StratisError::Term(ref err) => Some(err),
        }
    }
}

impl From<InternalError> for StratisError {
    fn from(err: InternalError) -> StratisError {
        StratisError::Stratis(err)
    }
}

impl From<io::Error> for StratisError {
    fn from(err: io::Error) -> StratisError {
        StratisError::Io(err)
    }
}

impl From<nix::Error> for StratisError {
    fn from(err: nix::Error) -> StratisError {
        StratisError::Nix(err)
    }
}

impl From<dbus::Error> for StratisError {
    fn from(err: dbus::Error) -> StratisError {
        StratisError::Dbus(err)
    }
}

impl From<term::Error> for StratisError {
    fn from(err: term::Error) -> StratisError {
        StratisError::Term(err)
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use syntax::ast;
use syntax::ast::*;
use syntax::ast_util::{is_comparison_binop, binop_to_string};
use syntax::codemap::Span;
use syntax::visit::{FnKind, Visitor, walk_ty};
use rustc::middle::ty;
use syntax::codemap::ExpnInfo;

use utils::{in_macro, match_type, snippet, span_lint, span_help_and_lint, in_external_macro};
use utils::{LL_PATH, VEC_PATH};

/// Handles all the linting of funky types
#[allow(missing_copy_implementations)]
pub struct TypePass;

declare_lint!(pub BOX_VEC, Warn,
              "usage of `Box<Vec<T>>`, vector elements are already on the heap");
declare_lint!(pub LINKEDLIST, Warn,
              "usage of LinkedList, usually a vector is faster, or a more specialized data \
               structure like a RingBuf");

impl LintPass for TypePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOX_VEC, LINKEDLIST)
    }

    fn check_ty(&mut self, cx: &Context, ast_ty: &ast::Ty) {
        if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) {
            if let ty::TyBox(ref inner) = ty.sty {
                if match_type(cx, inner, &VEC_PATH) {
                    span_help_and_lint(
                        cx, BOX_VEC, ast_ty.span,
                        "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?",
                        "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation");
                }
            }
            else if match_type(cx, ty, &LL_PATH) {
                span_help_and_lint(
                    cx, LINKEDLIST, ast_ty.span,
                    "I see you're using a LinkedList! Perhaps you meant some other data structure?",
                    "a RingBuf might work");
            }
        }
    }
}

#[allow(missing_copy_implementations)]
pub struct LetPass;

declare_lint!(pub LET_UNIT_VALUE, Warn,
              "creating a let binding to a value of unit type, which usually can't be used afterwards");

fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) {
    if in_macro(cx, info) { return; }
    if let DeclLocal(ref local) = decl.node {
        let bindtype = &cx.tcx.pat_ty(&*local.pat).sty;
        if *bindtype == ty::TyTuple(vec![]) {
            span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
                "this let-binding has unit value. Consider omitting `let {} =`",
                snippet(cx, local.pat.span, "..")));
        }
    }
}

impl LintPass for LetPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(LET_UNIT_VALUE)
    }

    fn check_decl(&mut self, cx: &Context, decl: &Decl) {
        cx.sess().codemap().with_expn_info(
            decl.span.expn_id,
            |info| check_let_unit(cx, decl, info));
    }
}

declare_lint!(pub UNIT_CMP, Warn,
              "comparing unit values (which is always `true` or `false`, respectively)");

#[allow(missing_copy_implementations)]
pub struct UnitCmp;

impl LintPass for UnitCmp {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_CMP)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, _) = expr.node {
            let op = cmp.node;
            let sty = &cx.tcx.expr_ty(left).sty;
            if *sty == ty::TyTuple(vec![]) && is_comparison_binop(op) {
                let result = match op {
                    BiEq | BiLe | BiGe => "true",
                    _ => "false"
                };
                span_lint(cx, UNIT_CMP, expr.span, &format!(
                    "{}-comparison of unit values detected. This will always be {}",
                    binop_to_string(op), result));
            }
        }
    }
}

pub struct CastPass;

declare_lint!(pub CAST_PRECISION_LOSS, Allow,
              "casts that cause loss of precision, e.g `x as f32` where `x: u64`");
declare_lint!(pub CAST_SIGN_LOSS, Allow,
              "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`");
declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow,
              "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`");

/// Returns the size in bits of an integral type.
/// Will return 0 if the type is not an int or uint variant
fn int_ty_to_nbits(typ: &ty::TyS) -> usize {
    let n = match &typ.sty {
    &ty::TyInt(i) =>  4 << (i as usize),
    &ty::TyUint(u) => 4 << (u as usize),
    _ => 0
    };
    // n == 4 is the usize/isize case
    if n == 4 { ::std::usize::BITS } else { n }
}

impl LintPass for CastPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(CAST_PRECISION_LOSS,
                    CAST_SIGN_LOSS,
                    CAST_POSSIBLE_TRUNCATION)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprCast(ref ex, _) = expr.node {
            let (cast_from, cast_to) = (cx.tcx.expr_ty(&*ex), cx.tcx.expr_ty(expr));
            if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
                match (cast_from.is_integral(), cast_to.is_integral()) {
                    (true, false) => {
                        let from_nbits = int_ty_to_nbits(cast_from);
                        let to_nbits : usize = match &cast_to.sty {
                            &ty::TyFloat(ast::TyF32) => 32,
                            &ty::TyFloat(ast::TyF64) => 64,
                            _ => 0
                        };
                        if from_nbits != 0 {
                            if from_nbits >= to_nbits {
                                span_lint(cx, CAST_PRECISION_LOSS, expr.span,
                                          &format!("converting from {0} to {1}, which causes a loss of precision \
                                          			({0} is {2} bits wide, but {1}'s mantissa is only {3} bits wide)",
                                                   cast_from, cast_to, from_nbits, if to_nbits == 64 {52} else {23} ));
                            }
                        }
                    },
                    (false, true) => {
                        span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span,
                                  &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to));
                        if !cast_to.is_signed() {
                            span_lint(cx, CAST_SIGN_LOSS, expr.span,
                                      &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to));
                        }
                    },
                    (true, true) => {
                        if cast_from.is_signed() && !cast_to.is_signed() {
                            span_lint(cx, CAST_SIGN_LOSS, expr.span,
                                      &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to));
                        }
                        let from_nbits = int_ty_to_nbits(cast_from);
                        let to_nbits   = int_ty_to_nbits(cast_to);
                        if to_nbits < from_nbits ||
                           (!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) {
                                span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span,
                                          &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to));
                        }
                    }
                    (false, false) => {
                        if let (&ty::TyFloat(ast::TyF64),
                                &ty::TyFloat(ast::TyF32)) = (&cast_from.sty, &cast_to.sty) {
                            span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, "casting f64 to f32 may cause truncation of the value");
                        }
                    }
                }
            }
        }
    }
}

declare_lint!(pub TYPE_COMPLEXITY, Warn,
              "usage of very complex types; recommends factoring out parts into `type` definitions");

#[allow(missing_copy_implementations)]
pub struct TypeComplexityPass;

impl LintPass for TypeComplexityPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(TYPE_COMPLEXITY)
    }

    fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
        check_fndecl(cx, decl);
    }

    fn check_struct_field(&mut self, cx: &Context, field: &StructField) {
        check_type(cx, &*field.node.ty);
    }

    fn check_variant(&mut self, cx: &Context, var: &Variant, _: &Generics) {
        // StructVariant is covered by check_struct_field
        if let TupleVariantKind(ref args) = var.node.kind {
            for arg in args {
                check_type(cx, &*arg.ty);
            }
        }
    }

    fn check_item(&mut self, cx: &Context, item: &Item) {
        match item.node {
            ItemStatic(ref ty, _, _) |
            ItemConst(ref ty, _) => check_type(cx, ty),
            // functions, enums, structs, impls and traits are covered
            _ => ()
        }
    }

    fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) {
        match item.node {
            ConstTraitItem(ref ty, _) |
            TypeTraitItem(_, Some(ref ty)) => check_type(cx, ty),
            MethodTraitItem(MethodSig { ref decl, .. }, None) => check_fndecl(cx, decl),
            // methods with default impl are covered by check_fn
            _ => ()
        }
    }

    fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) {
        match item.node {
            ConstImplItem(ref ty, _) |
            TypeImplItem(ref ty) => check_type(cx, ty),
            // methods are covered by check_fn
            _ => ()
        }
    }

    fn check_local(&mut self, cx: &Context, local: &Local) {
        if let Some(ref ty) = local.ty {
            check_type(cx, ty);
        }
    }
}

fn check_fndecl(cx: &Context, decl: &FnDecl) {
    for arg in &decl.inputs {
        check_type(cx, &*arg.ty);
    }
    if let Return(ref ty) = decl.output {
        check_type(cx, ty);
    }
}

fn check_type(cx: &Context, ty: &ast::Ty) {
    let score = {
        let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
        visitor.visit_ty(ty);
        visitor.score
    };
    // println!("{:?} --> {}", ty, score);
    if score > 250 {
        span_lint(cx, TYPE_COMPLEXITY, ty.span, &format!(
            "very complex type used. Consider factoring parts into `type` definitions"));
    }
}

/// Walks a type and assigns a complexity score to it.
struct TypeComplexityVisitor {
    /// total complexity score of the type
    score: u32,
    /// current nesting level
    nest: u32,
}

impl<'v> Visitor<'v> for TypeComplexityVisitor {
    fn visit_ty(&mut self, ty: &'v ast::Ty) {
        let (add_score, sub_nest) = match ty.node {
            // _, &x and *x have only small overhead; don't mess with nesting level
            TyInfer |
            TyPtr(..) |
            TyRptr(..) => (1, 0),

            // the "normal" components of a type: named types, arrays/tuples
            TyPath(..) |
            TyVec(..) |
            TyTup(..) |
            TyFixedLengthVec(..) => (10 * self.nest, 1),

            // "Sum" of trait bounds
            TyObjectSum(..) => (20 * self.nest, 0),

            // function types and "for<...>" bring a lot of overhead
            TyBareFn(..) |
            TyPolyTraitRef(..) => (50 * self.nest, 1),

            _ => (0, 0)
        };
        self.score += add_score;
        self.nest += sub_nest;
        walk_ty(self, ty);
        self.nest -= sub_nest;
    }
}
<commit_msg>types: check for macros in type complexity check<commit_after>use rustc::lint::*;
use syntax::ast;
use syntax::ast::*;
use syntax::ast_util::{is_comparison_binop, binop_to_string};
use syntax::codemap::Span;
use syntax::visit::{FnKind, Visitor, walk_ty};
use rustc::middle::ty;
use syntax::codemap::ExpnInfo;

use utils::{in_macro, match_type, snippet, span_lint, span_help_and_lint, in_external_macro};
use utils::{LL_PATH, VEC_PATH};

/// Handles all the linting of funky types
#[allow(missing_copy_implementations)]
pub struct TypePass;

declare_lint!(pub BOX_VEC, Warn,
              "usage of `Box<Vec<T>>`, vector elements are already on the heap");
declare_lint!(pub LINKEDLIST, Warn,
              "usage of LinkedList, usually a vector is faster, or a more specialized data \
               structure like a RingBuf");

impl LintPass for TypePass {
    fn get_lints(&self) -> LintArray {
        lint_array!(BOX_VEC, LINKEDLIST)
    }

    fn check_ty(&mut self, cx: &Context, ast_ty: &ast::Ty) {
        if let Some(ty) = cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) {
            if let ty::TyBox(ref inner) = ty.sty {
                if match_type(cx, inner, &VEC_PATH) {
                    span_help_and_lint(
                        cx, BOX_VEC, ast_ty.span,
                        "you seem to be trying to use `Box<Vec<T>>`. Did you mean to use `Vec<T>`?",
                        "`Vec<T>` is already on the heap, `Box<Vec<T>>` makes an extra allocation");
                }
            }
            else if match_type(cx, ty, &LL_PATH) {
                span_help_and_lint(
                    cx, LINKEDLIST, ast_ty.span,
                    "I see you're using a LinkedList! Perhaps you meant some other data structure?",
                    "a RingBuf might work");
            }
        }
    }
}

#[allow(missing_copy_implementations)]
pub struct LetPass;

declare_lint!(pub LET_UNIT_VALUE, Warn,
              "creating a let binding to a value of unit type, which usually can't be used afterwards");

fn check_let_unit(cx: &Context, decl: &Decl, info: Option<&ExpnInfo>) {
    if in_macro(cx, info) { return; }
    if let DeclLocal(ref local) = decl.node {
        let bindtype = &cx.tcx.pat_ty(&*local.pat).sty;
        if *bindtype == ty::TyTuple(vec![]) {
            span_lint(cx, LET_UNIT_VALUE, decl.span, &format!(
                "this let-binding has unit value. Consider omitting `let {} =`",
                snippet(cx, local.pat.span, "..")));
        }
    }
}

impl LintPass for LetPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(LET_UNIT_VALUE)
    }

    fn check_decl(&mut self, cx: &Context, decl: &Decl) {
        cx.sess().codemap().with_expn_info(
            decl.span.expn_id,
            |info| check_let_unit(cx, decl, info));
    }
}

declare_lint!(pub UNIT_CMP, Warn,
              "comparing unit values (which is always `true` or `false`, respectively)");

#[allow(missing_copy_implementations)]
pub struct UnitCmp;

impl LintPass for UnitCmp {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_CMP)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprBinary(ref cmp, ref left, _) = expr.node {
            let op = cmp.node;
            let sty = &cx.tcx.expr_ty(left).sty;
            if *sty == ty::TyTuple(vec![]) && is_comparison_binop(op) {
                let result = match op {
                    BiEq | BiLe | BiGe => "true",
                    _ => "false"
                };
                span_lint(cx, UNIT_CMP, expr.span, &format!(
                    "{}-comparison of unit values detected. This will always be {}",
                    binop_to_string(op), result));
            }
        }
    }
}

pub struct CastPass;

declare_lint!(pub CAST_PRECISION_LOSS, Allow,
              "casts that cause loss of precision, e.g `x as f32` where `x: u64`");
declare_lint!(pub CAST_SIGN_LOSS, Allow,
              "casts from signed types to unsigned types, e.g `x as u32` where `x: i32`");
declare_lint!(pub CAST_POSSIBLE_TRUNCATION, Allow,
              "casts that may cause truncation of the value, e.g `x as u8` where `x: u32`, or `x as i32` where `x: f32`");

/// Returns the size in bits of an integral type.
/// Will return 0 if the type is not an int or uint variant
fn int_ty_to_nbits(typ: &ty::TyS) -> usize {
    let n = match &typ.sty {
    &ty::TyInt(i) =>  4 << (i as usize),
    &ty::TyUint(u) => 4 << (u as usize),
    _ => 0
    };
    // n == 4 is the usize/isize case
    if n == 4 { ::std::usize::BITS } else { n }
}

impl LintPass for CastPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(CAST_PRECISION_LOSS,
                    CAST_SIGN_LOSS,
                    CAST_POSSIBLE_TRUNCATION)
    }

    fn check_expr(&mut self, cx: &Context, expr: &Expr) {
        if let ExprCast(ref ex, _) = expr.node {
            let (cast_from, cast_to) = (cx.tcx.expr_ty(&*ex), cx.tcx.expr_ty(expr));
            if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx, expr.span) {
                match (cast_from.is_integral(), cast_to.is_integral()) {
                    (true, false) => {
                        let from_nbits = int_ty_to_nbits(cast_from);
                        let to_nbits : usize = match &cast_to.sty {
                            &ty::TyFloat(ast::TyF32) => 32,
                            &ty::TyFloat(ast::TyF64) => 64,
                            _ => 0
                        };
                        if from_nbits != 0 {
                            if from_nbits >= to_nbits {
                                span_lint(cx, CAST_PRECISION_LOSS, expr.span,
                                          &format!("converting from {0} to {1}, which causes a loss of precision \
                                          			({0} is {2} bits wide, but {1}'s mantissa is only {3} bits wide)",
                                                   cast_from, cast_to, from_nbits, if to_nbits == 64 {52} else {23} ));
                            }
                        }
                    },
                    (false, true) => {
                        span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span,
                                  &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to));
                        if !cast_to.is_signed() {
                            span_lint(cx, CAST_SIGN_LOSS, expr.span,
                                      &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to));
                        }
                    },
                    (true, true) => {
                        if cast_from.is_signed() && !cast_to.is_signed() {
                            span_lint(cx, CAST_SIGN_LOSS, expr.span,
                                      &format!("casting from {} to {} loses the sign of the value", cast_from, cast_to));
                        }
                        let from_nbits = int_ty_to_nbits(cast_from);
                        let to_nbits   = int_ty_to_nbits(cast_to);
                        if to_nbits < from_nbits ||
                           (!cast_from.is_signed() && cast_to.is_signed() && to_nbits <= from_nbits) {
                                span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span,
                                          &format!("casting {} to {} may cause truncation of the value", cast_from, cast_to));
                        }
                    }
                    (false, false) => {
                        if let (&ty::TyFloat(ast::TyF64),
                                &ty::TyFloat(ast::TyF32)) = (&cast_from.sty, &cast_to.sty) {
                            span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, "casting f64 to f32 may cause truncation of the value");
                        }
                    }
                }
            }
        }
    }
}

declare_lint!(pub TYPE_COMPLEXITY, Warn,
              "usage of very complex types; recommends factoring out parts into `type` definitions");

#[allow(missing_copy_implementations)]
pub struct TypeComplexityPass;

impl LintPass for TypeComplexityPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(TYPE_COMPLEXITY)
    }

    fn check_fn(&mut self, cx: &Context, _: FnKind, decl: &FnDecl, _: &Block, _: Span, _: NodeId) {
        check_fndecl(cx, decl);
    }

    fn check_struct_field(&mut self, cx: &Context, field: &StructField) {
        check_type(cx, &*field.node.ty);
    }

    fn check_variant(&mut self, cx: &Context, var: &Variant, _: &Generics) {
        // StructVariant is covered by check_struct_field
        if let TupleVariantKind(ref args) = var.node.kind {
            for arg in args {
                check_type(cx, &*arg.ty);
            }
        }
    }

    fn check_item(&mut self, cx: &Context, item: &Item) {
        match item.node {
            ItemStatic(ref ty, _, _) |
            ItemConst(ref ty, _) => check_type(cx, ty),
            // functions, enums, structs, impls and traits are covered
            _ => ()
        }
    }

    fn check_trait_item(&mut self, cx: &Context, item: &TraitItem) {
        match item.node {
            ConstTraitItem(ref ty, _) |
            TypeTraitItem(_, Some(ref ty)) => check_type(cx, ty),
            MethodTraitItem(MethodSig { ref decl, .. }, None) => check_fndecl(cx, decl),
            // methods with default impl are covered by check_fn
            _ => ()
        }
    }

    fn check_impl_item(&mut self, cx: &Context, item: &ImplItem) {
        match item.node {
            ConstImplItem(ref ty, _) |
            TypeImplItem(ref ty) => check_type(cx, ty),
            // methods are covered by check_fn
            _ => ()
        }
    }

    fn check_local(&mut self, cx: &Context, local: &Local) {
        if let Some(ref ty) = local.ty {
            check_type(cx, ty);
        }
    }
}

fn check_fndecl(cx: &Context, decl: &FnDecl) {
    for arg in &decl.inputs {
        check_type(cx, &*arg.ty);
    }
    if let Return(ref ty) = decl.output {
        check_type(cx, ty);
    }
}

fn check_type(cx: &Context, ty: &ast::Ty) {
    if in_external_macro(cx, ty.span) { return; }
    let score = {
        let mut visitor = TypeComplexityVisitor { score: 0, nest: 1 };
        visitor.visit_ty(ty);
        visitor.score
    };
    // println!("{:?} --> {}", ty, score);
    if score > 250 {
        span_lint(cx, TYPE_COMPLEXITY, ty.span, &format!(
            "very complex type used. Consider factoring parts into `type` definitions"));
    }
}

/// Walks a type and assigns a complexity score to it.
struct TypeComplexityVisitor {
    /// total complexity score of the type
    score: u32,
    /// current nesting level
    nest: u32,
}

impl<'v> Visitor<'v> for TypeComplexityVisitor {
    fn visit_ty(&mut self, ty: &'v ast::Ty) {
        let (add_score, sub_nest) = match ty.node {
            // _, &x and *x have only small overhead; don't mess with nesting level
            TyInfer |
            TyPtr(..) |
            TyRptr(..) => (1, 0),

            // the "normal" components of a type: named types, arrays/tuples
            TyPath(..) |
            TyVec(..) |
            TyTup(..) |
            TyFixedLengthVec(..) => (10 * self.nest, 1),

            // "Sum" of trait bounds
            TyObjectSum(..) => (20 * self.nest, 0),

            // function types and "for<...>" bring a lot of overhead
            TyBareFn(..) |
            TyPolyTraitRef(..) => (50 * self.nest, 1),

            _ => (0, 0)
        };
        self.score += add_score;
        self.nest += sub_nest;
        walk_ty(self, ty);
        self.nest -= sub_nest;
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use blas::ddot;
use std::cmp::min;
use std::f64;

pub fn dot(x: &[f64], y: &[f64]) -> f64 {
    let n: i32 = min(x.len() as i32, y.len() as i32);

    unsafe { ddot(n, x, 1, y, 1) }
}

pub fn argmaxima(vals: &[f64]) -> (f64, Vec<usize>) {
    let mut max = f64::MIN;
    let mut ixs = vec![];

    for (i, &v) in vals.iter().enumerate() {
        if (v - max).abs() < 1e-7 {
            ixs.push(i);
        } else if v > max {
            max = v;
            ixs.clear();
            ixs.push(i);
        }
    }

    (max, ixs)
}

// TODO: Pass by iterator so that we don't have to collect before passing.
pub fn sub2ind(dims: &[usize], inds: &[usize]) -> usize {
    let d_it = dims.iter().rev().skip(1);
    let i_it = inds.iter().rev().skip(1);

    d_it.zip(i_it)
        .fold(inds.last().cloned().unwrap(), |acc, (d, i)| i + d * acc)
}

/// Given a vector containing a partial Cartesian product, and a list of items,
/// return a vector adding the list of items to the partial Cartesian product.
///
/// # Example
///
/// ```
/// use rsrl::utils::partial_cartesian;
///
/// let partial_product = vec![vec![1, 4], vec![1, 5], vec![2, 4], vec![2, 5]];
/// let items = vec![6, 7];
/// let next_product = partial_cartesian(partial_product, &items);
///
/// assert_eq!(
///     next_product,
///     vec![
///         vec![1, 4, 6],
///         vec![1, 4, 7],
///         vec![1, 5, 6],
///         vec![1, 5, 7],
///         vec![2, 4, 6],
///         vec![2, 4, 7],
///         vec![2, 5, 6],
///         vec![2, 5, 7],
///     ]
/// );
/// ```
///
/// Pulled from [here](https://gist.github.com/kylewlacy/115965b40e02a3325558).
pub fn partial_cartesian<T: Clone>(a: Vec<Vec<T>>, b: &Vec<T>) -> Vec<Vec<T>> {
    a.into_iter()
        .flat_map(|xs| {
            b.iter()
                .cloned()
                .map(|y| {
                    let mut vec = xs.clone();
                    vec.push(y);
                    vec
                })
                .collect::<Vec<_>>()
        })
        .collect()
}

/// Computes the Cartesian product of lists[0] * lists[1] * ... * lists[n].
///
/// # Example
///
/// ```
/// use rsrl::utils::cartesian_product;
///
/// let lists = vec![vec![1, 2], vec![4, 5], vec![6, 7]];
/// let product = cartesian_product(&lists);
///
/// assert_eq!(
///     product,
///     vec![
///         vec![1, 4, 6],
///         vec![1, 4, 7],
///         vec![1, 5, 6],
///         vec![1, 5, 7],
///         vec![2, 4, 6],
///         vec![2, 4, 7],
///         vec![2, 5, 6],
///         vec![2, 5, 7],
///     ]
/// );
/// ```
///
/// Pulled from [here](https://gist.github.com/kylewlacy/115965b40e02a3325558).
pub fn cartesian_product<T: Clone>(lists: &Vec<Vec<T>>) -> Vec<Vec<T>> {
    match lists.split_first() {
        Some((first, rest)) => {
            let init: Vec<Vec<T>> = first.iter().cloned().map(|n| vec![n]).collect();

            rest.iter()
                .cloned()
                .fold(init, |vec, list| partial_cartesian(vec, &list))
        },
        None => vec![],
    }
}

#[cfg(test)]
mod tests {
    use super::{cartesian_product, sub2ind};

    #[test]
    fn test_sub2ind() {
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![3, 0, 0]), 3);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 0, 5]), 177);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 5, 5]), 202);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![0, 0, 11]), 385);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![5, 0, 11]), 390);
    }

    #[test]
    #[should_panic]
    fn test_sub2ind_empty() { sub2ind(&vec![], &vec![]); }

    #[test]
    fn test_cartesian_product() {
        let to_combine = vec![vec![0.0, 1.0, 2.0], vec![7.0, 8.0, 9.0]];

        let combs = cartesian_product(&to_combine);

        assert_eq!(combs[0], vec![0.0, 7.0]);
        assert_eq!(combs[1], vec![0.0, 8.0]);
        assert_eq!(combs[2], vec![0.0, 9.0]);

        assert_eq!(combs[3], vec![1.0, 7.0]);
        assert_eq!(combs[4], vec![1.0, 8.0]);
        assert_eq!(combs[5], vec![1.0, 9.0]);

        assert_eq!(combs[6], vec![2.0, 7.0]);
        assert_eq!(combs[7], vec![2.0, 8.0]);
        assert_eq!(combs[8], vec![2.0, 9.0]);
    }
}
<commit_msg>chore(utils): remove redundant TODO note<commit_after>#![allow(dead_code)]

use blas::ddot;
use std::cmp::min;
use std::f64;

pub fn dot(x: &[f64], y: &[f64]) -> f64 {
    let n: i32 = min(x.len() as i32, y.len() as i32);

    unsafe { ddot(n, x, 1, y, 1) }
}

pub fn argmaxima(vals: &[f64]) -> (f64, Vec<usize>) {
    let mut max = f64::MIN;
    let mut ixs = vec![];

    for (i, &v) in vals.iter().enumerate() {
        if (v - max).abs() < 1e-7 {
            ixs.push(i);
        } else if v > max {
            max = v;
            ixs.clear();
            ixs.push(i);
        }
    }

    (max, ixs)
}

pub fn sub2ind(dims: &[usize], inds: &[usize]) -> usize {
    let d_it = dims.iter().rev().skip(1);
    let i_it = inds.iter().rev().skip(1);

    d_it.zip(i_it)
        .fold(inds.last().cloned().unwrap(), |acc, (d, i)| i + d * acc)
}

/// Given a vector containing a partial Cartesian product, and a list of items,
/// return a vector adding the list of items to the partial Cartesian product.
///
/// # Example
///
/// ```
/// use rsrl::utils::partial_cartesian;
///
/// let partial_product = vec![vec![1, 4], vec![1, 5], vec![2, 4], vec![2, 5]];
/// let items = vec![6, 7];
/// let next_product = partial_cartesian(partial_product, &items);
///
/// assert_eq!(
///     next_product,
///     vec![
///         vec![1, 4, 6],
///         vec![1, 4, 7],
///         vec![1, 5, 6],
///         vec![1, 5, 7],
///         vec![2, 4, 6],
///         vec![2, 4, 7],
///         vec![2, 5, 6],
///         vec![2, 5, 7],
///     ]
/// );
/// ```
///
/// Pulled from [here](https://gist.github.com/kylewlacy/115965b40e02a3325558).
pub fn partial_cartesian<T: Clone>(a: Vec<Vec<T>>, b: &Vec<T>) -> Vec<Vec<T>> {
    a.into_iter()
        .flat_map(|xs| {
            b.iter()
                .cloned()
                .map(|y| {
                    let mut vec = xs.clone();
                    vec.push(y);
                    vec
                })
                .collect::<Vec<_>>()
        })
        .collect()
}

/// Computes the Cartesian product of lists[0] * lists[1] * ... * lists[n].
///
/// # Example
///
/// ```
/// use rsrl::utils::cartesian_product;
///
/// let lists = vec![vec![1, 2], vec![4, 5], vec![6, 7]];
/// let product = cartesian_product(&lists);
///
/// assert_eq!(
///     product,
///     vec![
///         vec![1, 4, 6],
///         vec![1, 4, 7],
///         vec![1, 5, 6],
///         vec![1, 5, 7],
///         vec![2, 4, 6],
///         vec![2, 4, 7],
///         vec![2, 5, 6],
///         vec![2, 5, 7],
///     ]
/// );
/// ```
///
/// Pulled from [here](https://gist.github.com/kylewlacy/115965b40e02a3325558).
pub fn cartesian_product<T: Clone>(lists: &Vec<Vec<T>>) -> Vec<Vec<T>> {
    match lists.split_first() {
        Some((first, rest)) => {
            let init: Vec<Vec<T>> = first.iter().cloned().map(|n| vec![n]).collect();

            rest.iter()
                .cloned()
                .fold(init, |vec, list| partial_cartesian(vec, &list))
        },
        None => vec![],
    }
}

#[cfg(test)]
mod tests {
    use super::{cartesian_product, sub2ind};

    #[test]
    fn test_sub2ind() {
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![3, 0, 0]), 3);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 0, 5]), 177);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 5, 5]), 202);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![0, 0, 11]), 385);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![5, 0, 11]), 390);
    }

    #[test]
    #[should_panic]
    fn test_sub2ind_empty() { sub2ind(&vec![], &vec![]); }

    #[test]
    fn test_cartesian_product() {
        let to_combine = vec![vec![0.0, 1.0, 2.0], vec![7.0, 8.0, 9.0]];

        let combs = cartesian_product(&to_combine);

        assert_eq!(combs[0], vec![0.0, 7.0]);
        assert_eq!(combs[1], vec![0.0, 8.0]);
        assert_eq!(combs[2], vec![0.0, 9.0]);

        assert_eq!(combs[3], vec![1.0, 7.0]);
        assert_eq!(combs[4], vec![1.0, 8.0]);
        assert_eq!(combs[5], vec![1.0, 9.0]);

        assert_eq!(combs[6], vec![2.0, 7.0]);
        assert_eq!(combs[7], vec![2.0, 8.0]);
        assert_eq!(combs[8], vec![2.0, 9.0]);
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use crate::Error;
use futures::future::Future;
use slog_scope::error;
use std::collections::BTreeMap;
use std::process::exit;
use std::sync::Arc;
use structopt::StructOpt;

use crate::logger::logger_init;

pub fn get_zip_codes_from_admins(admins: &[Arc<places::admin::Admin>]) -> Vec<String> {
    let level = admins.iter().fold(0, |level, adm| {
        if adm.level > level && !adm.zip_codes.is_empty() {
            adm.level
        } else {
            level
        }
    });
    if level == 0 {
        return vec![];
    }
    admins
        .iter()
        .filter(|adm| adm.level == level)
        .flat_map(|adm| adm.zip_codes.iter().cloned())
        .collect()
}

pub const ADMIN_MAX_WEIGHT: f64 = 1_400_000_000.; // China's population

/// normalize the admin weight for it to be in [0, 1]
pub fn normalize_admin_weight(admins: &mut [places::admin::Admin]) {
    for admin in admins {
        admin.weight = normalize_weight(admin.weight, ADMIN_MAX_WEIGHT);
    }
}

/// normalize the weight for it to be in [0, 1]
pub fn normalize_weight(weight: f64, max_weight: f64) -> f64 {
    let w = weight / max_weight;
    if w > 1. {
        1.
    } else {
        w
    }
}

pub async fn wrapped_launch_async<O, F, Fut>(run: F) -> Result<(), Error>
where
    O: StructOpt,
    F: FnOnce(O) -> Fut,
    Fut: Future<Output = Result<(), Error>>,
{
    let _guard = logger_init();
    if let Err(err) = run(O::from_args()).await {
        for cause in err.iter_chain() {
            error!("{}", cause);
        }
        Err(err)
    } else {
        Ok(())
    }
}

pub async fn launch_async<O, F, Fut>(run: F)
where
    O: StructOpt,
    F: FnOnce(O) -> Fut,
    Fut: Future<Output = Result<(), Error>>,
{
    if wrapped_launch_async(run).await.is_err() {
        // we wrap the real stuff in another method to std::exit after
        // the destruction of the logger (so we won't loose any messages)
        exit(1);
    }
}

pub fn wrapped_launch_run<O, F>(run: F) -> Result<(), Error>
where
    F: FnOnce(O) -> Result<(), Error>,
    O: StructOpt,
{
    let _guard = logger_init();
    if let Err(err) = run(O::from_args()) {
        for cause in err.iter_chain() {
            error!("{}", cause);
        }
        Err(err)
    } else {
        Ok(())
    }
}

pub fn launch_run<O, F>(run: F)
where
    F: FnOnce(O) -> Result<(), Error>,
    O: StructOpt,
{
    if wrapped_launch_run(run).is_err() {
        // we wrap the real stuff in another method to std::exit after
        // the destruction of the logger (so we won't loose any messages)
        exit(1);
    }
}

pub fn get_country_code(codes: &BTreeMap<String, String>) -> Option<String> {
    codes.get("ISO3166-1:alpha2").cloned()
}

pub fn find_country_codes<'a>(
    admins: impl Iterator<Item = &'a places::admin::Admin>,
) -> Vec<String> {
    admins.filter_map(|a| get_country_code(&a.codes)).collect()
}
<commit_msg>Fix guard on slog_scope<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

use crate::Error;
use futures::future::Future;
use slog_scope::error;
use std::collections::BTreeMap;
use std::process::exit;
use std::sync::Arc;
use structopt::StructOpt;

use crate::logger::logger_init;

pub fn get_zip_codes_from_admins(admins: &[Arc<places::admin::Admin>]) -> Vec<String> {
    let level = admins.iter().fold(0, |level, adm| {
        if adm.level > level && !adm.zip_codes.is_empty() {
            adm.level
        } else {
            level
        }
    });
    if level == 0 {
        return vec![];
    }
    admins
        .iter()
        .filter(|adm| adm.level == level)
        .flat_map(|adm| adm.zip_codes.iter().cloned())
        .collect()
}

pub const ADMIN_MAX_WEIGHT: f64 = 1_400_000_000.; // China's population

/// normalize the admin weight for it to be in [0, 1]
pub fn normalize_admin_weight(admins: &mut [places::admin::Admin]) {
    for admin in admins {
        admin.weight = normalize_weight(admin.weight, ADMIN_MAX_WEIGHT);
    }
}

/// normalize the weight for it to be in [0, 1]
pub fn normalize_weight(weight: f64, max_weight: f64) -> f64 {
    let w = weight / max_weight;
    if w > 1. {
        1.
    } else {
        w
    }
}

pub async fn wrapped_launch_async<O, F, Fut>(run: F) -> Result<(), Error>
where
    O: StructOpt,
    F: FnOnce(O) -> Fut,
    Fut: Future<Output = Result<(), Error>>,
{
    let (guard, _) = logger_init();
    guard.cancel_reset(); // The guard should not be dropped before the Future has been resolved
    if let Err(err) = run(O::from_args()).await {
        for cause in err.iter_chain() {
            error!("{}", cause);
        }
        Err(err)
    } else {
        Ok(())
    }
}

pub async fn launch_async<O, F, Fut>(run: F)
where
    O: StructOpt,
    F: FnOnce(O) -> Fut,
    Fut: Future<Output = Result<(), Error>>,
{
    if wrapped_launch_async(run).await.is_err() {
        // we wrap the real stuff in another method to std::exit after
        // the destruction of the logger (so we won't loose any messages)
        exit(1);
    }
}

pub fn wrapped_launch_run<O, F>(run: F) -> Result<(), Error>
where
    F: FnOnce(O) -> Result<(), Error>,
    O: StructOpt,
{
    let _guard = logger_init();
    if let Err(err) = run(O::from_args()) {
        for cause in err.iter_chain() {
            error!("{}", cause);
        }
        Err(err)
    } else {
        Ok(())
    }
}

pub fn launch_run<O, F>(run: F)
where
    F: FnOnce(O) -> Result<(), Error>,
    O: StructOpt,
{
    if wrapped_launch_run(run).is_err() {
        // we wrap the real stuff in another method to std::exit after
        // the destruction of the logger (so we won't loose any messages)
        exit(1);
    }
}

pub fn get_country_code(codes: &BTreeMap<String, String>) -> Option<String> {
    codes.get("ISO3166-1:alpha2").cloned()
}

pub fn find_country_codes<'a>(
    admins: impl Iterator<Item = &'a places::admin::Admin>,
) -> Vec<String> {
    admins.filter_map(|a| get_country_code(&a.codes)).collect()
}
<|endoftext|>