<commit_before>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Show`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test
//!

#![crate_type = "lib"]
#![feature(macro_rules)]
#![deny(warnings, missing_doc)]
#![allow(visible_private_types)]

extern crate serialize;

use std::collections::HashMap;
use std::from_str::FromStr;

pub use parser::{Parser, Error};
pub use serialization::{Encoder, encode, encode_str};
pub use serialization::{Decoder, decode, decode_str};
pub use serialization::{Error, NeedsKey, NoValue};
pub use serialization::{InvalidMapKeyLocation, InvalidMapKeyType};

mod parser;
mod show;
mod serialization;

/// Representation of a TOML value.
#[deriving(PartialEq, Clone)]
#[allow(missing_doc)]
pub enum Value {
    String(String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(String),
    Array(Array),
    Table(Table),
}

pub type Array = Vec<Value>;
pub type Table = HashMap<String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&String(..), &String(..)) |
            (&Integer(..), &Integer(..)) |
            (&Float(..), &Float(..)) |
            (&Boolean(..), &Boolean(..)) |
            (&Datetime(..), &Datetime(..)) |
            (&Array(..), &Array(..)) |
            (&Table(..), &Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            String(..) => "string",
            Integer(..) => "integer",
            Float(..) => "float",
            Boolean(..) => "boolean",
            Datetime(..) => "datetime",
            Array(..) => "array",
            Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
        match *self { String(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime<'a>(&'a self) -> Option<&'a str> {
        match *self { Datetime(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice<'a>(&'a self) -> Option<&'a [Value]> {
        match *self { Array(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table<'a>(&'a self) -> Option<&'a Table> {
        match *self { Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// ```
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = from_str(toml).unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        Value::lookup_path(self, path.split('.'))
    }

    // Performs actual traverse starting with value
    //
    // For arrays tries to convert key to uint and retrieve
    // corresponding element
    fn lookup_path<'a, I:Iterator<&'a str>>(value: &'a Value,
                                            components: I) -> Option<&'a Value> {
        let mut cur_value: &'a Value = value;
        let mut iter = components;
        for key in iter {
            match cur_value {
                &Table(ref hm) => {
                    match hm.find_equiv(&key) {
                        Some(v) => cur_value = v,
                        _ => return None
                    }
                },
                &Array(ref v) => {
                    let idx: Option<uint> = FromStr::from_str(key);
                    match idx {
                        Some(idx) if idx < v.len() => cur_value = v.get(idx),
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)
    }
}

impl FromStr for Value {
    fn from_str(s: &str) -> Option<Value> {
        Parser::new(s).parse().map(Table)
    }
}

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

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = from_str(toml).unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        let no_bar = value.lookup("test.bar");
        assert!(no_bar.is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = from_str(toml).unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }
}
<commit_msg>Fixed tests, merged lookup functions<commit_after>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Show`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test
//!

#![crate_type = "lib"]
#![feature(macro_rules)]
#![deny(warnings, missing_doc)]
#![allow(visible_private_types)]

extern crate serialize;

use std::collections::HashMap;
use std::from_str::FromStr;

pub use parser::{Parser, Error};
pub use serialization::{Encoder, encode, encode_str};
pub use serialization::{Decoder, decode, decode_str};
pub use serialization::{Error, NeedsKey, NoValue};
pub use serialization::{InvalidMapKeyLocation, InvalidMapKeyType};

mod parser;
mod show;
mod serialization;
#[cfg(test)]mod test;
/// Representation of a TOML value.
#[deriving(PartialEq, Clone)]
#[allow(missing_doc)]
pub enum Value {
    String(String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(String),
    Array(Array),
    Table(Table),
}

pub type Array = Vec<Value>;
pub type Table = HashMap<String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&String(..), &String(..)) |
            (&Integer(..), &Integer(..)) |
            (&Float(..), &Float(..)) |
            (&Boolean(..), &Boolean(..)) |
            (&Datetime(..), &Datetime(..)) |
            (&Array(..), &Array(..)) |
            (&Table(..), &Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            String(..) => "string",
            Integer(..) => "integer",
            Float(..) => "float",
            Boolean(..) => "boolean",
            Datetime(..) => "datetime",
            Array(..) => "array",
            Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
        match *self { String(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime<'a>(&'a self) -> Option<&'a str> {
        match *self { Datetime(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice<'a>(&'a self) -> Option<&'a [Value]> {
        match *self { Array(ref s) => Some(s.as_slice()), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table<'a>(&'a self) -> Option<&'a Table> {
        match *self { Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// ```
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = from_str(toml).unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        let mut cur_value = self;
        for key in path.split('.') {
            match cur_value {
                &Table(ref hm) => {
                    match hm.find_equiv(&key) {
                        Some(v) => cur_value = v,
                        _ => return None
                    }
                },
                &Array(ref v) => {
                    let idx: Option<uint> = FromStr::from_str(key);
                    match idx {
                        Some(idx) if idx < v.len() => cur_value = v.get(idx),
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)
    }
}

impl FromStr for Value {
    fn from_str(s: &str) -> Option<Value> {
        Parser::new(s).parse().map(Table)
    }
}

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

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = from_str(toml).unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        let no_bar = value.lookup("test.bar");
        assert!(no_bar.is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = from_str(toml).unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }
}
<|endoftext|>


<commit_before>//! Extension traits for `Stream` implementing various operators.
//!
//! A collection of functions taking typed `Stream` objects as input and producing new `Stream`
//! objects as output. Many of the operators provide simple, composable functionality. Some of the
//! operators are more complicated, for use with advanced timely dataflow features.
//!
//! The [`Unary`](./unary/index.html) and [`Binary`](./binary/index.html) operators provide general
//! operators whose behavior can be supplied using closures accepting input and output handles.
//! Most of the operators in this module are defined using these two general operators.

pub use self::enterleave::{Enter, EnterAt, Leave};
pub use self::unary::Unary;
// pub use self::queue::*;
pub use self::input::Input;
pub use self::unordered_input::UnorderedInput;
pub use self::feedback::{LoopVariable, ConnectLoop};
pub use self::concat::{Concat, Concatenate};
pub use self::partition::Partition;
pub use self::map::Map;
pub use self::inspect::Inspect;
pub use self::filter::Filter;
pub use self::binary::Binary;
pub use self::delay::Delay;
pub use self::exchange::Exchange;
pub use self::broadcast::Broadcast;
pub use self::probe::Probe;
pub use self::to_stream::ToStream;
pub use self::capture::Capture;
pub use self::operator::Operator;

pub use self::reclock::Reclock;
pub use self::count::Accumulate;

pub mod enterleave;
pub mod unary;
// pub mod queue;
pub mod input;
pub mod unordered_input;
pub mod feedback;
pub mod concat;
pub mod partition;
pub mod map;
pub mod inspect;
pub mod filter;
pub mod binary;
pub mod delay;
pub mod exchange;
pub mod broadcast;
pub mod probe;
pub mod to_stream;
pub mod capture;
pub mod operator;

pub mod aggregation;

pub mod reclock;
pub mod count;

// keep the handle constructors private
mod handles;
// pub use self::handles::{InputHandle, FrontieredInputHandle, OutputHandle};

mod notificator;
pub use self::notificator::Notificator;
pub use self::notificator::FrontierNotificator;

// keep "mint" module-private
mod capability;
pub use self::capability::{Capability, CapabilitySet};
<commit_msg>make OutputHandle visible again<commit_after>//! Extension traits for `Stream` implementing various operators.
//!
//! A collection of functions taking typed `Stream` objects as input and producing new `Stream`
//! objects as output. Many of the operators provide simple, composable functionality. Some of the
//! operators are more complicated, for use with advanced timely dataflow features.
//!
//! The [`Unary`](./unary/index.html) and [`Binary`](./binary/index.html) operators provide general
//! operators whose behavior can be supplied using closures accepting input and output handles.
//! Most of the operators in this module are defined using these two general operators.

pub use self::enterleave::{Enter, EnterAt, Leave};
pub use self::unary::Unary;
// pub use self::queue::*;
pub use self::input::Input;
pub use self::unordered_input::UnorderedInput;
pub use self::feedback::{LoopVariable, ConnectLoop};
pub use self::concat::{Concat, Concatenate};
pub use self::partition::Partition;
pub use self::map::Map;
pub use self::inspect::Inspect;
pub use self::filter::Filter;
pub use self::binary::Binary;
pub use self::delay::Delay;
pub use self::exchange::Exchange;
pub use self::broadcast::Broadcast;
pub use self::probe::Probe;
pub use self::to_stream::ToStream;
pub use self::capture::Capture;
pub use self::operator::Operator;

pub use self::reclock::Reclock;
pub use self::count::Accumulate;

pub mod enterleave;
pub mod unary;
// pub mod queue;
pub mod input;
pub mod unordered_input;
pub mod feedback;
pub mod concat;
pub mod partition;
pub mod map;
pub mod inspect;
pub mod filter;
pub mod binary;
pub mod delay;
pub mod exchange;
pub mod broadcast;
pub mod probe;
pub mod to_stream;
pub mod capture;
pub mod operator;

pub mod aggregation;

pub mod reclock;
pub mod count;

// keep the handle constructors private
mod handles;
// pub use self::handles::{InputHandle, FrontieredInputHandle};
pub use self::handles::OutputHandle;

mod notificator;
pub use self::notificator::Notificator;
pub use self::notificator::FrontierNotificator;

// keep "mint" module-private
mod capability;
pub use self::capability::{Capability, CapabilitySet};
<|endoftext|>


<commit_before>use line_buffer::LineBuffer;
use std_unicode::str::UnicodeStr;
use unicode_segmentation::UnicodeSegmentation;

enum Action {
    Insert(String), // QuotedInsert, SelfInsert, Yank
    Delete(String), /* BackwardDeleteChar, BackwardKillWord, DeleteChar, KillLine, KillWholeLine, KillWord, UnixLikeDiscard, ViDeleteTo */
    Replace(String, String), /* CapitalizeWord, Complete, DowncaseWord, Replace, TransposeChars, TransposeWords, UpcaseWord, YankPop */
}

struct Change {
    idx: usize, // where the change happens
    action: Action,
}

impl Change {
    fn undo(&self, line: &mut LineBuffer) {
        match self.action {
            Action::Insert(ref text) => {
                line.delete_range(self.idx..self.idx + text.len());
            }
            Action::Delete(ref text) => {
                line.insert_str(self.idx, text);
            }
            Action::Replace(ref old, ref new) => {
                line.replace(self.idx..self.idx + new.len(), old);
            }
        }
    }

    fn redo(&self, line: &mut LineBuffer) {
        match self.action {
            Action::Insert(ref text) => {
                line.insert_str(self.idx, text);
            }
            Action::Delete(ref text) => {
                line.delete_range(self.idx..self.idx + text.len());
            }
            Action::Replace(ref old, ref new) => {
                line.replace(self.idx..self.idx + old.len(), new);
            }
        }
    }

    fn insert_seq(&self, idx: usize) -> bool {
        if let Action::Insert(ref text) = self.action {
            self.idx + text.len() == idx
        } else {
            false
        }
    }

    fn delete_seq(&self, idx: usize, len: usize) -> bool {
        if let Action::Delete(_) = self.action {
            // delete or backspace
            self.idx == idx || self.idx == idx + len
        } else {
            false
        }
    }
}

pub struct Changeset {
    undos: Vec<Change>, // undoable changes
    redos: Vec<Change>, // undone changes, redoable
}

impl Changeset {
    pub fn new() -> Changeset {
        Changeset {
            undos: Vec::new(),
            redos: Vec::new(),
        }
    }

    fn insert_char(idx: usize, c: char) -> Change {
        let mut text = String::new();
        text.push(c);
        Change {
            idx: idx,
            action: Action::Insert(text),
        }
    }

    pub fn insert(&mut self, idx: usize, c: char) {
        self.redos.clear();
        if !c.is_alphanumeric() {
            self.undos.push(Self::insert_char(idx, c));
            return;
        }
        let last_change = self.undos.pop();
        match last_change {
            Some(last_change) => {
                // merge consecutive char insertions when char is alphanumeric
                if last_change.insert_seq(idx) {
                    let mut last_change = last_change;
                    if let Action::Insert(ref mut text) = last_change.action {
                        text.push(c);
                    } else {
                        unreachable!();
                    }
                    self.undos.push(last_change);
                } else {
                    self.undos.push(last_change);
                    self.undos.push(Self::insert_char(idx, c));
                }
            }
            None => {
                self.undos.push(Self::insert_char(idx, c));
            }
        };
    }

    pub fn insert_str(&mut self, idx: usize, string: &str) {
        self.redos.clear();
        self.undos.push(Change {
            idx: idx,
            action: Action::Insert(string.to_string()),
        });
    }

    pub fn delete(&mut self, idx: usize, string: String) {
        self.redos.clear();

        if !Self::single_char(&string) {
            self.undos.push(Change {
                idx: idx,
                action: Action::Delete(string),
            });
            return;
        }
        let last_change = self.undos.pop();
        match last_change {
            Some(last_change) => {
                // merge consecutive char deletions when char is alphanumeric
                if last_change.delete_seq(idx, string.len()) {
                    let mut last_change = last_change;
                    if let Action::Delete(ref mut text) = last_change.action {
                        if last_change.idx == idx {
                            text.push_str(&string);
                        } else {
                            text.insert_str(0, &string);
                            last_change.idx = idx;
                        }
                    } else {
                        unreachable!();
                    }
                    self.undos.push(last_change);
                } else {
                    self.undos.push(last_change);
                    self.undos.push(Change {
                        idx: idx,
                        action: Action::Delete(string),
                    });
                }
            }
            None => {
                self.undos.push(Change {
                    idx: idx,
                    action: Action::Delete(string),
                });
            }
        };
    }

    fn single_char(s: &str) -> bool {
        let mut graphemes = s.graphemes(true);
        graphemes.next().map_or(false, |grapheme| grapheme.is_alphanumeric()) &&
        graphemes.next().is_none()
    }

    pub fn replace(&mut self, idx: usize, old: String, new: &str) {
        self.redos.clear();
        self.undos.push(Change {
            idx: idx,
            action: Action::Replace(old, new.to_string()),
        });
    }

    pub fn undo(&mut self, line: &mut LineBuffer) -> bool {
        match self.undos.pop() {
            Some(change) => {
                change.undo(line);
                self.redos.push(change);
                true
            }
            None => false,
        }
    }

    pub fn redo(&mut self, line: &mut LineBuffer) -> bool {
        match self.redos.pop() {
            Some(change) => {
                change.redo(line);
                self.undos.push(change);
                true
            }
            None => false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Changeset;
    use line_buffer::LineBuffer;

    #[test]
    fn test_insert_chars() {
        let mut cs = Changeset::new();
        cs.insert(0, 'H');
        cs.insert(1, 'i');
        assert_eq!(1, cs.undos.len());
        assert_eq!(0, cs.redos.len());
        cs.insert(0, ' ');
        assert_eq!(2, cs.undos.len());
    }

    #[test]
    fn test_insert_strings() {
        let mut cs = Changeset::new();
        cs.insert_str(0, "Hello");
        cs.insert_str(5, ", ");
        assert_eq!(2, cs.undos.len());
        assert_eq!(0, cs.redos.len());
    }

    #[test]
    fn test_undo_insert() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hello");
        buf.insert_str(5, ", world!");
        let mut cs = Changeset::new();
        assert_eq!(buf.as_str(), "Hello, world!");

        cs.insert_str(5, ", world!");

        cs.undo(&mut buf);
        assert_eq!(0, cs.undos.len());
        assert_eq!(1, cs.redos.len());
        assert_eq!(buf.as_str(), "Hello");

        cs.redo(&mut buf);
        assert_eq!(1, cs.undos.len());
        assert_eq!(0, cs.redos.len());
        assert_eq!(buf.as_str(), "Hello, world!");
    }

    #[test]
    fn test_undo_delete() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hello");
        let mut cs = Changeset::new();
        assert_eq!(buf.as_str(), "Hello");

        cs.delete(5, ", world!".to_string());

        cs.undo(&mut buf);
        assert_eq!(buf.as_str(), "Hello, world!");

        cs.redo(&mut buf);
        assert_eq!(buf.as_str(), "Hello");
    }

    #[test]
    fn test_delete_chars() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hlo");

        let mut cs = Changeset::new();
        cs.delete(1, "e".to_string());
        cs.delete(1, "l".to_string());
        assert_eq!(1, cs.undos.len());

        cs.undo(&mut buf);
        assert_eq!(buf.as_str(), "Hello");
    }

    #[test]
    fn test_backspace_chars() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hlo");

        let mut cs = Changeset::new();
        cs.delete(2, "l".to_string());
        cs.delete(1, "e".to_string());
        assert_eq!(1, cs.undos.len());

        cs.undo(&mut buf);
        assert_eq!(buf.as_str(), "Hello");
    }

    #[test]
    fn test_undo_replace() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hello, world!");
        let mut cs = Changeset::new();
        assert_eq!(buf.as_str(), "Hello, world!");

        buf.replace(1..5, "i");
        assert_eq!(buf.as_str(), "Hi, world!");
        cs.replace(1, "ello".to_string(), "i");

        cs.undo(&mut buf);
        assert_eq!(buf.as_str(), "Hello, world!");

        cs.redo(&mut buf);
        assert_eq!(buf.as_str(), "Hi, world!");
    }
}
<commit_msg>Refactor undos (#60)<commit_after>use line_buffer::LineBuffer;
use std_unicode::str::UnicodeStr;
use unicode_segmentation::UnicodeSegmentation;

enum Action {
    Insert(String), // QuotedInsert, SelfInsert, Yank
    Delete(String), /* BackwardDeleteChar, BackwardKillWord, DeleteChar, KillLine, KillWholeLine, KillWord, UnixLikeDiscard, ViDeleteTo */
    Replace(String, String), /* CapitalizeWord, Complete, DowncaseWord, Replace, TransposeChars, TransposeWords, UpcaseWord, YankPop */
}

struct Change {
    idx: usize, // where the change happens
    action: Action,
}

impl Change {
    fn undo(&self, line: &mut LineBuffer) {
        match self.action {
            Action::Insert(ref text) => {
                line.delete_range(self.idx..self.idx + text.len());
            }
            Action::Delete(ref text) => {
                line.insert_str(self.idx, text);
                line.set_pos(self.idx + text.len());
            }
            Action::Replace(ref old, ref new) => {
                line.replace(self.idx..self.idx + new.len(), old);
            }
        }
    }

    #[cfg(test)]
    fn redo(&self, line: &mut LineBuffer) {
        match self.action {
            Action::Insert(ref text) => {
                line.insert_str(self.idx, text);
            }
            Action::Delete(ref text) => {
                line.delete_range(self.idx..self.idx + text.len());
            }
            Action::Replace(ref old, ref new) => {
                line.replace(self.idx..self.idx + old.len(), new);
            }
        }
    }

    fn insert_seq(&self, idx: usize) -> bool {
        if let Action::Insert(ref text) = self.action {
            self.idx + text.len() == idx
        } else {
            false
        }
    }

    fn delete_seq(&self, idx: usize, len: usize) -> bool {
        if let Action::Delete(_) = self.action {
            // delete or backspace
            self.idx == idx || self.idx == idx + len
        } else {
            false
        }
    }
}

pub struct Changeset {
    undos: Vec<Change>, // undoable changes
    redos: Vec<Change>, // undone changes, redoable
}

impl Changeset {
    pub fn new() -> Changeset {
        Changeset {
            undos: Vec::new(),
            redos: Vec::new(),
        }
    }

    fn insert_char(idx: usize, c: char) -> Change {
        let mut text = String::new();
        text.push(c);
        Change {
            idx: idx,
            action: Action::Insert(text),
        }
    }

    pub fn insert(&mut self, idx: usize, c: char) {
        self.redos.clear();
        if !c.is_alphanumeric() {
            self.undos.push(Self::insert_char(idx, c));
            return;
        }
        let last_change = self.undos.pop();
        match last_change {
            Some(last_change) => {
                // merge consecutive char insertions when char is alphanumeric
                if last_change.insert_seq(idx) {
                    let mut last_change = last_change;
                    if let Action::Insert(ref mut text) = last_change.action {
                        text.push(c);
                    } else {
                        unreachable!();
                    }
                    self.undos.push(last_change);
                } else {
                    self.undos.push(last_change);
                    self.undos.push(Self::insert_char(idx, c));
                }
            }
            None => {
                self.undos.push(Self::insert_char(idx, c));
            }
        };
    }

    pub fn insert_str<S: Into<String>>(&mut self, idx: usize, string: S) {
        self.redos.clear();
        self.undos.push(Change {
            idx: idx,
            action: Action::Insert(string.into()),
        });
    }

    pub fn delete<S: AsRef<str> + Into<String>>(&mut self, idx: usize, string: S) {
        self.redos.clear();

        if !Self::single_char(string.as_ref()) {
            self.undos.push(Change {
                idx: idx,
                action: Action::Delete(string.into()),
            });
            return;
        }
        let last_change = self.undos.pop();
        match last_change {
            Some(last_change) => {
                // merge consecutive char deletions when char is alphanumeric
                if last_change.delete_seq(idx, string.as_ref().len()) {
                    let mut last_change = last_change;
                    if let Action::Delete(ref mut text) = last_change.action {
                        if last_change.idx == idx {
                            text.push_str(string.as_ref());
                        } else {
                            text.insert_str(0, string.as_ref());
                            last_change.idx = idx;
                        }
                    } else {
                        unreachable!();
                    }
                    self.undos.push(last_change);
                } else {
                    self.undos.push(last_change);
                    self.undos.push(Change {
                        idx: idx,
                        action: Action::Delete(string.into()),
                    });
                }
            }
            None => {
                self.undos.push(Change {
                    idx: idx,
                    action: Action::Delete(string.into()),
                });
            }
        };
    }

    fn single_char(s: &str) -> bool {
        let mut graphemes = s.graphemes(true);
        graphemes.next().map_or(false, |grapheme| grapheme.is_alphanumeric()) &&
        graphemes.next().is_none()
    }

    pub fn replace<S: Into<String>>(&mut self, idx: usize, old: String, new: S) {
        self.redos.clear();
        self.undos.push(Change {
            idx: idx,
            action: Action::Replace(old.into(), new.into()),
        });
    }

    pub fn undo(&mut self, line: &mut LineBuffer) -> bool {
        match self.undos.pop() {
            Some(change) => {
                change.undo(line);
                self.redos.push(change);
                true
            }
            None => false,
        }
    }

    #[cfg(test)]
    pub fn redo(&mut self, line: &mut LineBuffer) -> bool {
        match self.redos.pop() {
            Some(change) => {
                change.redo(line);
                self.undos.push(change);
                true
            }
            None => false,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Changeset;
    use line_buffer::LineBuffer;

    #[test]
    fn test_insert_chars() {
        let mut cs = Changeset::new();
        cs.insert(0, 'H');
        cs.insert(1, 'i');
        assert_eq!(1, cs.undos.len());
        assert_eq!(0, cs.redos.len());
        cs.insert(0, ' ');
        assert_eq!(2, cs.undos.len());
    }

    #[test]
    fn test_insert_strings() {
        let mut cs = Changeset::new();
        cs.insert_str(0, "Hello");
        cs.insert_str(5, ", ");
        assert_eq!(2, cs.undos.len());
        assert_eq!(0, cs.redos.len());
    }

    #[test]
    fn test_undo_insert() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hello");
        buf.insert_str(5, ", world!");
        let mut cs = Changeset::new();
        assert_eq!(buf.as_str(), "Hello, world!");

        cs.insert_str(5, ", world!");

        cs.undo(&mut buf);
        assert_eq!(0, cs.undos.len());
        assert_eq!(1, cs.redos.len());
        assert_eq!(buf.as_str(), "Hello");

        cs.redo(&mut buf);
        assert_eq!(1, cs.undos.len());
        assert_eq!(0, cs.redos.len());
        assert_eq!(buf.as_str(), "Hello, world!");
    }

    #[test]
    fn test_undo_delete() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hello");
        let mut cs = Changeset::new();
        assert_eq!(buf.as_str(), "Hello");

        cs.delete(5, ", world!".to_string());

        cs.undo(&mut buf);
        assert_eq!(buf.as_str(), "Hello, world!");

        cs.redo(&mut buf);
        assert_eq!(buf.as_str(), "Hello");
    }

    #[test]
    fn test_delete_chars() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hlo");

        let mut cs = Changeset::new();
        cs.delete(1, "e".to_string());
        cs.delete(1, "l".to_string());
        assert_eq!(1, cs.undos.len());

        cs.undo(&mut buf);
        assert_eq!(buf.as_str(), "Hello");
    }

    #[test]
    fn test_backspace_chars() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hlo");

        let mut cs = Changeset::new();
        cs.delete(2, "l".to_string());
        cs.delete(1, "e".to_string());
        assert_eq!(1, cs.undos.len());

        cs.undo(&mut buf);
        assert_eq!(buf.as_str(), "Hello");
    }

    #[test]
    fn test_undo_replace() {
        let mut buf = LineBuffer::init("", 0);
        buf.insert_str(0, "Hello, world!");
        let mut cs = Changeset::new();
        assert_eq!(buf.as_str(), "Hello, world!");

        buf.replace(1..5, "i");
        assert_eq!(buf.as_str(), "Hi, world!");
        cs.replace(1, "ello".to_string(), "i");

        cs.undo(&mut buf);
        assert_eq!(buf.as_str(), "Hello, world!");

        cs.redo(&mut buf);
        assert_eq!(buf.as_str(), "Hi, world!");
    }
}
<|endoftext|>


<commit_before>use request::ToParams;

#[derive(Debug)]
pub enum User {
    UserId(String),
    OAuthToken(String)
}

impl User {
    pub fn from_user_id(user_id: String) -> Self {
        User::UserId(user_id)
    }

    pub fn from_oauth_token(token: String) -> Self {
        User::OAuthToken(token)
    }
}

impl ToParams for User {
    fn to_params(&self) -> Vec<(&str, &str)> {
        let (field, value) = match *self {
            User::UserId(ref user_id) => ("user_id", user_id),
            User::OAuthToken(ref token) => ("access_token", token)
        };
        vec![(field, value)]
    }
}

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

    #[test]
    fn transforms_user_id_into_params() {
        let user_id = "my_user_id";
        let user = User::from_user_id(user_id.to_owned());

        let result = user.to_params();

        let expected = vec![("user_id", user_id)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_oauth_token_into_params() {
        let oauth_token = "my_oauth_token";
        let user = User::from_oauth_token(oauth_token.to_owned());

        let result = user.to_params();

        let expected = vec![("access_token", oauth_token)];
        assert_eq!(expected, result);
    }
}
<commit_msg>user: avoid stringly types by implementing several traits<commit_after>use request::ToParams;
use errors::*;

use std::str::FromStr;

#[derive(Debug)]
pub struct UserId(String);
#[derive(Debug)]
pub struct OAuthToken(String);

// These trait impls provide a way to reference our types as &str
impl AsRef<str> for UserId {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

impl AsRef<str> for OAuthToken {
    fn as_ref(&self) -> &str {
        self.0.as_str()
    }
}

// These trait impls provide a way to &str#parse()
impl FromStr for UserId {
    type Err = Error;

    fn from_str(s: &str) -> Result<UserId> {
        Ok(UserId(s.to_owned()))
    }
}

impl FromStr for OAuthToken {
    type Err = Error;

    fn from_str(s: &str) -> Result<OAuthToken> {
        Ok(OAuthToken(s.to_owned()))
    }
}

// These trait impls are similar to FromStr (but are infallible)
impl<'a> From<&'a str> for UserId where Self: FromStr {
    fn from(s: &'a str) -> UserId {
        s.parse().unwrap()
    }
}

impl<'a> From<&'a str> for OAuthToken where Self: FromStr {
    fn from(s: &'a str) -> OAuthToken {
        s.parse().unwrap()
    }
}

// These trait impls take ownership of a given String
impl From<String> for UserId {
    fn from(s: String) -> UserId {
        UserId(s)
    }
}

impl From<String> for OAuthToken {
    fn from(s: String) -> OAuthToken {
        OAuthToken(s)
    }
}

#[derive(Debug)]
pub enum User {
    UserId(UserId),
    OAuthToken(OAuthToken)
}

impl Into<User> for UserId {
    fn into(self) -> User {
        User::UserId(self)
    }
}

impl Into<User> for OAuthToken {
    fn into(self) -> User {
        User::OAuthToken(self)
    }
}

impl User {
    pub fn from_user_id<T: Into<UserId>>(user_id: T) -> Self {
        User::UserId(user_id.into())
    }

    pub fn from_oauth_token<T: Into<OAuthToken>>(token: T) -> Self {
        User::OAuthToken(token.into())
    }
}

impl ToParams for User {
    fn to_params(&self) -> Vec<(&str, &str)> {
        let (field, value) = match *self {
            User::UserId(ref user_id) => ("user_id", user_id.as_ref()),
            User::OAuthToken(ref token) => ("access_token", token.as_ref())
        };
        vec![(field, value)]
    }
}

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

    #[test]
    fn transforms_user_id_into_params() {
        let user_id = "my_user_id";
        let user = User::from_user_id(user_id.to_owned());

        let result = user.to_params();

        let expected = vec![("user_id", user_id)];
        assert_eq!(expected, result);
    }

    #[test]
    fn transforms_oauth_token_into_params() {
        let oauth_token = "my_oauth_token";
        let user = User::from_oauth_token(oauth_token.to_owned());

        let result = user.to_params();

        let expected = vec![("access_token", oauth_token)];
        assert_eq!(expected, result);
    }
}
<|endoftext|>


<commit_before>// Copyright © 2014, Simonas Kazlauskas <git@kazlauskas.me>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
// fee is hereby granted, provided that the above copyright notice and this permission notice
// appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//! Utility functions to detect presence of `rdrand` and `rdseed` instruction support.

#![allow(dead_code)]

pub use self::imp::*;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod imp {
    #[inline]
    fn cpuid(ain : u32, cin : u32) -> (u32, u32, u32, u32) {
        let (a, b, c, d);
        unsafe {
            asm!("cpuid"
                :"={eax}"(a), "={ebx}"(b), "={ecx}"(c), "={edx}"(d)
                :"{eax}"(ain), "{ecx}"(cin)
                );
        }
        (a, b, c, d)
    }

    #[inline]
    pub fn is_intel() -> bool {
        let (_, b, c, d) = cpuid(0, 0);
        // GenuineIntel
        return b == 0x756E6547 && d == 0x49656e69 && c == 0x6C65746E;
    }

    #[inline]
    pub fn has_rdrand() -> bool {
        const FLAG : u32 = 1 << 30;
        let (_, _, c, _) = cpuid(1, 0);
        return c & FLAG == FLAG;
    }

    #[inline]
    pub fn has_rdseed() -> bool {
        const FLAG : u32 = 1 << 18;
        let (_, b, _, _) = cpuid(7, 0);
        return b & FLAG == FLAG;
    }
}

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
mod imp {
    #[inline]
    pub fn is_intel() -> bool {
        false
    }

    #[inline]
    pub fn has_rdrand() -> bool {
        false
    }

    #[inline]
    pub fn has_rdseed() -> bool {
        false
    }
}
<commit_msg>Remove some redundancy in cpuid wrapper<commit_after>// Copyright © 2014, Simonas Kazlauskas <git@kazlauskas.me>
//
// Permission to use, copy, modify, and/or distribute this software for any purpose with or without
// fee is hereby granted, provided that the above copyright notice and this permission notice
// appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
// SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
// AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
// OF THIS SOFTWARE.
//! Utility functions to detect presence of `rdrand` and `rdseed` instruction support.

#![allow(dead_code)]

pub use self::imp::*;

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod imp {
    #[inline]
    fn cpuid(mut a: u32, mut c: u32) -> (u32, u32, u32, u32) {
        let (b, d);
        unsafe {
            asm!("cpuid"
                :"+{eax}"(a), "={ebx}"(b), "+{ecx}"(c), "={edx}"(d)
                );
        }
        (a, b, c, d)
    }

    #[inline]
    pub fn is_intel() -> bool {
        let (_, b, c, d) = cpuid(0, 0);
        // GenuineIntel
        return b == 0x756E6547 && d == 0x49656e69 && c == 0x6C65746E;
    }

    #[inline]
    pub fn has_rdrand() -> bool {
        const FLAG : u32 = 1 << 30;
        let (_, _, c, _) = cpuid(1, 0);
        return c & FLAG == FLAG;
    }

    #[inline]
    pub fn has_rdseed() -> bool {
        const FLAG : u32 = 1 << 18;
        let (_, b, _, _) = cpuid(7, 0);
        return b & FLAG == FLAG;
    }
}

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
mod imp {
    #[inline]
    pub fn is_intel() -> bool {
        false
    }

    #[inline]
    pub fn has_rdrand() -> bool {
        false
    }

    #[inline]
    pub fn has_rdseed() -> bool {
        false
    }
}
<|endoftext|>


<commit_before>use time;
use time::Tm;
use std::io;
use std::io::prelude::*;

pub fn msdos_datetime_to_tm(time: u16, date: u16) -> Tm
{
    let seconds = (time & 0b0000000000011111) << 1;
    let minutes = (time & 0b0000011111100000) >> 5;
    let hours =   (time & 0b1111100000000000) >> 11;
    let days =    (date & 0b0000000000011111) >> 0;
    let months =  (date & 0b0000000111100000) >> 5;
    let years =   (date & 0b1111111000000000) >> 9;

    let datetime = format!("{:04}-{:02}-{:02} {:02}:{:02}:{:02}",
                           years as u32 + 1980,
                           months,
                           days,
                           hours,
                           minutes,
                           seconds);
    let format = "%Y-%m-%d %H:%M:%S";

    match time::strptime(&*datetime, format)
    {
        Ok(tm) => tm,
        Err(m) => {
            let _ = write!(&mut io::stderr(), "Failed parsing date: {}", m);
            time::empty_tm()
        },
    }
}

pub fn tm_to_msdos_time(time: Tm) -> u16
{
    ((time.tm_sec >> 1) | (time.tm_min << 5) | (time.tm_hour << 11)) as u16
}

pub fn tm_to_msdos_date(time: Tm) -> u16
{
    (time.tm_mday | ((time.tm_mon + 1) << 5) | ((time.tm_year - 80) << 9)) as u16
}
<commit_msg>Simplify date parsing code<commit_after>use time::{Tm, empty_tm};

pub fn msdos_datetime_to_tm(time: u16, date: u16) -> Tm
{
    let seconds = (time & 0b0000000000011111) << 1;
    let minutes = (time & 0b0000011111100000) >> 5;
    let hours =   (time & 0b1111100000000000) >> 11;
    let days =    (date & 0b0000000000011111) >> 0;
    let months =  (date & 0b0000000111100000) >> 5;
    let years =   (date & 0b1111111000000000) >> 9;

    // Month range: Dos [1..12], Tm [0..11]
    // Year zero: Dos 1980, Tm 1900

    Tm {
        tm_sec: seconds as i32,
        tm_min: minutes as i32,
        tm_hour: hours as i32,
        tm_mday: days as i32,
        tm_mon: months as i32 - 1,
        tm_year: years as i32 + 80,
        ..empty_tm()
    }
}

pub fn tm_to_msdos_time(time: Tm) -> u16
{
    ((time.tm_sec >> 1) | (time.tm_min << 5) | (time.tm_hour << 11)) as u16
}

pub fn tm_to_msdos_date(time: Tm) -> u16
{
    (time.tm_mday | ((time.tm_mon + 1) << 5) | ((time.tm_year - 80) << 9)) as u16
}
<|endoftext|>


<commit_before>extern crate num;
use std::collections::BTreeSet;
use std::cmp;
use rand::Rng;
use std::ops::Range;
use std::iter::Rev;
use super::{Genetic, SISO};
use std::marker::PhantomData;

///Defines an opcode for the Mep. Every opcode contains an instruction and two parameter indices. These specify which
///previous opcodes produced the result required as inputs to this opcode. These parameters can also come from the inputs
///to the program, which sequentially preceed the internal instructions.
#[derive(Clone, Copy)]
struct Opcode<Ins> {
    instruction: Ins,
    first: usize,
    second: usize,
}

///A multi-expression program represented using a series of operations that can reuse results of previous operations.
pub struct Mep<Ins, R, Param, F1, F2> {
    program: Vec<Opcode<Ins>>,
    pub unit_mutate_size: usize,
    pub crossover_points: usize,
    inputs: usize,
    outputs: usize,
    mutator: F1,
    processor: F2,
    _phantom: (PhantomData<R>, PhantomData<Param>),
}

impl<Ins, R, Param, F1, F2> Clone for Mep<Ins, R, Param, F1, F2>
    where Ins: Clone, F1: Copy, F2: Copy
{
    fn clone(&self) -> Self {
        Mep{
            program: self.program.clone(),
            unit_mutate_size: self.unit_mutate_size,
            crossover_points: self.crossover_points,
            inputs: self.inputs,
            outputs: self.outputs,
            mutator: self.mutator,
            processor: self.processor,
            _phantom: (PhantomData, PhantomData),
        }
    }
}

impl<Ins, R, Param, F1, F2> Mep<Ins, R, Param, F1, F2> {
    ///Generates a new Mep with a particular size and takes a closure to generate random instructions.
    ///Takes an RNG as well to generate random internal data for each instruction. This Rng is different from the Mep's
    ///Rng, thus it is parameterized separately here.
    pub fn new<I, Rg>(inputs: usize, outputs: usize, unit_mutate_size: usize, crossover_points: usize, rng: &mut Rg,
        instruction_iter: I, mutator: F1, processor: F2) -> Self
        where I: Iterator<Item=Ins>, Rg: Rng, F1: Fn(&mut Ins, &mut R), F2: Fn(&Ins, Param, Param) -> Param
    {
        Mep{
            program: instruction_iter.enumerate()
                .map(|(index, ins)| Opcode{
                        instruction: ins,
                        first: rng.gen_range(0, index + inputs),
                        second: rng.gen_range(0, index + inputs),
                    }
                ).collect(),
            unit_mutate_size: unit_mutate_size,
            crossover_points: crossover_points,
            inputs: inputs,
            outputs: outputs,
            mutator: mutator,
            processor: processor,
            _phantom: (PhantomData, PhantomData),
        }
    }
}

impl<Ins, R, Param, F1, F2> Genetic<R> for Mep<Ins, R, Param, F1, F2>
    where R: Rng, Ins: Clone, Param: Clone, F1: Copy + Fn(&mut Ins, &mut R), F2: Copy
{
    fn mate(parents: (&Self, &Self), rng: &mut R) -> Self {
        //Each Mep must have the same amount of inputs
        //TODO: Once Rust implements generic values, this can be made explicit and is not needed
        assert!(parents.0.inputs == parents.1.inputs);
        assert!(parents.0.outputs == parents.1.outputs);
        //Get the smallest of the two lengths
        let total_instructions = cmp::min(parents.0.program.len(), parents.1.program.len());
        let crossover_choice = rng.gen_range(0, 2);
        Mep{program:
            //Generate a randomly sized sequence between 1 and crossover_points
            (0..rng.gen_range(1, cmp::min(total_instructions / 2, {
                if crossover_choice == 0 {parents.0}
                else {parents.1}}.crossover_points + 1)))
            //Map these to random crossover points
            .map(|_| rng.gen_range(0, total_instructions))
            //Add total_instructions at the end so we can generate a range with it
            .chain(Some(total_instructions))
            //Sort them by value into BTree, which removes duplicates and orders them
            .fold(BTreeSet::new(), |mut set, i| {set.insert(i); set})
            //Iterate over the sorted values
            .iter()
            //Turn every copy of two, prepending a 0, into a range
            .scan(0, |prev, x| {let out = Some(*prev..*x); *prev = *x; out})
            //Enumerate by index to differentiate odd and even values
            .enumerate()
            //Map even pairs to ranges in parent 0 and odd ones to ranges in parent 1 and expand the ranges
            .flat_map(|(index, range)| {
                {if index % 2 == 0 {parents.0} else {parents.1}}.program[range].iter().cloned()
            })
            //Collect all the instruction ranges from each parent
            .collect(),

            unit_mutate_size: if parents.0.unit_mutate_size < parents.1.unit_mutate_size {
                rng.gen_range(parents.0.unit_mutate_size, parents.1.unit_mutate_size + 1)
            } else {
                rng.gen_range(parents.1.unit_mutate_size, parents.0.unit_mutate_size + 1)
            },

            crossover_points: if parents.0.crossover_points < parents.1.crossover_points {
                rng.gen_range(parents.0.crossover_points, parents.1.crossover_points + 1)
            } else {
                rng.gen_range(parents.1.crossover_points, parents.0.crossover_points + 1)
            },

            inputs: parents.0.inputs,
            outputs: parents.0.outputs,
            mutator: {if rng.gen_range(0, 2) == 0 {parents.0} else {parents.1}}.mutator,
            processor: {if rng.gen_range(0, 2) == 0 {parents.0} else {parents.1}}.processor,
            _phantom: (PhantomData, PhantomData),
        }
    }

    ///The Mep mutate function operates using the unit_mutate_size. This variable specifies the amount of instructions
    ///for which a single mutation is expect to occour every time mutate is called. This variable can be mutated inside
    ///of mutate, in which case it may never go below 1, but may tend towards infinity in increments of 1. This variable
    ///is implemented as a u64 to permit it to expand unbounded to mutation levels that are so low that mutations
    ///virtually never happen. Allowing this to mutate allows species to find the equilibrium between genomic
    ///adaptability and stability. If a species develops information gathering, then it can adapt intellegently, making
    ///it possibly more beneficial to operate at lower mutation rates. Setting the default mutation rate for species
    ///properly, or allowing it to adapt as the simulation continues, permits species to survive more frequently that
    ///are randomly generated.
    fn mutate(&mut self, rng: &mut R) {
        //Mutate unit_mutate_size
        if rng.gen_range(0, self.unit_mutate_size) == 0 {
            //Make it possibly go up or down by 1
            match rng.gen_range(0, 2) {
                0 => self.unit_mutate_size += 1,
                1 => if self.unit_mutate_size > 1 {self.unit_mutate_size -= 1},
                _ => unreachable!(),
            }
        }
        //Mutate crossover_points
        if rng.gen_range(0, self.unit_mutate_size) == 0 {
            //Make it possibly go up or down by 1
            match rng.gen_range(0, 2) {
                0 => self.crossover_points += 1,
                1 => if self.crossover_points > 1 {self.crossover_points -= 1},
                _ => unreachable!(),
            }
        }

        //Mutate the instructions using the mutator
        loop {
            //Choose a random location in the instructions and then add a random value up to the unit_mutate_size
            let choice = rng.gen_range(0, self.program.len() + self.unit_mutate_size);
            //Whenever we choose a location outside the vector reject the choice and end mutation
            if choice >= self.program.len() {
                break;
            }
            let op = &mut self.program[choice];
            //Randomly mutate only one of the things contained here
            match rng.gen_range(0, 3) {
                0 => (self.mutator)(&mut op.instruction, rng),
                1 => op.first = rng.gen_range(0, choice + self.inputs),
                2 => op.second = rng.gen_range(0, choice + self.inputs),
                _ => unreachable!(),
            }
        }
    }
}

impl<'a, Ins: 'a, R: 'a, Param: 'a, F1: 'a, F2: 'a> SISO<'a, Param, Param> for Mep<Ins, R, Param, F1, F2>
    where F2: Fn(&Ins, Param, Param) -> Param, Param: Clone
{
    type Iter = ResultIterator<'a, Ins, R, Param, F1, F2>;

    fn compute(&'a self, inputs: &'a [Param]) -> Self::Iter {
        //Ensure we have enough opcodes to produce the desired amount of outputs, otherwise the programmer has failed
        assert!(self.outputs <= self.program.len());
        ResultIterator{
            mep: self,
            buff: vec![None; self.program.len()],
            solve_iter: ((self.program.len() + self.inputs - self.outputs)..(self.program.len() + self.inputs)).rev(),
            inputs: inputs,
        }
    }
}

pub struct ResultIterator<'a, Ins: 'a, R: 'a, Param: 'a, F1: 'a, F2: 'a> {
    mep: &'a Mep<Ins, R, Param, F1, F2>,
    buff: Vec<Option<Param>>,
    solve_iter: Rev<Range<usize>>,
    inputs: &'a [Param],
}

impl<'a, Ins, R, Param, F1, F2> ResultIterator<'a, Ins, R, Param, F1, F2>
    where F2: Fn(&Ins, Param, Param) -> Param, Param: Clone
{
    fn op_solved(&mut self, i: usize) -> Param {
        //If this is an input, it is already solved, so return the result immediately
        if i < self.mep.inputs {
            return unsafe{
                self.inputs.get_unchecked(i)
            }.clone();
        }
        //Check if this has been evaluated or not
        let possible = unsafe{
            self.buff.get_unchecked(i - self.mep.inputs)
        }.clone();
        match possible {
            //If it has, return the value
            Some(x) => x,
            //If it hasnt been solved
            None => {
                //Get a reference to the opcode
                let op = unsafe{
                    self.mep.program.get_unchecked(i - self.mep.inputs)
                };
                //Compute the result of the operation, ensuring the inputs are solved beforehand
                let result = (self.mep.processor)(&op.instruction, self.op_solved(op.first), self.op_solved(op.second));
                //Properly store the Some result to the buffer
                unsafe{
                    *self.buff.get_unchecked_mut(i - self.mep.inputs) = Some(result.clone())
                };
                //Return the result
                result
            }
        }
    }
}

impl<'a, Ins, R, Param, F1, F2> Iterator for ResultIterator<'a, Ins, R, Param, F1, F2>
    where F2: Fn(&Ins, Param, Param) -> Param, Param: Clone
{
    type Item = Param;
    fn next(&mut self) -> Option<Param> {
        match self.solve_iter.next() {
            None => None,
            Some(i) => Some(self.op_solved(i)),
        }
    }
}

#[cfg(test)]
mod tests {
    use rand::{Isaac64Rng, SeedableRng, Rng};
    use super::*;
    use super::super::{Genetic, SISO};

    fn mutator(_: &mut i32, _: &mut Isaac64Rng) {}
    fn processor(_: &i32, _: i32, _: i32) -> i32 {0}

    #[test]
    fn new() {
        let a = Mep::new(3, 1, 10, 10, &mut Isaac64Rng::from_seed(&[1, 2, 3, 4]), 0..30, mutator, processor);

        assert_eq!(a.program.iter().map(|i| i.instruction).collect::<Vec<_>>(), (0..30).collect::<Vec<_>>());
    }

    #[test]
    fn crossover() {
        let mut rng = Isaac64Rng::from_seed(&[1, 2, 3, 4]);
        let (a, b) = {
            let mut clos = || Mep::new(3, 1, 10, 10, &mut rng, 0..30, mutator, processor);
            (clos(), clos())
        };
        let old_rngs: Vec<_> = rng.clone().gen_iter::<i32>().take(5).collect();
        let _ = Mep::mate((&a, &b), &mut rng);
        //Ensure that rng was borrowed mutably
        assert!(rng.clone().gen_iter::<i32>().take(5).collect::<Vec<_>>() != old_rngs);
    }

    #[test]
    fn compute() {
        let mut rng = Isaac64Rng::from_seed(&[1, 2, 3, 4]);
        let a = Mep::new(3, 1, 10, 10, &mut rng, 0..30, mutator, processor);

        let inputs = [2, 3, 4];
        assert_eq!(a.compute(&inputs[..]).collect::<Vec<_>>(), [0]);
    }
}
<commit_msg>disallow output instructions from using other outputs as inputs<commit_after>extern crate num;
use std::collections::BTreeSet;
use std::cmp;
use rand::Rng;
use std::ops::Range;
use std::iter::Rev;
use super::{Genetic, SISO};
use std::marker::PhantomData;

///Defines an opcode for the Mep. Every opcode contains an instruction and two parameter indices. These specify which
///previous opcodes produced the result required as inputs to this opcode. These parameters can also come from the inputs
///to the program, which sequentially preceed the internal instructions.
#[derive(Clone, Copy)]
struct Opcode<Ins> {
    instruction: Ins,
    first: usize,
    second: usize,
}

///A multi-expression program represented using a series of operations that can reuse results of previous operations.
pub struct Mep<Ins, R, Param, F1, F2> {
    program: Vec<Opcode<Ins>>,
    pub unit_mutate_size: usize,
    pub crossover_points: usize,
    inputs: usize,
    outputs: usize,
    mutator: F1,
    processor: F2,
    _phantom: (PhantomData<R>, PhantomData<Param>),
}

impl<Ins, R, Param, F1, F2> Clone for Mep<Ins, R, Param, F1, F2>
    where Ins: Clone, F1: Copy, F2: Copy
{
    fn clone(&self) -> Self {
        Mep{
            program: self.program.clone(),
            unit_mutate_size: self.unit_mutate_size,
            crossover_points: self.crossover_points,
            inputs: self.inputs,
            outputs: self.outputs,
            mutator: self.mutator,
            processor: self.processor,
            _phantom: (PhantomData, PhantomData),
        }
    }
}

impl<Ins, R, Param, F1, F2> Mep<Ins, R, Param, F1, F2> {
    ///Generates a new Mep with a particular size and takes a closure to generate random instructions.
    ///Takes an RNG as well to generate random internal data for each instruction. This Rng is different from the Mep's
    ///Rng, thus it is parameterized separately here.
    pub fn new<I, Rg>(inputs: usize, outputs: usize, unit_mutate_size: usize, crossover_points: usize, rng: &mut Rg,
        instruction_iter: I, mutator: F1, processor: F2) -> Self
        where I: ExactSizeIterator<Item=Ins>, Rg: Rng, F1: Fn(&mut Ins, &mut R), F2: Fn(&Ins, Param, Param) -> Param
    {
        let outputs_beginning = instruction_iter.len() - outputs;
        Mep{
            program: instruction_iter.enumerate()
                .map(|(index, ins)|
                    // For normal instructions previous outputs may be used.
                    if index < outputs_beginning {
                        Opcode{
                            instruction: ins,
                            first: rng.gen_range(0, index + inputs),
                            second: rng.gen_range(0, index + inputs),
                        }
                    // An output should not be used as an input to another output.
                    } else {
                        Opcode{
                            instruction: ins,
                            first: rng.gen_range(0, outputs_beginning + inputs),
                            second: rng.gen_range(0, outputs_beginning + inputs),
                        }
                    }
                )
                .collect(),
            unit_mutate_size: unit_mutate_size,
            crossover_points: crossover_points,
            inputs: inputs,
            outputs: outputs,
            mutator: mutator,
            processor: processor,
            _phantom: (PhantomData, PhantomData),
        }
    }
}

impl<Ins, R, Param, F1, F2> Genetic<R> for Mep<Ins, R, Param, F1, F2>
    where R: Rng, Ins: Clone, Param: Clone, F1: Copy + Fn(&mut Ins, &mut R), F2: Copy
{
    fn mate(parents: (&Self, &Self), rng: &mut R) -> Self {
        //Each Mep must have the same amount of inputs
        //TODO: Once Rust implements generic values, this can be made explicit and is not needed
        assert!(parents.0.inputs == parents.1.inputs);
        assert!(parents.0.outputs == parents.1.outputs);
        //Get the smallest of the two lengths
        let total_instructions = cmp::min(parents.0.program.len(), parents.1.program.len());
        let crossover_choice = rng.gen_range(0, 2);
        Mep{program:
            //Generate a randomly sized sequence between 1 and crossover_points
            (0..rng.gen_range(1, cmp::min(total_instructions / 2, {
                if crossover_choice == 0 {parents.0}
                else {parents.1}}.crossover_points + 1)))
            //Map these to random crossover points
            .map(|_| rng.gen_range(0, total_instructions))
            //Add total_instructions at the end so we can generate a range with it
            .chain(Some(total_instructions))
            //Sort them by value into BTree, which removes duplicates and orders them
            .fold(BTreeSet::new(), |mut set, i| {set.insert(i); set})
            //Iterate over the sorted values
            .iter()
            //Turn every copy of two, prepending a 0, into a range
            .scan(0, |prev, x| {let out = Some(*prev..*x); *prev = *x; out})
            //Enumerate by index to differentiate odd and even values
            .enumerate()
            //Map even pairs to ranges in parent 0 and odd ones to ranges in parent 1 and expand the ranges
            .flat_map(|(index, range)| {
                {if index % 2 == 0 {parents.0} else {parents.1}}.program[range].iter().cloned()
            })
            //Collect all the instruction ranges from each parent
            .collect(),

            unit_mutate_size: if parents.0.unit_mutate_size < parents.1.unit_mutate_size {
                rng.gen_range(parents.0.unit_mutate_size, parents.1.unit_mutate_size + 1)
            } else {
                rng.gen_range(parents.1.unit_mutate_size, parents.0.unit_mutate_size + 1)
            },

            crossover_points: if parents.0.crossover_points < parents.1.crossover_points {
                rng.gen_range(parents.0.crossover_points, parents.1.crossover_points + 1)
            } else {
                rng.gen_range(parents.1.crossover_points, parents.0.crossover_points + 1)
            },

            inputs: parents.0.inputs,
            outputs: parents.0.outputs,
            mutator: {if rng.gen_range(0, 2) == 0 {parents.0} else {parents.1}}.mutator,
            processor: {if rng.gen_range(0, 2) == 0 {parents.0} else {parents.1}}.processor,
            _phantom: (PhantomData, PhantomData),
        }
    }

    ///The Mep mutate function operates using the unit_mutate_size. This variable specifies the amount of instructions
    ///for which a single mutation is expect to occour every time mutate is called. This variable can be mutated inside
    ///of mutate, in which case it may never go below 1, but may tend towards infinity in increments of 1. This variable
    ///is implemented as a u64 to permit it to expand unbounded to mutation levels that are so low that mutations
    ///virtually never happen. Allowing this to mutate allows species to find the equilibrium between genomic
    ///adaptability and stability. If a species develops information gathering, then it can adapt intellegently, making
    ///it possibly more beneficial to operate at lower mutation rates. Setting the default mutation rate for species
    ///properly, or allowing it to adapt as the simulation continues, permits species to survive more frequently that
    ///are randomly generated.
    fn mutate(&mut self, rng: &mut R) {
        //Mutate unit_mutate_size
        if rng.gen_range(0, self.unit_mutate_size) == 0 {
            //Make it possibly go up or down by 1
            match rng.gen_range(0, 2) {
                0 => self.unit_mutate_size += 1,
                1 => if self.unit_mutate_size > 1 {self.unit_mutate_size -= 1},
                _ => unreachable!(),
            }
        }
        //Mutate crossover_points
        if rng.gen_range(0, self.unit_mutate_size) == 0 {
            //Make it possibly go up or down by 1
            match rng.gen_range(0, 2) {
                0 => self.crossover_points += 1,
                1 => if self.crossover_points > 1 {self.crossover_points -= 1},
                _ => unreachable!(),
            }
        }

        //Mutate the instructions using the mutator
        loop {
            //Choose a random location in the instructions and then add a random value up to the unit_mutate_size
            let choice = rng.gen_range(0, self.program.len() + self.unit_mutate_size);
            //Whenever we choose a location outside the vector reject the choice and end mutation
            if choice >= self.program.len() {
                break;
            }
            let op = &mut self.program[choice];
            //Randomly mutate only one of the things contained here
            match rng.gen_range(0, 3) {
                0 => (self.mutator)(&mut op.instruction, rng),
                1 => op.first = rng.gen_range(0, choice + self.inputs),
                2 => op.second = rng.gen_range(0, choice + self.inputs),
                _ => unreachable!(),
            }
        }
    }
}

impl<'a, Ins: 'a, R: 'a, Param: 'a, F1: 'a, F2: 'a> SISO<'a, Param, Param> for Mep<Ins, R, Param, F1, F2>
    where F2: Fn(&Ins, Param, Param) -> Param, Param: Clone
{
    type Iter = ResultIterator<'a, Ins, R, Param, F1, F2>;

    fn compute(&'a self, inputs: &'a [Param]) -> Self::Iter {
        //Ensure we have enough opcodes to produce the desired amount of outputs, otherwise the programmer has failed
        assert!(self.outputs <= self.program.len());
        ResultIterator{
            mep: self,
            buff: vec![None; self.program.len()],
            solve_iter: ((self.program.len() + self.inputs - self.outputs)..(self.program.len() + self.inputs)).rev(),
            inputs: inputs,
        }
    }
}

pub struct ResultIterator<'a, Ins: 'a, R: 'a, Param: 'a, F1: 'a, F2: 'a> {
    mep: &'a Mep<Ins, R, Param, F1, F2>,
    buff: Vec<Option<Param>>,
    solve_iter: Rev<Range<usize>>,
    inputs: &'a [Param],
}

impl<'a, Ins, R, Param, F1, F2> ResultIterator<'a, Ins, R, Param, F1, F2>
    where F2: Fn(&Ins, Param, Param) -> Param, Param: Clone
{
    fn op_solved(&mut self, i: usize) -> Param {
        //If this is an input, it is already solved, so return the result immediately
        if i < self.mep.inputs {
            return unsafe{
                self.inputs.get_unchecked(i)
            }.clone();
        }
        //Check if this has been evaluated or not
        let possible = unsafe{
            self.buff.get_unchecked(i - self.mep.inputs)
        }.clone();
        match possible {
            //If it has, return the value
            Some(x) => x,
            //If it hasnt been solved
            None => {
                //Get a reference to the opcode
                let op = unsafe{
                    self.mep.program.get_unchecked(i - self.mep.inputs)
                };
                //Compute the result of the operation, ensuring the inputs are solved beforehand
                let result = (self.mep.processor)(&op.instruction, self.op_solved(op.first), self.op_solved(op.second));
                //Properly store the Some result to the buffer
                unsafe{
                    *self.buff.get_unchecked_mut(i - self.mep.inputs) = Some(result.clone())
                };
                //Return the result
                result
            }
        }
    }
}

impl<'a, Ins, R, Param, F1, F2> Iterator for ResultIterator<'a, Ins, R, Param, F1, F2>
    where F2: Fn(&Ins, Param, Param) -> Param, Param: Clone
{
    type Item = Param;
    fn next(&mut self) -> Option<Param> {
        match self.solve_iter.next() {
            None => None,
            Some(i) => Some(self.op_solved(i)),
        }
    }
}

#[cfg(test)]
mod tests {
    use rand::{Isaac64Rng, SeedableRng, Rng};
    use super::*;
    use super::super::{Genetic, SISO};

    fn mutator(_: &mut i32, _: &mut Isaac64Rng) {}
    fn processor(_: &i32, _: i32, _: i32) -> i32 {0}

    #[test]
    fn new() {
        let a = Mep::new(3, 1, 10, 10, &mut Isaac64Rng::from_seed(&[1, 2, 3, 4]), 0..30, mutator, processor);

        assert_eq!(a.program.iter().map(|i| i.instruction).collect::<Vec<_>>(), (0..30).collect::<Vec<_>>());
    }

    #[test]
    fn crossover() {
        let mut rng = Isaac64Rng::from_seed(&[1, 2, 3, 4]);
        let (a, b) = {
            let mut clos = || Mep::new(3, 1, 10, 10, &mut rng, 0..30, mutator, processor);
            (clos(), clos())
        };
        let old_rngs: Vec<_> = rng.clone().gen_iter::<i32>().take(5).collect();
        let _ = Mep::mate((&a, &b), &mut rng);
        //Ensure that rng was borrowed mutably
        assert!(rng.clone().gen_iter::<i32>().take(5).collect::<Vec<_>>() != old_rngs);
    }

    #[test]
    fn compute() {
        let mut rng = Isaac64Rng::from_seed(&[1, 2, 3, 4]);
        let a = Mep::new(3, 1, 10, 10, &mut rng, 0..30, mutator, processor);

        let inputs = [2, 3, 4];
        assert_eq!(a.compute(&inputs[..]).collect::<Vec<_>>(), [0]);
    }
}
<|endoftext|>