<commit_before>use crate::distribution::{Continuous, Univariate};
use crate::statistics::*;
use crate::{Result, StatsError};
use rand::distributions::Distribution;
use rand::Rng;
use std::f64;

/// Implements the [Dirac Delta](https://en.wikipedia.org/wiki/Dirac_delta_function#As_a_distribution)
/// distribution
///
/// # Examples
///
/// ```
/// use statrs::distribution::{Dirac};
///
/// let n = Dirac::new(3.0).unwrap();
/// assert_eq!(n.mean(), 3.0);
/// assert_eq!(n.pdf(1.0), 0.0);
/// ```
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Dirac(f64);

impl Dirac {
    ///  Constructs a new dirac distribution function at value `v`.
    ///
    /// # Errors
    ///
    /// Returns an error if `v` is not-a-number.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Dirac;
    ///
    /// let mut result = Dirac::new(0.0);
    /// assert!(result.is_ok());
    ///
    /// result = Dirac::new(f64::NAN);
    /// assert!(result.is_err());
    /// ```
    pub fn new(v: f64) -> Result<Self> {
        if v.is_nan() {
            Err(StatsError::BadParams)
        } else {
            Ok(Dirac(v))
        }
    }
}

impl Distribution<f64> for Dirac {
    fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> f64 {
        self.0
    }
}

impl Univariate<f64, f64> for Dirac {
    /// Calculates the cumulative distribution function for the
    /// dirac distribution at `x`
    ///
    /// Where the value is 1 if x > `v`, 0 otherwise.
    ///
    fn cdf(&self, x: f64) -> f64 {
      if x < self.0 { 0.0 } else { 1.0 }
    }
}

impl Min<f64> for Dirac {
    /// Returns the minimum value in the domain of the
    /// dirac distribution representable by a double precision float
    ///
    /// # Formula
    ///
    /// ```ignore
    /// v
    /// ```
    fn min(&self) -> f64 { self.0 }
}

impl Max<f64> for Dirac {
    /// Returns the maximum value in the domain of the
    /// dirac distribution representable by a double precision float
    ///
    /// # Formula
    ///
    /// ```ignore
    /// v
    /// ```
    fn max(&self) -> f64 { self.0 }
}

impl Mean<f64> for Dirac {
    /// Returns the mean of the dirac distribution
    ///
    /// # Remarks
    ///
    /// Since the only value that can be produced by this distribution is `v` with probability
    /// 1, it is just `v`.
    fn mean(&self) -> f64 { self.0 }
}

impl Variance<f64> for Dirac {
    /// Returns the variance of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// 0
    /// ```
    ///
    /// Since only one value can be produced there is no variance.
    fn variance(&self) -> f64 { 0.0 }

    /// Returns the standard deviation of the dirac distribution
    ///
    /// # Remarks
    ///
    /// Since there is no variance in draws from this distribution the standard deviation is
    /// also 0.
    fn std_dev(&self) -> f64 { 0.0 }
}

impl Entropy<f64> for Dirac {
    /// Returns the entropy of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// 0
    /// ```
    ///
    /// Since this distribution has full certainty, it encodes no information
    fn entropy(&self) -> f64 { 0.0 }
}

impl Skewness<f64> for Dirac {
    /// Returns the skewness of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// 0
    /// ```
    fn skewness(&self) -> f64 { 0.0 }
}

impl Median<f64> for Dirac {
    /// Returns the median of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// v
    /// ```
    ///
    /// where `v` is the point of the dirac distribution
    fn median(&self) -> f64 {
        self.0
    }
}

impl Mode<f64> for Dirac {
    /// Returns the mode of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// v
    /// ```
    ///
    /// where `v` is the point of the dirac distribution
    fn mode(&self) -> f64 {
        self.0
    }
}

impl Continuous<f64, f64> for Dirac {
    /// Calculates the probability density function for the dirac distribution
    /// at `x`
    ///
    /// # Formula
    ///
    /// ```ignore
    /// 1 if x = v, 0 otherwise
    /// ```
    ///
    /// where `v` is point of this dirac distribution
    fn pdf(&self, x: f64) -> f64 {
      if x == self.0 { 1.0 } else { 0.0 }
    }

    /// Calculates the log probability density function for the dirac
    /// distribution
    /// at `x`
    ///
    /// # Formula
    ///
    /// ```ignore
    /// ln(1 if x = v, 0 otherwise)
    /// ```
    ///
    /// where `v` is the point of this dirac distribution
    ///
    /// # Remarks
    /// This distribution is usually negative infinity everywhere except at `v`.
    fn ln_pdf(&self, x: f64) -> f64 {
      if self.0 == x { 0.0 } else { f64::NEG_INFINITY }
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    use std::f64;
    use crate::statistics::*;
    use crate::distribution::{Univariate, Continuous, Dirac};
    use crate::distribution::internal::*;

    fn try_create(v: f64) -> Dirac {
        let d = Dirac::new(v);
        assert!(d.is_ok());
        d.unwrap()
    }

    fn create_case(v: f64) {
        let d = try_create(v);
        assert_eq!(v, d.mean());
    }

    fn bad_create_case(v: f64) {
        let d = Dirac::new(v);
        assert!(d.is_err());
    }

    fn test_case<F>(v: f64, expected: f64, eval: F)
        where F: Fn(Dirac) -> f64
    {
        let x = eval(try_create(v));
        assert_eq!(expected, x);
    }

    #[test]
    fn test_create() {
        create_case(10.0);
        create_case(-5.0);
        create_case(10.0);
        create_case(100.0);
        create_case(f64::INFINITY);
    }

    #[test]
    fn test_bad_create() {
        bad_create_case(f64::NAN);
    }

    #[test]
    fn test_variance() {
        test_case(0.0, 0.0, |x| x.variance());
        test_case(-5.0, 0.0, |x| x.variance());
        test_case(f64::INFINITY, 0.0, |x| x.variance());
    }

    #[test]
    fn test_entropy() {
        test_case(0.0, 0.0, |x| x.entropy());
        test_case(f64::INFINITY, 0.0, |x| x.entropy());
    }

    #[test]
    fn test_skewness() {
        test_case(0.0, 0.0, |x| x.skewness());
        test_case(4.0, 0.0, |x| x.skewness());
        test_case(0.3, 0.0, |x| x.skewness());
        test_case(f64::INFINITY, 0.0, |x| x.skewness());
    }

    #[test]
    fn test_mode() {
        test_case(0.0, 0.0, |x| x.mode());
        test_case(3.0, 3.0, |x| x.mode());
        test_case(f64::INFINITY, f64::INFINITY, |x| x.mode());
    }

    #[test]
    fn test_median() {
        test_case(0.0, 0.0, |x| x.median());
        test_case(3.0, 3.0, |x| x.median());
        test_case(f64::INFINITY, f64::INFINITY, |x| x.median());
    }

    #[test]
    fn test_min_max() {
        test_case(0.0, 0.0, |x| x.min());
        test_case(3.0, 3.0, |x| x.min());
        test_case(f64::INFINITY, f64::INFINITY, |x| x.min());

        test_case(0.0, 0.0, |x| x.max());
        test_case(3.0, 3.0, |x| x.max());
        test_case(f64::NEG_INFINITY, f64::NEG_INFINITY, |x| x.max());
    }

    #[test]
    fn test_pdf() {
        test_case(0.0, 0.0, |x| x.pdf(1.0));
        test_case(3.0, 1.0, |x| x.pdf(3.0));
        test_case(f64::NEG_INFINITY, 0.0, |x| x.pdf(1.0));
        test_case(f64::NEG_INFINITY, 1.0, |x| x.pdf(f64::NEG_INFINITY));
    }

    #[test]
    fn test_ln_pdf() {
        test_case(0.0, 0.0, |x| x.ln_pdf(0.0));
        test_case(3.0, 0.0, |x| x.ln_pdf(3.0));
        test_case(f64::INFINITY, f64::NEG_INFINITY, |x| x.ln_pdf(1.0));
        test_case(f64::INFINITY, 0.0, |x| x.ln_pdf(f64::INFINITY));
    }

    #[test]
    fn test_cdf() {
        test_case(0.0, 1.0, |x| x.cdf(0.0));
        test_case(3.0, 1.0, |x| x.cdf(3.0));
        test_case(f64::INFINITY, 0.0, |x| x.cdf(1.0));
        test_case(f64::INFINITY, 1.0, |x| x.cdf(f64::INFINITY));
    }
}
<commit_msg>fix: dirac docstring tests<commit_after>use crate::distribution::{Continuous, Univariate};
use crate::statistics::*;
use crate::{Result, StatsError};
use rand::distributions::Distribution;
use rand::Rng;
use std::f64;

/// Implements the [Dirac Delta](https://en.wikipedia.org/wiki/Dirac_delta_function#As_a_distribution)
/// distribution
///
/// # Examples
///
/// ```
/// use statrs::distribution::{Dirac, Continuous};
/// use statrs::statistics::Mean;
///
/// let n = Dirac::new(3.0).unwrap();
/// assert_eq!(n.mean(), 3.0);
/// assert_eq!(n.pdf(1.0), 0.0);
/// ```
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Dirac(f64);

impl Dirac {
    ///  Constructs a new dirac distribution function at value `v`.
    ///
    /// # Errors
    ///
    /// Returns an error if `v` is not-a-number.
    ///
    /// # Examples
    ///
    /// ```
    /// use statrs::distribution::Dirac;
    ///
    /// let mut result = Dirac::new(0.0);
    /// assert!(result.is_ok());
    ///
    /// result = Dirac::new(f64::NAN);
    /// assert!(result.is_err());
    /// ```
    pub fn new(v: f64) -> Result<Self> {
        if v.is_nan() {
            Err(StatsError::BadParams)
        } else {
            Ok(Dirac(v))
        }
    }
}

impl Distribution<f64> for Dirac {
    fn sample<R: Rng + ?Sized>(&self, _: &mut R) -> f64 {
        self.0
    }
}

impl Univariate<f64, f64> for Dirac {
    /// Calculates the cumulative distribution function for the
    /// dirac distribution at `x`
    ///
    /// Where the value is 1 if x > `v`, 0 otherwise.
    ///
    fn cdf(&self, x: f64) -> f64 {
        if x < self.0 {
            0.0
        } else {
            1.0
        }
    }
}

impl Min<f64> for Dirac {
    /// Returns the minimum value in the domain of the
    /// dirac distribution representable by a double precision float
    ///
    /// # Formula
    ///
    /// ```ignore
    /// v
    /// ```
    fn min(&self) -> f64 {
        self.0
    }
}

impl Max<f64> for Dirac {
    /// Returns the maximum value in the domain of the
    /// dirac distribution representable by a double precision float
    ///
    /// # Formula
    ///
    /// ```ignore
    /// v
    /// ```
    fn max(&self) -> f64 {
        self.0
    }
}

impl Mean<f64> for Dirac {
    /// Returns the mean of the dirac distribution
    ///
    /// # Remarks
    ///
    /// Since the only value that can be produced by this distribution is `v` with probability
    /// 1, it is just `v`.
    fn mean(&self) -> f64 {
        self.0
    }
}

impl Variance<f64> for Dirac {
    /// Returns the variance of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// 0
    /// ```
    ///
    /// Since only one value can be produced there is no variance.
    fn variance(&self) -> f64 {
        0.0
    }

    /// Returns the standard deviation of the dirac distribution
    ///
    /// # Remarks
    ///
    /// Since there is no variance in draws from this distribution the standard deviation is
    /// also 0.
    fn std_dev(&self) -> f64 {
        0.0
    }
}

impl Entropy<f64> for Dirac {
    /// Returns the entropy of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// 0
    /// ```
    ///
    /// Since this distribution has full certainty, it encodes no information
    fn entropy(&self) -> f64 {
        0.0
    }
}

impl Skewness<f64> for Dirac {
    /// Returns the skewness of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// 0
    /// ```
    fn skewness(&self) -> f64 {
        0.0
    }
}

impl Median<f64> for Dirac {
    /// Returns the median of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// v
    /// ```
    ///
    /// where `v` is the point of the dirac distribution
    fn median(&self) -> f64 {
        self.0
    }
}

impl Mode<f64> for Dirac {
    /// Returns the mode of the dirac distribution
    ///
    /// # Formula
    ///
    /// ```ignore
    /// v
    /// ```
    ///
    /// where `v` is the point of the dirac distribution
    fn mode(&self) -> f64 {
        self.0
    }
}

impl Continuous<f64, f64> for Dirac {
    /// Calculates the probability density function for the dirac distribution
    /// at `x`
    ///
    /// # Formula
    ///
    /// ```ignore
    /// 1 if x = v, 0 otherwise
    /// ```
    ///
    /// where `v` is point of this dirac distribution
    fn pdf(&self, x: f64) -> f64 {
        if x == self.0 {
            1.0
        } else {
            0.0
        }
    }

    /// Calculates the log probability density function for the dirac
    /// distribution
    /// at `x`
    ///
    /// # Formula
    ///
    /// ```ignore
    /// ln(1 if x = v, 0 otherwise)
    /// ```
    ///
    /// where `v` is the point of this dirac distribution
    ///
    /// # Remarks
    /// This distribution is usually negative infinity everywhere except at `v`.
    fn ln_pdf(&self, x: f64) -> f64 {
        if self.0 == x {
            0.0
        } else {
            f64::NEG_INFINITY
        }
    }
}

#[cfg_attr(rustfmt, rustfmt_skip)]
#[cfg(test)]
mod test {
    use std::f64;
    use crate::statistics::*;
    use crate::distribution::{Univariate, Continuous, Dirac};

    fn try_create(v: f64) -> Dirac {
        let d = Dirac::new(v);
        assert!(d.is_ok());
        d.unwrap()
    }

    fn create_case(v: f64) {
        let d = try_create(v);
        assert_eq!(v, d.mean());
    }

    fn bad_create_case(v: f64) {
        let d = Dirac::new(v);
        assert!(d.is_err());
    }

    fn test_case<F>(v: f64, expected: f64, eval: F)
        where F: Fn(Dirac) -> f64
    {
        let x = eval(try_create(v));
        assert_eq!(expected, x);
    }

    #[test]
    fn test_create() {
        create_case(10.0);
        create_case(-5.0);
        create_case(10.0);
        create_case(100.0);
        create_case(f64::INFINITY);
    }

    #[test]
    fn test_bad_create() {
        bad_create_case(f64::NAN);
    }

    #[test]
    fn test_variance() {
        test_case(0.0, 0.0, |x| x.variance());
        test_case(-5.0, 0.0, |x| x.variance());
        test_case(f64::INFINITY, 0.0, |x| x.variance());
    }

    #[test]
    fn test_entropy() {
        test_case(0.0, 0.0, |x| x.entropy());
        test_case(f64::INFINITY, 0.0, |x| x.entropy());
    }

    #[test]
    fn test_skewness() {
        test_case(0.0, 0.0, |x| x.skewness());
        test_case(4.0, 0.0, |x| x.skewness());
        test_case(0.3, 0.0, |x| x.skewness());
        test_case(f64::INFINITY, 0.0, |x| x.skewness());
    }

    #[test]
    fn test_mode() {
        test_case(0.0, 0.0, |x| x.mode());
        test_case(3.0, 3.0, |x| x.mode());
        test_case(f64::INFINITY, f64::INFINITY, |x| x.mode());
    }

    #[test]
    fn test_median() {
        test_case(0.0, 0.0, |x| x.median());
        test_case(3.0, 3.0, |x| x.median());
        test_case(f64::INFINITY, f64::INFINITY, |x| x.median());
    }

    #[test]
    fn test_min_max() {
        test_case(0.0, 0.0, |x| x.min());
        test_case(3.0, 3.0, |x| x.min());
        test_case(f64::INFINITY, f64::INFINITY, |x| x.min());

        test_case(0.0, 0.0, |x| x.max());
        test_case(3.0, 3.0, |x| x.max());
        test_case(f64::NEG_INFINITY, f64::NEG_INFINITY, |x| x.max());
    }

    #[test]
    fn test_pdf() {
        test_case(0.0, 0.0, |x| x.pdf(1.0));
        test_case(3.0, 1.0, |x| x.pdf(3.0));
        test_case(f64::NEG_INFINITY, 0.0, |x| x.pdf(1.0));
        test_case(f64::NEG_INFINITY, 1.0, |x| x.pdf(f64::NEG_INFINITY));
    }

    #[test]
    fn test_ln_pdf() {
        test_case(0.0, 0.0, |x| x.ln_pdf(0.0));
        test_case(3.0, 0.0, |x| x.ln_pdf(3.0));
        test_case(f64::INFINITY, f64::NEG_INFINITY, |x| x.ln_pdf(1.0));
        test_case(f64::INFINITY, 0.0, |x| x.ln_pdf(f64::INFINITY));
    }

    #[test]
    fn test_cdf() {
        test_case(0.0, 1.0, |x| x.cdf(0.0));
        test_case(3.0, 1.0, |x| x.cdf(3.0));
        test_case(f64::INFINITY, 0.0, |x| x.cdf(1.0));
        test_case(f64::INFINITY, 1.0, |x| x.cdf(f64::INFINITY));
    }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Flipping_bits_game

// For random generation
extern crate rand;

// For fmt::Display
use std::fmt;
// For I/O (stdin, stdout, etc)
use std::io::prelude::*;

/// A simple struct for a board
struct Board {
    /// The cells of the board
    cells: Vec<bool>,
    /// The size of the board
    size: usize,
}

// Functions for the Board struct
impl Board {
    /// Generate a new, empty board, of size >= 1
    ///
    /// Returns a Board in the "off" state, where all cells are 0.
    /// If a size of 0 is given, a Board of size 1 will be created instead.
    fn new(size: usize) -> Board {
        // Ensure we make a board with a non-zero size
        if size > 0 {
            Board {
                cells: vec![false; size*size],
                size: size,
            }
        } else {
            Board::new(1)
        }
    }

    /// Flip the specified row
    ///
    /// Returns true if the row is within the size, false otherwise.
    ///
    /// ```
    /// let mut board: Board = Board::new();
    /// board.fliprow(1);
    /// ```
    fn fliprow(&mut self, row: usize) -> bool {
        // Check constraints
        if row > self.size {
            return false;
        }
        // Starting position in the vector
        let start = row * self.size;
        // Loop through the vector row
        for i in start..start + self.size {
            self.cells[i] = !self.cells[i];
        }
        true
    }

    /// Flip the specified column
    ///
    /// Returns true if the column is within the size, false otherwise.
    ///
    /// ```
    /// let mut board: Board = Board::new();
    /// board.flipcol(0);
    /// ```
    fn flipcol(&mut self, col: usize) -> bool {
        // Check constraints
        if col > self.size {
            return false;
        }
        // Loop through the vector column
        for i in 0..self.size {
            self.cells[col + i * self.size] = !self.cells[col + i * self.size];
        }
        true
    }

    /// Generate a random board
    ///
    /// Returns a Board in a random state.
    /// If a size of 0 is given, a Board of size 1 will be created instead.
    fn random(size: usize) -> Board {
        // Ensure we make a board with a non-zero size
        if size > 0 {
            // Make a vector of the board size
            let mut r: Vec<bool> = vec![false; size*size];
            // Loop through all the cells
            for i in 0..size * size {
                // Give it a random state
                r[i] = rand::random::<bool>();
            }
            // Return the random board
            Board {
                cells: r.clone(),
                size: size,
            }
        } else {
            Board::random(1)
        }
    }

    /// Check if a board is equal to another
    ///
    /// Returns true if boards are of equal size and contents, false otherwise.
    fn eq(&self, rhs: &Board) -> bool {
        // Has to be a board of the same size
        if self.size != rhs.size {
            return false;
        }
        // Loop through the board
        for i in 0..self.size * self.size {
            // If cells do not match, not equal
            if self.cells[i] != rhs.cells[i] {
                return false;
            }
        }
        // If we get here, boards are equal
        true
    }
}

// Implement the Display format, used with `print!("{}", &board);`
impl fmt::Display for Board {
    // Example output:
    //   0 1 2
    // 0 0 1 0
    // 1 1 0 0
    // 2 0 1 1
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Get the string width of the size of the board
        let width = (self.size - 1).to_string().len();
        // Write the initial spaces (upper left)
        try!(write!(f, "{space: >0$}", width, space = " "));
        // Write the column numbers
        for i in 0..self.size {
            try!(write!(f, " {offset:>0$}", width, offset = i));
        }
        // Newline for rows
        try!(write!(f, "\n"));
        // Loop through the rows
        for row in 0..self.size {
            // Write the row number
            try!(write!(f, "{row:>0$}", width, row = row));
            // Loop through the columns
            for col in 0..self.size {
                // Get the value of the cell as 1 or 0
                let p = if self.cells[row * self.size + col] {
                    1
                } else {
                    0
                };
                // Write the column value
                try!(write!(f, " {col:>0$}", width, col = p));
            }
            // Newline for next row
            try!(write!(f, "\n"));
        }
        // Return Formatter result
        write!(f, "")
    }
}

fn main() {
    // The board size
    let size: usize = 3;
    // The target board
    let target: Board = Board::random(size);
    // The user board
    let mut board: Board = Board::new(size);
    // How many moves taken
    let mut moves: u32 = 0;
    // Loop until win or quit
    'mainloop: loop {
        // User input
        let mut input: String;
        // Write the boards
        println!("Target:\n{}\nBoard:\n{}", &target, &board);
        // User input loop
        'userinput: loop {
            // Prompt
            print!("\nFlip? [q|[r|c]#] ");
            // Flush stdout to write the previous print, if we can't then exit
            match std::io::stdout().flush() {
                Ok(_) => {}
                Err(e) => {
                    println!("Error: cannot flush stdout: {}", e);
                    break 'mainloop;
                }
            };
            // Reset input for each loop
            input = String::new();
            // Read user input
            match std::io::stdin().read_line(&mut input) {
                Ok(_) => {
                    input = input.trim().to_string();
                    // Get the first character
                    let rc: char = match input.chars().nth(0) {
                        Some(c) => c,
                        None => {
                            println!("Error: No input");
                            continue 'userinput;
                        }
                    };
                    // Make sure input is r, c, or q
                    if rc != 'r' && rc != 'c' && rc != 'q' {
                        println!("Error: '{}': Must use 'r'ow or 'c'olumn or 'q'uit", rc);
                        continue 'userinput;
                    }
                    // If input is q, exit game
                    if rc == 'q' {
                        println!("Thanks for playing!");
                        break 'mainloop;
                    }
                    // If input is r or c, get the number after
                    let n: usize = match input[1..].to_string().parse() {
                        Ok(x) => {
                            // If we're within bounds, return the parsed number
                            if x < size {
                                x
                            } else {
                                println!("Error: Must specify a row or column within size({})",
                                         size);
                                continue 'userinput;
                            }
                        }
                        Err(_) => {
                            println!("Error: '{}': Unable to parse row or column number",
                                     input[1..].to_string());
                            continue 'userinput;
                        }
                    };
                    // Flip the row or column specified
                    match rc {
                        'r' => board.fliprow(n),
                        'c' => board.flipcol(n),
                        _ => {
                            // We want to panic here because should NEVER
                            // have anything other than 'r' or 'c' here
                            panic!("How did you end up here?");
                        }
                    };
                    // Increment moves
                    moves += 1;
                    println!("Moves taken: {}", moves);
                    break 'userinput;
                }
                Err(e) => {
                    println!("Error reading input: {}", e);
                    break 'mainloop;
                }
            }
        } // 'userinput
        if board.eq(&target) {
            println!("You win!");
            break;
        }
    } // 'mainloop
}
<commit_msg>Add a few more examples in the comments, and fix the fliprow and flipcol Board::new examples<commit_after>// http://rosettacode.org/wiki/Flipping_bits_game

// For random generation
extern crate rand;

// For fmt::Display
use std::fmt;
// For I/O (stdin, stdout, etc)
use std::io::prelude::*;

/// A simple struct for a board
struct Board {
    /// The cells of the board
    cells: Vec<bool>,
    /// The size of the board
    size: usize,
}

// Functions for the Board struct
impl Board {
    /// Generate a new, empty board, of size >= 1
    ///
    /// Returns a Board in the "off" state, where all cells are 0.
    /// If a size of 0 is given, a Board of size 1 will be created instead.
    /// A mutable board is required for using Board::fliprow and Board::flipcol functions.
    ///
    /// ```
    /// let mut board: Board = Board::new(3);
    /// ```
    fn new(size: usize) -> Board {
        // Ensure we make a board with a non-zero size
        if size > 0 {
            Board {
                cells: vec![false; size*size],
                size: size,
            }
        } else {
            Board::new(1)
        }
    }

    /// Flip the specified row
    ///
    /// Returns true if the row is within the size, false otherwise.
    ///
    /// ```
    /// let mut board: Board = Board::new(3);
    /// board.fliprow(1);
    /// ```
    fn fliprow(&mut self, row: usize) -> bool {
        // Check constraints
        if row > self.size {
            return false;
        }
        // Starting position in the vector
        let start = row * self.size;
        // Loop through the vector row
        for i in start..start + self.size {
            self.cells[i] = !self.cells[i];
        }
        true
    }

    /// Flip the specified column
    ///
    /// Returns true if the column is within the size, false otherwise.
    ///
    /// ```
    /// let mut board: Board = Board::new(3);
    /// board.flipcol(0);
    /// ```
    fn flipcol(&mut self, col: usize) -> bool {
        // Check constraints
        if col > self.size {
            return false;
        }
        // Loop through the vector column
        for i in 0..self.size {
            self.cells[col + i * self.size] = !self.cells[col + i * self.size];
        }
        true
    }

    /// Generate a random board
    ///
    /// Returns a Board in a random state.
    /// If a size of 0 is given, a Board of size 1 will be created instead.
    ///
    /// ```
    /// let target: Board = Board::random(3);
    /// ```
    fn random(size: usize) -> Board {
        // Ensure we make a board with a non-zero size
        if size > 0 {
            // Make a vector of the board size
            let mut r: Vec<bool> = vec![false; size*size];
            // Loop through all the cells
            for i in 0..size * size {
                // Give it a random state
                r[i] = rand::random::<bool>();
            }
            // Return the random board
            Board {
                cells: r.clone(),
                size: size,
            }
        } else {
            Board::random(1)
        }
    }

    /// Check if a board is equal to another
    ///
    /// Returns true if boards are of equal size and contents, false otherwise.
    ///
    /// ```
    /// let mut board: Board = Board::new(3);
    /// let target: Board = Board::random(3);
    /// if board.eq(&target) {
    ///     // randomness won and set to empty board
    /// } else {
    ///     // not equal
    /// ```
    fn eq(&self, rhs: &Board) -> bool {
        // Has to be a board of the same size
        if self.size != rhs.size {
            return false;
        }
        // Loop through the board
        for i in 0..self.size * self.size {
            // If cells do not match, not equal
            if self.cells[i] != rhs.cells[i] {
                return false;
            }
        }
        // If we get here, boards are equal
        true
    }
}

// Implement the Display format, used with `print!("{}", &board);`
impl fmt::Display for Board {
    // Example output:
    //   0 1 2
    // 0 0 1 0
    // 1 1 0 0
    // 2 0 1 1
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Get the string width of the size of the board
        let width = (self.size - 1).to_string().len();
        // Write the initial spaces (upper left)
        try!(write!(f, "{space: >0$}", width, space = " "));
        // Write the column numbers
        for i in 0..self.size {
            try!(write!(f, " {offset:>0$}", width, offset = i));
        }
        // Newline for rows
        try!(write!(f, "\n"));
        // Loop through the rows
        for row in 0..self.size {
            // Write the row number
            try!(write!(f, "{row:>0$}", width, row = row));
            // Loop through the columns
            for col in 0..self.size {
                // Get the value of the cell as 1 or 0
                let p = if self.cells[row * self.size + col] {
                    1
                } else {
                    0
                };
                // Write the column value
                try!(write!(f, " {col:>0$}", width, col = p));
            }
            // Newline for next row
            try!(write!(f, "\n"));
        }
        // Return Formatter result
        write!(f, "")
    }
}

fn main() {
    // The board size
    let size: usize = 3;
    // The target board
    let target: Board = Board::random(size);
    // The user board
    let mut board: Board = Board::new(size);
    // How many moves taken
    let mut moves: u32 = 0;
    // Loop until win or quit
    'mainloop: loop {
        // User input
        let mut input: String;
        // Write the boards
        println!("Target:\n{}\nBoard:\n{}", &target, &board);
        // User input loop
        'userinput: loop {
            // Prompt
            print!("\nFlip? [q|[r|c]#] ");
            // Flush stdout to write the previous print, if we can't then exit
            match std::io::stdout().flush() {
                Ok(_) => {}
                Err(e) => {
                    println!("Error: cannot flush stdout: {}", e);
                    break 'mainloop;
                }
            };
            // Reset input for each loop
            input = String::new();
            // Read user input
            match std::io::stdin().read_line(&mut input) {
                Ok(_) => {
                    input = input.trim().to_string();
                    // Get the first character
                    let rc: char = match input.chars().nth(0) {
                        Some(c) => c,
                        None => {
                            println!("Error: No input");
                            continue 'userinput;
                        }
                    };
                    // Make sure input is r, c, or q
                    if rc != 'r' && rc != 'c' && rc != 'q' {
                        println!("Error: '{}': Must use 'r'ow or 'c'olumn or 'q'uit", rc);
                        continue 'userinput;
                    }
                    // If input is q, exit game
                    if rc == 'q' {
                        println!("Thanks for playing!");
                        break 'mainloop;
                    }
                    // If input is r or c, get the number after
                    let n: usize = match input[1..].to_string().parse() {
                        Ok(x) => {
                            // If we're within bounds, return the parsed number
                            if x < size {
                                x
                            } else {
                                println!("Error: Must specify a row or column within size({})",
                                         size);
                                continue 'userinput;
                            }
                        }
                        Err(_) => {
                            println!("Error: '{}': Unable to parse row or column number",
                                     input[1..].to_string());
                            continue 'userinput;
                        }
                    };
                    // Flip the row or column specified
                    match rc {
                        'r' => board.fliprow(n),
                        'c' => board.flipcol(n),
                        _ => {
                            // We want to panic here because should NEVER
                            // have anything other than 'r' or 'c' here
                            panic!("How did you end up here?");
                        }
                    };
                    // Increment moves
                    moves += 1;
                    println!("Moves taken: {}", moves);
                    break 'userinput;
                }
                Err(e) => {
                    println!("Error reading input: {}", e);
                    break 'mainloop;
                }
            }
        } // 'userinput
        if board.eq(&target) {
            println!("You win!");
            break;
        }
    } // 'mainloop
}
<|endoftext|>


<commit_before>use collections::slice::{mod, AsSlice, SlicePrelude};
use collections::vec::{mod, Vec};
use core::mem;
use core::iter::{mod, Iterator};
use core::option::{mod, Some, None, Option};

use iobuf::Iobuf;

/// A span over potentially many Iobufs. This is useful as a "string" type where
/// the contents of the string can potentially come from multiple IObufs, and
/// you want to avoid copying.
///
/// As an optimization, pushing an Iobuf that points to data immediately after
/// the range represented by the last Iobuf pushed will result in just expanding
/// the held Iobuf's range. This prevents allocating lots of unnecessary
/// intermediate buffers, while still maintaining the illusion of "pushing lots
/// of buffers" while incrementally parsing.
///
/// A `BufSpan` is internally represented as either an `Iobuf` or a `Vec<Iobuf>`,
/// depending on how many different buffers were used.
pub enum BufSpan<Buf> {
  Empty,
  One (Buf),
  Many(Vec<Buf>),
}

impl<Buf: Iobuf> BufSpan<Buf> {
  /// Creates a new, empty `Bufspan`.
  #[inline]
  pub fn new() -> BufSpan<Buf> {
    Empty
  }

  /// Returns `true` iff the span is over an empty range.
  #[inline]
  pub fn is_empty(&self) -> bool {
    match *self {
      Empty       => true,
      One (ref b) => b.is_empty(),
      Many(ref v) => v.iter().all(|b| b.is_empty()),
    }
  }

  /// The fast path during pushing -- either fills in the first buffer, or
  /// extends an existing one.
  ///
  /// Returns `None` if the fast path was taken and nothing more needs to be
  /// done. Returns `Some` if we need to do a slow push.
  #[inline]
  fn try_to_extend(&mut self, b: Buf) -> Option<Buf> {
    match self {
      &Empty => {},
      &One(ref mut b0) => {
        unsafe {
          if b0.is_extended_by(&b) {
            b0.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b); // Upgrade the `One` into a `Many` in the slow path.
          }
        }
      }
      &Many(ref mut v) => {
        // I wish this wouldn't unwind, and just abort... :(
        let last = v.last_mut().unwrap();
        unsafe {
          if last.is_extended_by(&b) {
            last.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b);
          }
        }
      }
    }

    // Handle this case in the fast path, instead of leaving it for slow_push
    // to clean up.
    *self = One(b);
    None
  }

  /// Appends a buffer to a `BufSpan`. If the buffer is an extension of the
  /// previously pushed buffer, the range will be extended. Otherwise, the new
  /// non-extension buffer will be added to the end of a vector.
  #[inline]
  pub fn push(&mut self, b: Buf) {
    match self.try_to_extend(b) {
      None    => {},
      Some(b) => self.slow_push(b),
    }
  }

  /// The slow path during a push. This is only taken if a `BufSpan` must span
  /// multiple backing buffers.
  #[cold]
  fn slow_push(&mut self, b: Buf) {
    let this = mem::replace(self, Empty);
    *self =
      match this {
        Empty   => One(b),
        One(b0) => {
          let mut v = Vec::with_capacity(2);
          v.push(b0);
          v.push(b);
          Many(v)
        },
        Many(mut bs) => { bs.push(b); Many(bs) }
      };
  }

  /// Returns an iterator over references to the buffers inside the `BufSpan`.
  #[inline]
  pub fn iter<'a>(&'a self) -> SpanIter<'a, Buf> {
    match *self {
      Empty       => Opt(None.into_iter()),
      One (ref b) => Opt(Some(b).into_iter()),
      Many(ref v) => Lot(v.as_slice().iter()),
    }
  }

  /// Returns a moving iterator over the buffers inside the `BufSpan`.
  #[inline]
  pub fn into_iter(self) -> SpanMoveIter<Buf> {
    match self {
      Empty   => MoveOpt(None.into_iter()),
      One (b) => MoveOpt(Some(b).into_iter()),
      Many(v) => MoveLot(v.into_iter()),
    }
  }

  /// Returns an iterator over the bytes in the `BufSpan`.
  #[inline]
  pub fn iter_bytes<'a>(&'a self) -> ByteIter<'a, Buf> {
    self.iter()
        .flat_map(|buf| unsafe { buf.as_window_slice().iter() })
        .map(|&b| b)
  }
}

/// An iterator over the bytes in a `BufSpan`.
pub type ByteIter<'a, Buf> =
  iter::Map<'static, &'a u8, u8,
    iter::FlatMap<'static, &'a Buf,
      SpanIter<'a, Buf>,
      slice::Items<'a, u8>>>;

/// An iterator over references to buffers inside a `BufSpan`.
pub enum SpanIter<'a, Buf: 'a> {
  Opt(option::Item<&'a Buf>),
  Lot(slice::Items<'a, Buf>),
}

impl<'a, Buf: Iobuf> Iterator<&'a Buf> for SpanIter<'a, Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<&'a Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      Opt(ref mut iter) => iter.next(),
      Lot(ref mut iter) => iter.next(),
    }
  }
}

/// A moving iterator over buffers inside a `BufSpan`.
pub enum SpanMoveIter<Buf> {
  MoveOpt(option::Item<Buf>),
  MoveLot(vec::MoveItems<Buf>),
}

impl<Buf: Iobuf> Iterator<Buf> for SpanMoveIter<Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      MoveOpt(ref mut iter) => iter.next(),
      MoveLot(ref mut iter) => iter.next(),
    }
  }
}
<commit_msg>[bufspan] more docs, more funcs<commit_after>use collections::slice::{mod, AsSlice, SlicePrelude};
use collections::vec::{mod, Vec};
use core::mem;
use core::iter::{mod, Iterator};
use core::option::{mod, Some, None, Option};

use iobuf::Iobuf;

/// A span over potentially many Iobufs. This is useful as a "string" type where
/// the contents of the string can potentially come from multiple IObufs, and
/// you want to avoid copying.
///
/// As an optimization, pushing an Iobuf that points to data immediately after
/// the range represented by the last Iobuf pushed will result in just expanding
/// the held Iobuf's range. This prevents allocating lots of unnecessary
/// intermediate buffers, while still maintaining the illusion of "pushing lots
/// of buffers" while incrementally parsing.
///
/// A `BufSpan` is internally represented as either an `Iobuf` or a `Vec<Iobuf>`,
/// depending on how many different buffers were used.
pub enum BufSpan<Buf> {
  Empty,
  One (Buf),
  Many(Vec<Buf>),
}

impl<Buf: Iobuf> BufSpan<Buf> {
  /// Creates a new, empty `Bufspan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let s: BufSpan<ROIobuf<'static>> = BufSpan::new();
  /// assert!(s.is_empty());
  /// ```
  #[inline]
  pub fn new() -> BufSpan<Buf> {
    Empty
  }

  /// Creates a new `BufSpan` from a slice of bytes.
  ///
  /// ```
  /// use iobuf::{BufSpan, Iobuf, ROIobuf};
  /// use std::iter::AdditiveIterator;
  ///
  /// let s = BufSpan::from_buf(ROIobuf::from_slice(b"hello"));
  /// assert_eq!(s.iter().count(), 1);
  /// assert_eq!(s.iter().map(|b| b.len()).sum(), 5);
  /// ```
  #[inline]
  pub fn from_buf(b: Buf) -> BufSpan<Buf> {
    One(b)
  }

  /// Returns `true` iff the span is over an empty range.
  ///
  /// ```
  /// use iobuf::{BufSpan, Iobuf, ROIobuf};
  ///
  /// let mut s = BufSpan::new();
  ///
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str(""));
  /// assert!(s.is_empty());
  ///
  /// s.push(ROIobuf::from_str("hello, world!"));
  /// assert!(!s.is_empty());
  /// ```
  #[inline]
  pub fn is_empty(&self) -> bool {
    match *self {
      Empty       => true,
      One (ref b) => b.is_empty(),
      Many(ref v) => v.iter().all(|b| b.is_empty()),
    }
  }

  /// The fast path during pushing -- either fills in the first buffer, or
  /// extends an existing one.
  ///
  /// Returns `None` if the fast path was taken and nothing more needs to be
  /// done. Returns `Some` if we need to do a slow push.
  #[inline]
  fn try_to_extend(&mut self, b: Buf) -> Option<Buf> {
    match *self {
      Empty => {},
      One(ref mut b0) => {
        unsafe {
          if b0.is_extended_by(&b) {
            b0.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b); // Upgrade the `One` into a `Many` in the slow path.
          }
        }
      }
      Many(ref mut v) => {
        // I wish this wouldn't unwind, and just abort... :(
        let last = v.last_mut().unwrap();
        unsafe {
          if last.is_extended_by(&b) {
            last.unsafe_extend(b.len());
            return None;
          } else {
            return Some(b);
          }
        }
      }
    }

    // Handle this case in the fast path, instead of leaving it for slow_push
    // to clean up.
    *self = One(b);
    None
  }

  /// Appends a buffer to a `BufSpan`. If the buffer is an extension of the
  /// previously pushed buffer, the range will be extended. Otherwise, the new
  /// non-extension buffer will be added to the end of a vector.
  #[inline]
  pub fn push(&mut self, b: Buf) {
    match self.try_to_extend(b) {
      None    => {},
      Some(b) => self.slow_push(b),
    }
  }

  /// The slow path during a push. This is only taken if a `BufSpan` must span
  /// multiple backing buffers.
  #[cold]
  fn slow_push(&mut self, b: Buf) {
    let this = mem::replace(self, Empty);
    *self =
      match this {
        Empty   => One(b),
        One(b0) => {
          let mut v = Vec::with_capacity(2);
          v.push(b0);
          v.push(b);
          Many(v)
        },
        Many(mut bs) => { bs.push(b); Many(bs) }
      };
  }

  /// Returns an iterator over references to the buffers inside the `BufSpan`.
  #[inline]
  pub fn iter<'a>(&'a self) -> SpanIter<'a, Buf> {
    match *self {
      Empty       => Opt(None.into_iter()),
      One (ref b) => Opt(Some(b).into_iter()),
      Many(ref v) => Lot(v.as_slice().iter()),
    }
  }

  /// Returns a moving iterator over the buffers inside the `BufSpan`.
  #[inline]
  pub fn into_iter(self) -> SpanMoveIter<Buf> {
    match self {
      Empty   => MoveOpt(None.into_iter()),
      One (b) => MoveOpt(Some(b).into_iter()),
      Many(v) => MoveLot(v.into_iter()),
    }
  }

  /// Returns an iterator over the bytes in the `BufSpan`.
  #[inline]
  pub fn iter_bytes<'a>(&'a self) -> ByteIter<'a, Buf> {
    self.iter()
        .flat_map(|buf| unsafe { buf.as_window_slice().iter() })
        .map(|&b| b)
  }

  /// Returns `true` iff the bytes in this `BufSpan` are the same as the bytes
  /// in the other `BufSpan`.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf, RWIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  /// let b = BufSpan::from_buf(RWIobuf::from_string("hello".into_string()));
  ///
  /// assert!(a.byte_equal(&b));
  ///
  /// let mut c = BufSpan::from_buf(ROIobuf::from_str("hel"));
  /// c.push(ROIobuf::from_str("lo"));
  ///
  /// assert!(a.byte_equal(&c)); assert!(c.byte_equal(&a));
  ///
  /// let d = BufSpan::from_buf(ROIobuf::from_str("helo"));
  /// assert!(!a.byte_equal(&d));
  /// ```
  #[inline]
  pub fn byte_equal<Buf2: Iobuf>(&self, other: &BufSpan<Buf2>) -> bool {
    self.iter_bytes().zip(other.iter_bytes()).all(|(a, b)| a == b)
  }

  /// A more efficient version of byte_equal, specialized to work exclusively on
  /// slices.
  ///
  /// ```
  /// use iobuf::{BufSpan, ROIobuf};
  ///
  /// let a = BufSpan::from_buf(ROIobuf::from_str("hello"));
  ///
  /// assert!(a.byte_equal_slice(b"hello"));
  /// assert!(!a.byte_equal_slice(b"helo"));
  /// ```
  #[inline]
  pub fn byte_equal_slice(&self, other: &[u8]) -> bool {
    self.iter_bytes().zip(other.iter()).all(|(a, &b)| a == b)
  }
}

/// An iterator over the bytes in a `BufSpan`.
pub type ByteIter<'a, Buf> =
  iter::Map<'static, &'a u8, u8,
    iter::FlatMap<'static, &'a Buf,
      SpanIter<'a, Buf>,
      slice::Items<'a, u8>>>;

/// An iterator over references to buffers inside a `BufSpan`.
pub enum SpanIter<'a, Buf: 'a> {
  Opt(option::Item<&'a Buf>),
  Lot(slice::Items<'a, Buf>),
}

impl<'a, Buf: Iobuf> Iterator<&'a Buf> for SpanIter<'a, Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<&'a Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      Opt(ref mut iter) => iter.next(),
      Lot(ref mut iter) => iter.next(),
    }
  }
}

/// A moving iterator over buffers inside a `BufSpan`.
pub enum SpanMoveIter<Buf> {
  MoveOpt(option::Item<Buf>),
  MoveLot(vec::MoveItems<Buf>),
}

impl<Buf: Iobuf> Iterator<Buf> for SpanMoveIter<Buf> {
  #[inline(always)]
  fn next(&mut self) -> Option<Buf> {
    // I'm couting on this match getting lifted out of the loop with
    // loop-invariant code motion.
    match *self {
      MoveOpt(ref mut iter) => iter.next(),
      MoveLot(ref mut iter) => iter.next(),
    }
  }
}
<|endoftext|>


<commit_before>use std::old_io::Buffer;

use dom::{Document, Element, Text, Node, rc_node_new, RcElement, rc_element_new, rc_text_new};
use error::BuildError;

use xml::common::XmlVersion;
use xml::reader::EventReader;
use xml::reader::events::XmlEvent;

/// `build` creates a `Document` from an `EventReader`.
///
/// `build` iterates through the events yielded by the provided `EventReader`.
/// This allows you to configure the `EvenReader` as you desire. It will create
/// a reference counted DOM that you can then manipulate. The builder will return
/// a `BuildError` if the source document is invalid of if it is empty.
///
/// The builder should not panic. It should only panic in case of an impossible
/// scenario. Please report any panics.
pub fn build<B: Buffer>(reader: &mut EventReader<B>) -> Result<Document, BuildError> {
    let mut root: Option<RcElement> = None;
    let mut curr: Option<RcElement> = None;
    let mut doc_version: Option<XmlVersion> = None;
    let mut doc_encoding: Option<String> = None;

    for event in reader.events() {
        match event {
            // StartDocument
            XmlEvent::StartDocument { version, encoding, standalone: _ } => {
                doc_version = Some(version);
                doc_encoding = Some(encoding);
            }
            // StartElement
            XmlEvent::StartElement { name, attributes, namespace } => {
                // Check if a root exists.
                match root {
                    // If it does not, it must be created.
                    // Also sets the current element to the root.
                    None => {
                        let elem = Element::new_root(name, attributes, namespace);
                        let rcelem = rc_element_new(elem);
                        root = Some(rcelem.clone());
                        curr = Some(rcelem.clone());
                    }
                    // If it does, the new element will be appended,
                    // to the current element.
                    Some (_) => {
                        match curr {
                            // This should never happen.
                            None => panic!("Root is set but current is not."),
                            Some(parent) => {
                                // create the element with the parent as a weak reference
                                let elem = Element::new(parent.clone().downgrade(), name, attributes, namespace);
                                let rcelem = rc_element_new(elem);
                                // create a node from the element
                                let node = Node::Element(rcelem.clone());
                                let rcnode = rc_node_new(node);
                                // add the element to the parent
                                parent.borrow_mut().add_child(rcnode);
                                // move into the new element
                                curr = Some(rcelem.clone());
                            }
                        }
                    }
                }
            }
            // EndElement
            XmlEvent::EndElement { name: _ } => {
                match curr {
                    // This should never happen.
                    None => panic!("End element before start element."),
                    Some(elem) => {
                        // move out of the element by setting the current
                        // element to the parent of the element we're
                        // exiting
                        match elem.borrow().parent {
                            // current has no parent, so it's probably root
                            None => {
                                // check if root is valid
                                match root {
                                    // This should never happen.
                                    None => panic!("End element without any root."),
                                    Some(ref root) => {
                                        curr = Some(root.clone());
                                    }
                                }
                            }
                            Some(ref parent) => {
                                curr = Some(parent.clone().upgrade()
                                    .expect("Unable to upgrade WeakReference, parent was dropped."));
                            }
                        }
                    }
                }
            },
            // Cdata or Characters
            XmlEvent::CData(content) | XmlEvent::Characters(content) => {
                match curr {
                    // This should never happen.
                    None => panic!("Text node before any element."),
                    Some(ref parent) => {
                        // create the text node with the parent as a weak reference
                        let text = Text::new(parent.clone().downgrade(), content);
                        let rctext = rc_text_new(text);
                        // create wrapper node
                        let node = Node::Text(rctext);
                        let rcnode = rc_node_new(node);
                        // add the text node to the parent
                        parent.borrow_mut().add_child(rcnode.clone());
                    }
                }
            },
            // Error
            XmlEvent::Error(err) => {
                return Err(BuildError::ParserError(err));
            }
            // Ignore other events.
            _ => {}
        }
    }

    match root {
        None => Err(BuildError::UndefinedRoot),
        Some (root) => {
            Ok(Document {
                version: doc_version,
                encoding: doc_encoding,
                root: root.clone(),
            })
        }
    }
}
<commit_msg>Use Read rather than removed Buffer.<commit_after>use std::io::Read;

use dom::{Document, Element, Text, Node, rc_node_new, RcElement, rc_element_new, rc_text_new};
use error::BuildError;

use xml::common::XmlVersion;
use xml::reader::EventReader;
use xml::reader::events::XmlEvent;

/// `build` creates a `Document` from an `EventReader`.
///
/// `build` iterates through the events yielded by the provided `EventReader`.
/// This allows you to configure the `EvenReader` as you desire. It will create
/// a reference counted DOM that you can then manipulate. The builder will return
/// a `BuildError` if the source document is invalid of if it is empty.
///
/// The builder should not panic. It should only panic in case of an impossible
/// scenario. Please report any panics.
pub fn build<B: Read>(reader: &mut EventReader<B>) -> Result<Document, BuildError> {
    let mut root: Option<RcElement> = None;
    let mut curr: Option<RcElement> = None;
    let mut doc_version: Option<XmlVersion> = None;
    let mut doc_encoding: Option<String> = None;

    for event in reader.events() {
        match event {
            // StartDocument
            XmlEvent::StartDocument { version, encoding, standalone: _ } => {
                doc_version = Some(version);
                doc_encoding = Some(encoding);
            }
            // StartElement
            XmlEvent::StartElement { name, attributes, namespace } => {
                // Check if a root exists.
                match root {
                    // If it does not, it must be created.
                    // Also sets the current element to the root.
                    None => {
                        let elem = Element::new_root(name, attributes, namespace);
                        let rcelem = rc_element_new(elem);
                        root = Some(rcelem.clone());
                        curr = Some(rcelem.clone());
                    }
                    // If it does, the new element will be appended,
                    // to the current element.
                    Some (_) => {
                        match curr {
                            // This should never happen.
                            None => panic!("Root is set but current is not."),
                            Some(parent) => {
                                // create the element with the parent as a weak reference
                                let elem = Element::new(parent.clone().downgrade(), name, attributes, namespace);
                                let rcelem = rc_element_new(elem);
                                // create a node from the element
                                let node = Node::Element(rcelem.clone());
                                let rcnode = rc_node_new(node);
                                // add the element to the parent
                                parent.borrow_mut().add_child(rcnode);
                                // move into the new element
                                curr = Some(rcelem.clone());
                            }
                        }
                    }
                }
            }
            // EndElement
            XmlEvent::EndElement { name: _ } => {
                match curr {
                    // This should never happen.
                    None => panic!("End element before start element."),
                    Some(elem) => {
                        // move out of the element by setting the current
                        // element to the parent of the element we're
                        // exiting
                        match elem.borrow().parent {
                            // current has no parent, so it's probably root
                            None => {
                                // check if root is valid
                                match root {
                                    // This should never happen.
                                    None => panic!("End element without any root."),
                                    Some(ref root) => {
                                        curr = Some(root.clone());
                                    }
                                }
                            }
                            Some(ref parent) => {
                                curr = Some(parent.clone().upgrade()
                                    .expect("Unable to upgrade WeakReference, parent was dropped."));
                            }
                        }
                    }
                }
            },
            // Cdata or Characters
            XmlEvent::CData(content) | XmlEvent::Characters(content) => {
                match curr {
                    // This should never happen.
                    None => panic!("Text node before any element."),
                    Some(ref parent) => {
                        // create the text node with the parent as a weak reference
                        let text = Text::new(parent.clone().downgrade(), content);
                        let rctext = rc_text_new(text);
                        // create wrapper node
                        let node = Node::Text(rctext);
                        let rcnode = rc_node_new(node);
                        // add the text node to the parent
                        parent.borrow_mut().add_child(rcnode.clone());
                    }
                }
            },
            // Error
            XmlEvent::Error(err) => {
                return Err(BuildError::ParserError(err));
            }
            // Ignore other events.
            _ => {}
        }
    }

    match root {
        None => Err(BuildError::UndefinedRoot),
        Some (root) => {
            Ok(Document {
                version: doc_version,
                encoding: doc_encoding,
                root: root.clone(),
            })
        }
    }
}
<|endoftext|>


<commit_before>use std::process::Command;
use std::rc::Rc;
use std::fs::{create_dir_all, copy};

use paths::Paths;
use reporter::{report, report_command};

pub struct Builder {
   paths: Rc<Paths>,
}

impl Builder {
   pub fn new(paths: Rc<Paths>) -> Self {
      Builder {
         paths: paths,
      }
   }

   pub fn build(&self) {
      self.configure();
   }

   fn configure(&self) {
      self.setup_conf_path();

      let prefix = format!("--prefix={}", self.paths.target_path.to_str().unwrap());
      let conf_path = format!("--conf-path={}", self.paths.nginx_conf_path.to_str().unwrap());
      let add_module = format!("--add-module={}", self.paths.module_dir_path.to_str().unwrap());

      let args = vec![
         "--with-http_ssl_module",
         prefix.as_slice(),
         conf_path.as_slice(),
         add_module.as_slice(),
      ];

      report_command("Configuring", "configure", &args);

      Command::new(&self.paths.configure_path).args(&args).current_dir(&self.paths.extract_path).status().unwrap_or_else(|e| {
         panic!("Configuring Nginx build failed: {}.", e)
      });
   }

   fn setup_conf_path(&self) {
      report("Creating", format!("{:?}", &self.paths.nginx_conf_prefix_path));

      create_dir_all(&self.paths.nginx_conf_prefix_path).unwrap_or_else(|e| {
         panic!("Cannot create nginx conf prefix path - {:?}: {}.", self.paths.nginx_conf_prefix_path, e)
      });

      report("Copying", format!("nginx.conf {:?}", &self.paths.nginx_conf_path));

      copy(&self.paths.nginx_conf_source_path, &self.paths.nginx_conf_path).unwrap_or_else(|e| {
         panic!("Cannot copy nginx.conf {:?} -> {:?}: {}.", self.paths.nginx_conf_source_path, self.paths.nginx_conf_path, e)
      });
   }
}
<commit_msg>Make and make install commands for the nginx build.<commit_after>use std::process::Command;
use std::rc::Rc;
use std::fs::{create_dir_all, copy};

use paths::Paths;
use reporter::{report, report_command};

pub struct Builder {
   paths: Rc<Paths>,
}

impl Builder {
   pub fn new(paths: Rc<Paths>) -> Self {
      Builder {
         paths: paths,
      }
   }

   pub fn build(&self) {
      self.configure();
      self.make();
      self.make_install();
   }

   fn configure(&self) {
      self.setup_conf_path();

      let prefix = format!("--prefix={}", self.paths.target_path.to_str().unwrap());
      let conf_path = format!("--conf-path={}", self.paths.nginx_conf_path.to_str().unwrap());
      let add_module = format!("--add-module={}", self.paths.module_dir_path.to_str().unwrap());

      let args = vec![
         "--with-http_ssl_module",
         prefix.as_slice(),
         conf_path.as_slice(),
         add_module.as_slice(),
      ];

      report_command("Configuring", "configure", &args);

      Command::new(&self.paths.configure_path).args(&args).current_dir(&self.paths.extract_path).status().unwrap_or_else(|e| {
         panic!("Configuring Nginx build failed: {}.", e)
      });
   }

   fn setup_conf_path(&self) {
      report("Creating", format!("{:?}", &self.paths.nginx_conf_prefix_path));

      create_dir_all(&self.paths.nginx_conf_prefix_path).unwrap_or_else(|e| {
         panic!("Cannot create nginx conf prefix path - {:?}: {}.", self.paths.nginx_conf_prefix_path, e)
      });

      report("Copying", format!("nginx.conf {:?}", &self.paths.nginx_conf_path));

      copy(&self.paths.nginx_conf_source_path, &self.paths.nginx_conf_path).unwrap_or_else(|e| {
         panic!("Cannot copy nginx.conf {:?} -> {:?}: {}.", self.paths.nginx_conf_source_path, self.paths.nginx_conf_path, e)
      });
   }

   fn make(&self) {
      report("Building", "make");

      Command::new("make").current_dir(&self.paths.extract_path).status().unwrap_or_else(|e| {
         panic!("Make failed: {}.", e)
      });
   }

   fn make_install(&self) {
      let args = vec!["install"];

      report_command("Installing", "make", &args);

      Command::new("make").args(&args).current_dir(&self.paths.extract_path).status().unwrap_or_else(|e| {
         panic!("Make install failed: {}.", e)
      });
   }
}
<|endoftext|>


<commit_before>extern crate sdl2;
extern crate minifb;
use minifb::*;
use utils;
pub mod cpu;
pub mod opcodes;
mod clock;
mod memory;
mod io;
mod cia;
mod vic;

pub const SCREEN_WIDTH:  usize = 384; // extend 20 pixels left and right for the borders
pub const SCREEN_HEIGHT: usize = 272; // extend 36 pixels top and down for the borders

// PAL clock frequency in Hz
const CLOCK_FREQ: f64 = 985248.0;

pub struct C64
{
    pub window: minifb::Window,
    memory: memory::MemShared,
    io:    io::IO,
    clock: clock::Clock,
    cpu: cpu::CPUShared,
    cia1: cia::CIAShared,
    cia2: cia::CIAShared,
    vic: vic::VICShared,

    boot_complete: bool,
    pub file_to_load: String,
    cycle_count: u32,
}

impl C64
{
    pub fn new() -> C64
    {
        let memory = memory::Memory::new_shared();
        let vic    = vic::VIC::new_shared();
        let cia1   = cia::CIA::new_shared(true);
        let cia2   = cia::CIA::new_shared(false);
        let cpu    = cpu::CPU::new_shared();

        let c64 = C64
        {
            window: Window::new("Rust64", SCREEN_WIDTH, SCREEN_HEIGHT, Scale::X1, Vsync::No).unwrap(),
            memory: memory.clone(), // shared system memory (RAM, ROM, IO registers)
            io:    io::IO::new(),
            clock: clock::Clock::new(CLOCK_FREQ),
            cpu: cpu.clone(),
            cia1: cia1.clone(),
            cia2: cia2.clone(),
            vic: vic.clone(),
            boot_complete: false,
            file_to_load: String::new(),
            cycle_count: 0,
        };

        // cyclic dependencies are not possible in Rust (yet?), so we have
        // to resort to setting references manually
        c64.cia1.borrow_mut().set_references(memory.clone(), cpu.clone(), vic.clone());
        c64.cia2.borrow_mut().set_references(memory.clone(), cpu.clone(), vic.clone());
        c64.vic.borrow_mut().set_references(memory.clone(), cpu.clone());
        c64.cpu.borrow_mut().set_references(memory.clone(), vic.clone(), cia1.clone(), cia2.clone());

        drop(memory);
        drop(cia1);
        drop(cia2);
        drop(vic);
        drop(cpu);

        c64
    }

    pub fn reset(&mut self)
    {
        self.memory.borrow_mut().reset();
        self.cpu.borrow_mut().reset();
        self.cia1.borrow_mut().reset();
        self.cia2.borrow_mut().reset();
    }

    fn load_prg(&mut self, filename: &str)
    {
        let prg_data = utils::open_file(filename, 0);
        let start_address: u16 = ((prg_data[1] as u16) << 8) | (prg_data[0] as u16);
        //let end_addr = start_address + (prg_data.len() as u16) - 2;
        println!("Loading {} to start location at ${:04x} ({})", filename, start_address, start_address);

        for i in 2..(prg_data.len())
        {
            self.memory.borrow_mut().write_byte(start_address + (i as u16) - 2, prg_data[i]);
        }

        //self.memory.borrow_mut().write_word_le(0x02b, start_address);
        //self.memory.borrow_mut().write_word_le(0x02d, end_addr);
        //self.memory.borrow_mut().write_word_le(0x02f, end_addr);
        //self.memory.borrow_mut().write_word_le(0x031, end_addr);
    }

    pub fn run(&mut self)
    {
        if !self.boot_complete
        {
            // $A480 is the BASIC warm start sequence - safe to assume we can load a cmdline program now
            self.boot_complete = self.cpu.borrow_mut().PC == 0xA480;

            if self.boot_complete
            {
                if self.file_to_load.len() > 0
                {
                    let prg_file = &self.file_to_load.to_owned()[..];
                    self.load_prg(prg_file);
                }
            }
        }

        if self.clock.tick() {
            let mut should_trigger_vblank = false;

            self.vic.borrow_mut().update(self.cycle_count, &mut should_trigger_vblank);

            // TODO: update sid *HERE* when it's done
            self.cia1.borrow_mut().process_irq();
            self.cia2.borrow_mut().process_irq();
            self.cia1.borrow_mut().update();
            self.cia2.borrow_mut().update();

            self.cpu.borrow_mut().update();

            if should_trigger_vblank
            {
                self.window.update(&self.vic.borrow_mut().window_buffer);
                self.io.update(&self.window, &mut self.cia1);
                self.cia1.borrow_mut().count_tod();
                self.cia2.borrow_mut().count_tod();

                if self.io.check_restore_key(&self.window)
                {
                    self.cpu.borrow_mut().trigger_nmi();
                }
            }

            self.cycle_count += 1;
        }
    }
}
<commit_msg>changed prg loading syntax slightly (easier for fast debugging)<commit_after>extern crate sdl2;
extern crate minifb;
use minifb::*;
use utils;
pub mod cpu;
pub mod opcodes;
mod clock;
mod memory;
mod io;
mod cia;
mod vic;

pub const SCREEN_WIDTH:  usize = 384; // extend 20 pixels left and right for the borders
pub const SCREEN_HEIGHT: usize = 272; // extend 36 pixels top and down for the borders

// PAL clock frequency in Hz
const CLOCK_FREQ: f64 = 985248.0;

pub struct C64
{
    pub window: minifb::Window,
    memory: memory::MemShared,
    io:    io::IO,
    clock: clock::Clock,
    cpu: cpu::CPUShared,
    cia1: cia::CIAShared,
    cia2: cia::CIAShared,
    vic: vic::VICShared,

    boot_complete: bool,
    pub file_to_load: String,
    cycle_count: u32,
}

impl C64
{
    pub fn new() -> C64
    {
        let memory = memory::Memory::new_shared();
        let vic    = vic::VIC::new_shared();
        let cia1   = cia::CIA::new_shared(true);
        let cia2   = cia::CIA::new_shared(false);
        let cpu    = cpu::CPU::new_shared();

        let c64 = C64
        {
            window: Window::new("Rust64", SCREEN_WIDTH, SCREEN_HEIGHT, Scale::X1, Vsync::No).unwrap(),
            memory: memory.clone(), // shared system memory (RAM, ROM, IO registers)
            io:    io::IO::new(),
            clock: clock::Clock::new(CLOCK_FREQ),
            cpu: cpu.clone(),
            cia1: cia1.clone(),
            cia2: cia2.clone(),
            vic: vic.clone(),
            boot_complete: false,
            file_to_load: String::new(),
            cycle_count: 0,
        };

        // cyclic dependencies are not possible in Rust (yet?), so we have
        // to resort to setting references manually
        c64.cia1.borrow_mut().set_references(memory.clone(), cpu.clone(), vic.clone());
        c64.cia2.borrow_mut().set_references(memory.clone(), cpu.clone(), vic.clone());
        c64.vic.borrow_mut().set_references(memory.clone(), cpu.clone());
        c64.cpu.borrow_mut().set_references(memory.clone(), vic.clone(), cia1.clone(), cia2.clone());

        drop(memory);
        drop(cia1);
        drop(cia2);
        drop(vic);
        drop(cpu);

        c64
    }

    pub fn reset(&mut self)
    {
        self.memory.borrow_mut().reset();
        self.cpu.borrow_mut().reset();
        self.cia1.borrow_mut().reset();
        self.cia2.borrow_mut().reset();
    }

    fn load_prg(&mut self, filename: &str)
    {
        let prg_data = utils::open_file(filename, 0);
        let start_address: u16 = ((prg_data[1] as u16) << 8) | (prg_data[0] as u16);
        //let end_addr = start_address + (prg_data.len() as u16) - 2;
        println!("Loading {} to start location at ${:04x} ({})", filename, start_address, start_address);

        for i in 2..(prg_data.len())
        {
            self.memory.borrow_mut().write_byte(start_address + (i as u16) - 2, prg_data[i]);
        }

        //self.memory.borrow_mut().write_word_le(0x02b, start_address);
        //self.memory.borrow_mut().write_word_le(0x02d, end_addr);
        //self.memory.borrow_mut().write_word_le(0x02f, end_addr);
        //self.memory.borrow_mut().write_word_le(0x031, end_addr);
    }

    pub fn run(&mut self)
    {
        if !self.boot_complete
        {
            // $A480 is the BASIC warm start sequence - safe to assume we can load a cmdline program now
            self.boot_complete = self.cpu.borrow_mut().PC == 0xA480;

            if self.boot_complete
            {
                let prg_file = &self.file_to_load.to_owned()[..];
                if prg_file.len() > 0
                {
                    self.load_prg(prg_file);
                }
            }
        }

        if self.clock.tick() {
            let mut should_trigger_vblank = false;

            self.vic.borrow_mut().update(self.cycle_count, &mut should_trigger_vblank);

            // TODO: update sid *HERE* when it's done
            self.cia1.borrow_mut().process_irq();
            self.cia2.borrow_mut().process_irq();
            self.cia1.borrow_mut().update();
            self.cia2.borrow_mut().update();

            self.cpu.borrow_mut().update();

            if should_trigger_vblank
            {
                self.window.update(&self.vic.borrow_mut().window_buffer);
                self.io.update(&self.window, &mut self.cia1);
                self.cia1.borrow_mut().count_tod();
                self.cia2.borrow_mut().count_tod();

                if self.io.check_restore_key(&self.window)
                {
                    self.cpu.borrow_mut().trigger_nmi();
                }
            }

            self.cycle_count += 1;
        }
    }
}
<|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/.
 *
 * Copyright 2017 - Dario Ostuni <dario.ostuni@gmail.com>
 *
 */

use common::PlayerInfo;
use std::default::Default;
use std::hash::Hasher;
use twox_hash::XxHash;

pub struct CHasher
{
    internal: XxHash,
}

impl Default for CHasher
{
    fn default() -> CHasher
    {
        CHasher::new()
    }
}

impl CHasher
{
    pub fn new() -> CHasher
    {
        CHasher { internal: XxHash::with_seed(0) }
    }

    pub fn update(&mut self, data: &[u8])
    {
        self.internal.write(data);
    }

    pub fn finalize(self) -> u64
    {
        self.internal.finish() >> 32
    }
}

pub fn player_hash(player_info: &PlayerInfo) -> u64
{
    let mut hasher = CHasher::new();
    hasher.update(player_info.name.as_str().as_bytes());
    hasher.finalize()
}
<commit_msg>Make the player id at most 31 bit<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/.
 *
 * Copyright 2017 - Dario Ostuni <dario.ostuni@gmail.com>
 *
 */

use common::PlayerInfo;
use std::default::Default;
use std::hash::Hasher;
use twox_hash::XxHash;

pub struct CHasher
{
    internal: XxHash,
}

impl Default for CHasher
{
    fn default() -> CHasher
    {
        CHasher::new()
    }
}

impl CHasher
{
    pub fn new() -> CHasher
    {
        CHasher { internal: XxHash::with_seed(0) }
    }

    pub fn update(&mut self, data: &[u8])
    {
        self.internal.write(data);
    }

    pub fn finalize(self) -> u64
    {
        self.internal.finish() >> 33
    }
}

pub fn player_hash(player_info: &PlayerInfo) -> u64
{
    let mut hasher = CHasher::new();
    hasher.update(player_info.name.as_str().as_bytes());
    hasher.finalize()
}
<|endoftext|>


<commit_before>use bit_vec;

use std::fmt;

use crypto::PublicKey;

pub use self::raw::{RawMessage, MessageWriter, MessageBuffer, Message, FromRaw,
                     HEADER_SIZE, TEST_NETWORK_ID, PROTOCOL_MAJOR_VERSION};
pub use self::error::Error;
pub use self::fields::{Field, SegmentField};
pub use self::protocol::*;

#[macro_use]
mod spec;
#[cfg(test)]
mod tests;
mod raw;
mod error;
mod fields;
mod protocol;

pub mod utils;

pub type BitVec = bit_vec::BitVec;

// TODO: implement common methods for enum types (hash, raw, from_raw, verify)
// TODO: use macro for implementing enums

pub type RawTransaction = RawMessage;

#[derive(Debug, Clone, PartialEq)]
pub enum Any {
    Connect(Connect),
    Status(Status),
    Block(Block),
    Consensus(ConsensusMessage),
    Request(RequestMessage),
    Transaction(RawTransaction),
}

#[derive(Clone, PartialEq)]
pub enum ConsensusMessage {
    Propose(Propose),
    Prevote(Prevote),
    Precommit(Precommit),
}

#[derive(Clone, PartialEq)]
pub enum RequestMessage {
    Propose(RequestPropose),
    Transactions(RequestTransactions),
    Prevotes(RequestPrevotes),
    Peers(RequestPeers),
    Block(RequestBlock),
}

impl RequestMessage {
    pub fn from(&self) -> &PublicKey {
        match *self {
            RequestMessage::Propose(ref msg) => msg.from(),
            RequestMessage::Transactions(ref msg) => msg.from(),
            RequestMessage::Prevotes(ref msg) => msg.from(),
            RequestMessage::Peers(ref msg) => msg.from(),
            RequestMessage::Block(ref msg) => msg.from(),
        }
    }

    pub fn to(&self) -> &PublicKey {
        match *self {
            RequestMessage::Propose(ref msg) => msg.to(),
            RequestMessage::Transactions(ref msg) => msg.to(),
            RequestMessage::Prevotes(ref msg) => msg.to(),
            RequestMessage::Peers(ref msg) => msg.to(),
            RequestMessage::Block(ref msg) => msg.to(),
        }
    }

    #[cfg_attr(feature="flame_profile", flame)]
    pub fn verify(&self, public_key: &PublicKey) -> bool {
        match *self {
            RequestMessage::Propose(ref msg) => msg.verify_signature(public_key),
            RequestMessage::Transactions(ref msg) => msg.verify_signature(public_key),
            RequestMessage::Prevotes(ref msg) => msg.verify_signature(public_key),
            RequestMessage::Peers(ref msg) => msg.verify_signature(public_key),
            RequestMessage::Block(ref msg) => msg.verify_signature(public_key),
        }
    }

    pub fn raw(&self) -> &RawMessage {
        match *self {
            RequestMessage::Propose(ref msg) => msg.raw(),
            RequestMessage::Transactions(ref msg) => msg.raw(),
            RequestMessage::Prevotes(ref msg) => msg.raw(),
            RequestMessage::Peers(ref msg) => msg.raw(),
            RequestMessage::Block(ref msg) => msg.raw(),
        }
    }
}

impl fmt::Debug for RequestMessage {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            RequestMessage::Propose(ref msg) => write!(fmt, "{:?}", msg),
            RequestMessage::Transactions(ref msg) => write!(fmt, "{:?}", msg),
            RequestMessage::Prevotes(ref msg) => write!(fmt, "{:?}", msg),
            RequestMessage::Peers(ref msg) => write!(fmt, "{:?}", msg),
            RequestMessage::Block(ref msg) => write!(fmt, "{:?}", msg),
        }
    }
}

impl ConsensusMessage {
    pub fn validator(&self) -> u32 {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.validator(),
            ConsensusMessage::Prevote(ref msg) => msg.validator(),
            ConsensusMessage::Precommit(ref msg) => msg.validator(),
        }
    }

    pub fn height(&self) -> u64 {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.height(),
            ConsensusMessage::Prevote(ref msg) => msg.height(),
            ConsensusMessage::Precommit(ref msg) => msg.height(),
        }
    }

    pub fn round(&self) -> u32 {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.round(),
            ConsensusMessage::Prevote(ref msg) => msg.round(),
            ConsensusMessage::Precommit(ref msg) => msg.round(),
        }
    }

    pub fn raw(&self) -> &RawMessage {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.raw(),
            ConsensusMessage::Prevote(ref msg) => msg.raw(),
            ConsensusMessage::Precommit(ref msg) => msg.raw(),
        }
    }

    pub fn verify(&self, public_key: &PublicKey) -> bool {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.verify_signature(public_key),
            ConsensusMessage::Prevote(ref msg) => msg.verify_signature(public_key),
            ConsensusMessage::Precommit(ref msg) => msg.verify_signature(public_key),
        }
    }
}

impl fmt::Debug for ConsensusMessage {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            ConsensusMessage::Propose(ref msg) => write!(fmt, "{:?}", msg),
            ConsensusMessage::Prevote(ref msg) => write!(fmt, "{:?}", msg),
            ConsensusMessage::Precommit(ref msg) => write!(fmt, "{:?}", msg),
        }
    }
}

impl Any {
    pub fn from_raw(raw: RawMessage) -> Result<Any, Error> {
        // TODO: check input message size
        let msg =
            if raw.service_id() == CONSENSUS {
                match raw.message_type() {
                    CONNECT_MESSAGE_ID => Any::Connect(Connect::from_raw(raw)?),
                    STATUS_MESSAGE_ID => Any::Status(Status::from_raw(raw)?),
                    BLOCK_MESSAGE_ID => Any::Block(Block::from_raw(raw)?),

                    PROPOSE_MESSAGE_ID => {
                        Any::Consensus(ConsensusMessage::Propose(Propose::from_raw(raw)?))
                    }
                    PREVOTE_MESSAGE_ID => {
                        Any::Consensus(ConsensusMessage::Prevote(Prevote::from_raw(raw)?))
                    }
                    PRECOMMIT_MESSAGE_ID => {
                        Any::Consensus(ConsensusMessage::Precommit(Precommit::from_raw(raw)?))
                    }

                    REQUEST_PROPOSE_MESSAGE_ID => {
                        Any::Request(RequestMessage::Propose(RequestPropose::from_raw(raw)?))
                    }
                    REQUEST_TRANSACTIONS_MESSAGE_ID => Any::Request(RequestMessage::Transactions(RequestTransactions::from_raw(raw)?)),
                    REQUEST_PREVOTES_MESSAGE_ID => {
                        Any::Request(RequestMessage::Prevotes(RequestPrevotes::from_raw(raw)?))
                    }
                    REQUEST_PEERS_MESSAGE_ID => {
                        Any::Request(RequestMessage::Peers(RequestPeers::from_raw(raw)?))
                    }
                    REQUEST_BLOCK_MESSAGE_ID => {
                        Any::Request(RequestMessage::Block(RequestBlock::from_raw(raw)?))
                    }
                    _ => panic!("Wrong consensus message type"),
                }
            } else {
                Any::Transaction(raw)
            };
        Ok(msg)
    }
}
<commit_msg>Remove panic in Any::from_raw<commit_after>use bit_vec;

use std::fmt;

use crypto::PublicKey;

pub use self::raw::{RawMessage, MessageWriter, MessageBuffer, Message, FromRaw,
                     HEADER_SIZE, TEST_NETWORK_ID, PROTOCOL_MAJOR_VERSION};
pub use self::error::Error;
pub use self::fields::{Field, SegmentField};
pub use self::protocol::*;

#[macro_use]
mod spec;
#[cfg(test)]
mod tests;
mod raw;
mod error;
mod fields;
mod protocol;

pub mod utils;

pub type BitVec = bit_vec::BitVec;

// TODO: implement common methods for enum types (hash, raw, from_raw, verify)
// TODO: use macro for implementing enums

pub type RawTransaction = RawMessage;

#[derive(Debug, Clone, PartialEq)]
pub enum Any {
    Connect(Connect),
    Status(Status),
    Block(Block),
    Consensus(ConsensusMessage),
    Request(RequestMessage),
    Transaction(RawTransaction),
}

#[derive(Clone, PartialEq)]
pub enum ConsensusMessage {
    Propose(Propose),
    Prevote(Prevote),
    Precommit(Precommit),
}

#[derive(Clone, PartialEq)]
pub enum RequestMessage {
    Propose(RequestPropose),
    Transactions(RequestTransactions),
    Prevotes(RequestPrevotes),
    Peers(RequestPeers),
    Block(RequestBlock),
}

impl RequestMessage {
    pub fn from(&self) -> &PublicKey {
        match *self {
            RequestMessage::Propose(ref msg) => msg.from(),
            RequestMessage::Transactions(ref msg) => msg.from(),
            RequestMessage::Prevotes(ref msg) => msg.from(),
            RequestMessage::Peers(ref msg) => msg.from(),
            RequestMessage::Block(ref msg) => msg.from(),
        }
    }

    pub fn to(&self) -> &PublicKey {
        match *self {
            RequestMessage::Propose(ref msg) => msg.to(),
            RequestMessage::Transactions(ref msg) => msg.to(),
            RequestMessage::Prevotes(ref msg) => msg.to(),
            RequestMessage::Peers(ref msg) => msg.to(),
            RequestMessage::Block(ref msg) => msg.to(),
        }
    }

    #[cfg_attr(feature="flame_profile", flame)]
    pub fn verify(&self, public_key: &PublicKey) -> bool {
        match *self {
            RequestMessage::Propose(ref msg) => msg.verify_signature(public_key),
            RequestMessage::Transactions(ref msg) => msg.verify_signature(public_key),
            RequestMessage::Prevotes(ref msg) => msg.verify_signature(public_key),
            RequestMessage::Peers(ref msg) => msg.verify_signature(public_key),
            RequestMessage::Block(ref msg) => msg.verify_signature(public_key),
        }
    }

    pub fn raw(&self) -> &RawMessage {
        match *self {
            RequestMessage::Propose(ref msg) => msg.raw(),
            RequestMessage::Transactions(ref msg) => msg.raw(),
            RequestMessage::Prevotes(ref msg) => msg.raw(),
            RequestMessage::Peers(ref msg) => msg.raw(),
            RequestMessage::Block(ref msg) => msg.raw(),
        }
    }
}

impl fmt::Debug for RequestMessage {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            RequestMessage::Propose(ref msg) => write!(fmt, "{:?}", msg),
            RequestMessage::Transactions(ref msg) => write!(fmt, "{:?}", msg),
            RequestMessage::Prevotes(ref msg) => write!(fmt, "{:?}", msg),
            RequestMessage::Peers(ref msg) => write!(fmt, "{:?}", msg),
            RequestMessage::Block(ref msg) => write!(fmt, "{:?}", msg),
        }
    }
}

impl ConsensusMessage {
    pub fn validator(&self) -> u32 {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.validator(),
            ConsensusMessage::Prevote(ref msg) => msg.validator(),
            ConsensusMessage::Precommit(ref msg) => msg.validator(),
        }
    }

    pub fn height(&self) -> u64 {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.height(),
            ConsensusMessage::Prevote(ref msg) => msg.height(),
            ConsensusMessage::Precommit(ref msg) => msg.height(),
        }
    }

    pub fn round(&self) -> u32 {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.round(),
            ConsensusMessage::Prevote(ref msg) => msg.round(),
            ConsensusMessage::Precommit(ref msg) => msg.round(),
        }
    }

    pub fn raw(&self) -> &RawMessage {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.raw(),
            ConsensusMessage::Prevote(ref msg) => msg.raw(),
            ConsensusMessage::Precommit(ref msg) => msg.raw(),
        }
    }

    pub fn verify(&self, public_key: &PublicKey) -> bool {
        match *self {
            ConsensusMessage::Propose(ref msg) => msg.verify_signature(public_key),
            ConsensusMessage::Prevote(ref msg) => msg.verify_signature(public_key),
            ConsensusMessage::Precommit(ref msg) => msg.verify_signature(public_key),
        }
    }
}

impl fmt::Debug for ConsensusMessage {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            ConsensusMessage::Propose(ref msg) => write!(fmt, "{:?}", msg),
            ConsensusMessage::Prevote(ref msg) => write!(fmt, "{:?}", msg),
            ConsensusMessage::Precommit(ref msg) => write!(fmt, "{:?}", msg),
        }
    }
}

impl Any {
    pub fn from_raw(raw: RawMessage) -> Result<Any, Error> {
        // TODO: check input message size
        let msg =
            if raw.service_id() == CONSENSUS {
                match raw.message_type() {
                    CONNECT_MESSAGE_ID => Any::Connect(Connect::from_raw(raw)?),
                    STATUS_MESSAGE_ID => Any::Status(Status::from_raw(raw)?),
                    BLOCK_MESSAGE_ID => Any::Block(Block::from_raw(raw)?),

                    PROPOSE_MESSAGE_ID => {
                        Any::Consensus(ConsensusMessage::Propose(Propose::from_raw(raw)?))
                    }
                    PREVOTE_MESSAGE_ID => {
                        Any::Consensus(ConsensusMessage::Prevote(Prevote::from_raw(raw)?))
                    }
                    PRECOMMIT_MESSAGE_ID => {
                        Any::Consensus(ConsensusMessage::Precommit(Precommit::from_raw(raw)?))
                    }

                    REQUEST_PROPOSE_MESSAGE_ID => {
                        Any::Request(RequestMessage::Propose(RequestPropose::from_raw(raw)?))
                    }
                    REQUEST_TRANSACTIONS_MESSAGE_ID => Any::Request(RequestMessage::Transactions(RequestTransactions::from_raw(raw)?)),
                    REQUEST_PREVOTES_MESSAGE_ID => {
                        Any::Request(RequestMessage::Prevotes(RequestPrevotes::from_raw(raw)?))
                    }
                    REQUEST_PEERS_MESSAGE_ID => {
                        Any::Request(RequestMessage::Peers(RequestPeers::from_raw(raw)?))
                    }
                    REQUEST_BLOCK_MESSAGE_ID => {
                        Any::Request(RequestMessage::Block(RequestBlock::from_raw(raw)?))
                    }
                    message_type => {
                        return Err(Error::IncorrectMessageType{ message_type });
                    }
                }
            } else {
                Any::Transaction(raw)
            };
        Ok(msg)
    }
}
<|endoftext|>