<commit_before>use fall_tree::visitor::{Visitor, NodeVisitor};
use fall_tree::{Text, TextRange, AstNode, Node, NodeType};
use fall_tree::search::{children_of_type, child_of_type_exn, child_of_type, ast_parent_exn};

use ::{STRING, IDENT, SIMPLE_STRING, HASH_STRING, AST_SELECTOR, QUESTION, DOT, STAR, PUB,
       LexRule, SynRule, FallFile, VerbatimDef, MethodDef,
       RefExpr, AstClassDef, AstDef, Expr, Attributes, Attribute, ExampleDef,
       CallExpr, Parameter};

impl<'f> FallFile<'f> {
    pub fn resolve_rule(&self, name: Text<'f>) -> Option<SynRule<'f>> {
        self.syn_rules()
            .find(|r| r.name().is_some() && r.name().unwrap() == name)
    }

    pub fn resolve_ty(&self, name: Text<'f>) -> Option<usize> {
        self.node_types().iter().position(|&it| it.0 == name)
            .map(|idx| idx + 1)
    }

    pub fn node_types(&self) -> Vec<(Text<'f>, bool)> {
        let mut result = Vec::new();
        if let Some(tokenizer) = self.tokenizer_def() {
            result.extend(
                tokenizer.lex_rules()
                    .map(|r| (r.node_type(), r.is_skip()))
            )
        }
        result.extend(
            self.syn_rules()
                .filter(|r| r.is_pub() && r.type_attr().is_none())
                .filter_map(|r| r.name())
                .map(|n| (n, false))
        );
        result
    }

    pub fn contexts(&self) -> Vec<Text<'f>> {
        let mut result = Vec::new();
        Visitor(&mut result)
            .visit::<CallExpr, _>(|contexts, call| {
                if call.fn_name() == "is_in" || call.fn_name() == "enter" || call.fn_name() == "exit" {
                    if let Some(ctx) = call.context() {
                        contexts.push(ctx);
                    }
                }
            })
            .walk_recursively_children_first(self.node());
        result
    }
}

impl<'f> LexRule<'f> {
    pub fn token_re(&self) -> Option<String> {
        let raw = match self.raw_re() {
            Some(raw) => raw,
            None => return None,
        };

        if raw.starts_with("r") {
            Some(lit_body(raw).to_string())
        } else {
            Some(::regex::escape(&lit_body(raw).to_cow()))
        }
    }

    pub fn extern_fn(&self) -> Option<Text<'f>> {
        children_of_type(self.node(), STRING).nth(1).map(|n| {
            lit_body(n.text())
        })
    }

    pub fn token_name(&self) -> Text<'f> {
        if let Some(r) = self.raw_re() {
            if r.starts_with("'") {
                return r
            }
        }
        self.node_type()
    }

    pub fn is_contextual(&self) -> bool {
        if let Some(attrs) = self.attributes() {
            return attrs.has_attribute("contextual")
        }
        false
    }

    pub fn is_skip(&self) -> bool {
        if let Some(attrs) = self.attributes() {
            return attrs.has_attribute("skip")
        }
        false
    }

    pub fn node_type_index(&self) -> usize {
        let file = ast_parent_exn::<FallFile>(self.node());
        file.resolve_ty(self.node_type()).unwrap()
    }

    fn raw_re(&self) -> Option<Text<'f>> {
        children_of_type(self.node(), STRING).next().map(|child| child.text())
    }
}

pub enum PratKind {
    Atom,
    Bin(u32),
    Postfix,
    Prefix
}

impl<'f> SynRule<'f> {
    pub fn resolve_ty(&self) -> Option<usize> {
        if !self.is_pub() || self.is_pratt() {
            return None
        }

        let file = ast_parent_exn::<FallFile>(self.node());
        if let Some(name) = self.ty_name() {
            file.resolve_ty(name)
        } else {
            None
        }
    }

    pub fn is_pub(&self) -> bool {
        child_of_type(self.node(), PUB).is_some()
    }

    pub fn index(&self) -> usize {
        let file = ast_parent_exn::<FallFile>(self.node());
        file.syn_rules().position(|r| r.node() == self.node()).unwrap()
    }

    pub fn pratt_kind(&self) -> Option<PratKind> {
        let attrs = match self.attributes() {
            Some(attrs) => attrs,
            None => return None,
        };

        if attrs.has_attribute("atom") {
            Some(PratKind::Atom)
        } else if attrs.has_attribute("postfix") {
            Some(PratKind::Postfix)
        } else if attrs.has_attribute("prefix") {
            Some(PratKind::Prefix)
        } else if let Some(priority) = attrs.find("bin").and_then(|attr| attr.u32_value()) {
            Some(PratKind::Bin(priority))
        } else {
            None
        }
    }

    pub fn is_pratt(&self) -> bool {
        self.has_attribute("pratt")
    }

    fn has_attribute(&self, attribute: &str) -> bool {
        if let Some(attrs) = self.attributes() {
            attrs.has_attribute(attribute)
        } else {
            false
        }
    }

    fn type_attr(&self) -> Option<Attribute<'f>> {
        self.attributes().and_then(|attrs| attrs.find("type"))
    }

    fn ty_name(&self) -> Option<Text<'f>> {
        if let Some(ty) = self.type_attr() {
            return ty.text_value();
        }
        self.name()
    }
}

impl<'f> VerbatimDef<'f> {
    pub fn contents(&self) -> Text<'f> {
        let literal_text = child_of_type_exn(self.node(), HASH_STRING).text();
        lit_body(literal_text).trim()
    }
}

impl<'f> ExampleDef<'f> {
    pub fn contents(&self) -> Text<'f> {
        let literal_text = child_of_type_exn(self.node(), HASH_STRING).text();
        lit_body(literal_text).trim()
    }
}

impl<'f> MethodDef<'f> {
    pub fn selector_kind(&self) -> SelectorKind<'f> {
        let selector = child_of_type_exn(self.node(), AST_SELECTOR);
        let name = self.selector_name();
        if has(selector, QUESTION) && has(selector, DOT) {
            SelectorKind::OptText(name)
        } else if has(selector, QUESTION) {
            SelectorKind::Opt(name)
        } else if has(selector, STAR) {
            SelectorKind::Many(name)
        } else if has(selector, DOT) {
            SelectorKind::Text(name)
        } else {
            SelectorKind::Single(name)
        }
    }

    pub fn is_class(&self) -> bool {
        let ast_def = ast_parent_exn::<AstDef>(self.node());
        let name = self.selector_name();
        ast_def.ast_classes().find(|cls| cls.name() == name).is_some()
    }

    fn selector_name(&self) -> Text<'f> {
        let selector = child_of_type_exn(self.node(), AST_SELECTOR);
        child_of_type_exn(selector, IDENT).text()
    }
}

impl<'f> AstClassDef<'f> {
    pub fn name(&self) -> Text<'f> {
        child_of_type(self.node(), IDENT).unwrap().text()
    }

    pub fn variants<'a>(&'a self) -> Box<Iterator<Item=Text<'f>> + 'a> {
        Box::new(children_of_type(self.node(), IDENT).skip(1).map(|it| it.text()))
    }
}

pub enum SelectorKind<'f> {
    Single(Text<'f>),
    Opt(Text<'f>),
    Many(Text<'f>),
    Text(Text<'f>),
    OptText(Text<'f>),
}

pub enum RefKind<'f> {
    Token(LexRule<'f>),
    RuleReference(SynRule<'f>),
    Param(u32),
}

impl<'f> RefExpr<'f> {
    pub fn resolve(&self) -> Option<RefKind<'f>> {
        let file = ast_parent_exn::<FallFile>(self.node());

        if let Some(ident) = child_of_type(self.node(), IDENT) {
            let rule: SynRule = ast_parent_exn(self.node());
            if let Some(parameters) = rule.parameters() {
                if let Some(p) = parameters.parameters().find(|p| p.name() == ident.text()) {
                    return Some(RefKind::Param(p.idx()))
                }
            }

            if let Some(rule) = file.resolve_rule(ident.text()) {
                return Some(RefKind::RuleReference(rule))
            }
        }
        let token_name = child_of_type(self.node(), IDENT)
            .unwrap_or_else(|| child_of_type_exn(self.node(), SIMPLE_STRING))
            .text();

        file.tokenizer_def()
            .and_then(|td| td.lex_rules().find(|r| r.token_name() == token_name))
            .map(|rule| RefKind::Token(rule))
    }
}

pub enum CallKind<'f> {
    Eof,
    Any,
    Commit,
    Enter(u32, Expr<'f>),
    Exit(u32, Expr<'f>),
    IsIn(u32),
    Not(Expr<'f>),
    Rep(Expr<'f>),
    Opt(Expr<'f>),
    Layer(Expr<'f>, Expr<'f>),
    WithSkip(Expr<'f>, Expr<'f>),
    RuleCall(SynRule<'f>, Vec<(u32, Expr<'f>)>)
}

impl<'f> CallExpr<'f> {
    pub fn context(&self) -> Option<Text<'f>> {
        if let Some(Expr::RefExpr(e)) = self.args().next() {
            if let Some(context) = child_of_type(e.node(), SIMPLE_STRING) {
                return Some(lit_body(context.text()))
            }
        }
        None
    }

    pub fn resolve_context(&self) -> Option<u32> {
        if let Some(Expr::RefExpr(e)) = self.args().next() {
            if let Some(context) = child_of_type(e.node(), SIMPLE_STRING) {
                let ctx_name = lit_body(context.text());
                let file: FallFile = ast_parent_exn(self.node());
                return file.contexts().into_iter().position(|c| c == ctx_name).map(|i| i as u32)
            }
        }
        None
    }

    pub fn kind(&self) -> Result<CallKind<'f>, &'static str> {
        let file: FallFile = ast_parent_exn(self.node());
        macro_rules! check_args {
            ($n:expr) => {
                if self.args().count() != $n {
                    return Err(concat!("expected ", $n, " arguments"))
                }
            }
        };

        let kind = match self.fn_name().to_cow().as_ref() {
            "eof" => { check_args!(0); CallKind::Eof }
            "any" => { check_args!(0); CallKind::Any }
            "commit" => { check_args!(0); CallKind::Commit }
            "enter" => {
                check_args!(2);
                let ctx = self.resolve_context().ok_or("enter without context")?;
                let arg = self.args().nth(1).unwrap();
                CallKind::Enter(ctx, arg)
            }
            "exit" => {
                check_args!(2);
                let ctx = self.resolve_context().ok_or("exit without context")?;
                let arg = self.args().nth(1).unwrap();
                CallKind::Exit(ctx, arg)
            }
            "is_in" => {
                check_args!(1);
                let ctx = self.resolve_context().ok_or("is_in without context")?;
                CallKind::IsIn(ctx)
            }
            "not" => {
                check_args!(1);
                CallKind::Not(self.args().next().unwrap())
            }
            "rep" => {
                check_args!(1);
                CallKind::Rep(self.args().next().unwrap())
            }
            "opt" => {
                check_args!(1);
                CallKind::Opt(self.args().next().unwrap())
            }
            "layer" => {
                check_args!(2);
                CallKind::Layer(self.args().nth(0).unwrap(), self.args().nth(1).unwrap())
            }
            "with_skip" => {
                check_args!(2);
                CallKind::WithSkip(self.args().nth(0).unwrap(), self.args().nth(1).unwrap())
            }
            _ => {
                if let Some(rule) = file.resolve_rule(self.fn_name()) {
                    if let Some(parameters) = rule.parameters() {
                        let params = parameters.parameters()
                            .map(|p| p.idx())
                            .zip(self.args())
                            .collect();
                        return Ok(CallKind::RuleCall(rule, params))
                    }
                }
                return Err("unknown rule")
            }
        };

        Ok(kind)
    }
}

impl<'f> Parameter<'f> {
    fn idx(&self) -> u32 {
        let file: FallFile = ast_parent_exn(self.node());
        let idx = file.syn_rules()
            .filter_map(|rule| rule.parameters())
            .flat_map(|p| p.parameters())
            .position(|p| p.node() == self.node())
            .unwrap();

        idx as u32
    }
}

impl<'f> Attributes<'f> {
    pub fn has_attribute(&self, name: &str) -> bool {
        self.find(name).is_some()
    }

    pub fn find(&self, name: &str) -> Option<Attribute<'f>> {
        self.attributes().find(|a| a.name() == name)
    }
}

impl<'f> Attribute<'f> {
    pub fn u32_value(&self) -> Option<u32> {
        self.text_value()
            .and_then(|text| text.to_cow().parse().ok())
    }

    pub fn text_value(&self) -> Option<Text<'f>> {
        self.value().map(|v| v.node().text())
    }
}

fn lit_body(lit: Text) -> Text {
    let q = if lit.starts_with("'") { "'" } else { "\"" };
    let s = lit.find(q).unwrap();
    let e = lit.rfind(q).unwrap();
    lit.slice(TextRange::from_to(s + 1, e))
}

fn has(node: Node, ty: NodeType) -> bool {
    child_of_type(node, ty).is_some()
}
<commit_msg>Reformat<commit_after>use fall_tree::visitor::{Visitor, NodeVisitor};
use fall_tree::{Text, TextRange, AstNode, Node, NodeType};
use fall_tree::search::{children_of_type, child_of_type_exn, child_of_type, ast_parent_exn};

use ::{STRING, IDENT, SIMPLE_STRING, HASH_STRING, AST_SELECTOR, QUESTION, DOT, STAR, PUB,
       LexRule, SynRule, FallFile, VerbatimDef, MethodDef,
       RefExpr, AstClassDef, AstDef, Expr, Attributes, Attribute, ExampleDef,
       CallExpr, Parameter};

impl<'f> FallFile<'f> {
    pub fn resolve_rule(&self, name: Text<'f>) -> Option<SynRule<'f>> {
        self.syn_rules()
            .find(|r| r.name().is_some() && r.name().unwrap() == name)
    }

    pub fn resolve_ty(&self, name: Text<'f>) -> Option<usize> {
        self.node_types().iter().position(|&it| it.0 == name)
            .map(|idx| idx + 1)
    }

    pub fn node_types(&self) -> Vec<(Text<'f>, bool)> {
        let mut result = Vec::new();
        if let Some(tokenizer) = self.tokenizer_def() {
            result.extend(
                tokenizer.lex_rules()
                    .map(|r| (r.node_type(), r.is_skip()))
            )
        }
        result.extend(
            self.syn_rules()
                .filter(|r| r.is_pub() && r.type_attr().is_none())
                .filter_map(|r| r.name())
                .map(|n| (n, false))
        );
        result
    }

    pub fn contexts(&self) -> Vec<Text<'f>> {
        let mut result = Vec::new();
        Visitor(&mut result)
            .visit::<CallExpr, _>(|contexts, call| {
                if call.fn_name() == "is_in" || call.fn_name() == "enter" || call.fn_name() == "exit" {
                    if let Some(ctx) = call.context() {
                        contexts.push(ctx);
                    }
                }
            })
            .walk_recursively_children_first(self.node());
        result
    }
}

impl<'f> LexRule<'f> {
    pub fn token_re(&self) -> Option<String> {
        let raw = match self.raw_re() {
            Some(raw) => raw,
            None => return None,
        };

        if raw.starts_with("r") {
            Some(lit_body(raw).to_string())
        } else {
            Some(::regex::escape(&lit_body(raw).to_cow()))
        }
    }

    pub fn extern_fn(&self) -> Option<Text<'f>> {
        children_of_type(self.node(), STRING).nth(1).map(|n| {
            lit_body(n.text())
        })
    }

    pub fn token_name(&self) -> Text<'f> {
        if let Some(r) = self.raw_re() {
            if r.starts_with("'") {
                return r
            }
        }
        self.node_type()
    }

    pub fn is_contextual(&self) -> bool {
        if let Some(attrs) = self.attributes() {
            return attrs.has_attribute("contextual")
        }
        false
    }

    pub fn is_skip(&self) -> bool {
        if let Some(attrs) = self.attributes() {
            return attrs.has_attribute("skip")
        }
        false
    }

    pub fn node_type_index(&self) -> usize {
        let file = ast_parent_exn::<FallFile>(self.node());
        file.resolve_ty(self.node_type()).unwrap()
    }

    fn raw_re(&self) -> Option<Text<'f>> {
        children_of_type(self.node(), STRING).next().map(|child| child.text())
    }
}

pub enum PratKind {
    Atom,
    Bin(u32),
    Postfix,
    Prefix
}

impl<'f> SynRule<'f> {
    pub fn resolve_ty(&self) -> Option<usize> {
        if !self.is_pub() || self.is_pratt() {
            return None
        }

        let file = ast_parent_exn::<FallFile>(self.node());
        if let Some(name) = self.ty_name() {
            file.resolve_ty(name)
        } else {
            None
        }
    }

    pub fn is_pub(&self) -> bool {
        child_of_type(self.node(), PUB).is_some()
    }

    pub fn index(&self) -> usize {
        let file = ast_parent_exn::<FallFile>(self.node());
        file.syn_rules().position(|r| r.node() == self.node()).unwrap()
    }

    pub fn pratt_kind(&self) -> Option<PratKind> {
        let attrs = match self.attributes() {
            Some(attrs) => attrs,
            None => return None,
        };

        if attrs.has_attribute("atom") {
            Some(PratKind::Atom)
        } else if attrs.has_attribute("postfix") {
            Some(PratKind::Postfix)
        } else if attrs.has_attribute("prefix") {
            Some(PratKind::Prefix)
        } else if let Some(priority) = attrs.find("bin").and_then(|attr| attr.u32_value()) {
            Some(PratKind::Bin(priority))
        } else {
            None
        }
    }

    pub fn is_pratt(&self) -> bool {
        self.has_attribute("pratt")
    }

    fn has_attribute(&self, attribute: &str) -> bool {
        if let Some(attrs) = self.attributes() {
            attrs.has_attribute(attribute)
        } else {
            false
        }
    }

    fn type_attr(&self) -> Option<Attribute<'f>> {
        self.attributes().and_then(|attrs| attrs.find("type"))
    }

    fn ty_name(&self) -> Option<Text<'f>> {
        if let Some(ty) = self.type_attr() {
            return ty.text_value();
        }
        self.name()
    }
}

impl<'f> VerbatimDef<'f> {
    pub fn contents(&self) -> Text<'f> {
        let literal_text = child_of_type_exn(self.node(), HASH_STRING).text();
        lit_body(literal_text).trim()
    }
}

impl<'f> ExampleDef<'f> {
    pub fn contents(&self) -> Text<'f> {
        let literal_text = child_of_type_exn(self.node(), HASH_STRING).text();
        lit_body(literal_text).trim()
    }
}

impl<'f> MethodDef<'f> {
    pub fn selector_kind(&self) -> SelectorKind<'f> {
        let selector = child_of_type_exn(self.node(), AST_SELECTOR);
        let name = self.selector_name();
        if has(selector, QUESTION) && has(selector, DOT) {
            SelectorKind::OptText(name)
        } else if has(selector, QUESTION) {
            SelectorKind::Opt(name)
        } else if has(selector, STAR) {
            SelectorKind::Many(name)
        } else if has(selector, DOT) {
            SelectorKind::Text(name)
        } else {
            SelectorKind::Single(name)
        }
    }

    pub fn is_class(&self) -> bool {
        let ast_def = ast_parent_exn::<AstDef>(self.node());
        let name = self.selector_name();
        ast_def.ast_classes().find(|cls| cls.name() == name).is_some()
    }

    fn selector_name(&self) -> Text<'f> {
        let selector = child_of_type_exn(self.node(), AST_SELECTOR);
        child_of_type_exn(selector, IDENT).text()
    }
}

impl<'f> AstClassDef<'f> {
    pub fn name(&self) -> Text<'f> {
        child_of_type(self.node(), IDENT).unwrap().text()
    }

    pub fn variants<'a>(&'a self) -> Box<Iterator<Item=Text<'f>> + 'a> {
        Box::new(children_of_type(self.node(), IDENT).skip(1).map(|it| it.text()))
    }
}

pub enum SelectorKind<'f> {
    Single(Text<'f>),
    Opt(Text<'f>),
    Many(Text<'f>),
    Text(Text<'f>),
    OptText(Text<'f>),
}

pub enum RefKind<'f> {
    Token(LexRule<'f>),
    RuleReference(SynRule<'f>),
    Param(u32),
}

impl<'f> RefExpr<'f> {
    pub fn resolve(&self) -> Option<RefKind<'f>> {
        let file = ast_parent_exn::<FallFile>(self.node());

        if let Some(ident) = child_of_type(self.node(), IDENT) {
            let rule: SynRule = ast_parent_exn(self.node());
            if let Some(parameters) = rule.parameters() {
                if let Some(p) = parameters.parameters().find(|p| p.name() == ident.text()) {
                    return Some(RefKind::Param(p.idx()))
                }
            }

            if let Some(rule) = file.resolve_rule(ident.text()) {
                return Some(RefKind::RuleReference(rule))
            }
        }
        let token_name = child_of_type(self.node(), IDENT)
            .unwrap_or_else(|| child_of_type_exn(self.node(), SIMPLE_STRING))
            .text();

        file.tokenizer_def()
            .and_then(|td| td.lex_rules().find(|r| r.token_name() == token_name))
            .map(|rule| RefKind::Token(rule))
    }
}

pub enum CallKind<'f> {
    Eof,
    Any,
    Commit,
    Enter(u32, Expr<'f>),
    Exit(u32, Expr<'f>),
    IsIn(u32),
    Not(Expr<'f>),
    Rep(Expr<'f>),
    Opt(Expr<'f>),
    Layer(Expr<'f>, Expr<'f>),
    WithSkip(Expr<'f>, Expr<'f>),
    RuleCall(SynRule<'f>, Vec<(u32, Expr<'f>)>)
}

impl<'f> CallExpr<'f> {
    pub fn context(&self) -> Option<Text<'f>> {
        if let Some(Expr::RefExpr(e)) = self.args().next() {
            if let Some(context) = child_of_type(e.node(), SIMPLE_STRING) {
                return Some(lit_body(context.text()))
            }
        }
        None
    }

    pub fn resolve_context(&self) -> Option<u32> {
        if let Some(Expr::RefExpr(e)) = self.args().next() {
            if let Some(context) = child_of_type(e.node(), SIMPLE_STRING) {
                let ctx_name = lit_body(context.text());
                let file: FallFile = ast_parent_exn(self.node());
                return file.contexts().into_iter().position(|c| c == ctx_name).map(|i| i as u32)
            }
        }
        None
    }

    pub fn kind(&self) -> Result<CallKind<'f>, &'static str> {
        let file: FallFile = ast_parent_exn(self.node());
        macro_rules! check_args {
            ($n:expr) => {
                if self.args().count() != $n {
                    return Err(concat!("expected ", $n, " arguments"))
                }
            }
        };

        let kind = match self.fn_name().to_cow().as_ref() {
            "eof" => {
                check_args!(0);
                CallKind::Eof
            }
            "any" => {
                check_args!(0);
                CallKind::Any
            }
            "commit" => {
                check_args!(0);
                CallKind::Commit
            }
            "enter" => {
                check_args!(2);
                let ctx = self.resolve_context().ok_or("enter without context")?;
                let arg = self.args().nth(1).unwrap();
                CallKind::Enter(ctx, arg)
            }
            "exit" => {
                check_args!(2);
                let ctx = self.resolve_context().ok_or("exit without context")?;
                let arg = self.args().nth(1).unwrap();
                CallKind::Exit(ctx, arg)
            }
            "is_in" => {
                check_args!(1);
                let ctx = self.resolve_context().ok_or("is_in without context")?;
                CallKind::IsIn(ctx)
            }
            "not" => {
                check_args!(1);
                CallKind::Not(self.args().next().unwrap())
            }
            "rep" => {
                check_args!(1);
                CallKind::Rep(self.args().next().unwrap())
            }
            "opt" => {
                check_args!(1);
                CallKind::Opt(self.args().next().unwrap())
            }
            "layer" => {
                check_args!(2);
                CallKind::Layer(self.args().nth(0).unwrap(), self.args().nth(1).unwrap())
            }
            "with_skip" => {
                check_args!(2);
                CallKind::WithSkip(self.args().nth(0).unwrap(), self.args().nth(1).unwrap())
            }
            _ => {
                if let Some(rule) = file.resolve_rule(self.fn_name()) {
                    if let Some(parameters) = rule.parameters() {
                        let params = parameters.parameters()
                            .map(|p| p.idx())
                            .zip(self.args())
                            .collect();
                        return Ok(CallKind::RuleCall(rule, params))
                    }
                }
                return Err("unknown rule")
            }
        };

        Ok(kind)
    }
}

impl<'f> Parameter<'f> {
    fn idx(&self) -> u32 {
        let file: FallFile = ast_parent_exn(self.node());
        let idx = file.syn_rules()
            .filter_map(|rule| rule.parameters())
            .flat_map(|p| p.parameters())
            .position(|p| p.node() == self.node())
            .unwrap();

        idx as u32
    }
}

impl<'f> Attributes<'f> {
    pub fn has_attribute(&self, name: &str) -> bool {
        self.find(name).is_some()
    }

    pub fn find(&self, name: &str) -> Option<Attribute<'f>> {
        self.attributes().find(|a| a.name() == name)
    }
}

impl<'f> Attribute<'f> {
    pub fn u32_value(&self) -> Option<u32> {
        self.text_value()
            .and_then(|text| text.to_cow().parse().ok())
    }

    pub fn text_value(&self) -> Option<Text<'f>> {
        self.value().map(|v| v.node().text())
    }
}

fn lit_body(lit: Text) -> Text {
    let q = if lit.starts_with("'") { "'" } else { "\"" };
    let s = lit.find(q).unwrap();
    let e = lit.rfind(q).unwrap();
    lit.slice(TextRange::from_to(s + 1, e))
}

fn has(node: Node, ty: NodeType) -> bool {
    child_of_type(node, ty).is_some()
}
<|endoftext|>


<commit_before>//! soundstream.rs
//!
//! A real-time soundstream demo that smoothly copies input
//! from a microphone straight to the output. If <Space> is
//! pressed, the SoundStream thread will begin to calculate
//! and print the samplerate to demonstrate the inter-task
//! event handling.
//!
//! Note: Beware of feedback!

#![feature(globs)]

extern crate piston;

use piston::{
    InteractiveEvent,
    keyboard,
    AssetStore,
    Game,
    GameWindow,
    GameWindowSDL2,
    GameWindowSettings,
    KeyPress,
    KeyPressArgs,
    SoundStream,
    soundstreamer
};

//------------------------------

static SAMPLE_RATE: f64 = 44100f64;
static NUM_FRAMES: u32 = 1024u32;
static NUM_CHANNELS: i32 = 2i32;

// Structs
//------------------------------

/// Main application struct.
pub struct App {
    /// Channel for sending information to the audio stream.
    stream_chan: Option<Sender<InteractiveEvent>> // Channel for sending Events.
}

/// The audio is non-blocking and needs it's own struct.
pub struct AppSoundStream {
    /// Channel for receiving game events from main game stream.
    chan: Option<Receiver<InteractiveEvent>>, // Channel for receiving Events.
    is_exit: bool, // Trigger for closing the stream.
    is_print: bool, // Toggle for printing the sample_rate.
    buffer: Vec<f32> // Buffer for passing input to output.
}

// Game Method Implementations
//------------------------------

impl Game for App {

    /// Setup / load the app stuff ready for the main loop.
    /// If using a SoundStream, it must be created within this method.
    fn load(&mut self, asset_store: &mut AssetStore) {

        // Create a channel for communicating events with the soundstream.
        // Note: this channel is used for sending InteractiveEvents, but
        // the same technique could be used here to create custom channels
        // that can safely send any kind of unique data.
        let (send, recv) = channel();
        self.stream_chan = Some(send);

        // Create the soundstream on it's own thread for non-blocking, real-time audio.
        // "soundstreamer" will setup and iterate soundstream using portaudio.
        spawn(proc() {
            let mut soundstream = AppSoundStream::new(Some(recv));
            soundstreamer(SAMPLE_RATE, NUM_FRAMES, NUM_CHANNELS, &mut soundstream);
        });

    }

    /// Keypress callback.
    fn key_press(&mut self, args: &KeyPressArgs) {
        println!("Game thread key: {}", args.key);
    }

    /// Specify the event sending channel. This must be done if we wish
    /// to send interactive events to the SoundStream.
    fn get_event_sender(&self) -> Option<Sender<InteractiveEvent>> {
        self.stream_chan.clone()
    }

}

impl Drop for App {
    /// Tell the soundstream to exit when App is destroyed.
    fn drop(&mut self) {
        let chan = self.stream_chan.clone();
        match chan {
            Some(sender) => sender.send(KeyPress(KeyPressArgs { key: keyboard::Escape })),
            None => ()
        }
    }
}

impl App {
    /// Creates a new application.
    pub fn new() -> App {
        App {
            stream_chan: None
        }
    }
}

// SoundStream Method Implementations
//------------------------------

impl SoundStream for AppSoundStream {

    /// Load (called prior to main soundstream loop).
    fn load(&mut self) {
        println!("Press <Spacebar> to start/stop printing the real-time sample rate.");
    }

    /// Update (gets called prior to audio_in/audio_out).
    fn update(&mut self, dt: u64) {
        if self.is_print {
            let dtsec: f64 = dt as f64 / 1000000000f64;
            println!("Real-time sample rate: {}", (1f64 / dtsec) * NUM_FRAMES as f64);
        }
    }

    /// AudioInput
    fn audio_in(&mut self, input: &Vec<f32>, num_frames: u32, num_channels: i32) {
        self.buffer = input.clone();
    }

    /// AudioOutput
    fn audio_out(&mut self, output: &mut Vec<f32>, num_frames: u32, num_channels: i32) {
        *output = self.buffer.clone()
    }

    /// KeyPress
    fn key_press(&mut self, args: &KeyPressArgs) {
        println!("Soundstream thread key: {}", args.key);
        if args.key == keyboard::Space {
            let b_print = if self.is_print { false } else { true };
            self.is_print = b_print;
        }
        if args.key == keyboard::Escape {
            self.is_exit = true;
        }
    }

    /// Retrieve Events for callback (i.e. mouse, keyboard).
    fn check_for_event(&self) -> Option<InteractiveEvent> {
        match self.chan {
            Some(ref receiver) => match receiver.try_recv() {
                Ok(event) => Some(event),
                Err(_) => None
            },
            None => None
        }
    }

    /// Setup the exit condition (is checked once per buffer).
    fn exit(&self) -> bool { self.is_exit }

}

impl AppSoundStream {
    /// AppSoundStream constructor.
    pub fn new(recv: Option<Receiver<InteractiveEvent>>) -> AppSoundStream {
        AppSoundStream {
            chan: recv,
            is_exit: false,
            is_print: false,
            buffer: vec![]
        }
    }
}

// Main
//------------------------------

#[start]
fn start(argc: int, argv: **u8) -> int {
    // Run gui on the main thread.
    native::start(argc, argv, main)
}

fn main() {
    let mut window: GameWindowSDL2 = GameWindow::new(
        GameWindowSettings {
            title: "soundstream".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            background_color: [0.1, 0.1, 0.1, 0.1],
        }
    );

    let mut asset_store = AssetStore::from_folder("assets");
    let mut app = App::new();
    app.run(&mut window, &mut asset_store);
}

//------------------------------
<commit_msg>Fixed sound stream example partially<commit_after>//! soundstream.rs
//!
//! A real-time soundstream demo that smoothly copies input
//! from a microphone straight to the output. If <Space> is
//! pressed, the SoundStream thread will begin to calculate
//! and print the samplerate to demonstrate the inter-task
//! event handling.
//!
//! Note: Beware of feedback!

#![feature(globs)]

extern crate piston;

use piston::{
    keyboard,
    AssetStore,
    Game,
    GameEvent,
    GameWindow,
    GameWindowSDL2,
    GameWindowSettings,
    KeyPress,
    KeyPressArgs,
    SoundStream,
    soundstreamer
};

//------------------------------

static SAMPLE_RATE: f64 = 44100f64;
static NUM_FRAMES: u32 = 1024u32;
static NUM_CHANNELS: i32 = 2i32;

// Structs
//------------------------------

/// Main application struct.
pub struct App {
    /// Channel for sending information to the audio stream.
    stream_chan: Option<Sender<GameEvent<'static>>> // Channel for sending Events.
}

/// The audio is non-blocking and needs it's own struct.
pub struct AppSoundStream {
    /// Channel for receiving game events from main game stream.
    chan: Option<Receiver<GameEvent<'static>>>, // Channel for receiving Events.
    is_exit: bool, // Trigger for closing the stream.
    is_print: bool, // Toggle for printing the sample_rate.
    buffer: Vec<f32> // Buffer for passing input to output.
}

// Game Method Implementations
//------------------------------

impl Game for App {

    /// Setup / load the app stuff ready for the main loop.
    /// If using a SoundStream, it must be created within this method.
    fn load(&mut self, asset_store: &mut AssetStore) {

        // Create a channel for communicating events with the soundstream.
        // Note: this channel is used for sending InteractiveEvents, but
        // the same technique could be used here to create custom channels
        // that can safely send any kind of unique data.
        let (send, recv) = channel();
        self.stream_chan = Some(send);

        // Create the soundstream on it's own thread for non-blocking, real-time audio.
        // "soundstreamer" will setup and iterate soundstream using portaudio.
        spawn(proc() {
            let mut soundstream = AppSoundStream::new(Some(recv));
            soundstreamer(SAMPLE_RATE, NUM_FRAMES, NUM_CHANNELS, &mut soundstream);
        });

    }

    /// Keypress callback.
    fn key_press(&mut self, args: &KeyPressArgs) {
        println!("Game thread key: {}", args.key);
    }

    /*
    /// Specify the event sending channel. This must be done if we wish
    /// to send interactive events to the SoundStream.
    fn get_event_sender(&self) -> Option<Sender<GameEvent<'static>>> {
        self.stream_chan.clone()
    }
    */
}

impl Drop for App {
    /// Tell the soundstream to exit when App is destroyed.
    fn drop(&mut self) {
        let chan = self.stream_chan.clone();
        match chan {
            Some(sender) => sender.send(KeyPress(KeyPressArgs { key: keyboard::Escape })),
            None => ()
        }
    }
}

impl App {
    /// Creates a new application.
    pub fn new() -> App {
        App {
            stream_chan: None
        }
    }
}

// SoundStream Method Implementations
//------------------------------

impl SoundStream for AppSoundStream {

    /// Load (called prior to main soundstream loop).
    fn load(&mut self) {
        println!("Press <Spacebar> to start/stop printing the real-time sample rate.");
    }

    /// Update (gets called prior to audio_in/audio_out).
    fn update(&mut self, dt: u64) {
        if self.is_print {
            let dtsec: f64 = dt as f64 / 1000000000f64;
            println!("Real-time sample rate: {}", (1f64 / dtsec) * NUM_FRAMES as f64);
        }
    }

    /// AudioInput
    fn audio_in(&mut self, input: &Vec<f32>, num_frames: u32, num_channels: i32) {
        self.buffer = input.clone();
    }

    /// AudioOutput
    fn audio_out(&mut self, output: &mut Vec<f32>, num_frames: u32, num_channels: i32) {
        *output = self.buffer.clone()
    }

    /// KeyPress
    fn key_press(&mut self, args: &KeyPressArgs) {
        println!("Soundstream thread key: {}", args.key);
        if args.key == keyboard::Space {
            let b_print = if self.is_print { false } else { true };
            self.is_print = b_print;
        }
        if args.key == keyboard::Escape {
            self.is_exit = true;
        }
    }

    /*
    /// Retrieve Events for callback (i.e. mouse, keyboard).
    fn check_for_event(&self) -> Option<GameEvent<'static>> {
        match self.chan {
            Some(ref receiver) => match receiver.try_recv() {
                Ok(event) => Some(event),
                Err(_) => None
            },
            None => None
        }
    }
    */

    /// Setup the exit condition (is checked once per buffer).
    fn exit(&self) -> bool { self.is_exit }

}

impl AppSoundStream {
    /// AppSoundStream constructor.
    pub fn new(recv: Option<Receiver<GameEvent<'static>>>) -> AppSoundStream {
        AppSoundStream {
            chan: recv,
            is_exit: false,
            is_print: false,
            buffer: vec![]
        }
    }
}

// Main
//------------------------------

#[start]
fn start(argc: int, argv: **u8) -> int {
    // Run gui on the main thread.
    native::start(argc, argv, main)
}

fn main() {
    let mut window: GameWindowSDL2 = GameWindow::new(
        GameWindowSettings {
            title: "soundstream".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            background_color: [0.1, 0.1, 0.1, 0.1],
        }
    );

    let mut asset_store = AssetStore::from_folder("assets");
    let mut app = App::new();
    app.run(&mut window, &mut asset_store);
}

//------------------------------
<|endoftext|>


<commit_before>import common::*;
import lib::llvm::{TypeRef};
import syntax::ast;
import lib::llvm::llvm;
import driver::session::session;
import std::map::hashmap;

export type_of;
export type_of_dtor;
export type_of_explicit_args;
export type_of_fn_from_ty;
export type_of_fn;
export type_of_non_gc_box;

fn type_of_explicit_args(cx: @crate_ctxt,
                         inputs: ~[ty::arg]) -> ~[TypeRef] {
    do vec::map(inputs) |arg| {
        let arg_ty = arg.ty;
        let llty = type_of(cx, arg_ty);
        match ty::resolved_mode(cx.tcx, arg.mode) {
          ast::by_val => llty,
          _ => T_ptr(llty)
        }
    }
}

fn type_of_fn(cx: @crate_ctxt, inputs: ~[ty::arg],
              output: ty::t) -> TypeRef {
    let mut atys: ~[TypeRef] = ~[];

    // Arg 0: Output pointer.
    vec::push(atys, T_ptr(type_of(cx, output)));

    // Arg 1: Environment
    vec::push(atys, T_opaque_box_ptr(cx));

    // ... then explicit args.
    vec::push_all(atys, type_of_explicit_args(cx, inputs));
    return T_fn(atys, llvm::LLVMVoidType());
}

// Given a function type and a count of ty params, construct an llvm type
fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
    type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty))
}

fn type_of_non_gc_box(cx: @crate_ctxt, t: ty::t) -> TypeRef {
    assert !ty::type_needs_infer(t);

    let t_norm = ty::normalize_ty(cx.tcx, t);
    if t != t_norm {
        type_of_non_gc_box(cx, t_norm)
    } else {
        match ty::get(t).struct {
          ty::ty_box(mt) => {
            T_ptr(T_box(cx, type_of(cx, mt.ty)))
          }
          ty::ty_uniq(mt) => {
            T_ptr(T_unique(cx, type_of(cx, mt.ty)))
          }
          _ => {
            cx.sess.bug(~"non-box in type_of_non_gc_box");
          }
        }
    }
}

fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
    debug!{"type_of %?: %?", t, ty::get(t)};

    // Check the cache.
    if cx.lltypes.contains_key(t) { return cx.lltypes.get(t); }

    // Replace any typedef'd types with their equivalent non-typedef
    // type. This ensures that all LLVM nominal types that contain
    // Rust types are defined as the same LLVM types.  If we don't do
    // this then, e.g. `option<{myfield: bool}>` would be a different
    // type than `option<myrec>`.
    let t_norm = ty::normalize_ty(cx.tcx, t);

    let mut llty;
    if t != t_norm {
        llty = type_of(cx, t_norm);
        cx.lltypes.insert(t, llty);
    } else {
        llty = match ty::get(t).struct {
          ty::ty_nil | ty::ty_bot => T_nil(),
          ty::ty_bool => T_bool(),
          ty::ty_int(t) => T_int_ty(cx, t),
          ty::ty_uint(t) => T_uint_ty(cx, t),
          ty::ty_float(t) => T_float_ty(cx, t),
          ty::ty_estr(ty::vstore_uniq) => {
            T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
          }
          ty::ty_enum(did, _) => {
            // Only create the named struct, but don't fill it in. We
            // fill it in *after* placing it into the type cache. This
            // avoids creating more than one copy of the enum when one
            // of the enum's variants refers to the enum itself.

            common::T_named_struct(llvm_type_name(cx, t))
          }
          ty::ty_estr(ty::vstore_box) => {
            T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
          }
          ty::ty_evec(mt, ty::vstore_box) => {
            T_box_ptr(T_box(cx, T_vec(cx, type_of(cx, mt.ty))))
          }
          ty::ty_box(mt) => T_box_ptr(T_box(cx, type_of(cx, mt.ty))),
          ty::ty_opaque_box => T_box_ptr(T_box(cx, T_i8())),
          ty::ty_uniq(mt) => T_unique_ptr(T_unique(cx, type_of(cx, mt.ty))),
          ty::ty_evec(mt, ty::vstore_uniq) => {
            T_unique_ptr(T_unique(cx, T_vec(cx, type_of(cx, mt.ty))))
          }
          ty::ty_unboxed_vec(mt) => {
            T_vec(cx, type_of(cx, mt.ty))
          }
          ty::ty_ptr(mt) => T_ptr(type_of(cx, mt.ty)),
          ty::ty_rptr(_, mt) => T_ptr(type_of(cx, mt.ty)),

          ty::ty_evec(mt, ty::vstore_slice(_)) => {
            T_struct(~[T_ptr(type_of(cx, mt.ty)),
                      T_uint_ty(cx, ast::ty_u)])
          }

          ty::ty_estr(ty::vstore_slice(_)) => {
            T_struct(~[T_ptr(T_i8()),
                      T_uint_ty(cx, ast::ty_u)])
          }

          ty::ty_estr(ty::vstore_fixed(n)) => {
            T_array(T_i8(), n + 1u /* +1 for trailing null */)
          }

          ty::ty_evec(mt, ty::vstore_fixed(n)) => {
            T_array(type_of(cx, mt.ty), n)
          }

          ty::ty_rec(fields) => {
            let mut tys: ~[TypeRef] = ~[];
            for vec::each(fields) |f| {
                let mt_ty = f.mt.ty;
                vec::push(tys, type_of(cx, mt_ty));
            }
            T_struct(tys)
          }
          ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
          ty::ty_trait(_, _) => T_opaque_trait(cx),
          ty::ty_type => T_ptr(cx.tydesc_type),
          ty::ty_tup(elts) => {
            let mut tys = ~[];
            for vec::each(elts) |elt| {
                vec::push(tys, type_of(cx, elt));
            }
            T_struct(tys)
          }
          ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
          ty::ty_class(*) => {
            // Only create the named struct, but don't fill it in. We fill it
            // in *after* placing it into the type cache. This prevents
            // infinite recursion with recursive class types.

            common::T_named_struct(llvm_type_name(cx, t))
          }
          ty::ty_self => cx.tcx.sess.unimpl(~"type_of: ty_self"),
          ty::ty_var(_) => cx.tcx.sess.bug(~"type_of with ty_var"),
          ty::ty_param(*) => cx.tcx.sess.bug(~"type_of with ty_param"),
          ty::ty_var_integral(_) => {
            cx.tcx.sess.bug(~"type_of shouldn't see a ty_var_integral");
          }
        };

        cx.lltypes.insert(t, llty);

        // If this was an enum or class, fill in the type now.
        match ty::get(t).struct {
          ty::ty_enum(did, _) => {
              fill_type_of_enum(cx, did, t, llty);
          }
          ty::ty_class(did, ts) => {
            // Only instance vars are record fields at runtime.
            let fields = ty::lookup_class_fields(cx.tcx, did);
            let mut tys = do vec::map(fields) |f| {
                let t = ty::lookup_field_type(cx.tcx, did, f.id, ts);
                type_of(cx, t)
            };

            if ty::ty_dtor(cx.tcx, did) != none {
              // resource type
              tys = ~[T_i8(), T_struct(tys)];
            }

            common::set_struct_body(llty, tys);
          }
          _ => {
            // Nothing more to do.
          }
        }
    };

    return llty;
}

fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t,
                     llty: TypeRef) {

    debug!{"type_of_enum %?: %?", t, ty::get(t)};

    let lltys = {
        let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u;
        let size = shape::static_size_of_enum(cx, t);
        if !degen {
            ~[T_enum_discrim(cx), T_array(T_i8(), size)]
        }
        else if size == 0u {
            ~[T_enum_discrim(cx)]
        }
        else {
            ~[T_array(T_i8(), size)]
        }
    };

    common::set_struct_body(llty, lltys);
}

fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> ~str {
    let (name, did, tps) = match check ty::get(t).struct {
      ty::ty_enum(did, substs) => (~"enum", did, substs.tps),
      ty::ty_class(did, substs) => (~"class", did, substs.tps)
    };
    return fmt!{
        "%s %s[#%d]",
        name,
        util::ppaux::parameterized(
            cx.tcx,
            ty::item_path_str(cx.tcx, did),
            none,
            tps),
        did.crate
    };
}

fn type_of_dtor(ccx: @crate_ctxt, self_ty: ty::t) -> TypeRef {
    T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))),
          T_ptr(type_of(ccx, self_ty))],
         llvm::LLVMVoidType())
}

<commit_msg>rustc: Cosmetic change to type_of to make control flow more obvious.<commit_after>import common::*;
import lib::llvm::{TypeRef};
import syntax::ast;
import lib::llvm::llvm;
import driver::session::session;
import std::map::hashmap;

export type_of;
export type_of_dtor;
export type_of_explicit_args;
export type_of_fn_from_ty;
export type_of_fn;
export type_of_non_gc_box;

fn type_of_explicit_args(cx: @crate_ctxt,
                         inputs: ~[ty::arg]) -> ~[TypeRef] {
    do vec::map(inputs) |arg| {
        let arg_ty = arg.ty;
        let llty = type_of(cx, arg_ty);
        match ty::resolved_mode(cx.tcx, arg.mode) {
          ast::by_val => llty,
          _ => T_ptr(llty)
        }
    }
}

fn type_of_fn(cx: @crate_ctxt, inputs: ~[ty::arg],
              output: ty::t) -> TypeRef {
    let mut atys: ~[TypeRef] = ~[];

    // Arg 0: Output pointer.
    vec::push(atys, T_ptr(type_of(cx, output)));

    // Arg 1: Environment
    vec::push(atys, T_opaque_box_ptr(cx));

    // ... then explicit args.
    vec::push_all(atys, type_of_explicit_args(cx, inputs));
    return T_fn(atys, llvm::LLVMVoidType());
}

// Given a function type and a count of ty params, construct an llvm type
fn type_of_fn_from_ty(cx: @crate_ctxt, fty: ty::t) -> TypeRef {
    type_of_fn(cx, ty::ty_fn_args(fty), ty::ty_fn_ret(fty))
}

fn type_of_non_gc_box(cx: @crate_ctxt, t: ty::t) -> TypeRef {
    assert !ty::type_needs_infer(t);

    let t_norm = ty::normalize_ty(cx.tcx, t);
    if t != t_norm {
        type_of_non_gc_box(cx, t_norm)
    } else {
        match ty::get(t).struct {
          ty::ty_box(mt) => {
            T_ptr(T_box(cx, type_of(cx, mt.ty)))
          }
          ty::ty_uniq(mt) => {
            T_ptr(T_unique(cx, type_of(cx, mt.ty)))
          }
          _ => {
            cx.sess.bug(~"non-box in type_of_non_gc_box");
          }
        }
    }
}

fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
    debug!{"type_of %?: %?", t, ty::get(t)};

    // Check the cache.
    if cx.lltypes.contains_key(t) { return cx.lltypes.get(t); }

    // Replace any typedef'd types with their equivalent non-typedef
    // type. This ensures that all LLVM nominal types that contain
    // Rust types are defined as the same LLVM types.  If we don't do
    // this then, e.g. `option<{myfield: bool}>` would be a different
    // type than `option<myrec>`.
    let t_norm = ty::normalize_ty(cx.tcx, t);

    if t != t_norm {
        let llty = type_of(cx, t_norm);
        cx.lltypes.insert(t, llty);
        return llty;
    }

    let llty = match ty::get(t).struct {
      ty::ty_nil | ty::ty_bot => T_nil(),
      ty::ty_bool => T_bool(),
      ty::ty_int(t) => T_int_ty(cx, t),
      ty::ty_uint(t) => T_uint_ty(cx, t),
      ty::ty_float(t) => T_float_ty(cx, t),
      ty::ty_estr(ty::vstore_uniq) => {
        T_unique_ptr(T_unique(cx, T_vec(cx, T_i8())))
      }
      ty::ty_enum(did, _) => {
        // Only create the named struct, but don't fill it in. We
        // fill it in *after* placing it into the type cache. This
        // avoids creating more than one copy of the enum when one
        // of the enum's variants refers to the enum itself.

        common::T_named_struct(llvm_type_name(cx, t))
      }
      ty::ty_estr(ty::vstore_box) => {
        T_box_ptr(T_box(cx, T_vec(cx, T_i8())))
      }
      ty::ty_evec(mt, ty::vstore_box) => {
        T_box_ptr(T_box(cx, T_vec(cx, type_of(cx, mt.ty))))
      }
      ty::ty_box(mt) => T_box_ptr(T_box(cx, type_of(cx, mt.ty))),
      ty::ty_opaque_box => T_box_ptr(T_box(cx, T_i8())),
      ty::ty_uniq(mt) => T_unique_ptr(T_unique(cx, type_of(cx, mt.ty))),
      ty::ty_evec(mt, ty::vstore_uniq) => {
        T_unique_ptr(T_unique(cx, T_vec(cx, type_of(cx, mt.ty))))
      }
      ty::ty_unboxed_vec(mt) => {
        T_vec(cx, type_of(cx, mt.ty))
      }
      ty::ty_ptr(mt) => T_ptr(type_of(cx, mt.ty)),
      ty::ty_rptr(_, mt) => T_ptr(type_of(cx, mt.ty)),

      ty::ty_evec(mt, ty::vstore_slice(_)) => {
        T_struct(~[T_ptr(type_of(cx, mt.ty)),
                   T_uint_ty(cx, ast::ty_u)])
      }

      ty::ty_estr(ty::vstore_slice(_)) => {
        T_struct(~[T_ptr(T_i8()),
                   T_uint_ty(cx, ast::ty_u)])
      }

      ty::ty_estr(ty::vstore_fixed(n)) => {
        T_array(T_i8(), n + 1u /* +1 for trailing null */)
      }

      ty::ty_evec(mt, ty::vstore_fixed(n)) => {
        T_array(type_of(cx, mt.ty), n)
      }

      ty::ty_rec(fields) => {
        let mut tys: ~[TypeRef] = ~[];
        for vec::each(fields) |f| {
            let mt_ty = f.mt.ty;
            vec::push(tys, type_of(cx, mt_ty));
        }
        T_struct(tys)
      }
      ty::ty_fn(_) => T_fn_pair(cx, type_of_fn_from_ty(cx, t)),
      ty::ty_trait(_, _) => T_opaque_trait(cx),
      ty::ty_type => T_ptr(cx.tydesc_type),
      ty::ty_tup(elts) => {
        let mut tys = ~[];
        for vec::each(elts) |elt| {
            vec::push(tys, type_of(cx, elt));
        }
        T_struct(tys)
      }
      ty::ty_opaque_closure_ptr(_) => T_opaque_box_ptr(cx),
      ty::ty_class(*) => {
        // Only create the named struct, but don't fill it in. We fill it
        // in *after* placing it into the type cache. This prevents
        // infinite recursion with recursive class types.

        common::T_named_struct(llvm_type_name(cx, t))
      }
      ty::ty_self => cx.tcx.sess.unimpl(~"type_of: ty_self"),
      ty::ty_var(_) => cx.tcx.sess.bug(~"type_of with ty_var"),
      ty::ty_param(*) => cx.tcx.sess.bug(~"type_of with ty_param"),
      ty::ty_var_integral(_) => {
        cx.tcx.sess.bug(~"type_of shouldn't see a ty_var_integral");
      }
    };

    cx.lltypes.insert(t, llty);

    // If this was an enum or class, fill in the type now.
    match ty::get(t).struct {
      ty::ty_enum(did, _) => {
        fill_type_of_enum(cx, did, t, llty);
      }
      ty::ty_class(did, ts) => {
        // Only instance vars are record fields at runtime.
        let fields = ty::lookup_class_fields(cx.tcx, did);
        let mut tys = do vec::map(fields) |f| {
            let t = ty::lookup_field_type(cx.tcx, did, f.id, ts);
            type_of(cx, t)
        };

        if ty::ty_dtor(cx.tcx, did) != none {
            // resource type
            tys = ~[T_i8(), T_struct(tys)];
        }

        common::set_struct_body(llty, tys);
      }
      _ => ()
    }

    return llty;
}

fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t,
                     llty: TypeRef) {

    debug!{"type_of_enum %?: %?", t, ty::get(t)};

    let lltys = {
        let degen = (*ty::enum_variants(cx.tcx, did)).len() == 1u;
        let size = shape::static_size_of_enum(cx, t);
        if !degen {
            ~[T_enum_discrim(cx), T_array(T_i8(), size)]
        }
        else if size == 0u {
            ~[T_enum_discrim(cx)]
        }
        else {
            ~[T_array(T_i8(), size)]
        }
    };

    common::set_struct_body(llty, lltys);
}

fn llvm_type_name(cx: @crate_ctxt, t: ty::t) -> ~str {
    let (name, did, tps) = match check ty::get(t).struct {
      ty::ty_enum(did, substs) => (~"enum", did, substs.tps),
      ty::ty_class(did, substs) => (~"class", did, substs.tps)
    };
    return fmt!{
        "%s %s[#%d]",
        name,
        util::ppaux::parameterized(
            cx.tcx,
            ty::item_path_str(cx.tcx, did),
            none,
            tps),
        did.crate
    };
}

fn type_of_dtor(ccx: @crate_ctxt, self_ty: ty::t) -> TypeRef {
    T_fn(~[T_ptr(type_of(ccx, ty::mk_nil(ccx.tcx))),
          T_ptr(type_of(ccx, self_ty))],
         llvm::LLVMVoidType())
}

<|endoftext|>


<commit_before>// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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.

//! Utilities for working with packets, eg. checksumming.

use ip::IpNextHeaderProtocol;
use pnet_macros_support::types::u16be;

use std::net::{Ipv4Addr, Ipv6Addr};
use std::slice;
use std::u8;

/// Convert a value to a byte array.
pub trait Octets {
    /// Output type - bytes array.
    type Output;

    /// Return a value as bytes (big-endian order).
    fn octets(&self) -> Self::Output;
}

impl Octets for u64 {
    type Output = [u8; 8];

    fn octets(&self) -> Self::Output {
        [(*self >> 56) as u8,
         (*self >> 48) as u8,
         (*self >> 40) as u8,
         (*self >> 32) as u8,
         (*self >> 24) as u8,
         (*self >> 16) as u8,
         (*self >> 8) as u8,
         *self as u8]
    }
}

impl Octets for u32 {
    type Output = [u8; 4];

    fn octets(&self) -> Self::Output {
        [(*self >> 24) as u8, (*self >> 16) as u8, (*self >> 8) as u8, *self as u8]
    }
}

impl Octets for u16 {
    type Output = [u8; 2];

    fn octets(&self) -> Self::Output {
        [(*self >> 8) as u8, *self as u8]
    }
}

impl Octets for u8 {
    type Output = [u8; 1];

    fn octets(&self) -> Self::Output {
        [*self]
    }
}

/// Calculates a checksum. Used by ipv4 and icmp. The two bytes starting at `skipword * 2` will be
/// ignored. Supposed to be the checksum field, which is regarded as zero during calculation.
pub fn checksum(data: &[u8], skipword: usize) -> u16be {
    let sum = sum_be_words(data, skipword);
    finalize_checksum(sum)
}

fn finalize_checksum(mut sum: u32) -> u16be {
    while sum >> 16 != 0 {
        sum = (sum >> 16) + (sum & 0xFFFF);
    }
    !sum as u16
}

/// Calculate the checksum for a packet built on IPv4. Used by UDP and TCP.
pub fn ipv4_checksum(data: &[u8],
                     skipword: usize,
                     extra_data: &[u8],
                     source: &Ipv4Addr,
                     destination: &Ipv4Addr,
                     next_level_protocol: IpNextHeaderProtocol)
    -> u16be {
    let mut sum = 0u32;

    // Checksum pseudo-header
    sum += ipv4_word_sum(source);
    sum += ipv4_word_sum(destination);

    let IpNextHeaderProtocol(next_level_protocol) = next_level_protocol;
    sum += next_level_protocol as u32;

    let len = data.len() + extra_data.len();
    sum += len as u32;

    // Checksum packet header and data
    sum += sum_be_words(data, skipword);
    sum += sum_be_words(extra_data, extra_data.len() / 2);

    finalize_checksum(sum)
}

fn ipv4_word_sum(ip: &Ipv4Addr) -> u32 {
    let octets = ip.octets();
    ((octets[0] as u32) << 8 | octets[1] as u32) + ((octets[2] as u32) << 8 | octets[3] as u32)
}

/// Calculate the checksum for a packet built on IPv6.
pub fn ipv6_checksum(data: &[u8],
                     skipword: usize,
                     extra_data: &[u8],
                     source: &Ipv6Addr,
                     destination: &Ipv6Addr,
                     next_level_protocol: IpNextHeaderProtocol)
    -> u16be {
    let mut sum = 0u32;

    // Checksum pseudo-header
    sum += ipv6_word_sum(source);
    sum += ipv6_word_sum(destination);

    let IpNextHeaderProtocol(next_level_protocol) = next_level_protocol;
    sum += next_level_protocol as u32;

    let len = data.len() + extra_data.len();
    sum += len as u32;

    // Checksum packet header and data
    sum += sum_be_words(data, skipword);
    sum += sum_be_words(extra_data, extra_data.len() / 2);

    finalize_checksum(sum)
}

fn ipv6_word_sum(ip: &Ipv6Addr) -> u32 {
    ip.segments().iter().map(|x| *x as u32).sum()
}

/// Sum all words (16 bit chunks) in the given data. The word at word offset
/// `skipword` will be skipped. Each word is treated as big endian.
fn sum_be_words(data: &[u8], mut skipword: usize) -> u32 {
    let len = data.len();
    let wdata: &[u16] = unsafe { slice::from_raw_parts(data.as_ptr() as *const u16, len / 2) };
    skipword = ::std::cmp::min(skipword, wdata.len());

    let mut sum = 0u32;
    let mut i = 0;
    while i < skipword {
        sum += u16::from_be(unsafe { *wdata.get_unchecked(i) }) as u32;
        i += 1;
    }
    i += 1;
    while i < wdata.len() {
        sum += u16::from_be(unsafe { *wdata.get_unchecked(i) }) as u32;
        i += 1;
    }
    // If the length is odd, make sure to checksum the final byte
    if len & 1 != 0 {
        sum += (unsafe { *data.get_unchecked(len - 1) } as u32) << 8;
    }

    sum
}

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

    #[test]
    fn sum_be_words_different_skipwords() {
        let data = (0..11).collect::<Vec<u8>>();
        assert_eq!(7190, sum_be_words(&data, 1));
        assert_eq!(6676, sum_be_words(&data, 2));
        // Assert having the skipword outside the range gives correct and equal
        // results
        assert_eq!(7705, sum_be_words(&data, 99));
        assert_eq!(7705, sum_be_words(&data, 101));
    }
}

#[cfg(all(test, feature = "benchmark"))]
mod checksum_benchmarks {
    use super::checksum;
    use test::{Bencher, black_box};

    #[bench]
    fn bench_checksum_small(b: &mut Bencher) {
        let data = vec![99u8; 20];
        b.iter(|| checksum(black_box(&data), 5));
    }

    #[bench]
    fn bench_checksum_large(b: &mut Bencher) {
        let data = vec![123u8; 1024];
        b.iter(|| checksum(black_box(&data), 5));
    }
}

<commit_msg>enforce checksum safety with assert<commit_after>// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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.

//! Utilities for working with packets, eg. checksumming.

use ip::IpNextHeaderProtocol;
use pnet_macros_support::types::u16be;

use std::net::{Ipv4Addr, Ipv6Addr};
use std::slice;
use std::u8;

/// Convert a value to a byte array.
pub trait Octets {
    /// Output type - bytes array.
    type Output;

    /// Return a value as bytes (big-endian order).
    fn octets(&self) -> Self::Output;
}

impl Octets for u64 {
    type Output = [u8; 8];

    fn octets(&self) -> Self::Output {
        [(*self >> 56) as u8,
         (*self >> 48) as u8,
         (*self >> 40) as u8,
         (*self >> 32) as u8,
         (*self >> 24) as u8,
         (*self >> 16) as u8,
         (*self >> 8) as u8,
         *self as u8]
    }
}

impl Octets for u32 {
    type Output = [u8; 4];

    fn octets(&self) -> Self::Output {
        [(*self >> 24) as u8, (*self >> 16) as u8, (*self >> 8) as u8, *self as u8]
    }
}

impl Octets for u16 {
    type Output = [u8; 2];

    fn octets(&self) -> Self::Output {
        [(*self >> 8) as u8, *self as u8]
    }
}

impl Octets for u8 {
    type Output = [u8; 1];

    fn octets(&self) -> Self::Output {
        [*self]
    }
}

/// Calculates a checksum. Used by ipv4 and icmp. The two bytes starting at `skipword * 2` will be
/// ignored. Supposed to be the checksum field, which is regarded as zero during calculation. Will
/// panic if data is not u16-aligned.
pub fn checksum(data: &[u8], skipword: usize) -> u16be {
    if data.len() == 0 { return 0 }
    assert_eq!(0, data.as_ptr() as usize % 2, "Cannot sum mis-aligned words at {:p}", data.as_ptr());
    let sum = sum_be_words(data, skipword);
    finalize_checksum(sum)
}

fn finalize_checksum(mut sum: u32) -> u16be {
    while sum >> 16 != 0 {
        sum = (sum >> 16) + (sum & 0xFFFF);
    }
    !sum as u16
}

/// Calculate the checksum for a packet built on IPv4. Used by UDP and TCP.
pub fn ipv4_checksum(data: &[u8],
                     skipword: usize,
                     extra_data: &[u8],
                     source: &Ipv4Addr,
                     destination: &Ipv4Addr,
                     next_level_protocol: IpNextHeaderProtocol)
    -> u16be {
    let mut sum = 0u32;

    // Checksum pseudo-header
    sum += ipv4_word_sum(source);
    sum += ipv4_word_sum(destination);

    let IpNextHeaderProtocol(next_level_protocol) = next_level_protocol;
    sum += next_level_protocol as u32;

    let len = data.len() + extra_data.len();
    sum += len as u32;

    // Checksum packet header and data
    sum += sum_be_words(data, skipword);
    sum += sum_be_words(extra_data, extra_data.len() / 2);

    finalize_checksum(sum)
}

fn ipv4_word_sum(ip: &Ipv4Addr) -> u32 {
    let octets = ip.octets();
    ((octets[0] as u32) << 8 | octets[1] as u32) + ((octets[2] as u32) << 8 | octets[3] as u32)
}

/// Calculate the checksum for a packet built on IPv6.
pub fn ipv6_checksum(data: &[u8],
                     skipword: usize,
                     extra_data: &[u8],
                     source: &Ipv6Addr,
                     destination: &Ipv6Addr,
                     next_level_protocol: IpNextHeaderProtocol)
    -> u16be {
    let mut sum = 0u32;

    // Checksum pseudo-header
    sum += ipv6_word_sum(source);
    sum += ipv6_word_sum(destination);

    let IpNextHeaderProtocol(next_level_protocol) = next_level_protocol;
    sum += next_level_protocol as u32;

    let len = data.len() + extra_data.len();
    sum += len as u32;

    // Checksum packet header and data
    sum += sum_be_words(data, skipword);
    sum += sum_be_words(extra_data, extra_data.len() / 2);

    finalize_checksum(sum)
}

fn ipv6_word_sum(ip: &Ipv6Addr) -> u32 {
    ip.segments().iter().map(|x| *x as u32).sum()
}

/// Sum all words (16 bit chunks) in the given data. The word at word offset
/// `skipword` will be skipped. Each word is treated as big endian. Must be
/// called with u16-aligned data.
fn sum_be_words(data: &[u8], mut skipword: usize) -> u32 {
    if data.len() == 0 { return 0 }
    debug_assert_eq!(0, data.as_ptr() as usize % 2, "Cannot sum mis-aligned words at {:p}", data.as_ptr());
    let len = data.len();
    let wdata: &[u16] = unsafe { slice::from_raw_parts(data.as_ptr() as *const u16, len / 2) };
    skipword = ::std::cmp::min(skipword, wdata.len());

    let mut sum = 0u32;
    let mut i = 0;
    while i < skipword {
        sum += u16::from_be(unsafe { *wdata.get_unchecked(i) }) as u32;
        i += 1;
    }
    i += 1;
    while i < wdata.len() {
        sum += u16::from_be(unsafe { *wdata.get_unchecked(i) }) as u32;
        i += 1;
    }
    // If the length is odd, make sure to checksum the final byte
    if len & 1 != 0 {
        sum += (unsafe { *data.get_unchecked(len - 1) } as u32) << 8;
    }

    sum
}

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

    #[test]
    fn sum_be_words_different_skipwords() {
        let data = (0..11).collect::<Vec<u8>>();
        assert_eq!(7190, sum_be_words(&data, 1));
        assert_eq!(6676, sum_be_words(&data, 2));
        // Assert having the skipword outside the range gives correct and equal
        // results
        assert_eq!(7705, sum_be_words(&data, 99));
        assert_eq!(7705, sum_be_words(&data, 101));
    }
}

#[cfg(all(test, feature = "benchmark"))]
mod checksum_benchmarks {
    use super::checksum;
    use test::{Bencher, black_box};

    #[bench]
    fn bench_checksum_small(b: &mut Bencher) {
        let data = vec![99u8; 20];
        b.iter(|| checksum(black_box(&data), 5));
    }

    #[bench]
    fn bench_checksum_large(b: &mut Bencher) {
        let data = vec![123u8; 1024];
        b.iter(|| checksum(black_box(&data), 5));
    }
}

<|endoftext|>


<commit_before>//! Various simple lock-free data structures built on `conc`

mod stm;
mod treiber;

pub use self::stm::Stm;
pub use self::treiber::Treiber;
<commit_msg>Add dot to doc comment of `conc::sync`.<commit_after>//! Various simple lock-free data structures built on `conc`.

mod stm;
mod treiber;

pub use self::stm::Stm;
pub use self::treiber::Treiber;
<|endoftext|>


<commit_before>// spell-checker:ignore (URL) appspot

use crate::numeric::*;

pub(crate) trait Basis {
    const BASIS: &'static [u64];
}

impl Basis for Montgomery<u64> {
    // Small set of bases for the Miller-Rabin prime test, valid for all 64b integers;
    //  discovered by Jim Sinclair on 2011-04-20, see miller-rabin.appspot.com
    #[allow(clippy::unreadable_literal)]
    const BASIS: &'static [u64] = &[2, 325, 9375, 28178, 450775, 9780504, 1795265022];
}

impl Basis for Montgomery<u32> {
    // Small set of bases for the Miller-Rabin prime test, valid for all 32b integers;
    //  discovered by Steve Worley on 2013-05-27, see miller-rabin.appspot.com
    #[allow(clippy::unreadable_literal)]
    const BASIS: &'static [u64] = &[
        4230279247111683200,
        14694767155120705706,
        16641139526367750375,
    ];
}

#[derive(Eq, PartialEq)]
pub(crate) enum Result {
    Prime,
    Pseudoprime,
    Composite(u64),
}

impl Result {
    pub(crate) fn is_prime(&self) -> bool {
        *self == Result::Prime
    }
}

// Deterministic Miller-Rabin primality-checking algorithm, adapted to extract
// (some) dividers; it will fail to factor strong pseudoprimes.
#[allow(clippy::many_single_char_names)]
pub(crate) fn test<A: Arithmetic + Basis>(m: A) -> Result {
    use self::Result::*;

    let n = m.modulus();
    if n < 2 {
        return Pseudoprime;
    }
    if n % 2 == 0 {
        return if n == 2 { Prime } else { Composite(2) };
    }

    // n-1 = r 2ⁱ
    let i = (n - 1).trailing_zeros();
    let r = (n - 1) >> i;

    let one = m.one();
    let minus_one = m.minus_one();

    for _a in A::BASIS.iter() {
        let _a = _a % n;
        if _a == 0 {
            break;
        }

        let a = m.from_u64(_a);

        // x = a^r mod n
        let mut x = m.pow(a, r);

        {
            // y = ((x²)²...)² i times = x ^ (2ⁱ) = a ^ (r 2ⁱ) = x ^ (n - 1)
            let mut y = x;
            for _ in 0..i {
                y = m.mul(y, y)
            }
            if y != one {
                return Pseudoprime;
            };
        }

        if x == one || x == minus_one {
            continue;
        }

        loop {
            let y = m.mul(x, x);
            if y == one {
                return Composite(gcd(m.to_u64(x) - 1, m.modulus()));
            }
            if y == minus_one {
                // This basis element is not a witness of `n` being composite.
                // Keep looking.
                break;
            }
            x = y;
        }
    }

    Prime
}

// Used by build.rs' tests and debug assertions
#[allow(dead_code)]
pub(crate) fn is_prime(n: u64) -> bool {
    if n % 2 == 0 {
        n == 2
    } else {
        test::<Montgomery<u64>>(Montgomery::new(n)).is_prime()
    }
}

#[cfg(test)]
mod tests {
    use super::is_prime;
    const LARGEST_U64_PRIME: u64 = 0xFFFFFFFFFFFFFFC5;

    fn primes() -> impl Iterator<Item = u64> {
        use crate::table::{NEXT_PRIME, P_INVS_U64};
        use std::iter::once;
        once(2)
            .chain(P_INVS_U64.iter().map(|(p, _, _)| *p))
            .chain(once(NEXT_PRIME))
    }

    #[test]
    fn largest_prime() {
        assert!(is_prime(LARGEST_U64_PRIME));
    }

    #[test]
    fn largest_composites() {
        for i in LARGEST_U64_PRIME + 1..=u64::MAX {
            assert!(!is_prime(i), "2⁶⁴ - {} reported prime", u64::MAX - i + 1);
        }
    }

    #[test]
    fn first_primes() {
        for p in primes() {
            assert!(is_prime(p), "{} reported composite", p);
        }
    }

    #[test]
    fn issue_1556() {
        // 10 425 511 = 2441 × 4271
        assert!(!is_prime(10_425_511));
    }

    #[test]
    fn small_composites() {
        for p in primes() {
            for q in primes().take_while(|q| *q <= p) {
                let n = p * q;
                assert!(!is_prime(n), "{} = {} × {} reported prime", n, p, q);
            }
        }
    }
}
<commit_msg>factor::miller_rabin: Add negative test over all small composites<commit_after>// spell-checker:ignore (URL) appspot

use crate::numeric::*;

pub(crate) trait Basis {
    const BASIS: &'static [u64];
}

impl Basis for Montgomery<u64> {
    // Small set of bases for the Miller-Rabin prime test, valid for all 64b integers;
    //  discovered by Jim Sinclair on 2011-04-20, see miller-rabin.appspot.com
    #[allow(clippy::unreadable_literal)]
    const BASIS: &'static [u64] = &[2, 325, 9375, 28178, 450775, 9780504, 1795265022];
}

impl Basis for Montgomery<u32> {
    // Small set of bases for the Miller-Rabin prime test, valid for all 32b integers;
    //  discovered by Steve Worley on 2013-05-27, see miller-rabin.appspot.com
    #[allow(clippy::unreadable_literal)]
    const BASIS: &'static [u64] = &[
        4230279247111683200,
        14694767155120705706,
        16641139526367750375,
    ];
}

#[derive(Eq, PartialEq)]
pub(crate) enum Result {
    Prime,
    Pseudoprime,
    Composite(u64),
}

impl Result {
    pub(crate) fn is_prime(&self) -> bool {
        *self == Result::Prime
    }
}

// Deterministic Miller-Rabin primality-checking algorithm, adapted to extract
// (some) dividers; it will fail to factor strong pseudoprimes.
#[allow(clippy::many_single_char_names)]
pub(crate) fn test<A: Arithmetic + Basis>(m: A) -> Result {
    use self::Result::*;

    let n = m.modulus();
    if n < 2 {
        return Pseudoprime;
    }
    if n % 2 == 0 {
        return if n == 2 { Prime } else { Composite(2) };
    }

    // n-1 = r 2ⁱ
    let i = (n - 1).trailing_zeros();
    let r = (n - 1) >> i;

    let one = m.one();
    let minus_one = m.minus_one();

    for _a in A::BASIS.iter() {
        let _a = _a % n;
        if _a == 0 {
            break;
        }

        let a = m.from_u64(_a);

        // x = a^r mod n
        let mut x = m.pow(a, r);

        {
            // y = ((x²)²...)² i times = x ^ (2ⁱ) = a ^ (r 2ⁱ) = x ^ (n - 1)
            let mut y = x;
            for _ in 0..i {
                y = m.mul(y, y)
            }
            if y != one {
                return Pseudoprime;
            };
        }

        if x == one || x == minus_one {
            continue;
        }

        loop {
            let y = m.mul(x, x);
            if y == one {
                return Composite(gcd(m.to_u64(x) - 1, m.modulus()));
            }
            if y == minus_one {
                // This basis element is not a witness of `n` being composite.
                // Keep looking.
                break;
            }
            x = y;
        }
    }

    Prime
}

// Used by build.rs' tests and debug assertions
#[allow(dead_code)]
pub(crate) fn is_prime(n: u64) -> bool {
    if n % 2 == 0 {
        n == 2
    } else {
        test::<Montgomery<u64>>(Montgomery::new(n)).is_prime()
    }
}

#[cfg(test)]
mod tests {
    use super::is_prime;
    const LARGEST_U64_PRIME: u64 = 0xFFFFFFFFFFFFFFC5;

    fn primes() -> impl Iterator<Item = u64> {
        use crate::table::{NEXT_PRIME, P_INVS_U64};
        use std::iter::once;
        once(2)
            .chain(P_INVS_U64.iter().map(|(p, _, _)| *p))
            .chain(once(NEXT_PRIME))
    }

    #[test]
    fn largest_prime() {
        assert!(is_prime(LARGEST_U64_PRIME));
    }

    #[test]
    fn largest_composites() {
        for i in LARGEST_U64_PRIME + 1..=u64::MAX {
            assert!(!is_prime(i), "2⁶⁴ - {} reported prime", u64::MAX - i + 1);
        }
    }

    #[test]
    fn first_primes() {
        for p in primes() {
            assert!(is_prime(p), "{} reported composite", p);
        }
    }

    #[test]
    fn first_composites() {
        assert!(!is_prime(0));
        assert!(!is_prime(1));

        for (p, q) in primes().zip(primes().skip(1)) {
            for i in p + 1..q {
                assert!(!is_prime(i), "{} reported prime", i);
            }
        }
    }

    #[test]
    fn issue_1556() {
        // 10 425 511 = 2441 × 4271
        assert!(!is_prime(10_425_511));
    }

    #[test]
    fn small_composites() {
        for p in primes() {
            for q in primes().take_while(|q| *q <= p) {
                let n = p * q;
                assert!(!is_prime(n), "{} = {} × {} reported prime", n, p, q);
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate file;
extern crate fall_gen;
extern crate lang_fall;
extern crate fall_tree;

use std::error::Error;
use std::io::Write;
use std::path::PathBuf;
use std::fs;
use std::process::{Command, Stdio};

use clap::{App, Arg};

enum Task {
    Generate(PathBuf),
    Examples(PathBuf)
}

fn main() {
    let matches = App::new("Fall parser generator")
        .arg(Arg::with_name("grammar").index(1).required(true))
        .arg(Arg::with_name("examples").long("examples"))
        .get_matches();
    let grammar = PathBuf::from(matches.value_of("grammar").unwrap());
    let command = if matches.is_present("examples") {
        Task::Examples(grammar)
    } else {
        Task::Generate(grammar)
    };

    let return_code = if let Err(e) = main_inner(command) {
        writeln!(::std::io::stderr(), "Error occurred: {}", e).unwrap();
        101
    } else {
        0
    };
    std::process::exit(return_code)
}

fn main_inner(command: Task) -> Result<(), Box<Error>> {
    match command {
        Task::Generate(grammar) => {
            let input = file::get_text(&grammar)?;
            let file = lang_fall::LANG_FALL.parse(input);
            let ast = lang_fall::ast(&file);
            let result = fall_gen::generate(ast)?;
            file::put_text(grammar.with_extension("rs"), result)?;
        }
        Task::Examples(grammar) => {
            let input = file::get_text(&grammar)?;
            let result = render_examples(input)?;
            file::put_text(grammar.with_extension("txt"), result)?;
        }
    }
    Ok(())
}

fn render_examples(grammar: String) -> Result<String, Box<Error>> {
    let file = lang_fall::LANG_FALL.parse(grammar);
    let ast = lang_fall::ast(&file);
    let parser = fall_gen::generate(ast)?;
    let example = match ast.examples().next() {
        Some(ex) => ex.contents().to_string(),
        None => return Ok("".to_owned())
    };

    let base_dir = base_directory()?;
    let syntax = base_dir.join("src").join("syntax.rs");
    file::put_text(&syntax, parser)?;
    let toml = base_dir.join("Cargo.toml");
    file::put_text(&toml, format!(r##"
        [package]
        name = "fall_examples"
        version = "0.1.0"
        authors = []

        [workspace]

        [dependencies]
        regex = "0.2"
        serde_json = "1.*"
        lazy_static = "0.2"

        fall_tree = {{ path = "{fall_dir}/fall_tree" }}
        fall_parse = {{ path = "{fall_dir}/fall_parse" }}
    "##, fall_dir = fall_dir().display()))?;
    file::put_text(&base_dir.join("src").join("main.rs"), r##"
        extern crate regex;
        extern crate fall_tree;
        extern crate fall_parse;
        #[macro_use]
        extern crate lazy_static;
        extern crate serde_json;
        mod syntax;

        use std::io::Read;

        fn main() {
            let mut input = String::new();
            ::std::io::stdin().read_to_string(&mut input).unwrap();
            let file = syntax::LANG.parse(input);
            println!("{}", fall_tree::dump_file(&file));
        }
    "##)?;

    let build = Command::new("cargo")
        .arg("build")
        .arg("--manifest-path")
        .arg(&toml)
        .spawn()?
        .wait_with_output()?;

    if !build.status.success() {
        return Ok(String::from_utf8(build.stderr).unwrap());
    }

    let mut child = Command::new("cargo")
        .arg("run")
        .arg("--manifest-path")
        .arg(&toml)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()?;

    {
        let mut stdin = child.stdin.as_mut().unwrap();
        stdin.write_all(example.as_bytes()).unwrap();
        stdin.flush().unwrap();
    }

    let rendered = child.wait_with_output()?;
    assert!(rendered.status.success());
    let out = String::from_utf8(rendered.stdout).unwrap();
    Ok(out)
}

fn base_directory() -> Result<PathBuf, Box<Error>> {
    let result = PathBuf::from("./fall-examples");
    fs::create_dir_all(&result)?;
    fs::create_dir_all(&result.join("src"))?;
    Ok(result)
}

fn fall_dir() -> PathBuf {
    let dir = env!("CARGO_MANIFEST_DIR");
    PathBuf::from(dir).parent().unwrap().to_owned()
}
<commit_msg>Reuse temp directory<commit_after>extern crate clap;
extern crate file;
extern crate fall_gen;
extern crate lang_fall;
extern crate fall_tree;

use std::error::Error;
use std::io::Write;
use std::path::PathBuf;
use std::fs;
use std::process::{Command, Stdio};

use clap::{App, Arg};

enum Task {
    Generate(PathBuf),
    Examples(PathBuf)
}

fn main() {
    let matches = App::new("Fall parser generator")
        .arg(Arg::with_name("grammar").index(1).required(true))
        .arg(Arg::with_name("examples").long("examples"))
        .get_matches();
    let grammar = PathBuf::from(matches.value_of("grammar").unwrap());
    let command = if matches.is_present("examples") {
        Task::Examples(grammar)
    } else {
        Task::Generate(grammar)
    };

    let return_code = if let Err(e) = main_inner(command) {
        writeln!(::std::io::stderr(), "Error occurred: {}", e).unwrap();
        101
    } else {
        0
    };
    std::process::exit(return_code)
}

fn main_inner(command: Task) -> Result<(), Box<Error>> {
    match command {
        Task::Generate(grammar) => {
            let input = file::get_text(&grammar)?;
            let file = lang_fall::LANG_FALL.parse(input);
            let ast = lang_fall::ast(&file);
            let result = fall_gen::generate(ast)?;
            file::put_text(grammar.with_extension("rs"), result)?;
        }
        Task::Examples(grammar) => {
            let input = file::get_text(&grammar)?;
            let result = render_examples(input)?;
            file::put_text(grammar.with_extension("txt"), result)?;
        }
    }
    Ok(())
}

fn render_examples(grammar: String) -> Result<String, Box<Error>> {
    let file = lang_fall::LANG_FALL.parse(grammar);
    let ast = lang_fall::ast(&file);
    let parser = fall_gen::generate(ast)?;
    let example = match ast.examples().next() {
        Some(ex) => ex.contents().to_string(),
        None => return Ok("".to_owned())
    };

    let base_dir = base_directory()?;
    let syntax = base_dir.join("src").join("syntax.rs");
    file::put_text(&syntax, parser)?;
    let toml = base_dir.join("Cargo.toml");
    file::put_text(&toml, format!(r##"
        [package]
        name = "fall_examples"
        version = "0.1.0"
        authors = []

        [workspace]

        [dependencies]
        regex = "0.2"
        serde_json = "1.*"
        lazy_static = "0.2"

        fall_tree = {{ path = "{fall_dir}/fall_tree" }}
        fall_parse = {{ path = "{fall_dir}/fall_parse" }}
    "##, fall_dir = fall_dir().display()))?;
    file::put_text(&base_dir.join("src").join("main.rs"), r##"
        extern crate regex;
        extern crate fall_tree;
        extern crate fall_parse;
        #[macro_use]
        extern crate lazy_static;
        extern crate serde_json;
        mod syntax;

        use std::io::Read;

        fn main() {
            let mut input = String::new();
            ::std::io::stdin().read_to_string(&mut input).unwrap();
            let file = syntax::LANG.parse(input);
            println!("{}", fall_tree::dump_file(&file));
        }
    "##)?;

    let build = Command::new("cargo")
        .arg("build")
        .arg("--manifest-path")
        .arg(&toml)
        .spawn()?
        .wait_with_output()?;

    if !build.status.success() {
        return Ok(String::from_utf8(build.stderr).unwrap());
    }

    let mut child = Command::new("cargo")
        .arg("run")
        .arg("--manifest-path")
        .arg(&toml)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()?;

    {
        let mut stdin = child.stdin.as_mut().unwrap();
        stdin.write_all(example.as_bytes()).unwrap();
        stdin.flush().unwrap();
    }

    let rendered = child.wait_with_output()?;
    assert!(rendered.status.success());
    let out = String::from_utf8(rendered.stdout).unwrap();
    Ok(out)
}

fn base_directory() -> Result<PathBuf, Box<Error>> {
    let result = ::std::env::temp_dir().join("fall-examples");
    fs::create_dir_all(&result)?;
    fs::create_dir_all(&result.join("src"))?;
    Ok(result)
}

fn fall_dir() -> PathBuf {
    let dir = env!("CARGO_MANIFEST_DIR");
    PathBuf::from(dir).parent().unwrap().to_owned()
}
<|endoftext|>


<commit_before>extern crate websocket;
extern crate futures;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::fmt::Debug;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::client::async::Framed;
use websocket::async::{Server, MessageCodec};

use tokio_core::net::TcpStream;
use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let server = Server::bind("localhost:8081", &handle).unwrap();

    let f = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(|(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle);
                return Ok(());
            }

            let client = upgrade
                .use_protocol("rust-websocket")
                .accept();
            let f = client
                .and_then(|(stream, _)| {
                 future::loop_fn(stream, |stream| {
                        stream
                            .into_future()
                            .or_else(|(err, stream)| {
                                println!("Could not send message: {:?}", err);
                                stream.send(OwnedMessage::Close(None)).map(|s| (None, s))
                            })
                            .and_then(|(msg, stream)|{
                                let mut state = State::new();
                                handle_incoming(&mut state, &msg);
                                Ok((msg, stream))
                            }).map(|(msg, stream)| {
                                match msg {
                                    Some(_) => Loop::Continue(stream),
                                    None => Loop::Break(()),
                                }
                            })
                            .boxed()
                    })
            });
            spawn_future(f, "Client Status", &handle);
            Ok(())
        });

    core.run(f).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("{}: '{:?}'", desc, e))
        .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &Option<OwnedMessage>) {
    match msg {
        &Some(OwnedMessage::Text(ref txt)) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

type FramedStream = Framed<TcpStream, MessageCodec<OwnedMessage>>;

fn send(state: &State, stream: FramedStream) -> futures::sink::Send<FramedStream> {
    let msg = serde_json::to_string(&state).unwrap();
    println!("Sending message: {}", msg);
    stream.send(OwnedMessage::Text(msg))
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State {
            msg: "git gud".to_string()
        }
    }
}

<commit_msg>Core: Run rustfmt<commit_after>extern crate websocket;
extern crate futures;
extern crate tokio_core;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

use std::fmt::Debug;

use websocket::message::OwnedMessage;
use websocket::server::InvalidConnection;
use websocket::client::async::Framed;
use websocket::async::{Server, MessageCodec};

use tokio_core::net::TcpStream;
use tokio_core::reactor::{Handle, Core};

use futures::{Future, Sink, Stream};
use futures::future::{self, Loop};

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();
    let server = Server::bind("localhost:8081", &handle).unwrap();

    let f = server.incoming()
        // we don't wanna save the stream if it drops
        .map_err(|InvalidConnection { error, .. }| error)
        .for_each(|(upgrade, addr)| {
            println!("Got a connection from: {}", addr);
            if !upgrade.protocols().iter().any(|s| s == "rust-websocket") {
                spawn_future(upgrade.reject(), "Upgrade Rejection", &handle);
                return Ok(());
            }

            let client = upgrade
                .use_protocol("rust-websocket")
                .accept();
            let f = client
                .and_then(|(stream, _)| {
                 future::loop_fn(stream, |stream| {
                        stream
                            .into_future()
                            .or_else(|(err, stream)| {
                                println!("Could not send message: {:?}", err);
                                stream.send(OwnedMessage::Close(None)).map(|s| (None, s))
                            })
                            .and_then(|(msg, stream)|{
                                let mut state = State::new();
                                handle_incoming(&mut state, &msg);
                                Ok((msg, stream))
                            }).map(|(msg, stream)| {
                                match msg {
                                    Some(_) => Loop::Continue(stream),
                                    None => Loop::Break(()),
                                }
                            })
                            .boxed()
                })
            });
            spawn_future(f, "Client Status", &handle);
            Ok(())
        });

    core.run(f).unwrap();
}

fn spawn_future<F, I, E>(f: F, desc: &'static str, handle: &Handle)
    where F: Future<Item = I, Error = E> + 'static,
          E: Debug
{
    handle.spawn(f.map_err(move |e| println!("{}: '{:?}'", desc, e))
                     .map(move |_| println!("{}: Finished.", desc)));
}

fn handle_incoming(state: &mut State, msg: &Option<OwnedMessage>) {
    match msg {
        &Some(OwnedMessage::Text(ref txt)) => {
            println!("Received message: {}", txt);
            state.msg = txt.clone();
        }
        _ => {}
    }
}

type FramedStream = Framed<TcpStream, MessageCodec<OwnedMessage>>;

fn send(state: &State, stream: FramedStream) -> futures::sink::Send<FramedStream> {
    let msg = serde_json::to_string(&state).unwrap();
    println!("Sending message: {}", msg);
    stream.send(OwnedMessage::Text(msg))
}

#[derive(Serialize)]
struct State {
    msg: String,
}

impl State {
    fn new() -> State {
        State { msg: "git gud".to_string() }
    }
}
<|endoftext|>