<commit_before>use super::*;
use crate::punctuated::Punctuated;

ast_struct! {
    /// An enum variant.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    pub struct Variant {
        /// Attributes tagged on the variant.
        pub attrs: Vec<Attribute>,

        /// Name of the variant.
        pub ident: Ident,

        /// Content stored in the variant.
        pub fields: Fields,

        /// Explicit discriminant: `Variant = 1`
        pub discriminant: Option<(Token![=], Expr)>,
    }
}

ast_enum_of_structs! {
    /// Data stored within an enum variant or struct.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    ///
    /// # Syntax tree enum
    ///
    /// This type is a [syntax tree enum].
    ///
    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
    //
    // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
    // blocked on https://github.com/rust-lang/rust/issues/62833
    pub enum Fields {
        /// Named fields of a struct or struct variant such as `Point { x: f64,
        /// y: f64 }`.
        Named(FieldsNamed),

        /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
        Unnamed(FieldsUnnamed),

        /// Unit struct or unit variant such as `None`.
        Unit,
    }
}

ast_struct! {
    /// Named fields of a struct or struct variant such as `Point { x: f64,
    /// y: f64 }`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct FieldsNamed {
        pub brace_token: token::Brace,
        pub named: Punctuated<Field, Token![,]>,
    }
}

ast_struct! {
    /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct FieldsUnnamed {
        pub paren_token: token::Paren,
        pub unnamed: Punctuated<Field, Token![,]>,
    }
}

impl Fields {
    /// Get an iterator over the borrowed [`Field`] items in this object. This
    /// iterator can be used to iterate over a named or unnamed struct or
    /// variant's fields uniformly.
    pub fn iter(&self) -> punctuated::Iter<Field> {
        match self {
            Fields::Unit => crate::punctuated::empty_punctuated_iter(),
            Fields::Named(f) => f.named.iter(),
            Fields::Unnamed(f) => f.unnamed.iter(),
        }
    }

    /// Get an iterator over the mutably borrowed [`Field`] items in this
    /// object. This iterator can be used to iterate over a named or unnamed
    /// struct or variant's fields uniformly.
    pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
        match self {
            Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
            Fields::Named(f) => f.named.iter_mut(),
            Fields::Unnamed(f) => f.unnamed.iter_mut(),
        }
    }

    /// Returns the number of fields.
    pub fn len(&self) -> usize {
        match self {
            Fields::Unit => 0,
            Fields::Named(f) => f.named.len(),
            Fields::Unnamed(f) => f.unnamed.len(),
        }
    }

    /// Returns `true` if there are zero fields.
    pub fn is_empty(&self) -> bool {
        match self {
            Fields::Unit => true,
            Fields::Named(f) => f.named.is_empty(),
            Fields::Unnamed(f) => f.unnamed.is_empty(),
        }
    }
}

impl IntoIterator for Fields {
    type Item = Field;
    type IntoIter = punctuated::IntoIter<Field>;

    fn into_iter(self) -> Self::IntoIter {
        match self {
            Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
            Fields::Named(f) => f.named.into_iter(),
            Fields::Unnamed(f) => f.unnamed.into_iter(),
        }
    }
}

impl<'a> IntoIterator for &'a Fields {
    type Item = &'a Field;
    type IntoIter = punctuated::Iter<'a, Field>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> IntoIterator for &'a mut Fields {
    type Item = &'a mut Field;
    type IntoIter = punctuated::IterMut<'a, Field>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

ast_struct! {
    /// A field of a struct or enum variant.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    pub struct Field {
        /// Attributes tagged on the field.
        pub attrs: Vec<Attribute>,

        /// Visibility of the field.
        pub vis: Visibility,

        /// Name of the field, if any.
        ///
        /// Fields of tuple structs have no names.
        pub ident: Option<Ident>,

        pub colon_token: Option<Token![:]>,

        /// Type of the field.
        pub ty: Type,
    }
}

ast_enum_of_structs! {
    /// The visibility level of an item: inherited or `pub` or
    /// `pub(restricted)`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    ///
    /// # Syntax tree enum
    ///
    /// This type is a [syntax tree enum].
    ///
    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
    //
    // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
    // blocked on https://github.com/rust-lang/rust/issues/62833
    pub enum Visibility {
        /// A public visibility level: `pub`.
        Public(VisPublic),

        /// A crate-level visibility: `crate`.
        Crate(VisCrate),

        /// A visibility level restricted to some path: `pub(self)` or
        /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
        Restricted(VisRestricted),

        /// An inherited visibility, which usually means private.
        Inherited,
    }
}

ast_struct! {
    /// A public visibility level: `pub`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct VisPublic {
        pub pub_token: Token![pub],
    }
}

ast_struct! {
    /// A crate-level visibility: `crate`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct VisCrate {
        pub crate_token: Token![crate],
    }
}

ast_struct! {
    /// A visibility level restricted to some path: `pub(self)` or
    /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct VisRestricted {
        pub pub_token: Token![pub],
        pub paren_token: token::Paren,
        pub in_token: Option<Token![in]>,
        pub path: Box<Path>,
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;

    use crate::ext::IdentExt;
    use crate::parse::discouraged::Speculative;
    use crate::parse::{Parse, ParseStream, Result};

    impl Parse for Variant {
        fn parse(input: ParseStream) -> Result<Self> {
            let attrs = input.call(Attribute::parse_outer)?;
            let _visibility: Visibility = input.parse()?;
            Ok(Variant {
                attrs,
                ident: input.parse()?,
                fields: {
                    if input.peek(token::Brace) {
                        Fields::Named(input.parse()?)
                    } else if input.peek(token::Paren) {
                        Fields::Unnamed(input.parse()?)
                    } else {
                        Fields::Unit
                    }
                },
                discriminant: {
                    if input.peek(Token![=]) {
                        let eq_token: Token![=] = input.parse()?;
                        let discriminant: Expr = input.parse()?;
                        Some((eq_token, discriminant))
                    } else {
                        None
                    }
                },
            })
        }
    }

    impl Parse for FieldsNamed {
        fn parse(input: ParseStream) -> Result<Self> {
            let content;
            Ok(FieldsNamed {
                brace_token: braced!(content in input),
                named: content.parse_terminated(Field::parse_named)?,
            })
        }
    }

    impl Parse for FieldsUnnamed {
        fn parse(input: ParseStream) -> Result<Self> {
            let content;
            Ok(FieldsUnnamed {
                paren_token: parenthesized!(content in input),
                unnamed: content.parse_terminated(Field::parse_unnamed)?,
            })
        }
    }

    impl Field {
        /// Parses a named (braced struct) field.
        pub fn parse_named(input: ParseStream) -> Result<Self> {
            Ok(Field {
                attrs: input.call(Attribute::parse_outer)?,
                vis: input.parse()?,
                ident: Some(input.parse()?),
                colon_token: Some(input.parse()?),
                ty: input.parse()?,
            })
        }

        /// Parses an unnamed (tuple struct) field.
        pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
            Ok(Field {
                attrs: input.call(Attribute::parse_outer)?,
                vis: input.parse()?,
                ident: None,
                colon_token: None,
                ty: input.parse()?,
            })
        }
    }

    impl Parse for Visibility {
        fn parse(input: ParseStream) -> Result<Self> {
            if input.peek(Token![pub]) {
                Self::parse_pub(input)
            } else if input.peek(Token![crate]) {
                Self::parse_crate(input)
            } else {
                Ok(Visibility::Inherited)
            }
        }
    }

    impl Visibility {
        fn parse_pub(input: ParseStream) -> Result<Self> {
            let pub_token = input.parse::<Token![pub]>()?;

            if input.peek(token::Paren) {
                let ahead = input.fork();

                let content;
                let paren_token = parenthesized!(content in ahead);
                if content.peek(Token![crate])
                    || content.peek(Token![self])
                    || content.peek(Token![super])
                {
                    let path = content.call(Ident::parse_any)?;

                    // Ensure there are no additional tokens within `content`.
                    // Without explicitly checking, we may misinterpret a tuple
                    // field as a restricted visibility, causing a parse error.
                    // e.g. `pub (crate::A, crate::B)` (Issue #720).
                    if content.is_empty() {
                        input.advance_to(&ahead);
                        return Ok(Visibility::Restricted(VisRestricted {
                            pub_token,
                            paren_token,
                            in_token: None,
                            path: Box::new(Path::from(path)),
                        }));
                    }
                } else if content.peek(Token![in]) {
                    let in_token: Token![in] = content.parse()?;
                    let path = content.call(Path::parse_mod_style)?;

                    input.advance_to(&ahead);
                    return Ok(Visibility::Restricted(VisRestricted {
                        pub_token,
                        paren_token,
                        in_token: Some(in_token),
                        path: Box::new(path),
                    }));
                }
            }

            Ok(Visibility::Public(VisPublic { pub_token }))
        }

        fn parse_crate(input: ParseStream) -> Result<Self> {
            if input.peek2(Token![::]) {
                Ok(Visibility::Inherited)
            } else {
                Ok(Visibility::Crate(VisCrate {
                    crate_token: input.parse()?,
                }))
            }
        }

        #[cfg(feature = "full")]
        pub(crate) fn is_some(&self) -> bool {
            match self {
                Visibility::Inherited => false,
                _ => true,
            }
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;

    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};

    use crate::print::TokensOrDefault;

    impl ToTokens for Variant {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.ident.to_tokens(tokens);
            self.fields.to_tokens(tokens);
            if let Some((eq_token, disc)) = &self.discriminant {
                eq_token.to_tokens(tokens);
                disc.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for FieldsNamed {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                self.named.to_tokens(tokens);
            });
        }
    }

    impl ToTokens for FieldsUnnamed {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.paren_token.surround(tokens, |tokens| {
                self.unnamed.to_tokens(tokens);
            });
        }
    }

    impl ToTokens for Field {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            if let Some(ident) = &self.ident {
                ident.to_tokens(tokens);
                TokensOrDefault(&self.colon_token).to_tokens(tokens);
            }
            self.ty.to_tokens(tokens);
        }
    }

    impl ToTokens for VisPublic {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.pub_token.to_tokens(tokens)
        }
    }

    impl ToTokens for VisCrate {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.crate_token.to_tokens(tokens);
        }
    }

    impl ToTokens for VisRestricted {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.pub_token.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                // TODO: If we have a path which is not "self" or "super" or
                // "crate", automatically add the "in" token.
                self.in_token.to_tokens(tokens);
                self.path.to_tokens(tokens);
            });
        }
    }
}
<commit_msg>Parse empty None-delimited group as inherited visibility<commit_after>use super::*;
use crate::punctuated::Punctuated;

ast_struct! {
    /// An enum variant.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    pub struct Variant {
        /// Attributes tagged on the variant.
        pub attrs: Vec<Attribute>,

        /// Name of the variant.
        pub ident: Ident,

        /// Content stored in the variant.
        pub fields: Fields,

        /// Explicit discriminant: `Variant = 1`
        pub discriminant: Option<(Token![=], Expr)>,
    }
}

ast_enum_of_structs! {
    /// Data stored within an enum variant or struct.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    ///
    /// # Syntax tree enum
    ///
    /// This type is a [syntax tree enum].
    ///
    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
    //
    // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
    // blocked on https://github.com/rust-lang/rust/issues/62833
    pub enum Fields {
        /// Named fields of a struct or struct variant such as `Point { x: f64,
        /// y: f64 }`.
        Named(FieldsNamed),

        /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
        Unnamed(FieldsUnnamed),

        /// Unit struct or unit variant such as `None`.
        Unit,
    }
}

ast_struct! {
    /// Named fields of a struct or struct variant such as `Point { x: f64,
    /// y: f64 }`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct FieldsNamed {
        pub brace_token: token::Brace,
        pub named: Punctuated<Field, Token![,]>,
    }
}

ast_struct! {
    /// Unnamed fields of a tuple struct or tuple variant such as `Some(T)`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct FieldsUnnamed {
        pub paren_token: token::Paren,
        pub unnamed: Punctuated<Field, Token![,]>,
    }
}

impl Fields {
    /// Get an iterator over the borrowed [`Field`] items in this object. This
    /// iterator can be used to iterate over a named or unnamed struct or
    /// variant's fields uniformly.
    pub fn iter(&self) -> punctuated::Iter<Field> {
        match self {
            Fields::Unit => crate::punctuated::empty_punctuated_iter(),
            Fields::Named(f) => f.named.iter(),
            Fields::Unnamed(f) => f.unnamed.iter(),
        }
    }

    /// Get an iterator over the mutably borrowed [`Field`] items in this
    /// object. This iterator can be used to iterate over a named or unnamed
    /// struct or variant's fields uniformly.
    pub fn iter_mut(&mut self) -> punctuated::IterMut<Field> {
        match self {
            Fields::Unit => crate::punctuated::empty_punctuated_iter_mut(),
            Fields::Named(f) => f.named.iter_mut(),
            Fields::Unnamed(f) => f.unnamed.iter_mut(),
        }
    }

    /// Returns the number of fields.
    pub fn len(&self) -> usize {
        match self {
            Fields::Unit => 0,
            Fields::Named(f) => f.named.len(),
            Fields::Unnamed(f) => f.unnamed.len(),
        }
    }

    /// Returns `true` if there are zero fields.
    pub fn is_empty(&self) -> bool {
        match self {
            Fields::Unit => true,
            Fields::Named(f) => f.named.is_empty(),
            Fields::Unnamed(f) => f.unnamed.is_empty(),
        }
    }
}

impl IntoIterator for Fields {
    type Item = Field;
    type IntoIter = punctuated::IntoIter<Field>;

    fn into_iter(self) -> Self::IntoIter {
        match self {
            Fields::Unit => Punctuated::<Field, ()>::new().into_iter(),
            Fields::Named(f) => f.named.into_iter(),
            Fields::Unnamed(f) => f.unnamed.into_iter(),
        }
    }
}

impl<'a> IntoIterator for &'a Fields {
    type Item = &'a Field;
    type IntoIter = punctuated::Iter<'a, Field>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> IntoIterator for &'a mut Fields {
    type Item = &'a mut Field;
    type IntoIter = punctuated::IterMut<'a, Field>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter_mut()
    }
}

ast_struct! {
    /// A field of a struct or enum variant.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    pub struct Field {
        /// Attributes tagged on the field.
        pub attrs: Vec<Attribute>,

        /// Visibility of the field.
        pub vis: Visibility,

        /// Name of the field, if any.
        ///
        /// Fields of tuple structs have no names.
        pub ident: Option<Ident>,

        pub colon_token: Option<Token![:]>,

        /// Type of the field.
        pub ty: Type,
    }
}

ast_enum_of_structs! {
    /// The visibility level of an item: inherited or `pub` or
    /// `pub(restricted)`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or `"full"`
    /// feature.*
    ///
    /// # Syntax tree enum
    ///
    /// This type is a [syntax tree enum].
    ///
    /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums
    //
    // TODO: change syntax-tree-enum link to an intra rustdoc link, currently
    // blocked on https://github.com/rust-lang/rust/issues/62833
    pub enum Visibility {
        /// A public visibility level: `pub`.
        Public(VisPublic),

        /// A crate-level visibility: `crate`.
        Crate(VisCrate),

        /// A visibility level restricted to some path: `pub(self)` or
        /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
        Restricted(VisRestricted),

        /// An inherited visibility, which usually means private.
        Inherited,
    }
}

ast_struct! {
    /// A public visibility level: `pub`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct VisPublic {
        pub pub_token: Token![pub],
    }
}

ast_struct! {
    /// A crate-level visibility: `crate`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct VisCrate {
        pub crate_token: Token![crate],
    }
}

ast_struct! {
    /// A visibility level restricted to some path: `pub(self)` or
    /// `pub(super)` or `pub(crate)` or `pub(in some::module)`.
    ///
    /// *This type is available only if Syn is built with the `"derive"` or
    /// `"full"` feature.*
    pub struct VisRestricted {
        pub pub_token: Token![pub],
        pub paren_token: token::Paren,
        pub in_token: Option<Token![in]>,
        pub path: Box<Path>,
    }
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;

    use crate::ext::IdentExt;
    use crate::parse::discouraged::Speculative;
    use crate::parse::{Parse, ParseStream, Result};

    impl Parse for Variant {
        fn parse(input: ParseStream) -> Result<Self> {
            let attrs = input.call(Attribute::parse_outer)?;
            let _visibility: Visibility = input.parse()?;
            Ok(Variant {
                attrs,
                ident: input.parse()?,
                fields: {
                    if input.peek(token::Brace) {
                        Fields::Named(input.parse()?)
                    } else if input.peek(token::Paren) {
                        Fields::Unnamed(input.parse()?)
                    } else {
                        Fields::Unit
                    }
                },
                discriminant: {
                    if input.peek(Token![=]) {
                        let eq_token: Token![=] = input.parse()?;
                        let discriminant: Expr = input.parse()?;
                        Some((eq_token, discriminant))
                    } else {
                        None
                    }
                },
            })
        }
    }

    impl Parse for FieldsNamed {
        fn parse(input: ParseStream) -> Result<Self> {
            let content;
            Ok(FieldsNamed {
                brace_token: braced!(content in input),
                named: content.parse_terminated(Field::parse_named)?,
            })
        }
    }

    impl Parse for FieldsUnnamed {
        fn parse(input: ParseStream) -> Result<Self> {
            let content;
            Ok(FieldsUnnamed {
                paren_token: parenthesized!(content in input),
                unnamed: content.parse_terminated(Field::parse_unnamed)?,
            })
        }
    }

    impl Field {
        /// Parses a named (braced struct) field.
        pub fn parse_named(input: ParseStream) -> Result<Self> {
            Ok(Field {
                attrs: input.call(Attribute::parse_outer)?,
                vis: input.parse()?,
                ident: Some(input.parse()?),
                colon_token: Some(input.parse()?),
                ty: input.parse()?,
            })
        }

        /// Parses an unnamed (tuple struct) field.
        pub fn parse_unnamed(input: ParseStream) -> Result<Self> {
            Ok(Field {
                attrs: input.call(Attribute::parse_outer)?,
                vis: input.parse()?,
                ident: None,
                colon_token: None,
                ty: input.parse()?,
            })
        }
    }

    impl Parse for Visibility {
        fn parse(input: ParseStream) -> Result<Self> {
            // Recognize an empty None-delimited group, as produced by a $:vis
            // matcher that matched no tokens.
            if input.peek(token::Group) {
                let ahead = input.fork();
                let group = crate::group::parse_group(&ahead)?;
                if group.content.is_empty() {
                    input.advance_to(&ahead);
                    return Ok(Visibility::Inherited);
                }
            }

            if input.peek(Token![pub]) {
                Self::parse_pub(input)
            } else if input.peek(Token![crate]) {
                Self::parse_crate(input)
            } else {
                Ok(Visibility::Inherited)
            }
        }
    }

    impl Visibility {
        fn parse_pub(input: ParseStream) -> Result<Self> {
            let pub_token = input.parse::<Token![pub]>()?;

            if input.peek(token::Paren) {
                let ahead = input.fork();

                let content;
                let paren_token = parenthesized!(content in ahead);
                if content.peek(Token![crate])
                    || content.peek(Token![self])
                    || content.peek(Token![super])
                {
                    let path = content.call(Ident::parse_any)?;

                    // Ensure there are no additional tokens within `content`.
                    // Without explicitly checking, we may misinterpret a tuple
                    // field as a restricted visibility, causing a parse error.
                    // e.g. `pub (crate::A, crate::B)` (Issue #720).
                    if content.is_empty() {
                        input.advance_to(&ahead);
                        return Ok(Visibility::Restricted(VisRestricted {
                            pub_token,
                            paren_token,
                            in_token: None,
                            path: Box::new(Path::from(path)),
                        }));
                    }
                } else if content.peek(Token![in]) {
                    let in_token: Token![in] = content.parse()?;
                    let path = content.call(Path::parse_mod_style)?;

                    input.advance_to(&ahead);
                    return Ok(Visibility::Restricted(VisRestricted {
                        pub_token,
                        paren_token,
                        in_token: Some(in_token),
                        path: Box::new(path),
                    }));
                }
            }

            Ok(Visibility::Public(VisPublic { pub_token }))
        }

        fn parse_crate(input: ParseStream) -> Result<Self> {
            if input.peek2(Token![::]) {
                Ok(Visibility::Inherited)
            } else {
                Ok(Visibility::Crate(VisCrate {
                    crate_token: input.parse()?,
                }))
            }
        }

        #[cfg(feature = "full")]
        pub(crate) fn is_some(&self) -> bool {
            match self {
                Visibility::Inherited => false,
                _ => true,
            }
        }
    }
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;

    use proc_macro2::TokenStream;
    use quote::{ToTokens, TokenStreamExt};

    use crate::print::TokensOrDefault;

    impl ToTokens for Variant {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.ident.to_tokens(tokens);
            self.fields.to_tokens(tokens);
            if let Some((eq_token, disc)) = &self.discriminant {
                eq_token.to_tokens(tokens);
                disc.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for FieldsNamed {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.brace_token.surround(tokens, |tokens| {
                self.named.to_tokens(tokens);
            });
        }
    }

    impl ToTokens for FieldsUnnamed {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.paren_token.surround(tokens, |tokens| {
                self.unnamed.to_tokens(tokens);
            });
        }
    }

    impl ToTokens for Field {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            tokens.append_all(&self.attrs);
            self.vis.to_tokens(tokens);
            if let Some(ident) = &self.ident {
                ident.to_tokens(tokens);
                TokensOrDefault(&self.colon_token).to_tokens(tokens);
            }
            self.ty.to_tokens(tokens);
        }
    }

    impl ToTokens for VisPublic {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.pub_token.to_tokens(tokens)
        }
    }

    impl ToTokens for VisCrate {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.crate_token.to_tokens(tokens);
        }
    }

    impl ToTokens for VisRestricted {
        fn to_tokens(&self, tokens: &mut TokenStream) {
            self.pub_token.to_tokens(tokens);
            self.paren_token.surround(tokens, |tokens| {
                // TODO: If we have a path which is not "self" or "super" or
                // "crate", automatically add the "in" token.
                self.in_token.to_tokens(tokens);
                self.path.to_tokens(tokens);
            });
        }
    }
}
<|endoftext|>


<commit_before>//! Miscellaneous utilities.

use std::cell::Cell;
use std::num::Wrapping;
use std::process;
use std::sync::atomic;
use std::thread;
use std::time::Duration;

use rand;

/// A counter that performs exponential backoff in spin loops.
pub struct Backoff(u32);

impl Backoff {
    /// Creates a new `Backoff`.
    #[inline]
    pub fn new() -> Self {
        Backoff(0)
    }

    /// Backs off in a spin loop.
    ///
    /// This method may yield the current processor. Use it in lock-free retry loops.
    #[inline]
    pub fn spin(&mut self) {
        for _ in 0..1 << self.0.min(6) {
            atomic::spin_loop_hint();
        }
        self.0 = self.0.wrapping_add(1);
    }

    /// Backs off in a wait loop.
    ///
    /// This method may yield the current processor or the current thread. Use it when waiting on a
    /// resource.
    #[inline]
    pub fn snooze(&mut self) -> bool {
        if self.0 <= 6 {
            for _ in 0..1 << self.0 {
                atomic::spin_loop_hint();
            }
        } else {
            thread::yield_now();
        }

        self.0 = self.0.wrapping_add(1);
        self.0 <= 10
    }
}

/// Once dropped, aborts with an error message.
///
/// This guard is used for protection from unrecoverable panics.
pub struct AbortGuard(pub &'static str);

impl Drop for AbortGuard {
    fn drop(&mut self) {
        eprintln!(
            "{}, {}:{}:{}",
            self.0,
            file!(),
            line!(),
            column!(),
        );
        process::abort();
    }
}

/// Shuffles a slice randomly.
pub fn shuffle<T>(v: &mut [T]) {
    let len = v.len();
    if len <= 1 {
        return;
    }

    thread_local! {
        static RNG: Cell<Wrapping<u32>> = {
            let init = rand::random::<u32>() | 1;
            Cell::new(Wrapping(init))
        }
    }

    let _ = RNG.try_with(|rng| {
        for i in 1..len {
            // This is the 32-bit variant of Xorshift.
            // https://en.wikipedia.org/wiki/Xorshift
            let mut x = rng.get();
            x ^= x << 13;
            x ^= x >> 17;
            x ^= x << 5;
            rng.set(x);

            let x = x.0;
            let n = i + 1;

            // This is a fast alternative to `let j = x % n`.
            // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
            let j = ((x as u64).wrapping_mul(n as u64) >> 32) as u32 as usize;

            v.swap(i, j);
        }
    });
}

/// Blocks the current thread forever.
pub fn sleep_forever() -> ! {
    loop {
        thread::sleep(Duration::from_secs(1000));
    }
}
<commit_msg>Expand a comment<commit_after>//! Miscellaneous utilities.

use std::cell::Cell;
use std::num::Wrapping;
use std::process;
use std::sync::atomic;
use std::thread;
use std::time::Duration;

use rand;

/// A counter that performs exponential backoff in spin loops.
pub struct Backoff(u32);

impl Backoff {
    /// Creates a new `Backoff`.
    #[inline]
    pub fn new() -> Self {
        Backoff(0)
    }

    /// Backs off in a spin loop.
    ///
    /// This method may yield the current processor. Use it in lock-free retry loops.
    #[inline]
    pub fn spin(&mut self) {
        for _ in 0..1 << self.0.min(6) {
            atomic::spin_loop_hint();
        }
        self.0 = self.0.wrapping_add(1);
    }

    /// Backs off in a wait loop.
    ///
    /// Returns `true` if snoozing has reached a threshold where we should consider parking the
    /// thread instead.
    ///
    /// This method may yield the current processor or the current thread. Use it when waiting on a
    /// resource.
    #[inline]
    pub fn snooze(&mut self) -> bool {
        if self.0 <= 6 {
            for _ in 0..1 << self.0 {
                atomic::spin_loop_hint();
            }
        } else {
            thread::yield_now();
        }

        self.0 = self.0.wrapping_add(1);
        self.0 <= 10
    }
}

/// Once dropped, aborts with an error message.
///
/// This guard is used for protection from unrecoverable panics.
pub struct AbortGuard(pub &'static str);

impl Drop for AbortGuard {
    fn drop(&mut self) {
        eprintln!(
            "{}, {}:{}:{}",
            self.0,
            file!(),
            line!(),
            column!(),
        );
        process::abort();
    }
}

/// Shuffles a slice randomly.
pub fn shuffle<T>(v: &mut [T]) {
    let len = v.len();
    if len <= 1 {
        return;
    }

    thread_local! {
        static RNG: Cell<Wrapping<u32>> = {
            let init = rand::random::<u32>() | 1;
            Cell::new(Wrapping(init))
        }
    }

    let _ = RNG.try_with(|rng| {
        for i in 1..len {
            // This is the 32-bit variant of Xorshift.
            // https://en.wikipedia.org/wiki/Xorshift
            let mut x = rng.get();
            x ^= x << 13;
            x ^= x >> 17;
            x ^= x << 5;
            rng.set(x);

            let x = x.0;
            let n = i + 1;

            // This is a fast alternative to `let j = x % n`.
            // https://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
            let j = ((x as u64).wrapping_mul(n as u64) >> 32) as u32 as usize;

            v.swap(i, j);
        }
    });
}

/// Blocks the current thread forever.
pub fn sleep_forever() -> ! {
    loop {
        thread::sleep(Duration::from_secs(1000));
    }
}
<|endoftext|>


<commit_before>#![crate_type="dylib"]
#![feature(plugin_registrar)]
#![feature(rustc_private, core)]
#![deny(warnings)]
#![allow(unused_features)]

extern crate syntax;
extern crate rustc;
extern crate glassful;

use syntax::ast;
use syntax::parse::token;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacEager, MacResult, DummyResult};
use syntax::ext::build::AstBuilder;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("glassful", expand);
}

fn expand(cx: &mut ExtCtxt, outer_span: Span, toks: &[ast::TokenTree])
    -> Box<MacResult + 'static>
{
    let inner_span = match toks {
        [] => {
            cx.span_err(outer_span, "empty invocation");
            return DummyResult::expr(outer_span);
        }
        [ref first, ..] => {
            let first = first.get_span();
            let last = toks.iter().rev().next().unwrap().get_span();
            if first.expn_id != last.expn_id {
                cx.span_err(first, "invocation is split between expansion contexts??");
                cx.span_note(last, "last token is here");
                return DummyResult::expr(outer_span);
            }

            Span {
                lo: first.lo,
                hi: last.hi,
                expn_id: first.expn_id,
            }
        }
    };

    let src = match cx.codemap().span_to_snippet(inner_span) {
        Err(e) => {
            cx.span_err(inner_span, &format!("can't extract source snippet: {:?}", e)[..]);
            return DummyResult::expr(inner_span);
        }
        Ok(src) => src,
    };

    match glassful::try_translate(src) {
        None => {
            cx.span_err(outer_span, "translation failed");
            DummyResult::expr(outer_span)
        }
        Some(res) => {
            let interned = token::intern_and_get_ident(&res[..]);
            MacEager::expr(cx.expr_str(inner_span, interned))
        }
    }
}
<commit_msg>Add slice_patterns attribute to macros library<commit_after>#![crate_type="dylib"]
#![feature(plugin_registrar, slice_patterns)]
#![feature(rustc_private, core)]
#![deny(warnings)]
#![allow(unused_features)]

extern crate syntax;
extern crate rustc;
extern crate glassful;

use syntax::ast;
use syntax::parse::token;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacEager, MacResult, DummyResult};
use syntax::ext::build::AstBuilder;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("glassful", expand);
}

fn expand(cx: &mut ExtCtxt, outer_span: Span, toks: &[ast::TokenTree])
    -> Box<MacResult + 'static>
{
    let inner_span = match toks {
        [] => {
            cx.span_err(outer_span, "empty invocation");
            return DummyResult::expr(outer_span);
        }
        [ref first, ..] => {
            let first = first.get_span();
            let last = toks.iter().rev().next().unwrap().get_span();
            if first.expn_id != last.expn_id {
                cx.span_err(first, "invocation is split between expansion contexts??");
                cx.span_note(last, "last token is here");
                return DummyResult::expr(outer_span);
            }

            Span {
                lo: first.lo,
                hi: last.hi,
                expn_id: first.expn_id,
            }
        }
    };

    let src = match cx.codemap().span_to_snippet(inner_span) {
        Err(e) => {
            cx.span_err(inner_span, &format!("can't extract source snippet: {:?}", e)[..]);
            return DummyResult::expr(inner_span);
        }
        Ok(src) => src,
    };

    match glassful::try_translate(src) {
        None => {
            cx.span_err(outer_span, "translation failed");
            DummyResult::expr(outer_span)
        }
        Some(res) => {
            let interned = token::intern_and_get_ident(&res[..]);
            MacEager::expr(cx.expr_str(inner_span, interned))
        }
    }
}
<|endoftext|>


<commit_before>use std::convert::TryFrom;

use log::trace;
use nom::{
    branch::permutation,
    bytes::streaming::take,
    combinator::{complete, flat_map, map, map_parser, opt, verify},
    number::streaming::{be_f32, be_f64},
    sequence::{pair, preceded},
    Err, IResult, Needed, Parser,
};

/*
struct Document {
    header: Header,
    body: Vec<Element>,
}

struct Header {}

#[derive(Debug)]
enum ElementData {
    Signed(i64),
    Unsigned(u64),
    Float(f64),
    PlainString(String),
    UTF8String(String),
    Date(u64),
    Master(Vec<Element>),
    Binary(Vec<u8>),
    Unknown(u64),
}

#[derive(Debug)]
pub struct Element {
    id: u64,
    size: u64,
    data: ElementData,
}
*/

#[derive(Debug, PartialEq)]
pub struct Error<'a> {
    input: &'a [u8],
    kind: ErrorKind,
}

#[derive(Debug, PartialEq)]
pub enum ErrorKind {
    Nom(nom::error::ErrorKind),
    Custom(u8),
}

impl<'a> nom::error::ParseError<&'a [u8]> for Error<'a> {
    fn from_error_kind(input: &'a [u8], kind: nom::error::ErrorKind) -> Self {
        Error {
            input,
            kind: ErrorKind::Nom(kind),
        }
    }

    fn append(_input: &'a [u8], _kind: nom::error::ErrorKind, other: Self) -> Self {
        other
    }
}

pub fn custom_error(input: &[u8], code: u8) -> Error {
    Error {
        input,
        kind: ErrorKind::Custom(code),
    }
}

pub(crate) fn usize_error(input: &[u8], size: u64) -> Result<usize, nom::Err<Error>> {
    usize::try_from(size).map_err(|_| {
        log::error!("Not possible to convert size into usize");
        nom::Err::Error(custom_error(input, 0))
    })
}

pub fn vint(input: &[u8]) -> IResult<&[u8], u64, Error> {
    if input.is_empty() {
        return Err(Err::Incomplete(Needed::new(1)));
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return Err(Err::Error(custom_error(input, 100)));
    }

    if input.len() <= len as usize {
        return Err(Err::Incomplete(Needed::new(1)));
    }

    let mut val = u64::from(v ^ (1 << (7 - len)));

    trace!(
        "vint {:08b} {:08b} {:08b} {}",
        val,
        v,
        (1 << (8 - len)),
        len
    );

    for i in 0..len as usize {
        val = (val << 8) | u64::from(input[i + 1]);
    }

    trace!("     result {:08x}", val);

    Ok((&input[len as usize + 1..], val))
}

// The ID are represented in the specification as their binary representation
// do not drop the marker bit.
pub fn vid(input: &[u8]) -> IResult<&[u8], u64, Error> {
    if input.is_empty() {
        return Err(Err::Incomplete(Needed::new(1)));
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return Err(Err::Error(custom_error(input, 100)));
    }

    if input.len() <= len as usize {
        return Err(Err::Incomplete(Needed::new(1)));
    }

    let mut val = u64::from(v);

    trace!("vid {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | u64::from(input[i + 1]);
    }

    trace!("     result {:08x}", val);

    Ok((&input[len as usize + 1..], val))
}

pub fn parse_uint_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], u64, Error> {
    move |input| {
        let mut val = 0;

        if size > 8 {
            return Err(Err::Error(custom_error(input, 102)));
        }

        for i in input.iter().take(size as usize) {
            val = (val << 8) | u64::from(*i);
        }

        Ok((&input[size as usize..], val))
    }
}

pub fn parse_int_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], i64, Error> {
    move |input| {
        let mut val = 0;

        if size > 8 {
            return Err(Err::Error(custom_error(input, 103)));
        }

        for i in input.iter().take(size as usize) {
            val = (val << 8) | u64::from(*i);
        }

        Ok((&input[size as usize..], val as i64))
    }
}

pub fn parse_str_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], String, Error> {
    move |input| {
        map(take(usize_error(input, size)?), |data: &[u8]| {
            String::from_utf8(data.to_owned()).unwrap_or_default()
        })(input)
    }
}

pub fn parse_binary_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], Vec<u8>, Error> {
    move |input| {
        map(take(usize_error(input, size)?), |data: &[u8]| {
            data.to_owned()
        })(input)
    }
}

//FIXME: handle default values
//FIXME: is that really following IEEE_754-1985 ?
pub fn parse_float_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], f64, Error> {
    move |input| {
        if size == 0 {
            Ok((input, 0f64))
        } else if size == 4 {
            map(map_parser(take(4usize), be_f32), f64::from)(input)
        } else if size == 8 {
            map_parser(take(8usize), be_f64)(input)
        } else {
            Err(Err::Error(custom_error(input, 104)))
        }
    }
}

fn compute_ebml_type<'a, G, H, O1>(
    id: u64,
    second: G,
) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O1, Error>
where
    G: Fn(u64) -> H,
    H: Parser<&'a [u8], O1, Error<'a>>,
{
    move |i| {
        flat_map(pair(verify(vid, |val| *val == id), vint), |(_, size)| {
            second(size)
        })(i)
    }
}

pub fn ebml_uint<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], u64, Error> {
    compute_ebml_type(id, parse_uint_data)
}

pub fn ebml_int<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], i64, Error> {
    compute_ebml_type(id, parse_int_data)
}

pub fn ebml_float<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], f64, Error> {
    compute_ebml_type(id, parse_float_data)
}

pub fn ebml_str<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], String, Error> {
    compute_ebml_type(id, parse_str_data)
}

pub fn ebml_binary<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Vec<u8>, Error> {
    compute_ebml_type(id, parse_binary_data)
}

pub fn ebml_binary_ref(id: u64) -> impl Fn(&[u8]) -> IResult<&[u8], &[u8], Error> {
    move |i| {
        pair(verify(vid, |val| *val == id), vint)(i)
            .and_then(|(i, (_, size))| take(usize_error(i, size)?)(i))
    }
}

pub fn ebml_master<'a, G, O1>(
    id: u64,
    second: G,
) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O1, Error>
where
    G: Fn(&'a [u8]) -> IResult<&'a [u8], O1, Error> + Copy,
{
    move |i| {
        pair(verify(vid, |val| *val == id), vint)(i)
            .and_then(|(i, (_, size))| map_parser(take(usize_error(i, size)?), second)(i))
    }
}

pub fn eat_void<'a, G, O1>(second: G) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O1, Error<'a>>
where
    G: Parser<&'a [u8], O1, Error<'a>> + Copy,
{
    move |i| preceded(opt(skip_void), second)(i)
}

pub fn skip_void(input: &[u8]) -> IResult<&[u8], &[u8], Error> {
    pair(verify(vid, |val| *val == 0xEC), vint)(input)
        .and_then(|(i, (_, size))| take(usize_error(input, size)?)(i))
}

#[derive(Debug, Clone, PartialEq)]
pub struct EBMLHeader {
    pub version: u64,
    pub read_version: u64,
    pub max_id_length: u64,
    pub max_size_length: u64,
    pub doc_type: String,
    pub doc_type_version: u64,
    pub doc_type_read_version: u64,
}

pub fn ebml_header(input: &[u8]) -> IResult<&[u8], EBMLHeader, Error> {
    ebml_master(0x1A45DFA3, |i| {
        map(
            permutation((
                ebml_uint(0x4286), // version
                ebml_uint(0x42F7), // read_version
                ebml_uint(0x42F2), // max id length
                ebml_uint(0x42F3), // max size length
                ebml_str(0x4282),  // doctype
                ebml_uint(0x4287), // doctype version
                ebml_uint(0x4285), // doctype_read version
                opt(complete(skip_void)),
            )),
            |t| EBMLHeader {
                version: t.0,
                read_version: t.1,
                max_id_length: t.2,
                max_size_length: t.3,
                doc_type: t.4,
                doc_type_version: t.5,
                doc_type_read_version: t.6,
            },
        )(i)
    })(input)
}

#[cfg(test)]
#[allow(non_upper_case_globals)]
mod tests {
    use super::*;
    use log::trace;
    use nom::{HexDisplay, Offset};

    const single_stream: &'static [u8] = include_bytes!("../assets/single_stream.mkv");
    const webm: &'static [u8] = include_bytes!("../assets/big-buck-bunny_trailer.webm");

    #[test]
    fn variable_integer() {
        let val01 = [0b10000000];
        //        let val01 = [0b01000000, 0b1];

        match vint(&val01) {
            Ok((_, v)) => assert!(0 == v),
            _ => panic!(),
        }
    }

    /*
    #[test]
    fn header() {
        trace!("{}", single_stream[..8].to_hex(8));
        trace!("{:b} {:b}", single_stream[0], single_stream[1]);
        trace!("{:#?}", parse_element(single_stream));
        panic!();
    }*/

    #[test]
    fn mkv_header() {
        trace!("{}", single_stream[..8].to_hex(8));
        trace!("{:b} {:b}", single_stream[0], single_stream[1]);
        trace!("{:?}", ebml_header(&single_stream[..100]).unwrap());
    }

    #[test]
    fn webm_header() {
        trace!("{}", webm[..8].to_hex(8));
        let res = ebml_header(&webm[..100]);
        trace!("{:?}", res);

        if let Ok((i, _)) = res {
            trace!("offset: {} bytes", webm.offset(i));
        } else {
            panic!();
        }
    }
}
<commit_msg>Return an error instead of unwrapping<commit_after>use std::convert::TryFrom;

use log::trace;
use nom::{
    branch::permutation,
    bytes::streaming::take,
    combinator::{complete, flat_map, map, map_parser, opt, verify},
    number::streaming::{be_f32, be_f64},
    sequence::{pair, preceded},
    Err, IResult, Needed, Parser,
};

/*
struct Document {
    header: Header,
    body: Vec<Element>,
}

struct Header {}

#[derive(Debug)]
enum ElementData {
    Signed(i64),
    Unsigned(u64),
    Float(f64),
    PlainString(String),
    UTF8String(String),
    Date(u64),
    Master(Vec<Element>),
    Binary(Vec<u8>),
    Unknown(u64),
}

#[derive(Debug)]
pub struct Element {
    id: u64,
    size: u64,
    data: ElementData,
}
*/

#[derive(Debug, PartialEq)]
pub struct Error<'a> {
    input: &'a [u8],
    kind: ErrorKind,
}

#[derive(Debug, PartialEq)]
pub enum ErrorKind {
    Nom(nom::error::ErrorKind),
    Custom(u8),
}

impl<'a> nom::error::ParseError<&'a [u8]> for Error<'a> {
    fn from_error_kind(input: &'a [u8], kind: nom::error::ErrorKind) -> Self {
        Error {
            input,
            kind: ErrorKind::Nom(kind),
        }
    }

    fn append(_input: &'a [u8], _kind: nom::error::ErrorKind, other: Self) -> Self {
        other
    }
}

pub fn custom_error(input: &[u8], code: u8) -> Error {
    Error {
        input,
        kind: ErrorKind::Custom(code),
    }
}

pub(crate) fn usize_error(input: &[u8], size: u64) -> Result<usize, nom::Err<Error>> {
    usize::try_from(size).map_err(|_| {
        log::error!("Not possible to convert size into usize");
        nom::Err::Error(custom_error(input, 0))
    })
}

pub fn vint(input: &[u8]) -> IResult<&[u8], u64, Error> {
    if input.is_empty() {
        return Err(Err::Incomplete(Needed::new(1)));
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return Err(Err::Error(custom_error(input, 100)));
    }

    if input.len() <= len as usize {
        return Err(Err::Incomplete(Needed::new(1)));
    }

    let mut val = u64::from(v ^ (1 << (7 - len)));

    trace!(
        "vint {:08b} {:08b} {:08b} {}",
        val,
        v,
        (1 << (8 - len)),
        len
    );

    for i in 0..len as usize {
        val = (val << 8) | u64::from(input[i + 1]);
    }

    trace!("     result {:08x}", val);

    Ok((&input[len as usize + 1..], val))
}

// The ID are represented in the specification as their binary representation
// do not drop the marker bit.
pub fn vid(input: &[u8]) -> IResult<&[u8], u64, Error> {
    if input.is_empty() {
        return Err(Err::Incomplete(Needed::new(1)));
    }

    let v = input[0];
    let len = v.leading_zeros();

    if len == 8 {
        return Err(Err::Error(custom_error(input, 100)));
    }

    if input.len() <= len as usize {
        return Err(Err::Incomplete(Needed::new(1)));
    }

    let mut val = u64::from(v);

    trace!("vid {:08b} {:08b} {:08b} {}", val, v, (1 << (8 - len)), len);

    for i in 0..len as usize {
        val = (val << 8) | u64::from(input[i + 1]);
    }

    trace!("     result {:08x}", val);

    Ok((&input[len as usize + 1..], val))
}

pub fn parse_uint_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], u64, Error> {
    move |input| {
        let mut val = 0;

        if size > 8 {
            return Err(Err::Error(custom_error(input, 102)));
        }

        for i in input.iter().take(size as usize) {
            val = (val << 8) | u64::from(*i);
        }

        Ok((&input[size as usize..], val))
    }
}

pub fn parse_int_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], i64, Error> {
    move |input| {
        let mut val = 0;

        if size > 8 {
            return Err(Err::Error(custom_error(input, 103)));
        }

        for i in input.iter().take(size as usize) {
            val = (val << 8) | u64::from(*i);
        }

        Ok((&input[size as usize..], val as i64))
    }
}

pub fn parse_str_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], String, Error> {
    move |input| {
        take(usize_error(input, size)?)(input).and_then(|(i, data)| {
            match String::from_utf8(data.to_owned()) {
                Ok(s) => Ok((i, s)),
                Err(_) => return Err(Err::Error(custom_error(i, 104))),
            }
        })
    }
}

pub fn parse_binary_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], Vec<u8>, Error> {
    move |input| {
        map(take(usize_error(input, size)?), |data: &[u8]| {
            data.to_owned()
        })(input)
    }
}

//FIXME: handle default values
//FIXME: is that really following IEEE_754-1985 ?
pub fn parse_float_data(size: u64) -> impl Fn(&[u8]) -> IResult<&[u8], f64, Error> {
    move |input| {
        if size == 0 {
            Ok((input, 0f64))
        } else if size == 4 {
            map(map_parser(take(4usize), be_f32), f64::from)(input)
        } else if size == 8 {
            map_parser(take(8usize), be_f64)(input)
        } else {
            Err(Err::Error(custom_error(input, 104)))
        }
    }
}

fn compute_ebml_type<'a, G, H, O1>(
    id: u64,
    second: G,
) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O1, Error>
where
    G: Fn(u64) -> H,
    H: Parser<&'a [u8], O1, Error<'a>>,
{
    move |i| {
        flat_map(pair(verify(vid, |val| *val == id), vint), |(_, size)| {
            second(size)
        })(i)
    }
}

pub fn ebml_uint<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], u64, Error> {
    compute_ebml_type(id, parse_uint_data)
}

pub fn ebml_int<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], i64, Error> {
    compute_ebml_type(id, parse_int_data)
}

pub fn ebml_float<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], f64, Error> {
    compute_ebml_type(id, parse_float_data)
}

pub fn ebml_str<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], String, Error> {
    compute_ebml_type(id, parse_str_data)
}

pub fn ebml_binary<'a>(id: u64) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], Vec<u8>, Error> {
    compute_ebml_type(id, parse_binary_data)
}

pub fn ebml_binary_ref(id: u64) -> impl Fn(&[u8]) -> IResult<&[u8], &[u8], Error> {
    move |i| {
        pair(verify(vid, |val| *val == id), vint)(i)
            .and_then(|(i, (_, size))| take(usize_error(i, size)?)(i))
    }
}

pub fn ebml_master<'a, G, O1>(
    id: u64,
    second: G,
) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O1, Error>
where
    G: Fn(&'a [u8]) -> IResult<&'a [u8], O1, Error> + Copy,
{
    move |i| {
        pair(verify(vid, |val| *val == id), vint)(i)
            .and_then(|(i, (_, size))| map_parser(take(usize_error(i, size)?), second)(i))
    }
}

pub fn eat_void<'a, G, O1>(second: G) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O1, Error<'a>>
where
    G: Parser<&'a [u8], O1, Error<'a>> + Copy,
{
    move |i| preceded(opt(skip_void), second)(i)
}

pub fn skip_void(input: &[u8]) -> IResult<&[u8], &[u8], Error> {
    pair(verify(vid, |val| *val == 0xEC), vint)(input)
        .and_then(|(i, (_, size))| take(usize_error(input, size)?)(i))
}

#[derive(Debug, Clone, PartialEq)]
pub struct EBMLHeader {
    pub version: u64,
    pub read_version: u64,
    pub max_id_length: u64,
    pub max_size_length: u64,
    pub doc_type: String,
    pub doc_type_version: u64,
    pub doc_type_read_version: u64,
}

pub fn ebml_header(input: &[u8]) -> IResult<&[u8], EBMLHeader, Error> {
    ebml_master(0x1A45DFA3, |i| {
        map(
            permutation((
                ebml_uint(0x4286), // version
                ebml_uint(0x42F7), // read_version
                ebml_uint(0x42F2), // max id length
                ebml_uint(0x42F3), // max size length
                ebml_str(0x4282),  // doctype
                ebml_uint(0x4287), // doctype version
                ebml_uint(0x4285), // doctype_read version
                opt(complete(skip_void)),
            )),
            |t| EBMLHeader {
                version: t.0,
                read_version: t.1,
                max_id_length: t.2,
                max_size_length: t.3,
                doc_type: t.4,
                doc_type_version: t.5,
                doc_type_read_version: t.6,
            },
        )(i)
    })(input)
}

#[cfg(test)]
#[allow(non_upper_case_globals)]
mod tests {
    use super::*;
    use log::trace;
    use nom::{HexDisplay, Offset};

    const single_stream: &'static [u8] = include_bytes!("../assets/single_stream.mkv");
    const webm: &'static [u8] = include_bytes!("../assets/big-buck-bunny_trailer.webm");

    #[test]
    fn variable_integer() {
        let val01 = [0b10000000];
        //        let val01 = [0b01000000, 0b1];

        match vint(&val01) {
            Ok((_, v)) => assert!(0 == v),
            _ => panic!(),
        }
    }

    /*
    #[test]
    fn header() {
        trace!("{}", single_stream[..8].to_hex(8));
        trace!("{:b} {:b}", single_stream[0], single_stream[1]);
        trace!("{:#?}", parse_element(single_stream));
        panic!();
    }*/

    #[test]
    fn mkv_header() {
        trace!("{}", single_stream[..8].to_hex(8));
        trace!("{:b} {:b}", single_stream[0], single_stream[1]);
        trace!("{:?}", ebml_header(&single_stream[..100]).unwrap());
    }

    #[test]
    fn webm_header() {
        trace!("{}", webm[..8].to_hex(8));
        let res = ebml_header(&webm[..100]);
        trace!("{:?}", res);

        if let Ok((i, _)) = res {
            trace!("offset: {} bytes", webm.offset(i));
        } else {
            panic!();
        }
    }
}
<|endoftext|>


<commit_before>use matrix::{Scalar,Mat,RoCM,Matrix};
use core::ptr;
use core::marker::{PhantomData};
use composables::{GemmNode,AlgorithmStep};
use thread_comm::{ThreadInfo};
use typenum::Unsigned;
use super::ukernel_wrapper::{UkernelWrapper,GenericUkernelWrapper};

pub struct KernelNM<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>, Nr: Unsigned, Mr: Unsigned> {
    tmp: Matrix<T>,
    _at: PhantomData<At>,
    _bt: PhantomData<Bt>,
    _ct: PhantomData<Ct>,
    _nrt: PhantomData<Nr>,
    _mrt: PhantomData<Mr>,
}
impl<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>, Nr: Unsigned, Mr: Unsigned>
    GemmNode<T, At, Bt, Ct> for KernelNM<T, At, Bt, Ct, Nr, Mr>
    where At: RoCM<T>, Bt: RoCM<T>, Ct: RoCM<T>
{
    #[inline(always)]
    default unsafe fn run(&mut self, a: &mut At, b: &mut Bt, c: &mut Ct, _thr: &ThreadInfo<T>) -> () {
        //A must be column major and B must be row major
        debug_assert!(a.get_leaf_rs() == 1 && a.get_leaf_cs() == Mr::to_usize());
        debug_assert!(b.get_leaf_cs() == 1 && b.get_leaf_rs() == Nr::to_usize());

        let ap = a.get_mut_buffer();
        let bp = b.get_mut_buffer();
        let cp = c.get_mut_buffer();

        let m = c.height() as isize;
        let n = c.width() as isize;
        let k = a.width() as isize;

        let mut alpha = a.get_scalar() * b.get_scalar();
        let mut beta = c.get_scalar();

        let c_leaf_rs = c.get_leaf_rs() as isize;
        let c_leaf_cs = c.get_leaf_cs() as isize;

        let c_nr_stride = c.get_block_cs(1, Nr::to_usize()) as isize;
        let b_nr_stride = b.get_block_cs(1, Nr::to_usize()) as isize;

        let c_mr_stride = c.get_block_rs(1, Mr::to_usize()) as isize;
        let a_mr_stride = a.get_block_rs(1, Mr::to_usize()) as isize;

        let mut c_jr = cp;
        let mut b_jr = bp;
        let mut jr : isize = 0;
        while jr < n {
            b.establish_leaf(0, (jr as usize) / Nr::to_usize(), k as usize, Nr::to_usize());
            let mut ir : isize = 0;
            let mut a_ir = ap;
            let mut c_ir = c_jr;
            while ir < m {
                //prefetch next C
                let next_c_ir = c_ir.offset(c_mr_stride);

                //These prefetches are only correct if C is row major!!!!
                if cfg!(feature="asm_snippets") {
                    asm!(" prefetcht2 ($0)
                           prefetcht2 64($0)" : : "r"(next_c_ir));
                    asm!(" prefetcht2 ($0)
                           prefetcht2 64($0)" : : "r"(next_c_ir.offset(c_leaf_rs)));
                    asm!(" prefetcht2 ($0)
                           prefetcht2 64($0)" : : "r"(next_c_ir.offset(2*c_leaf_rs)));
                    asm!(" prefetcht2 ($0)
                           prefetcht2 64($0)" : : "r"(next_c_ir.offset(3*c_leaf_rs)));
                }

                if Ct::full_leaves() || (n - jr >= Nr::to_isize()) && (m - ir >= Mr::to_isize()) {
                    <UkernelWrapper<Mr, Nr, T>>::run(k, &mut alpha, a_ir, b_jr, &mut beta, c_ir, c_leaf_rs, c_leaf_cs);
                } else {
					let tp = self.tmp.get_mut_buffer();
					let mut t_scalar = T::zero();
                    let t_rs = self.tmp.get_row_stride() as isize;
                    let t_cs = self.tmp.get_column_stride() as isize;
					<UkernelWrapper<Mr,Nr,T>>::run(k, &mut alpha, a_ir, b_jr, &mut t_scalar, tp, t_rs, t_cs);

                    let local_m = if m-ir >= Mr::to_isize() { Mr::to_isize() } else { m-ir };
                    let local_n = if n-jr >= Nr::to_isize() { Nr::to_isize() } else { n-jr };

					//Add t to c
                    for ii in 0..local_m {
                        for jj in 0..local_n {
                            let tau = ptr::read(tp.offset(ii * t_rs + jj * t_cs));
                            let chi = ptr::read(c_ir.offset(ii * c_leaf_rs + jj * c_leaf_cs));
                            ptr::write(c_ir.offset(ii * c_leaf_rs + jj * c_leaf_cs), tau+beta*chi);
                        }
                    }
                }

                ir += Mr::to_isize();
                a_ir = a_ir.offset(a_mr_stride);
                c_ir = c_ir.offset(c_mr_stride);
            }
            jr += Nr::to_isize();
            c_jr = c_jr.offset(c_nr_stride);
            b_jr = b_jr.offset(b_nr_stride);
        }

    }
    fn new() -> Self {
        let mut tmp = <Matrix<T>>::new(Nr::to_usize(), Mr::to_usize());
        tmp.transpose();
        KernelNM{ tmp: tmp, _at: PhantomData, _bt: PhantomData, _ct: PhantomData, _nrt: PhantomData, _mrt: PhantomData }
    }
    fn hierarchy_description() -> Vec<AlgorithmStep> {
        let mut desc = Vec::new();
        desc.push(AlgorithmStep::M{bsz: Mr::to_usize()});
        desc.push(AlgorithmStep::N{bsz: Nr::to_usize()});
        desc
    }
}
<commit_msg>very slight prefetch improvements<commit_after>use matrix::{Scalar,Mat,RoCM,Matrix};
use core::ptr;
use core::marker::{PhantomData};
use composables::{GemmNode,AlgorithmStep};
use thread_comm::{ThreadInfo};
use typenum::Unsigned;
use super::ukernel_wrapper::{UkernelWrapper,GenericUkernelWrapper};

#[inline(always)]
unsafe fn prefetch_c_row<T: Scalar>(ptr: *mut T) {
    asm!("
         prefetchw ($0)
         prefetchw 64($0)
         "
         : : "r"(ptr));
}

pub struct KernelNM<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>, Nr: Unsigned, Mr: Unsigned> {
    tmp: Matrix<T>,
    _at: PhantomData<At>,
    _bt: PhantomData<Bt>,
    _ct: PhantomData<Ct>,
    _nrt: PhantomData<Nr>,
    _mrt: PhantomData<Mr>,
}
impl<T: Scalar, At: Mat<T>, Bt: Mat<T>, Ct: Mat<T>, Nr: Unsigned, Mr: Unsigned>
    GemmNode<T, At, Bt, Ct> for KernelNM<T, At, Bt, Ct, Nr, Mr>
    where At: RoCM<T>, Bt: RoCM<T>, Ct: RoCM<T>
{
    #[inline(always)]
    default unsafe fn run(&mut self, a: &mut At, b: &mut Bt, c: &mut Ct, _thr: &ThreadInfo<T>) -> () {
        //A must be column major and B must be row major
        debug_assert!(a.get_leaf_rs() == 1 && a.get_leaf_cs() == Mr::to_usize());
        debug_assert!(b.get_leaf_cs() == 1 && b.get_leaf_rs() == Nr::to_usize());

        let ap = a.get_mut_buffer();
        let bp = b.get_mut_buffer();
        let cp = c.get_mut_buffer();

        let m = c.height() as isize;
        let n = c.width() as isize;
        let k = a.width() as isize;

        let mut alpha = a.get_scalar() * b.get_scalar();
        let mut beta = c.get_scalar();

        let c_leaf_rs = c.get_leaf_rs() as isize;
        let c_leaf_cs = c.get_leaf_cs() as isize;

        let c_nr_stride = c.get_block_cs(1, Nr::to_usize()) as isize;
        let b_nr_stride = b.get_block_cs(1, Nr::to_usize()) as isize;

        let c_mr_stride = c.get_block_rs(1, Mr::to_usize()) as isize;
        let a_mr_stride = a.get_block_rs(1, Mr::to_usize()) as isize;

        let mut c_jr = cp;
        let mut b_jr = bp;
        let mut jr : isize = 0;
        while jr < n {
            b.establish_leaf(0, (jr as usize) / Nr::to_usize(), k as usize, Nr::to_usize());
            let mut ir : isize = 0;
            let mut a_ir = ap;
            let mut c_ir = c_jr;
            while ir < m {
                //prefetch next C
                //These prefetches are only correct if C is row major!!!!
                if cfg!(feature="asm_snippets") {
                    let next_c_ir = c_ir.offset(c_mr_stride);
                    prefetch_c_row(next_c_ir);
                    prefetch_c_row(next_c_ir.offset(c_leaf_rs));
                    prefetch_c_row(next_c_ir.offset(2*c_leaf_rs));
                    prefetch_c_row(next_c_ir.offset(3*c_leaf_rs));
                }

                if Ct::full_leaves() || (n - jr >= Nr::to_isize()) && (m - ir >= Mr::to_isize()) {
                    <UkernelWrapper<Mr, Nr, T>>::run(k, &mut alpha, a_ir, b_jr, &mut beta, c_ir, c_leaf_rs, c_leaf_cs);
                } else {
					let tp = self.tmp.get_mut_buffer();
					let mut t_scalar = T::zero();
                    let t_rs = self.tmp.get_row_stride() as isize;
                    let t_cs = self.tmp.get_column_stride() as isize;
					<UkernelWrapper<Mr,Nr,T>>::run(k, &mut alpha, a_ir, b_jr, &mut t_scalar, tp, t_rs, t_cs);

                    let local_m = if m-ir >= Mr::to_isize() { Mr::to_isize() } else { m-ir };
                    let local_n = if n-jr >= Nr::to_isize() { Nr::to_isize() } else { n-jr };

					//Add t to c
                    for ii in 0..local_m {
                        for jj in 0..local_n {
                            let tau = ptr::read(tp.offset(ii * t_rs + jj * t_cs));
                            let chi = ptr::read(c_ir.offset(ii * c_leaf_rs + jj * c_leaf_cs));
                            ptr::write(c_ir.offset(ii * c_leaf_rs + jj * c_leaf_cs), tau+beta*chi);
                        }
                    }
                }

                ir += Mr::to_isize();
                a_ir = a_ir.offset(a_mr_stride);
                c_ir = c_ir.offset(c_mr_stride);
            }
            jr += Nr::to_isize();
            c_jr = c_jr.offset(c_nr_stride);
            b_jr = b_jr.offset(b_nr_stride);
        }

    }
    fn new() -> Self {
        let mut tmp = <Matrix<T>>::new(Nr::to_usize(), Mr::to_usize());
        tmp.transpose();
        KernelNM{ tmp: tmp, _at: PhantomData, _bt: PhantomData, _ct: PhantomData, _nrt: PhantomData, _mrt: PhantomData }
    }
    fn hierarchy_description() -> Vec<AlgorithmStep> {
        let mut desc = Vec::new();
        desc.push(AlgorithmStep::M{bsz: Mr::to_usize()});
        desc.push(AlgorithmStep::N{bsz: Nr::to_usize()});
        desc
    }
}
<|endoftext|>


<commit_before>use piston_window::*;
use piston_window::types::Color;

use board::Board;
use tetromino::*;
use settings::*;

enum GameState {
    Playing,
    Paused
}

pub trait Game {
    fn on_input(&mut self, input: Input);
    fn on_update(&mut self, update_args: UpdateArgs);
    fn on_render(&mut self, render_args: RenderArgs, e: PistonWindow);
}

pub trait Renderer {
    fn render(&self, context: Context, graphics: &mut G2d);
}

pub trait GridRenderer {
    fn render(&self, x: i32, y: i32, context: Context, graphics: &mut G2d);
}

pub struct Rustris {
    board: Board,
    current_piece: Piece,
    next_piece: Piece,
    score: u32,
    level: u32,
    time_since_moved: f64,
    time_per_tick: f64
    // state: GameState
}
impl Rustris {
    pub fn new() -> Rustris {
        Rustris {
            board: Board::new(),
            current_piece: create_random_piece(),
            next_piece: create_random_piece(),
            score: 0,
            level: 1,
            time_since_moved: 0.0,
            time_per_tick: 0.3  //For testing
        }
    }

    pub fn reset(&mut self) {

    }

    pub fn set_current_piece(&mut self, piece: Piece) {
        if self.is_valid_board_position(&piece) {
            self.current_piece = piece;
        }
    }

    fn is_valid_board_position(&self, piece: &Piece) -> bool {
        piece.blocks_iter().all(|block| {
            (block.x >= 0 && block.x < WIDTH_IN_BLOCKS as i32 &&
             block.y >= 0 && block.y < HEIGHT_IN_BLOCKS as i32 &&
             !self.board.is_space_occupied(block))
        })
    }

    fn has_landed(&self, piece: &Piece) -> bool {
        piece.blocks_iter().any(|block| {
            block.y >= HEIGHT_IN_BLOCKS as i32 ||
            self.board.is_space_occupied(block)
        })
    }
}
impl Game for Rustris {
    fn on_input(&mut self, input: Input) {
        match input {
            Input::Press(key) => {
                match key {
                    Button::Keyboard(Key::Up) => {
                        let rotated = self.current_piece.rotated();
                        self.set_current_piece(rotated);
                    }
                    Button::Keyboard(Key::Down) => {

                    }
                    Button::Keyboard(Key::Left) => {
                        let moved = self.current_piece.moved(Direction::Left);
                        self.set_current_piece(moved);
                    }
                    Button::Keyboard(Key::Right) => {
                        let moved = self.current_piece.moved(Direction::Right);
                        self.set_current_piece(moved);
                    }
                    Button::Keyboard(Key::Space) => {

                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }

    fn on_update(&mut self, update_args: UpdateArgs) {
        self.time_since_moved += update_args.dt;
        // TODO: The threshold needs to be able to be updated
        // as the game progresses
        if self.time_since_moved >= self.time_per_tick {
            self.time_since_moved -= self.time_per_tick;
            let moved = self.current_piece.moved(Direction::Down);
            if self.has_landed(&moved) {
                self.board.set_piece(&self.current_piece);
                let next = self.next_piece;
                self.set_current_piece(next);
                self.next_piece = create_random_piece();
            } else {
                self.set_current_piece(moved);
            }
        }
    }

    fn on_render(&mut self, render_args: RenderArgs, e: PistonWindow) {
        e.draw_2d(|c, g| {
            clear([0.0, 0.0, 0.0, 1.0], g);
            self.board.render(c, g);
            self.current_piece.render(c, g);
        });
    }
}

pub fn render_square_in_grid(x: i32, y: i32, color: Color, context: Context, graphics: &mut G2d) {
    let square = rectangle::square(
        0.0, 0.0, BLOCK_SIZE - (2.0 * GRID_LINE_WIDTH)
    );
    let transform = context.transform
        // Translate the origin of the transform based on where the grid starts
        .trans(GRID_X_OFFSET, GRID_Y_OFFSET)
        // Translate the square into the first grid cell (off of the bounding box)
        .trans(GRID_LINE_WIDTH, GRID_LINE_WIDTH)
        // Translate the square into the proper grid cell based on the grid x and y position
        .trans((x as f64)*BLOCK_SIZE, (y as f64)*BLOCK_SIZE);
    rectangle(color, square, transform, graphics);
}

// pub struct TheGame {
//     rotation: f64,
//     x: f64,
//     y: f64,
//     up_d: bool, down_d: bool, left_d: bool, right_d: bool
// }
// impl TheGame {
//     pub fn new() -> TheGame {
//         TheGame { rotation : 0.0, x : 0.0, y : 0.0, up_d: false, down_d: false, left_d: false, right_d: false }
//     }
// }
// impl Game for TheGame {
//     fn on_update(&mut self, update_args: UpdateArgs) {
//         self.rotation += 3.0 * update_args.dt;
//         if self.up_d {
//             self.y += (-50.0) * update_args.dt;
//         }
//         if self.down_d {
//             self.y += (50.0) * update_args.dt;
//         }
//         if self.left_d {
//             self.x += (-50.0) * update_args.dt;
//         }
//         if self.right_d {
//             self.x += (50.0) * update_args.dt;
//         }
//     }
//     fn on_render(&mut self, render_args: RenderArgs, e: PistonWindow) {
//         e.draw_2d(|c, g| {
//             clear([0.0, 0.0, 0.0, 1.0], g);
//             let center = c.transform.trans((render_args.width / 2) as f64, (render_args.height / 2) as f64);
//             let square = rectangle::square(0.0, 0.0, 100.0);
//             let red = [1.0, 0.0, 0.0, 1.0];
//             rectangle(red, square, center.trans(self.x, self.y).rot_rad(self.rotation).trans(-50.0, -50.0), g);
//         });
//     }
//     fn on_input(&mut self, inp: Input) {
//         match inp {
//             Input::Press(but) => {
//                 match but {
//                     Button::Keyboard(Key::Up) => {
//                         self.up_d = true;
//                     }
//                     Button::Keyboard(Key::Down) => {
//                         self.down_d = true;
//                     }
//                     Button::Keyboard(Key::Left) => {
//                         self.left_d = true;
//                     }
//                     Button::Keyboard(Key::Right) => {
//                         self.right_d = true;
//                     }
//                     _ => {}
//                 }
//             }
//             Input::Release(but) => {
//                 match but {
//                     Button::Keyboard(Key::Up) => {
//                         self.up_d = false;
//                     }
//                     Button::Keyboard(Key::Down) => {
//                         self.down_d = false;
//                     }
//                     Button::Keyboard(Key::Left) => {
//                         self.left_d = false;
//                     }
//                     Button::Keyboard(Key::Right) => {
//                         self.right_d = false;
//                     }
//                     _ => {}
//                 }
//             }
//             _ => {}
//         }
//     }
// }
<commit_msg>remove the commented out Game example<commit_after>use piston_window::*;
use piston_window::types::Color;

use board::Board;
use tetromino::*;
use settings::*;

enum GameState {
    Playing,
    Paused
}

pub trait Game {
    fn on_input(&mut self, input: Input);
    fn on_update(&mut self, update_args: UpdateArgs);
    fn on_render(&mut self, render_args: RenderArgs, e: PistonWindow);
}

pub trait Renderer {
    fn render(&self, context: Context, graphics: &mut G2d);
}

pub trait GridRenderer {
    fn render(&self, x: i32, y: i32, context: Context, graphics: &mut G2d);
}

pub struct Rustris {
    board: Board,
    current_piece: Piece,
    next_piece: Piece,
    score: u32,
    level: u32,
    time_since_moved: f64,
    time_per_tick: f64
    // state: GameState
}
impl Rustris {
    pub fn new() -> Rustris {
        Rustris {
            board: Board::new(),
            current_piece: create_random_piece(),
            next_piece: create_random_piece(),
            score: 0,
            level: 1,
            time_since_moved: 0.0,
            time_per_tick: 0.3  //For testing
        }
    }

    pub fn reset(&mut self) {

    }

    pub fn set_current_piece(&mut self, piece: Piece) {
        if self.is_valid_board_position(&piece) {
            self.current_piece = piece;
        }
    }

    fn is_valid_board_position(&self, piece: &Piece) -> bool {
        piece.blocks_iter().all(|block| {
            (block.x >= 0 && block.x < WIDTH_IN_BLOCKS as i32 &&
             block.y >= 0 && block.y < HEIGHT_IN_BLOCKS as i32 &&
             !self.board.is_space_occupied(block))
        })
    }

    fn has_landed(&self, piece: &Piece) -> bool {
        piece.blocks_iter().any(|block| {
            block.y >= HEIGHT_IN_BLOCKS as i32 ||
            self.board.is_space_occupied(block)
        })
    }
}
impl Game for Rustris {
    fn on_input(&mut self, input: Input) {
        match input {
            Input::Press(key) => {
                match key {
                    Button::Keyboard(Key::Up) => {
                        let rotated = self.current_piece.rotated();
                        self.set_current_piece(rotated);
                    }
                    Button::Keyboard(Key::Down) => {

                    }
                    Button::Keyboard(Key::Left) => {
                        let moved = self.current_piece.moved(Direction::Left);
                        self.set_current_piece(moved);
                    }
                    Button::Keyboard(Key::Right) => {
                        let moved = self.current_piece.moved(Direction::Right);
                        self.set_current_piece(moved);
                    }
                    Button::Keyboard(Key::Space) => {

                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }

    fn on_update(&mut self, update_args: UpdateArgs) {
        self.time_since_moved += update_args.dt;
        // TODO: The threshold needs to be able to be updated
        // as the game progresses
        if self.time_since_moved >= self.time_per_tick {
            self.time_since_moved -= self.time_per_tick;
            let moved = self.current_piece.moved(Direction::Down);
            if self.has_landed(&moved) {
                self.board.set_piece(&self.current_piece);
                let next = self.next_piece;
                self.set_current_piece(next);
                self.next_piece = create_random_piece();
            } else {
                self.set_current_piece(moved);
            }
        }
    }

    fn on_render(&mut self, render_args: RenderArgs, e: PistonWindow) {
        e.draw_2d(|c, g| {
            clear([0.0, 0.0, 0.0, 1.0], g);
            self.board.render(c, g);
            self.current_piece.render(c, g);
        });
    }
}

pub fn render_square_in_grid(x: i32, y: i32, color: Color, context: Context, graphics: &mut G2d) {
    let square = rectangle::square(
        0.0, 0.0, BLOCK_SIZE - (2.0 * GRID_LINE_WIDTH)
    );
    let transform = context.transform
        // Translate the origin of the transform based on where the grid starts
        .trans(GRID_X_OFFSET, GRID_Y_OFFSET)
        // Translate the square into the first grid cell (off of the bounding box)
        .trans(GRID_LINE_WIDTH, GRID_LINE_WIDTH)
        // Translate the square into the proper grid cell based on the grid x and y position
        .trans((x as f64)*BLOCK_SIZE, (y as f64)*BLOCK_SIZE);
    rectangle(color, square, transform, graphics);
}
<|endoftext|>