<commit_before>#[llvm_versions(9.0..=latest)]
use llvm_sys::core::{LLVMGetIntrinsicDeclaration, LLVMIntrinsicIsOverloaded, LLVMLookupIntrinsicID};
use llvm_sys::prelude::LLVMTypeRef;

use crate::module::Module;
use crate::types::{AsTypeRef, BasicTypeEnum, FunctionType};
use crate::values::FunctionValue;

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Intrinsic {
    id: u32,
}

/// A wrapper around LLVM intrinsic id
///
/// To call it you would need to create a declaration inside a module using [`Self::get_declaration()`].
#[llvm_versions(9.0..=latest)]
impl Intrinsic {
    /// Create an Intrinsic object from raw LLVM intrinsic id
    ///
    /// SAFETY: the id is a valid LLVM intrinsic ID
    pub(crate) unsafe fn new(id: u32) -> Self {
        Self {
            id
        }
    }

    /// Find llvm intrinsic id from name
    ///
    /// # Example
    /// ```no_run
    /// use inkwell::intrinsics::Intrinsic;
    ///
    /// let trap_intrinsic = Intrinsic::find("llvm.trap").unwrap();
    ///
    /// let context = Context::create();
    /// let module = context.create_module("trap");
    /// let builder = context.create_builder();
    /// let fn_type = struct_type.fn_type(&[], false);
    /// let fn_value = module.add_function("trap", fn_type, None);
    /// let entry = context.append_basic_block(fn_value, "entry");
    ///
    /// let trap_function = trap_intrinsic.get_declaration(module, &[]).unwrap();
    ///
    /// builder.position_at_end(entry);
    /// builder.build(trap_function, &[], "trap_call");
    /// ```
    pub fn find(name: &str) -> Option<Self> {
        let id = unsafe {
            LLVMLookupIntrinsicID(name.as_ptr() as *const ::libc::c_char, name.len())
        };

        if id == 0 {
            return None;
        }

        return Some(unsafe {
            Intrinsic::new(id)
        });
    }

    /// Check if specified intrinsic is overloaded
    ///
    /// Overloaded intrinsics need some argument types to be specified to declare them
    pub fn is_overloaded(&self) -> bool {
        unsafe {
            LLVMIntrinsicIsOverloaded(self.id) != 0
        }
    }

    /// Create or insert the declaration of an intrinsic.
    ///
    /// For overloaded intrinsics, parameter types must be provided to uniquely identify an overload.
    ///
    /// # Example
    /// ```no_run
    /// use inkwell::intrinsics::Intrinsic;
    ///
    /// let trap_intrinsic = Intrinsic::find("llvm.trap").unwrap();
    ///
    /// let context = Context::create();
    /// let module = context.create_module("trap");
    /// let builder = context.create_builder();
    /// let fn_type = struct_type.fn_type(&[], false);
    /// let fn_value = module.add_function("trap", fn_type, None);
    /// let entry = context.append_basic_block(fn_value, "entry");
    ///
    /// let trap_function = trap_intrinsic.get_declaration(module, &[]).unwrap();
    ///
    /// builder.position_at_end(entry);
    /// builder.build(trap_function, &[], "trap_call");
    /// ```
    pub fn get_declaration<'ctx>(&self, module: &Module<'ctx>, param_types: &[BasicTypeEnum]) -> Option<FunctionValue<'ctx>> {
        let mut param_types: Vec<LLVMTypeRef> = param_types.iter()
            .map(|val| val.as_type_ref())
            .collect();

        // param_types should be empty for non-overloaded intrinsics (I think?)
        // for overloaded intrinsics they determine the overload used

        if self.is_overloaded() && param_types.is_empty() {
            // LLVM crashes otherwise
            return None;
        }

        let res = unsafe {
            FunctionValue::new(
                LLVMGetIntrinsicDeclaration(
                    module.module.get(),
                    self.id,
                    param_types.as_mut_ptr(),
                    param_types.len()
                )
            )
        };

        res
    }
}<commit_msg>Fix doctests<commit_after>#[llvm_versions(9.0..=latest)]
use llvm_sys::core::{LLVMGetIntrinsicDeclaration, LLVMIntrinsicIsOverloaded, LLVMLookupIntrinsicID};
use llvm_sys::prelude::LLVMTypeRef;

use crate::module::Module;
use crate::types::{AsTypeRef, BasicTypeEnum, FunctionType};
use crate::values::FunctionValue;

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Intrinsic {
    id: u32,
}

/// A wrapper around LLVM intrinsic id
///
/// To call it you would need to create a declaration inside a module using [`Self::get_declaration()`].
#[llvm_versions(9.0..=latest)]
impl Intrinsic {
    /// Create an Intrinsic object from raw LLVM intrinsic id
    ///
    /// SAFETY: the id is a valid LLVM intrinsic ID
    pub(crate) unsafe fn new(id: u32) -> Self {
        Self {
            id
        }
    }

    /// Find llvm intrinsic id from name
    ///
    /// # Example
    /// ```no_run
    /// use inkwell::{intrinsics::Intrinsic, context::Context};
    ///
    /// let trap_intrinsic = Intrinsic::find("llvm.trap").unwrap();
    ///
    /// let context = Context::create();
    /// let module = context.create_module("trap");
    /// let builder = context.create_builder();
    /// let void_type = context.void_type();
    /// let fn_type = void_type.fn_type(&[], false);
    /// let fn_value = module.add_function("trap", fn_type, None);
    /// let entry = context.append_basic_block(fn_value, "entry");
    ///
    /// let trap_function = trap_intrinsic.get_declaration(&module, &[]).unwrap();
    ///
    /// builder.position_at_end(entry);
    /// builder.build_call(trap_function, &[], "trap_call");
    /// ```
    pub fn find(name: &str) -> Option<Self> {
        let id = unsafe {
            LLVMLookupIntrinsicID(name.as_ptr() as *const ::libc::c_char, name.len())
        };

        if id == 0 {
            return None;
        }

        return Some(unsafe {
            Intrinsic::new(id)
        });
    }

    /// Check if specified intrinsic is overloaded
    ///
    /// Overloaded intrinsics need some argument types to be specified to declare them
    pub fn is_overloaded(&self) -> bool {
        unsafe {
            LLVMIntrinsicIsOverloaded(self.id) != 0
        }
    }

    /// Create or insert the declaration of an intrinsic.
    ///
    /// For overloaded intrinsics, parameter types must be provided to uniquely identify an overload.
    ///
    /// # Example
    /// ```no_run
    /// use inkwell::{intrinsics::Intrinsic, context::Context};
    ///
    /// let trap_intrinsic = Intrinsic::find("llvm.trap").unwrap();
    ///
    /// let context = Context::create();
    /// let module = context.create_module("trap");
    /// let builder = context.create_builder();
    /// let void_type = context.void_type();
    /// let fn_type = void_type.fn_type(&[], false);
    /// let fn_value = module.add_function("trap", fn_type, None);
    /// let entry = context.append_basic_block(fn_value, "entry");
    ///
    /// let trap_function = trap_intrinsic.get_declaration(&module, &[]).unwrap();
    ///
    /// builder.position_at_end(entry);
    /// builder.build_call(trap_function, &[], "trap_call");
    /// ```
    pub fn get_declaration<'ctx>(&self, module: &Module<'ctx>, param_types: &[BasicTypeEnum]) -> Option<FunctionValue<'ctx>> {
        let mut param_types: Vec<LLVMTypeRef> = param_types.iter()
            .map(|val| val.as_type_ref())
            .collect();

        // param_types should be empty for non-overloaded intrinsics (I think?)
        // for overloaded intrinsics they determine the overload used

        if self.is_overloaded() && param_types.is_empty() {
            // LLVM crashes otherwise
            return None;
        }

        let res = unsafe {
            FunctionValue::new(
                LLVMGetIntrinsicDeclaration(
                    module.module.get(),
                    self.id,
                    param_types.as_mut_ptr(),
                    param_types.len()
                )
            )
        };

        res
    }
}<|endoftext|>


<commit_before>// 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.

#![allow(missing_docs)]

use std::str;
use super::ast::*;

pub struct Parser<'a> {
    source: str::Chars<'a>,
    ch: Option<char>,
    pos: u16,
}

impl<'a> Parser<'a> {
    pub fn new(source: &'a str) -> Parser<'a> {
        Parser {
            source: source.chars(),
            ch: None,
            pos: 0,
        }
    }

    fn bump(&mut self) {
        self.ch = self.source.next();

        self.pos += 1;
    }

    fn ch_is(&self, ch: char) -> bool {
        self.ch == Some(ch)
    }

    fn get_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\n') || self.ch_is('\t') || self.ch_is('\r') {
            self.bump();
        }
    }

    fn get_line_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\t') {
            self.bump();
        }
    }

    pub fn parse(&mut self) -> Vec<Entry> {
        let mut entries: Vec<Entry> = Vec::new();

        self.get_ws();

        self.bump();

        loop {
            if self.ch == None {
                break;
            }

            entries.push(self.get_entry());
            self.get_ws();
        }
        entries
    }

    fn get_entry(&mut self) -> Entry {
        let val = self.get_entity();

        val
    }

    fn get_entity(&mut self) -> Entry {
        let id = self.get_identifier();
        self.get_line_ws();

        if !self.ch_is('=') {
            panic!();
        }
        self.bump();

        self.get_line_ws();

        let value = self.get_pattern();

        Entry::Entity {
            id: id,
            value: value,
        }
    }

    fn get_identifier(&mut self) -> Identifier {
        let mut name = String::new();

        let ch = match self.ch {
            Some(c) => c,
            None => panic!(),
        };

        match ch {
            'a'...'z' | 'A'...'Z' | '_' => name.push(ch),
            _ => return Identifier { name: name },
        }
        self.bump();

        loop {
            let ch = match self.ch {
                Some(c) => c,
                None => break,
            };

            match ch {
                'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => name.push(ch),
                _ => break,
            }
            self.bump();
        }

        Identifier { name: name }
    }

    fn get_pattern(&mut self) -> Value {
        let mut buffer = String::new();
        let mut source = String::new();
        let mut content = vec![];
        let mut quote_delimited: bool = false;
        let mut first_line = true;

        if self.ch_is('"') {
            quote_delimited = true;
        }

        loop {
            match self.ch {
                Some(c) if c == '\n' => {
                    if quote_delimited {
                        panic!("Unclosed string");
                    }
                    self.bump();
                    self.get_line_ws();

                    if !self.ch_is('|') {
                        break;
                    }
                    if first_line && buffer.len() != 0 {
                        panic!("Multiline string should have the ID line empty");
                    }
                    first_line = false;
                    self.bump();
                    if self.ch_is(' ') {
                        self.bump();
                    }
                    if buffer.len() != 0 {
                        buffer.push('\n');
                    }
                    continue;
                }
                Some(c) if c == '"' => {
                    self.bump();
                    quote_delimited = false;
                    break;
                }
                Some(c) => source.push(c),
                None => break,
            }
            match self.ch {
                Some(c) => buffer.push(c),
                None => continue,
            };
            self.bump();
        }

        if quote_delimited {
            panic!("Unclosed string");
        }

        if buffer.len() != 0 {
            // source.append(buffer);
            content.push(PatternElement::TextElement { value: source.clone() });
        }

        if content.len() == 0 {
            // return Value::Pattern(source: source, elements: content);
        }

        content.push(PatternElement::TextElement { value: source.clone() });

        Value::Pattern {
            source: source,
            elements: content,
        }
    }
}
<commit_msg>Use Result to propagate errors.<commit_after>// 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.

#![allow(missing_docs)]

use std::str;
use super::ast::*;

pub struct ParseError {
    pub error_message: String,
}

impl ParseError {
    pub fn new(error_message: &str) -> Self {
        ParseError { error_message: String::from(error_message) }
    }
}

pub struct Parser<'a> {
    source: str::Chars<'a>,
    ch: Option<char>,
    pos: u16,
}

impl<'a> Parser<'a> {
    pub fn new(source: &'a str) -> Parser<'a> {
        Parser {
            source: source.chars(),
            ch: None,
            pos: 0,
        }
    }

    fn bump(&mut self) {
        self.ch = self.source.next();

        self.pos += 1;
    }

    fn ch_is(&self, ch: char) -> bool {
        self.ch == Some(ch)
    }

    fn get_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\n') || self.ch_is('\t') || self.ch_is('\r') {
            self.bump();
        }
    }

    fn get_line_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\t') {
            self.bump();
        }
    }

    pub fn parse(&mut self) -> Result<Vec<Entry>, ParseError> {
        let mut entries: Vec<Entry> = Vec::new();

        self.get_ws();

        self.bump();

        loop {
            if self.ch == None {
                break;
            }

            match self.get_entry() {
                Ok(entry) => entries.push(entry),
                Err(err) => return Err(err),
            }
            self.get_ws();
        }
        Ok(entries)
    }

    fn get_entry(&mut self) -> Result<Entry, ParseError> {
        self.get_entity()
    }

    fn get_entity(&mut self) -> Result<Entry, ParseError> {
        let id = try!(self.get_identifier());
        self.get_line_ws();

        if !self.ch_is('=') {
            return Err(ParseError::new("Expected '='"));
        }
        self.bump();

        self.get_line_ws();

        match self.get_pattern() {
            Ok(value) => {
                Ok(Entry::Entity {
                    id: id,
                    value: value,
                })
            }
            Err(err) => Err(err),
        }
    }

    fn get_identifier(&mut self) -> Result<Identifier, ParseError> {
        let mut name = String::new();

        let ch = match self.ch {
            Some(c) => c,
            None => return Err(ParseError::new("Unexpected end of input.")),
        };

        match ch {
            'a'...'z' | 'A'...'Z' | '_' => name.push(ch),
            _ => return Ok(Identifier { name: name }),
        }
        self.bump();

        loop {
            let ch = match self.ch {
                Some(c) => c,
                None => break,
            };

            match ch {
                'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => name.push(ch),
                _ => break,
            }
            self.bump();
        }

        Ok(Identifier { name: name })
    }

    fn get_pattern(&mut self) -> Result<Value, ParseError> {
        let mut buffer = String::new();
        let mut source = String::new();
        let mut content = vec![];
        let mut quote_delimited: bool = false;
        let mut first_line = true;

        if self.ch_is('"') {
            quote_delimited = true;
        }

        loop {
            match self.ch {
                Some(c) if c == '\n' => {
                    if quote_delimited {
                        return Err(ParseError::new("Unclosed string"));
                    }
                    self.bump();
                    self.get_line_ws();

                    if !self.ch_is('|') {
                        break;
                    }
                    if first_line && buffer.len() != 0 {
                        return Err(ParseError::new("Multiline string should have the ID line \
                                                    empty"));
                    }
                    first_line = false;
                    self.bump();
                    if self.ch_is(' ') {
                        self.bump();
                    }
                    if buffer.len() != 0 {
                        buffer.push('\n');
                    }
                    continue;
                }
                Some(c) if c == '"' => {
                    self.bump();
                    quote_delimited = false;
                    break;
                }
                Some(c) => source.push(c),
                None => break,
            }
            match self.ch {
                Some(c) => buffer.push(c),
                None => continue,
            };
            self.bump();
        }

        if quote_delimited {
            return Err(ParseError::new("Unclosed string"));
        }

        if buffer.len() != 0 {
            // source.append(buffer);
            content.push(PatternElement::TextElement { value: source.clone() });
        }

        if content.len() == 0 {
            // return Value::Pattern(source: source, elements: content);
        }

        content.push(PatternElement::TextElement { value: source.clone() });

        Ok(Value::Pattern {
            source: source,
            elements: content,
        })
    }
}
<|endoftext|>


<commit_before>// 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.

#![allow(missing_docs)]

use std::str;
use super::ast::*;

pub struct ParseError {
    pub error_message: String,
}

impl ParseError {
    pub fn new(error_message: &str) -> Self {
        ParseError { error_message: String::from(error_message) }
    }
}

pub struct Parser<'a> {
    source: str::Chars<'a>,
    ch: Option<char>,
    pos: u16,
}

impl<'a> Parser<'a> {
    pub fn new(source: &'a str) -> Parser<'a> {
        Parser {
            source: source.chars(),
            ch: None,
            pos: 0,
        }
    }

    fn bump(&mut self) {
        self.ch = self.source.next();

        self.pos += 1;
    }

    fn ch_is(&self, ch: char) -> bool {
        self.ch == Some(ch)
    }

    fn get_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\n') || self.ch_is('\t') || self.ch_is('\r') {
            self.bump();
        }
    }

    fn get_line_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\t') {
            self.bump();
        }
    }

    pub fn parse(&mut self) -> Result<Vec<Entry>, ParseError> {
        let mut entries: Vec<Entry> = Vec::new();

        self.get_ws();

        self.bump();

        loop {
            if self.ch == None {
                break;
            }

            match self.get_entry() {
                Ok(entry) => entries.push(entry),
                Err(err) => return Err(err),
            }
            self.get_ws();
        }
        Ok(entries)
    }

    fn get_entry(&mut self) -> Result<Entry, ParseError> {
        self.get_entity()
    }

    fn get_entity(&mut self) -> Result<Entry, ParseError> {
        let id = try!(self.get_identifier());
        self.get_line_ws();

        if !self.ch_is('=') {
            return Err(ParseError::new("Expected '='"));
        }
        self.bump();

        self.get_line_ws();

        match self.get_pattern() {
            Ok(value) => {
                Ok(Entry::Entity {
                    id: id,
                    value: value,
                })
            }
            Err(err) => Err(err),
        }
    }

    fn get_identifier(&mut self) -> Result<Identifier, ParseError> {
        let mut name = String::new();

        let ch = match self.ch {
            Some(c) => c,
            None => return Err(ParseError::new("Unexpected end of input.")),
        };

        match ch {
            'a'...'z' | 'A'...'Z' | '_' => name.push(ch),
            _ => return Ok(Identifier { name: name }),
        }
        self.bump();

        loop {
            let ch = match self.ch {
                Some(c) => c,
                None => break,
            };

            match ch {
                'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => name.push(ch),
                _ => break,
            }
            self.bump();
        }

        Ok(Identifier { name: name })
    }

    fn get_pattern(&mut self) -> Result<Value, ParseError> {
        let mut buffer = String::new();
        let mut source = String::new();
        let mut content = vec![];
        let mut quote_delimited: bool = false;
        let mut first_line = true;

        if self.ch_is('"') {
            quote_delimited = true;
        }

        loop {
            match self.ch {
                Some(c) if c == '\n' => {
                    if quote_delimited {
                        return Err(ParseError::new("Unclosed string"));
                    }
                    self.bump();
                    self.get_line_ws();

                    if !self.ch_is('|') {
                        break;
                    }
                    if first_line && buffer.len() != 0 {
                        return Err(ParseError::new("Multiline string should have the ID line \
                                                    empty"));
                    }
                    first_line = false;
                    self.bump();
                    if self.ch_is(' ') {
                        self.bump();
                    }
                    if buffer.len() != 0 {
                        buffer.push('\n');
                    }
                    continue;
                }
                Some(c) if c == '"' => {
                    self.bump();
                    quote_delimited = false;
                    break;
                }
                Some(c) => source.push(c),
                None => break,
            }
            match self.ch {
                Some(c) => buffer.push(c),
                None => continue,
            };
            self.bump();
        }

        if quote_delimited {
            return Err(ParseError::new("Unclosed string"));
        }

        if buffer.len() != 0 {
            // source.append(buffer);
            content.push(PatternElement::TextElement { value: source.clone() });
        }

        if content.len() == 0 {
            // return Value::Pattern(source: source, elements: content);
        }

        content.push(PatternElement::TextElement { value: source.clone() });

        Ok(Value::Pattern {
            source: source,
            elements: content,
        })
    }
}
<commit_msg>Impl Debug,Display,Error for l20n ParseError.<commit_after>// 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.

#![allow(missing_docs)]

use std::error::Error;
use std::fmt;
use std::str;
use super::ast::*;

#[derive(Debug)]
pub struct ParseError {
    pub error_message: String,
}

impl ParseError {
    pub fn new(error_message: &str) -> Self {
        ParseError { error_message: String::from(error_message) }
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        &self.error_message
    }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

pub struct Parser<'a> {
    source: str::Chars<'a>,
    ch: Option<char>,
    pos: u16,
}

impl<'a> Parser<'a> {
    pub fn new(source: &'a str) -> Parser<'a> {
        Parser {
            source: source.chars(),
            ch: None,
            pos: 0,
        }
    }

    fn bump(&mut self) {
        self.ch = self.source.next();

        self.pos += 1;
    }

    fn ch_is(&self, ch: char) -> bool {
        self.ch == Some(ch)
    }

    fn get_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\n') || self.ch_is('\t') || self.ch_is('\r') {
            self.bump();
        }
    }

    fn get_line_ws(&mut self) {
        while self.ch_is(' ') || self.ch_is('\t') {
            self.bump();
        }
    }

    pub fn parse(&mut self) -> Result<Vec<Entry>, ParseError> {
        let mut entries: Vec<Entry> = Vec::new();

        self.get_ws();

        self.bump();

        loop {
            if self.ch == None {
                break;
            }

            match self.get_entry() {
                Ok(entry) => entries.push(entry),
                Err(err) => return Err(err),
            }
            self.get_ws();
        }
        Ok(entries)
    }

    fn get_entry(&mut self) -> Result<Entry, ParseError> {
        self.get_entity()
    }

    fn get_entity(&mut self) -> Result<Entry, ParseError> {
        let id = try!(self.get_identifier());
        self.get_line_ws();

        if !self.ch_is('=') {
            return Err(ParseError::new("Expected '='"));
        }
        self.bump();

        self.get_line_ws();

        match self.get_pattern() {
            Ok(value) => {
                Ok(Entry::Entity {
                    id: id,
                    value: value,
                })
            }
            Err(err) => Err(err),
        }
    }

    fn get_identifier(&mut self) -> Result<Identifier, ParseError> {
        let mut name = String::new();

        let ch = match self.ch {
            Some(c) => c,
            None => return Err(ParseError::new("Unexpected end of input.")),
        };

        match ch {
            'a'...'z' | 'A'...'Z' | '_' => name.push(ch),
            _ => return Ok(Identifier { name: name }),
        }
        self.bump();

        loop {
            let ch = match self.ch {
                Some(c) => c,
                None => break,
            };

            match ch {
                'a'...'z' | 'A'...'Z' | '0'...'9' | '_' | '-' => name.push(ch),
                _ => break,
            }
            self.bump();
        }

        Ok(Identifier { name: name })
    }

    fn get_pattern(&mut self) -> Result<Value, ParseError> {
        let mut buffer = String::new();
        let mut source = String::new();
        let mut content = vec![];
        let mut quote_delimited: bool = false;
        let mut first_line = true;

        if self.ch_is('"') {
            quote_delimited = true;
        }

        loop {
            match self.ch {
                Some(c) if c == '\n' => {
                    if quote_delimited {
                        return Err(ParseError::new("Unclosed string"));
                    }
                    self.bump();
                    self.get_line_ws();

                    if !self.ch_is('|') {
                        break;
                    }
                    if first_line && buffer.len() != 0 {
                        return Err(ParseError::new("Multiline string should have the ID line \
                                                    empty"));
                    }
                    first_line = false;
                    self.bump();
                    if self.ch_is(' ') {
                        self.bump();
                    }
                    if buffer.len() != 0 {
                        buffer.push('\n');
                    }
                    continue;
                }
                Some(c) if c == '"' => {
                    self.bump();
                    quote_delimited = false;
                    break;
                }
                Some(c) => source.push(c),
                None => break,
            }
            match self.ch {
                Some(c) => buffer.push(c),
                None => continue,
            };
            self.bump();
        }

        if quote_delimited {
            return Err(ParseError::new("Unclosed string"));
        }

        if buffer.len() != 0 {
            // source.append(buffer);
            content.push(PatternElement::TextElement { value: source.clone() });
        }

        if content.len() == 0 {
            // return Value::Pattern(source: source, elements: content);
        }

        content.push(PatternElement::TextElement { value: source.clone() });

        Ok(Value::Pattern {
            source: source,
            elements: content,
        })
    }
}
<|endoftext|>


<commit_before>
#[macro_export]
macro_rules! make_units { ($System:ident, $allowed_root:ident; base { $($Type:ident, $constant:ident, $print_as:ident;)* } derived {$($Derived:ident($derived_constant: ident) = $e: expr;    )*} ) => (
    pub struct $System<$($Type: Peano),*> {
        $($constant: PhantomData<$Type>),*
    }
    impl<$($Type: Peano),*> Dimension for $System<$($Type),*> {}

    // using $Type and $constant for these traits is confusing. It should really be $Type_Left and
    // $Type_Right or something, but as far as I can tell, that is not supported by Rust
    #[allow(non_camel_case_types)]
    impl<$($Type),*, $($constant),*> KeepDim<$System<$($constant),*>> for $System<$($Type),*> where
        $($Type: Peano + KeepPeano<$constant>),*, $($constant: Peano),* {
            type Output = $System<$(<$Type as KeepPeano<$constant>>::Output),*>;
        }
    #[allow(non_camel_case_types)]
    impl<$($Type),*, $($constant),*> AddDim<$System<$($constant),*>> for $System<$($Type),*> where
        $($Type: Peano + AddPeano<$constant>),*, $($constant: Peano),* {
            type Output = $System<$(<$Type as AddPeano<$constant>>::Output),*>;
        }
    #[allow(non_camel_case_types)]
    impl<$($Type),*, $($constant),*> SubDim<$System<$($constant),*>> for $System<$($Type),*> where
        $($Type: Peano + SubPeano<$constant>),*, $($constant: Peano),* {
            type Output = $System<$(<$Type as SubPeano<$constant>>::Output),*>;
        }
    impl<$($Type),*, RHS> MulDim<RHS> for $System<$($Type),*> where
        $($Type: Peano + MulPeano<RHS>),*, RHS: Peano {
            type Output = $System<$(<$Type as MulPeano<RHS>>::Output),*>;
        }
    impl<$($Type),*, RHS> DivDim<RHS> for $System<$($Type),*> where
        $($Type: Peano + DivPeano<RHS>),*, RHS: Peano {
            type Output = $System<$(<$Type as DivPeano<RHS>>::Output),*>;
        }

    impl<$($Type),*> DimToString for $System<$($Type),*>
        where $($Type: ToInt),* {
            fn to_string() -> String {
                let mut s = String::new();
                $(
                    let temp = match <$Type as ToInt>::to_int() {
                        0 => ("", "".to_string()),
                        1 => (stringify!($print_as), "*".to_string()),
                        n => (stringify!($print_as), format!("^{}*", n/<$allowed_root as ToInt>::to_int()))
                    };
                    s = format!("{}{}{}", s, temp.0, temp.1);
                    )*
                    s.pop();
                s
            }
        }

    _make_types!($System, $allowed_root | $($Type),* | $($Type),* |);
    // fixme: when _make_types is fixed, use following line to call:
    // _make_types!($System, $allowed_root | $($Type),* | $($Type),*);

    #[allow(non_upper_case_globals)]
    pub const one: Dim<Unitless, f64> = Dim(1.0, PhantomData);
    $(#[allow(non_upper_case_globals)] pub const $constant: Dim<$Type, f64> = Dim(1.0, PhantomData);)*

        // $(
        //   _make_derived_type!($Derived, $e);
        //   // pub const $derived_constant = Dim<$Derived, f64> = Dim(1.0, PhantomData);
        //   )*
        );
}

// fixme: This is a bunch of malarky. Can't cycle the direction I want, so we reverse
// $Typse to compensate. The "correct" way is commented below, but won't work until RFC:
// https://github.com/rust-lang/rust/issues/24827 is fixed
#[doc_hidden]
#[macro_export]
macro_rules! _make_types {
    // this first arm filters out the end Types into Zeros with Num, so we go from say
    // (One | Meters, Seconds | Meters, Seconds) to (One, Zero | Meters, Seconds |
    // Meters) and then we move to a different branch I would like a cleaner way to
    // create the list $Num, Zero, Zero, ... but I have yet to find one.
    ($System: ident, $($Nums: ident),+ | $($Types: ident),+ | $DeadType: ident, $($Others: ident),* | $($New: ident),*) => (
        _make_types!($System, $($Nums),+, Zero | $($Types),+ | $($Others),* | $DeadType $(, $New)*);
        );
    // This branch creates our Unitless type and then trims off the last $Type that we no longer need:
    ($System: ident, $First: ident, $($Nums: ident),* | $($Types: ident),+ | $Type: ident | $($New: ident),+) => (
        pub type Unitless = $System<Zero, $($Nums),*>;
        impl Dimensionless for Unitless {}
        _make_types!($System, $($Nums),*, $First | $Type, $($New),* );
        );
    // Create the type, cycle the numbers, then call again:
    ($System: ident, $First: ident, $($Nums: ident),* | $Type: ident, $($Types: ident),+) => (
        pub type $Type = $System<$First, $($Nums),*>;
        _make_types!($System, $($Nums),*, $First | $($Types),*);
        );
    ($System: ident, $($Nums: ident),* | $Type: ident) => (
        pub type $Type = $System<$($Nums),*>;
        );
}
// end of malarky

// // we call this with _make_types!(Num | Types | Types)
// #[doc_hidden]
// #[macro_export]
// macro_rules! _make_types {
//     // this first arm filters out the end Types into Zeros with Num, so we go from say
//     // (One | Meters, Seconds | Meters, Seconds) to (One, Zero | Meters, Seconds |
//     // Meters) and then we move to a different branch I would like a cleaner way to
//     // create the list $Num, Zero, Zero, ... but I have yet to find one.
//     ($System: ident, $($Nums: ident),+ | $($Types: ident),+ | $DeadType: ident, $($Others: ident),+) => (
//         _make_types!($System, $($Nums),*, Zero | $($Types),* | $($Others),*);
//         );
//     // This branch creates our Unitless type and then trims off the last $Type that we no longer need:
//     ($System: ident, $First: ident, $($Nums: ident),* | $($Types: ident),+ | $Type: ident) => (
//         pub type Unitless = $System<Zero, $($Nums),*>;
//         impl Dimensionless for Unitless {}
//         _make_types!($System, $First, $($Nums),* | $($Types),* );
//         );
//     // Create the type, cycle the numbers, then call again:
//     ($System: ident, $($Nums: ident),*, $Last: ident | $Type: ident, $($Types: ident),+) => (
//         pub type $Type = $System<$($Nums),*, $Last>;
//         _make_types!($System, $Last, $($Nums),* | $($Types),*);
//         );
//     ($System: ident, $($Nums: ident),* | $Type: ident) => (
//         pub type $Type = $System<$($Nums),*>;
//         );
// }

// macro_rules! _make_derived_type {
//     ($D: ident, $e: expr) => ();
// }

// macro_rules! _convert_expression {
//     ($a: ident * $b: expr) => ($a as AddDim<_convert_expression!{$b}>>::Output);
//     ($a: ident / $b: expr) => ($a as SubDim<_convert_expression!{$b}>>::Output);
//     ($a: ident) => ($a);
// }
<commit_msg>Fix for older Rust version<commit_after>
#[macro_export]
macro_rules! make_units { ($System:ident, $allowed_root:ident; base { $($Type:ident, $constant:ident, $print_as:ident;)* } derived {$($Derived:ident($derived_constant: ident) = $e: expr;    )*} ) => (
    pub struct $System<$($Type: Peano),*> {
        $($constant: PhantomData<$Type>),*
    }
    impl<$($Type: Peano),*> Dimension for $System<$($Type),*> {}

    // using $Type and $constant for these traits is confusing. It should really be $Type_Left and
    // $Type_Right or something, but as far as I can tell, that is not supported by Rust
    #[allow(non_camel_case_types)]
    impl<$($Type),*, $($constant),*> KeepDim<$System<$($constant),*>> for $System<$($Type),*> where
        $($Type: Peano + KeepPeano<$constant>),*, $($constant: Peano),* {
            type Output = $System<$(<$Type as KeepPeano<$constant>>::Output),*>;
        }
    #[allow(non_camel_case_types)]
    impl<$($Type),*, $($constant),*> AddDim<$System<$($constant),*>> for $System<$($Type),*> where
        $($Type: Peano + AddPeano<$constant>),*, $($constant: Peano),* {
            type Output = $System<$(<$Type as AddPeano<$constant>>::Output),*>;
        }
    #[allow(non_camel_case_types)]
    impl<$($Type),*, $($constant),*> SubDim<$System<$($constant),*>> for $System<$($Type),*> where
        $($Type: Peano + SubPeano<$constant>),*, $($constant: Peano),* {
            type Output = $System<$(<$Type as SubPeano<$constant>>::Output),*>;
        }
    impl<$($Type),*, RHS> MulDim<RHS> for $System<$($Type),*> where
        $($Type: Peano + MulPeano<RHS>),*, RHS: Peano {
            type Output = $System<$(<$Type as MulPeano<RHS>>::Output),*>;
        }
    impl<$($Type),*, RHS> DivDim<RHS> for $System<$($Type),*> where
        $($Type: Peano + DivPeano<RHS>),*, RHS: Peano {
            type Output = $System<$(<$Type as DivPeano<RHS>>::Output),*>;
        }

    impl<$($Type),*> DimToString for $System<$($Type),*>
        where $($Type: ToInt),* {
            fn to_string() -> String {
                let mut s = String::new();
                $(
                    let temp = match <$Type as ToInt>::to_int() {
                        0 => ("", "".to_string()),
                        1 => (stringify!($print_as), "*".to_string()),
                        n => (stringify!($print_as), format!("^{}*", n/<$allowed_root as ToInt>::to_int()))
                    };
                    s = format!("{}{}{}", s, temp.0, temp.1);
                    )*
                    s.pop();
                s
            }
        }

    __make_types!($System, $allowed_root | $($Type),* | $($Type),* |);
    // fixme: when __make_types is fixed, use following line to call:
    // __make_types!($System, $allowed_root | $($Type),* | $($Type),*);

    #[allow(non_upper_case_globals)]
    pub const one: Dim<Unitless, f64> = Dim(1.0, PhantomData);
    $(#[allow(non_upper_case_globals)] pub const $constant: Dim<$Type, f64> = Dim(1.0, PhantomData);)*

        // $(
        //   _make_derived_type!($Derived, $e);
        //   // pub const $derived_constant = Dim<$Derived, f64> = Dim(1.0, PhantomData);
        //   )*
        );
}

// fixme: This is a bunch of malarky. Can't cycle the direction I want, so we reverse
// $Typse to compensate. The "correct" way is commented below, but won't work until RFC:
// https://github.com/rust-lang/rust/issues/24827 is fixed
//#[doc_hidden] fixme: uncomment when more mature
#[macro_export]
macro_rules! __make_types {
    // this first arm filters out the end Types into Zeros with Num, so we go from say
    // (One | Meters, Seconds | Meters, Seconds) to (One, Zero | Meters, Seconds |
    // Meters) and then we move to a different branch I would like a cleaner way to
    // create the list $Num, Zero, Zero, ... but I have yet to find one.
    ($System: ident, $($Nums: ident),+ | $($Types: ident),+ | $DeadType: ident, $($Others: ident),* | $($New: ident),*) => (
        __make_types!($System, $($Nums),+, Zero | $($Types),+ | $($Others),* | $DeadType $(, $New)*);
        );
    // This branch creates our Unitless type and then trims off the last $Type that we no longer need:
    ($System: ident, $First: ident, $($Nums: ident),* | $($Types: ident),+ | $Type: ident | $($New: ident),+) => (
        pub type Unitless = $System<Zero, $($Nums),*>;
        impl Dimensionless for Unitless {}
        __make_types!($System, $($Nums),*, $First | $Type, $($New),* );
        );
    // Create the type, cycle the numbers, then call again:
    ($System: ident, $First: ident, $($Nums: ident),* | $Type: ident, $($Types: ident),+) => (
        pub type $Type = $System<$First, $($Nums),*>;
        __make_types!($System, $($Nums),*, $First | $($Types),*);
        );
    ($System: ident, $($Nums: ident),* | $Type: ident) => (
        pub type $Type = $System<$($Nums),*>;
        );
}
// end of malarky

// // we call this with __make_types!(Num | Types | Types)
// #[doc_hidden]
// #[macro_export]
// macro_rules! __make_types {
//     // this first arm filters out the end Types into Zeros with Num, so we go from say
//     // (One | Meters, Seconds | Meters, Seconds) to (One, Zero | Meters, Seconds |
//     // Meters) and then we move to a different branch I would like a cleaner way to
//     // create the list $Num, Zero, Zero, ... but I have yet to find one.
//     ($System: ident, $($Nums: ident),+ | $($Types: ident),+ | $DeadType: ident, $($Others: ident),+) => (
//         __make_types!($System, $($Nums),*, Zero | $($Types),* | $($Others),*);
//         );
//     // This branch creates our Unitless type and then trims off the last $Type that we no longer need:
//     ($System: ident, $First: ident, $($Nums: ident),* | $($Types: ident),+ | $Type: ident) => (
//         pub type Unitless = $System<Zero, $($Nums),*>;
//         impl Dimensionless for Unitless {}
//         __make_types!($System, $First, $($Nums),* | $($Types),* );
//         );
//     // Create the type, cycle the numbers, then call again:
//     ($System: ident, $($Nums: ident),*, $Last: ident | $Type: ident, $($Types: ident),+) => (
//         pub type $Type = $System<$($Nums),*, $Last>;
//         __make_types!($System, $Last, $($Nums),* | $($Types),*);
//         );
//     ($System: ident, $($Nums: ident),* | $Type: ident) => (
//         pub type $Type = $System<$($Nums),*>;
//         );
// }

// macro_rules! __make_derived_type {
//     ($D: ident, $e: expr) => ();
// }

// macro_rules! __convert_expression {
//     ($a: ident * $b: expr) => ($a as AddDim<__convert_expression!{$b}>>::Output);
//     ($a: ident / $b: expr) => ($a as SubDim<__convert_expression!{$b}>>::Output);
//     ($a: ident) => ($a);
// }
<|endoftext|>


<commit_before>extern crate abra;
extern crate rocksdb;
extern crate rustc_serialize;

use std::sync::Arc;

use rocksdb::{DB, Writable, Options};
use abra::schema::{Schema, FieldType, FieldRef, AddFieldError};
use rustc_serialize::{json, Encodable};

pub struct RocksDBIndexStore {
    schema: Arc<Schema>,
    db: DB,
}

impl RocksDBIndexStore {
    pub fn create(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        let db = try!(DB::open(&opts, path));

        // Schema
        let schema = Schema::new();
        db.put(b"schema", json::encode(&schema).unwrap().as_bytes());

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn open(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        let db = try!(DB::open(&opts, path));

        let schema = match db.get(b"schema") {
            Ok(Some(schema)) => {
                let schema = schema.to_utf8().unwrap().to_string();
                json::decode(&schema).unwrap()
            }
            Ok(None) => Schema::new(),  // TODO: error
            Err(_) => Schema::new(),  // TODO: error
        };

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn add_field(&mut self, name: String, field_type: FieldType) -> Result<FieldRef, AddFieldError> {
        let mut schema_copy = (*self.schema).clone();
        let field_ref = try!(schema_copy.add_field(name, field_type));
        self.schema = Arc::new(schema_copy);

        self.db.put(b"schema", json::encode(&self.schema).unwrap().as_bytes());

        Ok(field_ref)
    }
}

#[cfg(test)]
mod tests {
    use rocksdb::{DB, Options};

    use super::RocksDBIndexStore;

    fn clean_test_indices() {
        use std::fs::remove_dir_all;

        remove_dir_all("test_indices");
    }

    #[test]
    fn test_create() {
        clean_test_indices();

        let store = RocksDBIndexStore::create("test_indices/test_create");
        assert!(store.is_ok());
    }

    #[test]
    fn test_open() {
        clean_test_indices();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_err());

        // Create DB
        let mut opts = Options::default();
        opts.create_if_missing(true);
        DB::open(&opts, "test_indices/test_open").unwrap();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_ok());
    }
}
<commit_msg>Implemented remove_field<commit_after>extern crate abra;
extern crate rocksdb;
extern crate rustc_serialize;

use std::sync::Arc;

use rocksdb::{DB, Writable, Options};
use abra::schema::{Schema, FieldType, FieldRef, AddFieldError};
use rustc_serialize::{json, Encodable};

pub struct RocksDBIndexStore {
    schema: Arc<Schema>,
    db: DB,
}

impl RocksDBIndexStore {
    pub fn create(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        let db = try!(DB::open(&opts, path));

        // Schema
        let schema = Schema::new();
        db.put(b"schema", json::encode(&schema).unwrap().as_bytes());

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn open(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        let db = try!(DB::open(&opts, path));

        let schema = match db.get(b"schema") {
            Ok(Some(schema)) => {
                let schema = schema.to_utf8().unwrap().to_string();
                json::decode(&schema).unwrap()
            }
            Ok(None) => Schema::new(),  // TODO: error
            Err(_) => Schema::new(),  // TODO: error
        };

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn add_field(&mut self, name: String, field_type: FieldType) -> Result<FieldRef, AddFieldError> {
        let mut schema_copy = (*self.schema).clone();
        let field_ref = try!(schema_copy.add_field(name, field_type));
        self.schema = Arc::new(schema_copy);

        self.db.put(b"schema", json::encode(&self.schema).unwrap().as_bytes());

        Ok(field_ref)
    }

    pub fn remove_field(&mut self, field_ref: &FieldRef) -> bool {
        let mut schema_copy = (*self.schema).clone();
        let field_removed = schema_copy.remove_field(field_ref);

        if field_removed {
            self.schema = Arc::new(schema_copy);
            self.db.put(b"schema", json::encode(&self.schema).unwrap().as_bytes());
        }

        field_removed
    }
}

#[cfg(test)]
mod tests {
    use rocksdb::{DB, Options};

    use super::RocksDBIndexStore;

    fn clean_test_indices() {
        use std::fs::remove_dir_all;

        remove_dir_all("test_indices");
    }

    #[test]
    fn test_create() {
        clean_test_indices();

        let store = RocksDBIndexStore::create("test_indices/test_create");
        assert!(store.is_ok());
    }

    #[test]
    fn test_open() {
        clean_test_indices();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_err());

        // Create DB
        let mut opts = Options::default();
        opts.create_if_missing(true);
        DB::open(&opts, "test_indices/test_open").unwrap();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_ok());
    }
}
<|endoftext|>


<commit_before>use num::traits::{Zero};

#[derive(PartialEq,Debug)]
pub struct Matrix44<T> {
    pub m: [[T; 4]; 4],
}

impl <T> Matrix44<T> where T: Zero {
    pub fn zero() -> Matrix44<T> {
        Matrix44 { m: [
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()], ]}
    }
}

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

    #[test]
    fn should_be_initialized_as_zero_matrix() {
        let m: Matrix44<f64> = Matrix44::zero();

        assert_eq!(m, Matrix44::<f64> { m: [
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            ]});
    }
}
<commit_msg>Create a matrix constructor<commit_after>use num::traits::{Zero};

#[derive(PartialEq,Debug)]
pub struct Matrix44<T> {
    pub m: [[T; 4]; 4],
}

impl <T> Matrix44<T> where T: Zero {
    pub fn zero() -> Matrix44<T> {
        Matrix44 { m: [
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()], ]}
    }

    pub fn new(mm: [[T; 4]; 4]) -> Matrix44<T> {
        Matrix44 { m : mm }
    }
}

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

    #[test]
    fn should_be_initialized_as_zero_matrix() {
        let m: Matrix44<f64> = Matrix44::zero();

        assert_eq!(m, Matrix44::<f64> { m: [
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            ]});
    }

    #[test]
    fn should_be_initialized_by_coefficients() {
        let m: Matrix44<f64> = Matrix44::new([
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 2.0, 0.0, 0.0],
            [0.0, 0.0, 3.0, 0.0],
            [0.0, 0.0, 4.0, 0.0],
            ]);

        assert_eq!(m, Matrix44::<f64> { m: [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 2.0, 0.0, 0.0],
            [0.0, 0.0, 3.0, 0.0],
            [0.0, 0.0, 4.0, 0.0],
            ]});
    }
}
<|endoftext|>


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

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Color", inherited=True) %>

<% from data import to_rust_ident %>

<%helpers:longhand name="color" need_clone="True"
                   animation_value_type="IntermediateRGBA"
                   ignored_when_colors_disabled="True"
                   spec="https://drafts.csswg.org/css-color/#color">
    use cssparser::RGBA;
    use values::specified::{AllowQuirks, Color};

    impl ToComputedValue for SpecifiedValue {
        type ComputedValue = computed_value::T;

        #[inline]
        fn to_computed_value(&self, context: &Context) -> computed_value::T {
            self.0.to_computed_value(context)
                .to_rgba(context.inherited_style.get_color().clone_color())
        }

        #[inline]
        fn from_computed_value(computed: &computed_value::T) -> Self {
            SpecifiedValue(Color::rgba(*computed).into())
        }
    }

    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    #[derive(Clone, Debug, PartialEq, ToCss)]
    pub struct SpecifiedValue(pub Color);
    no_viewport_percentage!(SpecifiedValue);

    pub mod computed_value {
        use cssparser;
        pub type T = cssparser::RGBA;
    }
    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        RGBA::new(0, 0, 0, 255) // black
    }
    pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue, ParseError<'i>> {
        Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue)
    }

    // FIXME(#15973): Add servo support for system colors
    % if product == "gecko":
        <%
            # These are actually parsed. See nsCSSProps::kColorKTable
            system_colors = """activeborder activecaption appworkspace background buttonface
                               buttonhighlight buttonshadow buttontext captiontext graytext highlight
                               highlighttext inactiveborder inactivecaption inactivecaptiontext
                               infobackground infotext menu menutext scrollbar threeddarkshadow
                               threedface threedhighlight threedlightshadow threedshadow window
                               windowframe windowtext -moz-buttondefault -moz-buttonhoverface
                               -moz-buttonhovertext -moz-cellhighlight -moz-cellhighlighttext
                               -moz-eventreerow -moz-field -moz-fieldtext -moz-dialog -moz-dialogtext
                               -moz-dragtargetzone -moz-gtk-info-bar-text -moz-html-cellhighlight
                               -moz-html-cellhighlighttext -moz-mac-buttonactivetext
                               -moz-mac-chrome-active -moz-mac-chrome-inactive
                               -moz-mac-defaultbuttontext -moz-mac-focusring -moz-mac-menuselect
                               -moz-mac-menushadow -moz-mac-menutextdisable -moz-mac-menutextselect
                               -moz-mac-disabledtoolbartext -moz-mac-secondaryhighlight
                               -moz-menuhover -moz-menuhovertext -moz-menubartext -moz-menubarhovertext
                               -moz-oddtreerow -moz-win-mediatext -moz-win-communicationstext
                               -moz-win-accentcolor -moz-win-accentcolortext
                               -moz-nativehyperlinktext -moz-comboboxtext -moz-combobox""".split()

            # These are not parsed but must be serialized
            # They are only ever set directly by Gecko
            extra_colors = """WindowBackground WindowForeground WidgetBackground WidgetForeground
                              WidgetSelectBackground WidgetSelectForeground Widget3DHighlight Widget3DShadow
                              TextBackground TextForeground TextSelectBackground TextSelectForeground
                              TextSelectForegroundCustom TextSelectBackgroundDisabled TextSelectBackgroundAttention
                              TextHighlightBackground TextHighlightForeground IMERawInputBackground
                              IMERawInputForeground IMERawInputUnderline IMESelectedRawTextBackground
                              IMESelectedRawTextForeground IMESelectedRawTextUnderline
                              IMEConvertedTextBackground IMEConvertedTextForeground IMEConvertedTextUnderline
                              IMESelectedConvertedTextBackground IMESelectedConvertedTextForeground
                              IMESelectedConvertedTextUnderline SpellCheckerUnderline""".split()
        %>
        use gecko_bindings::bindings::Gecko_GetLookAndFeelSystemColor;
        use gecko_bindings::structs::root::mozilla::LookAndFeel_ColorID;
        use std::fmt;
        use style_traits::ToCss;

        pub type SystemColor = LookAndFeel_ColorID;

        impl ToCss for SystemColor {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                let s = match *self {
                    % for color in system_colors + extra_colors:
                        LookAndFeel_ColorID::eColorID_${to_rust_ident(color)} => "${color}",
                    % endfor
                    LookAndFeel_ColorID::eColorID_LAST_COLOR => unreachable!(),
                };
                dest.write_str(s)
            }
        }

        impl ToComputedValue for SystemColor {
            type ComputedValue = u32; // nscolor
            #[inline]
            fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
                unsafe {
                    Gecko_GetLookAndFeelSystemColor(*self as i32,
                                                    cx.device.pres_context())
                }
            }

            #[inline]
            fn from_computed_value(_: &Self::ComputedValue) -> Self {
                unreachable!()
            }
        }

        impl SystemColor {
            pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
                #[cfg(feature = "gecko")]
                use std::ascii::AsciiExt;
                static PARSE_ARRAY: &'static [(&'static str, SystemColor); ${len(system_colors)}] = &[
                    % for color in system_colors:
                        ("${color}", LookAndFeel_ColorID::eColorID_${to_rust_ident(color)}),
                    % endfor
                ];

                let ident = input.expect_ident()?;
                for &(name, color) in PARSE_ARRAY.iter() {
                    if name.eq_ignore_ascii_case(&ident) {
                        return Ok(color)
                    }
                }
                Err(SelectorParseError::UnexpectedIdent(ident).into())
            }
        }
    % endif
</%helpers:longhand>
<commit_msg>Auto merge of #17754 - SergeevPavel:system-colors-refactor, r=SimonSapin<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Color", inherited=True) %>

<% from data import to_rust_ident %>

<%helpers:longhand name="color" need_clone="True"
                   animation_value_type="IntermediateRGBA"
                   ignored_when_colors_disabled="True"
                   spec="https://drafts.csswg.org/css-color/#color">
    use cssparser::RGBA;
    use values::specified::{AllowQuirks, Color};

    impl ToComputedValue for SpecifiedValue {
        type ComputedValue = computed_value::T;

        #[inline]
        fn to_computed_value(&self, context: &Context) -> computed_value::T {
            self.0.to_computed_value(context)
                .to_rgba(context.inherited_style.get_color().clone_color())
        }

        #[inline]
        fn from_computed_value(computed: &computed_value::T) -> Self {
            SpecifiedValue(Color::rgba(*computed).into())
        }
    }

    #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
    #[derive(Clone, Debug, PartialEq, ToCss)]
    pub struct SpecifiedValue(pub Color);
    no_viewport_percentage!(SpecifiedValue);

    pub mod computed_value {
        use cssparser;
        pub type T = cssparser::RGBA;
    }
    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        RGBA::new(0, 0, 0, 255) // black
    }
    pub fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>)
                         -> Result<SpecifiedValue, ParseError<'i>> {
        Color::parse_quirky(context, input, AllowQuirks::Yes).map(SpecifiedValue)
    }

    // FIXME(#15973): Add servo support for system colors
    % if product == "gecko":
        <%
            # These are actually parsed. See nsCSSProps::kColorKTable
            system_colors = """activeborder activecaption appworkspace background buttonface
                               buttonhighlight buttonshadow buttontext captiontext graytext highlight
                               highlighttext inactiveborder inactivecaption inactivecaptiontext
                               infobackground infotext menu menutext scrollbar threeddarkshadow
                               threedface threedhighlight threedlightshadow threedshadow window
                               windowframe windowtext -moz-buttondefault -moz-buttonhoverface
                               -moz-buttonhovertext -moz-cellhighlight -moz-cellhighlighttext
                               -moz-eventreerow -moz-field -moz-fieldtext -moz-dialog -moz-dialogtext
                               -moz-dragtargetzone -moz-gtk-info-bar-text -moz-html-cellhighlight
                               -moz-html-cellhighlighttext -moz-mac-buttonactivetext
                               -moz-mac-chrome-active -moz-mac-chrome-inactive
                               -moz-mac-defaultbuttontext -moz-mac-focusring -moz-mac-menuselect
                               -moz-mac-menushadow -moz-mac-menutextdisable -moz-mac-menutextselect
                               -moz-mac-disabledtoolbartext -moz-mac-secondaryhighlight
                               -moz-menuhover -moz-menuhovertext -moz-menubartext -moz-menubarhovertext
                               -moz-oddtreerow -moz-win-mediatext -moz-win-communicationstext
                               -moz-win-accentcolor -moz-win-accentcolortext
                               -moz-nativehyperlinktext -moz-comboboxtext -moz-combobox""".split()

            # These are not parsed but must be serialized
            # They are only ever set directly by Gecko
            extra_colors = """WindowBackground WindowForeground WidgetBackground WidgetForeground
                              WidgetSelectBackground WidgetSelectForeground Widget3DHighlight Widget3DShadow
                              TextBackground TextForeground TextSelectBackground TextSelectForeground
                              TextSelectForegroundCustom TextSelectBackgroundDisabled TextSelectBackgroundAttention
                              TextHighlightBackground TextHighlightForeground IMERawInputBackground
                              IMERawInputForeground IMERawInputUnderline IMESelectedRawTextBackground
                              IMESelectedRawTextForeground IMESelectedRawTextUnderline
                              IMEConvertedTextBackground IMEConvertedTextForeground IMEConvertedTextUnderline
                              IMESelectedConvertedTextBackground IMESelectedConvertedTextForeground
                              IMESelectedConvertedTextUnderline SpellCheckerUnderline""".split()
        %>
        use gecko_bindings::bindings::Gecko_GetLookAndFeelSystemColor;
        use gecko_bindings::structs::root::mozilla::LookAndFeel_ColorID;
        use std::fmt;
        use style_traits::ToCss;

        pub type SystemColor = LookAndFeel_ColorID;

        impl ToCss for SystemColor {
            fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
                let s = match *self {
                    % for color in system_colors + extra_colors:
                        LookAndFeel_ColorID::eColorID_${to_rust_ident(color)} => "${color}",
                    % endfor
                    LookAndFeel_ColorID::eColorID_LAST_COLOR => unreachable!(),
                };
                dest.write_str(s)
            }
        }

        impl ToComputedValue for SystemColor {
            type ComputedValue = u32; // nscolor
            #[inline]
            fn to_computed_value(&self, cx: &Context) -> Self::ComputedValue {
                unsafe {
                    Gecko_GetLookAndFeelSystemColor(*self as i32,
                                                    cx.device.pres_context())
                }
            }

            #[inline]
            fn from_computed_value(_: &Self::ComputedValue) -> Self {
                unreachable!()
            }
        }

        impl SystemColor {
            pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
                ascii_case_insensitive_phf_map! {
                    color_name -> SystemColor = {
                        % for color in system_colors:
                            "${color}" => LookAndFeel_ColorID::eColorID_${to_rust_ident(color)},
                        % endfor
                    }
                }

                let ident = input.expect_ident()?;
                if let Some(color) = color_name(&ident) {
                    Ok(*color)
                } else {
                    Err(SelectorParseError::UnexpectedIdent(ident).into())
                }
            }
        }
    % endif
</%helpers:longhand>
<|endoftext|>


<commit_before><commit_msg>Solve Simple Product in rust<commit_after><|endoftext|>


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

//! The Gamma and derived distributions.

use core::num::Float;

use {Rng, Open01};
use super::normal::StandardNormal;
use super::{IndependentSample, Sample, Exp};

/// The Gamma distribution `Gamma(shape, scale)` distribution.
///
/// The density function of this distribution is
///
/// ```text
/// f(x) =  x^(k - 1) * exp(-x / θ) / (Γ(k) * θ^k)
/// ```
///
/// where `Γ` is the Gamma function, `k` is the shape and `θ` is the
/// scale and both `k` and `θ` are strictly positive.
///
/// The algorithm used is that described by Marsaglia & Tsang 2000[1],
/// falling back to directly sampling from an Exponential for `shape
/// == 1`, and using the boosting technique described in [1] for
/// `shape < 1`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{IndependentSample, Gamma};
///
/// let gamma = Gamma::new(2.0, 5.0);
/// let v = gamma.ind_sample(&mut rand::task_rng());
/// println!("{} is from a Gamma(2, 5) distribution", v);
/// ```
///
/// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
/// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
/// (September 2000),
/// 363-372. DOI:[10.1145/358407.358414](http://doi.acm.org/10.1145/358407.358414)
pub struct Gamma {
    repr: GammaRepr,
}

enum GammaRepr {
    Large(GammaLargeShape),
    One(Exp),
    Small(GammaSmallShape)
}

// These two helpers could be made public, but saving the
// match-on-Gamma-enum branch from using them directly (e.g. if one
// knows that the shape is always > 1) doesn't appear to be much
// faster.

/// Gamma distribution where the shape parameter is less than 1.
///
/// Note, samples from this require a compulsory floating-point `pow`
/// call, which makes it significantly slower than sampling from a
/// gamma distribution where the shape parameter is greater than or
/// equal to 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaSmallShape {
    inv_shape: f64,
    large_shape: GammaLargeShape
}

/// Gamma distribution where the shape parameter is larger than 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaLargeShape {
    scale: f64,
    c: f64,
    d: f64
}

impl Gamma {
    /// Construct an object representing the `Gamma(shape, scale)`
    /// distribution.
    ///
    /// Fails if `shape <= 0` or `scale <= 0`.
    pub fn new(shape: f64, scale: f64) -> Gamma {
        assert!(shape > 0.0, "Gamma::new called with shape <= 0");
        assert!(scale > 0.0, "Gamma::new called with scale <= 0");

        let repr = match shape {
            1.0         => One(Exp::new(1.0 / scale)),
            0.0 ... 1.0 => Small(GammaSmallShape::new_raw(shape, scale)),
            _           => Large(GammaLargeShape::new_raw(shape, scale))
        };
        Gamma { repr: repr }
    }
}

impl GammaSmallShape {
    fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
        GammaSmallShape {
            inv_shape: 1. / shape,
            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale)
        }
    }
}

impl GammaLargeShape {
    fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
        let d = shape - 1. / 3.;
        GammaLargeShape {
            scale: scale,
            c: 1. / (9. * d).sqrt(),
            d: d
        }
    }
}

impl Sample<f64> for Gamma {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl Sample<f64> for GammaSmallShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl Sample<f64> for GammaLargeShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}

impl IndependentSample<f64> for Gamma {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            Small(ref g) => g.ind_sample(rng),
            One(ref g) => g.ind_sample(rng),
            Large(ref g) => g.ind_sample(rng),
        }
    }
}
impl IndependentSample<f64> for GammaSmallShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let Open01(u) = rng.gen::<Open01<f64>>();

        self.large_shape.ind_sample(rng) * u.powf(self.inv_shape)
    }
}
impl IndependentSample<f64> for GammaLargeShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        loop {
            let StandardNormal(x) = rng.gen::<StandardNormal>();
            let v_cbrt = 1.0 + self.c * x;
            if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
                continue
            }

            let v = v_cbrt * v_cbrt * v_cbrt;
            let Open01(u) = rng.gen::<Open01<f64>>();

            let x_sqr = x * x;
            if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
                u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
                return self.d * v * self.scale
            }
        }
    }
}

/// The chi-squared distribution `χ²(k)`, where `k` is the degrees of
/// freedom.
///
/// For `k > 0` integral, this distribution is the sum of the squares
/// of `k` independent standard normal random variables. For other
/// `k`, this uses the equivalent characterisation `χ²(k) = Gamma(k/2,
/// 2)`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{ChiSquared, IndependentSample};
///
/// let chi = ChiSquared::new(11.0);
/// let v = chi.ind_sample(&mut rand::task_rng());
/// println!("{} is from a χ²(11) distribution", v)
/// ```
pub struct ChiSquared {
    repr: ChiSquaredRepr,
}

enum ChiSquaredRepr {
    // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
    // e.g. when alpha = 1/2 as it would be for this case, so special-
    // casing and using the definition of N(0,1)^2 is faster.
    DoFExactlyOne,
    DoFAnythingElse(Gamma),
}

impl ChiSquared {
    /// Create a new chi-squared distribution with degrees-of-freedom
    /// `k`. Fails if `k < 0`.
    pub fn new(k: f64) -> ChiSquared {
        let repr = if k == 1.0 {
            DoFExactlyOne
        } else {
            assert!(k > 0.0, "ChiSquared::new called with `k` < 0");
            DoFAnythingElse(Gamma::new(0.5 * k, 2.0))
        };
        ChiSquared { repr: repr }
    }
}
impl Sample<f64> for ChiSquared {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for ChiSquared {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            DoFExactlyOne => {
                // k == 1 => N(0,1)^2
                let StandardNormal(norm) = rng.gen::<StandardNormal>();
                norm * norm
            }
            DoFAnythingElse(ref g) => g.ind_sample(rng)
        }
    }
}

/// The Fisher F distribution `F(m, n)`.
///
/// This distribution is equivalent to the ratio of two normalised
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
/// (χ²(n)/n)`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{FisherF, IndependentSample};
///
/// let f = FisherF::new(2.0, 32.0);
/// let v = f.ind_sample(&mut rand::task_rng());
/// println!("{} is from an F(2, 32) distribution", v)
/// ```
pub struct FisherF {
    numer: ChiSquared,
    denom: ChiSquared,
    // denom_dof / numer_dof so that this can just be a straight
    // multiplication, rather than a division.
    dof_ratio: f64,
}

impl FisherF {
    /// Create a new `FisherF` distribution, with the given
    /// parameter. Fails if either `m` or `n` are not positive.
    pub fn new(m: f64, n: f64) -> FisherF {
        assert!(m > 0.0, "FisherF::new called with `m < 0`");
        assert!(n > 0.0, "FisherF::new called with `n < 0`");

        FisherF {
            numer: ChiSquared::new(m),
            denom: ChiSquared::new(n),
            dof_ratio: n / m
        }
    }
}
impl Sample<f64> for FisherF {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for FisherF {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
    }
}

/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{StudentT, IndependentSample};
///
/// let t = StudentT::new(11.0);
/// let v = t.ind_sample(&mut rand::task_rng());
/// println!("{} is from a t(11) distribution", v)
/// ```
pub struct StudentT {
    chi: ChiSquared,
    dof: f64
}

impl StudentT {
    /// Create a new Student t distribution with `n` degrees of
    /// freedom. Fails if `n <= 0`.
    pub fn new(n: f64) -> StudentT {
        assert!(n > 0.0, "StudentT::new called with `n <= 0`");
        StudentT {
            chi: ChiSquared::new(n),
            dof: n
        }
    }
}
impl Sample<f64> for StudentT {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for StudentT {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let StandardNormal(norm) = rng.gen::<StandardNormal>();
        norm * (self.dof / self.chi.ind_sample(rng)).sqrt()
    }
}

#[cfg(test)]
mod test {
    use std::prelude::*;

    use distributions::{Sample, IndependentSample};
    use super::{ChiSquared, StudentT, FisherF};

    #[test]
    fn test_chi_squared_one() {
        let mut chi = ChiSquared::new(1.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_small() {
        let mut chi = ChiSquared::new(0.5);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_large() {
        let mut chi = ChiSquared::new(30.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    #[should_fail]
    fn test_chi_squared_invalid_dof() {
        ChiSquared::new(-1.0);
    }

    #[test]
    fn test_f() {
        let mut f = FisherF::new(2.0, 32.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            f.sample(&mut rng);
            f.ind_sample(&mut rng);
        }
    }

    #[test]
    fn test_t() {
        let mut t = StudentT::new(11.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            t.sample(&mut rng);
            t.ind_sample(&mut rng);
        }
    }
}

#[cfg(test)]
mod bench {
    extern crate test;
    use std::prelude::*;
    use self::test::Bencher;
    use std::mem::size_of;
    use distributions::IndependentSample;
    use super::Gamma;

    #[bench]
    fn bench_gamma_large_shape(b: &mut Bencher) {
        let gamma = Gamma::new(10., 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in range(0, ::RAND_BENCH_N) {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }

    #[bench]
    fn bench_gamma_small_shape(b: &mut Bencher) {
        let gamma = Gamma::new(0.1, 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in range(0, ::RAND_BENCH_N) {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }
}
<commit_msg>Switch to purely namespaced enums<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//
// ignore-lexer-test FIXME #15679

//! The Gamma and derived distributions.

use self::GammaRepr::*;
use self::ChiSquaredRepr::*;

use core::num::Float;

use {Rng, Open01};
use super::normal::StandardNormal;
use super::{IndependentSample, Sample, Exp};

/// The Gamma distribution `Gamma(shape, scale)` distribution.
///
/// The density function of this distribution is
///
/// ```text
/// f(x) =  x^(k - 1) * exp(-x / θ) / (Γ(k) * θ^k)
/// ```
///
/// where `Γ` is the Gamma function, `k` is the shape and `θ` is the
/// scale and both `k` and `θ` are strictly positive.
///
/// The algorithm used is that described by Marsaglia & Tsang 2000[1],
/// falling back to directly sampling from an Exponential for `shape
/// == 1`, and using the boosting technique described in [1] for
/// `shape < 1`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{IndependentSample, Gamma};
///
/// let gamma = Gamma::new(2.0, 5.0);
/// let v = gamma.ind_sample(&mut rand::task_rng());
/// println!("{} is from a Gamma(2, 5) distribution", v);
/// ```
///
/// [1]: George Marsaglia and Wai Wan Tsang. 2000. "A Simple Method
/// for Generating Gamma Variables" *ACM Trans. Math. Softw.* 26, 3
/// (September 2000),
/// 363-372. DOI:[10.1145/358407.358414](http://doi.acm.org/10.1145/358407.358414)
pub struct Gamma {
    repr: GammaRepr,
}

enum GammaRepr {
    Large(GammaLargeShape),
    One(Exp),
    Small(GammaSmallShape)
}

// These two helpers could be made public, but saving the
// match-on-Gamma-enum branch from using them directly (e.g. if one
// knows that the shape is always > 1) doesn't appear to be much
// faster.

/// Gamma distribution where the shape parameter is less than 1.
///
/// Note, samples from this require a compulsory floating-point `pow`
/// call, which makes it significantly slower than sampling from a
/// gamma distribution where the shape parameter is greater than or
/// equal to 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaSmallShape {
    inv_shape: f64,
    large_shape: GammaLargeShape
}

/// Gamma distribution where the shape parameter is larger than 1.
///
/// See `Gamma` for sampling from a Gamma distribution with general
/// shape parameters.
struct GammaLargeShape {
    scale: f64,
    c: f64,
    d: f64
}

impl Gamma {
    /// Construct an object representing the `Gamma(shape, scale)`
    /// distribution.
    ///
    /// Fails if `shape <= 0` or `scale <= 0`.
    pub fn new(shape: f64, scale: f64) -> Gamma {
        assert!(shape > 0.0, "Gamma::new called with shape <= 0");
        assert!(scale > 0.0, "Gamma::new called with scale <= 0");

        let repr = match shape {
            1.0         => One(Exp::new(1.0 / scale)),
            0.0 ... 1.0 => Small(GammaSmallShape::new_raw(shape, scale)),
            _           => Large(GammaLargeShape::new_raw(shape, scale))
        };
        Gamma { repr: repr }
    }
}

impl GammaSmallShape {
    fn new_raw(shape: f64, scale: f64) -> GammaSmallShape {
        GammaSmallShape {
            inv_shape: 1. / shape,
            large_shape: GammaLargeShape::new_raw(shape + 1.0, scale)
        }
    }
}

impl GammaLargeShape {
    fn new_raw(shape: f64, scale: f64) -> GammaLargeShape {
        let d = shape - 1. / 3.;
        GammaLargeShape {
            scale: scale,
            c: 1. / (9. * d).sqrt(),
            d: d
        }
    }
}

impl Sample<f64> for Gamma {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl Sample<f64> for GammaSmallShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl Sample<f64> for GammaLargeShape {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}

impl IndependentSample<f64> for Gamma {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            Small(ref g) => g.ind_sample(rng),
            One(ref g) => g.ind_sample(rng),
            Large(ref g) => g.ind_sample(rng),
        }
    }
}
impl IndependentSample<f64> for GammaSmallShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let Open01(u) = rng.gen::<Open01<f64>>();

        self.large_shape.ind_sample(rng) * u.powf(self.inv_shape)
    }
}
impl IndependentSample<f64> for GammaLargeShape {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        loop {
            let StandardNormal(x) = rng.gen::<StandardNormal>();
            let v_cbrt = 1.0 + self.c * x;
            if v_cbrt <= 0.0 { // a^3 <= 0 iff a <= 0
                continue
            }

            let v = v_cbrt * v_cbrt * v_cbrt;
            let Open01(u) = rng.gen::<Open01<f64>>();

            let x_sqr = x * x;
            if u < 1.0 - 0.0331 * x_sqr * x_sqr ||
                u.ln() < 0.5 * x_sqr + self.d * (1.0 - v + v.ln()) {
                return self.d * v * self.scale
            }
        }
    }
}

/// The chi-squared distribution `χ²(k)`, where `k` is the degrees of
/// freedom.
///
/// For `k > 0` integral, this distribution is the sum of the squares
/// of `k` independent standard normal random variables. For other
/// `k`, this uses the equivalent characterisation `χ²(k) = Gamma(k/2,
/// 2)`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{ChiSquared, IndependentSample};
///
/// let chi = ChiSquared::new(11.0);
/// let v = chi.ind_sample(&mut rand::task_rng());
/// println!("{} is from a χ²(11) distribution", v)
/// ```
pub struct ChiSquared {
    repr: ChiSquaredRepr,
}

enum ChiSquaredRepr {
    // k == 1, Gamma(alpha, ..) is particularly slow for alpha < 1,
    // e.g. when alpha = 1/2 as it would be for this case, so special-
    // casing and using the definition of N(0,1)^2 is faster.
    DoFExactlyOne,
    DoFAnythingElse(Gamma),
}

impl ChiSquared {
    /// Create a new chi-squared distribution with degrees-of-freedom
    /// `k`. Fails if `k < 0`.
    pub fn new(k: f64) -> ChiSquared {
        let repr = if k == 1.0 {
            DoFExactlyOne
        } else {
            assert!(k > 0.0, "ChiSquared::new called with `k` < 0");
            DoFAnythingElse(Gamma::new(0.5 * k, 2.0))
        };
        ChiSquared { repr: repr }
    }
}
impl Sample<f64> for ChiSquared {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for ChiSquared {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        match self.repr {
            DoFExactlyOne => {
                // k == 1 => N(0,1)^2
                let StandardNormal(norm) = rng.gen::<StandardNormal>();
                norm * norm
            }
            DoFAnythingElse(ref g) => g.ind_sample(rng)
        }
    }
}

/// The Fisher F distribution `F(m, n)`.
///
/// This distribution is equivalent to the ratio of two normalised
/// chi-squared distributions, that is, `F(m,n) = (χ²(m)/m) /
/// (χ²(n)/n)`.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{FisherF, IndependentSample};
///
/// let f = FisherF::new(2.0, 32.0);
/// let v = f.ind_sample(&mut rand::task_rng());
/// println!("{} is from an F(2, 32) distribution", v)
/// ```
pub struct FisherF {
    numer: ChiSquared,
    denom: ChiSquared,
    // denom_dof / numer_dof so that this can just be a straight
    // multiplication, rather than a division.
    dof_ratio: f64,
}

impl FisherF {
    /// Create a new `FisherF` distribution, with the given
    /// parameter. Fails if either `m` or `n` are not positive.
    pub fn new(m: f64, n: f64) -> FisherF {
        assert!(m > 0.0, "FisherF::new called with `m < 0`");
        assert!(n > 0.0, "FisherF::new called with `n < 0`");

        FisherF {
            numer: ChiSquared::new(m),
            denom: ChiSquared::new(n),
            dof_ratio: n / m
        }
    }
}
impl Sample<f64> for FisherF {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for FisherF {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        self.numer.ind_sample(rng) / self.denom.ind_sample(rng) * self.dof_ratio
    }
}

/// The Student t distribution, `t(nu)`, where `nu` is the degrees of
/// freedom.
///
/// # Example
///
/// ```rust
/// use std::rand;
/// use std::rand::distributions::{StudentT, IndependentSample};
///
/// let t = StudentT::new(11.0);
/// let v = t.ind_sample(&mut rand::task_rng());
/// println!("{} is from a t(11) distribution", v)
/// ```
pub struct StudentT {
    chi: ChiSquared,
    dof: f64
}

impl StudentT {
    /// Create a new Student t distribution with `n` degrees of
    /// freedom. Fails if `n <= 0`.
    pub fn new(n: f64) -> StudentT {
        assert!(n > 0.0, "StudentT::new called with `n <= 0`");
        StudentT {
            chi: ChiSquared::new(n),
            dof: n
        }
    }
}
impl Sample<f64> for StudentT {
    fn sample<R: Rng>(&mut self, rng: &mut R) -> f64 { self.ind_sample(rng) }
}
impl IndependentSample<f64> for StudentT {
    fn ind_sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let StandardNormal(norm) = rng.gen::<StandardNormal>();
        norm * (self.dof / self.chi.ind_sample(rng)).sqrt()
    }
}

#[cfg(test)]
mod test {
    use std::prelude::*;

    use distributions::{Sample, IndependentSample};
    use super::{ChiSquared, StudentT, FisherF};

    #[test]
    fn test_chi_squared_one() {
        let mut chi = ChiSquared::new(1.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_small() {
        let mut chi = ChiSquared::new(0.5);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    fn test_chi_squared_large() {
        let mut chi = ChiSquared::new(30.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            chi.sample(&mut rng);
            chi.ind_sample(&mut rng);
        }
    }
    #[test]
    #[should_fail]
    fn test_chi_squared_invalid_dof() {
        ChiSquared::new(-1.0);
    }

    #[test]
    fn test_f() {
        let mut f = FisherF::new(2.0, 32.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            f.sample(&mut rng);
            f.ind_sample(&mut rng);
        }
    }

    #[test]
    fn test_t() {
        let mut t = StudentT::new(11.0);
        let mut rng = ::test::rng();
        for _ in range(0u, 1000) {
            t.sample(&mut rng);
            t.ind_sample(&mut rng);
        }
    }
}

#[cfg(test)]
mod bench {
    extern crate test;
    use std::prelude::*;
    use self::test::Bencher;
    use std::mem::size_of;
    use distributions::IndependentSample;
    use super::Gamma;

    #[bench]
    fn bench_gamma_large_shape(b: &mut Bencher) {
        let gamma = Gamma::new(10., 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in range(0, ::RAND_BENCH_N) {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }

    #[bench]
    fn bench_gamma_small_shape(b: &mut Bencher) {
        let gamma = Gamma::new(0.1, 1.0);
        let mut rng = ::test::weak_rng();

        b.iter(|| {
            for _ in range(0, ::RAND_BENCH_N) {
                gamma.ind_sample(&mut rng);
            }
        });
        b.bytes = size_of::<f64>() as u64 * ::RAND_BENCH_N;
    }
}
<|endoftext|>


<commit_before>pub fn read_file_data(path: &PathBuf) -> Vec<u8> {
    let mut data = Vec::new();
    let mut f = File::open(path).ok().unwrap();
    f.read_to_end(&mut data).unwrap();
    data
}

const VALIDATOR_CONFIG: Option<ValidatingParserConfig> = Some(ValidatingParserConfig {
    operator_config: OperatorValidatorConfig {
        enable_threads: true,
        enable_reference_types: true,
        enable_simd: true,
        enable_bulk_memory: true,
    },
    mutable_global_imports: true,
});

#[macro_use]
extern crate criterion;
extern crate wasmparser;

use criterion::Criterion;
use wasmparser::{OperatorValidatorConfig, Parser, ValidatingParser, ValidatingParserConfig};

use std::fs::{read_dir, File};
use std::io::Read;
use std::path::PathBuf;

fn it_works_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![vec![]];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("it works benchmark", move |b| {
        for d in &mut data {
            b.iter(|| Parser::new(d.as_slice()))
        }
    });
}

fn validator_not_fails_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![vec![]];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("validator no fails benchmark", move |b| {
        for d in &mut data {
            b.iter(|| ValidatingParser::new(d.as_slice(), VALIDATOR_CONFIG));
        }
    });
}

criterion_group!(benchmark, it_works_benchmark, validator_not_fails_benchmark);
criterion_main!(benchmark);
<commit_msg>Fix benchmarks and add validate() benchmark.<commit_after>pub fn read_file_data(path: &PathBuf) -> Vec<u8> {
    let mut data = Vec::new();
    let mut f = File::open(path).ok().unwrap();
    f.read_to_end(&mut data).unwrap();
    data
}

const VALIDATOR_CONFIG: Option<ValidatingParserConfig> = Some(ValidatingParserConfig {
    operator_config: OperatorValidatorConfig {
        enable_threads: true,
        enable_reference_types: true,
        enable_simd: true,
        enable_bulk_memory: true,
    },
    mutable_global_imports: true,
});

#[macro_use]
extern crate criterion;
extern crate wasmparser;

use criterion::Criterion;
use wasmparser::{
    validate, OperatorValidatorConfig, Parser, ParserState, ValidatingParser,
    ValidatingParserConfig, WasmDecoder,
};

use std::fs::{read_dir, File};
use std::io::Read;
use std::path::PathBuf;

fn read_all_wasm<'a, T>(mut d: T)
where
    T: WasmDecoder<'a>,
{
    loop {
        match *d.read() {
            ParserState::Error(e) => panic!("unexpected error {:?}", e),
            ParserState::EndWasm => return,
            _ => (),
        }
    }
}

fn it_works_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("it works benchmark", move |b| {
        for d in &mut data {
            b.iter(|| read_all_wasm(Parser::new(d.as_slice())));
        }
    });
}

fn validator_not_fails_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("validator no fails benchmark", move |b| {
        for d in &mut data {
            b.iter(|| read_all_wasm(ValidatingParser::new(d.as_slice(), VALIDATOR_CONFIG)));
        }
    });
}

fn validate_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![vec![]];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("validate benchmark", move |b| {
        for d in &mut data {
            b.iter(|| validate(&d, VALIDATOR_CONFIG));
        }
    });
}

criterion_group!(
    benchmark,
    it_works_benchmark,
    validator_not_fails_benchmark,
    validate_benchmark
);
criterion_main!(benchmark);
<|endoftext|>