<commit_before>//! The `Parse` trait for CSS properties, and utilities for parsers.

use cssparser::{Parser, ParserInput};
use markup5ever::QualName;

use std::str;

use crate::error::*;

/// Trait to parse values using `cssparser::Parser`.
pub trait Parse: Sized {
    /// Parses a value out of the `parser`.
    ///
    /// All value types should implement this for composability.
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind>;

    /// Convenience function to parse a value out of a `&str`.
    ///
    /// This is useful mostly for tests which want to avoid creating a
    /// `cssparser::Parser` by hand.
    fn parse_str(s: &str) -> Result<Self, ValueErrorKind> {
        let mut input = ParserInput::new(s);
        let mut parser = Parser::new(&mut input);

        Self::parse(&mut parser).and_then(|r| {
            // FIXME: parser.expect_exhausted()?;
            Ok(r)
        })
    }
}

/// Consumes a comma if it exists, or does nothing.
pub fn optional_comma<'i, 't>(parser: &mut Parser<'i, 't>) {
    let _ = parser.try_parse(|p| p.expect_comma());
}

pub fn finite_f32(n: f32) -> Result<f32, ValueErrorKind> {
    if n.is_finite() {
        Ok(n)
    } else {
        Err(ValueErrorKind::Value("expected finite number".to_string()))
    }
}

pub trait ParseValue<T: Parse> {
    /// Parses a `value` string into a type `T`.
    fn parse(&self, value: &str) -> Result<T, NodeError>;

    /// Parses a `value` string into a type `T` with an optional validation function.
    fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
        &self,
        value: &str,
        validate: F,
    ) -> Result<T, NodeError>;
}

impl<T: Parse> ParseValue<T> for QualName {
    fn parse(&self, value: &str) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse(&mut parser).attribute(self.clone())
    }

    fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
        &self,
        value: &str,
        validate: F,
    ) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse(&mut parser)
            .and_then(validate)
            .attribute(self.clone())
    }
}

impl Parse for f64 {
    /// Avoid infinities, and convert to `f64`.
    /// https://www.w3.org/TR/SVG11/types.html#DataTypeNumber
    fn parse(parser: &mut Parser<'_, '_>) -> Result<f64, ValueErrorKind> {
        parser
            .expect_number()
            .map_err(|_| ValueErrorKind::parse_error("parse error"))
            .and_then(|n| Ok(f64::from(finite_f32(n)?)))
    }
}

pub trait ParseToParseError: Sized {
    fn parse_to_parse_error<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, CssParseError<'i>>;
    fn parse_str_to_parse_error<'i>(s: &'i str) -> Result<Self, CssParseError<'i>> {
        let mut input = ParserInput::new(s);
        let mut parser = Parser::new(&mut input);

        Self::parse_to_parse_error(&mut parser).and_then(|r| {
            // FIXME: parser.expect_exhausted()?;
            Ok(r)
        })
    }
}

impl ParseToParseError for f64 {
    fn parse_to_parse_error<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, CssParseError<'i>> {
        let loc = parser.current_source_location();
        parser
            .expect_number()
            .map_err(|e| e.into())
            .and_then(|n| {
                if n.is_finite() {
                    Ok(f64::from(n))
                } else {
                    Err(loc.new_custom_error(ValueErrorKind::value_error("expected finite number")))
                }
            })
    }
}

// number-optional-number
//
// https://www.w3.org/TR/SVG/types.html#DataTypeNumberOptionalNumber

pub fn number_optional_number(s: &str) -> Result<(f64, f64), ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let x = f64::parse(&mut parser)?;

    if !parser.is_exhausted() {
        optional_comma(&mut parser);

        let y = f64::parse(&mut parser)?;

        parser.expect_exhausted()?;

        Ok((x, y))
    } else {
        Ok((x, x))
    }
}

// integer
//
// https://www.w3.org/TR/SVG11/types.html#DataTypeInteger
pub fn integer(s: &str) -> Result<i32, ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    Ok(parser.expect_integer()?)
}

// integer-optional-integer
//
// Like number-optional-number but with integers.
pub fn integer_optional_integer(s: &str) -> Result<(i32, i32), ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let x = parser.expect_integer()?;

    if !parser.is_exhausted() {
        optional_comma(&mut parser);

        let y = parser.expect_integer()?;

        parser.expect_exhausted()?;

        Ok((x, y))
    } else {
        Ok((x, x))
    }
}

/// Parses a list of identifiers from a `cssparser::Parser`
///
/// # Example
///
/// ```ignore
/// let my_boolean = parse_identifiers!(
///     parser,
///     "true" => true,
///     "false" => false,
/// )?;
/// ```
macro_rules! parse_identifiers {
    ($parser:expr,
     $($str:expr => $val:expr,)+) => {
        {
            let loc = $parser.current_source_location();
            let token = $parser.next()?;

            match token {
                $(cssparser::Token::Ident(ref cow) if cow.eq_ignore_ascii_case($str) => Ok($val),)+

                _ => Err(loc.new_basic_unexpected_token_error(token.clone()))
            }
        }
    };
}

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

    #[test]
    fn parses_number_optional_number() {
        assert_eq!(number_optional_number("1, 2"), Ok((1.0, 2.0)));
        assert_eq!(number_optional_number("1 2"), Ok((1.0, 2.0)));
        assert_eq!(number_optional_number("1"), Ok((1.0, 1.0)));

        assert_eq!(number_optional_number("-1, -2"), Ok((-1.0, -2.0)));
        assert_eq!(number_optional_number("-1 -2"), Ok((-1.0, -2.0)));
        assert_eq!(number_optional_number("-1"), Ok((-1.0, -1.0)));
    }

    #[test]
    fn invalid_number_optional_number() {
        assert!(number_optional_number("").is_err());
        assert!(number_optional_number("1x").is_err());
        assert!(number_optional_number("x1").is_err());
        assert!(number_optional_number("1 x").is_err());
        assert!(number_optional_number("1 , x").is_err());
        assert!(number_optional_number("1 , 2x").is_err());
        assert!(number_optional_number("1 2 x").is_err());
    }

    #[test]
    fn parses_integer() {
        assert_eq!(integer("1"), Ok(1));
        assert_eq!(integer("-1"), Ok(-1));
    }

    #[test]
    fn invalid_integer() {
        assert!(integer("").is_err());
        assert!(integer("1x").is_err());
        assert!(integer("1.5").is_err());
    }

    #[test]
    fn parses_integer_optional_integer() {
        assert_eq!(integer_optional_integer("1, 2"), Ok((1, 2)));
        assert_eq!(integer_optional_integer("1 2"), Ok((1, 2)));
        assert_eq!(integer_optional_integer("1"), Ok((1, 1)));

        assert_eq!(integer_optional_integer("-1, -2"), Ok((-1, -2)));
        assert_eq!(integer_optional_integer("-1 -2"), Ok((-1, -2)));
        assert_eq!(integer_optional_integer("-1"), Ok((-1, -1)));
    }

    #[test]
    fn invalid_integer_optional_integer() {
        assert!(integer_optional_integer("").is_err());
        assert!(integer_optional_integer("1x").is_err());
        assert!(integer_optional_integer("x1").is_err());
        assert!(integer_optional_integer("1 x").is_err());
        assert!(integer_optional_integer("1 , x").is_err());
        assert!(integer_optional_integer("1 , 2x").is_err());
        assert!(integer_optional_integer("1 2 x").is_err());
        assert!(integer_optional_integer("1.5").is_err());
        assert!(integer_optional_integer("1 2.5").is_err());
        assert!(integer_optional_integer("1, 2.5").is_err());
    }
}
<commit_msg>Temporary trait ParseValueToParseError<commit_after>//! The `Parse` trait for CSS properties, and utilities for parsers.

use cssparser::{Parser, ParserInput};
use markup5ever::QualName;

use std::str;

use crate::error::*;

/// Trait to parse values using `cssparser::Parser`.
pub trait Parse: Sized {
    /// Parses a value out of the `parser`.
    ///
    /// All value types should implement this for composability.
    fn parse(parser: &mut Parser<'_, '_>) -> Result<Self, ValueErrorKind>;

    /// Convenience function to parse a value out of a `&str`.
    ///
    /// This is useful mostly for tests which want to avoid creating a
    /// `cssparser::Parser` by hand.
    fn parse_str(s: &str) -> Result<Self, ValueErrorKind> {
        let mut input = ParserInput::new(s);
        let mut parser = Parser::new(&mut input);

        Self::parse(&mut parser).and_then(|r| {
            // FIXME: parser.expect_exhausted()?;
            Ok(r)
        })
    }
}

/// Consumes a comma if it exists, or does nothing.
pub fn optional_comma<'i, 't>(parser: &mut Parser<'i, 't>) {
    let _ = parser.try_parse(|p| p.expect_comma());
}

pub fn finite_f32(n: f32) -> Result<f32, ValueErrorKind> {
    if n.is_finite() {
        Ok(n)
    } else {
        Err(ValueErrorKind::Value("expected finite number".to_string()))
    }
}

pub trait ParseValue<T: Parse> {
    /// Parses a `value` string into a type `T`.
    fn parse(&self, value: &str) -> Result<T, NodeError>;

    /// Parses a `value` string into a type `T` with an optional validation function.
    fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
        &self,
        value: &str,
        validate: F,
    ) -> Result<T, NodeError>;
}

impl<T: Parse> ParseValue<T> for QualName {
    fn parse(&self, value: &str) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse(&mut parser).attribute(self.clone())
    }

    fn parse_and_validate<F: FnOnce(T) -> Result<T, ValueErrorKind>>(
        &self,
        value: &str,
        validate: F,
    ) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse(&mut parser)
            .and_then(validate)
            .attribute(self.clone())
    }
}

pub trait ParseValueToParseError<T: ParseToParseError> {
    /// Parses a `value` string into a type `T`.
    fn parse_to_parse_error(&self, value: &str) -> Result<T, NodeError>;

    /// Parses a `value` string into a type `T` with an optional validation function.
    fn parse_to_parse_error_and_validate<'i, F: FnOnce(T) -> Result<T, CssParseError<'i>>>(
        &self,
        value: &'i str,
        validate: F,
    ) -> Result<T, NodeError>;
}

impl<T: ParseToParseError> ParseValueToParseError<T> for QualName {
    fn parse_to_parse_error(&self, value: &str) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse_to_parse_error(&mut parser).attribute(self.clone())
    }

    fn parse_to_parse_error_and_validate<'i, F: FnOnce(T) -> Result<T, CssParseError<'i>>>(
        &self,
        value: &'i str,
        validate: F,
    ) -> Result<T, NodeError> {
        let mut input = ParserInput::new(value);
        let mut parser = Parser::new(&mut input);

        T::parse_to_parse_error(&mut parser)
            .and_then(validate)
            .attribute(self.clone())
    }
}

impl Parse for f64 {
    /// Avoid infinities, and convert to `f64`.
    /// https://www.w3.org/TR/SVG11/types.html#DataTypeNumber
    fn parse(parser: &mut Parser<'_, '_>) -> Result<f64, ValueErrorKind> {
        parser
            .expect_number()
            .map_err(|_| ValueErrorKind::parse_error("parse error"))
            .and_then(|n| Ok(f64::from(finite_f32(n)?)))
    }
}

pub trait ParseToParseError: Sized {
    fn parse_to_parse_error<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, CssParseError<'i>>;
    fn parse_str_to_parse_error<'i>(s: &'i str) -> Result<Self, CssParseError<'i>> {
        let mut input = ParserInput::new(s);
        let mut parser = Parser::new(&mut input);

        Self::parse_to_parse_error(&mut parser).and_then(|r| {
            // FIXME: parser.expect_exhausted()?;
            Ok(r)
        })
    }
}

impl ParseToParseError for f64 {
    fn parse_to_parse_error<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, CssParseError<'i>> {
        let loc = parser.current_source_location();
        parser
            .expect_number()
            .map_err(|e| e.into())
            .and_then(|n| {
                if n.is_finite() {
                    Ok(f64::from(n))
                } else {
                    Err(loc.new_custom_error(ValueErrorKind::value_error("expected finite number")))
                }
            })
    }
}

// number-optional-number
//
// https://www.w3.org/TR/SVG/types.html#DataTypeNumberOptionalNumber

pub fn number_optional_number(s: &str) -> Result<(f64, f64), ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let x = f64::parse(&mut parser)?;

    if !parser.is_exhausted() {
        optional_comma(&mut parser);

        let y = f64::parse(&mut parser)?;

        parser.expect_exhausted()?;

        Ok((x, y))
    } else {
        Ok((x, x))
    }
}

// integer
//
// https://www.w3.org/TR/SVG11/types.html#DataTypeInteger
pub fn integer(s: &str) -> Result<i32, ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    Ok(parser.expect_integer()?)
}

// integer-optional-integer
//
// Like number-optional-number but with integers.
pub fn integer_optional_integer(s: &str) -> Result<(i32, i32), ValueErrorKind> {
    let mut input = ParserInput::new(s);
    let mut parser = Parser::new(&mut input);

    let x = parser.expect_integer()?;

    if !parser.is_exhausted() {
        optional_comma(&mut parser);

        let y = parser.expect_integer()?;

        parser.expect_exhausted()?;

        Ok((x, y))
    } else {
        Ok((x, x))
    }
}

/// Parses a list of identifiers from a `cssparser::Parser`
///
/// # Example
///
/// ```ignore
/// let my_boolean = parse_identifiers!(
///     parser,
///     "true" => true,
///     "false" => false,
/// )?;
/// ```
macro_rules! parse_identifiers {
    ($parser:expr,
     $($str:expr => $val:expr,)+) => {
        {
            let loc = $parser.current_source_location();
            let token = $parser.next()?;

            match token {
                $(cssparser::Token::Ident(ref cow) if cow.eq_ignore_ascii_case($str) => Ok($val),)+

                _ => Err(loc.new_basic_unexpected_token_error(token.clone()))
            }
        }
    };
}

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

    #[test]
    fn parses_number_optional_number() {
        assert_eq!(number_optional_number("1, 2"), Ok((1.0, 2.0)));
        assert_eq!(number_optional_number("1 2"), Ok((1.0, 2.0)));
        assert_eq!(number_optional_number("1"), Ok((1.0, 1.0)));

        assert_eq!(number_optional_number("-1, -2"), Ok((-1.0, -2.0)));
        assert_eq!(number_optional_number("-1 -2"), Ok((-1.0, -2.0)));
        assert_eq!(number_optional_number("-1"), Ok((-1.0, -1.0)));
    }

    #[test]
    fn invalid_number_optional_number() {
        assert!(number_optional_number("").is_err());
        assert!(number_optional_number("1x").is_err());
        assert!(number_optional_number("x1").is_err());
        assert!(number_optional_number("1 x").is_err());
        assert!(number_optional_number("1 , x").is_err());
        assert!(number_optional_number("1 , 2x").is_err());
        assert!(number_optional_number("1 2 x").is_err());
    }

    #[test]
    fn parses_integer() {
        assert_eq!(integer("1"), Ok(1));
        assert_eq!(integer("-1"), Ok(-1));
    }

    #[test]
    fn invalid_integer() {
        assert!(integer("").is_err());
        assert!(integer("1x").is_err());
        assert!(integer("1.5").is_err());
    }

    #[test]
    fn parses_integer_optional_integer() {
        assert_eq!(integer_optional_integer("1, 2"), Ok((1, 2)));
        assert_eq!(integer_optional_integer("1 2"), Ok((1, 2)));
        assert_eq!(integer_optional_integer("1"), Ok((1, 1)));

        assert_eq!(integer_optional_integer("-1, -2"), Ok((-1, -2)));
        assert_eq!(integer_optional_integer("-1 -2"), Ok((-1, -2)));
        assert_eq!(integer_optional_integer("-1"), Ok((-1, -1)));
    }

    #[test]
    fn invalid_integer_optional_integer() {
        assert!(integer_optional_integer("").is_err());
        assert!(integer_optional_integer("1x").is_err());
        assert!(integer_optional_integer("x1").is_err());
        assert!(integer_optional_integer("1 x").is_err());
        assert!(integer_optional_integer("1 , x").is_err());
        assert!(integer_optional_integer("1 , 2x").is_err());
        assert!(integer_optional_integer("1 2 x").is_err());
        assert!(integer_optional_integer("1.5").is_err());
        assert!(integer_optional_integer("1 2.5").is_err());
        assert!(integer_optional_integer("1, 2.5").is_err());
    }
}
<|endoftext|>


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

use config_type::ConfigType;
use lists::*;

/// Macro for deriving implementations of Serialize/Deserialize for enums
#[macro_export]
macro_rules! impl_enum_serialize_and_deserialize {
    ( $e:ident, $( $x:ident ),* ) => {
        impl ::serde::ser::Serialize for $e {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: ::serde::ser::Serializer
            {
                use serde::ser::Error;

                // We don't know whether the user of the macro has given us all options.
                #[allow(unreachable_patterns)]
                match *self {
                    $(
                        $e::$x => serializer.serialize_str(stringify!($x)),
                    )*
                    _ => {
                        Err(S::Error::custom(format!("Cannot serialize {:?}", self)))
                    }
                }
            }
        }

        impl<'de> ::serde::de::Deserialize<'de> for $e {
            fn deserialize<D>(d: D) -> Result<Self, D::Error>
                    where D: ::serde::Deserializer<'de> {
                use serde::de::{Error, Visitor};
                use std::marker::PhantomData;
                use std::fmt;
                struct StringOnly<T>(PhantomData<T>);
                impl<'de, T> Visitor<'de> for StringOnly<T>
                        where T: ::serde::Deserializer<'de> {
                    type Value = String;
                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("string")
                    }
                    fn visit_str<E>(self, value: &str) -> Result<String, E> {
                        Ok(String::from(value))
                    }
                }
                let s = d.deserialize_string(StringOnly::<D>(PhantomData))?;
                $(
                    if stringify!($x).eq_ignore_ascii_case(&s) {
                      return Ok($e::$x);
                    }
                )*
                static ALLOWED: &'static[&str] = &[$(stringify!($x),)*];
                Err(D::Error::unknown_variant(&s, ALLOWED))
            }
        }

        impl ::std::str::FromStr for $e {
            type Err = &'static str;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                $(
                    if stringify!($x).eq_ignore_ascii_case(s) {
                        return Ok($e::$x);
                    }
                )*
                Err("Bad variant")
            }
        }

        impl ConfigType for $e {
            fn doc_hint() -> String {
                let mut variants = Vec::new();
                $(
                    variants.push(stringify!($x));
                )*
                format!("[{}]", variants.join("|"))
            }
        }
    };
}

macro_rules! configuration_option_enum{
    ($e:ident: $( $x:ident ),+ $(,)*) => {
        #[derive(Copy, Clone, Eq, PartialEq, Debug)]
        pub enum $e {
            $( $x ),+
        }

        impl_enum_serialize_and_deserialize!($e, $( $x ),+);
    }
}

configuration_option_enum! { NewlineStyle:
    Windows, // \r\n
    Unix, // \n
    Native, // \r\n in Windows, \n on other platforms
}

configuration_option_enum! { BraceStyle:
    AlwaysNextLine,
    PreferSameLine,
    // Prefer same line except where there is a where clause, in which case force
    // the brace to the next line.
    SameLineWhere,
}

configuration_option_enum! { ControlBraceStyle:
    // K&R style, Rust community default
    AlwaysSameLine,
    // Stroustrup style
    ClosingNextLine,
    // Allman style
    AlwaysNextLine,
}

configuration_option_enum! { IndentStyle:
    // First line on the same line as the opening brace, all lines aligned with
    // the first line.
    Visual,
    // First line is on a new line and all lines align with block indent.
    Block,
}

configuration_option_enum! { Density:
    // Fit as much on one line as possible.
    Compressed,
    // Use more lines.
    Tall,
    // Place every item on a separate line.
    Vertical,
}

configuration_option_enum! { TypeDensity:
    // No spaces around "=" and "+"
    Compressed,
    // Spaces around " = " and " + "
    Wide,
}

impl Density {
    pub fn to_list_tactic(self) -> ListTactic {
        match self {
            Density::Compressed => ListTactic::Mixed,
            Density::Tall => ListTactic::HorizontalVertical,
            Density::Vertical => ListTactic::Vertical,
        }
    }
}

configuration_option_enum! { ReportTactic:
    Always,
    Unnumbered,
    Never,
}

configuration_option_enum! { WriteMode:
    // Backs the original file up and overwrites the original.
    Replace,
    // Overwrites original file without backup.
    Overwrite,
    // Writes the output to stdout.
    Display,
    // Writes the diff to stdout.
    Diff,
    // Displays how much of the input file was processed
    Coverage,
    // Unfancy stdout
    Plain,
    // Outputs a checkstyle XML file.
    Checkstyle,
    // Output the changed lines
    Modified,
}

configuration_option_enum! { Color:
    // Always use color, whether it is a piped or terminal output
    Always,
    // Never use color
    Never,
    // Automatically use color, if supported by terminal
    Auto,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct WidthHeuristics {
    // Maximum width of the args of a function call before falling back
    // to vertical formatting.
    pub fn_call_width: usize,
    // Maximum width in the body of a struct lit before falling back to
    // vertical formatting.
    pub struct_lit_width: usize,
    // Maximum width in the body of a struct variant before falling back
    // to vertical formatting.
    pub struct_variant_width: usize,
    // Maximum width of an array literal before falling back to vertical
    // formatting.
    pub array_width: usize,
    // Maximum length of a chain to fit on a single line.
    pub chain_width: usize,
    // Maximum line length for single line if-else expressions. A value
    // of zero means always break if-else expressions.
    pub single_line_if_else_max_width: usize,
}

impl WidthHeuristics {
    // Using this WidthHeuristics means we ignore heuristics.
    pub fn null() -> WidthHeuristics {
        WidthHeuristics {
            fn_call_width: usize::max_value(),
            struct_lit_width: 0,
            struct_variant_width: 0,
            array_width: usize::max_value(),
            chain_width: usize::max_value(),
            single_line_if_else_max_width: 0,
        }
    }
}

impl Default for WidthHeuristics {
    fn default() -> WidthHeuristics {
        WidthHeuristics {
            fn_call_width: 60,
            struct_lit_width: 18,
            struct_variant_width: 35,
            array_width: 60,
            chain_width: 60,
            single_line_if_else_max_width: 50,
        }
    }
}

impl ::std::str::FromStr for WidthHeuristics {
    type Err = &'static str;

    fn from_str(_: &str) -> Result<Self, Self::Err> {
        Err("WidthHeuristics is not parsable")
    }
}
<commit_msg>Update comment to say that Modified is for internal use only.<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use config_type::ConfigType;
use lists::*;

/// Macro for deriving implementations of Serialize/Deserialize for enums
#[macro_export]
macro_rules! impl_enum_serialize_and_deserialize {
    ( $e:ident, $( $x:ident ),* ) => {
        impl ::serde::ser::Serialize for $e {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: ::serde::ser::Serializer
            {
                use serde::ser::Error;

                // We don't know whether the user of the macro has given us all options.
                #[allow(unreachable_patterns)]
                match *self {
                    $(
                        $e::$x => serializer.serialize_str(stringify!($x)),
                    )*
                    _ => {
                        Err(S::Error::custom(format!("Cannot serialize {:?}", self)))
                    }
                }
            }
        }

        impl<'de> ::serde::de::Deserialize<'de> for $e {
            fn deserialize<D>(d: D) -> Result<Self, D::Error>
                    where D: ::serde::Deserializer<'de> {
                use serde::de::{Error, Visitor};
                use std::marker::PhantomData;
                use std::fmt;
                struct StringOnly<T>(PhantomData<T>);
                impl<'de, T> Visitor<'de> for StringOnly<T>
                        where T: ::serde::Deserializer<'de> {
                    type Value = String;
                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("string")
                    }
                    fn visit_str<E>(self, value: &str) -> Result<String, E> {
                        Ok(String::from(value))
                    }
                }
                let s = d.deserialize_string(StringOnly::<D>(PhantomData))?;
                $(
                    if stringify!($x).eq_ignore_ascii_case(&s) {
                      return Ok($e::$x);
                    }
                )*
                static ALLOWED: &'static[&str] = &[$(stringify!($x),)*];
                Err(D::Error::unknown_variant(&s, ALLOWED))
            }
        }

        impl ::std::str::FromStr for $e {
            type Err = &'static str;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                $(
                    if stringify!($x).eq_ignore_ascii_case(s) {
                        return Ok($e::$x);
                    }
                )*
                Err("Bad variant")
            }
        }

        impl ConfigType for $e {
            fn doc_hint() -> String {
                let mut variants = Vec::new();
                $(
                    variants.push(stringify!($x));
                )*
                format!("[{}]", variants.join("|"))
            }
        }
    };
}

macro_rules! configuration_option_enum{
    ($e:ident: $( $x:ident ),+ $(,)*) => {
        #[derive(Copy, Clone, Eq, PartialEq, Debug)]
        pub enum $e {
            $( $x ),+
        }

        impl_enum_serialize_and_deserialize!($e, $( $x ),+);
    }
}

configuration_option_enum! { NewlineStyle:
    Windows, // \r\n
    Unix, // \n
    Native, // \r\n in Windows, \n on other platforms
}

configuration_option_enum! { BraceStyle:
    AlwaysNextLine,
    PreferSameLine,
    // Prefer same line except where there is a where clause, in which case force
    // the brace to the next line.
    SameLineWhere,
}

configuration_option_enum! { ControlBraceStyle:
    // K&R style, Rust community default
    AlwaysSameLine,
    // Stroustrup style
    ClosingNextLine,
    // Allman style
    AlwaysNextLine,
}

configuration_option_enum! { IndentStyle:
    // First line on the same line as the opening brace, all lines aligned with
    // the first line.
    Visual,
    // First line is on a new line and all lines align with block indent.
    Block,
}

configuration_option_enum! { Density:
    // Fit as much on one line as possible.
    Compressed,
    // Use more lines.
    Tall,
    // Place every item on a separate line.
    Vertical,
}

configuration_option_enum! { TypeDensity:
    // No spaces around "=" and "+"
    Compressed,
    // Spaces around " = " and " + "
    Wide,
}

impl Density {
    pub fn to_list_tactic(self) -> ListTactic {
        match self {
            Density::Compressed => ListTactic::Mixed,
            Density::Tall => ListTactic::HorizontalVertical,
            Density::Vertical => ListTactic::Vertical,
        }
    }
}

configuration_option_enum! { ReportTactic:
    Always,
    Unnumbered,
    Never,
}

configuration_option_enum! { WriteMode:
    // Backs the original file up and overwrites the original.
    Replace,
    // Overwrites original file without backup.
    Overwrite,
    // Writes the output to stdout.
    Display,
    // Writes the diff to stdout.
    Diff,
    // Displays how much of the input file was processed
    Coverage,
    // Unfancy stdout
    Plain,
    // Outputs a checkstyle XML file.
    Checkstyle,
    // Output the changed lines (for internal value only)
    Modified,
}

configuration_option_enum! { Color:
    // Always use color, whether it is a piped or terminal output
    Always,
    // Never use color
    Never,
    // Automatically use color, if supported by terminal
    Auto,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct WidthHeuristics {
    // Maximum width of the args of a function call before falling back
    // to vertical formatting.
    pub fn_call_width: usize,
    // Maximum width in the body of a struct lit before falling back to
    // vertical formatting.
    pub struct_lit_width: usize,
    // Maximum width in the body of a struct variant before falling back
    // to vertical formatting.
    pub struct_variant_width: usize,
    // Maximum width of an array literal before falling back to vertical
    // formatting.
    pub array_width: usize,
    // Maximum length of a chain to fit on a single line.
    pub chain_width: usize,
    // Maximum line length for single line if-else expressions. A value
    // of zero means always break if-else expressions.
    pub single_line_if_else_max_width: usize,
}

impl WidthHeuristics {
    // Using this WidthHeuristics means we ignore heuristics.
    pub fn null() -> WidthHeuristics {
        WidthHeuristics {
            fn_call_width: usize::max_value(),
            struct_lit_width: 0,
            struct_variant_width: 0,
            array_width: usize::max_value(),
            chain_width: usize::max_value(),
            single_line_if_else_max_width: 0,
        }
    }
}

impl Default for WidthHeuristics {
    fn default() -> WidthHeuristics {
        WidthHeuristics {
            fn_call_width: 60,
            struct_lit_width: 18,
            struct_variant_width: 35,
            array_width: 60,
            chain_width: 60,
            single_line_if_else_max_width: 50,
        }
    }
}

impl ::std::str::FromStr for WidthHeuristics {
    type Err = &'static str;

    fn from_str(_: &str) -> Result<Self, Self::Err> {
        Err("WidthHeuristics is not parsable")
    }
}
<|endoftext|>


<commit_before>//! **Plexus** is a library for polygonal mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable.

// TODO: Functions of the `fool::BoolExt` trait may collide with planned
//       inherent functions for `bool`. Most uses of these functions would cause
//       errors if these functions land in `bool`.
//
//       See uses of `#[allow(unstable_name_collisions)]`.

// This lint is a bit subjective. Using `next` is equivalent, but the Plexus
// authors find `nth(0)` more clear, especially as part of a non-trivial
// iterator expression. This may be revisited though.
#![allow(clippy::iter_nth_zero)]
#![doc(html_favicon_url = "https://plexus.rs/img/favicon.ico")]
#![doc(html_logo_url = "https://plexus.rs/img/plexus.svg")]

pub mod buffer;
pub mod builder;
pub mod encoding;
mod entity;
pub mod graph;
pub mod index;
pub mod integration;
pub mod primitive;
mod transact;

use itertools::{self, Itertools, MinMaxResult, MultiPeek};
use std::borrow::Borrow;
use std::fmt::Debug;

use crate::entity::view::ClosedView;

pub use theon::{AsPosition, Position};
pub use typenum::{U2, U3, U4};

pub mod prelude {
    //! Re-exports commonly used types and traits.
    //!
    //! Importing the contents of this module is recommended, especially when
    //! working with generators and iterator expressions, as those operations
    //! are expressed mostly through traits.
    //!
    //! # Traits
    //!
    //! This module re-exports numerous traits. Traits from the [`primitive`]
    //! module for generating and decomposing iterators over topological data
    //! (e.g., [`Trigon`], [`Tetragon`], etc.) are re-exported so that functions
    //! in iterator expressions can be used without lengthy imports.
    //!
    //! Basic traits for (de)constructing [`MeshBuffer`]s and [`MeshGraph`]s are
    //! also re-exported. These traits allow mesh types to be constructed from
    //! raw buffers and buffers to be re-indexed.
    //!
    //! # Types
    //!
    //! The [`Selector`] `enum` and its variants are re-exported for
    //! convenience. [`Selector`] is often used when mutating [`MeshGraph`]s.
    //!
    //! [`MeshBuffer`]: ../buffer/struct.MeshBuffer.html
    //! [`MeshGraph`]: ../graph/struct.MeshGraph.html
    //! [`primitive`]: ../primitive/index.html
    //! [`Selector`]: ../graph/enum.Selector.html
    //! [`Tetragon`]: ../primitive/type.Tetragon.html
    //! [`Trigon`]: ../primitive/type.Trigon.html

    pub use crate::buffer::{
        FromRawBuffers as _, FromRawBuffersWithArity as _, IntoFlatIndex as _,
        IntoStructuredIndex as _,
    };
    pub use crate::builder::{FacetBuilder as _, MeshBuilder as _, SurfaceBuilder as _};
    pub use crate::graph::{ClosedView as _, Rebind as _, Selector};
    pub use crate::index::{CollectWithIndexer as _, IndexVertices as _};
    pub use crate::primitive::decompose::{
        Edges as _, IntoEdges as _, IntoSubdivisions as _, IntoTetrahedrons as _, IntoTrigons as _,
        IntoVertices as _, Subdivide as _, Tetrahedrons as _, Triangulate as _, Vertices as _,
    };
    pub use crate::primitive::generate::Generator as _;
    pub use crate::primitive::{
        IntoPolygons as _, MapVertices as _, Polygonal as _, Topological as _,
    };
    pub use crate::IteratorExt as _;
    pub use crate::{DynamicArity as _, FromGeometry as _, IntoGeometry as _};

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub trait Arity: Copy {
    fn into_interval(self) -> (usize, Option<usize>);
}

/// Singular arity.
impl Arity for usize {
    fn into_interval(self) -> (usize, Option<usize>) {
        (self, Some(self))
    }
}

/// Closed interval arity.
///
/// This type represents a _closed interval_ arity with a minimum and maximum
/// inclusive range.
impl Arity for (usize, usize) {
    fn into_interval(self) -> (usize, Option<usize>) {
        let (min, max) = self;
        (min, Some(max))
    }
}

/// Open interval arity.
///
/// This type represents an _open interval_ arity with a minimum and optional
/// maximum inclusive range. When there is no maximum (`None`), the maximum
/// arity is unspecified. This typically means that there is no theoretical
/// maximum.
impl Arity for (usize, Option<usize>) {
    fn into_interval(self) -> (usize, Option<usize>) {
        self
    }
}

/// Type-level arity.
///
/// This trait specifies the arity that a type supports. Values of a
/// `StaticArity` type have an arity that reflects this constant, which may be
/// any type or form implementing the [`Arity`] trait.
///
/// [`Arity`]: trait.Arity.html
pub trait StaticArity {
    type Static: Arity;

    const ARITY: Self::Static;
}

/// Value-level arity.
///
/// This trait specifies the arity of a value at runtime. This is often
/// distinct from the type-level arity of the [`StaticArity`] trait, which
/// expresses the capabilities of a type.
///
/// [`StaticArity`]: trait.StaticArity.html
pub trait DynamicArity: StaticArity {
    type Dynamic: Arity;

    fn arity(&self) -> Self::Dynamic;
}

/// Topological types with fixed and singular arity.
///
/// Types are _monomorphic_ if they have a fixed and singular arity as types and
/// values. For example, [`Trigon`] always and only represents a trigon
/// (triangle) with an arity of three. [`Trigon`] values always have an arity of
/// three and types composed of only [`Trigon`]s have a compound arity of three.
///
/// This contrasts _polymorphic_ types like [`BoundedPolygon`], which have an
/// interval arity at the type-level and a singular but varying arity for values
/// (because a [`BoundedPolygon`] value may be either a trigon or tertragon).
///
/// [`BoundedPolygon`]: primitive/enum.BoundedPolygon.html
/// [`Trigon`]: primitive/type.Trigon.html
pub trait Monomorphic: StaticArity<Static = usize> {}

/// Arity of a compound structure.
///
/// `MeshArity` represents the arity of a compound structure, which may be
/// _uniform_ or _non-uniform_. This is typically the value-level arity for
/// mesh data structures like [`MeshGraph`] and [`MeshBuffer`].
///
/// [`MeshBuffer`]: buffer/struct.MeshBuffer.html
/// [`MeshGraph`]: graph/struct.MeshGraph.html
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MeshArity {
    /// A compound structure has _uniform_ arity if all of its components have
    /// the same arity, such as a `MeshBuffer` composed entirely of trigons.
    Uniform(usize),
    /// A compound structure has _non-uniform_ arity if the arity of its
    /// components differ, such as a `MeshGraph` composed of trigons and
    /// tetragons.
    ///
    /// Non-uniform arity is represented as an inclusive range known as an
    /// _interval_. This is the minimum and maximum arity of the components, in
    /// that order.
    NonUniform(usize, usize),
}

impl MeshArity {
    pub fn from_components<T, I>(components: I) -> Self
    where
        T: DynamicArity<Dynamic = usize>,
        I: IntoIterator,
        I::Item: Borrow<T>,
    {
        match components
            .into_iter()
            .map(|component| component.borrow().arity())
            .minmax()
        {
            MinMaxResult::OneElement(exact) => MeshArity::Uniform(exact),
            MinMaxResult::MinMax(min, max) => MeshArity::NonUniform(min, max),
            _ => MeshArity::Uniform(0),
        }
    }
}

impl Arity for MeshArity {
    fn into_interval(self) -> (usize, Option<usize>) {
        match self {
            MeshArity::Uniform(exact) => (exact, Some(exact)),
            MeshArity::NonUniform(min, max) => (min, Some(max)),
        }
    }
}

pub trait FromGeometry<T> {
    fn from_geometry(other: T) -> Self;
}

impl<T> FromGeometry<T> for T {
    fn from_geometry(other: T) -> Self {
        other
    }
}

/// Geometry elision into `()`.
impl<T> FromGeometry<T> for ()
where
    T: UnitGeometry,
{
    fn from_geometry(_: T) -> Self {}
}

/// Geometry elision from `()`.
impl<T> FromGeometry<()> for T
where
    T: UnitGeometry + Default,
{
    fn from_geometry(_: ()) -> Self {
        T::default()
    }
}

/// Geometry elision.
///
/// Geometric types that implement this trait may be elided. In particular,
/// these types may be converted into and from `()` via the [`FromGeometry`] and
/// [`IntoGeometry`] traits.
///
/// For a geometric type `T`, the following table illustrates the elisions in
/// which `T` may participate:
///
/// | Bounds on `T`            | From | Into |
/// |--------------------------|------|------|
/// | `UnitGeometry`           | `T`  | `()` |
/// | `Default + UnitGeometry` | `()` | `T`  |
///
/// These conversions are useful when converting between mesh data structures
/// with incompatible geometry, such as from a [`MeshGraph`] with face geometry
/// to a [`MeshBuffer`] that cannot support such geometry.
///
/// When geometry features are enabled, `UnitGeometry` is implemented for
/// integrated foreign types.
///
/// [`FromGeometry`]: trait.FromGeometry.html
/// [`IntoGeometry`]: trait.IntoGeometry.html
/// [`MeshBuffer`]: buffer/struct.MeshBuffer.html
/// [`MeshGraph`]: graph/struct.MeshGraph.html
pub trait UnitGeometry {}

pub trait IntoGeometry<T> {
    fn into_geometry(self) -> T;
}

impl<T, U> IntoGeometry<U> for T
where
    U: FromGeometry<T>,
{
    fn into_geometry(self) -> U {
        U::from_geometry(self)
    }
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection of ordered elements $\\{a, b, c\\}$, this iterator
    /// yeilds the ordered items $\\{(a, b), (b, c), (c, a)\\}$.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone,
    {
        Perimeter::new(self)
    }

    /// Maps an iterator over topological views to the keys of those views.
    ///
    /// It is often useful to examine or collect the keys of views over a
    /// [`MeshGraph`]. This iterator avoids redundant use of `map` to extract
    /// keys.
    ///
    /// # Examples
    ///
    /// Collecting keys of faces before a topological mutation:
    ///
    /// ```rust
    /// # extern crate decorum;
    /// # extern crate nalgebra;
    /// # extern crate plexus;
    /// #
    /// use decorum::R64;
    /// use nalgebra::Point3;
    /// use plexus::graph::MeshGraph;
    /// use plexus::prelude::*;
    /// use plexus::primitive::generate::Position;
    /// use plexus::primitive::sphere::UvSphere;
    ///
    /// type E3 = Point3<R64>;
    ///
    /// let mut graph = UvSphere::new(6, 6)
    ///     .polygons::<Position<E3>>()
    ///     .collect::<MeshGraph<E3>>();
    ///
    /// let keys = graph
    ///     .faces()
    ///     .filter(|face| face.arity() > 3)
    ///     .keys()
    ///     .collect::<Vec<_>>();
    /// for key in keys {
    ///     graph.face_mut(key).unwrap().poke_with_offset(0.5);
    /// }
    /// ```
    ///
    /// [`MeshGraph`]: graph/struct.MeshGraph.html
    fn keys(self) -> Keys<Self>
    where
        Self::Item: ClosedView,
    {
        Keys::new(self)
    }

    /// Determines if an iterator provides `n` or more elements.
    ///
    /// Returns a peekable iterator if the source iterator provides at least `n`
    /// elements, otherwise `None`.
    ///
    /// # Examples
    ///
    /// Ensuring that an iterator over vertices has an arity of at least three:
    ///
    /// ```rust
    /// use plexus::IteratorExt;
    ///
    /// fn is_convex(vertices: impl Iterator<Item = [f64; 2]>) -> bool {
    ///     vertices
    ///         .has_at_least(3)
    ///         .and_then(|vertices| {
    ///             for vertex in vertices {
    ///                 // ...
    ///             }
    ///             // ...
    ///             # Some(0usize)
    ///         })
    ///         .is_some()
    /// }
    /// ```
    fn has_at_least(self, n: usize) -> Option<MultiPeek<Self>> {
        let mut peekable = itertools::multipeek(self);
        let mut i = 0usize;
        while i < n {
            i = i + 1;
            peekable.peek()?;
        }
        peekable.reset_peek();
        Some(peekable)
    }
}

impl<I> IteratorExt for I where I: Iterator {}

/// Iterator that produces a window of duplets over its input.
///
/// The duplets produced include the first value in the input sequence at both
/// the beginning and end of the iteration, forming a perimeter. Given a
/// collection of ordered elements $\\{a, b, c\\}$, this iterator yields the
/// ordered items $\\{(a, b), (b, c), (c, a)\\}$.
#[derive(Clone)]
pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

impl<I> Iterator for Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}

#[derive(Clone)]
pub struct Keys<I>
where
    I: Iterator,
    I::Item: ClosedView,
{
    input: I,
}

impl<I> Keys<I>
where
    I: Iterator,
    I::Item: ClosedView,
{
    fn new(input: I) -> Self {
        Keys { input }
    }
}

impl<I> Iterator for Keys<I>
where
    I: Iterator,
    I::Item: ClosedView,
{
    type Item = <I::Item as ClosedView>::Key;

    fn next(&mut self) -> Option<Self::Item> {
        self.input.next().map(|view| view.key())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}
<commit_msg>Replace `while` loop with `for` loop.<commit_after>//! **Plexus** is a library for polygonal mesh processing.
//!
//! Please note that versions in the `0.0.*` series are experimental and
//! unstable.

// TODO: Functions of the `fool::BoolExt` trait may collide with planned
//       inherent functions for `bool`. Most uses of these functions would cause
//       errors if these functions land in `bool`.
//
//       See uses of `#[allow(unstable_name_collisions)]`.

// This lint is a bit subjective. Using `next` is equivalent, but the Plexus
// authors find `nth(0)` more clear, especially as part of a non-trivial
// iterator expression. This may be revisited though.
#![allow(clippy::iter_nth_zero)]
#![doc(html_favicon_url = "https://plexus.rs/img/favicon.ico")]
#![doc(html_logo_url = "https://plexus.rs/img/plexus.svg")]

pub mod buffer;
pub mod builder;
pub mod encoding;
mod entity;
pub mod graph;
pub mod index;
pub mod integration;
pub mod primitive;
mod transact;

use itertools::{self, Itertools, MinMaxResult, MultiPeek};
use std::borrow::Borrow;
use std::fmt::Debug;

use crate::entity::view::ClosedView;

pub use theon::{AsPosition, Position};
pub use typenum::{U2, U3, U4};

pub mod prelude {
    //! Re-exports commonly used types and traits.
    //!
    //! Importing the contents of this module is recommended, especially when
    //! working with generators and iterator expressions, as those operations
    //! are expressed mostly through traits.
    //!
    //! # Traits
    //!
    //! This module re-exports numerous traits. Traits from the [`primitive`]
    //! module for generating and decomposing iterators over topological data
    //! (e.g., [`Trigon`], [`Tetragon`], etc.) are re-exported so that functions
    //! in iterator expressions can be used without lengthy imports.
    //!
    //! Basic traits for (de)constructing [`MeshBuffer`]s and [`MeshGraph`]s are
    //! also re-exported. These traits allow mesh types to be constructed from
    //! raw buffers and buffers to be re-indexed.
    //!
    //! # Types
    //!
    //! The [`Selector`] `enum` and its variants are re-exported for
    //! convenience. [`Selector`] is often used when mutating [`MeshGraph`]s.
    //!
    //! [`MeshBuffer`]: ../buffer/struct.MeshBuffer.html
    //! [`MeshGraph`]: ../graph/struct.MeshGraph.html
    //! [`primitive`]: ../primitive/index.html
    //! [`Selector`]: ../graph/enum.Selector.html
    //! [`Tetragon`]: ../primitive/type.Tetragon.html
    //! [`Trigon`]: ../primitive/type.Trigon.html

    pub use crate::buffer::{
        FromRawBuffers as _, FromRawBuffersWithArity as _, IntoFlatIndex as _,
        IntoStructuredIndex as _,
    };
    pub use crate::builder::{FacetBuilder as _, MeshBuilder as _, SurfaceBuilder as _};
    pub use crate::graph::{ClosedView as _, Rebind as _, Selector};
    pub use crate::index::{CollectWithIndexer as _, IndexVertices as _};
    pub use crate::primitive::decompose::{
        Edges as _, IntoEdges as _, IntoSubdivisions as _, IntoTetrahedrons as _, IntoTrigons as _,
        IntoVertices as _, Subdivide as _, Tetrahedrons as _, Triangulate as _, Vertices as _,
    };
    pub use crate::primitive::generate::Generator as _;
    pub use crate::primitive::{
        IntoPolygons as _, MapVertices as _, Polygonal as _, Topological as _,
    };
    pub use crate::IteratorExt as _;
    pub use crate::{DynamicArity as _, FromGeometry as _, IntoGeometry as _};

    pub use Selector::ByIndex;
    pub use Selector::ByKey;
}

pub trait Arity: Copy {
    fn into_interval(self) -> (usize, Option<usize>);
}

/// Singular arity.
impl Arity for usize {
    fn into_interval(self) -> (usize, Option<usize>) {
        (self, Some(self))
    }
}

/// Closed interval arity.
///
/// This type represents a _closed interval_ arity with a minimum and maximum
/// inclusive range.
impl Arity for (usize, usize) {
    fn into_interval(self) -> (usize, Option<usize>) {
        let (min, max) = self;
        (min, Some(max))
    }
}

/// Open interval arity.
///
/// This type represents an _open interval_ arity with a minimum and optional
/// maximum inclusive range. When there is no maximum (`None`), the maximum
/// arity is unspecified. This typically means that there is no theoretical
/// maximum.
impl Arity for (usize, Option<usize>) {
    fn into_interval(self) -> (usize, Option<usize>) {
        self
    }
}

/// Type-level arity.
///
/// This trait specifies the arity that a type supports. Values of a
/// `StaticArity` type have an arity that reflects this constant, which may be
/// any type or form implementing the [`Arity`] trait.
///
/// [`Arity`]: trait.Arity.html
pub trait StaticArity {
    type Static: Arity;

    const ARITY: Self::Static;
}

/// Value-level arity.
///
/// This trait specifies the arity of a value at runtime. This is often
/// distinct from the type-level arity of the [`StaticArity`] trait, which
/// expresses the capabilities of a type.
///
/// [`StaticArity`]: trait.StaticArity.html
pub trait DynamicArity: StaticArity {
    type Dynamic: Arity;

    fn arity(&self) -> Self::Dynamic;
}

/// Topological types with fixed and singular arity.
///
/// Types are _monomorphic_ if they have a fixed and singular arity as types and
/// values. For example, [`Trigon`] always and only represents a trigon
/// (triangle) with an arity of three. [`Trigon`] values always have an arity of
/// three and types composed of only [`Trigon`]s have a compound arity of three.
///
/// This contrasts _polymorphic_ types like [`BoundedPolygon`], which have an
/// interval arity at the type-level and a singular but varying arity for values
/// (because a [`BoundedPolygon`] value may be either a trigon or tertragon).
///
/// [`BoundedPolygon`]: primitive/enum.BoundedPolygon.html
/// [`Trigon`]: primitive/type.Trigon.html
pub trait Monomorphic: StaticArity<Static = usize> {}

/// Arity of a compound structure.
///
/// `MeshArity` represents the arity of a compound structure, which may be
/// _uniform_ or _non-uniform_. This is typically the value-level arity for
/// mesh data structures like [`MeshGraph`] and [`MeshBuffer`].
///
/// [`MeshBuffer`]: buffer/struct.MeshBuffer.html
/// [`MeshGraph`]: graph/struct.MeshGraph.html
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum MeshArity {
    /// A compound structure has _uniform_ arity if all of its components have
    /// the same arity, such as a `MeshBuffer` composed entirely of trigons.
    Uniform(usize),
    /// A compound structure has _non-uniform_ arity if the arity of its
    /// components differ, such as a `MeshGraph` composed of trigons and
    /// tetragons.
    ///
    /// Non-uniform arity is represented as an inclusive range known as an
    /// _interval_. This is the minimum and maximum arity of the components, in
    /// that order.
    NonUniform(usize, usize),
}

impl MeshArity {
    pub fn from_components<T, I>(components: I) -> Self
    where
        T: DynamicArity<Dynamic = usize>,
        I: IntoIterator,
        I::Item: Borrow<T>,
    {
        match components
            .into_iter()
            .map(|component| component.borrow().arity())
            .minmax()
        {
            MinMaxResult::OneElement(exact) => MeshArity::Uniform(exact),
            MinMaxResult::MinMax(min, max) => MeshArity::NonUniform(min, max),
            _ => MeshArity::Uniform(0),
        }
    }
}

impl Arity for MeshArity {
    fn into_interval(self) -> (usize, Option<usize>) {
        match self {
            MeshArity::Uniform(exact) => (exact, Some(exact)),
            MeshArity::NonUniform(min, max) => (min, Some(max)),
        }
    }
}

pub trait FromGeometry<T> {
    fn from_geometry(other: T) -> Self;
}

impl<T> FromGeometry<T> for T {
    fn from_geometry(other: T) -> Self {
        other
    }
}

/// Geometry elision into `()`.
impl<T> FromGeometry<T> for ()
where
    T: UnitGeometry,
{
    fn from_geometry(_: T) -> Self {}
}

/// Geometry elision from `()`.
impl<T> FromGeometry<()> for T
where
    T: UnitGeometry + Default,
{
    fn from_geometry(_: ()) -> Self {
        T::default()
    }
}

/// Geometry elision.
///
/// Geometric types that implement this trait may be elided. In particular,
/// these types may be converted into and from `()` via the [`FromGeometry`] and
/// [`IntoGeometry`] traits.
///
/// For a geometric type `T`, the following table illustrates the elisions in
/// which `T` may participate:
///
/// | Bounds on `T`            | From | Into |
/// |--------------------------|------|------|
/// | `UnitGeometry`           | `T`  | `()` |
/// | `Default + UnitGeometry` | `()` | `T`  |
///
/// These conversions are useful when converting between mesh data structures
/// with incompatible geometry, such as from a [`MeshGraph`] with face geometry
/// to a [`MeshBuffer`] that cannot support such geometry.
///
/// When geometry features are enabled, `UnitGeometry` is implemented for
/// integrated foreign types.
///
/// [`FromGeometry`]: trait.FromGeometry.html
/// [`IntoGeometry`]: trait.IntoGeometry.html
/// [`MeshBuffer`]: buffer/struct.MeshBuffer.html
/// [`MeshGraph`]: graph/struct.MeshGraph.html
pub trait UnitGeometry {}

pub trait IntoGeometry<T> {
    fn into_geometry(self) -> T;
}

impl<T, U> IntoGeometry<U> for T
where
    U: FromGeometry<T>,
{
    fn into_geometry(self) -> U {
        U::from_geometry(self)
    }
}

/// Extension methods for types implementing `Iterator`.
pub trait IteratorExt: Iterator + Sized {
    /// Provides an iterator over a window of duplets that includes the first
    /// value in the sequence at the beginning and end of the iteration.
    ///
    /// Given a collection of ordered elements $\\{a, b, c\\}$, this iterator
    /// yeilds the ordered items $\\{(a, b), (b, c), (c, a)\\}$.
    fn perimeter(self) -> Perimeter<Self>
    where
        Self::Item: Clone,
    {
        Perimeter::new(self)
    }

    /// Maps an iterator over topological views to the keys of those views.
    ///
    /// It is often useful to examine or collect the keys of views over a
    /// [`MeshGraph`]. This iterator avoids redundant use of `map` to extract
    /// keys.
    ///
    /// # Examples
    ///
    /// Collecting keys of faces before a topological mutation:
    ///
    /// ```rust
    /// # extern crate decorum;
    /// # extern crate nalgebra;
    /// # extern crate plexus;
    /// #
    /// use decorum::R64;
    /// use nalgebra::Point3;
    /// use plexus::graph::MeshGraph;
    /// use plexus::prelude::*;
    /// use plexus::primitive::generate::Position;
    /// use plexus::primitive::sphere::UvSphere;
    ///
    /// type E3 = Point3<R64>;
    ///
    /// let mut graph = UvSphere::new(6, 6)
    ///     .polygons::<Position<E3>>()
    ///     .collect::<MeshGraph<E3>>();
    ///
    /// let keys = graph
    ///     .faces()
    ///     .filter(|face| face.arity() > 3)
    ///     .keys()
    ///     .collect::<Vec<_>>();
    /// for key in keys {
    ///     graph.face_mut(key).unwrap().poke_with_offset(0.5);
    /// }
    /// ```
    ///
    /// [`MeshGraph`]: graph/struct.MeshGraph.html
    fn keys(self) -> Keys<Self>
    where
        Self::Item: ClosedView,
    {
        Keys::new(self)
    }

    /// Determines if an iterator provides `n` or more elements.
    ///
    /// Returns a peekable iterator if the source iterator provides at least `n`
    /// elements, otherwise `None`.
    ///
    /// # Examples
    ///
    /// Ensuring that an iterator over vertices has an arity of at least three:
    ///
    /// ```rust
    /// use plexus::IteratorExt;
    ///
    /// fn is_convex(vertices: impl Iterator<Item = [f64; 2]>) -> bool {
    ///     vertices
    ///         .has_at_least(3)
    ///         .and_then(|vertices| {
    ///             for vertex in vertices {
    ///                 // ...
    ///             }
    ///             // ...
    ///             # Some(0usize)
    ///         })
    ///         .is_some()
    /// }
    /// ```
    fn has_at_least(self, n: usize) -> Option<MultiPeek<Self>> {
        let mut peekable = itertools::multipeek(self);
        for _ in 0..n {
            peekable.peek()?;
        }
        peekable.reset_peek();
        Some(peekable)
    }
}

impl<I> IteratorExt for I where I: Iterator {}

/// Iterator that produces a window of duplets over its input.
///
/// The duplets produced include the first value in the input sequence at both
/// the beginning and end of the iteration, forming a perimeter. Given a
/// collection of ordered elements $\\{a, b, c\\}$, this iterator yields the
/// ordered items $\\{(a, b), (b, c), (c, a)\\}$.
#[derive(Clone)]
pub struct Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    input: I,
    first: Option<I::Item>,
    previous: Option<I::Item>,
}

impl<I> Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    fn new(mut input: I) -> Self {
        let first = input.next();
        let previous = first.clone();
        Perimeter {
            input,
            first,
            previous,
        }
    }
}

impl<I> Iterator for Perimeter<I>
where
    I: Iterator,
    I::Item: Clone,
{
    type Item = (I::Item, I::Item);

    fn next(&mut self) -> Option<Self::Item> {
        let next = self.input.next();
        match (self.previous.clone(), next.or_else(|| self.first.take())) {
            (Some(a), Some(b)) => {
                self.previous = Some(b.clone());
                Some((a, b))
            }
            _ => None,
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}

#[derive(Clone)]
pub struct Keys<I>
where
    I: Iterator,
    I::Item: ClosedView,
{
    input: I,
}

impl<I> Keys<I>
where
    I: Iterator,
    I::Item: ClosedView,
{
    fn new(input: I) -> Self {
        Keys { input }
    }
}

impl<I> Iterator for Keys<I>
where
    I: Iterator,
    I::Item: ClosedView,
{
    type Item = <I::Item as ClosedView>::Key;

    fn next(&mut self) -> Option<Self::Item> {
        self.input.next().map(|view| view.key())
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.input.size_hint()
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "filelocal", feature(proc_macro_span))]

extern crate proc_macro;

use syn::parse;
use syn::{Token, parse_macro_input};
use proc_macro2::{TokenTree, TokenStream};
use quote::quote;
use proc_macro_error::proc_macro_error;

use std::collections::HashMap;

#[cfg(feature = "filelocal")]
use std::sync::{MutexGuard, Mutex};
#[cfg(feature = "filelocal")]
use std::path::PathBuf;
#[cfg(any(feature = "filelocal", feature = "dynasm_opmap", feature = "dynasm_extract"))]
use proc_macro2::Span;

/// Module with common infrastructure across assemblers
mod common;
/// Module with architecture-specific assembler implementations
mod arch;
/// Module contaning the implementation of directives
mod directive;
/// Module containing utility functions for creating TokenTrees from assembler / directive output
mod serialize;
/// Module containing utility functions for parsing
mod parse_helpers;

/// The whole point
#[proc_macro]
#[proc_macro_error]
pub fn dynasm(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
    // try parsing the tokenstream into a dynasm struct containing
    // an abstract representation of the statements to create
    let dynasm = parse_macro_input!(tokens as Dynasm);

    // serialize the resulting output into tokens
    serialize::serialize(&dynasm.target, dynasm.stmts).into()
}

/// point whole The
#[proc_macro]
#[proc_macro_error]
pub fn msanyd(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
    // try parsing the tokenstream into a dynasm struct containing
    // an abstract representation of the statements to create
    let dynasm = parse_macro_input!(tokens as Dynasm);

    // reverse the statement stream
    let stmts = serialize::invert(dynasm.stmts);

    // serialize the resulting output into tokens
    serialize::serialize(&dynasm.target, stmts).into()
}

/// output from parsing a full dynasm invocation. target represents the first dynasm argument, being the assembler
/// variable being used. stmts contains an abstract representation of the statements to be generated from this dynasm
/// invocation.
struct Dynasm {
    target: TokenTree,
    stmts: Vec<common::Stmt>
}

/// top-level parsing. Handles common prefix symbols and diverts to the selected architecture
/// when an assembly instruction is encountered. When parsing fails an Err() is returned, when
/// non-parsing errors happen err() will be called, but this function returns Ok().
impl parse::Parse for Dynasm {
    fn parse(input: parse::ParseStream) -> parse::Result<Self> {

        // parse the assembler target declaration
        let target: syn::Expr = input.parse()?;
        // and just convert it back to a tokentree since that's how we'll always be using it.
        let target = common::delimited(target);

        // get file-local data (alias definitions, current architecture)
        let mut provider = ContextProvider::new();
        let invocation_context = provider.get_context_mut();

        // prepare the statement buffer
        let mut stmts = Vec::new();

        // if we're not at the end of the macro, we should be expecting a semicolon and a new directive/statement/label/op
        while !input.is_empty() {
            let _: Token![;] = input.parse()?;

            // ;; stmt
            if input.peek(Token![;]) {
                let _: Token![;] = input.parse()?;

                // collect all tokentrees till the next ;
                let mut buffer = TokenStream::new();
                while !(input.is_empty() || input.peek(Token![;])) {
                    buffer.extend(std::iter::once(input.parse::<TokenTree>()?));
                }
                // glue an extra ; on there
                buffer.extend(quote! { ; } );

                if !buffer.is_empty() {
                    // ensure that the statement is actually a proper statement and then emit it for serialization
                    let stmt: syn::Stmt = syn::parse2(buffer)?;
                    stmts.push(common::Stmt::Stmt(common::delimited(stmt)));
                }
                continue;
            }

            // ; -> label :
            if input.peek(Token![->]) {
                let _: Token![->] = input.parse()?;

                let name: syn::Ident = input.parse()?;
                let _: Token![:] = input.parse()?;

                stmts.push(common::Stmt::GlobalLabel(name));
                continue;
            }

            // ; => expr
            if input.peek(Token![=>]) {
                let _: Token![=>] = input.parse()?;

                let expr: syn::Expr = input.parse()?;

                stmts.push(common::Stmt::DynamicLabel(common::delimited(expr)));
                continue;
            }

            // ; label :
            if input.peek(syn::Ident) && input.peek2(Token![:]) {

                let name: syn::Ident = input.parse()?;
                let _: Token![:] = input.parse()?;

                stmts.push(common::Stmt::LocalLabel(name));
                continue;
            }

            // ; . directive
            if input.peek(Token![.]) {
                let _: Token![.] = input.parse()?;

                directive::evaluate_directive(invocation_context, &mut stmts, input)?;
            } else {
                // anything else is an assembly instruction which should be in current_arch

                let mut state = State {
                    stmts: &mut stmts,
                    target: &target,
                    invocation_context: &*invocation_context,
                };
                invocation_context.current_arch.compile_instruction(&mut state, input)?;
            }

        }

        Ok(Dynasm {
            target,
            stmts
        })
    }
}

/// This is only compiled when the dynasm_opmap feature is used. It exports the internal assembly listings
/// into a string that can then be included into the documentation for dynasm.
#[cfg(feature = "dynasm_opmap")]
#[proc_macro]
pub fn dynasm_opmap(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {

    // parse to ensure that no macro arguments were provided
    let opmap = parse_macro_input!(tokens as DynasmOpmap);

    let mut s = String::new();
    s.push_str("% Instruction Reference\n\n");

    s.push_str(&match opmap.arch.as_str() {
        "x64" | "x86" => arch::x64::create_opmap(),
        "aarch64" => arch::aarch64::create_opmap(),
        x => panic!("Unknown architecture {}", x)
    });

    let token = quote::quote_spanned! { Span::mixed_site()=>
        #s
    };
    token.into()
}

/// This is only compiled when the dynasm_extract feature is used. It exports the internal assembly listings
/// into a string that can then be included into the documentation for dynasm.
#[cfg(feature = "dynasm_extract")]
#[proc_macro]
pub fn dynasm_extract(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {

    // parse to ensure that no macro arguments were provided
    let opmap = parse_macro_input!(tokens as DynasmOpmap);

    let s = match opmap.arch.as_str() {
        "x64" | "x86" => "UNIMPLEMENTED".into(),
        "aarch64" => arch::aarch64::extract_opmap(),
        x => panic!("Unknown architecture {}", x)
    };

    let token = quote::quote_spanned! { Span::mixed_site()=>
        #s
    };
    token.into()
}

/// As dynasm_opmap takes no args it doesn't parse to anything
struct DynasmOpmap {
    pub arch: String
}

/// As dynasm_opmap takes no args it doesn't parse to anything.
/// This just exists so syn will give an error when no args are present.
impl parse::Parse for DynasmOpmap {
    fn parse(input: parse::ParseStream) -> parse::Result<Self> {
        let arch: syn::Ident = input.parse()?;

        Ok(DynasmOpmap {
            arch: arch.to_string()
        })
    }
}

/// This struct contains all non-parsing state that dynasm! requires while parsing and compiling
struct State<'a> {
    pub stmts: &'a mut Vec<common::Stmt>,
    pub target: &'a TokenTree,
    pub invocation_context: &'a DynasmContext,
}

// File local data implementation.

// context inside of a dynasm invocation, manipulated by directives and such
struct DynasmContext {
    pub current_arch: Box<dyn arch::Arch>,
    pub aliases: HashMap<String, String>,
}

impl DynasmContext {
    fn new() -> DynasmContext {
        DynasmContext {
            current_arch: arch::from_str(arch::CURRENT_ARCH).expect("Invalid default architecture"),
            aliases: HashMap::new()
        }
    }
}

// Oneshot context provider
#[cfg(not(feature = "filelocal"))]
struct ContextProvider {
    context: DynasmContext
}

#[cfg(not(feature = "filelocal"))]
impl ContextProvider {
    pub fn new() -> ContextProvider {
        ContextProvider {
            context: DynasmContext::new()
        }
    }

    pub fn get_context_mut(&mut self) -> &mut DynasmContext {
        &mut self.context
    }
}

/// Filelocal context provider
#[cfg(feature = "filelocal")]
struct ContextProvider {
    guard: MutexGuard<'static, HashMap<PathBuf, DynasmContext>>
}

#[cfg(feature = "filelocal")]
impl ContextProvider {
    pub fn new() -> ContextProvider {
        ContextProvider {
            guard: CONTEXT_STORAGE.lock().unwrap()
        }
    }

    pub fn get_context_mut(&mut self) -> &mut DynasmContext {
        // get the file that generated this macro expansion
        let span = Span::call_site().unstable();

        // and use the file that that was at as scope for resolving dynasm data
        let id = span.source_file().path();

        self.guard.entry(id).or_insert_with(DynasmContext::new)
    }
}

#[cfg(feature = "filelocal")]
lazy_static::lazy_static! {
    static ref CONTEXT_STORAGE: Mutex<HashMap<PathBuf, DynasmContext>> = Mutex::new(HashMap::new());
}

// type DynasmStorage = HashMap<PathBuf, Mutex<DynasmData>>;

// struct DynasmData {
//     pub current_arch: Box<dyn arch::Arch>,
//     pub aliases: HashMap<String, String>,
// }

// impl DynasmData {
//     fn new() -> DynasmData {
//         DynasmData {
//             current_arch:
//                 arch::from_str(arch::CURRENT_ARCH).expect("Default architecture is invalid"),
//             aliases: HashMap::new(),
//         }
//     }
// }

// type FileLocalData = OwningRef<RwLockReadGuard<'static, DynasmStorage>, Mutex<DynasmData>>;

// fn file_local_data() -> FileLocalData {
//     // get the file that generated this macro expansion
//     let span = Span::call_site().unstable();

//     // and use the file that that was at as scope for resolving dynasm data
//     let id = span.source_file().path();

//     {
//         let data = RwLockReadGuardRef::new(DYNASM_STORAGE.read().unwrap());

//         if data.get(&id).is_some() {
//             return data.map(|x| x.get(&id).unwrap());
//         }
//     }

//     {
//         let mut lock = DYNASM_STORAGE.write().unwrap();
//         lock.insert(id.clone(), Mutex::new(DynasmData::new()));
//     }
//     RwLockReadGuardRef::new(DYNASM_STORAGE.read().unwrap()).map(|x| x.get(&id).unwrap())
// }

// // this is where the actual storage resides.
// lazy_static! {
//     static ref DYNASM_STORAGE: RwLock<DynasmStorage> = RwLock::new(HashMap::new());
// }
<commit_msg>Properly document dynasm! and dynasm_backwards!<commit_after>#![cfg_attr(feature = "filelocal", feature(proc_macro_span))]

extern crate proc_macro;

use syn::parse;
use syn::{Token, parse_macro_input};
use proc_macro2::{TokenTree, TokenStream};
use quote::quote;
use proc_macro_error::proc_macro_error;

use std::collections::HashMap;

#[cfg(feature = "filelocal")]
use std::sync::{MutexGuard, Mutex};
#[cfg(feature = "filelocal")]
use std::path::PathBuf;
#[cfg(any(feature = "filelocal", feature = "dynasm_opmap", feature = "dynasm_extract"))]
use proc_macro2::Span;

/// Module with common infrastructure across assemblers
mod common;
/// Module with architecture-specific assembler implementations
mod arch;
/// Module contaning the implementation of directives
mod directive;
/// Module containing utility functions for creating TokenTrees from assembler / directive output
mod serialize;
/// Module containing utility functions for parsing
mod parse_helpers;

/// The whole point. This macro compiles given assembly/rust templates down to `DynasmApi` and `DynasmLabelApi`
/// compliant calls to an assembler.
#[proc_macro]
#[proc_macro_error]
pub fn dynasm(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
    // try parsing the tokenstream into a dynasm struct containing
    // an abstract representation of the statements to create
    let dynasm = parse_macro_input!(tokens as Dynasm);

    // serialize the resulting output into tokens
    serialize::serialize(&dynasm.target, dynasm.stmts).into()
}

/// Similar to `dynasm!`, but the calls to the assembler are executed in piecewise reversed order.
/// This is to allow the system to be used with assemblers that assemble backwards.
/// Currently this is not supported by the `dynasmrt` crate, but this allows experimentation with it
/// out of tree.
#[proc_macro]
#[proc_macro_error]
pub fn dynasm_backwards(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {
    // try parsing the tokenstream into a dynasm struct containing
    // an abstract representation of the statements to create
    let dynasm = parse_macro_input!(tokens as Dynasm);

    // reverse the statement stream
    let stmts = serialize::invert(dynasm.stmts);

    // serialize the resulting output into tokens
    serialize::serialize(&dynasm.target, stmts).into()
}

/// output from parsing a full dynasm invocation. target represents the first dynasm argument, being the assembler
/// variable being used. stmts contains an abstract representation of the statements to be generated from this dynasm
/// invocation.
struct Dynasm {
    target: TokenTree,
    stmts: Vec<common::Stmt>
}

/// top-level parsing. Handles common prefix symbols and diverts to the selected architecture
/// when an assembly instruction is encountered. When parsing fails an Err() is returned, when
/// non-parsing errors happen err() will be called, but this function returns Ok().
impl parse::Parse for Dynasm {
    fn parse(input: parse::ParseStream) -> parse::Result<Self> {

        // parse the assembler target declaration
        let target: syn::Expr = input.parse()?;
        // and just convert it back to a tokentree since that's how we'll always be using it.
        let target = common::delimited(target);

        // get file-local data (alias definitions, current architecture)
        let mut provider = ContextProvider::new();
        let invocation_context = provider.get_context_mut();

        // prepare the statement buffer
        let mut stmts = Vec::new();

        // if we're not at the end of the macro, we should be expecting a semicolon and a new directive/statement/label/op
        while !input.is_empty() {
            let _: Token![;] = input.parse()?;

            // ;; stmt
            if input.peek(Token![;]) {
                let _: Token![;] = input.parse()?;

                // collect all tokentrees till the next ;
                let mut buffer = TokenStream::new();
                while !(input.is_empty() || input.peek(Token![;])) {
                    buffer.extend(std::iter::once(input.parse::<TokenTree>()?));
                }
                // glue an extra ; on there
                buffer.extend(quote! { ; } );

                if !buffer.is_empty() {
                    // ensure that the statement is actually a proper statement and then emit it for serialization
                    let stmt: syn::Stmt = syn::parse2(buffer)?;
                    stmts.push(common::Stmt::Stmt(common::delimited(stmt)));
                }
                continue;
            }

            // ; -> label :
            if input.peek(Token![->]) {
                let _: Token![->] = input.parse()?;

                let name: syn::Ident = input.parse()?;
                let _: Token![:] = input.parse()?;

                stmts.push(common::Stmt::GlobalLabel(name));
                continue;
            }

            // ; => expr
            if input.peek(Token![=>]) {
                let _: Token![=>] = input.parse()?;

                let expr: syn::Expr = input.parse()?;

                stmts.push(common::Stmt::DynamicLabel(common::delimited(expr)));
                continue;
            }

            // ; label :
            if input.peek(syn::Ident) && input.peek2(Token![:]) {

                let name: syn::Ident = input.parse()?;
                let _: Token![:] = input.parse()?;

                stmts.push(common::Stmt::LocalLabel(name));
                continue;
            }

            // ; . directive
            if input.peek(Token![.]) {
                let _: Token![.] = input.parse()?;

                directive::evaluate_directive(invocation_context, &mut stmts, input)?;
            } else {
                // anything else is an assembly instruction which should be in current_arch

                let mut state = State {
                    stmts: &mut stmts,
                    target: &target,
                    invocation_context: &*invocation_context,
                };
                invocation_context.current_arch.compile_instruction(&mut state, input)?;
            }

        }

        Ok(Dynasm {
            target,
            stmts
        })
    }
}

/// This is only compiled when the dynasm_opmap feature is used. It exports the internal assembly listings
/// into a string that can then be included into the documentation for dynasm.
#[cfg(feature = "dynasm_opmap")]
#[proc_macro]
pub fn dynasm_opmap(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {

    // parse to ensure that no macro arguments were provided
    let opmap = parse_macro_input!(tokens as DynasmOpmap);

    let mut s = String::new();
    s.push_str("% Instruction Reference\n\n");

    s.push_str(&match opmap.arch.as_str() {
        "x64" | "x86" => arch::x64::create_opmap(),
        "aarch64" => arch::aarch64::create_opmap(),
        x => panic!("Unknown architecture {}", x)
    });

    let token = quote::quote_spanned! { Span::mixed_site()=>
        #s
    };
    token.into()
}

/// This is only compiled when the dynasm_extract feature is used. It exports the internal assembly listings
/// into a string that can then be included into the documentation for dynasm.
#[cfg(feature = "dynasm_extract")]
#[proc_macro]
pub fn dynasm_extract(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream {

    // parse to ensure that no macro arguments were provided
    let opmap = parse_macro_input!(tokens as DynasmOpmap);

    let s = match opmap.arch.as_str() {
        "x64" | "x86" => "UNIMPLEMENTED".into(),
        "aarch64" => arch::aarch64::extract_opmap(),
        x => panic!("Unknown architecture {}", x)
    };

    let token = quote::quote_spanned! { Span::mixed_site()=>
        #s
    };
    token.into()
}

/// As dynasm_opmap takes no args it doesn't parse to anything
struct DynasmOpmap {
    pub arch: String
}

/// As dynasm_opmap takes no args it doesn't parse to anything.
/// This just exists so syn will give an error when no args are present.
impl parse::Parse for DynasmOpmap {
    fn parse(input: parse::ParseStream) -> parse::Result<Self> {
        let arch: syn::Ident = input.parse()?;

        Ok(DynasmOpmap {
            arch: arch.to_string()
        })
    }
}

/// This struct contains all non-parsing state that dynasm! requires while parsing and compiling
struct State<'a> {
    pub stmts: &'a mut Vec<common::Stmt>,
    pub target: &'a TokenTree,
    pub invocation_context: &'a DynasmContext,
}

// File local data implementation.

// context inside of a dynasm invocation, manipulated by directives and such
struct DynasmContext {
    pub current_arch: Box<dyn arch::Arch>,
    pub aliases: HashMap<String, String>,
}

impl DynasmContext {
    fn new() -> DynasmContext {
        DynasmContext {
            current_arch: arch::from_str(arch::CURRENT_ARCH).expect("Invalid default architecture"),
            aliases: HashMap::new()
        }
    }
}

// Oneshot context provider
#[cfg(not(feature = "filelocal"))]
struct ContextProvider {
    context: DynasmContext
}

#[cfg(not(feature = "filelocal"))]
impl ContextProvider {
    pub fn new() -> ContextProvider {
        ContextProvider {
            context: DynasmContext::new()
        }
    }

    pub fn get_context_mut(&mut self) -> &mut DynasmContext {
        &mut self.context
    }
}

/// Filelocal context provider
#[cfg(feature = "filelocal")]
struct ContextProvider {
    guard: MutexGuard<'static, HashMap<PathBuf, DynasmContext>>
}

#[cfg(feature = "filelocal")]
impl ContextProvider {
    pub fn new() -> ContextProvider {
        ContextProvider {
            guard: CONTEXT_STORAGE.lock().unwrap()
        }
    }

    pub fn get_context_mut(&mut self) -> &mut DynasmContext {
        // get the file that generated this macro expansion
        let span = Span::call_site().unstable();

        // and use the file that that was at as scope for resolving dynasm data
        let id = span.source_file().path();

        self.guard.entry(id).or_insert_with(DynasmContext::new)
    }
}

#[cfg(feature = "filelocal")]
lazy_static::lazy_static! {
    static ref CONTEXT_STORAGE: Mutex<HashMap<PathBuf, DynasmContext>> = Mutex::new(HashMap::new());
}

// type DynasmStorage = HashMap<PathBuf, Mutex<DynasmData>>;

// struct DynasmData {
//     pub current_arch: Box<dyn arch::Arch>,
//     pub aliases: HashMap<String, String>,
// }

// impl DynasmData {
//     fn new() -> DynasmData {
//         DynasmData {
//             current_arch:
//                 arch::from_str(arch::CURRENT_ARCH).expect("Default architecture is invalid"),
//             aliases: HashMap::new(),
//         }
//     }
// }

// type FileLocalData = OwningRef<RwLockReadGuard<'static, DynasmStorage>, Mutex<DynasmData>>;

// fn file_local_data() -> FileLocalData {
//     // get the file that generated this macro expansion
//     let span = Span::call_site().unstable();

//     // and use the file that that was at as scope for resolving dynasm data
//     let id = span.source_file().path();

//     {
//         let data = RwLockReadGuardRef::new(DYNASM_STORAGE.read().unwrap());

//         if data.get(&id).is_some() {
//             return data.map(|x| x.get(&id).unwrap());
//         }
//     }

//     {
//         let mut lock = DYNASM_STORAGE.write().unwrap();
//         lock.insert(id.clone(), Mutex::new(DynasmData::new()));
//     }
//     RwLockReadGuardRef::new(DYNASM_STORAGE.read().unwrap()).map(|x| x.get(&id).unwrap())
// }

// // this is where the actual storage resides.
// lazy_static! {
//     static ref DYNASM_STORAGE: RwLock<DynasmStorage> = RwLock::new(HashMap::new());
// }
<|endoftext|>


<commit_before>use vec3::Vec3;
use ray::Ray;

pub struct Camera {
    pub position: Vec3,
    pub look_at: Vec3,
    pub up: Vec3,
    pub fov_deg: f64,
    pub image_width: int,
    pub image_height: int,

    pub eye: Vec3,
    pub right: Vec3,
    pub half_width: f64,
    pub half_height: f64,
    pub pixel_width: f64,
    pub pixel_height: f64
}

impl Camera {
    pub fn new(position: Vec3, look_at: Vec3, up: Vec3, fov_deg: f64, image_width: int, image_height: int) -> Camera {
        let mut camera = Camera {
            position: position,
            look_at: look_at,
            up: up,
            fov_deg: fov_deg,
            image_width: image_width,
            image_height: image_height,
            eye: Vec3 {x: 0.0, y: 0.0, z: 0.0},
            right: Vec3 {x: 0.0, y: 0.0, z: 0.0},
            half_width: 0.0,
            half_height: 0.0,
            pixel_width: 0.0,
            pixel_height: 0.0
        };

        camera.update_eye_vector();
        camera.update_internal_sizes();

        camera
    }

    pub fn get_ray(&self, x: int, y: int) -> Ray {
        Ray {
            origin: self.position,
            direction: self.eye +
                self.right.scale(x as f64 * self.pixel_width - self.half_width) +
                self.up.scale(y as f64 * self.pixel_height - self.half_height).unit()
        }
    }

    fn update_eye_vector(&mut self) -> () {
        self.eye = (self.look_at - self.position).unit();
        self.right = self.eye.cross(&self.up);
    }

    fn update_internal_sizes(&mut self) -> () {
        let fov_rad = self.fov_deg.to_radians();
        let ratio = self.image_height as f64 / self.image_width as f64;

        self.half_width  = fov_rad.tan();
        self.half_height = self.half_width * ratio;

        let camera_width  = self.half_width  * 2.0;
        let camera_height = self.half_height * 2.0;

        self.pixel_width  = camera_width  / (self.image_width  - 1) as f64;
        self.pixel_height = camera_height / (self.image_height - 1) as f64;
    }
}
<commit_msg>Fix bad camera rays.<commit_after>use vec3::Vec3;
use ray::Ray;

pub struct Camera {
    pub position: Vec3,
    pub look_at: Vec3,
    pub up: Vec3,
    pub fov_deg: f64,
    pub image_width: int,
    pub image_height: int,

    pub eye: Vec3,
    pub right: Vec3,
    pub half_width: f64,
    pub half_height: f64,
    pub pixel_width: f64,
    pub pixel_height: f64
}

impl Camera {
    pub fn new(position: Vec3, look_at: Vec3, up: Vec3, fov_deg: f64, image_width: int, image_height: int) -> Camera {
        let mut camera = Camera {
            position: position,
            look_at: look_at,
            up: up,
            fov_deg: fov_deg,
            image_width: image_width,
            image_height: image_height,
            eye: Vec3 {x: 0.0, y: 0.0, z: 0.0},
            right: Vec3 {x: 0.0, y: 0.0, z: 0.0},
            half_width: 0.0,
            half_height: 0.0,
            pixel_width: 0.0,
            pixel_height: 0.0
        };

        camera.update_eye_vector();
        camera.update_internal_sizes();

        camera
    }

    pub fn get_ray(&self, x: int, y: int) -> Ray {
        Ray {
            origin: self.position,
            direction: (self.eye +
                self.right.scale(x as f64 * self.pixel_width - self.half_width) +
                self.up.scale(y as f64 * self.pixel_height - self.half_height)).unit()
        }
    }

    fn update_eye_vector(&mut self) -> () {
        self.eye = (self.look_at - self.position).unit();
        self.right = self.eye.cross(&self.up);
    }

    fn update_internal_sizes(&mut self) -> () {
        let fov_rad = self.fov_deg.to_radians();
        let ratio = self.image_height as f64 / self.image_width as f64;

        self.half_width  = fov_rad.tan();
        self.half_height = self.half_width * ratio;

        let camera_width  = self.half_width  * 2.0;
        let camera_height = self.half_height * 2.0;

        self.pixel_width  = camera_width  / (self.image_width  - 1) as f64;
        self.pixel_height = camera_height / (self.image_height - 1) as f64;
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![experimental]

use registry::{Registry, Ns};
use std::io::IoResult;

#[allow(missing_copy_implementations)]
pub struct StaticStructGenerator;

impl super::Generator for StaticStructGenerator {
    fn write<W>(&self, registry: &Registry, ns: Ns, dest: &mut W) -> IoResult<()> where W: Writer {
        try!(write_header(dest));
        try!(write_type_aliases(&ns, dest));
        try!(write_enums(registry, dest));
        try!(write_struct(&ns, dest));
        try!(write_impl(registry, &ns, dest));
        try!(write_fns(registry, &ns, dest));
        Ok(())
    }
}

/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
///  bindings.
fn write_header<W>(dest: &mut W) -> IoResult<()> where W: Writer {
    writeln!(dest, r#"
        mod __gl_imports {{
            extern crate libc;
            pub use std::mem;
        }}
    "#)
}

/// Creates a `types` module which contains all the type aliases.
///
/// See also `generators::gen_type_aliases`.
fn write_type_aliases<W>(ns: &Ns, dest: &mut W) -> IoResult<()> where W: Writer {
    try!(writeln!(dest, r#"
        #[stable]
        pub mod types {{
            #![allow(non_camel_case_types)]
            #![allow(non_snake_case)]
            #![allow(dead_code)]
            #![allow(missing_copy_implementations)]
    "#));

    try!(super::gen_type_aliases(ns, dest));

    writeln!(dest, "
        }}
    ")
}

/// Creates all the `<enum>` elements at the root of the bindings.
fn write_enums<W>(registry: &Registry, dest: &mut W) -> IoResult<()> where W: Writer {
    for e in registry.enum_iter() {
        try!(super::gen_enum_item(e, "types::", dest));
    }

    Ok(())
}

/// Creates a stub structure.
///
/// The name of the struct corresponds to the namespace.
fn write_struct<W>(ns: &Ns, dest: &mut W) -> IoResult<()> where W: Writer {
    writeln!(dest, "
        #[allow(non_camel_case_types)]
        #[allow(non_snake_case)]
        #[allow(dead_code)]
        #[stable]
        pub struct {ns};
        ",

        ns = ns.fmt_struct_name(),
    )
}

/// Creates the `impl` of the structure created by `write_struct`.
fn write_impl<W>(registry: &Registry, ns: &Ns, dest: &mut W) -> IoResult<()> where W: Writer {
    writeln!(dest, "
        impl {ns} {{
            /// Stub function.
            #[unstable]
            #[allow(dead_code)]
            pub fn load_with(_loadfn: |symbol: &str| -> *const __gl_imports::libc::c_void) -> {ns} {{
                {ns}
            }}

            {modules}
        }}",

        ns = ns.fmt_struct_name(),

        modules = registry.cmd_iter().map(|c| {
            format!(
                "#[allow(non_snake_case)]
                // #[allow(unused_variables)]
                #[allow(dead_code)]
                #[inline]
                #[unstable]
                pub unsafe fn {name}(&self, {typed_params}) -> {return_suffix} {{
                    {name}({idents})
                }}",
                name = c.proto.ident,
                typed_params = super::gen_parameters(c, true, true).connect(", "),
                return_suffix = super::gen_return_type(c),
                idents = super::gen_parameters(c, true, false).connect(", "),
            )
        }).collect::<Vec<String>>().connect("\n")
    )
}

/// Writes all functions corresponding to the GL bindings.
///
/// These are foreign functions, they don't have any content.
fn write_fns<W>(registry: &Registry, ns: &Ns, dest: &mut W) -> IoResult<()> where W: Writer {
    let symbols = registry.cmd_iter().map(|c| {
        format!(
            "#[link_name=\"{symbol}\"]
            pub fn {name}({params}) -> {return_suffix};",
            symbol = super::gen_symbol_name(ns, c.proto.ident.as_slice()),
            name = c.proto.ident,
            params = super::gen_parameters(c, true, true).connect(", "),
            return_suffix = super::gen_return_type(c)
        )
    }).collect::<Vec<String>>().connect("\n");

    writeln!(dest, "
        #[allow(non_snake_case)]
        #[allow(unused_variables)]
        #[allow(dead_code)]
        extern \"system\" {{
            {}
        }}
    ", symbols)
}
<commit_msg>static_struct_gen: Made plain functions private<commit_after>// Copyright 2013-2014 The gl-rs developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![experimental]

use registry::{Registry, Ns};
use std::io::IoResult;

#[allow(missing_copy_implementations)]
pub struct StaticStructGenerator;

impl super::Generator for StaticStructGenerator {
    fn write<W>(&self, registry: &Registry, ns: Ns, dest: &mut W) -> IoResult<()> where W: Writer {
        try!(write_header(dest));
        try!(write_type_aliases(&ns, dest));
        try!(write_enums(registry, dest));
        try!(write_struct(&ns, dest));
        try!(write_impl(registry, &ns, dest));
        try!(write_fns(registry, &ns, dest));
        Ok(())
    }
}

/// Creates a `__gl_imports` module which contains all the external symbols that we need for the
///  bindings.
fn write_header<W>(dest: &mut W) -> IoResult<()> where W: Writer {
    writeln!(dest, r#"
        mod __gl_imports {{
            extern crate libc;
            pub use std::mem;
        }}
    "#)
}

/// Creates a `types` module which contains all the type aliases.
///
/// See also `generators::gen_type_aliases`.
fn write_type_aliases<W>(ns: &Ns, dest: &mut W) -> IoResult<()> where W: Writer {
    try!(writeln!(dest, r#"
        #[stable]
        pub mod types {{
            #![allow(non_camel_case_types)]
            #![allow(non_snake_case)]
            #![allow(dead_code)]
            #![allow(missing_copy_implementations)]
    "#));

    try!(super::gen_type_aliases(ns, dest));

    writeln!(dest, "
        }}
    ")
}

/// Creates all the `<enum>` elements at the root of the bindings.
fn write_enums<W>(registry: &Registry, dest: &mut W) -> IoResult<()> where W: Writer {
    for e in registry.enum_iter() {
        try!(super::gen_enum_item(e, "types::", dest));
    }

    Ok(())
}

/// Creates a stub structure.
///
/// The name of the struct corresponds to the namespace.
fn write_struct<W>(ns: &Ns, dest: &mut W) -> IoResult<()> where W: Writer {
    writeln!(dest, "
        #[allow(non_camel_case_types)]
        #[allow(non_snake_case)]
        #[allow(dead_code)]
        #[stable]
        pub struct {ns};
        ",

        ns = ns.fmt_struct_name(),
    )
}

/// Creates the `impl` of the structure created by `write_struct`.
fn write_impl<W>(registry: &Registry, ns: &Ns, dest: &mut W) -> IoResult<()> where W: Writer {
    writeln!(dest, "
        impl {ns} {{
            /// Stub function.
            #[unstable]
            #[allow(dead_code)]
            pub fn load_with(_loadfn: |symbol: &str| -> *const __gl_imports::libc::c_void) -> {ns} {{
                {ns}
            }}

            {modules}
        }}",

        ns = ns.fmt_struct_name(),

        modules = registry.cmd_iter().map(|c| {
            format!(
                "#[allow(non_snake_case)]
                // #[allow(unused_variables)]
                #[allow(dead_code)]
                #[inline]
                #[unstable]
                pub unsafe fn {name}(&self, {typed_params}) -> {return_suffix} {{
                    {name}({idents})
                }}",
                name = c.proto.ident,
                typed_params = super::gen_parameters(c, true, true).connect(", "),
                return_suffix = super::gen_return_type(c),
                idents = super::gen_parameters(c, true, false).connect(", "),
            )
        }).collect::<Vec<String>>().connect("\n")
    )
}

/// Writes all functions corresponding to the GL bindings.
///
/// These are foreign functions, they don't have any content.
fn write_fns<W>(registry: &Registry, ns: &Ns, dest: &mut W) -> IoResult<()> where W: Writer {
    let symbols = registry.cmd_iter().map(|c| {
        format!(
            "#[link_name=\"{symbol}\"]
            fn {name}({params}) -> {return_suffix};",
            symbol = super::gen_symbol_name(ns, c.proto.ident.as_slice()),
            name = c.proto.ident,
            params = super::gen_parameters(c, true, true).connect(", "),
            return_suffix = super::gen_return_type(c)
        )
    }).collect::<Vec<String>>().connect("\n");

    writeln!(dest, "
        #[allow(non_snake_case)]
        #[allow(unused_variables)]
        #[allow(dead_code)]
        extern \"system\" {{
            {}
        }}
    ", symbols)
}
<|endoftext|>