<commit_before>#![crate_name = "docopt_macros"]
#![crate_type = "dylib"]

#![feature(plugin_registrar, quote, rustc_private)]

//! This crate defines the `docopt!` macro. It is documented in the
//! documentation of the `docopt` crate.

extern crate syntax;
extern crate rustc;
extern crate docopt;

use std::borrow::Borrow;
use std::collections::HashMap;

use rustc::plugin::Registry;
use syntax::{ast, codemap};
use syntax::ext::base::{ExtCtxt, MacResult, MacEager, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::common::SeqSep;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::util::small_vector::SmallVector;

use docopt::{Docopt, ArgvMap};
use docopt::parse::{Options, Atom, Positional, Zero, One};

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

fn expand(cx: &mut ExtCtxt, span: codemap::Span, tts: &[ast::TokenTree])
         -> Box<MacResult+'static> {
    let parsed = match MacParser::new(cx, tts).parse() {
        Ok(parsed) => parsed,
        Err(_) => return DummyResult::any(span),
    };
    parsed.items(cx)
}

/// Parsed corresponds to the result of parsing a `docopt` macro call.
/// It can be used to write a corresponding struct.
struct Parsed {
    struct_info: StructInfo,
    doc: Docopt,
    /// Overrided type annotations for struct members. May be empty.
    /// When a type annotation for an atom doesn't exist, then one is
    /// inferred automatically. It is one of: `bool`, `usize`, `String` or
    /// `Vec<String>`.
    types: HashMap<Atom, P<ast::Ty>>,
}

impl Parsed {
    /// Returns a macro result suitable for expansion.
    /// Contains two items: one for the struct and one for the struct impls.
    fn items(&self, cx: &ExtCtxt) -> Box<MacResult+'static> {
        let mut its = vec!();
        its.push(self.struct_decl(cx));

        let struct_name = self.struct_info.name;
        let full_doc = &*self.doc.parser().full_doc;
        its.push(quote_item!(cx,
            impl $struct_name {
                #[allow(dead_code)]
                fn docopt() -> docopt::Docopt {
                    // The unwrap is justified here because this code
                    // gen only happens if the Docopt usage string is valid.
                    docopt::Docopt::new($full_doc).unwrap()
                }
            }
        ).unwrap());
        MacEager::items(SmallVector::many(its))
    }

    /// Returns an item for the struct definition.
    fn struct_decl(&self, cx: &ExtCtxt) -> P<ast::Item> {
        let name = self.struct_info.name.clone();
        let vis = if self.struct_info.public { ast::Public }
                  else { ast::Inherited };
        let def = ast::StructDef {
            fields: self.struct_fields(cx),
            ctor_id: None
        };

        let mut traits = vec!["RustcDecodable".to_string()];
        traits.extend(self.struct_info.deriving.iter().cloned());
        let attrs = vec![attribute(cx, "allow", vec!["non_snake_case"]),
                         attribute(cx, "derive", traits)];

        let st = cx.item_struct(codemap::DUMMY_SP, name.clone(), def);
        cx.item(codemap::DUMMY_SP, name, attrs, st.node.clone()).map(|mut it| {
            it.vis = vis;
            it
        })
    }

    /// Returns a list of fields for the struct definition.
    /// Handles type annotations.
    fn struct_fields(&self, cx: &ExtCtxt) -> Vec<ast::StructField> {
        let mut fields: Vec<ast::StructField> = vec!();
        for (atom, opts) in self.doc.parser().descs.iter() {
            let name = ArgvMap::key_to_struct_field(&*atom.to_string());
            let ty = match self.types.get(atom) {
                None => self.pat_type(cx, atom, opts),
                Some(ty) => ty.clone(),
            };
            fields.push(self.mk_struct_field(&*name, ty));
        }
        fields
    }

    /// Returns an inferred type for a usage pattern.
    /// This is only invoked when a type annotation is not present.
    fn pat_type(&self, cx: &ExtCtxt, atom: &Atom, opts: &Options) -> P<ast::Ty> {
        let sp = codemap::DUMMY_SP;
        match (opts.repeats, &opts.arg) {
            (false, &Zero) => {
                match atom {
                    &Positional(_) => cx.ty_ident(sp, ident("String")),
                    _ => cx.ty_ident(sp, ident("bool")),
                }
            }
            (true, &Zero) => {
                match atom {
                    &Positional(_) => ty_vec_string(cx),
                    _ => cx.ty_ident(sp, ident("usize")),
                }
            }
            (false, &One(_)) => cx.ty_ident(sp, ident("String")),
            (true, &One(_)) => ty_vec_string(cx),
        }
    }

    /// Creates a struct field from a member name and type.
    fn mk_struct_field(&self, name: &str, ty: P<ast::Ty>) -> ast::StructField {
        codemap::dummy_spanned(ast::StructField_ {
            kind: ast::NamedField(ident(name), ast::Public),
            id: ast::DUMMY_NODE_ID,
            ty: ty,
            attrs: vec!(),
        })
    }
}

/// State for parsing a `docopt` macro invocation.
struct MacParser<'a, 'b:'a> {
    cx: &'a mut ExtCtxt<'b>,
    p: Parser<'b>,
}

impl<'a, 'b> MacParser<'a, 'b> {
    fn new(cx: &'a mut ExtCtxt<'b>, tts: &[ast::TokenTree]) -> MacParser<'a, 'b> {
        let p = cx.new_parser_from_tts(tts);
        MacParser { cx: cx, p: p }
    }

    /// Main entry point for parsing arguments to `docopt` macro.
    /// First looks for an identifier for the struct name.
    /// Second, a string containing the docopt usage patterns.
    /// Third, an optional list of type annotations.
    fn parse(&mut self) -> Result<Parsed, ()> {
        if self.p.token == token::Eof {
            self.cx.span_err(self.cx.call_site(), "macro expects arguments");
            return Err(());
        }
        let struct_info = try!(self.parse_struct_info());
        let docstr = try!(self.parse_str());

        let sep = SeqSep {
            sep: Some(token::Comma),
            trailing_sep_allowed: true,
        };
        let types = self.p.parse_seq_to_end(
            &token::Eof, sep, |p| MacParser::parse_type_annotation(p)
        ).into_iter()
         .map(|(ident, ty)| {
             let field_name = token::get_ident(ident).to_string();
             let key = ArgvMap::struct_field_to_key(&*field_name);
             (Atom::new(&*key), ty)
          })
         .collect::<HashMap<Atom, P<ast::Ty>>>();
        self.p.expect(&token::Eof);

        // This config does not matter because we're only asking for the
        // usage patterns in the Docopt string. The configuration does not
        // affect the retrieval of usage patterns.
        let doc = match Docopt::new(docstr) {
            Ok(doc) => doc,
            Err(err) => {
                self.cx.span_err(self.cx.call_site(),
                                 &*format!("Invalid Docopt usage: {}", err));
                return Err(());
            }
        };
        Ok(Parsed {
            struct_info: struct_info,
            doc: doc,
            types: types,
        })
    }

    /// Parses a single string literal. On failure, an error is logged and
    /// unit is returned.
    fn parse_str(&mut self) -> Result<String, ()> {
        fn lit_is_str(lit: &ast::Lit) -> bool {
            match lit.node {
                ast::LitStr(_, _) => true,
                _ => false,
            }
        }
        fn lit_to_string(lit: &ast::Lit) -> String {
            match lit.node {
                ast::LitStr(ref s, _) => s.to_string(),
                _ => panic!("BUG: expected string literal"),
            }
        }
        let exp = self.cx.expander().fold_expr(self.p.parse_expr());
        let s = match exp.node {
            ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
                lit_to_string(&**lit)
            }
            _ => {
                let err = format!("Expected string literal but got {}",
                                  pprust::expr_to_string(&*exp));
                self.cx.span_err(exp.span, &*err);
                return Err(());
            }
        };
        self.p.bump();
        Ok(s)
    }

    /// Parses a type annotation in a `docopt` invocation of the form
    /// `ident: Ty`.
    /// Note that this is a static method as it is used as a HOF.
    fn parse_type_annotation(p: &mut Parser) -> (ast::Ident, P<ast::Ty>) {
        let ident = p.parse_ident();
        p.expect(&token::Colon);
        let ty = p.parse_ty();
        (ident, ty)
    }

    /// Parses struct information, like visibility, name and deriving.
    fn parse_struct_info(&mut self) -> Result<StructInfo, ()> {
        let public = self.p.eat_keyword(token::keywords::Pub);
        let mut info = StructInfo {
            name: self.p.parse_ident(),
            public: public,
            deriving: vec![],
        };
        if self.p.eat(&token::Comma) { return Ok(info); }
        let deriving = self.p.parse_ident();
        if deriving.as_str() != "derive" {
            let err = format!("Expected 'derive' keyword but got '{}'",
                              deriving);
            self.cx.span_err(self.cx.call_site(), &*err);
            return Err(());
        }
        while !self.p.eat(&token::Comma) {
            info.deriving.push(self.p.parse_ident().as_str().to_string());
        }
        Ok(info)
    }
}

struct StructInfo {
    name: ast::Ident,
    public: bool,
    deriving: Vec<String>,
}

// Convenience functions for building intermediate values.

fn ident(s: &str) -> ast::Ident {
    ast::Ident::new(token::intern(s))
}

fn attribute<S, T>(cx: &ExtCtxt, name: S, items: Vec<T>) -> ast::Attribute
            where S: Borrow<str>, T: Borrow<str> {
    let sp = codemap::DUMMY_SP;
    let its = items.into_iter().map(|s| meta_item(cx, s.borrow())).collect();
    let mi = cx.meta_list(sp, intern(name.borrow()), its);
    cx.attribute(sp, mi)
}

fn meta_item(cx: &ExtCtxt, s: &str) -> P<ast::MetaItem> {
    cx.meta_word(codemap::DUMMY_SP, intern(s))
}

fn intern(s: &str) -> token::InternedString {
    token::intern_and_get_ident(s)
}

fn ty_vec_string(cx: &ExtCtxt) -> P<ast::Ty> {
    let sp = codemap::DUMMY_SP;
    let tystr = ast::AngleBracketedParameterData {
        lifetimes: vec![],
        types: OwnedSlice::from_vec(vec![cx.ty_ident(sp, ident("String"))]),
        bindings: OwnedSlice::empty(),
    };
    cx.ty_path(ast::Path {
        span: sp,
        global: false,
        segments: vec![ast::PathSegment {
            identifier: ident("Vec"),
            parameters: ast::PathParameters::AngleBracketedParameters(tystr),
        }]
    })
}
<commit_msg>rustup<commit_after>#![crate_name = "docopt_macros"]
#![crate_type = "dylib"]

#![feature(plugin_registrar, quote, rustc_private)]

//! This crate defines the `docopt!` macro. It is documented in the
//! documentation of the `docopt` crate.

extern crate syntax;
extern crate rustc;
extern crate docopt;

use std::borrow::Borrow;
use std::collections::HashMap;

use rustc::plugin::Registry;
use syntax::{ast, codemap};
use syntax::diagnostic::FatalError;
use syntax::ext::base::{ExtCtxt, MacResult, MacEager, DummyResult};
use syntax::ext::build::AstBuilder;
use syntax::fold::Folder;
use syntax::owned_slice::OwnedSlice;
use syntax::parse::common::SeqSep;
use syntax::parse::parser::Parser;
use syntax::parse::token;
use syntax::print::pprust;
use syntax::ptr::P;
use syntax::util::small_vector::SmallVector;

use docopt::{Docopt, ArgvMap};
use docopt::parse::{Options, Atom, Positional, Zero, One};

type PResult<T> = Result<T, FatalError>;

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

fn expand(cx: &mut ExtCtxt, span: codemap::Span, tts: &[ast::TokenTree])
         -> Box<MacResult+'static> {
    let parsed = match MacParser::new(cx, tts).parse() {
        Ok(parsed) => parsed,
        Err(_) => return DummyResult::any(span),
    };
    parsed.items(cx)
}

/// Parsed corresponds to the result of parsing a `docopt` macro call.
/// It can be used to write a corresponding struct.
struct Parsed {
    struct_info: StructInfo,
    doc: Docopt,
    /// Overrided type annotations for struct members. May be empty.
    /// When a type annotation for an atom doesn't exist, then one is
    /// inferred automatically. It is one of: `bool`, `usize`, `String` or
    /// `Vec<String>`.
    types: HashMap<Atom, P<ast::Ty>>,
}

impl Parsed {
    /// Returns a macro result suitable for expansion.
    /// Contains two items: one for the struct and one for the struct impls.
    fn items(&self, cx: &ExtCtxt) -> Box<MacResult+'static> {
        let mut its = vec!();
        its.push(self.struct_decl(cx));

        let struct_name = self.struct_info.name;
        let full_doc = &*self.doc.parser().full_doc;
        its.push(quote_item!(cx,
            impl $struct_name {
                #[allow(dead_code)]
                fn docopt() -> docopt::Docopt {
                    // The unwrap is justified here because this code
                    // gen only happens if the Docopt usage string is valid.
                    docopt::Docopt::new($full_doc).unwrap()
                }
            }
        ).unwrap());
        MacEager::items(SmallVector::many(its))
    }

    /// Returns an item for the struct definition.
    fn struct_decl(&self, cx: &ExtCtxt) -> P<ast::Item> {
        let name = self.struct_info.name.clone();
        let vis = if self.struct_info.public { ast::Public }
                  else { ast::Inherited };
        let def = ast::StructDef {
            fields: self.struct_fields(cx),
            ctor_id: None
        };

        let mut traits = vec!["RustcDecodable".to_string()];
        traits.extend(self.struct_info.deriving.iter().cloned());
        let attrs = vec![attribute(cx, "allow", vec!["non_snake_case"]),
                         attribute(cx, "derive", traits)];

        let st = cx.item_struct(codemap::DUMMY_SP, name.clone(), def);
        cx.item(codemap::DUMMY_SP, name, attrs, st.node.clone()).map(|mut it| {
            it.vis = vis;
            it
        })
    }

    /// Returns a list of fields for the struct definition.
    /// Handles type annotations.
    fn struct_fields(&self, cx: &ExtCtxt) -> Vec<ast::StructField> {
        let mut fields: Vec<ast::StructField> = vec!();
        for (atom, opts) in self.doc.parser().descs.iter() {
            let name = ArgvMap::key_to_struct_field(&*atom.to_string());
            let ty = match self.types.get(atom) {
                None => self.pat_type(cx, atom, opts),
                Some(ty) => ty.clone(),
            };
            fields.push(self.mk_struct_field(&*name, ty));
        }
        fields
    }

    /// Returns an inferred type for a usage pattern.
    /// This is only invoked when a type annotation is not present.
    fn pat_type(&self, cx: &ExtCtxt, atom: &Atom, opts: &Options) -> P<ast::Ty> {
        let sp = codemap::DUMMY_SP;
        match (opts.repeats, &opts.arg) {
            (false, &Zero) => {
                match atom {
                    &Positional(_) => cx.ty_ident(sp, ident("String")),
                    _ => cx.ty_ident(sp, ident("bool")),
                }
            }
            (true, &Zero) => {
                match atom {
                    &Positional(_) => ty_vec_string(cx),
                    _ => cx.ty_ident(sp, ident("usize")),
                }
            }
            (false, &One(_)) => cx.ty_ident(sp, ident("String")),
            (true, &One(_)) => ty_vec_string(cx),
        }
    }

    /// Creates a struct field from a member name and type.
    fn mk_struct_field(&self, name: &str, ty: P<ast::Ty>) -> ast::StructField {
        codemap::dummy_spanned(ast::StructField_ {
            kind: ast::NamedField(ident(name), ast::Public),
            id: ast::DUMMY_NODE_ID,
            ty: ty,
            attrs: vec!(),
        })
    }
}

/// State for parsing a `docopt` macro invocation.
struct MacParser<'a, 'b:'a> {
    cx: &'a mut ExtCtxt<'b>,
    p: Parser<'b>,
}

impl<'a, 'b> MacParser<'a, 'b> {
    fn new(cx: &'a mut ExtCtxt<'b>, tts: &[ast::TokenTree]) -> MacParser<'a, 'b> {
        let p = cx.new_parser_from_tts(tts);
        MacParser { cx: cx, p: p }
    }

    /// Main entry point for parsing arguments to `docopt` macro.
    /// First looks for an identifier for the struct name.
    /// Second, a string containing the docopt usage patterns.
    /// Third, an optional list of type annotations.
    fn parse(&mut self) -> PResult<Parsed> {
        if self.p.token == token::Eof {
            self.cx.span_err(self.cx.call_site(), "macro expects arguments");
            return Err(FatalError);
        }
        let struct_info = try!(self.parse_struct_info());
        let docstr = try!(self.parse_str());

        let sep = SeqSep {
            sep: Some(token::Comma),
            trailing_sep_allowed: true,
        };
        let types = try!(self.p.parse_seq_to_end(
            &token::Eof, sep, |p| MacParser::parse_type_annotation(p)
        )).into_iter()
          .map(|(ident, ty)| {
              let field_name = token::get_ident(ident).to_string();
              let key = ArgvMap::struct_field_to_key(&*field_name);
              (Atom::new(&*key), ty)
           })
          .collect::<HashMap<Atom, P<ast::Ty>>>();
        try!(self.p.expect(&token::Eof));

        // This config does not matter because we're only asking for the
        // usage patterns in the Docopt string. The configuration does not
        // affect the retrieval of usage patterns.
        let doc = match Docopt::new(docstr) {
            Ok(doc) => doc,
            Err(err) => {
                self.cx.span_err(self.cx.call_site(),
                                 &*format!("Invalid Docopt usage: {}", err));
                return Err(FatalError);
            }
        };
        Ok(Parsed {
            struct_info: struct_info,
            doc: doc,
            types: types,
        })
    }

    /// Parses a single string literal. On failure, an error is logged and
    /// unit is returned.
    fn parse_str(&mut self) -> PResult<String> {
        fn lit_is_str(lit: &ast::Lit) -> bool {
            match lit.node {
                ast::LitStr(_, _) => true,
                _ => false,
            }
        }
        fn lit_to_string(lit: &ast::Lit) -> String {
            match lit.node {
                ast::LitStr(ref s, _) => s.to_string(),
                _ => panic!("BUG: expected string literal"),
            }
        }
        let exp = self.cx.expander().fold_expr(self.p.parse_expr());
        let s = match exp.node {
            ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
                lit_to_string(&**lit)
            }
            _ => {
                let err = format!("Expected string literal but got {}",
                                  pprust::expr_to_string(&*exp));
                self.cx.span_err(exp.span, &*err);
                return Err(FatalError);
            }
        };
        try!(self.p.bump());
        Ok(s)
    }

    /// Parses a type annotation in a `docopt` invocation of the form
    /// `ident: Ty`.
    /// Note that this is a static method as it is used as a HOF.
    fn parse_type_annotation(p: &mut Parser)
                            -> PResult<(ast::Ident, P<ast::Ty>)> {
        let ident = try!(p.parse_ident());
        try!(p.expect(&token::Colon));
        let ty = p.parse_ty();
        Ok((ident, ty))
    }

    /// Parses struct information, like visibility, name and deriving.
    fn parse_struct_info(&mut self) -> PResult<StructInfo> {
        let public = try!(self.p.eat_keyword(token::keywords::Pub));
        let mut info = StructInfo {
            name: try!(self.p.parse_ident()),
            public: public,
            deriving: vec![],
        };
        if try!(self.p.eat(&token::Comma)) { return Ok(info); }
        let deriving = try!(self.p.parse_ident());
        if deriving.as_str() != "derive" {
            let err = format!("Expected 'derive' keyword but got '{}'",
                              deriving);
            self.cx.span_err(self.cx.call_site(), &*err);
            return Err(FatalError);
        }
        while !try!(self.p.eat(&token::Comma)) {
            info.deriving.push(
                try!(self.p.parse_ident()).as_str().to_string());
        }
        Ok(info)
    }
}

struct StructInfo {
    name: ast::Ident,
    public: bool,
    deriving: Vec<String>,
}

// Convenience functions for building intermediate values.

fn ident(s: &str) -> ast::Ident {
    ast::Ident::new(token::intern(s))
}

fn attribute<S, T>(cx: &ExtCtxt, name: S, items: Vec<T>) -> ast::Attribute
            where S: Borrow<str>, T: Borrow<str> {
    let sp = codemap::DUMMY_SP;
    let its = items.into_iter().map(|s| meta_item(cx, s.borrow())).collect();
    let mi = cx.meta_list(sp, intern(name.borrow()), its);
    cx.attribute(sp, mi)
}

fn meta_item(cx: &ExtCtxt, s: &str) -> P<ast::MetaItem> {
    cx.meta_word(codemap::DUMMY_SP, intern(s))
}

fn intern(s: &str) -> token::InternedString {
    token::intern_and_get_ident(s)
}

fn ty_vec_string(cx: &ExtCtxt) -> P<ast::Ty> {
    let sp = codemap::DUMMY_SP;
    let tystr = ast::AngleBracketedParameterData {
        lifetimes: vec![],
        types: OwnedSlice::from_vec(vec![cx.ty_ident(sp, ident("String"))]),
        bindings: OwnedSlice::empty(),
    };
    cx.ty_path(ast::Path {
        span: sp,
        global: false,
        segments: vec![ast::PathSegment {
            identifier: ident("Vec"),
            parameters: ast::PathParameters::AngleBracketedParameters(tystr),
        }]
    })
}
<|endoftext|>


<commit_before>//! Defines the BxDF interface implemented by BRDF/BTDFs to describe
//! material properties. Also provides the BSDF type which composes
//! various BRDF/BTDFs to describe materials

use std::collections::enum_set::{EnumSet, CLike};
use std::mem;
use std::num::{FloatMath, Float};

use linalg;
use linalg::Vector;
use film::Colorf;

pub use self::bsdf::BSDF;
pub use self::lambertian::Lambertian;

pub mod bsdf;
pub mod lambertian;

/// Various types of BxDFs that can be selected to specify which
/// types of surface functions should be evaluated
#[repr(uint)]
#[derive(Copy, Show)]
pub enum BxDFType {
    Reflection, Transmission, Diffuse, Glossy, Specular,
}

impl BxDFType {
    /// Get an EnumSet containing all flags for the different types of
    /// BxDFs: Diffuse, Glossy, Specular
    fn all_types() -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Diffuse);
        e.insert(BxDFType::Glossy);
        e.insert(BxDFType::Specular);
        e
    }
    /// Get an EnumSet containing all flags for reflective BxDFs (eg. BRDFs)
    fn all_brdf() -> EnumSet<BxDFType> {
        let mut e = BxDFType::all_types();
        e.insert(BxDFType::Reflection);
        e
    }
    /// Get an EnumSet containing all flags for transmissive BxDFs (eg. BTDFs)
    fn all_btdf() -> EnumSet<BxDFType> {
        let mut e = BxDFType::all_types();
        e.insert(BxDFType::Transmission);
        e
    }
    /// Get an EnumSet containing all flags for all BxDFs. This would be all
    /// types of BRDFs and BTDFs
    fn all() -> EnumSet<BxDFType> { BxDFType::all_brdf().union(BxDFType::all_btdf()) }
    /// Get an EnumSet containing flags for all types of specular BxDFs
    fn specular() -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Specular);
        e.insert(BxDFType::Reflection);
        e.insert(BxDFType::Transmission);
        e
    }
    /// Get an EnumSet containing flags for all non-specular BxDFs
    fn non_specular() -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Diffuse);
        e.insert(BxDFType::Glossy);
        e.insert(BxDFType::Reflection);
        e.insert(BxDFType::Transmission);
        e
    }
}

impl CLike for BxDFType {
    fn to_uint(&self) -> uint { *self as uint }
    fn from_uint(v: uint) -> BxDFType { unsafe { mem::transmute(v) } }
}

/// Trait implemented by BRDF/BTDFs in tray_rust. Provides methods for
/// evaluating and sampling the function
pub trait BxDF {
    /// Get the type of this BxDF
    fn bxdf_type(&self) -> EnumSet<BxDFType>;
    /// Check if this BxDF matches the type flags passed
    fn matches(&self, flags: EnumSet<BxDFType>) -> bool {
        self.bxdf_type().is_subset(&flags)
    }
    /// Evaluate the BxDF for the pair of incident and outgoing light directions,
    /// `w_i` and `w_o`.
    fn eval(&self, w_o: &Vector, w_i: &Vector) -> Colorf;
}

/// Compute the value of cosine theta for a vector in shading space
pub fn cos_theta(v: &Vector) -> f32 { v.z }
/// Compute the value of (sine theta)^2  for a vector in shading space
pub fn sin_theta_sqr(v: &Vector) -> f32 { FloatMath::max(0.0, 1.0 - v.z * v.z) }
/// Compute the value of sine theta for a vector in shading space
pub fn sin_theta(v: &Vector) -> f32 { Float::sqrt(sin_theta_sqr(v)) }
/// Compute the value of cosine phi for a vector in shading space
pub fn cos_phi(v: &Vector) -> f32 {
    let sin_theta = sin_theta(v);
    if sin_theta == 0.0 {
        1.0
    } else {
        linalg::clamp(v.x / sin_theta, -1.0, 1.0)
    }
}
/// Compute the value of sine phi for a vector in shading space
pub fn sin_phi(v: &Vector) -> f32 {
    let sin_theta = sin_theta(v);
    if sin_theta == 0.0 {
        0.0
    } else {
        linalg::clamp(v.y / sin_theta, -1.0, 1.0)
    }
}
/// Check if two vectors are in the same hemisphere in shading space
pub fn same_hemisphere(a: &Vector, b: &Vector) -> bool { a.z * b.z > 0.0 }

<commit_msg>Make the BxDFType functions public<commit_after>//! Defines the BxDF interface implemented by BRDF/BTDFs to describe
//! material properties. Also provides the BSDF type which composes
//! various BRDF/BTDFs to describe materials

use std::collections::enum_set::{EnumSet, CLike};
use std::mem;
use std::num::{FloatMath, Float};

use linalg;
use linalg::Vector;
use film::Colorf;

pub use self::bsdf::BSDF;
pub use self::lambertian::Lambertian;

pub mod bsdf;
pub mod lambertian;

/// Various types of BxDFs that can be selected to specify which
/// types of surface functions should be evaluated
#[repr(uint)]
#[derive(Copy, Show)]
pub enum BxDFType {
    Reflection, Transmission, Diffuse, Glossy, Specular,
}

impl BxDFType {
    /// Get an EnumSet containing all flags for the different types of
    /// BxDFs: Diffuse, Glossy, Specular
    pub fn all_types() -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Diffuse);
        e.insert(BxDFType::Glossy);
        e.insert(BxDFType::Specular);
        e
    }
    /// Get an EnumSet containing all flags for reflective BxDFs (eg. BRDFs)
    pub fn all_brdf() -> EnumSet<BxDFType> {
        let mut e = BxDFType::all_types();
        e.insert(BxDFType::Reflection);
        e
    }
    /// Get an EnumSet containing all flags for transmissive BxDFs (eg. BTDFs)
    pub fn all_btdf() -> EnumSet<BxDFType> {
        let mut e = BxDFType::all_types();
        e.insert(BxDFType::Transmission);
        e
    }
    /// Get an EnumSet containing all flags for all BxDFs. This would be all
    /// types of BRDFs and BTDFs
    pub fn all() -> EnumSet<BxDFType> { BxDFType::all_brdf().union(BxDFType::all_btdf()) }
    /// Get an EnumSet containing flags for all types of specular BxDFs
    pub fn specular() -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Specular);
        e.insert(BxDFType::Reflection);
        e.insert(BxDFType::Transmission);
        e
    }
    /// Get an EnumSet containing flags for all non-specular BxDFs
    pub fn non_specular() -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Diffuse);
        e.insert(BxDFType::Glossy);
        e.insert(BxDFType::Reflection);
        e.insert(BxDFType::Transmission);
        e
    }
}

impl CLike for BxDFType {
    fn to_uint(&self) -> uint { *self as uint }
    fn from_uint(v: uint) -> BxDFType { unsafe { mem::transmute(v) } }
}

/// Trait implemented by BRDF/BTDFs in tray_rust. Provides methods for
/// evaluating and sampling the function
pub trait BxDF {
    /// Get the type of this BxDF
    fn bxdf_type(&self) -> EnumSet<BxDFType>;
    /// Check if this BxDF matches the type flags passed
    fn matches(&self, flags: EnumSet<BxDFType>) -> bool {
        self.bxdf_type().is_subset(&flags)
    }
    /// Evaluate the BxDF for the pair of incident and outgoing light directions,
    /// `w_i` and `w_o`.
    fn eval(&self, w_o: &Vector, w_i: &Vector) -> Colorf;
}

/// Compute the value of cosine theta for a vector in shading space
pub fn cos_theta(v: &Vector) -> f32 { v.z }
/// Compute the value of (sine theta)^2  for a vector in shading space
pub fn sin_theta_sqr(v: &Vector) -> f32 { FloatMath::max(0.0, 1.0 - v.z * v.z) }
/// Compute the value of sine theta for a vector in shading space
pub fn sin_theta(v: &Vector) -> f32 { Float::sqrt(sin_theta_sqr(v)) }
/// Compute the value of cosine phi for a vector in shading space
pub fn cos_phi(v: &Vector) -> f32 {
    let sin_theta = sin_theta(v);
    if sin_theta == 0.0 {
        1.0
    } else {
        linalg::clamp(v.x / sin_theta, -1.0, 1.0)
    }
}
/// Compute the value of sine phi for a vector in shading space
pub fn sin_phi(v: &Vector) -> f32 {
    let sin_theta = sin_theta(v);
    if sin_theta == 0.0 {
        0.0
    } else {
        linalg::clamp(v.y / sin_theta, -1.0, 1.0)
    }
}
/// Check if two vectors are in the same hemisphere in shading space
pub fn same_hemisphere(a: &Vector, b: &Vector) -> bool { a.z * b.z > 0.0 }

<|endoftext|>


<commit_before>use serde_json::Value;
use iron::Handler;
use mount::Mount;

use crypto::{Hash, PublicKey, SecretKey};
use storage::{Snapshot, Fork};
use messages::{Message, RawTransaction};
use encoding::Error as MessageError;
use node::{Node, State, NodeChannel, TxSender};
use node::state::ValidatorState;
use events::Milliseconds;
use blockchain::{StoredConfiguration, ConsensusConfig, Blockchain};

pub trait Transaction: Message + 'static {
    fn verify(&self) -> bool;
    fn execute(&self, view: &mut Fork);
    fn info(&self) -> Value {
        Value::Null
    }
}

#[allow(unused_variables, unused_mut)]
pub trait Service: Send + Sync + 'static {
    /// Unique service identification for database schema and service messages.
    fn service_id(&self) -> u16;
    /// Unique human readable service name.
    fn service_name(&self) -> &'static str;

    fn state_hash(&self, _: &Snapshot) -> Vec<Hash> {
        Vec::new()
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, MessageError>;

    fn handle_genesis_block(&self, view: &Snapshot) -> Value {
        Value::Null
    }

    fn handle_commit(&self, context: &mut NodeState) { }

    /// Returns api handler for public users.
    fn public_api_handler(&self, context: &ApiContext) -> Option<Box<Handler>> {
        None
    }
    /// Returns api handler for maintainers.
    fn private_api_handler(&self, context: &ApiContext) -> Option<Box<Handler>> {
        None
    }
}

pub struct NodeState<'a, 'b> {
    state: &'a mut State,
    view: &'b Snapshot,
    txs: Vec<Box<Transaction>>,
}

impl<'a, 'b> NodeState<'a, 'b> {
    pub fn new(state: &'a mut State, view: &'b Snapshot) -> NodeState<'a, 'b> {
        NodeState {
            state: state,
            view: view,
            txs: Vec::new(),
        }
    }

    pub fn validator_state(&self) -> &Option<ValidatorState> {
        self.state.validator_state()
    }

    pub fn view(&self) -> &Snapshot {
        self.view
    }

    pub fn height(&self) -> u64 {
        self.state.height()
    }

    pub fn round(&self) -> u32 {
        self.state.round()
    }

    pub fn validators(&self) -> &[PublicKey] {
        self.state.validators()
    }

    pub fn public_key(&self) -> &PublicKey {
        self.state.public_key()
    }

    pub fn secret_key(&self) -> &SecretKey {
        self.state.secret_key()
    }

    pub fn actual_config(&self) -> &StoredConfiguration {
        self.state.config()
    }

    pub fn consensus_config(&self) -> &ConsensusConfig {
        self.state.consensus_config()
    }

    pub fn service_config(&self, service: &Service) -> &Value {
        let name = service.service_name();
        self.state
            .services_config()
            .get(name)
            .unwrap()
    }

    pub fn update_config(&mut self, new_config: StoredConfiguration) {
        self.state.update_config(new_config)
    }

    pub fn propose_timeout(&self) -> Milliseconds {
        self.state.propose_timeout()
    }

    pub fn set_propose_timeout(&mut self, timeout: Milliseconds) {
        self.state.set_propose_timeout(timeout)
    }

    pub fn add_transaction<T: Transaction>(&mut self, tx: T) {
        assert!(tx.verify());
        self.txs.push(Box::new(tx));
    }

    pub fn transactions(self) -> Vec<Box<Transaction>> {
        self.txs
    }
}

impl<'a, 'b> ::std::fmt::Debug for NodeState<'a, 'b> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "NodeState(state: {:?}, txs: {:?})", self.state, self.txs)
    }
}

#[derive(Debug)]
pub struct ApiContext {
    blockchain: Blockchain,
    node_channel: TxSender<NodeChannel>,
    public_key: PublicKey,
    secret_key: SecretKey,
}

impl ApiContext {
    pub fn new(node: &Node) -> ApiContext {
        let handler = node.handler();
        ApiContext {
            blockchain: handler.blockchain.clone(),
            node_channel: node.channel(),
            public_key: *node.state().public_key(),
            secret_key: node.state().secret_key().clone(),
        }
    }

    pub fn blockchain(&self) -> &Blockchain {
        &self.blockchain
    }

    pub fn node_channel(&self) -> &TxSender<NodeChannel> {
        &self.node_channel
    }

    pub fn public_key(&self) -> &PublicKey {
        &self.public_key
    }

    pub fn secret_key(&self) -> &SecretKey {
        &self.secret_key
    }

    pub fn mount_public_api(&self) -> Mount {
        self.blockchain.mount_public_api(self)
    }

    pub fn mount_private_api(&self) -> Mount {
        self.blockchain.mount_private_api(self)
    }
}
<commit_msg>Fix NodeState::view output lifetime bound<commit_after>use serde_json::Value;
use iron::Handler;
use mount::Mount;

use crypto::{Hash, PublicKey, SecretKey};
use storage::{Snapshot, Fork};
use messages::{Message, RawTransaction};
use encoding::Error as MessageError;
use node::{Node, State, NodeChannel, TxSender};
use node::state::ValidatorState;
use events::Milliseconds;
use blockchain::{StoredConfiguration, ConsensusConfig, Blockchain};

pub trait Transaction: Message + 'static {
    fn verify(&self) -> bool;
    fn execute(&self, view: &mut Fork);
    fn info(&self) -> Value {
        Value::Null
    }
}

#[allow(unused_variables, unused_mut)]
pub trait Service: Send + Sync + 'static {
    /// Unique service identification for database schema and service messages.
    fn service_id(&self) -> u16;
    /// Unique human readable service name.
    fn service_name(&self) -> &'static str;

    fn state_hash(&self, _: &Snapshot) -> Vec<Hash> {
        Vec::new()
    }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, MessageError>;

    fn handle_genesis_block(&self, view: &Snapshot) -> Value {
        Value::Null
    }

    fn handle_commit(&self, context: &mut NodeState) { }

    /// Returns api handler for public users.
    fn public_api_handler(&self, context: &ApiContext) -> Option<Box<Handler>> {
        None
    }
    /// Returns api handler for maintainers.
    fn private_api_handler(&self, context: &ApiContext) -> Option<Box<Handler>> {
        None
    }
}

pub struct NodeState<'a, 'b> {
    state: &'a mut State,
    view: &'b Snapshot,
    txs: Vec<Box<Transaction>>,
}

impl<'a, 'b> NodeState<'a, 'b> {
    pub fn new(state: &'a mut State, view: &'b Snapshot) -> NodeState<'a, 'b> {
        NodeState {
            state: state,
            view: view,
            txs: Vec::new(),
        }
    }

    pub fn validator_state(&self) -> &Option<ValidatorState> {
        self.state.validator_state()
    }

    pub fn view(&self) -> &'b Snapshot {
        self.view
    }

    pub fn height(&self) -> u64 {
        self.state.height()
    }

    pub fn round(&self) -> u32 {
        self.state.round()
    }

    pub fn validators(&self) -> &[PublicKey] {
        self.state.validators()
    }

    pub fn public_key(&self) -> &PublicKey {
        self.state.public_key()
    }

    pub fn secret_key(&self) -> &SecretKey {
        self.state.secret_key()
    }

    pub fn actual_config(&self) -> &StoredConfiguration {
        self.state.config()
    }

    pub fn consensus_config(&self) -> &ConsensusConfig {
        self.state.consensus_config()
    }

    pub fn service_config(&self, service: &Service) -> &Value {
        let name = service.service_name();
        self.state
            .services_config()
            .get(name)
            .unwrap()
    }

    pub fn update_config(&mut self, new_config: StoredConfiguration) {
        self.state.update_config(new_config)
    }

    pub fn propose_timeout(&self) -> Milliseconds {
        self.state.propose_timeout()
    }

    pub fn set_propose_timeout(&mut self, timeout: Milliseconds) {
        self.state.set_propose_timeout(timeout)
    }

    pub fn add_transaction<T: Transaction>(&mut self, tx: T) {
        assert!(tx.verify());
        self.txs.push(Box::new(tx));
    }

    pub fn transactions(self) -> Vec<Box<Transaction>> {
        self.txs
    }
}

impl<'a, 'b> ::std::fmt::Debug for NodeState<'a, 'b> {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "NodeState(state: {:?}, txs: {:?})", self.state, self.txs)
    }
}

#[derive(Debug)]
pub struct ApiContext {
    blockchain: Blockchain,
    node_channel: TxSender<NodeChannel>,
    public_key: PublicKey,
    secret_key: SecretKey,
}

impl ApiContext {
    pub fn new(node: &Node) -> ApiContext {
        let handler = node.handler();
        ApiContext {
            blockchain: handler.blockchain.clone(),
            node_channel: node.channel(),
            public_key: *node.state().public_key(),
            secret_key: node.state().secret_key().clone(),
        }
    }

    pub fn blockchain(&self) -> &Blockchain {
        &self.blockchain
    }

    pub fn node_channel(&self) -> &TxSender<NodeChannel> {
        &self.node_channel
    }

    pub fn public_key(&self) -> &PublicKey {
        &self.public_key
    }

    pub fn secret_key(&self) -> &SecretKey {
        &self.secret_key
    }

    pub fn mount_public_api(&self) -> Mount {
        self.blockchain.mount_public_api(self)
    }

    pub fn mount_private_api(&self) -> Mount {
        self.blockchain.mount_private_api(self)
    }
}
<|endoftext|>


<commit_before>use bson;

use client::coll::Collection;

use client::wire_protocol::flags::OpQueryFlags;
use client::wire_protocol::operations::Message;

use std::collections::vec_deque::VecDeque;
use std::io::{Read, Write};

pub const DEFAULT_BATCH_SIZE: i32 = 20;

/// Maintains a connection to the server and lazily returns documents from a
/// query.
///
/// # Fields
///
/// `collection` - The collection to read from.
/// `batch_size` - How many documents to fetch at a given time from the server.
/// `cursor_id` - Uniquely identifies the cursor being returned by the reply.
pub struct Cursor<'a> {
    collection: &'a Collection<'a>,
    batch_size: i32,
    cursor_id: i64,
    limit: i32,
    count: i32,
    buffer: VecDeque<bson::Document>,
}

impl <'a> Cursor<'a> {
    /// Gets the cursor id and BSON documents from a reply Message.
    ///
    /// # Arguments
    ///
    /// `message` - The reply message to get the documents from.
    ///
    /// # Return value.
    ///
    ///
    fn get_bson_and_cid_from_message(message: Message) -> Option<(VecDeque<bson::Document>, i64)> {
        match message {
            Message::OpReply { header: _, flags: _, cursor_id: cid,
                               starting_from: _, number_returned: _,
                               documents: docs } => {
                let mut v = VecDeque::new();

                for doc in docs {
                    v.push_back(doc.clone());
                }

                Some((v, cid))
            },
            _ => None
        }
    }

    /// Executes a query where the batch size of the returned cursor is
    /// specified.
    ///
    /// # Arguments
    ///
    /// `collection` - The collection to read from.
    /// `batch_size` - How many documents the cursor should return at a time.
    /// `flags` - Bit vector of query options.
    /// `number_to_skip` - The number of initial documents to skip over in the
    ///                    query results.
    /// `number_to_return - The total number of documents that should be
    ///                     returned by the query.
    /// `return_field_selector - An optional projection of which fields should
    ///                          be present in the documents to be returned by
    ///                          the query.
    ///
    /// # Return value
    ///
    /// Returns the cursor for the query results on success, or an error string
    /// on failure.
    pub fn query_with_batch_size(collection: &'a Collection<'a>,
                                 batch_size: i32,
                                 flags: OpQueryFlags,
                                 number_to_skip: i32, number_to_return: i32,
                                 query: bson::Document,
                                 return_field_selector: Option<bson::Document>) -> Result<Cursor<'a>, String> {
        let result = Message::with_query(collection.get_req_id(), flags,
                                         collection.namespace.to_owned(),
                                         number_to_skip, number_to_return,
                                         query, return_field_selector);

        let socket = match collection.db.client.socket.lock() {
            Ok(val) => val,
            Err(_) => return Err("Socket lock is poisoned.".to_owned()),
        };

        let message = try!(result);
        try!(message.write(&mut *socket.borrow_mut()));
        let reply = try!(Message::read(&mut *socket.borrow_mut()));

        match Cursor::get_bson_and_cid_from_message(reply) {
            Some((buf, cursor_id)) => Ok(Cursor {
                collection: collection,
                batch_size: batch_size,
                cursor_id: cursor_id,
                limit: number_to_return,
                count: 0,
                buffer: buf,
            }),
            None => Err("Invalid response received".to_owned()),
        }
    }

    /// Executes a query with the default batch size.
    ///
    /// # Arguments
    ///
    /// `collection` - The collection to read from.
    /// `flags` - Bit vector of query options.
    /// `number_to_skip` - The number of initial documents to skip over in the
    ///                    query results.
    /// `number_to_return - The total number of documents that should be
    ///                     returned by the query.
    /// `query` - Specifies which documents to return.
    /// `return_field_selector - An optional projection of which fields should
    ///                          be present in the documents to be returned by
    ///                          the query.
    ///
    /// # Return value
    ///
    /// Returns the cursor for the query results on success, or an error string
    /// on failure.
    pub fn query(collection: &'a Collection<'a>, flags: OpQueryFlags,
                 number_to_skip: i32, number_to_return: i32, query: bson::Document,
                 return_field_selector: Option<bson::Document>) -> Result<Cursor<'a>, String> {

        Cursor::query_with_batch_size(collection, DEFAULT_BATCH_SIZE, flags,
                                      number_to_skip,
                                      number_to_return, query,
                                      return_field_selector)
    }

    /// Helper method to create a "get more" request.
    ///
    /// # Return value
    ///
    /// Returns the newly-created method.
    fn new_get_more_request(&mut self) -> Message {
        Message::with_get_more(self.collection.get_req_id(),
                               self.collection.namespace.to_owned(),
                               self.batch_size, self.cursor_id)
    }

    /// Attempts to read another batch of BSON documents from the stream.
    fn get_from_stream(&mut self) -> Result<(), String> {
        let socket = match self.collection.db.client.socket.lock() {
            Ok(val) => val,
            Err(_) => return Err("Socket lock is poisoned.".to_owned()),
        };

        let get_more = self.new_get_more_request();
        try!(get_more.write(&mut *socket.borrow_mut()));
        let reply = try!(Message::read(&mut *socket.borrow_mut()));

        match Cursor::get_bson_and_cid_from_message(reply) {
            Some((v, _)) => {
                self.buffer.extend(v);
                Ok(())
            },
            None => Err("No bson found from server reply.".to_owned()),
        }
    }

    /// Attempts to read another batch of BSON documents from the stream.
    ///
    /// # Return value
    ///
    /// Returns the first BSON document returned from the stream, or `None` if
    /// there are no more documents to read.
    fn next_from_stream(&mut self) -> Option<bson::Document> {
        self.get_from_stream();
        self.buffer.pop_front()
    }

    /// Attempts to read a specified number of BSON documents from the cursor.
    ///
    /// # Arguments
    ///
    /// `n` - The number of documents to read.
    ///
    /// # Return value
    ///
    /// Returns a vector containing the BSON documents that were read.
    pub fn next_n(&mut self, n: i32) -> Vec<bson::Document> {
        let mut vec = vec![];

        for _ in 0..n {
            let bson_option = self.next();

            match bson_option {
                Some(bson) => vec.push(bson),
                None => break
            };
        }

        vec
    }

    /// Attempts to read a batch of BSON documents from the cursor.
    ///
    /// # Return value
    ///
    /// Returns a vector containing the BSON documents that were read.
    pub fn next_batch(&mut self) -> Vec<bson::Document> {
        let n = self.batch_size;

        self.next_n(n)
    }

    pub fn has_next(&mut self) -> bool {
        if self.limit > 0 && self.count >= self.limit {
            false
        } else {
            if self.buffer.is_empty() {
                self.get_from_stream();
            }
            !self.buffer.is_empty()
        }
    }
}

impl <'a> Iterator for Cursor<'a> {
    type Item = bson::Document;

    /// Attempts to read a BSON document from the cursor.
    ///
    /// # Return value
    ///
    /// Returns the document that was read, or `None` if there are no more
    /// documents to read.
    fn next(&mut self) -> Option<bson::Document> {
        if self.limit != 0 && self.count >= self.limit {
            return None;
        }

        self.count += 1;

        match self.buffer.pop_front() {
            Some(bson) => Some(bson),
            None => {
                if self.limit != 1 {
                    self.next_from_stream()
                } else {
                    None
                }
            }
        }
    }
}
<commit_msg>Simplify cursor.next()<commit_after>use bson;

use client::coll::Collection;

use client::wire_protocol::flags::OpQueryFlags;
use client::wire_protocol::operations::Message;

use std::collections::vec_deque::VecDeque;
use std::io::{Read, Write};

pub const DEFAULT_BATCH_SIZE: i32 = 20;

/// Maintains a connection to the server and lazily returns documents from a
/// query.
///
/// # Fields
///
/// `collection` - The collection to read from.
/// `batch_size` - How many documents to fetch at a given time from the server.
/// `cursor_id` - Uniquely identifies the cursor being returned by the reply.
pub struct Cursor<'a> {
    collection: &'a Collection<'a>,
    batch_size: i32,
    cursor_id: i64,
    limit: i32,
    count: i32,
    buffer: VecDeque<bson::Document>,
}

impl <'a> Cursor<'a> {
    /// Gets the cursor id and BSON documents from a reply Message.
    ///
    /// # Arguments
    ///
    /// `message` - The reply message to get the documents from.
    ///
    /// # Return value.
    ///
    ///
    fn get_bson_and_cid_from_message(message: Message) -> Option<(VecDeque<bson::Document>, i64)> {
        match message {
            Message::OpReply { header: _, flags: _, cursor_id: cid,
                               starting_from: _, number_returned: _,
                               documents: docs } => {
                let mut v = VecDeque::new();

                for doc in docs {
                    v.push_back(doc.clone());
                }

                Some((v, cid))
            },
            _ => None
        }
    }

    /// Executes a query where the batch size of the returned cursor is
    /// specified.
    ///
    /// # Arguments
    ///
    /// `collection` - The collection to read from.
    /// `batch_size` - How many documents the cursor should return at a time.
    /// `flags` - Bit vector of query options.
    /// `number_to_skip` - The number of initial documents to skip over in the
    ///                    query results.
    /// `number_to_return - The total number of documents that should be
    ///                     returned by the query.
    /// `return_field_selector - An optional projection of which fields should
    ///                          be present in the documents to be returned by
    ///                          the query.
    ///
    /// # Return value
    ///
    /// Returns the cursor for the query results on success, or an error string
    /// on failure.
    pub fn query_with_batch_size(collection: &'a Collection<'a>,
                                 batch_size: i32,
                                 flags: OpQueryFlags,
                                 number_to_skip: i32, number_to_return: i32,
                                 query: bson::Document,
                                 return_field_selector: Option<bson::Document>) -> Result<Cursor<'a>, String> {
        let result = Message::with_query(collection.get_req_id(), flags,
                                         collection.namespace.to_owned(),
                                         number_to_skip, number_to_return,
                                         query, return_field_selector);

        let socket = match collection.db.client.socket.lock() {
            Ok(val) => val,
            Err(_) => return Err("Socket lock is poisoned.".to_owned()),
        };

        let message = try!(result);
        try!(message.write(&mut *socket.borrow_mut()));
        let reply = try!(Message::read(&mut *socket.borrow_mut()));

        match Cursor::get_bson_and_cid_from_message(reply) {
            Some((buf, cursor_id)) => Ok(Cursor {
                collection: collection,
                batch_size: batch_size,
                cursor_id: cursor_id,
                limit: number_to_return,
                count: 0,
                buffer: buf,
            }),
            None => Err("Invalid response received".to_owned()),
        }
    }

    /// Executes a query with the default batch size.
    ///
    /// # Arguments
    ///
    /// `collection` - The collection to read from.
    /// `flags` - Bit vector of query options.
    /// `number_to_skip` - The number of initial documents to skip over in the
    ///                    query results.
    /// `number_to_return - The total number of documents that should be
    ///                     returned by the query.
    /// `query` - Specifies which documents to return.
    /// `return_field_selector - An optional projection of which fields should
    ///                          be present in the documents to be returned by
    ///                          the query.
    ///
    /// # Return value
    ///
    /// Returns the cursor for the query results on success, or an error string
    /// on failure.
    pub fn query(collection: &'a Collection<'a>, flags: OpQueryFlags,
                 number_to_skip: i32, number_to_return: i32, query: bson::Document,
                 return_field_selector: Option<bson::Document>) -> Result<Cursor<'a>, String> {

        Cursor::query_with_batch_size(collection, DEFAULT_BATCH_SIZE, flags,
                                      number_to_skip,
                                      number_to_return, query,
                                      return_field_selector)
    }

    /// Helper method to create a "get more" request.
    ///
    /// # Return value
    ///
    /// Returns the newly-created method.
    fn new_get_more_request(&mut self) -> Message {
        Message::with_get_more(self.collection.get_req_id(),
                               self.collection.namespace.to_owned(),
                               self.batch_size, self.cursor_id)
    }

    /// Attempts to read another batch of BSON documents from the stream.
    fn get_from_stream(&mut self) -> Result<(), String> {
        let socket = match self.collection.db.client.socket.lock() {
            Ok(val) => val,
            Err(_) => return Err("Socket lock is poisoned.".to_owned()),
        };

        let get_more = self.new_get_more_request();
        try!(get_more.write(&mut *socket.borrow_mut()));
        let reply = try!(Message::read(&mut *socket.borrow_mut()));

        match Cursor::get_bson_and_cid_from_message(reply) {
            Some((v, _)) => {
                self.buffer.extend(v);
                Ok(())
            },
            None => Err("No bson found from server reply.".to_owned()),
        }
    }

    /// Attempts to read another batch of BSON documents from the stream.
    ///
    /// # Return value
    ///
    /// Returns the first BSON document returned from the stream, or `None` if
    /// there are no more documents to read.
    fn next_from_stream(&mut self) -> Option<bson::Document> {
        self.get_from_stream();
        self.buffer.pop_front()
    }

    /// Attempts to read a specified number of BSON documents from the cursor.
    ///
    /// # Arguments
    ///
    /// `n` - The number of documents to read.
    ///
    /// # Return value
    ///
    /// Returns a vector containing the BSON documents that were read.
    pub fn next_n(&mut self, n: i32) -> Vec<bson::Document> {
        let mut vec = vec![];

        for _ in 0..n {
            let bson_option = self.next();

            match bson_option {
                Some(bson) => vec.push(bson),
                None => break
            };
        }

        vec
    }

    /// Attempts to read a batch of BSON documents from the cursor.
    ///
    /// # Return value
    ///
    /// Returns a vector containing the BSON documents that were read.
    pub fn next_batch(&mut self) -> Vec<bson::Document> {
        let n = self.batch_size;

        self.next_n(n)
    }

    pub fn has_next(&mut self) -> bool {
        if self.limit > 0 && self.count >= self.limit {
            false
        } else {
            if self.buffer.is_empty() && self.limit != 1 {
                self.get_from_stream();
            }
            !self.buffer.is_empty()
        }
    }
}

impl <'a> Iterator for Cursor<'a> {
    type Item = bson::Document;

    /// Attempts to read a BSON document from the cursor.
    ///
    /// # Return value
    ///
    /// Returns the document that was read, or `None` if there are no more
    /// documents to read.
    fn next(&mut self) -> Option<bson::Document> {
        if self.has_next() {
            self.count += 1;
            self.buffer.pop_front()
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use analysis::namespaces;
use analysis::rust_type::rust_type;
use codegen::general;
use config::gobjects::GObject;
use env::Env;
use file_saver;
use library::*;
use std::io::prelude::*;
use std::io::Result;
use std::path::Path;
use traits::*;

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    let configs: Vec<&GObject> = env.config.objects.values()
        .filter(|c| {
            c.status.need_generate() &&
                c.type_id.map_or(false, |tid| tid.ns_id == namespaces::MAIN)
        })
        .collect();
    let mut has_any = false;
    for config in &configs {
        if let Type::Alias(_) = *env.library.type_(config.type_id.unwrap()) {
            has_any = true;
            break;
        }
    }

    if !has_any {
        return;
    }

    let path = root_path.join("alias.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        try!(general::start_comments(w, &env.config));
        try!(writeln!(w, ""));

        if has_any {
            mod_rs.push("\nmod alias;".into());
        }
        for config in &configs {
            if let Type::Alias(ref alias) = *env.library.type_(config.type_id.unwrap()) {
                mod_rs.push(format!("pub use self::alias::{};", alias.name));
                try!(generate_alias(env, w, alias, config));
            }
        }

        Ok(())
    });
}

fn generate_alias(env: &Env, w: &mut Write, alias: &Alias, _: &GObject) -> Result<()> {
    let typ = rust_type(env, alias.typ).into_string();
    try!(writeln!(w, "pub type {} = {};", alias.name, typ));

    Ok(())
}

<commit_msg>Remove condition that is always true in alias code generator<commit_after>use analysis::namespaces;
use analysis::rust_type::rust_type;
use codegen::general;
use config::gobjects::GObject;
use env::Env;
use file_saver;
use library::*;
use std::io::prelude::*;
use std::io::Result;
use std::path::Path;
use traits::*;

pub fn generate(env: &Env, root_path: &Path, mod_rs: &mut Vec<String>) {
    let configs: Vec<&GObject> = env.config.objects.values()
        .filter(|c| {
            c.status.need_generate() &&
                c.type_id.map_or(false, |tid| tid.ns_id == namespaces::MAIN)
        })
        .collect();
    let mut has_any = false;
    for config in &configs {
        if let Type::Alias(_) = *env.library.type_(config.type_id.unwrap()) {
            has_any = true;
            break;
        }
    }

    if !has_any {
        return;
    }

    let path = root_path.join("alias.rs");
    file_saver::save_to_file(path, env.config.make_backup, |w| {
        try!(general::start_comments(w, &env.config));
        try!(writeln!(w, ""));

        mod_rs.push("\nmod alias;".into());
        for config in &configs {
            if let Type::Alias(ref alias) = *env.library.type_(config.type_id.unwrap()) {
                mod_rs.push(format!("pub use self::alias::{};", alias.name));
                try!(generate_alias(env, w, alias, config));
            }
        }

        Ok(())
    });
}

fn generate_alias(env: &Env, w: &mut Write, alias: &Alias, _: &GObject) -> Result<()> {
    let typ = rust_type(env, alias.typ).into_string();
    try!(writeln!(w, "pub type {} = {};", alias.name, typ));

    Ok(())
}

<|endoftext|>


<commit_before>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Color};

/// A context with color information.
pub struct ColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for ColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }
}

<commit_msg>Added rect to ColorContext<commit_after>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d, Color};
use {RectangleColorContext};

/// A context with color information.
pub struct ColorContext<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
    /// Current color.
    pub color: Field<'a, Color>,
}

impl<'a> Transform2d<'a> for ColorContext<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let trans = translate(x, y);
                Value(multiply(&trans, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let rot = rotate_radians(angle);
                Value(multiply(&rot, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let scale = scale(sx, sy);
                Value(multiply(&scale, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: {
                let shear = shear(sx, sy);
                Value(multiply(&shear, self.transform.get()))
            },
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a> ColorContext<'a> {
    /// Creates a RectangleColorContext.
    #[inline(always)]
    pub fn rect(&'a self, x: f64, y: f64, w: f64, h: f64) -> RectangleColorContext<'a> {
        RectangleColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Borrowed(self.color.get()),
            rect: Value([x, y, w, h]),
        }
    }
}

#[test]
fn test_rect() {
    use {Context};

    let c = Context::new();
    let color = c.rgba(1.0, 0.0, 0.0, 1.0);
    let rect_color = color.rect(0.0, 0.0, 100.0, 100.0);
    assert_eq!(rect_color.rect.get()[2], 100.0);
}

<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use super::{ElfResult, ElfWord, Section, section};
use super::ValidatesWord;
use core::{fmt, mem};

pub trait Header {
    type Word: ElfWord;

    /// Attempt to extract an ELF file header from a slice of bytes.
    /// TODO: should this be a From impl maybe?
    //          - eliza, 03/08/2017
    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self>;

    /// Attempt to extract a section header from a slice of bytes.
    /// TODO: can/should the index be `usize`?
    //          - eliza, 03/08/2017
    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>;

    // Field accessors -------------------------------------------
    fn ident(&self) -> Ident;
    fn get_type(&self) -> Type;
    fn machine(&self) -> Machine;
    /// Offset of the program entry point
    fn entry_point(&self) -> usize;
    /// Offset of the start of program headers
    fn ph_offset(&self) -> usize;
    /// Number of program headers.
    fn ph_count(&self) -> usize;
    /// Size of a program header.
    /// TODO: add function for using this and `ph_count` to make a memrange
    ///       representing the program header entries?
    //          - eliza, 03/08/2017
    fn ph_entry_size(&self) -> usize;
    /// Offset of the start of [section header]s.
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_offset(&self) -> usize;
    /// Number of [section header]s.
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_count(&self) -> usize;
    /// Size of a [section header].
    ///
    /// [section header]: ../section/struct.Header.html
    /// TODO: add function for using this and `sh_count` to make a memrange
    ///       representing the section header entries?
    //          - eliza, 03/08/2017
    fn sh_entry_size(&self) -> usize;
    /// TODO: can this return the flags type?
    //          - eliza, 03/08/2017
    fn flags(&self) -> u32;
    /// Index of the section header [string table].
    ///
    /// [string table]: ../section/struct.StrTable.html"]
    fn sh_str_idx(&self) -> usize;

}

/// FIXME(style): generate more stuff with macros/use `macro_attr` to derive
///               these...
//                  - eliza, 03/08/2017
macro_rules! impl_getters {
    ($(#[$attr:meta])* pub fn $name:ident(&self) -> $ty:ident; $($rest:tt)*) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* fn $name:ident(&self) -> $ty:ident; $($rest:tt)*) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ( $(#[$attr:meta])* pub fn $name: ident (&self)-> $ty: ident; ) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
    };
    ( $(#[$attr:meta])* fn $name: ident (&self)-> $ty: ident; ) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
    };
    () => {};
}

macro_rules! Header {
    (($($size:ty),+) $(pub)* enum $name:ident $($tail:tt)* ) => {
        Header! { @impl $name, $($size)+ }
    };
    (($($size:ty),+) $(pub)* struct $name:ident $($tail:tt)*) => {
        Header! { @impl $name, $($size)+ }
    };
    (@impl $name:ident, $($size:ty)+) => {
        $(impl Header for $name<$size> {
            type Word = $size;
            /// Attempt to extract an ELF file header from a slice of bytes.
            fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self> {
                if input.len() < mem::size_of::<Self>() {
                    Err("Input too short to extract ELF header")
                } else {
                    unsafe { Ok(&super::extract_from_slice::<Self>(input, 0, 1)[0]) }
                }
            }

            /// Attempt to extract a section header from a slice of bytes.
            fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                                    -> ElfResult<&'a Section>
            {
                if idx < section::SHN_LORESERVE {
                    Err("Cannot parse reserved section.")
                } else {
                    // use ValidatesWord to check if this section's Class field
                    // will let us interpret the section with the requested
                    // word length. this is a bit of a hack around the type
                    // system not letting me do this the way I wanted to to....
                    let validator: &ValidatesWord<Self::Word>
                        = &self.ident.class;
                    validator.check()?;

                    // start offset for section
                    let start = self.sh_offset() + idx as usize *
                                self.sh_entry_size();
                    // end offset for section
                    let end = start + self.sh_entry_size();
                    let raw = &input[start .. end];

                    match self.ident.class {
                        // Class::None is always invalid ----------------------
                        Class::None =>
                            Err("Invalid ELF class (ELFCLASSNONE).")
                        // Class and header types mismatch --------------------
                      , Class::Elf64 =>
                            Err("Cannot parse 64-bit section from 32-bit ELF.")
                        // class and header types match -----------------------
                      , Class::Elf32 => unsafe {
                            Ok(&*(raw as *const [u8] as *const u8 as *const Section))
                        }
                    }
                }
            }

            #[inline] fn get_type(&self) -> Type { self.elftype.as_type() }

            impl_getters! {
                #[doc = "Index for the start of [section header]s. \
                         [section header]: ../section/struct.Header.html"]
                fn sh_offset(&self) -> usize;
                fn sh_entry_size(&self) -> usize;
                fn sh_count(&self) -> usize;

                #[doc = "Index for the start of program headers"]
                fn ph_offset(&self) -> usize;
                fn ph_entry_size(&self) -> usize;
                fn ph_count(&self) -> usize;

                #[doc = "Index for the program entry point"]
                fn entry_point(&self) -> usize;
                #[doc = "Index of the section header [string table] \
                         [string table]: ../section/struct.StrTable.html"]
                fn sh_str_idx(&self) -> usize;
                fn flags(&self) -> u32;
                fn ident(&self) -> Ident;
                fn machine(&self) -> Machine;
            }
        })+
    }
}

macro_attr! {
    /// An ELF file header
    #[derive(Copy, Clone, Debug, Header!(u32, u64))]
    #[repr(C, packed)]
    pub struct HeaderRepr<W: ElfWord> {
        /// the ELF [file identifier](struct.Ident.html)
        pub ident: Ident
      , elftype: TypeRepr
      , pub machine: Machine
      , /// Program entry point
        /// TODO: getters for turning these into `usize`?
        //          - eliza, 03/08/2017
        entry_point: W
      , /// Offset for start of program headers
        ph_offset: W
      , /// Offset for start of [section header]s.
        /// [section header]: ../section/struct.Header.html
        sh_offset: W
      , pub flags: u32
      , pub header_size: u16
      , pub ph_entry_size: u16
      , pub ph_count: u16
      , pub sh_entry_size: u16
      , pub sh_count: u16
      , /// Index of the section header string table
        sh_str_idx: u16
    }
}

/// ELF header magic
pub const MAGIC: Magic = [0x7f, b'E', b'L', b'F'];

/// Type of header magic
pub type Magic = [u8; 4];

/// ELF identifier (`e_ident` in the ELF standard)
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Ident {
    /// ELF magic numbers. Must be equal to the [ELF magic], `[0x7, E, L, F]`.
    ///
    /// [ELF magic]: constant.MAGIC.html
    pub magic: Magic
  , /// ELF [file class](enum.Class.html) (32- or 64-bit)
    pub class: Class
  , /// ELF [data encoding](enum.DataEncoding.html) (big- or little-endian)
    pub encoding: DataEncoding
  , /// ELF file [version](enum.Version.html)
    pub version: Version
  , /// What [operating system ABI] this file was compiled for.
    ///
    /// [operating system ABI]: enum.OsAbi.html
    pub abi: OsAbi
  , /// ABI version (often this is just padding)
    pub abi_version: u8
  , _padding: [u8; 7]
}

impl Ident {
    #[inline] pub fn check_magic(&self) -> bool { self.magic == MAGIC }

    /// Returns true if the identifier section identifies a valid ELF file.
    #[inline] pub fn is_valid(&self) -> bool {
        // the ELF magic number is correct
        self.check_magic() &&
        // the file class is either 32- or 64-bits
        self.class.is_valid() &&
        // the data encoding is either big- or little-endian
        self.encoding.is_valid()
    }
}

/// Identifies the class of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Class {
    /// Invalid ELF class file (`ELFCLASSNONE` in the standard)
    None  = 0
  , /// 32-bit ELF file (`ELFCLASS32` in the standard)
    Elf32 = 1
  , /// 64-bit ELF file (`ELFCLASS64` in the standard)
    Elf64 = 2
}

impl Class {
    /// Returns true if the class field for this file is valid.
    #[inline]
    pub fn is_valid(&self) -> bool {
        match *self { Class::None => false
                    , _ => true
                    }
    }

}

impl ValidatesWord<u64> for Class {
    #[inline]
    fn check(&self) -> ElfResult<()> {
        use self::Class::*;
        match *self {
            None => Err("Invalid ELF type ELFCLASSNONE!")
          , Elf32 => Err("Cannot extract 64-bit section from 32-bit ELF ")
          , Elf64 => Ok(())
        }
    }
}

impl ValidatesWord<u32> for Class {
    #[inline]
    fn check(&self) -> ElfResult<()> {
        use self::Class::*;
        match *self {
            None => Err("Invalid ELF type ELFCLASSNONE!")
          , Elf64 =>
                // TODO: is this actually true?
                //          - eliza, 03/08/2017
                Err("Cannot extract 32-bit section from 64-bit ELF ")
          , Elf32 => Ok(())
        }
    }
}

/// Identifies the data encoding of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum DataEncoding {
    /// Invalid data encoding (`ELFDATANONE` in the standard)
    None  = 0
  , /// Twos-complement little-endian data encoding
    /// (`ELFDATA2LSB` in the standard)
    LittleEndian = 1
  , /// Twos-complement big-endian data encoding
    /// (`ELFDATA2MSB` in the standard)
    BigEndian = 2
}

impl DataEncoding {
    /// Returns true if the data encoding field for this file is valid.
    #[inline]
    pub fn is_valid(&self) -> bool {
        match *self { DataEncoding::None => false
                    , _ => true
                    }
    }
}

/// Operating system ABI
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
pub enum OsAbi { /// Ox00 also represents "none"
                 SystemV = 0x00
               , HpUx    = 0x01
               , NetBsd  = 0x02
               , Linux   = 0x03
               , Solaris = 0x06
               , Aix     = 0x07
               , Irix    = 0x08
               , FreeBsd = 0x09
               , OpenBsd = 0x0C
               , OpenVms = 0x0D
               }

/// Identifies the version of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Version { None = 0, Current = 1 }

#[derive(Clone, Copy, PartialEq)]
struct TypeRepr(u16);

impl TypeRepr {
    pub fn as_type(&self) -> Type {
        match self.0 {
            0 => Type::None
          , 1 => Type::Relocatable
          , 2 => Type::Executable
          , 3 => Type::SharedObject
          , 4 => Type::Core
          , anything => Type::Other(anything)
        }
    }
}

impl fmt::Debug for TypeRepr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_type().fmt(f)
    }
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Type { None
              , Relocatable
              , Executable
              , SharedObject
              , Core
              , Other(u16)
              }

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u16)]
pub enum Machine { None    = 0
                 , Sparc   = 0x02
                 , X86     = 0x03
                 , Mips    = 0x08
                 , PowerPc = 0x14
                 , Arm     = 0x28
                 , SuperH  = 0x2A
                 , Ia64    = 0x32
                 , X86_64  = 0x3E
                 , AArch64 = 0xB7
                 }
<commit_msg>fix(elf): fix a typo in elf::file::Class<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use super::{ElfResult, ElfWord, Section, section};
use super::ValidatesWord;
use core::{fmt, mem};

pub trait Header {
    type Word: ElfWord;

    /// Attempt to extract an ELF file header from a slice of bytes.
    /// TODO: should this be a From impl maybe?
    //          - eliza, 03/08/2017
    fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self>;

    /// Attempt to extract a section header from a slice of bytes.
    /// TODO: can/should the index be `usize`?
    //          - eliza, 03/08/2017
    fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                            -> ElfResult<&'a Section>;

    // Field accessors -------------------------------------------
    fn ident(&self) -> Ident;
    fn get_type(&self) -> Type;
    fn machine(&self) -> Machine;
    /// Offset of the program entry point
    fn entry_point(&self) -> usize;
    /// Offset of the start of program headers
    fn ph_offset(&self) -> usize;
    /// Number of program headers.
    fn ph_count(&self) -> usize;
    /// Size of a program header.
    /// TODO: add function for using this and `ph_count` to make a memrange
    ///       representing the program header entries?
    //          - eliza, 03/08/2017
    fn ph_entry_size(&self) -> usize;
    /// Offset of the start of [section header]s.
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_offset(&self) -> usize;
    /// Number of [section header]s.
    ///
    /// [section header]: ../section/struct.Header.html
    fn sh_count(&self) -> usize;
    /// Size of a [section header].
    ///
    /// [section header]: ../section/struct.Header.html
    /// TODO: add function for using this and `sh_count` to make a memrange
    ///       representing the section header entries?
    //          - eliza, 03/08/2017
    fn sh_entry_size(&self) -> usize;
    /// TODO: can this return the flags type?
    //          - eliza, 03/08/2017
    fn flags(&self) -> u32;
    /// Index of the section header [string table].
    ///
    /// [string table]: ../section/struct.StrTable.html"]
    fn sh_str_idx(&self) -> usize;

}

/// FIXME(style): generate more stuff with macros/use `macro_attr` to derive
///               these...
//                  - eliza, 03/08/2017
macro_rules! impl_getters {
    ($(#[$attr:meta])* pub fn $name:ident(&self) -> $ty:ident; $($rest:tt)*) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ($(#[$attr:meta])* fn $name:ident(&self) -> $ty:ident; $($rest:tt)*) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
        impl_getters!{ $( $rest )* }
    };
    ( $(#[$attr:meta])* pub fn $name: ident (&self)-> $ty: ident; ) => {
        $(#[$attr])* #[inline] pub fn $name(&self) -> $ty { self.$name as $ty }
    };
    ( $(#[$attr:meta])* fn $name: ident (&self)-> $ty: ident; ) => {
        $(#[$attr])* #[inline] fn $name(&self) -> $ty { self.$name as $ty }
    };
    () => {};
}

macro_rules! Header {
    (($($size:ty),+) $(pub)* enum $name:ident $($tail:tt)* ) => {
        Header! { @impl $name, $($size)+ }
    };
    (($($size:ty),+) $(pub)* struct $name:ident $($tail:tt)*) => {
        Header! { @impl $name, $($size)+ }
    };
    (@impl $name:ident, $($size:ty)+) => {
        $(impl Header for $name<$size> {
            type Word = $size;
            /// Attempt to extract an ELF file header from a slice of bytes.
            fn from_slice<'a>(input: &'a [u8]) -> ElfResult<&'a Self> {
                if input.len() < mem::size_of::<Self>() {
                    Err("Input too short to extract ELF header")
                } else {
                    unsafe { Ok(&super::extract_from_slice::<Self>(input, 0, 1)[0]) }
                }
            }

            /// Attempt to extract a section header from a slice of bytes.
            fn parse_section<'a>(&'a self, input: &'a [u8], idx: u16)
                                    -> ElfResult<&'a Section>
            {
                if idx < section::SHN_LORESERVE {
                    Err("Cannot parse reserved section.")
                } else {
                    // use ValidatesWord to check if this section's Class field
                    // will let us interpret the section with the requested
                    // word length. this is a bit of a hack around the type
                    // system not letting me do this the way I wanted to to....
                    let validator: &ValidatesWord<Self::Word>
                        = &self.ident.class;
                    validator.check()?;

                    // start offset for section
                    let start = self.sh_offset() + idx as usize *
                                self.sh_entry_size();
                    // end offset for section
                    let end = start + self.sh_entry_size();
                    let raw = &input[start .. end];

                    match self.ident.class {
                        // Class::None is always invalid ----------------------
                        Class::None =>
                            Err("Invalid ELF class (ELFCLASSNONE).")
                        // Class and header types mismatch --------------------
                      , Class::Elf64 =>
                            Err("Cannot parse 64-bit section from 32-bit ELF.")
                        // class and header types match -----------------------
                      , Class::Elf32 => unsafe {
                            Ok(&*(raw as *const [u8] as *const u8 as *const Section))
                        }
                    }
                }
            }

            #[inline] fn get_type(&self) -> Type { self.elftype.as_type() }

            impl_getters! {
                #[doc = "Index for the start of [section header]s. \
                         [section header]: ../section/struct.Header.html"]
                fn sh_offset(&self) -> usize;
                fn sh_entry_size(&self) -> usize;
                fn sh_count(&self) -> usize;

                #[doc = "Index for the start of program headers"]
                fn ph_offset(&self) -> usize;
                fn ph_entry_size(&self) -> usize;
                fn ph_count(&self) -> usize;

                #[doc = "Index for the program entry point"]
                fn entry_point(&self) -> usize;
                #[doc = "Index of the section header [string table] \
                         [string table]: ../section/struct.StrTable.html"]
                fn sh_str_idx(&self) -> usize;
                fn flags(&self) -> u32;
                fn ident(&self) -> Ident;
                fn machine(&self) -> Machine;
            }
        })+
    }
}

macro_attr! {
    /// An ELF file header
    #[derive(Copy, Clone, Debug, Header!(u32, u64))]
    #[repr(C, packed)]
    pub struct HeaderRepr<W: ElfWord> {
        /// the ELF [file identifier](struct.Ident.html)
        pub ident: Ident
      , elftype: TypeRepr
      , pub machine: Machine
      , /// Program entry point
        /// TODO: getters for turning these into `usize`?
        //          - eliza, 03/08/2017
        entry_point: W
      , /// Offset for start of program headers
        ph_offset: W
      , /// Offset for start of [section header]s.
        /// [section header]: ../section/struct.Header.html
        sh_offset: W
      , pub flags: u32
      , pub header_size: u16
      , pub ph_entry_size: u16
      , pub ph_count: u16
      , pub sh_entry_size: u16
      , pub sh_count: u16
      , /// Index of the section header string table
        sh_str_idx: u16
    }
}

/// ELF header magic
pub const MAGIC: Magic = [0x7f, b'E', b'L', b'F'];

/// Type of header magic
pub type Magic = [u8; 4];

/// ELF identifier (`e_ident` in the ELF standard)
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct Ident {
    /// ELF magic numbers. Must be equal to the [ELF magic], `[0x7, E, L, F]`.
    ///
    /// [ELF magic]: constant.MAGIC.html
    pub magic: Magic
  , /// ELF [file class](enum.Class.html) (32- or 64-bit)
    pub class: Class
  , /// ELF [data encoding](enum.DataEncoding.html) (big- or little-endian)
    pub encoding: DataEncoding
  , /// ELF file [version](enum.Version.html)
    pub version: Version
  , /// What [operating system ABI] this file was compiled for.
    ///
    /// [operating system ABI]: enum.OsAbi.html
    pub abi: OsAbi
  , /// ABI version (often this is just padding)
    pub abi_version: u8
  , _padding: [u8; 7]
}

impl Ident {
    #[inline] pub fn check_magic(&self) -> bool { self.magic == MAGIC }

    /// Returns true if the identifier section identifies a valid ELF file.
    #[inline] pub fn is_valid(&self) -> bool {
        // the ELF magic number is correct
        self.check_magic() &&
        // the file class is either 32- or 64-bits
        self.class.is_valid() &&
        // the data encoding is either big- or little-endian
        self.encoding.is_valid()
    }
}

/// Identifies the class of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Class {
    /// Invalid ELF class file (`ELFCLASSNONE` in the standard)
    None  = 0
  , /// 32-bit ELF file (`ELFCLASS32` in the standard)
    Elf32 = 1
  , /// 64-bit ELF file (`ELFCLASS64` in the standard)
    Elf64 = 2
}

impl Class {
    /// Returns true if the class field for this file is valid.
    #[inline]
    pub fn is_valid(&self) -> bool {
        match *self { Class::None => false
                    , _ => true
                    }
    }

}

impl ValidatesWord<u64> for Class {
    #[inline]
    fn check(&self) -> ElfResult<()> {
        use self::Class::*;
        match *self {
            None => Err("Invalid ELF type ELFCLASSNONE!")
          , Elf32 => Err("Cannot extract 64-bit section from 32-bit ELF")
          , Elf64 => Ok(())
        }
    }
}

impl ValidatesWord<u32> for Class {
    #[inline]
    fn check(&self) -> ElfResult<()> {
        use self::Class::*;
        match *self {
            None => Err("Invalid ELF type ELFCLASSNONE!")
          , Elf64 =>
                // TODO: is this actually true?
                //          - eliza, 03/08/2017
                Err("Cannot extract 32-bit section from 64-bit ELF")
          , Elf32 => Ok(())
        }
    }
}

/// Identifies the data encoding of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum DataEncoding {
    /// Invalid data encoding (`ELFDATANONE` in the standard)
    None  = 0
  , /// Twos-complement little-endian data encoding
    /// (`ELFDATA2LSB` in the standard)
    LittleEndian = 1
  , /// Twos-complement big-endian data encoding
    /// (`ELFDATA2MSB` in the standard)
    BigEndian = 2
}

impl DataEncoding {
    /// Returns true if the data encoding field for this file is valid.
    #[inline]
    pub fn is_valid(&self) -> bool {
        match *self { DataEncoding::None => false
                    , _ => true
                    }
    }
}

/// Operating system ABI
#[derive(Copy, Clone, Debug)]
#[repr(u8)]
pub enum OsAbi { /// Ox00 also represents "none"
                 SystemV = 0x00
               , HpUx    = 0x01
               , NetBsd  = 0x02
               , Linux   = 0x03
               , Solaris = 0x06
               , Aix     = 0x07
               , Irix    = 0x08
               , FreeBsd = 0x09
               , OpenBsd = 0x0C
               , OpenVms = 0x0D
               }

/// Identifies the version of the ELF file
#[derive(Copy, Clone, PartialEq, Debug)]
#[repr(u8)]
pub enum Version { None = 0, Current = 1 }

#[derive(Clone, Copy, PartialEq)]
struct TypeRepr(u16);

impl TypeRepr {
    pub fn as_type(&self) -> Type {
        match self.0 {
            0 => Type::None
          , 1 => Type::Relocatable
          , 2 => Type::Executable
          , 3 => Type::SharedObject
          , 4 => Type::Core
          , anything => Type::Other(anything)
        }
    }
}

impl fmt::Debug for TypeRepr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_type().fmt(f)
    }
}

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Type { None
              , Relocatable
              , Executable
              , SharedObject
              , Core
              , Other(u16)
              }

#[allow(non_camel_case_types)]
#[derive(Clone, Copy, PartialEq, Debug)]
#[repr(u16)]
pub enum Machine { None    = 0
                 , Sparc   = 0x02
                 , X86     = 0x03
                 , Mips    = 0x08
                 , PowerPc = 0x14
                 , Arm     = 0x28
                 , SuperH  = 0x2A
                 , Ia64    = 0x32
                 , X86_64  = 0x3E
                 , AArch64 = 0xB7
                 }
<|endoftext|>