<commit_before>use std::collections::HashMap;
use std::convert::Into;

use crate::data::frame::ArcFrame;
use crate::data::packet::Packet;
use crate::data::params::CodecParams;
use crate::data::value::Value;

use crate::error::*;

/// Used to interact with an encoder.
pub trait Encoder: Send {
    /// Returns the extra data added by an encoder to a codec.
    fn get_extradata(&self) -> Option<Vec<u8>>;
    /// Sends to the encoder a frame to be encoded.
    fn send_frame(&mut self, pkt: &ArcFrame) -> Result<()>;
    /// Returns an encoded packet.
    fn receive_packet(&mut self) -> Result<Packet>;
    /// Tells encoder to clear its internal state.
    fn flush(&mut self) -> Result<()>;

    /// Configures the encoder.
    fn configure(&mut self) -> Result<()>;
    /// Sets an encoder option.
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
    // fn get_option(&mut self, key: &str) -> Option<Value>;
    //
    /// Sets the parameters associated to a determined codec.
    fn set_params(&mut self, params: &CodecParams) -> Result<()>;
    /// Gets the parameters associated to a determined codec.
    fn get_params(&self) -> Result<CodecParams>;
}

/// Auxiliary structure to encapsulate an encoder object and
/// its additional data.
pub struct Context {
    enc: Box<dyn Encoder>,
    // TODO: Queue up packets/frames
    // TODO: Store here more information
    // TODO: Have a resource pool
    // format: Format
}

impl Context {
    // TODO: More constructors
    /// Retrieves a codec descriptor from a codec list through its name,
    /// creates the relative encoder, and encapsulates it into a new `Context`.
    pub fn by_name(codecs: &Codecs, name: &str) -> Option<Context> {
        if let Some(builder) = codecs.by_name(name) {
            let enc = builder.create();
            Some(Context { enc })
        } else {
            None
        }
    }

    /// Configures the encoder.
    pub fn configure(&mut self) -> Result<()> {
        self.enc.configure()
    }

    /// Sets the parameters associated to a determined codec.
    pub fn set_params(&mut self, params: &CodecParams) -> Result<()> {
        self.enc.set_params(params)
    }

    /// Gets the parameters associated to a determined codec.
    pub fn get_params(&self) -> Result<CodecParams> {
        self.enc.get_params()
    }

    /// Sets an encoder option.
    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
    where
        V: Into<Value<'a>>,
    {
        // TODO: support more options
        self.enc.set_option(key, val.into())
    }

    /// Returns the extra data added by an encoder to a codec.
    pub fn get_extradata(&mut self) -> Option<Vec<u8>> {
        self.enc.get_extradata()
    }
    /// Sends to the encoder a frame to be encoded.
    pub fn send_frame(&mut self, frame: &ArcFrame) -> Result<()> {
        self.enc.send_frame(frame)
    }
    /// Returns an encoded packet.
    // TODO: Return an Event?
    pub fn receive_packet(&mut self) -> Result<Packet> {
        self.enc.receive_packet()
    }

    /// Tells encoder to clear its internal state.
    pub fn flush(&mut self) -> Result<()> {
        self.enc.flush()
    }
}

/// Codec descriptor.
///
/// Contains information on a codec and its own encoder.
#[derive(Debug)]
pub struct Descr {
    /// The codec name.
    pub codec: &'static str,
    /// The extended codec name.
    pub name: &'static str,
    /// The codec description.
    pub desc: &'static str,
    /// The codec MIME.
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

/// Used to get the descriptor of a codec and create its own encoder.
pub trait Descriptor {
    /// Creates a new encoder for the requested codec.
    fn create(&self) -> Box<dyn Encoder>;
    /// Returns the codec descriptor.
    fn describe(&self) -> &Descr;
}

/// A list of codec descriptors.
pub struct Codecs {
    list: HashMap<&'static str, Vec<&'static dyn Descriptor>>,
}

pub use crate::common::CodecList;

impl CodecList for Codecs {
    type D = dyn Descriptor;
    fn new() -> Codecs {
        Codecs {
            list: HashMap::new(),
        }
    }
    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static dyn Descriptor> {
        self.list.get(name).map(|descs| descs[0])
    }

    fn append(&mut self, desc: &'static dyn Descriptor) {
        let codec_name = desc.describe().codec;

        self.list
            .entry(codec_name)
            .or_insert_with(Vec::new)
            .push(desc);
    }
}

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

    mod dummy {
        use super::super::super::error::Error;
        use super::super::*;
        use crate::data::pixel::Formaton;
        use std::sync::Arc;

        struct Enc {
            state: usize,
            w: Option<usize>,
            h: Option<usize>,
            format: Option<Arc<Formaton>>,
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            fn create(&self) -> Box<dyn Encoder> {
                Box::new(Enc {
                    state: 0,
                    w: None,
                    h: None,
                    format: None,
                })
            }
            fn describe(&self) -> &Descr {
                &self.descr
            }
        }

        impl Encoder for Enc {
            fn configure(&mut self) -> Result<()> {
                if self.h.is_some() && self.w.is_some() && self.format.is_some() {
                    Ok(())
                } else {
                    Err(Error::ConfigurationIncomplete)
                }
            }
            fn get_extradata(&self) -> Option<Vec<u8>> {
                Some(vec![self.state as u8; 1])
            }
            fn send_frame(&mut self, _frame: &ArcFrame) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_packet(&mut self) -> Result<Packet> {
                let mut p = Packet::with_capacity(1);

                p.data.push(self.state as u8);

                Ok(p)
            }
            fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()> {
                match (key, val) {
                    ("w", Value::U64(v)) => self.w = Some(v as usize),
                    ("h", Value::U64(v)) => self.h = Some(v as usize),
                    ("format", Value::Formaton(f)) => self.format = Some(f),
                    _ => return Err(Error::Unsupported(format!("{} key", key))),
                }

                Ok(())
            }

            fn set_params(&mut self, params: &CodecParams) -> Result<()> {
                use crate::data::params::*;

                if let Some(MediaKind::Video(ref info)) = params.kind {
                    self.w = Some(info.width);
                    self.h = Some(info.height);
                    self.format = info.format.clone();
                }
                Ok(())
            }

            fn get_params(&self) -> Result<CodecParams> {
                use crate::data::params::*;

                if self.w.is_none() || self.w.is_none() || self.format.is_none() {
                    return Err(Error::ConfigurationIncomplete);
                }

                Ok(CodecParams {
                    kind: Some(MediaKind::Video(VideoInfo {
                        height: self.w.unwrap(),
                        width: self.h.unwrap(),
                        format: self.format.clone(),
                    })),
                    codec_id: Some("dummy".to_owned()),
                    extradata: self.get_extradata(),
                    bit_rate: 0,
                    convergence_window: 0,
                    delay: 0,
                })
            }

            fn flush(&mut self) -> Result<()> {
                Ok(())
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy encoder",
                mime: "x-application/dummy",
            },
        };
    }
    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _enc = codecs.by_name("dummy");
    }
}
<commit_msg>codec: Replace Box with generics for Encoder<commit_after>use std::collections::HashMap;
use std::convert::Into;

use crate::common::CodecList;
use crate::data::frame::ArcFrame;
use crate::data::packet::Packet;
use crate::data::params::CodecParams;
use crate::data::value::Value;

use crate::error::*;

/// Used to interact with an encoder.
pub trait Encoder: Send {
    /// Returns the extra data added by an encoder to a codec.
    fn get_extradata(&self) -> Option<Vec<u8>>;
    /// Sends to the encoder a frame to be encoded.
    fn send_frame(&mut self, pkt: &ArcFrame) -> Result<()>;
    /// Returns an encoded packet.
    fn receive_packet(&mut self) -> Result<Packet>;
    /// Tells encoder to clear its internal state.
    fn flush(&mut self) -> Result<()>;

    /// Configures the encoder.
    fn configure(&mut self) -> Result<()>;
    /// Sets an encoder option.
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
    // fn get_option(&mut self, key: &str) -> Option<Value>;
    //
    /// Sets the parameters associated to a determined codec.
    fn set_params(&mut self, params: &CodecParams) -> Result<()>;
    /// Gets the parameters associated to a determined codec.
    fn get_params(&self) -> Result<CodecParams>;
}

/// Auxiliary structure to encapsulate an encoder object and
/// its additional data.
pub struct Context<E: Encoder> {
    enc: E,
    // TODO: Queue up packets/frames
    // TODO: Store here more information
    // TODO: Have a resource pool
    // format: Format
}

impl<E: Encoder> Context<E> {
    // TODO: More constructors
    /// Retrieves a codec descriptor from a codec list through its name,
    /// creates the relative encoder, and encapsulates it into a new `Context`.
    pub fn by_name<T: Descriptor<OutputEncoder = E> + ?Sized>(
        codecs: &Codecs<T>,
        name: &str,
    ) -> Option<Self> {
        if let Some(builder) = codecs.by_name(name) {
            let enc = builder.create();
            Some(Context { enc })
        } else {
            None
        }
    }

    /// Configures the encoder.
    pub fn configure(&mut self) -> Result<()> {
        self.enc.configure()
    }

    /// Sets the parameters associated to a determined codec.
    pub fn set_params(&mut self, params: &CodecParams) -> Result<()> {
        self.enc.set_params(params)
    }

    /// Gets the parameters associated to a determined codec.
    pub fn get_params(&self) -> Result<CodecParams> {
        self.enc.get_params()
    }

    /// Sets an encoder option.
    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
    where
        V: Into<Value<'a>>,
    {
        // TODO: support more options
        self.enc.set_option(key, val.into())
    }

    /// Returns the extra data added by an encoder to a codec.
    pub fn get_extradata(&mut self) -> Option<Vec<u8>> {
        self.enc.get_extradata()
    }
    /// Sends to the encoder a frame to be encoded.
    pub fn send_frame(&mut self, frame: &ArcFrame) -> Result<()> {
        self.enc.send_frame(frame)
    }
    /// Returns an encoded packet.
    // TODO: Return an Event?
    pub fn receive_packet(&mut self) -> Result<Packet> {
        self.enc.receive_packet()
    }

    /// Tells encoder to clear its internal state.
    pub fn flush(&mut self) -> Result<()> {
        self.enc.flush()
    }
}

/// Codec descriptor.
///
/// Contains information on a codec and its own encoder.
#[derive(Debug)]
pub struct Descr {
    /// The codec name.
    pub codec: &'static str,
    /// The extended codec name.
    pub name: &'static str,
    /// The codec description.
    pub desc: &'static str,
    /// The codec MIME.
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

/// Used to get the descriptor of a codec and create its own encoder.
pub trait Descriptor {
    type OutputEncoder: Encoder;

    /// Creates a new encoder for the requested codec.
    fn create(&self) -> Self::OutputEncoder;
    /// Returns the codec descriptor.
    fn describe(&self) -> &Descr;
}

/// A list of codec descriptors.
pub struct Codecs<T: 'static + Descriptor + ?Sized> {
    list: HashMap<&'static str, Vec<&'static T>>,
}

impl<T: Descriptor + ?Sized> CodecList for Codecs<T> {
    type D = T;

    fn new() -> Self {
        Codecs {
            list: HashMap::new(),
        }
    }

    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Self::D> {
        self.list.get(name).map(|descs| descs[0])
    }

    fn append(&mut self, desc: &'static Self::D) {
        let codec_name = desc.describe().codec;

        self.list
            .entry(codec_name)
            .or_insert_with(Vec::new)
            .push(desc);
    }
}

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

    mod dummy {
        use super::super::*;
        use crate::data::pixel::Formaton;
        use std::sync::Arc;

        pub struct Enc {
            state: usize,
            w: Option<usize>,
            h: Option<usize>,
            format: Option<Arc<Formaton>>,
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            type OutputEncoder = Enc;

            fn create(&self) -> Self::OutputEncoder {
                Enc {
                    state: 0,
                    w: None,
                    h: None,
                    format: None,
                }
            }

            fn describe(&self) -> &Descr {
                &self.descr
            }
        }

        impl Encoder for Enc {
            fn configure(&mut self) -> Result<()> {
                if self.h.is_some() && self.w.is_some() && self.format.is_some() {
                    Ok(())
                } else {
                    Err(Error::ConfigurationIncomplete)
                }
            }
            fn get_extradata(&self) -> Option<Vec<u8>> {
                Some(vec![self.state as u8; 1])
            }
            fn send_frame(&mut self, _frame: &ArcFrame) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_packet(&mut self) -> Result<Packet> {
                let mut p = Packet::with_capacity(1);

                p.data.push(self.state as u8);

                Ok(p)
            }
            fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()> {
                match (key, val) {
                    ("w", Value::U64(v)) => self.w = Some(v as usize),
                    ("h", Value::U64(v)) => self.h = Some(v as usize),
                    ("format", Value::Formaton(f)) => self.format = Some(f),
                    _ => return Err(Error::Unsupported(format!("{} key", key))),
                }

                Ok(())
            }

            fn set_params(&mut self, params: &CodecParams) -> Result<()> {
                use crate::data::params::*;

                if let Some(MediaKind::Video(ref info)) = params.kind {
                    self.w = Some(info.width);
                    self.h = Some(info.height);
                    self.format = info.format.clone();
                }
                Ok(())
            }

            fn get_params(&self) -> Result<CodecParams> {
                use crate::data::params::*;

                if self.w.is_none() || self.w.is_none() || self.format.is_none() {
                    return Err(Error::ConfigurationIncomplete);
                }

                Ok(CodecParams {
                    kind: Some(MediaKind::Video(VideoInfo {
                        height: self.w.unwrap(),
                        width: self.h.unwrap(),
                        format: self.format.clone(),
                    })),
                    codec_id: Some("dummy".to_owned()),
                    extradata: self.get_extradata(),
                    bit_rate: 0,
                    convergence_window: 0,
                    delay: 0,
                })
            }

            fn flush(&mut self) -> Result<()> {
                Ok(())
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy encoder",
                mime: "x-application/dummy",
            },
        };
    }

    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _enc = codecs.by_name("dummy");
    }
}
<|endoftext|>


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

use crate::LigError;
use gaze::steps::{TakeString, TakeWhile};
use gaze::{Gaze, Step};
use ligature::{validate_identifier_characters, Attribute, Bytes, Entity, Statement, Value};

/// Reads an Entity from the given &str.
/// Will return an error if there is anything other than an Entity + whitespace in the input.
pub fn read_entity(input: &str) -> Result<Entity, LigError> {
    let mut gaze = Gaze::new(input.trim());
    let step = EntityStep();
    gaze.run(&step)
}

pub fn read_attribute(input: &str) -> Result<Attribute, LigError> {
    let mut gaze = Gaze::new(input.trim());
    let step = AttributeStep();
    gaze.run(&step)
}

/// Reads a value from a passed str.
/// Ignores white space but will return an Err if there is any input besides an encoded value.
pub fn read_value(input: &str) -> Result<Value, LigError> {
    let mut gaze = Gaze::new(input.trim());
    let step = ValueStep();
    gaze.run(&step)
}

pub fn read(input: &str) -> Result<Vec<Statement>, LigError> {
    todo!()
}

pub struct EntityStep();
impl Step<Entity, LigError> for EntityStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Entity, LigError> {
        gaze.run(&TakeString::new("<"))
            .map_err(|_| LigError("Could not read Entity.".into()))?;
        let res = gaze.run(&TakeWhile(&|c: &str| validate_identifier_characters(c)));
        gaze.run(&TakeString::new(">"))
            .map_err(|_| LigError("Could not read Entity.".into()))?;
        match res {
            Ok(st) => Ok(Entity::new(&st)?),
            Err(_) => Err(LigError("Couldn't parse Entity.".into())),
        }
    }
}

pub struct AttributeStep();
impl Step<Attribute, LigError> for AttributeStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Attribute, LigError> {
        gaze.run(&TakeString::new("@<"))
            .map_err(|_| LigError("Could not read Attribute.".into()))?;
        let res = gaze.run(&TakeWhile(&|c: &str| validate_identifier_characters(c)));
        gaze.run(&TakeString::new(">"))
            .map_err(|_| LigError("Could not read Attribute.".into()))?;
        match res {
            Ok(st) => Ok(Attribute::new(&st)?),
            Err(_) => Err(LigError("Couldn't parse Attribute.".into())),
        }
    }
}

pub struct ValueStep();
impl Step<Value, LigError> for ValueStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        let next_char = gaze.peek();
        return match next_char {
            None => Err(LigError("Could not match Value".into())),
            Some(c) => {
                if c == "<" {
                    Ok(Value::Entity(gaze.run(&EntityStep())?))
                } else if is_digit(&c) {
                    gaze.run(&NumberStep())
                } else if c == "\"" {
                    gaze.run(&StringStep())
                } else {
                    Err(LigError("Could not match Value".into()))
                }
            }
        };
    }
}

fn is_digit(s: &str) -> bool {
    s == "0"
        || s == "1"
        || s == "2"
        || s == "3"
        || s == "4"
        || s == "5"
        || s == "6"
        || s == "7"
        || s == "8"
        || s == "9"
}

pub struct NumberStep();
impl Step<Value, LigError> for NumberStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        let is_hex = gaze.run(&TakeString::new("0x"));
        match is_hex {
            Ok(_) => {
                return gaze.run(&HexStep());
            },
            Err(_) => {
                let integer = gaze.run(&IntegerStep())?;
                let is_float = gaze.run(&TakeString::new("."));
                match is_float {
                    Ok(_) => todo!(),
                    Err(_) => todo!(),
                }
                //if not read integer
                //then check for decimal point
                //handle float if decimal point exists
            },
        }
        todo!()
    }
}

pub struct HexStep();
impl Step<Value, LigError> for HexStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        todo!()
    }
}

pub struct IntegerStep();
impl Step<Value, LigError> for IntegerStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        todo!()
    }
}

pub struct BytesStep();
impl Step<Value, LigError> for BytesStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        todo!()
    }
}

pub struct StringStep();
impl Step<Value, LigError> for StringStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        todo!()
    }
}

pub struct StatementStep();
impl Step<Statement, LigError> for StatementStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Statement, LigError> {
        todo!()
    }
}
<commit_msg>adding first pass at token enum, #200<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use crate::LigError;
use gaze::steps::{TakeString, TakeWhile};
use gaze::{Gaze, Step};
use ligature::{validate_identifier_characters, Attribute, Bytes, Entity, Statement, Value};

enum LigToken {
    OpenAngle,
    CloseAngle,
    AtSign,
    Identifier(String),
    Whitespace,
    NewLine,
    DoubleQuote,
    StringContent(String),
    Integer(String),
    Dot,
}

/// Reads an Entity from the given &str.
/// Will return an error if there is anything other than an Entity + whitespace in the input.
pub fn read_entity(input: &str) -> Result<Entity, LigError> {
    let mut gaze = Gaze::new(input.trim());
    let step = EntityStep();
    gaze.run(&step)
}

pub fn read_attribute(input: &str) -> Result<Attribute, LigError> {
    let mut gaze = Gaze::new(input.trim());
    let step = AttributeStep();
    gaze.run(&step)
}

/// Reads a value from a passed str.
/// Ignores white space but will return an Err if there is any input besides an encoded value.
pub fn read_value(input: &str) -> Result<Value, LigError> {
    let mut gaze = Gaze::new(input.trim());
    let step = ValueStep();
    gaze.run(&step)
}

pub fn read(input: &str) -> Result<Vec<Statement>, LigError> {
    todo!()
}

pub struct EntityStep();
impl Step<Entity, LigError> for EntityStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Entity, LigError> {
        gaze.run(&TakeString::new("<"))
            .map_err(|_| LigError("Could not read Entity.".into()))?;
        let res = gaze.run(&TakeWhile(&|c: &str| validate_identifier_characters(c)));
        gaze.run(&TakeString::new(">"))
            .map_err(|_| LigError("Could not read Entity.".into()))?;
        match res {
            Ok(st) => Ok(Entity::new(&st)?),
            Err(_) => Err(LigError("Couldn't parse Entity.".into())),
        }
    }
}

pub struct AttributeStep();
impl Step<Attribute, LigError> for AttributeStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Attribute, LigError> {
        gaze.run(&TakeString::new("@<"))
            .map_err(|_| LigError("Could not read Attribute.".into()))?;
        let res = gaze.run(&TakeWhile(&|c: &str| validate_identifier_characters(c)));
        gaze.run(&TakeString::new(">"))
            .map_err(|_| LigError("Could not read Attribute.".into()))?;
        match res {
            Ok(st) => Ok(Attribute::new(&st)?),
            Err(_) => Err(LigError("Couldn't parse Attribute.".into())),
        }
    }
}

pub struct ValueStep();
impl Step<Value, LigError> for ValueStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        let next_char = gaze.peek();
        return match next_char {
            None => Err(LigError("Could not match Value".into())),
            Some(c) => {
                if c == "<" {
                    Ok(Value::Entity(gaze.run(&EntityStep())?))
                } else if is_digit(&c) {
                    gaze.run(&NumberStep())
                } else if c == "\"" {
                    gaze.run(&StringStep())
                } else {
                    Err(LigError("Could not match Value".into()))
                }
            }
        };
    }
}

fn is_digit(s: &str) -> bool {
    s == "0"
        || s == "1"
        || s == "2"
        || s == "3"
        || s == "4"
        || s == "5"
        || s == "6"
        || s == "7"
        || s == "8"
        || s == "9"
}

pub struct NumberStep();
impl Step<Value, LigError> for NumberStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        let is_hex = gaze.run(&TakeString::new("0x"));
        match is_hex {
            Ok(_) => {
                return gaze.run(&HexStep());
            },
            Err(_) => {
                let integer = gaze.run(&IntegerStep())?;
                let is_float = gaze.run(&TakeString::new("."));
                match is_float {
                    Ok(_) => todo!(),
                    Err(_) => todo!(),
                }
                //if not read integer
                //then check for decimal point
                //handle float if decimal point exists
            },
        }
        todo!()
    }
}

pub struct HexStep();
impl Step<Value, LigError> for HexStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        todo!()
    }
}

pub struct IntegerStep();
impl Step<Value, LigError> for IntegerStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        todo!()
    }
}

pub struct BytesStep();
impl Step<Value, LigError> for BytesStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        todo!()
    }
}

pub struct StringStep();
impl Step<Value, LigError> for StringStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Value, LigError> {
        todo!()
    }
}

pub struct StatementStep();
impl Step<Statement, LigError> for StatementStep {
    fn attempt(&self, gaze: &mut Gaze) -> Result<Statement, LigError> {
        todo!()
    }
}
<|endoftext|>


<commit_before>use definitions::config::VMConfig;
use definitions::interrupt::ExternalInterrupt;
use definitions::typedef::*;
use error::*;
use sdl2;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use std::sync::mpsc::{Receiver, Sender, TryRecvError};
use std::time::Instant;

pub fn start(frame_receiver: Receiver<Frame>, interrupt_sender: Sender<ExternalInterrupt>, config: VMConfig)
    -> VMResult<()> {
    let sdl_context = sdl2::init()?;
    let video_subsystem = sdl_context.video()?;

    let window = video_subsystem
        .window(
            config.title.as_ref(),
            (config.display.scale * (config.display.resolution.width as Float)).round() as u32,
            (config.display.scale * (config.display.resolution.height as Float)).round() as u32,
        )
        .position_centered()
        .build()
        .chain_err(|| "unable to build window")?;

    let mut canvas = window
        .into_canvas()
        .target_texture()
        .present_vsync()
        .build()
        .chain_err(|| "unable to convert window into canvas")?;

    canvas.set_scale(config.display.scale as f32, config.display.scale as f32)?;

    let mut event_pump = sdl_context.event_pump()?;
    let mut frame_count = 0;
    let mut now_before = Instant::now();

    'main: loop {
        // get the inputs here
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. } |
                Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    interrupt_sender
                        .send(
                            ExternalInterrupt {
                                signal_id: 0,
                                args: Vec::new(),
                            },
                        )
                        .chain_err(|| "unable to send interrupt")?;

                    break 'main;
                }
                _ => {
                    // TODO: Send interrupt here
                }
            }
        }

        // Receive a frame
        let maybe_frame = frame_receiver.try_recv();
        if let Ok(frame) = maybe_frame {

            let mut index = 0;
            for y_coord in 0..config.display.resolution.height {
                for x_coord in 0..config.display.resolution.width {
                    if let Some(&(r, g, b)) = frame.get(index) {
                        canvas.set_draw_color(Color::RGB(r, g, b));
                        canvas.draw_point((x_coord as i32, y_coord as i32))?;
                        index += 1;
                    } else {
                        bail!("no color point available at index {}", index);
                    }
                }
            }

            canvas.present();
        } else if let Err(TryRecvError::Disconnected) = maybe_frame {
            interrupt_sender
                .send(
                    ExternalInterrupt {
                        signal_id: 0,
                        args: Vec::new(),
                    },
                )
                .chain_err(|| "unable to send interrupt")?;

            break 'main;
        }

        if now_before.elapsed().as_secs() >= 1 {
            now_before = Instant::now();
            println!("FPS: {:?}", frame_count);
            frame_count = 0;
        }

        frame_count += 1;
    }

    Ok(())
}
<commit_msg>Slow down io thread when there is no load<commit_after>use definitions::config::VMConfig;
use definitions::interrupt::ExternalInterrupt;
use definitions::typedef::*;
use error::*;
use sdl2;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::Color;
use std::sync::mpsc::{Receiver, Sender, TryRecvError};
use std::thread;
use std::time::{Duration, Instant};

pub fn start(frame_receiver: Receiver<Frame>, interrupt_sender: Sender<ExternalInterrupt>, config: VMConfig)
    -> VMResult<()> {
    let sdl_context = sdl2::init()?;
    let video_subsystem = sdl_context.video()?;

    let window = video_subsystem
        .window(
            config.title.as_ref(),
            (config.display.scale * (config.display.resolution.width as Float)).round() as u32,
            (config.display.scale * (config.display.resolution.height as Float)).round() as u32,
        )
        .position_centered()
        .build()
        .chain_err(|| "unable to build window")?;

    let mut canvas = window
        .into_canvas()
        .target_texture()
        .present_vsync()
        .build()
        .chain_err(|| "unable to convert window into canvas")?;

    canvas.set_scale(config.display.scale as f32, config.display.scale as f32)?;

    let mut event_pump = sdl_context.event_pump()?;
    let mut frame_count = 0;
    let mut now_before = Instant::now();

    'main: loop {
        // get the inputs here
        for event in event_pump.poll_iter() {
            match event {
                Event::Quit { .. } |
                Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                    interrupt_sender
                        .send(
                            ExternalInterrupt {
                                signal_id: 0,
                                args: Vec::new(),
                            },
                        )
                        .chain_err(|| "unable to send interrupt")?;

                    break 'main;
                }
                _ => {
                    // TODO: Send interrupt here
                }
            }
        }

        // Receive a frame
        let maybe_frame = frame_receiver.try_recv();
        if let Ok(frame) = maybe_frame {

            let mut index = 0;
            for y_coord in 0..config.display.resolution.height {
                for x_coord in 0..config.display.resolution.width {
                    if let Some(&(r, g, b)) = frame.get(index) {
                        canvas.set_draw_color(Color::RGB(r, g, b));
                        canvas.draw_point((x_coord as i32, y_coord as i32))?;
                        index += 1;
                    } else {
                        bail!("no color point available at index {}", index);
                    }
                }
            }

            canvas.present();
        } else if let Err(TryRecvError::Disconnected) = maybe_frame {
            interrupt_sender
                .send(
                    ExternalInterrupt {
                        signal_id: 0,
                        args: Vec::new(),
                    },
                )
                .chain_err(|| "unable to send interrupt")?;

            break 'main;
        } else {
            thread::sleep(Duration::from_millis(1));
        }

        let secs_elapsed = now_before.elapsed().as_secs();

        if secs_elapsed >= 1 {
            println!("FPS: {:?}", frame_count / secs_elapsed);
            now_before = Instant::now();
            frame_count = 0;
        }

        frame_count += 1;
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::cmp::Ordering::*;
use std::ops::Not;

#[derive(Debug, Clone)]
pub struct BST<T> {
    nodes: Vec<Option<Node<T>>>,
    root: Option<Ptr>,
    deleted_indices: Vec<Ptr>
}

#[derive(Debug, Clone, Copy)]
struct Ptr(usize);

#[derive(Debug, Clone, Copy)]
enum Color {Red, Black}

#[derive(Debug, Clone)]
struct Node<T> {
    elem: T,
    color: Color,
    left: Option<Ptr>,
    right: Option<Ptr>,
}

impl<T: Ord> Node<T> {
    fn new(elem: T, color: Color) -> Self {
        Node { elem: elem, color: color, left: None, right: None }
    }
}

impl Not for Color {
    type Output = Color;
    fn not(self) -> Self {
        match self {
            Color::Red => Color::Black,
            Color::Black => Color::Red,
        }
    }
}

impl<T: Ord> BST<T> {
    fn deref(&self, i: &Ptr) -> &Node<T> {
        self.nodes[i.0].as_ref().expect("deref encounters a reference to a deleted node")
    }

    fn deref_mut(&mut self, i: &Ptr) -> &mut Node<T> {
        self.nodes[i.0].as_mut().expect("deref_mut encounters a reference to a deleted node")
    }

    pub fn new() -> Self {
        BST{ nodes: Vec::new(), root: None, deleted_indices: Vec::new() }
    }

    pub fn singleton(elem: T) -> Self {
        BST{ nodes: vec![Some(Node::new(elem, Color::Black))], root: Some(Ptr(0)), deleted_indices: Vec::new() }
    }

    fn member_impl(&self, ptr: &Option<Ptr>, elem: &T) -> bool {
        match *ptr {
            None => false,
            Some(ref ptr) => {
                let node = self.deref(ptr);
                match node.elem.cmp(elem) {
                    Less => self.member_impl(&node.right, elem),
                    Greater => self.member_impl(&node.left, elem),
                    Equal => true,
                }
            }
        }
    }

    pub fn member(&self, elem: &T) -> bool {
        self.member_impl(&self.root, elem)
    }

    fn is_red(&self, ptr: &Option<Ptr>) -> bool {
        ptr.as_ref().map_or(false, |p| if let Color::Red = self.deref(p).color { true } else { false })
    }

    fn rotate_left(&mut self, h: Ptr) -> Ptr {
        let x : Ptr = self.deref(&h).right.expect("rotate left on node whose left child is nil");
        self.deref_mut(&h).right = self.deref(&x).left;
        self.deref_mut(&x).left = Some(h);
        self.deref_mut(&x).color = self.deref(&h).color;
        self.deref_mut(&h).color = Color::Red;
        x
        // Note to self: the braces on the right of the assignment are to limit
        // the scope of the immutable borrow, because we are immediately
        // borrowing again mutably.
    }

    fn rotate_right(&mut self, h: Ptr) -> Ptr {
        let x : Ptr = self.deref(&h).left.expect("rotate right on node whose left child is nil");
        self.deref_mut(&h).left = self.deref(&x).right;
        self.deref_mut(&x).right = Some(h);
        self.deref_mut(&x).color = self.deref(&h).color;
        self.deref_mut(&h).color = Color::Red;
        x
    }

    fn move_red_up_or_down(&mut self, h: Ptr) {
        self.deref_mut(&h).color = !self.deref(&h).color;
        let left : Ptr = self.deref(&h).left.expect("move red up/down on node whose left child is nil");
        self.deref_mut(&left).color = !self.deref(&left).color;
        let right: Ptr = self.deref(&h).right.expect("move red up/down on node whose right child is nil");
        self.deref_mut(&right).color = !self.deref(&right).color;
    }

    fn fixup(&mut self, mut node: Ptr) -> Ptr {
        if self.is_red(&self.deref(&node).right) && !self.is_red(&self.deref(&node).left) {
            node = self.rotate_left(node);
        }
        if self.is_red(&self.deref(&node).left) && self.is_red(&self.deref(&self.deref(&node).left.unwrap()).left) {
            node = self.rotate_right(node);
        }
        if self.is_red(&self.deref(&node).left) && self.is_red(&self.deref(&node).right) {
            self.move_red_up_or_down(node);
        }
        node
    }

    fn insert_impl(&mut self, node: Option<Ptr>, elem: T) -> Ptr {
        match node {
            None => {
                let new = Some(Node::new(elem, Color::Red));
                if let Some(index) = self.deleted_indices.pop() {
                    self.nodes[index.0] = new;
                    index
                } else {
                    self.nodes.push(new);
                    Ptr(self.nodes.len() - 1)
                }
            },
            Some(node) => {
                match self.deref(&node).elem.cmp(&elem) {
                    Less => {
                        let right : Option<Ptr> = self.deref(&node).right;
                        let new_right : Ptr = self.insert_impl(right, elem);
                        self.deref_mut(&node).right = Some(new_right);
                    },
                    Greater => {
                        let left : Option<Ptr> = self.deref(&node).left;
                        let new_left : Ptr = self.insert_impl(left, elem);
                        self.deref_mut(&node).left = Some(new_left);
                    },
                    Equal => self.deref_mut(&node).elem = elem,
                }
                self.fixup(node)
            }
        }
    }

    pub fn insert(&mut self, elem: T) {
        let old_root : Option<Ptr> = self.root;
        let new_root : Ptr = self.insert_impl(old_root, elem);
        self.root = Some(new_root);
        self.deref_mut(&new_root).color = Color::Black;
    }

    pub fn clear(&mut self) {
        self.root = None;
        self.nodes.clear();
        self.deleted_indices.clear();
    }

    fn move_red_left(&mut self, mut h: Ptr) -> Ptr {
        self.move_red_up_or_down(h);
        if self.is_red(&self.deref(&self.deref(&h).right.unwrap()).left) {
            self.deref_mut(&h).right = self.deref(&h).right.map(|right| self.rotate_right(right));
            h = self.rotate_left(h);
            self.move_red_up_or_down(h);
        }
        h
    }

    fn take_min_impl(&mut self, mut node: Ptr) -> (T, Option<Ptr>) {
        match self.deref(&node).left {
            None => {
                // The current node is the minimum in the tree.
                self.deleted_indices.push(node);
                (self.nodes[node.0].take().expect("take_min_impl: leftmost node is already deleted").elem, None)
            },
            Some(left) => {
                // We need to make sure the next node is not a 2-node.
                // Making the next node not a 2-node means either it or
                // its left child is red (or both, in the case of a 4-node).
                // This checks if this is violated.
                if !self.is_red(&Some(left)) && !self.is_red(&self.deref(&left).left) {
                    node = self.move_red_left(node);
                }
                let left = self.deref_mut(&node).left.unwrap();
                let (min, new_left) = self.take_min_impl(left);
                self.deref_mut(&node).left = new_left;
                (min, Some(self.fixup(node)))
            }
        }
    }

    pub fn take_min(&mut self) -> Option<T> {
        self.root.and_then(
            |root|
            if self.deref(&root).left.is_none() {
                // The tree has only one element.
                let rv = self.nodes.swap_remove(root.0).map(|node| node.elem);
                self.root = None;
                self.deleted_indices.clear();
                self.nodes.clear();
                rv
            } else {
                // The tree has more than one element.
                let (min, new_root) = self.take_min_impl(root);
                self.root = new_root;
                self.deref_mut(&new_root.unwrap()).color = Color::Black;
                Some(min)
            })
    }

    fn print_structure_inner(&self, node: Option<Ptr>) {
        match node {
            None => print!("[missing]"),
            Some(node_id) => {
                print!("{{ node ");
                let node = self.deref(&node_id);
                if let Color::Red = node.color {
                    print!("[draw=red]");
                }
                print!("{{{:?}}} ", node_id.0); // Prints order of insertion
                if let Color::Red = node.color {
                    print!("edge from parent[red]");
                }
                print!(" child ");
                self.print_structure_inner(node.left);
                print!(" child ");
                self.print_structure_inner(node.right);
                print!(" }}");
            }
        }
    }

    pub fn print_structure(&self) {
        match self.root {
            None => (),
            Some(ref node_id) => {
                println!("%% Put these in your preamble\n\
                          \\usepackage{{tikz}}\n\
                          \\usetikzlibrary{{graphdrawing}}\n\
                          \\usegdlibrary{{trees}}\n\
                          \\definecolor{{red}}{{RGB}}{{171,50,37}}\n\n\
                          %% Put these in the document body\n\
                          \\tikz [binary tree layout, nodes={{draw,circle}}, font=\\sffamily, semithick] \
                          \\node");
                let node = self.deref(&node_id);
                print!("{{{:?}}} child ", node_id.0); // Prints order of insertion
                self.print_structure_inner(node.left);
                print!(" child ");
                self.print_structure_inner(node.right);
                println!(";");
            }
        }
    }
}

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

    #[test]
    fn basics() {
        let e: BST<i32> = BST::new();
        let s = BST::singleton(2);

        assert_eq!(false, e.member(&1));
        assert_eq!(false, e.member(&2));
        assert_eq!(false, e.member(&3));

        assert_eq!(false, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));
    }

    #[test]
    fn insertion() {
        let mut s = BST::singleton(2);
        s.insert(1);
        assert_eq!(true, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));

        s.insert(4);
        assert_eq!(true, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));
        assert_eq!(true, s.member(&4));

        {
            let mut thousand : BST<i32> = BST::new();
            for i in 0..1000 {
                thousand.insert(i);
            }
            for i in 0..1000 {
                assert_eq!(true, thousand.member(&i));
            }
            assert_eq!(false, thousand.member(&1000));
        }

        {
            let mut thousand : BST<i32> = BST::new();
            for i in 0..1000 {
                if i % 2 == 0 {
                    thousand.insert(i);
                }
            }
            for i in 0..1000 {
                assert_eq!(i % 2 == 0, thousand.member(&i));
            }
            for i in 0..1000 {
                if i % 2 == 1 {
                    thousand.insert(i);
                }
            }
            for i in 0..1000 {
                assert_eq!(true, thousand.member(&i));
            }
        }

        {
            let mut ex : BST<i32> = BST::new();
            for c in 0..64 {
                ex.insert(c);
                ex.print_structure();
                println!("");
            }
        }

        {
            let mut ex : BST<i32> = BST::new();
            let v: [i32; 20] = [14, 9, 12, 6, 2, 10, 1, 18, 16, 5, 8, 17, 13, 3, 11, 15, 7, 19, 4, 20];
            for c in &v {
                ex.insert(*c);
                ex.print_structure();
                println!("");
            }
        }
    }

    #[test]
    fn taking_minimum() {
        {
            let mut tree: BST<i32> = BST::new();
            tree.insert(2);
            tree.insert(3);
            tree.insert(5);
            assert_eq!(tree.take_min(), Some(2)); // [3,5]
            tree.insert(1);                       // [1,3,5]
            assert_eq!(tree.take_min(), Some(1)); // [3,5]
            assert_eq!(tree.take_min(), Some(3)); // [5]
            tree.insert(2);                       // [2,5]
            tree.insert(1);                       // [1,2,5]
            assert_eq!(tree.take_min(), Some(1));
            assert_eq!(tree.take_min(), Some(2));
            assert_eq!(tree.take_min(), Some(5));
            assert_eq!(tree.take_min(), None);
            println!("Passed: take_min for a manual test case with interleaved insertions and deletions")
        }

        {
            let mut tree : BST<i32> = BST::new();
            for size in 0..10 {
                for i in 0..size {
                    tree.insert(i);
                }
                for i in 0..size {
                    assert_eq!(tree.take_min(), Some(i));
                }
                assert_eq!(tree.take_min(), None);
                println!("Passed: take_min for tree with {} element(s)", size);
            }
        }
    }
}
<commit_msg>Remove an outdated comment<commit_after>use std::cmp::Ordering::*;
use std::ops::Not;

#[derive(Debug, Clone)]
pub struct BST<T> {
    nodes: Vec<Option<Node<T>>>,
    root: Option<Ptr>,
    deleted_indices: Vec<Ptr>
}

#[derive(Debug, Clone, Copy)]
struct Ptr(usize);

#[derive(Debug, Clone, Copy)]
enum Color {Red, Black}

#[derive(Debug, Clone)]
struct Node<T> {
    elem: T,
    color: Color,
    left: Option<Ptr>,
    right: Option<Ptr>,
}

impl<T: Ord> Node<T> {
    fn new(elem: T, color: Color) -> Self {
        Node { elem: elem, color: color, left: None, right: None }
    }
}

impl Not for Color {
    type Output = Color;
    fn not(self) -> Self {
        match self {
            Color::Red => Color::Black,
            Color::Black => Color::Red,
        }
    }
}

impl<T: Ord> BST<T> {
    fn deref(&self, i: &Ptr) -> &Node<T> {
        self.nodes[i.0].as_ref().expect("deref encounters a reference to a deleted node")
    }

    fn deref_mut(&mut self, i: &Ptr) -> &mut Node<T> {
        self.nodes[i.0].as_mut().expect("deref_mut encounters a reference to a deleted node")
    }

    pub fn new() -> Self {
        BST{ nodes: Vec::new(), root: None, deleted_indices: Vec::new() }
    }

    pub fn singleton(elem: T) -> Self {
        BST{ nodes: vec![Some(Node::new(elem, Color::Black))], root: Some(Ptr(0)), deleted_indices: Vec::new() }
    }

    fn member_impl(&self, ptr: &Option<Ptr>, elem: &T) -> bool {
        match *ptr {
            None => false,
            Some(ref ptr) => {
                let node = self.deref(ptr);
                match node.elem.cmp(elem) {
                    Less => self.member_impl(&node.right, elem),
                    Greater => self.member_impl(&node.left, elem),
                    Equal => true,
                }
            }
        }
    }

    pub fn member(&self, elem: &T) -> bool {
        self.member_impl(&self.root, elem)
    }

    fn is_red(&self, ptr: &Option<Ptr>) -> bool {
        ptr.as_ref().map_or(false, |p| if let Color::Red = self.deref(p).color { true } else { false })
    }

    fn rotate_left(&mut self, h: Ptr) -> Ptr {
        let x : Ptr = self.deref(&h).right.expect("rotate left on node whose left child is nil");
        self.deref_mut(&h).right = self.deref(&x).left;
        self.deref_mut(&x).left = Some(h);
        self.deref_mut(&x).color = self.deref(&h).color;
        self.deref_mut(&h).color = Color::Red;
        x
    }

    fn rotate_right(&mut self, h: Ptr) -> Ptr {
        let x : Ptr = self.deref(&h).left.expect("rotate right on node whose left child is nil");
        self.deref_mut(&h).left = self.deref(&x).right;
        self.deref_mut(&x).right = Some(h);
        self.deref_mut(&x).color = self.deref(&h).color;
        self.deref_mut(&h).color = Color::Red;
        x
    }

    fn move_red_up_or_down(&mut self, h: Ptr) {
        self.deref_mut(&h).color = !self.deref(&h).color;
        let left : Ptr = self.deref(&h).left.expect("move red up/down on node whose left child is nil");
        self.deref_mut(&left).color = !self.deref(&left).color;
        let right: Ptr = self.deref(&h).right.expect("move red up/down on node whose right child is nil");
        self.deref_mut(&right).color = !self.deref(&right).color;
    }

    fn fixup(&mut self, mut node: Ptr) -> Ptr {
        if self.is_red(&self.deref(&node).right) && !self.is_red(&self.deref(&node).left) {
            node = self.rotate_left(node);
        }
        if self.is_red(&self.deref(&node).left) && self.is_red(&self.deref(&self.deref(&node).left.unwrap()).left) {
            node = self.rotate_right(node);
        }
        if self.is_red(&self.deref(&node).left) && self.is_red(&self.deref(&node).right) {
            self.move_red_up_or_down(node);
        }
        node
    }

    fn insert_impl(&mut self, node: Option<Ptr>, elem: T) -> Ptr {
        match node {
            None => {
                let new = Some(Node::new(elem, Color::Red));
                if let Some(index) = self.deleted_indices.pop() {
                    self.nodes[index.0] = new;
                    index
                } else {
                    self.nodes.push(new);
                    Ptr(self.nodes.len() - 1)
                }
            },
            Some(node) => {
                match self.deref(&node).elem.cmp(&elem) {
                    Less => {
                        let right : Option<Ptr> = self.deref(&node).right;
                        let new_right : Ptr = self.insert_impl(right, elem);
                        self.deref_mut(&node).right = Some(new_right);
                    },
                    Greater => {
                        let left : Option<Ptr> = self.deref(&node).left;
                        let new_left : Ptr = self.insert_impl(left, elem);
                        self.deref_mut(&node).left = Some(new_left);
                    },
                    Equal => self.deref_mut(&node).elem = elem,
                }
                self.fixup(node)
            }
        }
    }

    pub fn insert(&mut self, elem: T) {
        let old_root : Option<Ptr> = self.root;
        let new_root : Ptr = self.insert_impl(old_root, elem);
        self.root = Some(new_root);
        self.deref_mut(&new_root).color = Color::Black;
    }

    pub fn clear(&mut self) {
        self.root = None;
        self.nodes.clear();
        self.deleted_indices.clear();
    }

    fn move_red_left(&mut self, mut h: Ptr) -> Ptr {
        self.move_red_up_or_down(h);
        if self.is_red(&self.deref(&self.deref(&h).right.unwrap()).left) {
            self.deref_mut(&h).right = self.deref(&h).right.map(|right| self.rotate_right(right));
            h = self.rotate_left(h);
            self.move_red_up_or_down(h);
        }
        h
    }

    fn take_min_impl(&mut self, mut node: Ptr) -> (T, Option<Ptr>) {
        match self.deref(&node).left {
            None => {
                // The current node is the minimum in the tree.
                self.deleted_indices.push(node);
                (self.nodes[node.0].take().expect("take_min_impl: leftmost node is already deleted").elem, None)
            },
            Some(left) => {
                // We need to make sure the next node is not a 2-node.
                // Making the next node not a 2-node means either it or
                // its left child is red (or both, in the case of a 4-node).
                // This checks if this is violated.
                if !self.is_red(&Some(left)) && !self.is_red(&self.deref(&left).left) {
                    node = self.move_red_left(node);
                }
                let left = self.deref_mut(&node).left.unwrap();
                let (min, new_left) = self.take_min_impl(left);
                self.deref_mut(&node).left = new_left;
                (min, Some(self.fixup(node)))
            }
        }
    }

    pub fn take_min(&mut self) -> Option<T> {
        self.root.and_then(
            |root|
            if self.deref(&root).left.is_none() {
                // The tree has only one element.
                let rv = self.nodes.swap_remove(root.0).map(|node| node.elem);
                self.root = None;
                self.deleted_indices.clear();
                self.nodes.clear();
                rv
            } else {
                // The tree has more than one element.
                let (min, new_root) = self.take_min_impl(root);
                self.root = new_root;
                self.deref_mut(&new_root.unwrap()).color = Color::Black;
                Some(min)
            })
    }

    fn print_structure_inner(&self, node: Option<Ptr>) {
        match node {
            None => print!("[missing]"),
            Some(node_id) => {
                print!("{{ node ");
                let node = self.deref(&node_id);
                if let Color::Red = node.color {
                    print!("[draw=red]");
                }
                print!("{{{:?}}} ", node_id.0); // Prints order of insertion
                if let Color::Red = node.color {
                    print!("edge from parent[red]");
                }
                print!(" child ");
                self.print_structure_inner(node.left);
                print!(" child ");
                self.print_structure_inner(node.right);
                print!(" }}");
            }
        }
    }

    pub fn print_structure(&self) {
        match self.root {
            None => (),
            Some(ref node_id) => {
                println!("%% Put these in your preamble\n\
                          \\usepackage{{tikz}}\n\
                          \\usetikzlibrary{{graphdrawing}}\n\
                          \\usegdlibrary{{trees}}\n\
                          \\definecolor{{red}}{{RGB}}{{171,50,37}}\n\n\
                          %% Put these in the document body\n\
                          \\tikz [binary tree layout, nodes={{draw,circle}}, font=\\sffamily, semithick] \
                          \\node");
                let node = self.deref(&node_id);
                print!("{{{:?}}} child ", node_id.0); // Prints order of insertion
                self.print_structure_inner(node.left);
                print!(" child ");
                self.print_structure_inner(node.right);
                println!(";");
            }
        }
    }
}

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

    #[test]
    fn basics() {
        let e: BST<i32> = BST::new();
        let s = BST::singleton(2);

        assert_eq!(false, e.member(&1));
        assert_eq!(false, e.member(&2));
        assert_eq!(false, e.member(&3));

        assert_eq!(false, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));
    }

    #[test]
    fn insertion() {
        let mut s = BST::singleton(2);
        s.insert(1);
        assert_eq!(true, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));

        s.insert(4);
        assert_eq!(true, s.member(&1));
        assert_eq!(true, s.member(&2));
        assert_eq!(false, s.member(&3));
        assert_eq!(true, s.member(&4));

        {
            let mut thousand : BST<i32> = BST::new();
            for i in 0..1000 {
                thousand.insert(i);
            }
            for i in 0..1000 {
                assert_eq!(true, thousand.member(&i));
            }
            assert_eq!(false, thousand.member(&1000));
        }

        {
            let mut thousand : BST<i32> = BST::new();
            for i in 0..1000 {
                if i % 2 == 0 {
                    thousand.insert(i);
                }
            }
            for i in 0..1000 {
                assert_eq!(i % 2 == 0, thousand.member(&i));
            }
            for i in 0..1000 {
                if i % 2 == 1 {
                    thousand.insert(i);
                }
            }
            for i in 0..1000 {
                assert_eq!(true, thousand.member(&i));
            }
        }

        {
            let mut ex : BST<i32> = BST::new();
            for c in 0..64 {
                ex.insert(c);
                ex.print_structure();
                println!("");
            }
        }

        {
            let mut ex : BST<i32> = BST::new();
            let v: [i32; 20] = [14, 9, 12, 6, 2, 10, 1, 18, 16, 5, 8, 17, 13, 3, 11, 15, 7, 19, 4, 20];
            for c in &v {
                ex.insert(*c);
                ex.print_structure();
                println!("");
            }
        }
    }

    #[test]
    fn taking_minimum() {
        {
            let mut tree: BST<i32> = BST::new();
            tree.insert(2);
            tree.insert(3);
            tree.insert(5);
            assert_eq!(tree.take_min(), Some(2)); // [3,5]
            tree.insert(1);                       // [1,3,5]
            assert_eq!(tree.take_min(), Some(1)); // [3,5]
            assert_eq!(tree.take_min(), Some(3)); // [5]
            tree.insert(2);                       // [2,5]
            tree.insert(1);                       // [1,2,5]
            assert_eq!(tree.take_min(), Some(1));
            assert_eq!(tree.take_min(), Some(2));
            assert_eq!(tree.take_min(), Some(5));
            assert_eq!(tree.take_min(), None);
            println!("Passed: take_min for a manual test case with interleaved insertions and deletions")
        }

        {
            let mut tree : BST<i32> = BST::new();
            for size in 0..10 {
                for i in 0..size {
                    tree.insert(i);
                }
                for i in 0..size {
                    assert_eq!(tree.take_min(), Some(i));
                }
                assert_eq!(tree.take_min(), None);
                println!("Passed: take_min for tree with {} element(s)", size);
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use num_format::{Locale, ToFormattedString};
use rand::{thread_rng, Rng};

#[cfg_attr(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        feature = "jemalloc",
    ),
    global_allocator
)]
#[cfg(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        feature = "jemalloc",
    ),
)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);

const USAGE: &str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential] \
    [--total-ops=<n>] \
    [--flush-every=<ms>]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 10].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 94].
    --set-prop=<p>     The relative proportion of set requests [default: 2].
    --del-prop=<p>     The relative proportion of del requests [default: 1].
    --cas-prop=<p>     The relative proportion of cas requests [default: 1].
    --scan-prop=<p>    The relative proportion of scan requests [default: 1].
    --merge-prop=<p>   The relative proportion of merge requests [default: 1].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random.
    --total-ops=<n>    Stop test after executing a total number of operations.
    --flush-every=<m>  Flush and sync the database every ms [default: 200].
";

#[derive(Clone, Copy)]
struct Args {
    threads: usize,
    burn_in: bool,
    duration: u64,
    key_len: usize,
    val_len: usize,
    get_prop: usize,
    set_prop: usize,
    del_prop: usize,
    cas_prop: usize,
    scan_prop: usize,
    merge_prop: usize,
    entries: usize,
    sequential: bool,
    total_ops: Option<usize>,
    flush_every: u64,
}

impl Default for Args {
    fn default() -> Args {
        Args {
            threads: 4,
            burn_in: false,
            duration: 10,
            key_len: 10,
            val_len: 100,
            get_prop: 94,
            set_prop: 2,
            del_prop: 1,
            cas_prop: 1,
            scan_prop: 1,
            merge_prop: 1,
            entries: 100000,
            sequential: false,
            total_ops: None,
            flush_every: 200,
        }
    }
}

fn parse<'a, I, T>(mut iter: I) -> T
where
    I: Iterator<Item = &'a str>,
    T: std::str::FromStr,
    <T as std::str::FromStr>::Err: std::fmt::Debug,
{
    iter.next().expect(USAGE).parse().expect(USAGE)
}

impl Args {
    fn parse() -> Args {
        let mut args = Args::default();
        for raw_arg in std::env::args().skip(1) {
            let mut splits = raw_arg[2..].split('=');
            match splits.next().unwrap() {
                "threads" => args.threads = parse(&mut splits),
                "burn-in" => args.burn_in = true,
                "duration" => args.duration = parse(&mut splits),
                "key-len" => args.key_len = parse(&mut splits),
                "val-len" => args.val_len = parse(&mut splits),
                "get-prop" => args.get_prop = parse(&mut splits),
                "set-prop" => args.set_prop = parse(&mut splits),
                "del-prop" => args.del_prop = parse(&mut splits),
                "cas-prop" => args.cas_prop = parse(&mut splits),
                "scan-prop" => args.scan_prop = parse(&mut splits),
                "merge-prop" => args.merge_prop = parse(&mut splits),
                "entries" => args.entries = parse(&mut splits),
                "sequential" => args.sequential = true,
                "total-ops" => args.total_ops = Some(parse(&mut splits)),
                "flush-every" => args.flush_every = parse(&mut splits),
                other => panic!("unknown option: {}, {}", other, USAGE),
            }
        }
        args
    }
}

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!(
            "did {} ops, {}mb RSS",
            (total - last).to_formatted_string(&Locale::en),
            rss() / (1024 * 1024)
        );

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret = old_value.map(|ov| ov.to_vec()).unwrap_or_else(Vec::new);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(args: Args, tree: Arc<sled::Db>, shutdown: Arc<AtomicBool>) {
    let get_max = args.get_prop;
    let set_max = get_max + args.set_prop;
    let del_max = set_max + args.del_prop;
    let cas_max = del_max + args.cas_prop;
    let merge_max = cas_max + args.merge_prop;
    let scan_max = merge_max + args.scan_prop;

    let keygen = |len| -> sled::IVec {
        static SEQ: AtomicUsize = AtomicUsize::new(0);
        let i = if args.sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.entries;

        let start = if len < 8 { 8 - len } else { 0 };

        let i_keygen = &i.to_be_bytes()[start..];

        i_keygen.iter().cycle().take(len).copied().collect()
    };

    let valgen = |len| -> sled::IVec {
        if len == 0 {
            return vec![].into();
        }

        let i: usize = thread_rng().gen::<usize>() % (len * 8);

        let i_keygen = i.to_be_bytes();

        i_keygen
            .iter()
            .skip_while(|v| **v == 0)
            .cycle()
            .take(len)
            .copied()
            .collect()
    };

    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        let op = TOTAL.fetch_add(1, Ordering::Release);
        let key = keygen(args.key_len);
        let choice = rng.gen_range(0, scan_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get_zero_copy(&key, |_| {}).unwrap();
            }
            v if v > get_max && v <= set_max => {
                let value = valgen(args.val_len);
                tree.insert(&key, value).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.remove(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old = if rng.gen::<bool>() {
                    let value = valgen(args.val_len);
                    Some(value)
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    let value = valgen(args.val_len);
                    Some(value)
                } else {
                    None
                };

                if let Err(e) = tree.compare_and_swap(&key, old, new) {
                    panic!("operational error: {:?}", e);
                }
            }
            v if v > cas_max && v <= merge_max => {
                let value = valgen(args.val_len);
                tree.merge(&key, value).unwrap();
            }
            _ => {
                let iter = tree.range(key..).map(|res| res.unwrap());

                if op % 2 == 0 {
                    let _ = iter.take(rng.gen_range(0, 15)).collect::<Vec<_>>();
                } else {
                    let _ = iter
                        .rev()
                        .take(rng.gen_range(0, 15))
                        .collect::<Vec<_>>();
                }
            }
        }
    }
}

fn rss() -> usize {
    #[cfg(target_os = "linux")]
    {
        use std::io::prelude::*;
        use std::io::BufReader;

        let mut buf = String::new();
        let mut f =
            BufReader::new(std::fs::File::open("/proc/self/statm").unwrap());
        f.read_line(&mut buf).unwrap();
        let mut parts = buf.split_whitespace();
        let rss_pages = parts.nth(1).unwrap().parse::<usize>().unwrap();
        rss_pages * 4096
    }
    #[cfg(not(target_os = "linux"))]
    {
        0
    }
}

fn main() {
    #[cfg(feature = "logging")]
    setup_logger();

    let args = Args::parse();

    let shutdown = Arc::new(AtomicBool::new(false));

    let config = sled::Config::new()
        .cache_capacity(256 * 1024 * 1024)
        .flush_every_ms(Some(args.flush_every));

    let tree = Arc::new(config.open().unwrap());
    tree.set_merge_operator(concatenate_merge);

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.threads;

    for i in 0..=n_threads {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::Builder::new()
                .name("reporter".into())
                .spawn(move || report(shutdown))
                .unwrap()
        } else {
            thread::spawn(move || run(args, tree, shutdown))
        };

        threads.push(t);
    }

    if let Some(ops) = args.total_ops {
        assert!(!args.burn_in, "don't set both --burn-in and --total-ops");
        while TOTAL.load(Ordering::Relaxed) < ops {
            thread::sleep(std::time::Duration::from_millis(50));
        }
        shutdown.store(true, Ordering::SeqCst);
    } else if !args.burn_in {
        thread::sleep(std::time::Duration::from_secs(args.duration));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }
    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops.to_formatted_string(&Locale::en),
        time,
        ((ops * 1_000) / (time * 1_000)).to_formatted_string(&Locale::en)
    );

    #[cfg(feature = "metrics")]
    sled::print_profile();
}

#[cfg(feature = "logging")]
pub fn setup_logger() {
    use std::io::Write;

    color_backtrace::install();

    fn tn() -> String {
        std::thread::current().name().unwrap_or("unknown").to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record.module_path().unwrap().split("::").last().unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if let Ok(env) = std::env::var("RUST_LOG") {
        builder.parse_filters(&env);
    }

    let _r = builder.try_init();
}
<commit_msg>If stress2 flush-every argument is 0, disable flusher thread<commit_after>use std::{
    sync::{
        atomic::{AtomicBool, AtomicUsize, Ordering},
        Arc,
    },
    thread,
};

use num_format::{Locale, ToFormattedString};
use rand::{thread_rng, Rng};

#[cfg_attr(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        feature = "jemalloc",
    ),
    global_allocator
)]
#[cfg(
    // only enable jemalloc on linux and macos by default
    all(
        any(target_os = "linux", target_os = "macos"),
        feature = "jemalloc",
    ),
)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

static TOTAL: AtomicUsize = AtomicUsize::new(0);

const USAGE: &str = "
Usage: stress [--threads=<#>] [--burn-in] [--duration=<s>] \
    [--key-len=<l>] [--val-len=<l>] \
    [--get-prop=<p>] \
    [--set-prop=<p>] \
    [--del-prop=<p>] \
    [--cas-prop=<p>] \
    [--scan-prop=<p>] \
    [--merge-prop=<p>] \
    [--entries=<n>] \
    [--sequential] \
    [--total-ops=<n>] \
    [--flush-every=<ms>]

Options:
    --threads=<#>      Number of threads [default: 4].
    --burn-in          Don't halt until we receive a signal.
    --duration=<s>     Seconds to run for [default: 10].
    --key-len=<l>      The length of keys [default: 10].
    --val-len=<l>      The length of values [default: 100].
    --get-prop=<p>     The relative proportion of get requests [default: 94].
    --set-prop=<p>     The relative proportion of set requests [default: 2].
    --del-prop=<p>     The relative proportion of del requests [default: 1].
    --cas-prop=<p>     The relative proportion of cas requests [default: 1].
    --scan-prop=<p>    The relative proportion of scan requests [default: 1].
    --merge-prop=<p>   The relative proportion of merge requests [default: 1].
    --entries=<n>      The total keyspace [default: 100000].
    --sequential       Run the test in sequential mode instead of random.
    --total-ops=<n>    Stop test after executing a total number of operations.
    --flush-every=<m>  Flush and sync the database every ms [default: 200].
";

#[derive(Clone, Copy)]
struct Args {
    threads: usize,
    burn_in: bool,
    duration: u64,
    key_len: usize,
    val_len: usize,
    get_prop: usize,
    set_prop: usize,
    del_prop: usize,
    cas_prop: usize,
    scan_prop: usize,
    merge_prop: usize,
    entries: usize,
    sequential: bool,
    total_ops: Option<usize>,
    flush_every: u64,
}

impl Default for Args {
    fn default() -> Args {
        Args {
            threads: 4,
            burn_in: false,
            duration: 10,
            key_len: 10,
            val_len: 100,
            get_prop: 94,
            set_prop: 2,
            del_prop: 1,
            cas_prop: 1,
            scan_prop: 1,
            merge_prop: 1,
            entries: 100000,
            sequential: false,
            total_ops: None,
            flush_every: 200,
        }
    }
}

fn parse<'a, I, T>(mut iter: I) -> T
where
    I: Iterator<Item = &'a str>,
    T: std::str::FromStr,
    <T as std::str::FromStr>::Err: std::fmt::Debug,
{
    iter.next().expect(USAGE).parse().expect(USAGE)
}

impl Args {
    fn parse() -> Args {
        let mut args = Args::default();
        for raw_arg in std::env::args().skip(1) {
            let mut splits = raw_arg[2..].split('=');
            match splits.next().unwrap() {
                "threads" => args.threads = parse(&mut splits),
                "burn-in" => args.burn_in = true,
                "duration" => args.duration = parse(&mut splits),
                "key-len" => args.key_len = parse(&mut splits),
                "val-len" => args.val_len = parse(&mut splits),
                "get-prop" => args.get_prop = parse(&mut splits),
                "set-prop" => args.set_prop = parse(&mut splits),
                "del-prop" => args.del_prop = parse(&mut splits),
                "cas-prop" => args.cas_prop = parse(&mut splits),
                "scan-prop" => args.scan_prop = parse(&mut splits),
                "merge-prop" => args.merge_prop = parse(&mut splits),
                "entries" => args.entries = parse(&mut splits),
                "sequential" => args.sequential = true,
                "total-ops" => args.total_ops = Some(parse(&mut splits)),
                "flush-every" => args.flush_every = parse(&mut splits),
                other => panic!("unknown option: {}, {}", other, USAGE),
            }
        }
        args
    }
}

fn report(shutdown: Arc<AtomicBool>) {
    let mut last = 0;
    while !shutdown.load(Ordering::Relaxed) {
        thread::sleep(std::time::Duration::from_secs(1));
        let total = TOTAL.load(Ordering::Acquire);

        println!(
            "did {} ops, {}mb RSS",
            (total - last).to_formatted_string(&Locale::en),
            rss() / (1024 * 1024)
        );

        last = total;
    }
}

fn concatenate_merge(
    _key: &[u8],              // the key being merged
    old_value: Option<&[u8]>, // the previous value, if one existed
    merged_bytes: &[u8],      // the new bytes being merged in
) -> Option<Vec<u8>> {
    // set the new value, return None to delete
    let mut ret = old_value.map(|ov| ov.to_vec()).unwrap_or_else(Vec::new);

    ret.extend_from_slice(merged_bytes);

    Some(ret)
}

fn run(args: Args, tree: Arc<sled::Db>, shutdown: Arc<AtomicBool>) {
    let get_max = args.get_prop;
    let set_max = get_max + args.set_prop;
    let del_max = set_max + args.del_prop;
    let cas_max = del_max + args.cas_prop;
    let merge_max = cas_max + args.merge_prop;
    let scan_max = merge_max + args.scan_prop;

    let keygen = |len| -> sled::IVec {
        static SEQ: AtomicUsize = AtomicUsize::new(0);
        let i = if args.sequential {
            SEQ.fetch_add(1, Ordering::Relaxed)
        } else {
            thread_rng().gen::<usize>()
        } % args.entries;

        let start = if len < 8 { 8 - len } else { 0 };

        let i_keygen = &i.to_be_bytes()[start..];

        i_keygen.iter().cycle().take(len).copied().collect()
    };

    let valgen = |len| -> sled::IVec {
        if len == 0 {
            return vec![].into();
        }

        let i: usize = thread_rng().gen::<usize>() % (len * 8);

        let i_keygen = i.to_be_bytes();

        i_keygen
            .iter()
            .skip_while(|v| **v == 0)
            .cycle()
            .take(len)
            .copied()
            .collect()
    };

    let mut rng = thread_rng();

    while !shutdown.load(Ordering::Relaxed) {
        let op = TOTAL.fetch_add(1, Ordering::Release);
        let key = keygen(args.key_len);
        let choice = rng.gen_range(0, scan_max + 1);

        match choice {
            v if v <= get_max => {
                tree.get_zero_copy(&key, |_| {}).unwrap();
            }
            v if v > get_max && v <= set_max => {
                let value = valgen(args.val_len);
                tree.insert(&key, value).unwrap();
            }
            v if v > set_max && v <= del_max => {
                tree.remove(&key).unwrap();
            }
            v if v > del_max && v <= cas_max => {
                let old = if rng.gen::<bool>() {
                    let value = valgen(args.val_len);
                    Some(value)
                } else {
                    None
                };

                let new = if rng.gen::<bool>() {
                    let value = valgen(args.val_len);
                    Some(value)
                } else {
                    None
                };

                if let Err(e) = tree.compare_and_swap(&key, old, new) {
                    panic!("operational error: {:?}", e);
                }
            }
            v if v > cas_max && v <= merge_max => {
                let value = valgen(args.val_len);
                tree.merge(&key, value).unwrap();
            }
            _ => {
                let iter = tree.range(key..).map(|res| res.unwrap());

                if op % 2 == 0 {
                    let _ = iter.take(rng.gen_range(0, 15)).collect::<Vec<_>>();
                } else {
                    let _ = iter
                        .rev()
                        .take(rng.gen_range(0, 15))
                        .collect::<Vec<_>>();
                }
            }
        }
    }
}

fn rss() -> usize {
    #[cfg(target_os = "linux")]
    {
        use std::io::prelude::*;
        use std::io::BufReader;

        let mut buf = String::new();
        let mut f =
            BufReader::new(std::fs::File::open("/proc/self/statm").unwrap());
        f.read_line(&mut buf).unwrap();
        let mut parts = buf.split_whitespace();
        let rss_pages = parts.nth(1).unwrap().parse::<usize>().unwrap();
        rss_pages * 4096
    }
    #[cfg(not(target_os = "linux"))]
    {
        0
    }
}

fn main() {
    #[cfg(feature = "logging")]
    setup_logger();

    let args = Args::parse();

    let shutdown = Arc::new(AtomicBool::new(false));

    let config =
        sled::Config::new().cache_capacity(256 * 1024 * 1024).flush_every_ms(
            if args.flush_every == 0 { None } else { Some(args.flush_every) },
        );

    let tree = Arc::new(config.open().unwrap());
    tree.set_merge_operator(concatenate_merge);

    let mut threads = vec![];

    let now = std::time::Instant::now();

    let n_threads = args.threads;

    for i in 0..=n_threads {
        let tree = tree.clone();
        let shutdown = shutdown.clone();

        let t = if i == 0 {
            thread::Builder::new()
                .name("reporter".into())
                .spawn(move || report(shutdown))
                .unwrap()
        } else {
            thread::spawn(move || run(args, tree, shutdown))
        };

        threads.push(t);
    }

    if let Some(ops) = args.total_ops {
        assert!(!args.burn_in, "don't set both --burn-in and --total-ops");
        while TOTAL.load(Ordering::Relaxed) < ops {
            thread::sleep(std::time::Duration::from_millis(50));
        }
        shutdown.store(true, Ordering::SeqCst);
    } else if !args.burn_in {
        thread::sleep(std::time::Duration::from_secs(args.duration));
        shutdown.store(true, Ordering::SeqCst);
    }

    for t in threads.into_iter() {
        t.join().unwrap();
    }
    let ops = TOTAL.load(Ordering::SeqCst);
    let time = now.elapsed().as_secs() as usize;

    println!(
        "did {} total ops in {} seconds. {} ops/s",
        ops.to_formatted_string(&Locale::en),
        time,
        ((ops * 1_000) / (time * 1_000)).to_formatted_string(&Locale::en)
    );

    #[cfg(feature = "metrics")]
    sled::print_profile();
}

#[cfg(feature = "logging")]
pub fn setup_logger() {
    use std::io::Write;

    color_backtrace::install();

    fn tn() -> String {
        std::thread::current().name().unwrap_or("unknown").to_owned()
    }

    let mut builder = env_logger::Builder::new();
    builder
        .format(|buf, record| {
            writeln!(
                buf,
                "{:05} {:25} {:10} {}",
                record.level(),
                tn(),
                record.module_path().unwrap().split("::").last().unwrap(),
                record.args()
            )
        })
        .filter(None, log::LevelFilter::Info);

    if let Ok(env) = std::env::var("RUST_LOG") {
        builder.parse_filters(&env);
    }

    let _r = builder.try_init();
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;

extern crate futures;
extern crate tokio_core;

use std::thread;
use std::sync::mpsc::channel;
//use futures::stream::Stream;
//use tokio_core::reactor::Core;
//use tokio_core::net::TcpListener;
use std::net::TcpListener;
use std::collections::HashMap;
use std::io::Write;
//use futures::Future;
use std::sync::{Arc, Mutex};

mod userchannel;
mod messaging;

fn main() {
    let address = "127.0.0.1:8080";
    let listener = TcpListener::bind(&address).unwrap();
    let mut cnt = 0;

    let addr = listener.local_addr().unwrap();
    println!("Listening for connections on {}", addr);
    let (tx, rx) = channel();

    let mut channel_db = userchannel::ChannelDb{ channelname: "Rust".to_string(), users: HashMap::new(), values: Vec::new() };

    for socket in listener.incoming() {
        let mut thr_feed;
        cnt += 1;
        if(1 == cnt) {
            let tx = tx.clone();
            thread::spawn(move|| {
                let (thr_tx, thr_rx) = channel();
                println!("Spawned: Sending socket");
                loop {
                    tx.send(thr_tx.clone()).unwrap();
                    let mut thr_sock: std::net::TcpStream = thr_rx.recv().unwrap();
                    println!("Got thr sock");
                    thr_sock.write(b"Hello World\r\n").unwrap();
                }
            });
        }
        thr_feed = rx.recv().unwrap();
        println!("Got thr_feed");
        thr_feed.send(socket.unwrap()).unwrap();
    }
}
<commit_msg>Remove dependency of main and channel-thread channels.<commit_after>#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;

extern crate futures;
extern crate tokio_core;

use std::thread;
use std::sync::mpsc::channel;
//use futures::stream::Stream;
//use tokio_core::reactor::Core;
//use tokio_core::net::TcpListener;
use std::net::TcpListener;
use std::collections::HashMap;
use std::io::Write;
//use futures::Future;
use std::sync::{Arc, Mutex};

mod userchannel;
mod messaging;

fn main() {
    let address = "127.0.0.1:8080";
    let listener = TcpListener::bind(&address).unwrap();
    let mut spawned = HashMap::new();
    let mut cnt = 0;

    let addr = listener.local_addr().unwrap();
    println!("Listening for connections on {}", addr);
    let (tx, rx) = channel();

    for socket in listener.incoming() {
        /* 1. Read incoming msg channel
         * 2. If it does not exist, spawn new thread
         * 3. Send socket to thread
         */
        cnt += 1;
        if(1 == cnt) {
            let tx = tx.clone();
            thread::spawn(move|| {
                let (thr_tx, thr_rx) = channel();
                println!("Spawned: Sending socket");

                let mut channel_db = userchannel::ChannelDb{ channelname: "Rust".to_string(), users: HashMap::new(), values: Vec::new() };

                tx.send(thr_tx.clone()).unwrap();
                loop {
                    let mut thr_sock: std::net::TcpStream = thr_rx.recv().unwrap();
                    println!("Got thr sock");
                    thr_sock.write(b"Hello World\r\n").unwrap();
                }
            });
            let thr_feed = rx.recv().unwrap();
            println!("Got thr_feed");
            thr_feed.send(socket.unwrap()).unwrap();
            spawned.insert("Channel", thr_feed);
            continue;
        }
        let thr_socket = spawned.get_mut("Channel").unwrap();
        thr_socket.send(socket.unwrap()).unwrap();
    }
}
<|endoftext|>


<commit_before><commit_msg>grnenv-docopen: Add settings for windows<commit_after><|endoftext|>


<commit_before>use std::env;
use std::fs;
use std::process;

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::{Client, Url};
use kuchiki;

use extractor;
use downloader;
use profile;
use config::Config;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    fs::create_dir_all(&config.versions_dir).expect("Could not create versions directory.");
    if !env::home_dir()
        .unwrap_or_else(|| panic!("Cound not found homedir."))
        .join("Documents")
        .join("WindowsPowerShell")
        .join("profile.ps1")
        .exists() {
        println!(r#"Please create profile.ps1 the following place:

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

And write the following thing:

. $Env:USERPROFILE\.groonga\shims\bin\source-groonga.ps1
"#)
    }
}

pub fn install(m: &ArgMatches) {
    extern crate env_proxy;

    const BASE_URL: &'static str = "http://packages.groonga.org/windows/groonga";
    let maybe_proxy = env_proxy::for_url(&Url::parse(BASE_URL).unwrap());
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Obtaining Groonga version: {}",
             config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    let groonga_binary = format!("{}.zip", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = match maybe_proxy {
        None => Client::new(),
        Some(host_port) => Client::with_http_proxy(host_port.0, host_port.1)
    };
    let filename = downloader::file_download(&client,
                                             &*format!("{}/{}", BASE_URL, groonga_binary),
                                             download_dir,
                                             "groonga.zip")
        .expect("Failed to download");
    extractor::extract_zip(&filename, &config.versions_dir);
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    match config.version {
        Some("system") => {
            profile::windows::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ();
        }
        Some(_) => {
            profile::windows::create_profile_source(&config.shim_dir,
                                                    &groonga_dir,
                                                    &config.versions_dir)
                .expect("Could not create source-groonga.ps1")
        }
        None => unreachable!(),
    }
}

pub fn uninstall(m: &ArgMatches) {
    let config = Config::from_matches(m);
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Removing {}....", groonga_dir.clone());
        fs::remove_dir_all(&config.versions_dir.join(groonga_dir))
            .expect("Could not remove specified directory.");
    } else {
        println!("{} is not installed!", groonga_dir.clone());
        process::exit(1);
    }
}

pub fn list() {
    use kuchiki::traits::*;

    if let Ok(doc) = kuchiki::parse_html()
        .from_http("http://packages.groonga.org/windows/groonga") {
        let docs = doc.select("tr").unwrap().collect::<Vec<_>>();
        println!("Installable Groonga:");
        for handle in &docs {
            let texts = handle.as_node().descendants().text_nodes().collect::<Vec<_>>();
            if let Some(text) = texts.first() {
                let package = text.as_node().text_contents();
                if package.contains("groonga") && package.contains("zip") &&
                   (package.contains("x86") || package.contains("x64")) {
                    let display = package.split(".zip").collect::<Vec<_>>();
                    println!("\t{}", display.first().unwrap_or(&""));
                }
            }
        }
    } else {
        println!("{}", "The page couldn't be fetched");
    }
}
<commit_msg>windows list: More format list subcommand output<commit_after>use std::env;
use std::fs;
use std::process;

use clap::ArgMatches;
use tempdir::TempDir;
use hyper::{Client, Url};
use kuchiki;

use extractor;
use downloader;
use profile;
use config::Config;

pub fn init() {
    let config = Config::new();
    if config.install_dir.exists() || config.shim_dir.exists() {
        println!("Already initalized. Reinitializing....");
    }
    fs::create_dir_all(&config.install_dir).expect("Could not create installation directory.");
    fs::create_dir_all(&config.shim_dir).expect("Could not create shims directory.");
    fs::create_dir_all(&config.versions_dir).expect("Could not create versions directory.");
    if !env::home_dir()
        .unwrap_or_else(|| panic!("Cound not found homedir."))
        .join("Documents")
        .join("WindowsPowerShell")
        .join("profile.ps1")
        .exists() {
        println!(r#"Please create profile.ps1 the following place:

$Env:USERPROFILE\Documents\WindowsPowerShell\profile.ps1

And write the following thing:

. $Env:USERPROFILE\.groonga\shims\bin\source-groonga.ps1
"#)
    }
}

pub fn install(m: &ArgMatches) {
    extern crate env_proxy;

    const BASE_URL: &'static str = "http://packages.groonga.org/windows/groonga";
    let maybe_proxy = env_proxy::for_url(&Url::parse(BASE_URL).unwrap());
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Obtaining Groonga version: {}",
             config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    let groonga_binary = format!("{}.zip", groonga_dir.clone());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Already installed. Ready to use it.");
        return ();
    }

    let download_dir = TempDir::new("grnenv-rs")
        .expect("Could not create temp dir.")
        .into_path();

    let client = match maybe_proxy {
        None => Client::new(),
        Some(host_port) => Client::with_http_proxy(host_port.0, host_port.1)
    };
    let filename = downloader::file_download(&client,
                                             &*format!("{}/{}", BASE_URL, groonga_binary),
                                             download_dir,
                                             "groonga.zip")
        .expect("Failed to download");
    extractor::extract_zip(&filename, &config.versions_dir);
}

pub fn switch(m: &ArgMatches) {
    let config = Config::from_matches(m);
    println!("Value for architecture: {}",
             config.arch.clone().expect("unsupported platform"));
    println!("Using Groonga version: {}", config.version.clone().unwrap());
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    match config.version {
        Some("system") => {
            profile::windows::remove_grnenv_profile(&config.shim_dir).unwrap();
            return ();
        }
        Some(_) => {
            profile::windows::create_profile_source(&config.shim_dir,
                                                    &groonga_dir,
                                                    &config.versions_dir)
                .expect("Could not create source-groonga.ps1")
        }
        None => unreachable!(),
    }
}

pub fn uninstall(m: &ArgMatches) {
    let config = Config::from_matches(m);
    let groonga_dir = format!("groonga-{}-{}",
                              config.version.unwrap(),
                              config.arch.unwrap());
    if config.versions_dir.join(groonga_dir.clone()).exists() {
        println!("Removing {}....", groonga_dir.clone());
        fs::remove_dir_all(&config.versions_dir.join(groonga_dir))
            .expect("Could not remove specified directory.");
    } else {
        println!("{} is not installed!", groonga_dir.clone());
        process::exit(1);
    }
}

pub fn list() {
    use kuchiki::traits::*;

    if let Ok(doc) = kuchiki::parse_html()
        .from_http("http://packages.groonga.org/windows/groonga") {
        let docs = doc.select("tr").unwrap().collect::<Vec<_>>();
        println!("Installable Groonga:");
        for handle in &docs {
            let texts = handle.as_node().descendants().text_nodes().collect::<Vec<_>>();
            if let Some(text) = texts.first() {
                let package = text.as_node().text_contents();
                if package.contains("groonga") && package.contains("zip") &&
                   (package.contains("x86") || package.contains("x64")) {
                       let package = package.split(".zip").collect::<Vec<_>>();
                       let pkg = package.first().unwrap_or(&"").to_owned().split("-").collect::<Vec<_>>();
                       println!("\t{} --arch {}",
                                pkg.get(1).unwrap_or(&""),
                                pkg.get(2).unwrap_or(&""));
                }
            }
        }
    } else {
        println!("{}", "The page couldn't be fetched");
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use chrono::NaiveDate;
use error::Result;

pub const NAIVE_DATE_STRING_FORMAT : &'static str = "%Y-%m-%d";

pub fn date_to_string(ndt: &NaiveDate) -> String {
    ndt.format(NAIVE_DATE_STRING_FORMAT).to_string()
}

pub fn date_from_string(s: &str) -> Result<NaiveDate> {
    NaiveDate::parse_from_str(s, NAIVE_DATE_STRING_FORMAT).map_err(From::from)
}

<commit_msg>Add IsValidHabitObj helper trait<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::ops::BitXor;

use chrono::NaiveDate;
use error::Result;

use habit::HabitTemplate;
use instance::HabitInstance;

pub const NAIVE_DATE_STRING_FORMAT : &'static str = "%Y-%m-%d";

pub fn date_to_string(ndt: &NaiveDate) -> String {
    ndt.format(NAIVE_DATE_STRING_FORMAT).to_string()
}

pub fn date_from_string(s: &str) -> Result<NaiveDate> {
    NaiveDate::parse_from_str(s, NAIVE_DATE_STRING_FORMAT).map_err(From::from)
}

/// Helper trait to check whether a object which can be a habit instance and a habit template is
/// actually a valid object, whereas "valid" is defined that it is _either_ an instance or a
/// template (think XOR).
pub trait IsValidHabitObj : HabitInstance + HabitTemplate {
    fn is_valid_havit_obj(&self) -> Result<bool> {
        self.is_habit_instance().and_then(|b| self.is_habit_template().map(|a| a.bitxor(b)))
    }
}

impl<H> IsValidHabitObj for H
    where H: HabitInstance + HabitTemplate
{
    // Empty
}

<|endoftext|>