<commit_before>use pnet::packet::ipv4::Ipv4Packet;
use serde_json::{Value, Map, Number};

pub struct Ipv4Header {
	version: Number,
	ihl: Number,
	dscp: Number,
	ecn: Number,
	total_length: Number,
	identification: Number,
	flags: Number,
	fragment_offset: Number,
	ttl: Number,
	next_level_protocol: String,
	checksum: Number,
	source: String,
	destination: String,
}

impl Ipv4Header {
	pub fn new(p: &Ipv4Packet) -> Ipv4Header {
		Ipv4Header {
			version: Number::from(p.get_version()),
			ihl: Number::from(p.get_header_length()),
			dscp: Number::from(p.get_dscp()),
			ecn: Number::from(p.get_ecn()),
			total_length: Number::from(p.get_total_length()),
			identification: Number::from(p.get_identification()),
			flags: Number::from(p.get_flags()),
			fragment_offset: Number::from(p.get_fragment_offset()),
			ttl: Number::from(p.get_ttl()),
			next_level_protocol: p.get_next_level_protocol().to_string().to_lowercase(),
			checksum: Number::from(p.get_checksum()),
			source: p.get_source().to_string(),
			destination: p.get_destination().to_string(),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

    	header.insert("version".to_string(), Value::Number(self.version.clone()));
    	header.insert("ihl".to_string(), Value::Number(self.ihl.clone()));
    	header.insert("dscp".to_string(), Value::Number(self.dscp.clone()));
    	header.insert("ecn".to_string(), Value::Number(self.ecn.clone()));
    	header.insert("total_length".to_string(), Value::Number(self.total_length.clone()));
    	header.insert("identification".to_string(), Value::Number(self.identification.clone()));
    	header.insert("flags.".to_string(), Value::Number(self.flags.clone()));
    	header.insert("fragment_offset".to_string(), Value::Number(self.fragment_offset.clone()));
    	header.insert("ttl".to_string(), Value::Number(self.ttl.clone()));
    	header.insert("protocol".to_string(), Value::String(self.next_level_protocol.clone()));
    	header.insert("checksum".to_string(), Value::Number(self.checksum.clone()));
    	header.insert("source_address".to_string(), Value::String(self.source.clone()));
    	header.insert("destination_address".to_string(), Value::String(self.destination.clone()));

		header
	}
}<commit_msg>Use vector for IPv4 flags<commit_after>use pnet::packet::ipv4::{Ipv4Packet, Ipv4Flags};
use serde_json::{Value, Map, Number};

pub struct Ipv4Header {
	version: Number,
	ihl: Number,
	dscp: Number,
	ecn: Number,
	total_length: Number,
	identification: Number,
	flags: Value,
	fragment_offset: Number,
	ttl: Number,
	next_level_protocol: String,
	checksum: Number,
	source: String,
	destination: String,
}

impl Ipv4Header {
	pub fn new(p: &Ipv4Packet) -> Ipv4Header {
		let flags_number = p.get_flags();
		let mut flags: Vec<&str> = Vec::new();

		if (flags_number & Ipv4Flags::DontFragment) == Ipv4Flags::DontFragment {
			flags.push("DF");
		}
		if (flags_number & Ipv4Flags::MoreFragments) == Ipv4Flags::MoreFragments {
			flags.push("MF");
		}

		Ipv4Header {
			version: Number::from(p.get_version()),
			ihl: Number::from(p.get_header_length()),
			dscp: Number::from(p.get_dscp()),
			ecn: Number::from(p.get_ecn()),
			total_length: Number::from(p.get_total_length()),
			identification: Number::from(p.get_identification()),
			flags: Value::from(flags),
			//flags: Number::from(p.get_flags()),
			fragment_offset: Number::from(p.get_fragment_offset()),
			ttl: Number::from(p.get_ttl()),
			next_level_protocol: p.get_next_level_protocol().to_string().to_lowercase(),
			checksum: Number::from(p.get_checksum()),
			source: p.get_source().to_string(),
			destination: p.get_destination().to_string(),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

    	header.insert("version".to_string(), Value::Number(self.version.clone()));
    	header.insert("ihl".to_string(), Value::Number(self.ihl.clone()));
    	header.insert("dscp".to_string(), Value::Number(self.dscp.clone()));
    	header.insert("ecn".to_string(), Value::Number(self.ecn.clone()));
    	header.insert("total_length".to_string(), Value::Number(self.total_length.clone()));
    	header.insert("identification".to_string(), Value::Number(self.identification.clone()));
		header.insert("flags".to_string(), self.flags.clone());
    	//header.insert("flags.".to_string(), Value::Number(self.flags.clone()));
    	header.insert("fragment_offset".to_string(), Value::Number(self.fragment_offset.clone()));
    	header.insert("ttl".to_string(), Value::Number(self.ttl.clone()));
    	header.insert("protocol".to_string(), Value::String(self.next_level_protocol.clone()));
    	header.insert("checksum".to_string(), Value::Number(self.checksum.clone()));
    	header.insert("source_address".to_string(), Value::String(self.source.clone()));
    	header.insert("destination_address".to_string(), Value::String(self.destination.clone()));

		header
	}
}<|endoftext|>


<commit_before>// pest. Elegant, efficient grammars
// Copyright (C) 2016  Dragoș Tiselice
//
// 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/.

/// A `macro` useful for implementing the `Parser` `trait` as a recursive descent parser. It only
/// accepts `grammar!` and `process!` calls that get implemented on `self`.
///
/// # Rule
///
/// It also implements an `enum` called `Rule` that has a value for all
/// [non-silent](macro.grammar!#silent-rules-_) rules, but also for
/// [`any` and `eoi`](macro.grammar!). These `Rule`s are used within `Token`s to specify the type
/// of rule that matched.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate pest;
/// # use pest::prelude::*;
/// # fn main() {
/// impl_rdp! {
///     grammar! {
///         expression = _{ paren ~ expression? }
///         paren      =  { ["("] ~ expression? ~ [")"] }
///     }
/// }
///
/// let mut parser = Rdp::new(StringInput::new("(())((())())()"));
///
/// assert!(parser.expression());
/// assert!(parser.end());
/// # }
/// ```
#[macro_export]
macro_rules! impl_rdp {
    // implement rules
    ( @rules $( $name:ident )* ) => {
        #[allow(dead_code, non_camel_case_types)]
        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
        pub enum Rule {
            any,
            eoi,
            $( $name ),*
        }
    };

    // filter out silent rules
    ( @filter [  ] [ $( $rules:tt )* ] ) => {
        impl_rdp!(@rules $( $rules )*);
    };
    ( @filter [ $name:ident = { { $( $_primary:tt )* } $( $ts:tt )* } $( $tail:tt )* ]
      [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* $( $ts )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = @{ { $( $_primary:tt )* } $( $ts:tt )* } $( $tail:tt )* ]
      [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* $( $ts )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = _{ { $( $_primary:tt )* } $( $ts:tt )* } $( $tail:tt )* ]
      [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* $( $ts )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = { $( $_ts:tt )* } $( $tail:tt )* ] [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = @{ $( $_ts:tt )* } $( $tail:tt )* ] [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = _{ $( $_ts:tt )* } $( $tail:tt )* ] [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* ] [ $( $rules )* ]);
    };

    // implement empty whitespace rule
    ( @ws ) => {
        #[allow(dead_code)]
        #[inline]
        pub fn whitespace(&mut self) -> bool {
            false
        }
    };
    ( @ws whitespace = $( $_ts:tt )* ) => ();
    ( @ws $_name:ident = { $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@ws $( $tail )*);
    };
    ( @ws $_name:ident = @{ $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@ws $( $tail )*);
    };
    ( @ws $_name:ident = _{ $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@ws $( $tail )*);
    };

    // implement empty comment rule
    ( @com ) => {
        #[allow(dead_code)]
        #[inline]
        pub fn comment(&mut self) -> bool {
            false
        }
    };
    ( @com comment = $( $_ts:tt )* ) => ();
    ( @com $_name:ident = { $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@com $( $tail )*);
    };
    ( @com $_name:ident = @{ $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@com $( $tail )*);
    };
    ( @com $_name:ident = _{ $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@com $( $tail )*);
    };

    ( grammar! { $( $ts:tt )* } $( $mac:ident! { $( $rest:tt )* } )* ) => {
        use std::cell::Cell;
        use std::cmp;

        pub struct Rdp<T> {
            input:       T,
            queue:       Vec<Token<Rule>>,
            queue_index: Cell<usize>,
            failures:    Vec<Rule>,
            fail_pos:    usize,
            atomic:      bool,
            comment:     bool,
            eoi_matched: bool
        }

        impl_rdp!(@filter [ $( $ts )* ] []);

        impl<'input, T: Input<'input>> Rdp<T> {
            pub fn new(input: T) -> Rdp<T> {
                Rdp {
                    input:       input,
                    queue:       vec![],
                    queue_index: Cell::new(0),
                    failures:    vec![],
                    fail_pos:    0,
                    atomic:      false,
                    comment:     false,
                    eoi_matched: false
                }
            }

            impl_rdp!(@ws $( $ts )*);
            impl_rdp!(@com $( $ts )*);

            #[allow(dead_code)]
            #[inline]
            pub fn any(&mut self) -> bool {
                if self.end() {
                    let pos = self.input.pos();

                    self.track(Rule::any, pos);

                    false
                } else {
                    let next = self.input.pos() + 1;
                    self.input.set_pos(next);

                    true
                }
            }

            #[allow(dead_code)]
            #[inline]
            pub fn eoi(&mut self) -> bool {
                let result = self.end();

                if !result {
                    let pos = self.input.pos();

                    self.track(Rule::eoi, pos);
                } else {
                    self.eoi_matched = true;
                }

                result
            }

            grammar! {
                $( $ts )*
            }

            $(
                $mac! {
                    $( $rest )*
                }
            )*
        }

        impl<'input, T: Input<'input>> Parser<'input, T> for Rdp<T> {
            type Rule = Rule;
            type Token = Token<Rule>;

            #[inline]
            fn input(&self) -> &T {
                &self.input
            }

            #[inline]
            fn input_mut(&mut self) -> &mut T {
                &mut self.input
            }

            #[inline]
            fn try<F>(&mut self, revert: bool, rule: F) -> bool
                where F: FnOnce(&mut Self) -> bool {

                let pos = self.input.pos();
                let len = self.queue.len();

                let result = rule(self);

                if revert || !result {
                    self.input.set_pos(pos);
                }

                if !result {
                    self.queue.truncate(len);
                }

                result
            }

            fn prec_climb<F, G>(&mut self, pos: usize, left: usize, min_prec: u8,
                                last_op: Option<(Option<Rule>, u8, bool)>, primary: &mut F,
                                climb: &mut G) -> (Option<(Option<Rule>, u8, bool)>, Option<usize>)
                where F: FnMut(&mut Self) -> bool,
                      G: FnMut(&mut Self) -> Option<(Option<Rule>, u8, bool)> {

                let mut op = if last_op.is_some() {
                    last_op
                } else {
                    climb(self)
                };
                let mut last_right = None;

                while let Some((rule, prec, _)) = op {
                    if prec >= min_prec {
                        let mut new_pos = self.input.pos();
                        let mut right = self.input.pos();
                        let queue_pos = self.queue.len();

                        primary(self);

                        if let Some(token) = self.queue.get(queue_pos) {
                            new_pos = token.start;
                            right   = token.end;
                        }

                        op = climb(self);

                        while let Some((_, new_prec, right_assoc)) = op {
                            if new_prec > prec || right_assoc && new_prec == prec {
                                let (new_op, new_lr) = self.prec_climb(queue_pos, new_pos,
                                                                       new_prec, op, primary,
                                                                       climb);

                                op = new_op;
                                last_right = new_lr;
                            } else {
                                break
                            }
                        }

                        if let Some(pos) = last_right {
                            right = cmp::max(pos, right);
                        } else {
                            last_right = Some(right);
                        }

                        if let Some(rule) = rule {
                            let token = Token {
                                rule:  rule,
                                start: left,
                                end:   right
                            };

                            self.queue.insert(pos, token);
                        }
                    } else {
                        return (op, last_right)
                    }
                }

                (op, last_right)
            }

            #[inline]
            fn end(&self) -> bool {
                self.input.len() == self.input.pos()
            }

            #[inline]
            fn eoi_matched(&self) -> bool {
                self.eoi_matched
            }

            #[inline]
            fn reset(&mut self) {
                self.input.set_pos(0);
                self.queue.clear();
                self.failures.clear();
                self.fail_pos = 0;
            }

            #[inline]
            fn queue(&self) -> &Vec<Token<Rule>>{
                &self.queue
            }

            #[inline]
            fn queue_index(&self) -> usize {
                self.queue_index.get()
            }

            #[inline]
            fn inc_queue_index(&self) {
                self.queue_index.set(self.queue_index.get() + 1);
            }

            #[inline]
            fn set_queue_index(&self, index: usize) {
                self.queue_index.set(index);
            }

            #[inline]
            fn queue_mut(&mut self) -> &mut Vec<Token<Rule>>{
                &mut self.queue
            }

            #[inline]
            fn skip_ws(&mut self) {
                if self.atomic {
                    return
                }

                loop {
                    if !self.whitespace() {
                        break
                    }
                }
            }

            #[inline]
            fn skip_com(&mut self) {
                if self.atomic {
                    return
                }

                if !self.comment {
                    self.comment = true;

                    loop {
                        if !self.comment() {
                            break
                        }
                    }

                    self.comment = false;
                }
            }

            #[inline]
            fn is_atomic(&self) -> bool {
                self.atomic
            }

            #[inline]
            fn set_atomic(&mut self, value: bool) {
                self.atomic = value;
            }

            #[inline]
            fn track(&mut self, failed: Rule, pos: usize) {
                if self.atomic {
                    return
                }

                if self.failures.is_empty() {
                    self.failures.push(failed);

                    self.fail_pos = pos;
                } else {
                    if pos == self.fail_pos {
                        self.failures.push(failed);
                    } else if pos > self.fail_pos {
                        self.failures.clear();
                        self.failures.push(failed);

                        self.fail_pos = pos;
                    }
                }
            }

            fn tracked_len(&self) -> usize {
                self.failures.len()
            }

            fn expected(&mut self) -> (Vec<Rule>, usize) {
                self.failures.sort();
                self.failures.dedup();

                (self.failures.iter().cloned().collect(), self.fail_pos)
            }
        }
    };
}

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

    impl_rdp! {
        grammar! {
            expression = _{ paren ~ expression? }
            paren = { ["("] ~ expression? ~ [")"] }
            zero = { ["a"]* }
            one = { ["a"]+ }
            comment = _{ ["//"] ~ (!["\n"] ~ any)* ~ ["\n"] }
            whitespace = _{ [" "] }
        }
    }

    #[test]
    fn try() {
        let input = StringInput::new("asdasdf");
        let mut parser = Rdp::new(input);

        assert!(parser.input_mut().match_string("asd"));

        assert!(!parser.try(false, |parser| {
            parser.input_mut().match_string("as") && parser.input_mut().match_string("dd")
        }));

        assert!(parser.try(false, |parser| {
            parser.input_mut().match_string("as") && parser.input_mut().match_string("df")
        }));
    }

    #[test]
    fn end() {
        let input = StringInput::new("asdasdf");
        let mut parser = Rdp::new(input);

        assert!(parser.input_mut().match_string("asdasdf"));
        assert!(parser.end());
    }

    #[test]
    fn reset() {
        let input = StringInput::new("asdasdf");
        let mut parser = Rdp::new(input);

        assert!(parser.input_mut().match_string("asdasdf"));

        parser.reset();

        assert!(parser.input_mut().match_string("asdasdf"));
    }

    #[test]
    fn whitespace_seq() {
        let mut parser = Rdp::new(StringInput::new("  (  ( ))(( () )() )() "));

        assert!(parser.expression());
        assert!(!parser.end());

        let queue = vec![
            Token::new(Rule::paren, 2, 9),
            Token::new(Rule::paren, 5, 8),
            Token::new(Rule::paren, 9, 20),
            Token::new(Rule::paren, 10, 16),
            Token::new(Rule::paren, 12, 14),
            Token::new(Rule::paren, 16, 18),
            Token::new(Rule::paren, 20, 22)
        ];

        assert_eq!(parser.queue(), &queue);
    }

    #[test]
    fn whitespace_zero() {
        let mut parser = Rdp::new(StringInput::new("  a a aa aaaa a  "));

        assert!(parser.zero());
        assert!(!parser.end());

        let queue = vec![
            Token::new(Rule::zero, 2, 15)
        ];

        assert_eq!(parser.queue(), &queue);
    }

    #[test]
    fn whitespace_one() {
        let mut parser = Rdp::new(StringInput::new("  a a aa aaaa a  "));

        assert!(parser.one());
        assert!(!parser.end());

        let queue = vec![Token {
                             rule: Rule::one,
                             start: 2,
                             end: 15,
                         }];

        assert_eq!(parser.queue(), &queue);
    }

    #[test]
    fn comment() {
        let mut parser = Rdp::new(StringInput::new("// hi\n(())"));

        assert!(parser.expression());
        assert!(parser.end());

        let queue = vec![
            Token::new(Rule::paren, 6, 10),
            Token::new(Rule::paren, 7, 9)
        ];

        assert_eq!(parser.queue(), &queue);
    }

    #[test]
    fn comment_whitespace() {
        let mut parser = Rdp::new(StringInput::new("   // hi\n  (())"));

        assert!(parser.expression());
        assert!(parser.end());

        let queue = vec![
            Token::new(Rule::paren, 11, 15),
            Token::new(Rule::paren, 12, 14)
        ];

        assert_eq!(parser.queue(), &queue);
    }
}
<commit_msg>Resetting queue index in Parser::reset.<commit_after>// pest. Elegant, efficient grammars
// Copyright (C) 2016  Dragoș Tiselice
//
// 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/.

/// A `macro` useful for implementing the `Parser` `trait` as a recursive descent parser. It only
/// accepts `grammar!` and `process!` calls that get implemented on `self`.
///
/// # Rule
///
/// It also implements an `enum` called `Rule` that has a value for all
/// [non-silent](macro.grammar!#silent-rules-_) rules, but also for
/// [`any` and `eoi`](macro.grammar!). These `Rule`s are used within `Token`s to specify the type
/// of rule that matched.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate pest;
/// # use pest::prelude::*;
/// # fn main() {
/// impl_rdp! {
///     grammar! {
///         expression = _{ paren ~ expression? }
///         paren      =  { ["("] ~ expression? ~ [")"] }
///     }
/// }
///
/// let mut parser = Rdp::new(StringInput::new("(())((())())()"));
///
/// assert!(parser.expression());
/// assert!(parser.end());
/// # }
/// ```
#[macro_export]
macro_rules! impl_rdp {
    // implement rules
    ( @rules $( $name:ident )* ) => {
        #[allow(dead_code, non_camel_case_types)]
        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
        pub enum Rule {
            any,
            eoi,
            $( $name ),*
        }
    };

    // filter out silent rules
    ( @filter [  ] [ $( $rules:tt )* ] ) => {
        impl_rdp!(@rules $( $rules )*);
    };
    ( @filter [ $name:ident = { { $( $_primary:tt )* } $( $ts:tt )* } $( $tail:tt )* ]
      [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* $( $ts )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = @{ { $( $_primary:tt )* } $( $ts:tt )* } $( $tail:tt )* ]
      [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* $( $ts )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = _{ { $( $_primary:tt )* } $( $ts:tt )* } $( $tail:tt )* ]
      [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* $( $ts )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = { $( $_ts:tt )* } $( $tail:tt )* ] [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = @{ $( $_ts:tt )* } $( $tail:tt )* ] [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* ] [ $name $( $rules )* ]);
    };
    ( @filter [ $name:ident = _{ $( $_ts:tt )* } $( $tail:tt )* ] [ $( $rules:tt )* ] ) => {
        impl_rdp!(@filter [ $( $tail )* ] [ $( $rules )* ]);
    };

    // implement empty whitespace rule
    ( @ws ) => {
        #[allow(dead_code)]
        #[inline]
        pub fn whitespace(&mut self) -> bool {
            false
        }
    };
    ( @ws whitespace = $( $_ts:tt )* ) => ();
    ( @ws $_name:ident = { $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@ws $( $tail )*);
    };
    ( @ws $_name:ident = @{ $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@ws $( $tail )*);
    };
    ( @ws $_name:ident = _{ $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@ws $( $tail )*);
    };

    // implement empty comment rule
    ( @com ) => {
        #[allow(dead_code)]
        #[inline]
        pub fn comment(&mut self) -> bool {
            false
        }
    };
    ( @com comment = $( $_ts:tt )* ) => ();
    ( @com $_name:ident = { $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@com $( $tail )*);
    };
    ( @com $_name:ident = @{ $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@com $( $tail )*);
    };
    ( @com $_name:ident = _{ $( $_ts:tt )* } $( $tail:tt )* ) => {
        impl_rdp!(@com $( $tail )*);
    };

    ( grammar! { $( $ts:tt )* } $( $mac:ident! { $( $rest:tt )* } )* ) => {
        use std::cell::Cell;
        use std::cmp;

        pub struct Rdp<T> {
            input:       T,
            queue:       Vec<Token<Rule>>,
            queue_index: Cell<usize>,
            failures:    Vec<Rule>,
            fail_pos:    usize,
            atomic:      bool,
            comment:     bool,
            eoi_matched: bool
        }

        impl_rdp!(@filter [ $( $ts )* ] []);

        impl<'input, T: Input<'input>> Rdp<T> {
            pub fn new(input: T) -> Rdp<T> {
                Rdp {
                    input:       input,
                    queue:       vec![],
                    queue_index: Cell::new(0),
                    failures:    vec![],
                    fail_pos:    0,
                    atomic:      false,
                    comment:     false,
                    eoi_matched: false
                }
            }

            impl_rdp!(@ws $( $ts )*);
            impl_rdp!(@com $( $ts )*);

            #[allow(dead_code)]
            #[inline]
            pub fn any(&mut self) -> bool {
                if self.end() {
                    let pos = self.input.pos();

                    self.track(Rule::any, pos);

                    false
                } else {
                    let next = self.input.pos() + 1;
                    self.input.set_pos(next);

                    true
                }
            }

            #[allow(dead_code)]
            #[inline]
            pub fn eoi(&mut self) -> bool {
                let result = self.end();

                if !result {
                    let pos = self.input.pos();

                    self.track(Rule::eoi, pos);
                } else {
                    self.eoi_matched = true;
                }

                result
            }

            grammar! {
                $( $ts )*
            }

            $(
                $mac! {
                    $( $rest )*
                }
            )*
        }

        impl<'input, T: Input<'input>> Parser<'input, T> for Rdp<T> {
            type Rule = Rule;
            type Token = Token<Rule>;

            #[inline]
            fn input(&self) -> &T {
                &self.input
            }

            #[inline]
            fn input_mut(&mut self) -> &mut T {
                &mut self.input
            }

            #[inline]
            fn try<F>(&mut self, revert: bool, rule: F) -> bool
                where F: FnOnce(&mut Self) -> bool {

                let pos = self.input.pos();
                let len = self.queue.len();

                let result = rule(self);

                if revert || !result {
                    self.input.set_pos(pos);
                }

                if !result {
                    self.queue.truncate(len);
                }

                result
            }

            fn prec_climb<F, G>(&mut self, pos: usize, left: usize, min_prec: u8,
                                last_op: Option<(Option<Rule>, u8, bool)>, primary: &mut F,
                                climb: &mut G) -> (Option<(Option<Rule>, u8, bool)>, Option<usize>)
                where F: FnMut(&mut Self) -> bool,
                      G: FnMut(&mut Self) -> Option<(Option<Rule>, u8, bool)> {

                let mut op = if last_op.is_some() {
                    last_op
                } else {
                    climb(self)
                };
                let mut last_right = None;

                while let Some((rule, prec, _)) = op {
                    if prec >= min_prec {
                        let mut new_pos = self.input.pos();
                        let mut right = self.input.pos();
                        let queue_pos = self.queue.len();

                        primary(self);

                        if let Some(token) = self.queue.get(queue_pos) {
                            new_pos = token.start;
                            right   = token.end;
                        }

                        op = climb(self);

                        while let Some((_, new_prec, right_assoc)) = op {
                            if new_prec > prec || right_assoc && new_prec == prec {
                                let (new_op, new_lr) = self.prec_climb(queue_pos, new_pos,
                                                                       new_prec, op, primary,
                                                                       climb);

                                op = new_op;
                                last_right = new_lr;
                            } else {
                                break
                            }
                        }

                        if let Some(pos) = last_right {
                            right = cmp::max(pos, right);
                        } else {
                            last_right = Some(right);
                        }

                        if let Some(rule) = rule {
                            let token = Token {
                                rule:  rule,
                                start: left,
                                end:   right
                            };

                            self.queue.insert(pos, token);
                        }
                    } else {
                        return (op, last_right)
                    }
                }

                (op, last_right)
            }

            #[inline]
            fn end(&self) -> bool {
                self.input.len() == self.input.pos()
            }

            #[inline]
            fn eoi_matched(&self) -> bool {
                self.eoi_matched
            }

            #[inline]
            fn reset(&mut self) {
                self.input.set_pos(0);
                self.queue.clear();
                self.queue_index.set(0);
                self.failures.clear();
                self.fail_pos = 0;
            }

            #[inline]
            fn queue(&self) -> &Vec<Token<Rule>>{
                &self.queue
            }

            #[inline]
            fn queue_index(&self) -> usize {
                self.queue_index.get()
            }

            #[inline]
            fn inc_queue_index(&self) {
                self.queue_index.set(self.queue_index.get() + 1);
            }

            #[inline]
            fn set_queue_index(&self, index: usize) {
                self.queue_index.set(index);
            }

            #[inline]
            fn queue_mut(&mut self) -> &mut Vec<Token<Rule>>{
                &mut self.queue
            }

            #[inline]
            fn skip_ws(&mut self) {
                if self.atomic {
                    return
                }

                loop {
                    if !self.whitespace() {
                        break
                    }
                }
            }

            #[inline]
            fn skip_com(&mut self) {
                if self.atomic {
                    return
                }

                if !self.comment {
                    self.comment = true;

                    loop {
                        if !self.comment() {
                            break
                        }
                    }

                    self.comment = false;
                }
            }

            #[inline]
            fn is_atomic(&self) -> bool {
                self.atomic
            }

            #[inline]
            fn set_atomic(&mut self, value: bool) {
                self.atomic = value;
            }

            #[inline]
            fn track(&mut self, failed: Rule, pos: usize) {
                if self.atomic {
                    return
                }

                if self.failures.is_empty() {
                    self.failures.push(failed);

                    self.fail_pos = pos;
                } else {
                    if pos == self.fail_pos {
                        self.failures.push(failed);
                    } else if pos > self.fail_pos {
                        self.failures.clear();
                        self.failures.push(failed);

                        self.fail_pos = pos;
                    }
                }
            }

            fn tracked_len(&self) -> usize {
                self.failures.len()
            }

            fn expected(&mut self) -> (Vec<Rule>, usize) {
                self.failures.sort();
                self.failures.dedup();

                (self.failures.iter().cloned().collect(), self.fail_pos)
            }
        }
    };
}

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

    impl_rdp! {
        grammar! {
            expression = _{ paren ~ expression? }
            paren = { ["("] ~ expression? ~ [")"] }
            zero = { ["a"]* }
            one = { ["a"]+ }
            comment = _{ ["//"] ~ (!["\n"] ~ any)* ~ ["\n"] }
            whitespace = _{ [" "] }
        }
    }

    #[test]
    fn try() {
        let input = StringInput::new("asdasdf");
        let mut parser = Rdp::new(input);

        assert!(parser.input_mut().match_string("asd"));

        assert!(!parser.try(false, |parser| {
            parser.input_mut().match_string("as") && parser.input_mut().match_string("dd")
        }));

        assert!(parser.try(false, |parser| {
            parser.input_mut().match_string("as") && parser.input_mut().match_string("df")
        }));
    }

    #[test]
    fn end() {
        let input = StringInput::new("asdasdf");
        let mut parser = Rdp::new(input);

        assert!(parser.input_mut().match_string("asdasdf"));
        assert!(parser.end());
    }

    #[test]
    fn reset() {
        let input = StringInput::new("asdasdf");
        let mut parser = Rdp::new(input);

        assert!(parser.input_mut().match_string("asdasdf"));

        parser.reset();

        assert!(parser.input_mut().match_string("asdasdf"));
    }

    #[test]
    fn whitespace_seq() {
        let mut parser = Rdp::new(StringInput::new("  (  ( ))(( () )() )() "));

        assert!(parser.expression());
        assert!(!parser.end());

        let queue = vec![
            Token::new(Rule::paren, 2, 9),
            Token::new(Rule::paren, 5, 8),
            Token::new(Rule::paren, 9, 20),
            Token::new(Rule::paren, 10, 16),
            Token::new(Rule::paren, 12, 14),
            Token::new(Rule::paren, 16, 18),
            Token::new(Rule::paren, 20, 22)
        ];

        assert_eq!(parser.queue(), &queue);
    }

    #[test]
    fn whitespace_zero() {
        let mut parser = Rdp::new(StringInput::new("  a a aa aaaa a  "));

        assert!(parser.zero());
        assert!(!parser.end());

        let queue = vec![
            Token::new(Rule::zero, 2, 15)
        ];

        assert_eq!(parser.queue(), &queue);
    }

    #[test]
    fn whitespace_one() {
        let mut parser = Rdp::new(StringInput::new("  a a aa aaaa a  "));

        assert!(parser.one());
        assert!(!parser.end());

        let queue = vec![Token {
                             rule: Rule::one,
                             start: 2,
                             end: 15,
                         }];

        assert_eq!(parser.queue(), &queue);
    }

    #[test]
    fn comment() {
        let mut parser = Rdp::new(StringInput::new("// hi\n(())"));

        assert!(parser.expression());
        assert!(parser.end());

        let queue = vec![
            Token::new(Rule::paren, 6, 10),
            Token::new(Rule::paren, 7, 9)
        ];

        assert_eq!(parser.queue(), &queue);
    }

    #[test]
    fn comment_whitespace() {
        let mut parser = Rdp::new(StringInput::new("   // hi\n  (())"));

        assert!(parser.expression());
        assert!(parser.end());

        let queue = vec![
            Token::new(Rule::paren, 11, 15),
            Token::new(Rule::paren, 12, 14)
        ];

        assert_eq!(parser.queue(), &queue);
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use common;
use byteorder::{BigEndian, ByteOrder};
use super::Field;
use std::str;

/// Size (in bytes) of the buffer of a int field.
const INT_TERM_LEN: usize = 4 + 8;

/// Term represents the value that the token can take.
///
/// It actually wraps a `Vec<u8>`.
#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub struct Term(Vec<u8>);

/// Extract `field` from Term.
#[doc(hidden)]
pub(crate) fn extract_field_from_term_bytes(term_bytes: &[u8]) -> Field {
    Field(BigEndian::read_u32(&term_bytes[..4]))
}

impl Term {

    /// Set the content of the term.
    pub fn set_content(&mut self, content: &[u8]) {
        assert!(content.len() >= 4);
        self.0.resize(content.len(), 0u8);
        (&mut self.0[..]).clone_from_slice(content);
    }

    /// Returns the field.
    pub fn field(&self,) -> Field {
        extract_field_from_term_bytes(&self.0)
    }

    /// Returns the field.
    pub fn set_field(&mut self, field: Field) {
        if self.0.len() < 4 {
            self.0.resize(4, 0u8);
        }
        BigEndian::write_u32(&mut self.0[0..4], field.0);
    }

    /// Returns the field.
    pub fn set_field(&mut self, field: Field) {
        if self.0.len() < 4 {
            self.0.resize(4, 0u8);
        }
        BigEndian::write_u32(&mut self.0[0..4], field.0);
    }

    /// Builds a term given a field, and a u64-value
    ///
    /// Assuming the term has a field id of 1, and a u64 value of 3234,
    /// the Term will have 8 bytes.
    ///
    /// The first four byte are dedicated to storing the field id as a u64.
    /// The 4 following bytes are encoding the u64 value.
    pub fn from_field_u64(field: Field, val: u64) -> Term {
        let mut term = Term(vec![0u8; INT_TERM_LEN]);
        term.set_field(field);
        term.set_u64(val);
        term
    }

    /// Sets a u64 value in the term.
    ///
    /// U64 are serialized using (8-byte) BigEndian
    /// representation.
    /// The use of BigEndian has the benefit of preserving
    /// the natural order of the values.
    pub fn set_u64(&mut self, val: u64) {
        self.0.resize(INT_TERM_LEN, 0u8);
        BigEndian::write_u64(&mut self.0[4..], val);
    }

    /// Builds a term given a field, and a u64-value
    ///
    /// Assuming the term has a field id of 1, and a u64 value of 3234,
    /// the Term will have 8 bytes.
    ///
    /// The first four byte are dedicated to storing the field id as a u64.
    /// The 4 following bytes are encoding the u64 value.
    pub fn from_field_i64(field: Field, val: i64) -> Term {
        let val_u64: u64 = common::i64_to_u64(val);
        Term::from_field_u64(field, val_u64)
    }

    /// Builds a term given a field, and a string value
    ///
    /// Assuming the term has a field id of 2, and a text value of "abc",
    /// the Term will have 4 bytes.
    /// The first byte is 2, and the three following bytes are the utf-8
    /// representation of "abc".
    pub fn from_field_text(field: Field, text: &str) -> Term {
        let buffer = Vec::with_capacity(4 + text.len());
        let mut term = Term(buffer);
        term.set_field(field);
        term.set_text(text);
        term
    }

    /// Creates a new Term with an empty buffer,
    /// but with a given capacity.
    ///
    /// It is declared unsafe, as the term content
    /// is not initialized, and a call to `.field()`
    /// would panic.
    pub(crate) unsafe fn with_capacity(num_bytes: usize) -> Term {
        Term(Vec::with_capacity(num_bytes))
    }

    /// Assume the term is a u64 field.
    ///
    /// Panics if the term is not a u64 field.
    pub fn get_u64(&self) -> u64 {
        BigEndian::read_u64(&self.0[4..])
    }

    /// Builds a term from its byte representation.
    ///
    /// If you want to build a field for a given `str`,
    /// you want to use `from_field_text`.
    pub fn from_bytes(data: &[u8]) -> Term {
        Term(Vec::from(data))
    }

    /// Returns the serialized value of the term.
    /// (this does not include the field.)
    ///
    /// If the term is a string, its value is utf-8 encoded.
    /// If the term is a u64, its value is encoded according
    /// to `byteorder::LittleEndian`.
    pub fn value(&self) -> &[u8] {
        &self.0[4..]
    }

    /// Returns the text associated with the term.
    ///
    /// # Panics
    /// If the value is not valid utf-8. This may happen
    /// if the index is corrupted or if you try to
    /// call this method on a non-string type.
    pub fn text(&self) -> &str {
        str::from_utf8(self.value()).expect("Term does not contain valid utf-8.")
    }

    /// Set the texts only, keeping the field untouched.
    pub fn set_text(&mut self, text: &str) {
        self.0.resize(4, 0u8);
        self.0.extend(text.as_bytes());
    }

    /// Returns the underlying `&[u8]`
    pub fn as_slice(&self,)->&[u8] {
        &self.0
    }
}

impl AsRef<[u8]> for Term {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl fmt::Debug for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Term({:?})", &self.0[..])
    }
}

#[cfg(test)]
mod tests {

    use schema::*;

    #[test]
    pub fn test_term() {
        let mut schema_builder = SchemaBuilder::default();
        schema_builder.add_text_field("text", STRING);
        let title_field = schema_builder.add_text_field("title", STRING);
        let count_field = schema_builder.add_text_field("count", STRING);
        {
            let term = Term::from_field_text(title_field, "test");
            assert_eq!(term.field(), title_field);
            assert_eq!(&term.as_slice()[0..4], &[0u8,0u8,0u8,1u8]);
            assert_eq!(&term.as_slice()[4..], "test".as_bytes());
        }
        {
            let term = Term::from_field_u64(count_field, 983u64);
            assert_eq!(term.field(), count_field);
            assert_eq!(&term.as_slice()[0..4], &[0u8, 0u8, 0u8, 2u8]);
            assert_eq!(term.as_slice().len(), 4 + 8);
            assert_eq!(term.as_slice()[4], 0u8);
            assert_eq!(term.as_slice()[5], 0u8);
            assert_eq!(term.as_slice()[6], 0u8);
            assert_eq!(term.as_slice()[7], 0u8);
            assert_eq!(term.as_slice()[8], 0u8);
            assert_eq!(term.as_slice()[9], 0u8);
            assert_eq!(term.as_slice()[10], (933u64 / 256u64) as u8);
            assert_eq!(term.as_slice()[11], (983u64 % 256u64) as u8);
        }

    }
}<commit_msg>Fix broke compile<commit_after>use std::fmt;

use common;
use byteorder::{BigEndian, ByteOrder};
use super::Field;
use std::str;

/// Size (in bytes) of the buffer of a int field.
const INT_TERM_LEN: usize = 4 + 8;

/// Term represents the value that the token can take.
///
/// It actually wraps a `Vec<u8>`.
#[derive(Clone, PartialEq, PartialOrd, Ord, Eq, Hash)]
pub struct Term(Vec<u8>);

/// Extract `field` from Term.
#[doc(hidden)]
pub(crate) fn extract_field_from_term_bytes(term_bytes: &[u8]) -> Field {
    Field(BigEndian::read_u32(&term_bytes[..4]))
}

impl Term {

    /// Set the content of the term.
    pub fn set_content(&mut self, content: &[u8]) {
        assert!(content.len() >= 4);
        self.0.resize(content.len(), 0u8);
        (&mut self.0[..]).clone_from_slice(content);
    }

    /// Returns the field.
    pub fn field(&self,) -> Field {
        extract_field_from_term_bytes(&self.0)
    }

    /// Returns the field.
    pub fn set_field(&mut self, field: Field) {
        if self.0.len() < 4 {
            self.0.resize(4, 0u8);
        }
        BigEndian::write_u32(&mut self.0[0..4], field.0);
    }

    /// Builds a term given a field, and a u64-value
    ///
    /// Assuming the term has a field id of 1, and a u64 value of 3234,
    /// the Term will have 8 bytes.
    ///
    /// The first four byte are dedicated to storing the field id as a u64.
    /// The 4 following bytes are encoding the u64 value.
    pub fn from_field_u64(field: Field, val: u64) -> Term {
        let mut term = Term(vec![0u8; INT_TERM_LEN]);
        term.set_field(field);
        term.set_u64(val);
        term
    }

    /// Sets a u64 value in the term.
    ///
    /// U64 are serialized using (8-byte) BigEndian
    /// representation.
    /// The use of BigEndian has the benefit of preserving
    /// the natural order of the values.
    pub fn set_u64(&mut self, val: u64) {
        self.0.resize(INT_TERM_LEN, 0u8);
        BigEndian::write_u64(&mut self.0[4..], val);
    }

    /// Builds a term given a field, and a u64-value
    ///
    /// Assuming the term has a field id of 1, and a u64 value of 3234,
    /// the Term will have 8 bytes.
    ///
    /// The first four byte are dedicated to storing the field id as a u64.
    /// The 4 following bytes are encoding the u64 value.
    pub fn from_field_i64(field: Field, val: i64) -> Term {
        let val_u64: u64 = common::i64_to_u64(val);
        Term::from_field_u64(field, val_u64)
    }

    /// Builds a term given a field, and a string value
    ///
    /// Assuming the term has a field id of 2, and a text value of "abc",
    /// the Term will have 4 bytes.
    /// The first byte is 2, and the three following bytes are the utf-8
    /// representation of "abc".
    pub fn from_field_text(field: Field, text: &str) -> Term {
        let buffer = Vec::with_capacity(4 + text.len());
        let mut term = Term(buffer);
        term.set_field(field);
        term.set_text(text);
        term
    }

    /// Creates a new Term with an empty buffer,
    /// but with a given capacity.
    ///
    /// It is declared unsafe, as the term content
    /// is not initialized, and a call to `.field()`
    /// would panic.
    pub(crate) unsafe fn with_capacity(num_bytes: usize) -> Term {
        Term(Vec::with_capacity(num_bytes))
    }

    /// Assume the term is a u64 field.
    ///
    /// Panics if the term is not a u64 field.
    pub fn get_u64(&self) -> u64 {
        BigEndian::read_u64(&self.0[4..])
    }

    /// Builds a term from its byte representation.
    ///
    /// If you want to build a field for a given `str`,
    /// you want to use `from_field_text`.
    pub fn from_bytes(data: &[u8]) -> Term {
        Term(Vec::from(data))
    }

    /// Returns the serialized value of the term.
    /// (this does not include the field.)
    ///
    /// If the term is a string, its value is utf-8 encoded.
    /// If the term is a u64, its value is encoded according
    /// to `byteorder::LittleEndian`.
    pub fn value(&self) -> &[u8] {
        &self.0[4..]
    }

    /// Returns the text associated with the term.
    ///
    /// # Panics
    /// If the value is not valid utf-8. This may happen
    /// if the index is corrupted or if you try to
    /// call this method on a non-string type.
    pub fn text(&self) -> &str {
        str::from_utf8(self.value()).expect("Term does not contain valid utf-8.")
    }

    /// Set the texts only, keeping the field untouched.
    pub fn set_text(&mut self, text: &str) {
        self.0.resize(4, 0u8);
        self.0.extend(text.as_bytes());
    }

    /// Returns the underlying `&[u8]`
    pub fn as_slice(&self,)->&[u8] {
        &self.0
    }
}

impl AsRef<[u8]> for Term {
    fn as_ref(&self) -> &[u8] {
        &self.0
    }
}

impl fmt::Debug for Term {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Term({:?})", &self.0[..])
    }
}

#[cfg(test)]
mod tests {

    use schema::*;

    #[test]
    pub fn test_term() {
        let mut schema_builder = SchemaBuilder::default();
        schema_builder.add_text_field("text", STRING);
        let title_field = schema_builder.add_text_field("title", STRING);
        let count_field = schema_builder.add_text_field("count", STRING);
        {
            let term = Term::from_field_text(title_field, "test");
            assert_eq!(term.field(), title_field);
            assert_eq!(&term.as_slice()[0..4], &[0u8,0u8,0u8,1u8]);
            assert_eq!(&term.as_slice()[4..], "test".as_bytes());
        }
        {
            let term = Term::from_field_u64(count_field, 983u64);
            assert_eq!(term.field(), count_field);
            assert_eq!(&term.as_slice()[0..4], &[0u8, 0u8, 0u8, 2u8]);
            assert_eq!(term.as_slice().len(), 4 + 8);
            assert_eq!(term.as_slice()[4], 0u8);
            assert_eq!(term.as_slice()[5], 0u8);
            assert_eq!(term.as_slice()[6], 0u8);
            assert_eq!(term.as_slice()[7], 0u8);
            assert_eq!(term.as_slice()[8], 0u8);
            assert_eq!(term.as_slice()[9], 0u8);
            assert_eq!(term.as_slice()[10], (933u64 / 256u64) as u8);
            assert_eq!(term.as_slice()[11], (983u64 % 256u64) as u8);
        }

    }
}<|endoftext|>


<commit_before>extern crate rand;

use self::rand::distributions::normal::StandardNormal;

pub fn gasdev(a: &mut Vec<Vec<f64>>, b: &mut Vec<Vec<f64>>, mean: f64, std: f64) {

    let size: usize = a.capacity() - 1;

    assert!(a.capacity() == size + 1);
    assert!(b.capacity() == size + 1);
    assert!(a[0].capacity() == size + 1);
    assert!(b[0].capacity() == size + 1);

    for i in 0..(size / 2 + 1) {
        for j in 0..(size / 2 + 1) {

            let StandardNormal(x) = rand::random();
            let mode: f64 = x * std + mean;

            a[i][j] = mode;
        }
    }

    for i in 1..(size / 2) {
        for j in 1..(size / 2) {

            let StandardNormal(x) = rand::random();
            let mode: f64 = x * std + mean;

            b[i][j] = mode;
        }
    }
}
<commit_msg>spectra mod added<commit_after>extern crate rand;

use err::size_assert_2d;

use self::rand::distributions::normal::StandardNormal;

pub fn gasdev(
    field: &Vec<Vec<f64>>,
    a: &mut Vec<Vec<f64>>,
    b: &mut Vec<Vec<f64>>,
    mean: f64,
    std: f64,
) {

    let size: usize = field.capacity() - 1;

    size_assert_2d(&field, &a, &b);

    for i_mode in 0..1 {
        for j_mode in 0..(size / 2 + 1) {

            let StandardNormal(x) = rand::random();
            let mode: f64 = x * std + mean;

            a[i_mode][j_mode] = mode;
        }

        for j_mode in (size / 2 + 1)..size {
            a[i_mode][j_mode] = 0.;
        }

        for j_mode in 1..(size / 2) {

            let StandardNormal(x) = rand::random();
            let mode: f64 = x * std + mean;

            b[i_mode][j_mode] = mode;
        }
        for j_mode in (size / 2)..size {
            b[i_mode][j_mode] = 0.;
        }
    }

    for i_mode in 1..(size / 2) {
        for j_mode in 0..size {

            let StandardNormal(x) = rand::random();
            let mode: f64 = x * std + mean;

            a[i_mode][j_mode] = mode;

            let StandardNormal(x) = rand::random();
            let mode: f64 = x * std + mean;

            b[i_mode][j_mode] = mode;
        }
    }

    for i_mode in (size / 2)..(size / 2 + 1) {
        for j_mode in 0..(size / 2 + 1) {

            let StandardNormal(x) = rand::random();
            let mode: f64 = x * std + mean;

            a[i_mode][j_mode] = mode;
        }

        for j_mode in (size / 2 + 1)..size {
            a[i_mode][j_mode] = 0.;
        }

        for j_mode in 1..(size / 2) {

            let StandardNormal(x) = rand::random();
            let mode: f64 = x * std + mean;

            b[i_mode][j_mode] = mode;
        }
        for j_mode in (size / 2)..size {
            b[i_mode][j_mode] = 0.;
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Ted Mielczarek. See the COPYRIGHT
// file at the top-level directory of this distribution.

//! Information about the system that produced a `Minidump`.

use num_traits::FromPrimitive;
use std::borrow::Cow;
use std::fmt;

use minidump_common::format as md;
use minidump_common::format::PlatformId;
use minidump_common::format::ProcessorArchitecture::*;

/// Known operating systems
///
/// This is a slightly nicer layer over the `PlatformId` enum defined in the minidump-common crate.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Os {
    Windows,
    MacOs,
    Ios,
    Linux,
    Solaris,
    Android,
    Ps3,
    NaCl,
    Unknown(u32),
}

impl Os {
    /// Get an `Os` value matching the `platform_id` value from `MINIDUMP_SYSTEM_INFO`
    pub fn from_platform_id(id: u32) -> Os {
        match PlatformId::from_u32(id) {
            Some(PlatformId::VER_PLATFORM_WIN32_WINDOWS)
                | Some(PlatformId::VER_PLATFORM_WIN32_NT) => Os::Windows,
            Some(PlatformId::MacOs) => Os::MacOs,
            Some(PlatformId::Ios) => Os::Ios,
            Some(PlatformId::Linux) => Os::Linux,
            Some(PlatformId::Solaris) => Os::Solaris,
            Some(PlatformId::Android) => Os::Android,
            Some(PlatformId::Ps3) => Os::Ps3,
            Some(PlatformId::NaCl) => Os::NaCl,
            _ => Os::Unknown(id),
        }
    }

    /// Get a human-readable friendly name for an `Os`
    pub fn long_name(&self) -> Cow<str> {
        match *self {
            Os::Windows => Cow::Borrowed("Windows"),
            Os::MacOs => Cow::Borrowed("Mac OS X"),
            Os::Ios => Cow::Borrowed("iOS"),
            Os::Linux => Cow::Borrowed("Linux"),
            Os::Solaris => Cow::Borrowed("Solaris"),
            Os::Android => Cow::Borrowed("Android"),
            Os::Ps3 => Cow::Borrowed("PS3"),
            Os::NaCl => Cow::Borrowed("NaCl"),
            Os::Unknown(val) => Cow::Owned(format!("{:#08x}", val)),
        }
    }
}

impl fmt::Display for Os {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}",
            match *self {
                Os::Windows => "windows",
                Os::MacOs => "mac",
                Os::Ios => "ios",
                Os::Linux => "linux",
                Os::Solaris => "solaris",
                Os::Android => "android",
                Os::Ps3 => "ps3",
                Os::NaCl => "nacl",
                Os::Unknown(_) => "unknown",
            }
        )
    }
}

/// Known CPU types
///
/// This is a slightly nicer layer over the `ProcessorArchitecture` enum defined in
/// the minidump-common crate.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Cpu {
    X86,
    X86_64,
    Ppc,
    Ppc64,
    Sparc,
    Arm,
    Arm64,
    Unknown(u16),
}

impl Cpu {
    /// Get a `Cpu` value matching the `processor_architecture` value from `MINIDUMP_SYSTEM_INFO`
    pub fn from_processor_architecture(arch: u16) -> Cpu {
        match md::ProcessorArchitecture::from_u16(arch) {
            Some(PROCESSOR_ARCHITECTURE_INTEL) | Some(PROCESSOR_ARCHITECTURE_IA32_ON_WIN64) =>
                Cpu::X86,
            Some(PROCESSOR_ARCHITECTURE_AMD64) => Cpu::X86_64,
            Some(PROCESSOR_ARCHITECTURE_PPC) => Cpu::Ppc,
            Some(PROCESSOR_ARCHITECTURE_PPC64) => Cpu::Ppc64,
            Some(PROCESSOR_ARCHITECTURE_SPARC) => Cpu::Sparc,
            Some(PROCESSOR_ARCHITECTURE_ARM) => Cpu::Arm,
            Some(PROCESSOR_ARCHITECTURE_ARM64) => Cpu::Arm64,
            _ => Cpu::Unknown(arch),
        }
    }
}

impl fmt::Display for Cpu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}",
            match *self {
                Cpu::X86 => "x86",
                Cpu::X86_64 => "x86-64",
                Cpu::Ppc => "ppc",
                Cpu::Ppc64 => "ppc64",
                Cpu::Sparc => "sparc",
                Cpu::Arm => "arm",
                Cpu::Arm64 => "arm64",
                Cpu::Unknown(_) => "unknown",
            }
        )
    }
}
<commit_msg>handle old-style aarch64 dumps in Cpu<commit_after>// Copyright 2015 Ted Mielczarek. See the COPYRIGHT
// file at the top-level directory of this distribution.

//! Information about the system that produced a `Minidump`.

use num_traits::FromPrimitive;
use std::borrow::Cow;
use std::fmt;

use minidump_common::format as md;
use minidump_common::format::PlatformId;
use minidump_common::format::ProcessorArchitecture::*;

/// Known operating systems
///
/// This is a slightly nicer layer over the `PlatformId` enum defined in the minidump-common crate.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Os {
    Windows,
    MacOs,
    Ios,
    Linux,
    Solaris,
    Android,
    Ps3,
    NaCl,
    Unknown(u32),
}

impl Os {
    /// Get an `Os` value matching the `platform_id` value from `MINIDUMP_SYSTEM_INFO`
    pub fn from_platform_id(id: u32) -> Os {
        match PlatformId::from_u32(id) {
            Some(PlatformId::VER_PLATFORM_WIN32_WINDOWS)
                | Some(PlatformId::VER_PLATFORM_WIN32_NT) => Os::Windows,
            Some(PlatformId::MacOs) => Os::MacOs,
            Some(PlatformId::Ios) => Os::Ios,
            Some(PlatformId::Linux) => Os::Linux,
            Some(PlatformId::Solaris) => Os::Solaris,
            Some(PlatformId::Android) => Os::Android,
            Some(PlatformId::Ps3) => Os::Ps3,
            Some(PlatformId::NaCl) => Os::NaCl,
            _ => Os::Unknown(id),
        }
    }

    /// Get a human-readable friendly name for an `Os`
    pub fn long_name(&self) -> Cow<str> {
        match *self {
            Os::Windows => Cow::Borrowed("Windows"),
            Os::MacOs => Cow::Borrowed("Mac OS X"),
            Os::Ios => Cow::Borrowed("iOS"),
            Os::Linux => Cow::Borrowed("Linux"),
            Os::Solaris => Cow::Borrowed("Solaris"),
            Os::Android => Cow::Borrowed("Android"),
            Os::Ps3 => Cow::Borrowed("PS3"),
            Os::NaCl => Cow::Borrowed("NaCl"),
            Os::Unknown(val) => Cow::Owned(format!("{:#08x}", val)),
        }
    }
}

impl fmt::Display for Os {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}",
            match *self {
                Os::Windows => "windows",
                Os::MacOs => "mac",
                Os::Ios => "ios",
                Os::Linux => "linux",
                Os::Solaris => "solaris",
                Os::Android => "android",
                Os::Ps3 => "ps3",
                Os::NaCl => "nacl",
                Os::Unknown(_) => "unknown",
            }
        )
    }
}

/// Known CPU types
///
/// This is a slightly nicer layer over the `ProcessorArchitecture` enum defined in
/// the minidump-common crate.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Cpu {
    X86,
    X86_64,
    Ppc,
    Ppc64,
    Sparc,
    Arm,
    Arm64,
    Unknown(u16),
}

impl Cpu {
    /// Get a `Cpu` value matching the `processor_architecture` value from `MINIDUMP_SYSTEM_INFO`
    pub fn from_processor_architecture(arch: u16) -> Cpu {
        match md::ProcessorArchitecture::from_u16(arch) {
            Some(PROCESSOR_ARCHITECTURE_INTEL) | Some(PROCESSOR_ARCHITECTURE_IA32_ON_WIN64) =>
                Cpu::X86,
            Some(PROCESSOR_ARCHITECTURE_AMD64) => Cpu::X86_64,
            Some(PROCESSOR_ARCHITECTURE_PPC) => Cpu::Ppc,
            Some(PROCESSOR_ARCHITECTURE_PPC64) => Cpu::Ppc64,
            Some(PROCESSOR_ARCHITECTURE_SPARC) => Cpu::Sparc,
            Some(PROCESSOR_ARCHITECTURE_ARM) => Cpu::Arm,
            Some(PROCESSOR_ARCHITECTURE_ARM64) | Some(PROCESSOR_ARCHITECTURE_ARM64_OLD) =>
                Cpu::Arm64,
            _ => Cpu::Unknown(arch),
        }
    }
}

impl fmt::Display for Cpu {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}",
            match *self {
                Cpu::X86 => "x86",
                Cpu::X86_64 => "x86-64",
                Cpu::Ppc => "ppc",
                Cpu::Ppc64 => "ppc64",
                Cpu::Sparc => "sparc",
                Cpu::Arm => "arm",
                Cpu::Arm64 => "arm64",
                Cpu::Unknown(_) => "unknown",
            }
        )
    }
}
<|endoftext|>


<commit_before>use std::ops::Deref;
use {Result, Connection};

/// Old name for `TransactionBehavior`. `SqliteTransactionBehavior` is deprecated.
pub type SqliteTransactionBehavior = TransactionBehavior;

/// Options for transaction behavior. See [BEGIN
/// TRANSACTION](http://www.sqlite.org/lang_transaction.html) for details.
#[derive(Copy,Clone)]
pub enum TransactionBehavior {
    Deferred,
    Immediate,
    Exclusive,
}

/// Old name for `Transaction`. `SqliteTransaction` is deprecated.
pub type SqliteTransaction<'conn> = Transaction<'conn>;

///
/// Represents a transaction on a database connection.
///
/// ## Note
///
/// Transactions will roll back by default. Use the `set_commit` or `commit` methods to commit the
/// transaction.
///
/// ## Example
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result};
/// # fn do_queries_part_1(conn: &Connection) -> Result<()> { Ok(()) }
/// # fn do_queries_part_2(conn: &Connection) -> Result<()> { Ok(()) }
/// fn perform_queries(conn: &Connection) -> Result<()> {
///     let tx = try!(conn.transaction());
///
///     try!(do_queries_part_1(conn)); // tx causes rollback if this fails
///     try!(do_queries_part_2(conn)); // tx causes rollback if this fails
///
///     tx.commit()
/// }
/// ```
pub struct Transaction<'conn> {
    conn: &'conn Connection,
    depth: u32,
    commit: bool,
    finished: bool,
}

impl<'conn> Transaction<'conn> {
    /// Begin a new transaction. Cannot be nested; see `savepoint` for nested transactions.
    pub fn new(conn: &mut Connection, behavior: TransactionBehavior) -> Result<Transaction> {
        let query = match behavior {
            TransactionBehavior::Deferred => "BEGIN DEFERRED",
            TransactionBehavior::Immediate => "BEGIN IMMEDIATE",
            TransactionBehavior::Exclusive => "BEGIN EXCLUSIVE",
        };
        conn.execute_batch(query).map(move |_| {
            Transaction {
                conn: conn,
                depth: 0,
                commit: false,
                finished: false,
            }
        })
    }

    /// Starts a new [savepoint](http://www.sqlite.org/lang_savepoint.html), allowing nested
    /// transactions.
    ///
    /// ## Note
    ///
    /// Just like outer level transactions, savepoint transactions rollback by default.
    ///
    /// ## Example
    ///
    /// ```rust,no_run
    /// # use rusqlite::{Connection, Result};
    /// # fn perform_queries_part_1_succeeds(conn: &Connection) -> bool { true }
    /// fn perform_queries(conn: &Connection) -> Result<()> {
    ///     let tx = try!(conn.transaction());
    ///
    ///     {
    ///         let sp = try!(tx.savepoint());
    ///         if perform_queries_part_1_succeeds(conn) {
    ///             try!(sp.commit());
    ///         }
    ///         // otherwise, sp will rollback
    ///     }
    ///
    ///     tx.commit()
    /// }
    /// ```
    pub fn savepoint(&mut self) -> Result<Transaction> {
        self.conn.execute_batch("SAVEPOINT sp").map(|_| {
            Transaction {
                conn: self.conn,
                depth: self.depth + 1,
                commit: false,
                finished: false,
            }
        })
    }

    /// Returns whether or not the transaction is currently set to commit.
    pub fn will_commit(&self) -> bool {
        self.commit
    }

    /// Returns whether or not the transaction is currently set to rollback.
    pub fn will_rollback(&self) -> bool {
        !self.commit
    }

    /// Set the transaction to commit at its completion.
    pub fn set_commit(&mut self) {
        self.commit = true
    }

    /// Set the transaction to rollback at its completion.
    pub fn set_rollback(&mut self) {
        self.commit = false
    }

    /// A convenience method which consumes and commits a transaction.
    pub fn commit(mut self) -> Result<()> {
        self.commit_()
    }

    fn commit_(&mut self) -> Result<()> {
        self.finished = true;
        self.conn.execute_batch(if self.depth == 0 {
            "COMMIT"
        } else {
            "RELEASE sp"
        })
    }

    /// A convenience method which consumes and rolls back a transaction.
    pub fn rollback(mut self) -> Result<()> {
        self.rollback_()
    }

    fn rollback_(&mut self) -> Result<()> {
        self.finished = true;
        self.conn.execute_batch(if self.depth == 0 {
            "ROLLBACK"
        } else {
            "ROLLBACK TO sp"
        })
    }

    /// Consumes the transaction, committing or rolling back according to the current setting
    /// (see `will_commit`, `will_rollback`).
    ///
    /// Functionally equivalent to the `Drop` implementation, but allows callers to see any
    /// errors that occur.
    pub fn finish(mut self) -> Result<()> {
        self.finish_()
    }

    fn finish_(&mut self) -> Result<()> {
        match (self.finished, self.commit) {
            (true, _) => Ok(()),
            (false, true) => self.commit_(),
            (false, false) => self.rollback_(),
        }
    }
}

impl<'conn> Deref for Transaction<'conn> {
    type Target = Connection;

    fn deref(&self) -> &Connection {
        self.conn
    }
}

#[allow(unused_must_use)]
impl<'conn> Drop for Transaction<'conn> {
    fn drop(&mut self) {
        self.finish_();
    }
}

#[cfg(test)]
#[cfg_attr(feature="clippy", allow(similar_names))]
mod test {
    use Connection;

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (x INTEGER)").unwrap();
        db
    }

    #[test]
    fn test_drop() {
        let mut db = checked_memory_handle();
        {
            let tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
            // default: rollback
        }
        {
            let mut tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(2)").unwrap();
            tx.set_commit()
        }
        {
            let tx = db.transaction().unwrap();
            assert_eq!(2i32,
                       tx.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get(0)).unwrap());
        }
    }

    #[test]
    fn test_explicit_rollback_commit() {
        let mut db = checked_memory_handle();
        {
            let tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
            tx.rollback().unwrap();
        }
        {
            let tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(2)").unwrap();
            tx.commit().unwrap();
        }
        {
            let tx = db.transaction().unwrap();
            assert_eq!(2i32,
                       tx.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get(0)).unwrap());
        }
    }

    #[test]
    fn test_savepoint() {
        let mut db = checked_memory_handle();
        {
            let mut tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
            tx.set_commit();
            {
                let mut sp1 = tx.savepoint().unwrap();
                sp1.execute_batch("INSERT INTO foo VALUES(2)").unwrap();
                sp1.set_commit();
                {
                    let mut sp2 = sp1.savepoint().unwrap();
                    sp2.execute_batch("INSERT INTO foo VALUES(4)").unwrap();
                    // will rollback sp2
                    {
                        let sp3 = sp2.savepoint().unwrap();
                        sp3.execute_batch("INSERT INTO foo VALUES(8)").unwrap();
                        sp3.commit().unwrap();
                        // committed sp3, but will be erased by sp2 rollback
                    }
                }
            }
        }
        assert_eq!(3i32,
                   db.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get(0)).unwrap());
    }
}
<commit_msg>Add test and fix for nested savepoint rollbacks.<commit_after>use std::borrow::Cow;
use std::ops::Deref;
use {Result, Connection};

/// Old name for `TransactionBehavior`. `SqliteTransactionBehavior` is deprecated.
pub type SqliteTransactionBehavior = TransactionBehavior;

/// Options for transaction behavior. See [BEGIN
/// TRANSACTION](http://www.sqlite.org/lang_transaction.html) for details.
#[derive(Copy,Clone)]
pub enum TransactionBehavior {
    Deferred,
    Immediate,
    Exclusive,
}

/// Old name for `Transaction`. `SqliteTransaction` is deprecated.
pub type SqliteTransaction<'conn> = Transaction<'conn>;

///
/// Represents a transaction on a database connection.
///
/// ## Note
///
/// Transactions will roll back by default. Use the `set_commit` or `commit` methods to commit the
/// transaction.
///
/// ## Example
///
/// ```rust,no_run
/// # use rusqlite::{Connection, Result};
/// # fn do_queries_part_1(conn: &Connection) -> Result<()> { Ok(()) }
/// # fn do_queries_part_2(conn: &Connection) -> Result<()> { Ok(()) }
/// fn perform_queries(conn: &Connection) -> Result<()> {
///     let tx = try!(conn.transaction());
///
///     try!(do_queries_part_1(conn)); // tx causes rollback if this fails
///     try!(do_queries_part_2(conn)); // tx causes rollback if this fails
///
///     tx.commit()
/// }
/// ```
pub struct Transaction<'conn> {
    conn: &'conn Connection,
    depth: u32,
    commit: bool,
    finished: bool,
}

impl<'conn> Transaction<'conn> {
    /// Begin a new transaction. Cannot be nested; see `savepoint` for nested transactions.
    pub fn new(conn: &mut Connection, behavior: TransactionBehavior) -> Result<Transaction> {
        let query = match behavior {
            TransactionBehavior::Deferred => "BEGIN DEFERRED",
            TransactionBehavior::Immediate => "BEGIN IMMEDIATE",
            TransactionBehavior::Exclusive => "BEGIN EXCLUSIVE",
        };
        conn.execute_batch(query).map(move |_| {
            Transaction {
                conn: conn,
                depth: 0,
                commit: false,
                finished: false,
            }
        })
    }

    /// Starts a new [savepoint](http://www.sqlite.org/lang_savepoint.html), allowing nested
    /// transactions.
    ///
    /// ## Note
    ///
    /// Just like outer level transactions, savepoint transactions rollback by default.
    ///
    /// ## Example
    ///
    /// ```rust,no_run
    /// # use rusqlite::{Connection, Result};
    /// # fn perform_queries_part_1_succeeds(conn: &Connection) -> bool { true }
    /// fn perform_queries(conn: &Connection) -> Result<()> {
    ///     let tx = try!(conn.transaction());
    ///
    ///     {
    ///         let sp = try!(tx.savepoint());
    ///         if perform_queries_part_1_succeeds(conn) {
    ///             try!(sp.commit());
    ///         }
    ///         // otherwise, sp will rollback
    ///     }
    ///
    ///     tx.commit()
    /// }
    /// ```
    pub fn savepoint(&mut self) -> Result<Transaction> {
        let new_depth = self.depth + 1;
        self.conn.execute_batch(&format!("SAVEPOINT sp{}", new_depth)).map(|_| {
            Transaction {
                conn: self.conn,
                depth: new_depth,
                commit: false,
                finished: false,
            }
        })
    }

    /// Returns whether or not the transaction is currently set to commit.
    pub fn will_commit(&self) -> bool {
        self.commit
    }

    /// Returns whether or not the transaction is currently set to rollback.
    pub fn will_rollback(&self) -> bool {
        !self.commit
    }

    /// Set the transaction to commit at its completion.
    pub fn set_commit(&mut self) {
        self.commit = true
    }

    /// Set the transaction to rollback at its completion.
    pub fn set_rollback(&mut self) {
        self.commit = false
    }

    /// A convenience method which consumes and commits a transaction.
    pub fn commit(mut self) -> Result<()> {
        self.commit_()
    }

    fn commit_(&mut self) -> Result<()> {
        self.finished = true;
        let sql = if self.depth == 0 {
            Cow::Borrowed("COMMIT")
        } else {
            Cow::Owned(format!("RELEASE sp{}", self.depth))
        };
        self.conn.execute_batch(&sql)
    }

    /// A convenience method which consumes and rolls back a transaction.
    pub fn rollback(mut self) -> Result<()> {
        self.rollback_()
    }

    fn rollback_(&mut self) -> Result<()> {
        self.finished = true;
        let sql = if self.depth == 0 {
            Cow::Borrowed("ROLLBACK")
        } else {
            Cow::Owned(format!("ROLLBACK TO sp{}", self.depth))
        };
        self.conn.execute_batch(&sql)
    }

    /// Consumes the transaction, committing or rolling back according to the current setting
    /// (see `will_commit`, `will_rollback`).
    ///
    /// Functionally equivalent to the `Drop` implementation, but allows callers to see any
    /// errors that occur.
    pub fn finish(mut self) -> Result<()> {
        self.finish_()
    }

    fn finish_(&mut self) -> Result<()> {
        match (self.finished, self.commit) {
            (true, _) => Ok(()),
            (false, true) => self.commit_(),
            (false, false) => self.rollback_(),
        }
    }
}

impl<'conn> Deref for Transaction<'conn> {
    type Target = Connection;

    fn deref(&self) -> &Connection {
        self.conn
    }
}

#[allow(unused_must_use)]
impl<'conn> Drop for Transaction<'conn> {
    fn drop(&mut self) {
        self.finish_();
    }
}

#[cfg(test)]
#[cfg_attr(feature="clippy", allow(similar_names))]
mod test {
    use Connection;

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (x INTEGER)").unwrap();
        db
    }

    #[test]
    fn test_drop() {
        let mut db = checked_memory_handle();
        {
            let tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
            // default: rollback
        }
        {
            let mut tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(2)").unwrap();
            tx.set_commit()
        }
        {
            let tx = db.transaction().unwrap();
            assert_eq!(2i32,
                       tx.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get(0)).unwrap());
        }
    }

    #[test]
    fn test_explicit_rollback_commit() {
        let mut db = checked_memory_handle();
        {
            let tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
            tx.rollback().unwrap();
        }
        {
            let tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(2)").unwrap();
            tx.commit().unwrap();
        }
        {
            let tx = db.transaction().unwrap();
            assert_eq!(2i32,
                       tx.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get(0)).unwrap());
        }
    }

    #[test]
    fn test_savepoint() {
        fn assert_current_sum(x: i32, conn: &Connection) {
            let i = conn.query_row("SELECT SUM(x) FROM foo", &[], |r| r.get(0)).unwrap();
            assert_eq!(x, i);
        }

        let mut db = checked_memory_handle();
        {
            let mut tx = db.transaction().unwrap();
            tx.execute_batch("INSERT INTO foo VALUES(1)").unwrap();
            assert_current_sum(1, &tx);
            tx.set_commit();
            {
                let mut sp1 = tx.savepoint().unwrap();
                sp1.execute_batch("INSERT INTO foo VALUES(2)").unwrap();
                assert_current_sum(3, &sp1);
                // will rollback sp1
                {
                    let mut sp2 = sp1.savepoint().unwrap();
                    sp2.execute_batch("INSERT INTO foo VALUES(4)").unwrap();
                    assert_current_sum(7, &sp2);
                    // will rollback sp2
                    {
                        let sp3 = sp2.savepoint().unwrap();
                        sp3.execute_batch("INSERT INTO foo VALUES(8)").unwrap();
                        assert_current_sum(15, &sp3);
                        sp3.commit().unwrap();
                        // committed sp3, but will be erased by sp2 rollback
                    }
                    assert_current_sum(15, &sp2);
                }
                assert_current_sum(3, &sp1);
            }
            assert_current_sum(1, &tx);
        }
        assert_current_sum(1, &db);
    }
}
<|endoftext|>


<commit_before>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<commit_msg>Add trait for sample<commit_after>mod crc;
#[macro_use]
mod macros;
mod types;

pub use self::crc::{crc8, crc16};
pub use self::types::{ErrorKind, ByteStream, ReadStream};

use nom::{self, IResult};
use metadata::{Metadata, metadata_parser};

/// An interface for parsing through some type of producer to a byte stream.
///
/// External parsers get passed in and consumes the bytes held internally
/// and outputs the `Result` of that parser.
pub trait StreamProducer {
  fn parse<F, T>(&mut self, f: F) -> Result<T, ErrorKind>
   where F: FnOnce(&[u8]) -> IResult<&[u8], T, ErrorKind>;
}

pub trait Sample {
  type Normal;

  fn size() -> usize;
  fn to_normal(sample: Self) -> Option<Self::Normal>;
}

// Convert one to four byte slices into an unsigned 32-bit number.
//
// NOTE: This assumes big-endian since most numbers in the FLAC binary are
// that endianness.
#[inline]
pub fn to_u32(bytes: &[u8]) -> u32 {
  let length = bytes.len();

  debug_assert!(length <= 4);

  (0..length).fold(0, |result, i|
    result + ((bytes[i] as u32) << ((length - 1 - i) * 8))
  )
}

// Extends a signed value of a specific bit size to a larger bit size.
//
// NOTE: This assumes that the larger bit size will be 32 bit since that is
// the largest sample size supported in FLAC.
pub fn extend_sign(value: u32, bit_count: usize) -> i32 {
  if bit_count >= 32 || value < (1 << (bit_count - 1)) {
    value as i32
  } else {
    (value as i32).wrapping_sub(1 << bit_count)
  }
}

// Bit shifted version for two to the power of a given exponent.
#[inline]
pub fn power_of_two(exponent: u32) -> u32 {
  debug_assert!(exponent <= 31);

  1 << exponent
}

#[derive(PartialEq, Eq)]
enum ParserState {
  Header,
  StreamInfo,
  Metadata
}

fn parser<'a>(input: &'a [u8], state: &mut ParserState)
              -> IResult<&'a [u8], Metadata, ErrorKind> {
  let mut slice = input;
  let error     = nom::Err::Code(nom::ErrorKind::Custom(ErrorKind::Unknown));

  if *state == ParserState::Header {
    let (i, _) = try_parser! {
      to_custom_error!(slice, tag!("fLaC"), HeaderParser)
    };

    slice  = i;
    *state = ParserState::StreamInfo;
  }

  match *state {
    ParserState::StreamInfo => {
      let (i, block) = try_parse!(slice, metadata_parser);

      if block.is_stream_info() {
        *state = ParserState::Metadata;

        IResult::Done(i, block)
      } else {
        IResult::Error(error)
      }
    }
    ParserState::Metadata   => metadata_parser(slice),
    _                       => IResult::Error(error),
  }
}

pub fn many_metadata<S, F>(stream: &mut S, mut f: F) -> Result<(), ErrorKind>
 where S: StreamProducer,
       F: FnMut(Metadata) {
  let mut state  = ParserState::Header;
  let mut result = Ok(());

  loop {
    match stream.parse(|i| parser(i, &mut state)) {
      Ok(block)                => {
        let is_last = block.is_last();

        f(block);

        if is_last {
          break;
        }
      }
      Err(ErrorKind::Continue) => continue,
      Err(e)                   => {
        result = Err(e);

        break;
      }
    }
  }

  result
}

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

  #[test]
  #[should_panic]
  fn test_panic_to_u32() {
    to_u32(&[0x00, 0x00, 0x00, 0x00, 0x00]);
  }

  #[test]
  fn test_to_u32() {
    let bytes = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];

    assert_eq!(to_u32(&bytes[0..1]), 0x00000001);
    assert_eq!(to_u32(&bytes[3..5]), 0x00006789);
    assert_eq!(to_u32(&bytes[1..4]), 0x00234567);
    assert_eq!(to_u32(&bytes[4..]), 0x89abcdef);
  }

  #[test]
  fn test_extend_sign() {
    assert_eq!(extend_sign(32, 6), -32);
    assert_eq!(extend_sign(31, 6), 31);
    assert_eq!(extend_sign(128, 8), -128);
    assert_eq!(extend_sign(127, 8), 127);

    assert_eq!(extend_sign(2048, 12), -2048);
    assert_eq!(extend_sign(2047, 12), 2047);
    assert_eq!(extend_sign(32768, 16), -32768);
    assert_eq!(extend_sign(32767, 16), 32767);

    assert_eq!(extend_sign(8388608, 24), -8388608);
    assert_eq!(extend_sign(8388607, 24), 8388607);
    assert_eq!(extend_sign(2147483648, 32), -2147483648);
    assert_eq!(extend_sign(2147483647, 32), 2147483647);
  }

  #[test]
  #[should_panic]
  fn test_panic_power_of_two() {
    power_of_two(32);
  }

  #[test]
  fn test_power_of_two() {
    assert_eq!(power_of_two(0), 1);
    assert_eq!(power_of_two(1), 2);
    assert_eq!(power_of_two(2), 4);
    assert_eq!(power_of_two(10), 1024);
    assert_eq!(power_of_two(31), 2147483648);
  }
}
<|endoftext|>