<commit_before>use std::ops::Deref;

use super::{Command, Number, Parameters, Position};
use crate::node::Value;
use crate::parser::{Error, Reader, Result};

/// A [data][1] attribute.
///
/// [1]: https://www.w3.org/TR/SVG/paths.html#PathData
#[derive(Clone, Default)]
pub struct Data(Vec<Command>);

struct Parser<'l> {
    reader: Reader<'l>,
}

impl Data {
    /// Create a data attribute.
    #[inline]
    pub fn new() -> Self {
        Default::default()
    }

    /// Parse a data attribute.
    #[inline]
    pub fn parse(content: &str) -> Result<Self> {
        Parser::new(content).process()
    }
}

macro_rules! implement {
    (@one #[$doc:meta] fn $method:ident($command:ident, $position:ident)) => (
        #[$doc]
        pub fn $method<T>(mut self, parameters: T) -> Self
        where
            T: Into<Parameters>,
        {
            self.0.push(Command::$command(Position::$position, parameters.into()));
            self
        }
    );
    (@one #[$doc:meta] fn $method:ident($command:ident)) => (
        #[$doc]
        pub fn $method(mut self) -> Self {
            self.0.push(Command::$command);
            self
        }
    );
    ($(#[$doc:meta] fn $method:ident($($argument:tt)*))*) => (
        impl Data {
            $(implement! { @one #[$doc] fn $method($($argument)*) })*
        }
    );
}

implement! {
    #[doc = "Add an absolute `Command::Move` command."]
    fn move_to(Move, Absolute)

    #[doc = "Add a relative `Command::Move` command."]
    fn move_by(Move, Relative)

    #[doc = "Add an absolute `Command::Line` command."]
    fn line_to(Line, Absolute)

    #[doc = "Add a relative `Command::Line` command."]
    fn line_by(Line, Relative)

    #[doc = "Add an absolute `Command::HorizontalLine` command."]
    fn horizontal_line_to(HorizontalLine, Absolute)

    #[doc = "Add a relative `Command::HorizontalLine` command."]
    fn horizontal_line_by(HorizontalLine, Relative)

    #[doc = "Add an absolute `Command::VerticalLine` command."]
    fn vertical_line_to(VerticalLine, Absolute)

    #[doc = "Add a relative `Command::VerticalLine` command."]
    fn vertical_line_by(VerticalLine, Relative)

    #[doc = "Add an absolute `Command::QuadraticCurve` command."]
    fn quadratic_curve_to(QuadraticCurve, Absolute)

    #[doc = "Add a relative `Command::QuadraticCurve` command."]
    fn quadratic_curve_by(QuadraticCurve, Relative)

    #[doc = "Add an absolute `Command::SmoothQuadraticCurve` command."]
    fn smooth_quadratic_curve_to(SmoothQuadraticCurve, Absolute)

    #[doc = "Add a relative `Command::SmoothQuadraticCurve` command."]
    fn smooth_quadratic_curve_by(SmoothQuadraticCurve, Relative)

    #[doc = "Add an absolute `Command::CubicCurve` command."]
    fn cubic_curve_to(CubicCurve, Absolute)

    #[doc = "Add a relative `Command::CubicCurve` command."]
    fn cubic_curve_by(CubicCurve, Relative)

    #[doc = "Add an absolute `Command::SmoothCubicCurve` command."]
    fn smooth_cubic_curve_to(SmoothCubicCurve, Absolute)

    #[doc = "Add a relative `Command::SmoothCubicCurve` command."]
    fn smooth_cubic_curve_by(SmoothCubicCurve, Relative)

    #[doc = "Add an absolute `Command::EllipticalArc` command."]
    fn elliptical_arc_to(EllipticalArc, Absolute)

    #[doc = "Add a relative `Command::EllipticalArc` command."]
    fn elliptical_arc_by(EllipticalArc, Relative)

    #[doc = "Add a `Command::Close` command."]
    fn close(Close)
}

impl Deref for Data {
    type Target = [Command];

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<Vec<Command>> for Data {
    #[inline]
    fn from(commands: Vec<Command>) -> Self {
        Data(commands)
    }
}

impl From<Data> for Vec<Command> {
    #[inline]
    fn from(Data(commands): Data) -> Self {
        commands
    }
}

impl From<Data> for Value {
    #[inline]
    fn from(Data(mut inner): Data) -> Self {
        inner
            .drain(..)
            .map(String::from)
            .collect::<Vec<_>>()
            .join(" ")
            .into()
    }
}

macro_rules! raise(
    ($parser:expr, $($argument:tt)*) => (
        return Err(Error::new($parser.reader.position(), format!($($argument)*)));
    );
);

impl<'l> Parser<'l> {
    #[inline]
    fn new(content: &'l str) -> Self {
        Parser {
            reader: Reader::new(content),
        }
    }

    fn process(&mut self) -> Result<Data> {
        let mut commands = Vec::new();
        loop {
            self.reader.consume_whitespace();
            match self.read_command()? {
                Some(command) => commands.push(command),
                _ => break,
            }
        }
        Ok(Data(commands))
    }

    fn read_command(&mut self) -> Result<Option<Command>> {
        use super::Command::*;
        use super::Position::*;

        let name = match self.reader.next() {
            Some(name) => match name {
                'A'..='Z' | 'a'..='z' => name,
                _ => raise!(self, "expected a path command"),
            },
            _ => return Ok(None),
        };
        self.reader.consume_whitespace();
        let parameters = self.read_parameters()?.into();
        Ok(Some(match name {
            'M' => Move(Absolute, parameters),
            'm' => Move(Relative, parameters),

            'L' => Line(Absolute, parameters),
            'l' => Line(Relative, parameters),

            'H' => HorizontalLine(Absolute, parameters),
            'h' => HorizontalLine(Relative, parameters),

            'V' => VerticalLine(Absolute, parameters),
            'v' => VerticalLine(Relative, parameters),

            'Q' => QuadraticCurve(Absolute, parameters),
            'q' => QuadraticCurve(Relative, parameters),

            'T' => SmoothQuadraticCurve(Absolute, parameters),
            't' => SmoothQuadraticCurve(Relative, parameters),

            'C' => CubicCurve(Absolute, parameters),
            'c' => CubicCurve(Relative, parameters),

            'S' => SmoothCubicCurve(Absolute, parameters),
            's' => SmoothCubicCurve(Relative, parameters),

            'A' => EllipticalArc(Absolute, parameters),
            'a' => EllipticalArc(Relative, parameters),

            'Z' | 'z' => Close,

            _ => raise!(self, "found an unknown path command '{}'", name),
        }))
    }

    fn read_parameters(&mut self) -> Result<Vec<Number>> {
        let mut parameters = Vec::new();

        while let Some(number) = self.read_number()? {
            parameters.push(number);
            self.reader.consume_whitespace();
            self.reader.consume_char(',');
        }
        Ok(parameters)
    }

    pub fn read_number(&mut self) -> Result<Option<Number>> {
        self.reader.consume_whitespace();
        let number = self
            .reader
            .capture(|reader| reader.consume_number())
            .and_then(|number| Some(String::from(number)));
        match number {
            Some(number) => match (&number).parse() {
                Ok(number) => Ok(Some(number)),
                _ => raise!(self, "failed to parse a number '{}'", number),
            },
            _ => Ok(None),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::Command::*;
    use super::super::Position::*;
    use super::{Data, Parser};
    use crate::node::Value;

    #[test]
    fn data_into_value() {
        let data = Data::new()
            .line_to((1, 2))
            .cubic_curve_by((1, 2.5, 3, 4, 5, 6))
            .close();

        assert_eq!(Value::from(data).to_string(), "L1,2 c1,2.5,3,4,5,6 z");
    }

    #[test]
    fn data_parse() {
        let data = Data::parse("M1,2 l3,4").unwrap();

        assert_eq!(data.len(), 2);
        match data[0] {
            Move(Absolute, ref parameters) => assert_eq!(&parameters[..], &[1.0, 2.0]),
            _ => unreachable!(),
        }
        match data[1] {
            Line(Relative, ref parameters) => assert_eq!(&parameters[..], &[3.0, 4.0]),
            _ => unreachable!(),
        }
    }

    #[test]
    fn parser_read_command() {
        macro_rules! run(
            ($content:expr) => ({
                let mut parser = Parser::new($content);
                parser.read_command().unwrap().unwrap()
            });
        );

        macro_rules! test(
            ($content:expr, $command:ident, $position:ident, $parameters:expr) => (
                match run!($content) {
                    $command($position, parameters) => assert_eq!(&parameters[..], $parameters),
                    _ => unreachable!(),
                }
            );
            ($content:expr, $command:ident) => (
                match run!($content) {
                    $command => {}
                    _ => unreachable!(),
                }
            );
        );

        test!("M4,2", Move, Absolute, &[4.0, 2.0]);
        test!("m4,\n2", Move, Relative, &[4.0, 2.0]);

        test!("L7, 8  9", Line, Absolute, &[7.0, 8.0, 9.0]);
        test!("l 7,8 \n9", Line, Relative, &[7.0, 8.0, 9.0]);

        test!("H\t6,9", HorizontalLine, Absolute, &[6.0, 9.0]);
        test!("h6,  \t9", HorizontalLine, Relative, &[6.0, 9.0]);

        test!("V2.1,-3", VerticalLine, Absolute, &[2.1, -3.0]);
        test!("v\n2.1 -3", VerticalLine, Relative, &[2.1, -3.0]);

        test!("Q90.5 0", QuadraticCurve, Absolute, &[90.5, 0.0]);
        test!("q90.5\n, 0", QuadraticCurve, Relative, &[90.5, 0.0]);

        test!("T-1", SmoothQuadraticCurve, Absolute, &[-1.0]);
        test!("t -1", SmoothQuadraticCurve, Relative, &[-1.0]);

        test!("C0,1 0,2", CubicCurve, Absolute, &[0.0, 1.0, 0.0, 2.0]);
        test!("c0 ,1 0,  2", CubicCurve, Relative, &[0.0, 1.0, 0.0, 2.0]);

        test!("S42,0", SmoothCubicCurve, Absolute, &[42.0, 0.0]);
        test!("s \t 42,0", SmoothCubicCurve, Relative, &[42.0, 0.0]);

        test!("A2.6,0 -7", EllipticalArc, Absolute, &[2.6, 0.0, -7.0]);
        test!("a 2.6 ,0 -7", EllipticalArc, Relative, &[2.6, 0.0, -7.0]);

        test!("Z", Close);
        test!("z", Close);
    }

    #[test]
    fn parser_read_parameters() {
        macro_rules! test(
            ($content:expr, $parameters:expr) => ({
                let mut parser = Parser::new($content);
                let parameters = parser.read_parameters().unwrap();
                assert_eq!(&parameters[..], $parameters);
            });
        );

        test!("1,2 3,4 5 6.7", &[1.0, 2.0, 3.0, 4.0, 5.0, 6.7]);
        test!("4-3.1.3e2.4", &[4.0, -3.1, 0.3e2, 0.4]);
    }

    #[test]
    fn parser_read_number() {
        macro_rules! test(
            ($content:expr, $value:expr) => ({
                let mut parser = Parser::new($content);
                assert_eq!(parser.read_number().unwrap().unwrap(), $value);
            });
        );

        test!("0.30000000000000004", 0.3);
        test!("1e-4", 1e-4);
        test!("-1E2", -1e2);
        test!("-0.00100E-002", -1e-5);
    }
}
<commit_msg>Add debug derive on Data<commit_after>use std::ops::Deref;

use super::{Command, Number, Parameters, Position};
use crate::node::Value;
use crate::parser::{Error, Reader, Result};

/// A [data][1] attribute.
///
/// [1]: https://www.w3.org/TR/SVG/paths.html#PathData
#[derive(Clone, Debug, Default)]
pub struct Data(Vec<Command>);

struct Parser<'l> {
    reader: Reader<'l>,
}

impl Data {
    /// Create a data attribute.
    #[inline]
    pub fn new() -> Self {
        Default::default()
    }

    /// Parse a data attribute.
    #[inline]
    pub fn parse(content: &str) -> Result<Self> {
        Parser::new(content).process()
    }
}

macro_rules! implement {
    (@one #[$doc:meta] fn $method:ident($command:ident, $position:ident)) => (
        #[$doc]
        pub fn $method<T>(mut self, parameters: T) -> Self
        where
            T: Into<Parameters>,
        {
            self.0.push(Command::$command(Position::$position, parameters.into()));
            self
        }
    );
    (@one #[$doc:meta] fn $method:ident($command:ident)) => (
        #[$doc]
        pub fn $method(mut self) -> Self {
            self.0.push(Command::$command);
            self
        }
    );
    ($(#[$doc:meta] fn $method:ident($($argument:tt)*))*) => (
        impl Data {
            $(implement! { @one #[$doc] fn $method($($argument)*) })*
        }
    );
}

implement! {
    #[doc = "Add an absolute `Command::Move` command."]
    fn move_to(Move, Absolute)

    #[doc = "Add a relative `Command::Move` command."]
    fn move_by(Move, Relative)

    #[doc = "Add an absolute `Command::Line` command."]
    fn line_to(Line, Absolute)

    #[doc = "Add a relative `Command::Line` command."]
    fn line_by(Line, Relative)

    #[doc = "Add an absolute `Command::HorizontalLine` command."]
    fn horizontal_line_to(HorizontalLine, Absolute)

    #[doc = "Add a relative `Command::HorizontalLine` command."]
    fn horizontal_line_by(HorizontalLine, Relative)

    #[doc = "Add an absolute `Command::VerticalLine` command."]
    fn vertical_line_to(VerticalLine, Absolute)

    #[doc = "Add a relative `Command::VerticalLine` command."]
    fn vertical_line_by(VerticalLine, Relative)

    #[doc = "Add an absolute `Command::QuadraticCurve` command."]
    fn quadratic_curve_to(QuadraticCurve, Absolute)

    #[doc = "Add a relative `Command::QuadraticCurve` command."]
    fn quadratic_curve_by(QuadraticCurve, Relative)

    #[doc = "Add an absolute `Command::SmoothQuadraticCurve` command."]
    fn smooth_quadratic_curve_to(SmoothQuadraticCurve, Absolute)

    #[doc = "Add a relative `Command::SmoothQuadraticCurve` command."]
    fn smooth_quadratic_curve_by(SmoothQuadraticCurve, Relative)

    #[doc = "Add an absolute `Command::CubicCurve` command."]
    fn cubic_curve_to(CubicCurve, Absolute)

    #[doc = "Add a relative `Command::CubicCurve` command."]
    fn cubic_curve_by(CubicCurve, Relative)

    #[doc = "Add an absolute `Command::SmoothCubicCurve` command."]
    fn smooth_cubic_curve_to(SmoothCubicCurve, Absolute)

    #[doc = "Add a relative `Command::SmoothCubicCurve` command."]
    fn smooth_cubic_curve_by(SmoothCubicCurve, Relative)

    #[doc = "Add an absolute `Command::EllipticalArc` command."]
    fn elliptical_arc_to(EllipticalArc, Absolute)

    #[doc = "Add a relative `Command::EllipticalArc` command."]
    fn elliptical_arc_by(EllipticalArc, Relative)

    #[doc = "Add a `Command::Close` command."]
    fn close(Close)
}

impl Deref for Data {
    type Target = [Command];

    #[inline]
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl From<Vec<Command>> for Data {
    #[inline]
    fn from(commands: Vec<Command>) -> Self {
        Data(commands)
    }
}

impl From<Data> for Vec<Command> {
    #[inline]
    fn from(Data(commands): Data) -> Self {
        commands
    }
}

impl From<Data> for Value {
    #[inline]
    fn from(Data(mut inner): Data) -> Self {
        inner
            .drain(..)
            .map(String::from)
            .collect::<Vec<_>>()
            .join(" ")
            .into()
    }
}

macro_rules! raise(
    ($parser:expr, $($argument:tt)*) => (
        return Err(Error::new($parser.reader.position(), format!($($argument)*)));
    );
);

impl<'l> Parser<'l> {
    #[inline]
    fn new(content: &'l str) -> Self {
        Parser {
            reader: Reader::new(content),
        }
    }

    fn process(&mut self) -> Result<Data> {
        let mut commands = Vec::new();
        loop {
            self.reader.consume_whitespace();
            match self.read_command()? {
                Some(command) => commands.push(command),
                _ => break,
            }
        }
        Ok(Data(commands))
    }

    fn read_command(&mut self) -> Result<Option<Command>> {
        use super::Command::*;
        use super::Position::*;

        let name = match self.reader.next() {
            Some(name) => match name {
                'A'..='Z' | 'a'..='z' => name,
                _ => raise!(self, "expected a path command"),
            },
            _ => return Ok(None),
        };
        self.reader.consume_whitespace();
        let parameters = self.read_parameters()?.into();
        Ok(Some(match name {
            'M' => Move(Absolute, parameters),
            'm' => Move(Relative, parameters),

            'L' => Line(Absolute, parameters),
            'l' => Line(Relative, parameters),

            'H' => HorizontalLine(Absolute, parameters),
            'h' => HorizontalLine(Relative, parameters),

            'V' => VerticalLine(Absolute, parameters),
            'v' => VerticalLine(Relative, parameters),

            'Q' => QuadraticCurve(Absolute, parameters),
            'q' => QuadraticCurve(Relative, parameters),

            'T' => SmoothQuadraticCurve(Absolute, parameters),
            't' => SmoothQuadraticCurve(Relative, parameters),

            'C' => CubicCurve(Absolute, parameters),
            'c' => CubicCurve(Relative, parameters),

            'S' => SmoothCubicCurve(Absolute, parameters),
            's' => SmoothCubicCurve(Relative, parameters),

            'A' => EllipticalArc(Absolute, parameters),
            'a' => EllipticalArc(Relative, parameters),

            'Z' | 'z' => Close,

            _ => raise!(self, "found an unknown path command '{}'", name),
        }))
    }

    fn read_parameters(&mut self) -> Result<Vec<Number>> {
        let mut parameters = Vec::new();

        while let Some(number) = self.read_number()? {
            parameters.push(number);
            self.reader.consume_whitespace();
            self.reader.consume_char(',');
        }
        Ok(parameters)
    }

    pub fn read_number(&mut self) -> Result<Option<Number>> {
        self.reader.consume_whitespace();
        let number = self
            .reader
            .capture(|reader| reader.consume_number())
            .and_then(|number| Some(String::from(number)));
        match number {
            Some(number) => match (&number).parse() {
                Ok(number) => Ok(Some(number)),
                _ => raise!(self, "failed to parse a number '{}'", number),
            },
            _ => Ok(None),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::super::Command::*;
    use super::super::Position::*;
    use super::{Data, Parser};
    use crate::node::Value;

    #[test]
    fn data_into_value() {
        let data = Data::new()
            .line_to((1, 2))
            .cubic_curve_by((1, 2.5, 3, 4, 5, 6))
            .close();

        assert_eq!(Value::from(data).to_string(), "L1,2 c1,2.5,3,4,5,6 z");
    }

    #[test]
    fn data_parse() {
        let data = Data::parse("M1,2 l3,4").unwrap();

        assert_eq!(data.len(), 2);
        match data[0] {
            Move(Absolute, ref parameters) => assert_eq!(&parameters[..], &[1.0, 2.0]),
            _ => unreachable!(),
        }
        match data[1] {
            Line(Relative, ref parameters) => assert_eq!(&parameters[..], &[3.0, 4.0]),
            _ => unreachable!(),
        }
    }

    #[test]
    fn parser_read_command() {
        macro_rules! run(
            ($content:expr) => ({
                let mut parser = Parser::new($content);
                parser.read_command().unwrap().unwrap()
            });
        );

        macro_rules! test(
            ($content:expr, $command:ident, $position:ident, $parameters:expr) => (
                match run!($content) {
                    $command($position, parameters) => assert_eq!(&parameters[..], $parameters),
                    _ => unreachable!(),
                }
            );
            ($content:expr, $command:ident) => (
                match run!($content) {
                    $command => {}
                    _ => unreachable!(),
                }
            );
        );

        test!("M4,2", Move, Absolute, &[4.0, 2.0]);
        test!("m4,\n2", Move, Relative, &[4.0, 2.0]);

        test!("L7, 8  9", Line, Absolute, &[7.0, 8.0, 9.0]);
        test!("l 7,8 \n9", Line, Relative, &[7.0, 8.0, 9.0]);

        test!("H\t6,9", HorizontalLine, Absolute, &[6.0, 9.0]);
        test!("h6,  \t9", HorizontalLine, Relative, &[6.0, 9.0]);

        test!("V2.1,-3", VerticalLine, Absolute, &[2.1, -3.0]);
        test!("v\n2.1 -3", VerticalLine, Relative, &[2.1, -3.0]);

        test!("Q90.5 0", QuadraticCurve, Absolute, &[90.5, 0.0]);
        test!("q90.5\n, 0", QuadraticCurve, Relative, &[90.5, 0.0]);

        test!("T-1", SmoothQuadraticCurve, Absolute, &[-1.0]);
        test!("t -1", SmoothQuadraticCurve, Relative, &[-1.0]);

        test!("C0,1 0,2", CubicCurve, Absolute, &[0.0, 1.0, 0.0, 2.0]);
        test!("c0 ,1 0,  2", CubicCurve, Relative, &[0.0, 1.0, 0.0, 2.0]);

        test!("S42,0", SmoothCubicCurve, Absolute, &[42.0, 0.0]);
        test!("s \t 42,0", SmoothCubicCurve, Relative, &[42.0, 0.0]);

        test!("A2.6,0 -7", EllipticalArc, Absolute, &[2.6, 0.0, -7.0]);
        test!("a 2.6 ,0 -7", EllipticalArc, Relative, &[2.6, 0.0, -7.0]);

        test!("Z", Close);
        test!("z", Close);
    }

    #[test]
    fn parser_read_parameters() {
        macro_rules! test(
            ($content:expr, $parameters:expr) => ({
                let mut parser = Parser::new($content);
                let parameters = parser.read_parameters().unwrap();
                assert_eq!(&parameters[..], $parameters);
            });
        );

        test!("1,2 3,4 5 6.7", &[1.0, 2.0, 3.0, 4.0, 5.0, 6.7]);
        test!("4-3.1.3e2.4", &[4.0, -3.1, 0.3e2, 0.4]);
    }

    #[test]
    fn parser_read_number() {
        macro_rules! test(
            ($content:expr, $value:expr) => ({
                let mut parser = Parser::new($content);
                assert_eq!(parser.read_number().unwrap().unwrap(), $value);
            });
        );

        test!("0.30000000000000004", 0.3);
        test!("1e-4", 1e-4);
        test!("-1E2", -1e2);
        test!("-0.00100E-002", -1e-5);
    }
}
<|endoftext|>


<commit_before>use std::{collections::BTreeMap, fmt, panic};

use quickcheck::{Arbitrary, Gen, RngCore};
use rand::distributions::{Distribution, Gamma};
use rand::{rngs::StdRng, Rng, SeedableRng};

use pagecache::MAX_SPACE_AMPLIFICATION;
use sled::*;

#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct Key(pub Vec<u8>);

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

struct SledGen {
    r: StdRng,
    size: usize,
}

impl Gen for SledGen {
    fn size(&self) -> usize {
        self.size
    }
}

impl RngCore for SledGen {
    fn next_u32(&mut self) -> u32 {
        self.r.gen::<u32>()
    }

    fn next_u64(&mut self) -> u64 {
        self.r.gen::<u64>()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.r.fill_bytes(dest)
    }

    fn try_fill_bytes(
        &mut self,
        dest: &mut [u8],
    ) -> std::result::Result<(), rand::Error> {
        self.r.try_fill_bytes(dest)
    }
}

pub fn fuzz_then_shrink(buf: &[u8]) {
    let use_compression = buf.get(0).unwrap_or(&0) % 2 == 0;

    let ops: Vec<Op> = buf
        .chunks(2)
        .map(|chunk| {
            let mut seed = [0u8; 32];
            seed[0..chunk.len()].copy_from_slice(chunk);
            let rng: StdRng = SeedableRng::from_seed(seed);
            let mut sled_rng = SledGen { r: rng, size: 2 };

            Op::arbitrary(&mut sled_rng)
        })
        .collect();

    match panic::catch_unwind(move || {
        prop_tree_matches_btreemap(ops, 0, 100, false, use_compression)
    }) {
        Ok(_) => {}
        Err(_e) => panic!("TODO"),
    }
}

impl Arbitrary for Key {
    fn arbitrary<G: Gen>(g: &mut G) -> Key {
        if g.gen::<bool>() {
            let gs = g.size();
            let gamma = Gamma::new(0.3, gs as f64);
            let v = gamma.sample(&mut rand::thread_rng());
            let len = if v > 30000.0 {
                30000
            } else if v < 1. && v > 0.0001 {
                1
            } else {
                v as usize
            };

            let space = g.gen_range(0, gs) + 1;

            let inner = (0..len).map(|_| g.gen_range(0, space) as u8).collect();

            Key(inner)
        } else {
            let len = g.gen_range(0, 2);
            let mut inner = vec![];

            for _ in 0..len {
                inner.push(g.gen::<u8>());
            }

            Key(inner)
        }
    }

    fn shrink(&self) -> Box<Iterator<Item = Key>> {
        // we only want to shrink on length, not byte values
        Box::new(
            self.0
                .len()
                .shrink()
                .zip(std::iter::repeat(self.0.clone()))
                .map(|(len, underlying)| Key(underlying[..len].to_vec())),
        )
    }
}

#[derive(Debug, Clone)]
pub enum Op {
    Set(Key, u8),
    Merge(Key, u8),
    Get(Key),
    GetLt(Key),
    GetGt(Key),
    Del(Key),
    Cas(Key, u8, u8),
    Scan(Key, usize),
    Restart,
}

use self::Op::*;

impl Op {
    pub fn is_restart(&self) -> bool {
        if let Restart = self {
            true
        } else {
            false
        }
    }
}

impl Arbitrary for Op {
    fn arbitrary<G: Gen>(g: &mut G) -> Op {
        if g.gen_bool(1. / 10.) {
            return Restart;
        }

        let choice = g.gen_range(0, 8);

        match choice {
            0 => Set(Key::arbitrary(g), g.gen::<u8>()),
            1 => Merge(Key::arbitrary(g), g.gen::<u8>()),
            2 => Get(Key::arbitrary(g)),
            3 => GetLt(Key::arbitrary(g)),
            4 => GetGt(Key::arbitrary(g)),
            5 => Del(Key::arbitrary(g)),
            6 => Cas(Key::arbitrary(g), g.gen::<u8>(), g.gen::<u8>()),
            7 => Scan(Key::arbitrary(g), g.gen_range(0, 40)),
            _ => panic!("impossible choice"),
        }
    }

    fn shrink(&self) -> Box<Iterator<Item = Op>> {
        match *self {
            Set(ref k, v) => Box::new(k.shrink().map(move |sk| Set(sk, v))),
            Merge(ref k, v) => Box::new(k.shrink().map(move |k| Merge(k, v))),
            Get(ref k) => Box::new(k.shrink().map(Get)),
            GetLt(ref k) => Box::new(k.shrink().map(GetLt)),
            GetGt(ref k) => Box::new(k.shrink().map(GetGt)),
            Cas(ref k, old, new) => {
                Box::new(k.shrink().map(move |k| Cas(k, old, new)))
            }
            Scan(ref k, len) => Box::new(k.shrink().map(move |k| Scan(k, len))),
            Del(ref k) => Box::new(k.shrink().map(Del)),
            Restart => Box::new(vec![].into_iter()),
        }
    }
}

fn bytes_to_u16(v: &[u8]) -> u16 {
    assert_eq!(v.len(), 2);
    (u16::from(v[0]) << 8) + u16::from(v[1])
}

fn u16_to_bytes(u: u16) -> Vec<u8> {
    let ret = vec![(u >> 8) as u8, u as u8];
    ret
}

// just adds up values as if they were u16's
fn test_merge_operator(
    _k: &[u8],
    old: Option<&[u8]>,
    to_merge: &[u8],
) -> Option<Vec<u8>> {
    let base = old.unwrap_or(&[0, 0]);
    let base_n = bytes_to_u16(base);
    let new_n = base_n + u16::from(to_merge[0]);
    let ret = u16_to_bytes(new_n);
    Some(ret)
}

pub fn prop_tree_matches_btreemap(
    ops: Vec<Op>,
    blink_node_exponent: u8,
    snapshot_after: u8,
    flusher: bool,
    use_compression: bool,
) -> bool {
    super::setup_logger();

    use self::*;
    let config = ConfigBuilder::new()
        .async_io(false)
        .temporary(true)
        .use_compression(use_compression)
        .snapshot_after_ops(u64::from(snapshot_after) + 1)
        .flush_every_ms(if flusher { Some(1) } else { None })
        .io_buf_size(10000)
        .blink_node_split_size(1 << std::cmp::min(blink_node_exponent, 20))
        .cache_capacity(40)
        .cache_bits(0)
        .merge_operator(test_merge_operator)
        .idgen_persist_interval(1)
        .build();

    let mut tree = sled::Db::start(config.clone()).unwrap();
    let mut reference: BTreeMap<Key, u16> = BTreeMap::new();

    for op in ops.into_iter() {
        match op {
            Set(k, v) => {
                let old_actual = tree.insert(&k.0, vec![0, v]).unwrap();
                let old_reference = reference.insert(k.clone(), u16::from(v));
                assert_eq!(
                    old_actual.map(|v| bytes_to_u16(&*v)),
                    old_reference
                );
            }
            Merge(k, v) => {
                tree.merge(&k.0, vec![v]).unwrap();
                let entry = reference.entry(k).or_insert(0u16);
                *entry += u16::from(v);
            }
            Get(k) => {
                let res1 = tree.get(&*k.0).unwrap().map(|v| bytes_to_u16(&*v));
                let res2 = reference.get(&k).cloned();
                assert_eq!(res1, res2);
            }
            GetLt(k) => {
                let res1 = tree.get_lt(&*k.0).unwrap().map(|v| v.0);
                let res2 = reference
                    .iter()
                    .rev()
                    .filter(|(key, _)| **key < k)
                    .nth(0)
                    .map(|(k, _v)| IVec::from(&*k.0));
                assert_eq!(
                    res1, res2,
                    "get_lt({:?}) should have returned {:?} \
                     but it returned {:?} instead. \
                     \n Db: {:?}",
                    k, res2, res1, tree
                );
            }
            GetGt(k) => {
                let res1 = tree.get_gt(&*k.0).unwrap().map(|v| v.0);
                let res2 = reference
                    .iter()
                    .filter(|(key, _)| **key > k)
                    .nth(0)
                    .map(|(k, _v)| IVec::from(&*k.0));
                assert_eq!(
                    res1, res2,
                    "get_gt({:?}) expected {:?} in tree {:?}",
                    k, res2, tree
                );
            }
            Del(k) => {
                tree.remove(&*k.0).unwrap();
                reference.remove(&k);
            }
            Cas(k, old, new) => {
                let tree_old = tree.get(&*k.0).unwrap();
                if let Some(old_tree) = tree_old {
                    if old_tree == *vec![0, old] {
                        tree.insert(&k.0, vec![0, new]).unwrap();
                    }
                }

                let ref_old = reference.get(&k).cloned();
                if ref_old == Some(u16::from(old)) {
                    reference.insert(k, u16::from(new));
                }
            }
            Scan(k, len) => {
                let mut tree_iter =
                    tree.range(&*k.0..).take(len).map(|res| res.unwrap());
                let ref_iter = reference
                    .iter()
                    .filter(|&(ref rk, _rv)| **rk >= k)
                    .take(len)
                    .map(|(ref rk, ref rv)| (rk.0.clone(), **rv));

                for r in ref_iter {
                    let tree_next = tree_iter.next().unwrap();
                    let lhs = (tree_next.0, &*tree_next.1);
                    let rhs = (r.0.clone(), &*u16_to_bytes(r.1));
                    assert_eq!(
                        (lhs.0.as_ref(), lhs.1),
                        (rhs.0.as_ref(), rhs.1),
                        "expected {:?} while iterating from {:?} on tree: {:?}",
                        rhs,
                        k,
                        tree
                    );
                }
            }
            Restart => {
                drop(tree);
                tree = sled::Db::start(config.clone()).unwrap();
            }
        }
    }

    let space_amplification = tree
        .space_amplification()
        .expect("should be able to read files and pages");

    assert!(
        space_amplification < MAX_SPACE_AMPLIFICATION,
        "space amplification was measured to be {}, \
         which is higher than the maximum of {}",
        space_amplification,
        MAX_SPACE_AMPLIFICATION
    );

    true
}

#[test]
fn test_fuzz_test() {
    let seed = [0; 32];
    fuzz_then_shrink(&seed);
    let seed = [0; 31];
    fuzz_then_shrink(&seed);
    let seed = [0; 33];
    fuzz_then_shrink(&seed);
    fuzz_then_shrink(&[]);
}
<commit_msg>Test reverse iteration in tree quickcheck test<commit_after>use std::{collections::BTreeMap, fmt, panic};

use quickcheck::{Arbitrary, Gen, RngCore};
use rand::distributions::{Distribution, Gamma};
use rand::{rngs::StdRng, Rng, SeedableRng};

use pagecache::MAX_SPACE_AMPLIFICATION;
use sled::*;

#[derive(Clone, Ord, PartialOrd, Eq, PartialEq)]
pub struct Key(pub Vec<u8>);

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

struct SledGen {
    r: StdRng,
    size: usize,
}

impl Gen for SledGen {
    fn size(&self) -> usize {
        self.size
    }
}

impl RngCore for SledGen {
    fn next_u32(&mut self) -> u32 {
        self.r.gen::<u32>()
    }

    fn next_u64(&mut self) -> u64 {
        self.r.gen::<u64>()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.r.fill_bytes(dest)
    }

    fn try_fill_bytes(
        &mut self,
        dest: &mut [u8],
    ) -> std::result::Result<(), rand::Error> {
        self.r.try_fill_bytes(dest)
    }
}

pub fn fuzz_then_shrink(buf: &[u8]) {
    let use_compression = buf.get(0).unwrap_or(&0) % 2 == 0;

    let ops: Vec<Op> = buf
        .chunks(2)
        .map(|chunk| {
            let mut seed = [0u8; 32];
            seed[0..chunk.len()].copy_from_slice(chunk);
            let rng: StdRng = SeedableRng::from_seed(seed);
            let mut sled_rng = SledGen { r: rng, size: 2 };

            Op::arbitrary(&mut sled_rng)
        })
        .collect();

    match panic::catch_unwind(move || {
        prop_tree_matches_btreemap(ops, 0, 100, false, use_compression)
    }) {
        Ok(_) => {}
        Err(_e) => panic!("TODO"),
    }
}

impl Arbitrary for Key {
    fn arbitrary<G: Gen>(g: &mut G) -> Key {
        if g.gen::<bool>() {
            let gs = g.size();
            let gamma = Gamma::new(0.3, gs as f64);
            let v = gamma.sample(&mut rand::thread_rng());
            let len = if v > 30000.0 {
                1000
            } else {
                (v % 100.) as usize
            };

            let space = g.gen_range(0, gs) + 1;

            let inner = (0..len).map(|_| g.gen_range(0, space) as u8).collect();

            Key(inner)
        } else {
            let len = g.gen_range(0, 2);
            let mut inner = vec![];

            for _ in 0..len {
                inner.push(g.gen::<u8>());
            }

            Key(inner)
        }
    }

    fn shrink(&self) -> Box<Iterator<Item = Key>> {
        // we only want to shrink on length, not byte values
        Box::new(
            self.0
                .len()
                .shrink()
                .zip(std::iter::repeat(self.0.clone()))
                .map(|(len, underlying)| Key(underlying[..len].to_vec())),
        )
    }
}

#[derive(Debug, Clone)]
pub enum Op {
    Set(Key, u8),
    Merge(Key, u8),
    Get(Key),
    GetLt(Key),
    GetGt(Key),
    Del(Key),
    Cas(Key, u8, u8),
    Scan(Key, isize),
    Restart,
}

use self::Op::*;

impl Op {
    pub fn is_restart(&self) -> bool {
        if let Restart = self {
            true
        } else {
            false
        }
    }
}

impl Arbitrary for Op {
    fn arbitrary<G: Gen>(g: &mut G) -> Op {
        if g.gen_bool(1. / 10.) {
            return Restart;
        }

        let choice = g.gen_range(0, 8);

        match choice {
            0 => Set(Key::arbitrary(g), g.gen::<u8>()),
            1 => Merge(Key::arbitrary(g), g.gen::<u8>()),
            2 => Get(Key::arbitrary(g)),
            3 => GetLt(Key::arbitrary(g)),
            4 => GetGt(Key::arbitrary(g)),
            5 => Del(Key::arbitrary(g)),
            6 => Cas(Key::arbitrary(g), g.gen::<u8>(), g.gen::<u8>()),
            7 => Scan(Key::arbitrary(g), g.gen_range(-40, 40)),
            _ => panic!("impossible choice"),
        }
    }

    fn shrink(&self) -> Box<Iterator<Item = Op>> {
        match *self {
            Set(ref k, v) => Box::new(k.shrink().map(move |sk| Set(sk, v))),
            Merge(ref k, v) => Box::new(k.shrink().map(move |k| Merge(k, v))),
            Get(ref k) => Box::new(k.shrink().map(Get)),
            GetLt(ref k) => Box::new(k.shrink().map(GetLt)),
            GetGt(ref k) => Box::new(k.shrink().map(GetGt)),
            Cas(ref k, old, new) => {
                Box::new(k.shrink().map(move |k| Cas(k, old, new)))
            }
            Scan(ref k, len) => Box::new(k.shrink().map(move |k| Scan(k, len))),
            Del(ref k) => Box::new(k.shrink().map(Del)),
            Restart => Box::new(vec![].into_iter()),
        }
    }
}

fn bytes_to_u16(v: &[u8]) -> u16 {
    assert_eq!(v.len(), 2);
    (u16::from(v[0]) << 8) + u16::from(v[1])
}

fn u16_to_bytes(u: u16) -> Vec<u8> {
    let ret = vec![(u >> 8) as u8, u as u8];
    ret
}

// just adds up values as if they were u16's
fn test_merge_operator(
    _k: &[u8],
    old: Option<&[u8]>,
    to_merge: &[u8],
) -> Option<Vec<u8>> {
    let base = old.unwrap_or(&[0, 0]);
    let base_n = bytes_to_u16(base);
    let new_n = base_n + u16::from(to_merge[0]);
    let ret = u16_to_bytes(new_n);
    Some(ret)
}

pub fn prop_tree_matches_btreemap(
    ops: Vec<Op>,
    blink_node_exponent: u8,
    snapshot_after: u8,
    flusher: bool,
    use_compression: bool,
) -> bool {
    super::setup_logger();

    use self::*;
    let config = ConfigBuilder::new()
        .async_io(false)
        .temporary(true)
        .use_compression(use_compression)
        .snapshot_after_ops(u64::from(snapshot_after) + 1)
        .flush_every_ms(if flusher { Some(1) } else { None })
        .io_buf_size(1000)
        .cache_capacity(40)
        .cache_bits(0)
        .merge_operator(test_merge_operator)
        .idgen_persist_interval(1)
        .build();

    let mut tree = sled::Db::start(config.clone()).unwrap();
    let mut reference: BTreeMap<Key, u16> = BTreeMap::new();

    for op in ops.into_iter() {
        match op {
            Set(k, v) => {
                let old_actual = tree.insert(&k.0, vec![0, v]).unwrap();
                let old_reference = reference.insert(k.clone(), u16::from(v));
                assert_eq!(
                    old_actual.map(|v| bytes_to_u16(&*v)),
                    old_reference
                );
            }
            Merge(k, v) => {
                tree.merge(&k.0, vec![v]).unwrap();
                let entry = reference.entry(k).or_insert(0u16);
                *entry += u16::from(v);
            }
            Get(k) => {
                let res1 = tree.get(&*k.0).unwrap().map(|v| bytes_to_u16(&*v));
                let res2 = reference.get(&k).cloned();
                assert_eq!(res1, res2);
            }
            GetLt(k) => {
                let res1 = tree.get_lt(&*k.0).unwrap().map(|v| v.0);
                let res2 = reference
                    .iter()
                    .rev()
                    .filter(|(key, _)| **key < k)
                    .nth(0)
                    .map(|(k, _v)| IVec::from(&*k.0));
                assert_eq!(
                    res1, res2,
                    "get_lt({:?}) should have returned {:?} \
                     but it returned {:?} instead. \
                     \n Db: {:?}",
                    k, res2, res1, tree
                );
            }
            GetGt(k) => {
                let res1 = tree.get_gt(&*k.0).unwrap().map(|v| v.0);
                let res2 = reference
                    .iter()
                    .filter(|(key, _)| **key > k)
                    .nth(0)
                    .map(|(k, _v)| IVec::from(&*k.0));
                assert_eq!(
                    res1, res2,
                    "get_gt({:?}) expected {:?} in tree {:?}",
                    k, res2, tree
                );
            }
            Del(k) => {
                tree.remove(&*k.0).unwrap();
                reference.remove(&k);
            }
            Cas(k, old, new) => {
                let tree_old = tree.get(&*k.0).unwrap();
                if let Some(old_tree) = tree_old {
                    if old_tree == *vec![0, old] {
                        tree.insert(&k.0, vec![0, new]).unwrap();
                    }
                }

                let ref_old = reference.get(&k).cloned();
                if ref_old == Some(u16::from(old)) {
                    reference.insert(k, u16::from(new));
                }
            }
            Scan(k, len) => {
                if len > 0 {
                    let mut tree_iter = tree
                        .range(&*k.0..)
                        .take(len.abs() as usize)
                        .map(|res| res.unwrap());
                    let ref_iter = reference
                        .iter()
                        .filter(|&(ref rk, _rv)| **rk >= k)
                        .take(len.abs() as usize)
                        .map(|(ref rk, ref rv)| (rk.0.clone(), **rv));

                    for r in ref_iter {
                        let tree_next = tree_iter.next().unwrap();
                        let lhs = (tree_next.0, &*tree_next.1);
                        let rhs = (r.0.clone(), &*u16_to_bytes(r.1));
                        assert_eq!(
                            (lhs.0.as_ref(), lhs.1),
                            (rhs.0.as_ref(), rhs.1),
                            "expected {:?} while iterating from {:?} on tree: {:?}",
                            rhs,
                            k,
                            tree
                        );
                    }
                } else {
                    let mut tree_iter = tree
                        .range(&*k.0..)
                        .rev()
                        .take(len.abs() as usize)
                        .map(|res| res.unwrap());
                    let ref_iter = reference
                        .iter()
                        .rev()
                        .filter(|&(ref rk, _rv)| **rk >= k)
                        .take(len.abs() as usize)
                        .map(|(ref rk, ref rv)| (rk.0.clone(), **rv));

                    for r in ref_iter {
                        let tree_next = tree_iter.next().unwrap();
                        let lhs = (tree_next.0, &*tree_next.1);
                        let rhs = (r.0.clone(), &*u16_to_bytes(r.1));
                        assert_eq!(
                            (lhs.0.as_ref(), lhs.1),
                            (rhs.0.as_ref(), rhs.1),
                            "expected {:?} while reverse iterating from {:?} on tree: {:?}",
                            rhs,
                            k,
                            tree
                        );
                    }
                }
            }
            Restart => {
                drop(tree);
                tree = sled::Db::start(config.clone()).unwrap();
            }
        }
    }

    let space_amplification = tree
        .space_amplification()
        .expect("should be able to read files and pages");

    assert!(
        space_amplification < MAX_SPACE_AMPLIFICATION,
        "space amplification was measured to be {}, \
         which is higher than the maximum of {}",
        space_amplification,
        MAX_SPACE_AMPLIFICATION
    );

    true
}

#[test]
fn test_fuzz_test() {
    let seed = [0; 32];
    fuzz_then_shrink(&seed);
    let seed = [0; 31];
    fuzz_then_shrink(&seed);
    let seed = [0; 33];
    fuzz_then_shrink(&seed);
    fuzz_then_shrink(&[]);
}
<|endoftext|>


<commit_before>use std::{iter, local_data, num, uint};
use std::iter::MultiplicativeIterator;
use std::cell::RefCell;
use std::rc::Rc;
use std::local_data::Key;

use data::monoid::{Sum, MergeMonoidIterator, MergeMultiMonoidIterator, Wrap};

static PRIMES_BELOW100: &'static [uint] = &[
    2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
    43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
];

struct PrimeInner {
    priv data: ~[uint]
}

impl PrimeInner {
    fn new() -> PrimeInner { PrimeInner { data: PRIMES_BELOW100.to_owned() } }
    fn nth(&mut self, n: uint) -> uint {
        self.grow(n + 1);
        return self.data[n];
    }
    fn contains(&mut self, n: uint) -> bool {
        if n < *self.data.last().unwrap() {
            self.data.bsearch_elem(&n).is_some()
        } else {
            iter::count(0u, 1)
                .map(|i| self.nth(i))
                .take_while(|&p| p * p <= n)
                .all(|p| n % p != 0)
        }
    }

    #[inline]
    fn is_coprime(&self, n: uint) -> bool {
        self.data.iter()
            .take_while(|& &p| p * p <= n)
            .all(|&p| n % p != 0)

    }

    #[inline]
    fn grow(&mut self, len: uint) {
        if self.data.len() >= len { return; }
        let mut it = iter::count(self.data.last().unwrap() + 2, 2)
            .filter(|&n| self.is_coprime(n));
        for n in it {
            self.data.push(n);
            if self.data.len() > len { return; }
        }
    }
}

static TASK_PRIME_KEY: Key<Prime> = &Key;

#[deriving(Clone)]
pub struct Prime {
    priv data: Rc<RefCell<PrimeInner>>
}

impl Prime {
    #[inline]
    pub fn new() -> Prime {
        let prime = local_data::get_mut(TASK_PRIME_KEY, |val| match val {
                Some(prime) => Some(prime.clone()),
                None        => None
            });

        match prime {
            Some(prime) => prime,
            None => {
                let prime = Prime::new_empty();
                local_data::set(TASK_PRIME_KEY, prime.clone());
                prime
            }
        }
    }
    #[inline]
    fn new_empty() -> Prime { Prime { data: Rc::new(RefCell::new(PrimeInner::new())) } }
    #[inline]
    pub fn nth(&self, n: uint) -> uint { self.data.borrow().with_mut(|p| p.nth(n)) }
    #[inline]
    pub fn contains(&self, n: uint) -> bool { self.data.borrow().with_mut(|p| p.contains(n)) }

    #[inline]
    pub fn iter<'a>(&'a self) -> PrimeIterator { PrimeIterator { idx: 0, data: self.data.clone() } }
    #[inline]
    pub fn factorize(&self, n: uint) -> FactorizeIterator {
        FactorizeIterator { num: n, iter: self.iter() }
    }
    #[inline]
    pub fn num_of_divisor(&self, n: uint) -> uint {
        if n == 0 { return 0 }
        self.factorize(n)
            .map(|(_base, exp)| (exp as uint) + 1)
            .product()
    }
    #[inline]
    pub fn sum_of_divisor(&self, n: uint) -> uint {
        if n == 0 { return 0 }
        self.factorize(n)
            .map(|(base, exp)| (num::pow(base, (exp as uint) + 1) - 1) / (base - 1) )
            .product()
    }
    #[inline]
    pub fn num_of_proper_divisor(&self, n: uint) -> uint { self.num_of_divisor(n) - 1 }
    #[inline]
    pub fn sum_of_proper_divisor(&self, n: uint) -> uint { self.sum_of_divisor(n) - n }
    #[inline]
    pub fn comb(&self, n: uint, r: uint) -> uint {
        let ns = range(r + 1, n + 1)
            .map(|n| {
                self.factorize(n)
                    .map(|(base, exp)| (base, Sum(exp)))
            }).to_owned_vec();
        let numer = MergeMultiMonoidIterator::new(ns);

        let ds = range(1, n - r + 1)
            .map(|n| {
                self.factorize(n)
                    .map(|(base, exp)| (base, Sum(-exp)))
            }).to_owned_vec();
        let denom = MergeMultiMonoidIterator::new(ds);

        MergeMonoidIterator::new(numer, denom).map(|(a, m)| (a, m.unwrap())).to_uint()
    }
}

pub struct PrimeIterator {
    priv idx: uint,
    priv data: Rc<RefCell<PrimeInner>>
}

impl Iterator<uint> for PrimeIterator {
    #[inline]
    fn next(&mut self) -> Option<uint> {
        let p = self.data.borrow().with_mut(|p| p.nth(self.idx));
        self.idx += 1;
        Some(p)
    }
}

impl RandomAccessIterator<uint> for PrimeIterator {
    #[inline]
    fn indexable(&self) -> uint { uint::max_value }

    #[inline]
    fn idx(&self, index: uint) -> Option<uint> {
        let p = self.data.borrow().with_mut(|p| p.nth(index));
        Some(p)
    }
}

pub type Factor = (uint, int);

pub struct FactorizeIterator {
    priv num: uint,
    priv iter: PrimeIterator
}

impl Iterator<Factor> for FactorizeIterator {
    #[inline]
    fn next(&mut self) -> Option<Factor> {
        if self.num == 0 || self.num == 1 { return None; }

        while self.num > 1 {
            let p = self.iter.next().unwrap();

            if p * p > self.num {
                let n = self.num;
                self.num = 1;
                return Some((n, 1));
            }

            let mut exp = 0;
            while self.num % p == 0 {
                exp += 1;
                self.num /= p;
            }
            if exp > 0 { return Some((p, exp)); }
        }

        return None;
    }
}

pub trait FactorIterator {
    fn to_uint(&mut self) -> uint;
}

impl<IA: Iterator<Factor>> FactorIterator for IA {
    #[inline]
    fn to_uint(&mut self) -> uint {
        self.fold(1, |s, (base, exp)| {
                if exp > 0 {
                    s * num::pow(base, exp as uint)
                } else {
                    s / num::pow(base, (-exp) as uint)
                }
            })
    }
}

#[cfg(test)]
mod test {
    use super::{Prime, Factor, FactorIterator};

    static PRIMES_BELOW200: &'static [uint] = &[
        2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
        43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
        101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
        151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199
            ];

    #[test]
    fn iter() {
        let prime = Prime::new();
        assert_eq!(PRIMES_BELOW200.to_owned(), prime.iter().take(PRIMES_BELOW200.len()).to_owned_vec());
    }

    #[test]
    fn nth() {
        let prime = Prime::new_empty();
        // Generated primes
        for (i, &p) in PRIMES_BELOW200.iter().enumerate() {
            assert_eq!(p, prime.nth(i));
        }
        // Memoized primes
        for (i, &p) in PRIMES_BELOW200.iter().enumerate() {
            assert_eq!(p, prime.nth(i));
        }
    }

    #[test]
    fn contains() {
        let prime = Prime::new();
        assert!(!prime.contains(0));
        assert!(!prime.contains(1));
        assert!(prime.contains(2));
        assert!(prime.contains(3));
        assert!(!prime.contains(4));
        assert!(prime.contains(5));
        assert!(!prime.contains(6));
        assert!(prime.contains(7));
        assert!(!prime.contains(100));
    }

    #[test]
    fn multi_iter() {
        let prime = Prime::new();
        for _p1 in prime.iter() {
            for _p2 in prime.iter() {
                break;
            }
            break;
        }
    }

    #[test]
    fn clone_clones_data() {
        let p1 = Prime::new();
        let p2 = p1.clone();
        p1.nth(500);
        let l1 = p1.data.borrow().with(|p| p.data.len());
        let l2 = p2.data.borrow().with(|p| p.data.len());
        assert_eq!(l1, l2);
    }

    #[test]
    fn factorize() {
        fn check(n: uint, fs: ~[Factor]) {
            let ps = Prime::new();
            assert_eq!(fs, ps.factorize(n).to_owned_vec());
            if n != 0 {
                assert_eq!(n, ps.factorize(n).to_uint());
            }
        }

        check(0, ~[]);
        check(1, ~[]);
        check(2, ~[(2, 1)]);
        check(3, ~[(3, 1)]);
        check(4, ~[(2, 2)]);
        check(5, ~[(5, 1)]);
        check(6, ~[(2, 1), (3, 1)]);
        check(7, ~[(7, 1)]);
        check(8, ~[(2, 3)]);
        check(9, ~[(3, 2)]);
        check(10, ~[(2, 1), (5, 1)]);

        check(8 * 27, ~[(2, 3), (3, 3)]);
        check(97, ~[(97, 1)]);
        check(97 * 41, ~[(41, 1), (97, 1)]);
    }

    #[test]
    fn num_of_divisor() {
        let pairs = [
            (0, 0),
            (1, 1), (2, 2), (3, 2), (4, 3), (5, 2), (6, 4),
            (7, 2), (8, 4), (9, 3), (10, 4), (11, 2), (12, 6),
            (24, 8), (36, 9), (48, 10), (60, 12),
            (50, 6)
            ];
        let p = Prime::new();
        for &(n, num_div) in pairs.iter() {
            assert_eq!(num_div, p.num_of_divisor(n));
        }
    }

    #[test]
    fn sum_of_divisor() {
        let pairs = [
            (0, 0),
            (1, 1), (2, 3), (3, 4), (4, 7), (5, 6), (6, 12),
            (7, 8), (8, 15), (9, 13), (10, 18), (11, 12), (12, 28),
            (24, 60), (36, 91), (48, 124), (60, 168),
            (50, 93)
            ];
        let p = Prime::new();
        for &(n, sum_div) in pairs.iter() {
            assert_eq!(sum_div, p.sum_of_divisor(n));
        }
    }

    #[test]
    fn comb() {
        let prime = Prime::new();
        assert_eq!(1, prime.comb(2, 2));
        assert_eq!(3, prime.comb(3, 2));
        assert_eq!(6, prime.comb(4, 2));
        assert_eq!(10, prime.comb(5, 2));

        assert_eq!(137846528820, prime.comb(40, 20));
    }
}

#[cfg(test)]
mod bench {
    use super::Prime;
    use extra::test::BenchHarness;

    #[bench]
    fn get_5000th(bh: &mut BenchHarness) {
        bh.iter(|| { Prime::new().nth(5000); });
    }
    #[bench]
    fn get_5000th_nocache(bh: &mut BenchHarness) {
        bh.iter(|| { Prime::new_empty().nth(5000); });
    }

    #[bench]
    fn get_below_5000th(bh: &mut BenchHarness) {
        bh.iter(|| {
                let prime = Prime::new();
                for _p in prime.iter().take(5000) {}
            });
    }
    #[bench]
    fn get_below_5000th_nocache(bh: &mut BenchHarness) {
        bh.iter(|| {
                let prime = Prime::new_empty();
                for _p in prime.iter().take(5000) {}
            });
    }

    #[bench]
    fn factorial_600851475143(bh: &mut BenchHarness) {
        bh.iter(|| {
                let ps = Prime::new();
                ps.factorize(600851475143).fold(0, |a, (b, _)| a + b);
            });
    }

    #[bench]
    fn factorial_600851475143_nocache(bh: &mut BenchHarness) {
        bh.iter(|| {
                let ps = Prime::new_empty();
                ps.factorize(600851475143).fold(0, |a, (b, _)| a + b);
            });
    }
}
<commit_msg>Refactor prime<commit_after>use std::{iter, local_data, num, uint};
use std::iter::MultiplicativeIterator;
use std::cell::RefCell;
use std::rc::Rc;
use std::local_data::Key;

use data::monoid::{Sum, MergeMonoidIterator, MergeMultiMonoidIterator, Wrap};

static PRIMES_BELOW100: &'static [uint] = &[
    2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
    43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97
];

struct PrimeInner {
    priv data: ~[uint]
}

impl PrimeInner {
    #[inline]
    fn new() -> PrimeInner { PrimeInner { data: PRIMES_BELOW100.to_owned() } }

    #[inline]
    fn max_prime(&self) -> uint { *self.data.last().unwrap() }

    #[inline]
    fn nth(&mut self, n: uint) -> uint { self.grow(n + 1); self.data[n] }

    #[inline]
    fn contains(&mut self, n: uint) -> bool {
        if n < self.max_prime() { return self.data.bsearch_elem(&n).is_some() }

        if !self.is_coprime(n) { return false }

        iter::count(self.data.len(), 1)
            .map(|i| self.nth(i))
            .take_while(|&p| p * p <= n)
            .all(|p| !n.is_multiple_of(&p))
    }

    #[inline]
    fn is_coprime(&self, n: uint) -> bool {
        self.data.iter()
            .take_while(|& &p| p * p <= n)
            .all(|&p| !n.is_multiple_of(&p))
    }

    #[inline]
    fn grow(&mut self, len: uint) {
        if self.data.len() >= len { return }

        let mut it = iter::count(self.max_prime() + 2, 2)
            .filter(|&n| self.is_coprime(n));
        for n in it {
            self.data.push(n);
            if self.data.len() >= len { return }
        }
    }
}

static TASK_PRIME_KEY: Key<Prime> = &Key;

#[deriving(Clone)]
pub struct Prime {
    priv data: Rc<RefCell<PrimeInner>>
}

impl Prime {
    #[inline]
    pub fn new() -> Prime {
        let prime = local_data::get_mut(TASK_PRIME_KEY, |val| match val {
                Some(prime) => Some(prime.clone()),
                None        => None
            });

        match prime {
            Some(prime) => prime,
            None => {
                let prime = Prime::new_empty();
                local_data::set(TASK_PRIME_KEY, prime.clone());
                prime
            }
        }
    }
    #[inline]
    fn new_empty() -> Prime { Prime { data: Rc::new(RefCell::new(PrimeInner::new())) } }
    #[inline]
    pub fn nth(&self, n: uint) -> uint { self.data.borrow().with_mut(|p| p.nth(n)) }
    #[inline]
    pub fn contains(&self, n: uint) -> bool { self.data.borrow().with_mut(|p| p.contains(n)) }

    #[inline]
    pub fn iter<'a>(&'a self) -> PrimeIterator { PrimeIterator { idx: 0, data: self.data.clone() } }
    #[inline]
    pub fn factorize(&self, n: uint) -> FactorizeIterator {
        FactorizeIterator { num: n, iter: self.iter() }
    }
    #[inline]
    pub fn num_of_divisor(&self, n: uint) -> uint {
        if n == 0 { return 0 }
        self.factorize(n)
            .map(|(_base, exp)| (exp as uint) + 1)
            .product()
    }
    #[inline]
    pub fn sum_of_divisor(&self, n: uint) -> uint {
        if n == 0 { return 0 }
        self.factorize(n)
            .map(|(base, exp)| (num::pow(base, (exp as uint) + 1) - 1) / (base - 1) )
            .product()
    }
    #[inline]
    pub fn num_of_proper_divisor(&self, n: uint) -> uint { self.num_of_divisor(n) - 1 }
    #[inline]
    pub fn sum_of_proper_divisor(&self, n: uint) -> uint { self.sum_of_divisor(n) - n }
    #[inline]
    pub fn comb(&self, n: uint, r: uint) -> uint {
        let ns = range(r + 1, n + 1)
            .map(|n| {
                self.factorize(n)
                    .map(|(base, exp)| (base, Sum(exp)))
            }).to_owned_vec();
        let numer = MergeMultiMonoidIterator::new(ns);

        let ds = range(1, n - r + 1)
            .map(|n| {
                self.factorize(n)
                    .map(|(base, exp)| (base, Sum(-exp)))
            }).to_owned_vec();
        let denom = MergeMultiMonoidIterator::new(ds);

        MergeMonoidIterator::new(numer, denom).map(|(a, m)| (a, m.unwrap())).to_uint()
    }
}

pub struct PrimeIterator {
    priv idx: uint,
    priv data: Rc<RefCell<PrimeInner>>
}

impl Iterator<uint> for PrimeIterator {
    #[inline]
    fn next(&mut self) -> Option<uint> {
        let p = self.data.borrow().with_mut(|p| p.nth(self.idx));
        self.idx += 1;
        Some(p)
    }
}

impl RandomAccessIterator<uint> for PrimeIterator {
    #[inline]
    fn indexable(&self) -> uint { uint::max_value }

    #[inline]
    fn idx(&self, index: uint) -> Option<uint> {
        let p = self.data.borrow().with_mut(|p| p.nth(index));
        Some(p)
    }
}

pub type Factor = (uint, int);

pub struct FactorizeIterator {
    priv num: uint,
    priv iter: PrimeIterator
}

impl Iterator<Factor> for FactorizeIterator {
    #[inline]
    fn next(&mut self) -> Option<Factor> {
        if self.num <= 1 { return None }

        for p in self.iter {
            if p * p > self.num {
                let n = self.num;
                self.num = 1;
                return Some((n, 1))
            }

            if self.num.is_multiple_of(&p) {
                let mut exp = 1;
                self.num /= p;

                while self.num.is_multiple_of(&p) {
                    exp += 1;
                    self.num /= p;
                }
                return Some((p, exp))
            }
        }

        unreachable!()
    }
}

pub trait FactorIterator {
    fn to_uint(&mut self) -> uint;
}

impl<IA: Iterator<Factor>> FactorIterator for IA {
    #[inline]
    fn to_uint(&mut self) -> uint {
        self.fold(1, |s, (base, exp)| {
                if exp > 0 {
                    s * num::pow(base, exp as uint)
                } else {
                    s / num::pow(base, (-exp) as uint)
                }
            })
    }
}

#[cfg(test)]
mod test {
    use super::{Prime, Factor, FactorIterator};

    static PRIMES_BELOW200: &'static [uint] = &[
        2,  3,  5,  7, 11, 13, 17, 19, 23, 29, 31, 37, 41,
        43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,
        101, 103, 107, 109, 113, 127, 131, 137, 139, 149,
        151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199
            ];

    #[test]
    fn iter() {
        let prime = Prime::new();
        assert_eq!(PRIMES_BELOW200.to_owned(), prime.iter().take(PRIMES_BELOW200.len()).to_owned_vec());
    }

    #[test]
    fn nth() {
        let prime = Prime::new_empty();
        // Generated primes
        for (i, &p) in PRIMES_BELOW200.iter().enumerate() {
            assert_eq!(p, prime.nth(i));
        }
        // Memoized primes
        for (i, &p) in PRIMES_BELOW200.iter().enumerate() {
            assert_eq!(p, prime.nth(i));
        }
    }

    #[test]
    fn contains() {
        let prime = Prime::new();
        assert!(!prime.contains(0));
        assert!(!prime.contains(1));
        assert!(prime.contains(2));
        assert!(prime.contains(3));
        assert!(!prime.contains(4));
        assert!(prime.contains(5));
        assert!(!prime.contains(6));
        assert!(prime.contains(7));
        assert!(!prime.contains(100));
    }

    #[test]
    fn multi_iter() {
        let prime = Prime::new();
        for _p1 in prime.iter() {
            for _p2 in prime.iter() {
                break;
            }
            break;
        }
    }

    #[test]
    fn clone_clones_data() {
        let p1 = Prime::new();
        let p2 = p1.clone();
        p1.nth(500);
        let l1 = p1.data.borrow().with(|p| p.data.len());
        let l2 = p2.data.borrow().with(|p| p.data.len());
        assert_eq!(l1, l2);
    }

    #[test]
    fn factorize() {
        fn check(n: uint, fs: ~[Factor]) {
            let ps = Prime::new();
            assert_eq!(fs, ps.factorize(n).to_owned_vec());
            if n != 0 {
                assert_eq!(n, ps.factorize(n).to_uint());
            }
        }

        check(0, ~[]);
        check(1, ~[]);
        check(2, ~[(2, 1)]);
        check(3, ~[(3, 1)]);
        check(4, ~[(2, 2)]);
        check(5, ~[(5, 1)]);
        check(6, ~[(2, 1), (3, 1)]);
        check(7, ~[(7, 1)]);
        check(8, ~[(2, 3)]);
        check(9, ~[(3, 2)]);
        check(10, ~[(2, 1), (5, 1)]);

        check(8 * 27, ~[(2, 3), (3, 3)]);
        check(97, ~[(97, 1)]);
        check(97 * 41, ~[(41, 1), (97, 1)]);
    }

    #[test]
    fn num_of_divisor() {
        let pairs = [
            (0, 0),
            (1, 1), (2, 2), (3, 2), (4, 3), (5, 2), (6, 4),
            (7, 2), (8, 4), (9, 3), (10, 4), (11, 2), (12, 6),
            (24, 8), (36, 9), (48, 10), (60, 12),
            (50, 6)
            ];
        let p = Prime::new();
        for &(n, num_div) in pairs.iter() {
            assert_eq!(num_div, p.num_of_divisor(n));
        }
    }

    #[test]
    fn sum_of_divisor() {
        let pairs = [
            (0, 0),
            (1, 1), (2, 3), (3, 4), (4, 7), (5, 6), (6, 12),
            (7, 8), (8, 15), (9, 13), (10, 18), (11, 12), (12, 28),
            (24, 60), (36, 91), (48, 124), (60, 168),
            (50, 93)
            ];
        let p = Prime::new();
        for &(n, sum_div) in pairs.iter() {
            assert_eq!(sum_div, p.sum_of_divisor(n));
        }
    }

    #[test]
    fn comb() {
        let prime = Prime::new();
        assert_eq!(1, prime.comb(2, 2));
        assert_eq!(3, prime.comb(3, 2));
        assert_eq!(6, prime.comb(4, 2));
        assert_eq!(10, prime.comb(5, 2));

        assert_eq!(137846528820, prime.comb(40, 20));
    }
}

#[cfg(test)]
mod bench {
    use super::Prime;
    use extra::test::BenchHarness;

    #[bench]
    fn get_5000th(bh: &mut BenchHarness) {
        bh.iter(|| { Prime::new().nth(5000); });
    }
    #[bench]
    fn get_5000th_nocache(bh: &mut BenchHarness) {
        bh.iter(|| { Prime::new_empty().nth(5000); });
    }

    #[bench]
    fn get_below_5000th(bh: &mut BenchHarness) {
        bh.iter(|| {
                let prime = Prime::new();
                for _p in prime.iter().take(5000) {}
            });
    }
    #[bench]
    fn get_below_5000th_nocache(bh: &mut BenchHarness) {
        bh.iter(|| {
                let prime = Prime::new_empty();
                for _p in prime.iter().take(5000) {}
            });
    }

    #[bench]
    fn factorial_600851475143(bh: &mut BenchHarness) {
        bh.iter(|| {
                let ps = Prime::new();
                ps.factorize(600851475143).fold(0, |a, (b, _)| a + b);
            });
    }

    #[bench]
    fn factorial_600851475143_nocache(bh: &mut BenchHarness) {
        bh.iter(|| {
                let ps = Prime::new_empty();
                ps.factorize(600851475143).fold(0, |a, (b, _)| a + b);
            });
    }
}
<|endoftext|>


<commit_before>//! Composable memory behaviors.
//!
//! The `memory` module provides multiple implementations of the `Memory` trait,
//! that can be combined to yield the specified behavior of osci’s memory.
//! By themselves, they are not necessarily compliant.
//!
//! # osci’s memory
//! osci’s memory is only addressable at a word boundary and only entire words
//! can be read or written. A word is 4 bytes in little endian. osci always has
//! 2^32 bytes of virtual memory. Not all the memory address are necessarily
//! backed by physical memory. Reads from unmapped memory yield 0. Writes
//! to unmapped memory are discarded.
//!
//! At boot, the BIOS memory is mapped to the address space at 2^31 and the
//! instruction pointer (IP) is set to 2^31. The BIOS memory can be unmapped
//! by setting the `bD` flag. BIOS memory is read-only.
//!
//! The end of the address range is an area of mapped memory for control flags,
//! peripherals and interrupts.
//!
//! ```text
//! +---------------------------------------+ Address 0
//! |                 Word 0                |
//! |                 Word 1                |
//! |                   ...                 |
//! +---------------------------------------+ FLAGS_START_ADDRESS
//! |              Flags Word 0             |
//! |                   ...                 |
//! |              Flags Word i             |
//! +---------------------------------------+ IVT_START_ADDRESS
//! |               IVT Entry 0             |
//! |                   ...                 |
//! |               IVT Entry j             |
//! +---------------------------------------+
//! |           IVT Return address          | IVT_RETURN_ADDRESS
//! +---------------------------------------+ REGISTER_START_ADDRESS
//! |                Register 0             |
//! |                   ...                 |
//! |                Register k             |
//! +---------------------------------------+ MAX_ADDRESS = 2^32-1
//! ```
//!
//! Flags Word 0:
//!
//! ```text
//!  MSB                                LSB
//! +---------------------------------------+
//! |    |    |    |    |    |    | bD | H  | Byte 0
//! +---------------------------------------+
//! |                 Unused                |
//! +---------------------------------------+
//! |                 Unused                |
//! +---------------------------------------+
//! |                 Unused                | Byte 3
//! +---------------------------------------+
//! ```
//!
//! Flags:
//!
//! * biosDone (`bD`): Unmaps the BIOS from the address space
//! * halt (`H`): Halts the CPU

mod nullmemory;
mod slicememory;
pub mod mappedmemory;
pub mod address;
pub mod hookmemory;
pub use self::hookmemory::HookMemory;
pub use self::nullmemory::NullMemory;
pub use self::slicememory::SliceMemory;
pub use self::mappedmemory::MappedMemory;

/// Access to individual memory cells.
pub trait Memory {
    /// Gets the value of the memory cell at `addr`.
    fn get(&self, addr: usize) -> u32;
    /// Sets the value of the memory cell at `addr`.
    fn set(&mut self, addr: usize, value: u32);
    /// Returns the size of this memory in bytes.
    fn size(&self) -> usize;
}
<commit_msg>docs(memory): Merge new memory design from attempt3<commit_after>//! Composable memory behaviors.
//!
//! The `memory` module provides multiple implementations of the `Memory` trait,
//! that can be combined to yield the specified behavior of osci’s memory.
//! By themselves, they are not necessarily compliant.
//!
//! # osci’s memory
//! osci’s memory is a sequence of word-sized memory cells. One word has 32
//! bits. osci always has 2^31 words of virtual memory. Not all the memory
//! address are necessarily backed by physical memory. Reads from unmapped
//! memory yield 0. Writes to unmapped memory are discarded.
//!
//! At boot, the BIOS memory is mapped to the address space at 2^30 and the
//! instruction pointer (IP) is set to 2^30. The BIOS memory can be unmapped
//! by setting the `bD` flag. BIOS memory is read-only.
//!
//! The end of the address range is an area of mapped memory for control flags,
//! peripherals and interrupts.
//!
//! ```text
//!   +---------------------------------------+ Address 0
//!   |                 Word 0                |
//!   |                 Word 1                |
//!   |                   ...                 |
//!   +---------------------------------------+ STACK_POINTER_ADDRESS
//!   |              Stack Pointer            |
//!   +---------------------------------------+ REGISTERS_START_ADDRESS
//!   |                Register 0             |
//!   |                   ...                 |
//!   |                Register k             |
//!   +---------------------------------------+ IVT_START_ADDRESS
//!   |               IVT Entry 0             |
//!   |                   ...                 |
//!   |               IVT Entry j             |
//!   +---------------------------------------+ FLAGS_START_ADDRESS
//!   |              Flags Word 0             |
//!   |                   ...                 |
//!   |              Flags Word i             |
//!   +---------------------------------------+ MAX_ADDRESS = 2^31-1
//! ```
//!
//! Registers:
//! - Register 0: General purpose
//! - Register 1: General purpose
//! - Register 2: General purpose
//! - Register 3: General purpose
//!
//! IVTs:
//! - IVT Entry 0: Unused
//!
//! Flags Word 0::
//!
//!   MSB                                   LSB
//!   +---------------------------------------+
//!   |    |    |    |    |    |    | bD | H  | Byte 0
//!   +---------------------------------------+
//!   |                 Unused                |
//!   +---------------------------------------+
//!   |                 Unused                |
//!   +---------------------------------------+
//!   |                 Unused                | Byte 3
//!   +---------------------------------------+
//!
//! Flags:
//!
//! * ``biosDone`` (``bD``): Unmaps the BIOS from the address space
//! * ``halt`` (``H``): Halts the CPU

mod nullmemory;
mod slicememory;
pub mod mappedmemory;
pub mod address;
pub mod hookmemory;
pub use self::hookmemory::HookMemory;
pub use self::nullmemory::NullMemory;
pub use self::slicememory::SliceMemory;
pub use self::mappedmemory::MappedMemory;

/// Access to individual memory cells.
pub trait Memory {
    /// Gets the value of the memory cell at `addr`.
    fn get(&self, addr: usize) -> u32;
    /// Sets the value of the memory cell at `addr`.
    fn set(&mut self, addr: usize, value: u32);
    /// Returns the size of this memory in bytes.
    fn size(&self) -> usize;
}
<|endoftext|>


<commit_before>use std::f64;
use std::iter;
use std::slice;

use itertools::Itertools;

use bio::stats::logprobs::{self, LogProb};

#[derive(Debug, Clone)]
pub struct CDF<T: PartialOrd> {
    inner: Vec<(T, LogProb)>
}

impl<T: PartialOrd> CDF<T> {
    pub fn new(mut entries: Vec<(T, LogProb)>) -> Self {
        entries.sort_by(|&(ref a, _), &(ref b, _)| a.partial_cmp(b).unwrap());
        let mut i = 1;
        while i < entries.len() {
            if entries[i].0 == entries[i - 1].0 {
                entries[i - 1].1 = logprobs::add(entries[i - 1].1, entries[i].1);
                entries.remove(i);
            }
            else {
                entries[i].1 = logprobs::add(entries[i - 1].1, entries[i].1);
            }
            i += 1;
        }
        let mut cdf = CDF {
            inner: entries
        };

        if relative_eq!(cdf.total_prob(), 0.0) && cdf.total_prob() > 0.0 {
            cdf.inner.last_mut().unwrap().1 = 0.0;
        }

        cdf
    }

    pub fn sample(mut self, n: usize) -> Self {
        if self.inner.len() <= n {
            println!("not sampling");
            self
        }
        else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step(s).collect_vec();
            inner.push(last);
            CDF {
                inner: inner
            }
        }
    }

    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => self.inner[i].1,
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => if i > 0 { logprobs::sub(self.inner[i].1, self.inner[i - 1].1) } else { self.inner[0].1 },
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn total_prob(&self) -> LogProb {
        self.inner.last().unwrap().1
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }
}

impl<T: Clone + PartialOrd> CDF<T> {
    pub fn iter_pmf(&self) -> CDFPMFIter<T> {
        fn cdf_to_pmf<G: Clone>(last_prob: &mut LogProb, e: &(G, LogProb)) -> Option<(G, LogProb)> {
            let &(ref value, cdf_prob) = e;
            let prob = logprobs::sub(cdf_prob, *last_prob);
            *last_prob = cdf_prob;
            Some((value.clone(), prob))
        }
        self.inner.iter().scan(f64::NEG_INFINITY, cdf_to_pmf)
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<slice::Iter<'a, (T, LogProb)>, LogProb, fn(&mut LogProb, &(T, LogProb)) -> Option<(T, LogProb)>>;

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

    use itertools::Itertools;

    #[test]
    fn test_cdf() {
        let mut pmf = Vec::new();
        for i in 0..10 {
            pmf.push((i, 0.1f64.ln()));
        }

        let cdf = CDF::new(pmf.clone());
        for (value, prob) in pmf {
            assert_ulps_eq!(prob, cdf.get_pmf(&value).unwrap(), epsilon = 0.0000000000001);
        }
        assert_relative_eq!(cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(cdf.get(&1).unwrap(), 0.2f64.ln());
    }
}
<commit_msg>Fix index increase.<commit_after>use std::f64;
use std::iter;
use std::slice;

use itertools::Itertools;

use bio::stats::logprobs::{self, LogProb};

#[derive(Debug, Clone)]
pub struct CDF<T: PartialOrd> {
    inner: Vec<(T, LogProb)>
}

impl<T: PartialOrd> CDF<T> {
    pub fn new(mut entries: Vec<(T, LogProb)>) -> Self {
        entries.sort_by(|&(ref a, _), &(ref b, _)| a.partial_cmp(b).unwrap());
        let mut i = 1;
        while i < entries.len() {
            if entries[i].0 == entries[i - 1].0 {
                entries[i - 1].1 = logprobs::add(entries[i - 1].1, entries[i].1);
                entries.remove(i);
            }
            else {
                entries[i].1 = logprobs::add(entries[i - 1].1, entries[i].1);
                i += 1;
            }
        }
        let mut cdf = CDF {
            inner: entries
        };

        if relative_eq!(cdf.total_prob(), 0.0) && cdf.total_prob() > 0.0 {
            cdf.inner.last_mut().unwrap().1 = 0.0;
        }

        cdf
    }

    pub fn sample(mut self, n: usize) -> Self {
        if self.inner.len() <= n {
            println!("not sampling");
            self
        }
        else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step(s).collect_vec();
            inner.push(last);
            CDF {
                inner: inner
            }
        }
    }

    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => self.inner[i].1,
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        }
        else {
            Some(match self.inner.binary_search_by(|e| e.0.partial_cmp(value).unwrap()) {
                Ok(i) => if i > 0 { logprobs::sub(self.inner[i].1, self.inner[i - 1].1) } else { self.inner[0].1 },
                Err(i) => if i > 0 { self.inner[i - 1].1 } else { f64::NEG_INFINITY }
            })
        }
    }

    pub fn total_prob(&self) -> LogProb {
        self.inner.last().unwrap().1
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }
}

impl<T: Clone + PartialOrd> CDF<T> {
    pub fn iter_pmf(&self) -> CDFPMFIter<T> {
        fn cdf_to_pmf<G: Clone>(last_prob: &mut LogProb, e: &(G, LogProb)) -> Option<(G, LogProb)> {
            let &(ref value, cdf_prob) = e;
            let prob = logprobs::sub(cdf_prob, *last_prob);
            *last_prob = cdf_prob;
            Some((value.clone(), prob))
        }
        self.inner.iter().scan(f64::NEG_INFINITY, cdf_to_pmf)
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<slice::Iter<'a, (T, LogProb)>, LogProb, fn(&mut LogProb, &(T, LogProb)) -> Option<(T, LogProb)>>;

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

    use itertools::Itertools;

    #[test]
    fn test_cdf() {
        let mut pmf = Vec::new();
        for i in 0..10 {
            pmf.push((i, 0.1f64.ln()));
        }

        let cdf = CDF::new(pmf.clone());
        for (value, prob) in pmf {
            assert_ulps_eq!(prob, cdf.get_pmf(&value).unwrap(), epsilon = 0.0000000000001);
        }
        assert_relative_eq!(cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(cdf.get(&1).unwrap(), 0.2f64.ln());
    }
}
<|endoftext|>


<commit_before>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::path::Path;
use std::result::Result;

use storage::backend::{StorageBackend, StorageBackendError};
mod command;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

}

<commit_msg>The module itself has to be populate the Command instance<commit_after>use runtime::Runtime;
use std::error::Error;
use std::fmt::Formatter;
use std::fmt::Result as FMTResult;
use std::fmt::Display;
use std::path::Path;
use std::result::Result;

use storage::backend::{StorageBackend, StorageBackendError};
mod command;

#[derive(Debug)]
pub struct ModuleError {
    desc: String,
}

impl ModuleError {
    fn mk(desc: &'static str) -> ModuleError {
        ModuleError {
            desc: desc.to_owned().to_string(),
        }
    }
}

impl Error for ModuleError {

    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Display for ModuleError {
    fn fmt(&self, f: &mut Formatter) -> FMTResult {
        write!(f, "ModuleError: {}", self.description())
    }
}

pub type ModuleResult = Result<(), ModuleError>;

pub trait Module {

    fn new(rt : &Runtime) -> Self;
    fn callnames() -> &'static [&'static str];
    fn name(&self) -> &'static str;

    fn execute(&self, rt : &Runtime) -> ModuleResult;
    fn shutdown(&self, rt : &Runtime) -> ModuleResult;

    fn getCommandBuilder<T>() -> F
        where F: FnOnce(StorageBackend) -> T,
              T: ExecutableCommand;

}

<|endoftext|>


<commit_before>use std::net::{TcpListener, TcpStream};
use std::io::Read;
use std::io::Write;
use std::thread;

use super::parser::parse;
use super::parser::ParseError;

pub struct Client {
    pub stream: TcpStream
}

pub struct Server {
    pub ip: String,
    pub port: i32,
}

impl Client {
    pub fn new(stream: TcpStream) -> Client {
        return Client {
            stream: stream
        }
    }

    pub fn read(&mut self) {
        let mut buffer = [0u8; 512];
        loop {
            let result = self.stream.read(&mut buffer);
            if result.is_err() {
                break;
            }
            let len = result.unwrap();
            if len == 0 {
                break;
            }
            let try_parser = parse(&buffer, len);
            if try_parser.is_err() {
                let err = try_parser.unwrap_err();
                match err {
                    ParseError::BadProtocol => { break; }
                    ParseError::Incomplete => { continue; }
                };
            }
            let parser = try_parser.unwrap();
            if parser.argc == 1 && parser.get_str(0).unwrap() == "exit" {
                break;
            }
            if parser.argc == 2 && parser.get_str(0).unwrap() == "ping" {
                let response = parser.get_str(1).unwrap();
                let writeres = self.stream.write(&*format!("${}\r\n", response.len()).as_bytes());
                if writeres.is_err() {
                    break;
                }
                let writeres = self.stream.write(response.as_bytes());
                if writeres.is_err() {
                    break;
                }
                let writeres = self.stream.write(b"\r\n");
                if writeres.is_err() {
                    break;
                }
                continue;
            }
            println!("{}", parser.argc);
            for i in 0..parser.argc {
                println!("{}", parser.get_str(i).unwrap())
            }
        };
    }
}

fn handle_client(stream: TcpStream) {
    thread::spawn(move || {
        let mut client = Client::new(stream);
        client.read();
    });
}

pub fn run(listener: TcpListener) {
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                handle_client(stream)
            }
            Err(e) => { println!("error {}", e); }
        }
    }
    drop(listener);
}

impl Server {
    pub fn new(ip: &str, port: &i32) -> Server {
        return Server {
            ip: ip.to_string(),
            port: *port,
        }
    }

    fn get_listener(&self) -> TcpListener {
        let addr: String = format!("{}:{}", self.ip, self.port);
        return TcpListener::bind(&*addr).unwrap();
    }
    pub fn run(&self) {
        run(self.get_listener());
    }

    pub fn start(&self) {
        let listener = self.get_listener();
        thread::spawn(move || {
            run(listener);
        });
    }

    pub fn stop(&self) {
        // TODO
    }

}

pub fn new_server(ip: &str, port: &i32) -> Server {
    return Server::new(ip, port);
}
<commit_msg>Fix test, collapse write code<commit_after>use std::net::{TcpListener, TcpStream};
use std::io::Read;
use std::io::Write;
use std::thread;

use super::parser::parse;
use super::parser::ParseError;

pub struct Client {
    pub stream: TcpStream
}

pub struct Server {
    pub ip: String,
    pub port: i32,
}

impl Client {
    pub fn new(stream: TcpStream) -> Client {
        return Client {
            stream: stream
        }
    }

    pub fn read(&mut self) {
        let mut buffer = [0u8; 512];
        loop {
            let result = self.stream.read(&mut buffer);
            if result.is_err() {
                break;
            }
            let len = result.unwrap();
            if len == 0 {
                break;
            }
            let try_parser = parse(&buffer, len);
            if try_parser.is_err() {
                let err = try_parser.unwrap_err();
                match err {
                    ParseError::BadProtocol => { break; }
                    ParseError::Incomplete => { continue; }
                };
            }
            let parser = try_parser.unwrap();
            if parser.argc == 1 && parser.get_str(0).unwrap() == "exit" {
                break;
            }
            if parser.argc == 2 && parser.get_str(0).unwrap() == "ping" {
                let response = parser.get_str(1).unwrap();
                let writeres = self.stream.write(&*format!("${}\r\n{}\r\n", response.len(), response).as_bytes());
                if writeres.is_err() {
                    break;
                }
                continue;
            }
            println!("{}", parser.argc);
            for i in 0..parser.argc {
                println!("{}", parser.get_str(i).unwrap())
            }
        };
    }
}

fn handle_client(stream: TcpStream) {
    thread::spawn(move || {
        let mut client = Client::new(stream);
        client.read();
    });
}

pub fn run(listener: TcpListener) {
    for stream in listener.incoming() {
        match stream {
            Ok(stream) => {
                handle_client(stream)
            }
            Err(e) => { println!("error {}", e); }
        }
    }
    drop(listener);
}

impl Server {
    pub fn new(ip: &str, port: &i32) -> Server {
        return Server {
            ip: ip.to_string(),
            port: *port,
        }
    }

    fn get_listener(&self) -> TcpListener {
        let addr: String = format!("{}:{}", self.ip, self.port);
        return TcpListener::bind(&*addr).unwrap();
    }
    pub fn run(&self) {
        run(self.get_listener());
    }

    pub fn start(&self) {
        let listener = self.get_listener();
        thread::spawn(move || {
            run(listener);
        });
    }

    pub fn stop(&self) {
        // TODO
    }

}

pub fn new_server(ip: &str, port: &i32) -> Server {
    return Server::new(ip, port);
}
<|endoftext|>


<commit_before>mod account;
mod metadata;
mod project;
mod report_req;
mod traits;
mod uri;

pub use self::account::*;
pub use self::project::*;
pub use self::report_req::*;
pub use self::traits::*;
pub use self::uri::*;
<commit_msg>pub mod metadata;<commit_after>mod account;
pub mod metadata;
mod project;
mod report_req;
mod traits;
mod uri;

pub use self::account::*;
pub use self::project::*;
pub use self::report_req::*;
pub use self::traits::*;
pub use self::uri::*;
<|endoftext|>


<commit_before>#[cfg(not(feature = "color"))]
use crate::util::termcolor::{Color, ColorChoice};
#[cfg(feature = "color")]
use termcolor::{Color, ColorChoice};

use std::{
    fmt::{self, Display, Formatter},
    io::{self, Write},
};

#[cfg(feature = "color")]
fn is_a_tty(stderr: bool) -> bool {
    debug!("is_a_tty: stderr={:?}", stderr);

    let stream = if stderr {
        atty::Stream::Stderr
    } else {
        atty::Stream::Stdout
    };

    atty::is(stream)
}

#[derive(Debug)]
pub(crate) struct Colorizer {
    use_stderr: bool,
    color_when: ColorChoice,
    pieces: Vec<(String, Option<Color>)>,
}

impl Colorizer {
    #[inline]
    pub(crate) fn new(use_stderr: bool, color_when: ColorChoice) -> Self {
        Colorizer {
            use_stderr,
            color_when,
            pieces: vec![],
        }
    }

    #[inline]
    pub(crate) fn good(&mut self, msg: impl Into<String>) {
        self.pieces.push((msg.into(), Some(Color::Green)));
    }

    #[inline]
    pub(crate) fn warning(&mut self, msg: impl Into<String>) {
        self.pieces.push((msg.into(), Some(Color::Yellow)));
    }

    #[inline]
    pub(crate) fn error(&mut self, msg: impl Into<String>) {
        self.pieces.push((msg.into(), Some(Color::Red)));
    }

    #[inline]
    pub(crate) fn none(&mut self, msg: impl Into<String>) {
        self.pieces.push((msg.into(), None));
    }
}

/// Printing methods.
impl Colorizer {
    #[cfg(feature = "color")]
    pub(crate) fn print(&self) -> io::Result<()> {
        use termcolor::{BufferWriter, ColorSpec, WriteColor};

        let color_when = if is_a_tty(self.use_stderr) {
            self.color_when
        } else {
            ColorChoice::Never
        };

        let writer = if self.use_stderr {
            BufferWriter::stderr(color_when)
        } else {
            BufferWriter::stdout(color_when)
        };

        let mut buffer = writer.buffer();

        for piece in &self.pieces {
            let mut color = ColorSpec::new();
            color.set_fg(piece.1);
            if piece.1 == Some(Color::Red) {
                color.set_bold(true);
            }

            buffer.set_color(&color)?;
            buffer.write_all(piece.0.as_bytes())?;
            buffer.reset()?;
        }

        writer.print(&buffer)
    }

    #[cfg(not(feature = "color"))]
    pub(crate) fn print(&self) -> io::Result<()> {
        // [e]println can't be used here because it panics
        // if something went wrong. We don't want that.
        if self.use_stderr {
            let stderr = std::io::stderr();
            let mut stderr = stderr.lock();
            write!(stderr, "{}", self)
        } else {
            let stdout = std::io::stdout();
            let mut stdout = stdout.lock();
            write!(stdout, "{}", self)
        }
    }
}

/// Color-unaware printing. Never uses coloring.
impl Display for Colorizer {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        for piece in &self.pieces {
            Display::fmt(&piece.0, f)?;
        }

        Ok(())
    }
}
<commit_msg>Make colorizer respect `ColorChoice::Always`<commit_after>#[cfg(not(feature = "color"))]
use crate::util::termcolor::{Color, ColorChoice};
#[cfg(feature = "color")]
use termcolor::{Color, ColorChoice};

use std::{
    fmt::{self, Display, Formatter},
    io::{self, Write},
};

#[cfg(feature = "color")]
fn is_a_tty(stderr: bool) -> bool {
    debug!("is_a_tty: stderr={:?}", stderr);

    let stream = if stderr {
        atty::Stream::Stderr
    } else {
        atty::Stream::Stdout
    };

    atty::is(stream)
}

#[derive(Debug)]
pub(crate) struct Colorizer {
    use_stderr: bool,
    color_when: ColorChoice,
    pieces: Vec<(String, Option<Color>)>,
}

impl Colorizer {
    #[inline]
    pub(crate) fn new(use_stderr: bool, color_when: ColorChoice) -> Self {
        Colorizer {
            use_stderr,
            color_when,
            pieces: vec![],
        }
    }

    #[inline]
    pub(crate) fn good(&mut self, msg: impl Into<String>) {
        self.pieces.push((msg.into(), Some(Color::Green)));
    }

    #[inline]
    pub(crate) fn warning(&mut self, msg: impl Into<String>) {
        self.pieces.push((msg.into(), Some(Color::Yellow)));
    }

    #[inline]
    pub(crate) fn error(&mut self, msg: impl Into<String>) {
        self.pieces.push((msg.into(), Some(Color::Red)));
    }

    #[inline]
    pub(crate) fn none(&mut self, msg: impl Into<String>) {
        self.pieces.push((msg.into(), None));
    }
}

/// Printing methods.
impl Colorizer {
    #[cfg(feature = "color")]
    pub(crate) fn print(&self) -> io::Result<()> {
        use termcolor::{BufferWriter, ColorSpec, WriteColor};

        let color_when = match self.color_when {
            always @ ColorChoice::Always => always,
            choice if is_a_tty(self.use_stderr) => choice,
            _ => ColorChoice::Never,
        };

        let writer = if self.use_stderr {
            BufferWriter::stderr(color_when)
        } else {
            BufferWriter::stdout(color_when)
        };

        let mut buffer = writer.buffer();

        for piece in &self.pieces {
            let mut color = ColorSpec::new();
            color.set_fg(piece.1);
            if piece.1 == Some(Color::Red) {
                color.set_bold(true);
            }

            buffer.set_color(&color)?;
            buffer.write_all(piece.0.as_bytes())?;
            buffer.reset()?;
        }

        writer.print(&buffer)
    }

    #[cfg(not(feature = "color"))]
    pub(crate) fn print(&self) -> io::Result<()> {
        // [e]println can't be used here because it panics
        // if something went wrong. We don't want that.
        if self.use_stderr {
            let stderr = std::io::stderr();
            let mut stderr = stderr.lock();
            write!(stderr, "{}", self)
        } else {
            let stdout = std::io::stdout();
            let mut stdout = stdout.lock();
            write!(stdout, "{}", self)
        }
    }
}

/// Color-unaware printing. Never uses coloring.
impl Display for Colorizer {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        for piece in &self.pieces {
            Display::fmt(&piece.0, f)?;
        }

        Ok(())
    }
}
<|endoftext|>