<commit_before>use std::convert;
use std::io;
use std::result;
use std::num::FromPrimitive;
use std::str::Utf8Error;

use byteorder;

const FIXSTR_SIZE   : u8 = 0x1f;
const FIXARRAY_SIZE : u8 = 0x0f;
const FIXMAP_SIZE   : u8 = 0x0f;

#[derive(Debug, PartialEq)]
pub enum Marker {
    PositiveFixnum(u8),
    NegativeFixnum(i8),
    Null,
    True,
    False,
    U8,
    U16,
    U32,
    U64,
    I8,
    I16,
    I32,
    I64,
    F32,
    F64,
    FixedString(u8),
    Str8,
    Str16,
    Str32,
    Bin8,
    Bin16,
    Bin32,
    FixedArray(u8),
    Array16,
    Array32,
    FixedMap(u8),
    Map16,
    Map32,
    FixExt1,
    FixExt2,
    FixExt4,
    FixExt8,
    FixExt16,
    Ext8,
    Ext16,
    Ext32,
    Reserved,
}

impl FromPrimitive for Marker {
    fn from_i64(n: i64) -> Option<Marker> {
        FromPrimitive::from_u64(n as u64)
    }

    fn from_u64(n: u64) -> Option<Marker> {
        match n {
            val @ 0x00 ... 0x7f => Some(Marker::PositiveFixnum(val as u8)),
            val @ 0xe0 ... 0xff => Some(Marker::NegativeFixnum(val as i8)),
            val @ 0x80 ... 0x8f => Some(Marker::FixedMap((val as u8) & FIXMAP_SIZE)),
            val @ 0x90 ... 0x9f => Some(Marker::FixedArray((val as u8) & FIXARRAY_SIZE)),
            val @ 0xa0 ... 0xbf => Some(Marker::FixedString((val as u8) & FIXSTR_SIZE)),
            0xc0 => Some(Marker::Null),
            0xc1 => None, // Marked in MessagePack spec as never used.
            0xc2 => Some(Marker::False),
            0xc3 => Some(Marker::True),
            0xc4 => Some(Marker::Bin8),
            0xc5 => Some(Marker::Bin16),
            0xc6 => Some(Marker::Bin32),
            0xc7 => Some(Marker::Ext8),
            0xc8 => Some(Marker::Ext16),
            0xc9 => Some(Marker::Ext32),
            0xca => Some(Marker::F32),
            0xcb => Some(Marker::F64),
            0xcc => Some(Marker::U8),
            0xcd => Some(Marker::U16),
            0xce => Some(Marker::U32),
            0xcf => Some(Marker::U64),
            0xd0 => Some(Marker::I8),
            0xd1 => Some(Marker::I16),
            0xd2 => Some(Marker::I32),
            0xd3 => Some(Marker::I64),
            0xd4 => Some(Marker::FixExt1),
            0xd5 => Some(Marker::FixExt2),
            0xd6 => Some(Marker::FixExt4),
            0xd7 => Some(Marker::FixExt8),
            0xd8 => Some(Marker::FixExt16),
            0xd9 => Some(Marker::Str8),
            0xda => Some(Marker::Str16),
            0xdb => Some(Marker::Str32),
            0xdc => Some(Marker::Array16),
            0xdd => Some(Marker::Array32),
            0xde => Some(Marker::Map16),
            0xdf => Some(Marker::Map32),
            _ => None,
        }
    }
}

/// An error type for reading bytes from the reader.
///
/// This is a thin wrapper over the standard `io::Error` type. Namely, it adds one additional error
/// case: an unexpected EOF.
#[unstable(reason = "remove Debug trait")]
#[derive(Debug)]
pub enum ReadError {
    UnexpectedEOF,
    IO(io::Error),
}

// TODO: This is a hack, because io::Error has PartialEq once.
impl PartialEq for ReadError {
    fn eq(&self, other: &ReadError) -> bool {
        match (self, other) {
            (&ReadError::UnexpectedEOF, &ReadError::UnexpectedEOF) => true,
            (&ReadError::IO(ref lhs),   &ReadError::IO(ref rhs)) => {
                lhs.kind() == rhs.kind()
            }
            _ => false
        }
    }

    fn ne(&self, other: &ReadError) -> bool {
        return !self.eq(other);
    }
}

impl convert::From<io::Error> for ReadError {
    fn from(err: io::Error) -> ReadError { ReadError::IO(err) }
}

impl convert::From<ReadError> for io::Error {
    fn from(err: ReadError) -> io::Error {
        match err {
            ReadError::IO(err) => err,
            ReadError::UnexpectedEOF => io::Error::new(io::ErrorKind::Other, "unexpected EOF")
        }
    }
}

impl convert::From<byteorder::Error> for ReadError {
    fn from(err: byteorder::Error) -> ReadError {
        match err {
            byteorder::Error::UnexpectedEOF => ReadError::UnexpectedEOF,
            byteorder::Error::Io(err) => ReadError::IO(err),
        }
    }
}

#[unstable(reason = "remove Debug trait; drop MarkerError")]
#[derive(Debug, PartialEq)]
pub enum Error {
    /// Marker type error.
    TypeMismatch(Marker),
    /// IO error while reading marker.
    InvalidMarkerRead(ReadError),
    /// IO error while reading data.
    InvalidDataRead(ReadError),
}

#[unstable(reason = "Core? Shit name!")]
#[derive(Debug, PartialEq)]
pub enum DecodeStringError<'a> {
    Core(Error),
    /// The given buffer is too small to accumulate specified amount of bytes.
    BufferSizeTooSmall(u32),
    InvalidDataCopy(&'a [u8], ReadError),
    InvalidUtf8(&'a [u8], Utf8Error),
}

impl<'a> convert::From<Error> for DecodeStringError<'a> {
    fn from(err: Error) -> DecodeStringError<'a> {
        DecodeStringError::Core(err)
    }
}

pub type Result<T> = result::Result<T, Error>;

#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Null,
    Integer(Integer),
    String(String),
    Array(Vec<Value>),
}

pub mod decode;
<commit_msg>[Misc] Cleaning up.<commit_after>use std::convert;
use std::io;
use std::result;
use std::num::FromPrimitive;
use std::str::Utf8Error;

use byteorder;

const FIXSTR_SIZE   : u8 = 0x1f;
const FIXARRAY_SIZE : u8 = 0x0f;
const FIXMAP_SIZE   : u8 = 0x0f;

#[derive(Debug, PartialEq)]
pub enum Marker {
    PositiveFixnum(u8),
    NegativeFixnum(i8),
    Null,
    True,
    False,
    U8,
    U16,
    U32,
    U64,
    I8,
    I16,
    I32,
    I64,
    F32,
    F64,
    FixedString(u8),
    Str8,
    Str16,
    Str32,
    Bin8,
    Bin16,
    Bin32,
    FixedArray(u8),
    Array16,
    Array32,
    FixedMap(u8),
    Map16,
    Map32,
    FixExt1,
    FixExt2,
    FixExt4,
    FixExt8,
    FixExt16,
    Ext8,
    Ext16,
    Ext32,
    Reserved,
}

impl FromPrimitive for Marker {
    fn from_i64(n: i64) -> Option<Marker> {
        FromPrimitive::from_u64(n as u64)
    }

    fn from_u64(n: u64) -> Option<Marker> {
        match n {
            val @ 0x00 ... 0x7f => Some(Marker::PositiveFixnum(val as u8)),
            val @ 0xe0 ... 0xff => Some(Marker::NegativeFixnum(val as i8)),
            val @ 0x80 ... 0x8f => Some(Marker::FixedMap((val as u8) & FIXMAP_SIZE)),
            val @ 0x90 ... 0x9f => Some(Marker::FixedArray((val as u8) & FIXARRAY_SIZE)),
            val @ 0xa0 ... 0xbf => Some(Marker::FixedString((val as u8) & FIXSTR_SIZE)),
            0xc0 => Some(Marker::Null),
            0xc1 => None, // Marked in MessagePack spec as never used.
            0xc2 => Some(Marker::False),
            0xc3 => Some(Marker::True),
            0xc4 => Some(Marker::Bin8),
            0xc5 => Some(Marker::Bin16),
            0xc6 => Some(Marker::Bin32),
            0xc7 => Some(Marker::Ext8),
            0xc8 => Some(Marker::Ext16),
            0xc9 => Some(Marker::Ext32),
            0xca => Some(Marker::F32),
            0xcb => Some(Marker::F64),
            0xcc => Some(Marker::U8),
            0xcd => Some(Marker::U16),
            0xce => Some(Marker::U32),
            0xcf => Some(Marker::U64),
            0xd0 => Some(Marker::I8),
            0xd1 => Some(Marker::I16),
            0xd2 => Some(Marker::I32),
            0xd3 => Some(Marker::I64),
            0xd4 => Some(Marker::FixExt1),
            0xd5 => Some(Marker::FixExt2),
            0xd6 => Some(Marker::FixExt4),
            0xd7 => Some(Marker::FixExt8),
            0xd8 => Some(Marker::FixExt16),
            0xd9 => Some(Marker::Str8),
            0xda => Some(Marker::Str16),
            0xdb => Some(Marker::Str32),
            0xdc => Some(Marker::Array16),
            0xdd => Some(Marker::Array32),
            0xde => Some(Marker::Map16),
            0xdf => Some(Marker::Map32),
            _ => None,
        }
    }
}

/// An error type for reading bytes from the reader.
///
/// This is a thin wrapper over the standard `io::Error` type. Namely, it adds one additional error
/// case: an unexpected EOF.
#[unstable(reason = "remove Debug trait")]
#[derive(Debug)]
pub enum ReadError {
    UnexpectedEOF,
    IO(io::Error),
}

// TODO: This is a hack, because io::Error has PartialEq once.
impl PartialEq for ReadError {
    fn eq(&self, other: &ReadError) -> bool {
        match (self, other) {
            (&ReadError::UnexpectedEOF, &ReadError::UnexpectedEOF) => true,
            (&ReadError::IO(ref lhs),   &ReadError::IO(ref rhs)) => {
                lhs.kind() == rhs.kind()
            }
            _ => false
        }
    }

    fn ne(&self, other: &ReadError) -> bool {
        return !self.eq(other);
    }
}

impl convert::From<io::Error> for ReadError {
    fn from(err: io::Error) -> ReadError { ReadError::IO(err) }
}

impl convert::From<ReadError> for io::Error {
    fn from(err: ReadError) -> io::Error {
        match err {
            ReadError::IO(err) => err,
            ReadError::UnexpectedEOF => io::Error::new(io::ErrorKind::Other, "unexpected EOF")
        }
    }
}

impl convert::From<byteorder::Error> for ReadError {
    fn from(err: byteorder::Error) -> ReadError {
        match err {
            byteorder::Error::UnexpectedEOF => ReadError::UnexpectedEOF,
            byteorder::Error::Io(err) => ReadError::IO(err),
        }
    }
}

#[unstable(reason = "remove Debug trait")]
#[derive(Debug, PartialEq)]
pub enum Error {
    /// Marker type error.
    TypeMismatch(Marker),
    /// IO error while reading marker.
    InvalidMarkerRead(ReadError),
    /// IO error while reading data.
    InvalidDataRead(ReadError),
}

#[unstable(reason = "Core? Shit name!")]
#[derive(Debug, PartialEq)]
pub enum DecodeStringError<'a> {
    Core(Error),
    /// The given buffer is too small to accumulate specified amount of bytes.
    BufferSizeTooSmall(u32),
    InvalidDataCopy(&'a [u8], ReadError),
    InvalidUtf8(&'a [u8], Utf8Error),
}

impl<'a> convert::From<Error> for DecodeStringError<'a> {
    fn from(err: Error) -> DecodeStringError<'a> {
        DecodeStringError::Core(err)
    }
}

pub type Result<T> = result::Result<T, Error>;

#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Null,
    Integer(Integer),
    String(String),
    Array(Vec<Value>),
}

pub mod decode;
<|endoftext|>


<commit_before>use toml::{self, Parser, Value};

use std::fs::File;
use std::io::prelude::*;
use std::fmt;

/// Contain the configuration for ElasticSearch.
#[derive(RustcEncodable, RustcDecodable, Debug)]
pub struct ESConfig {
  pub host: String,
  pub port: u32,
  pub indexes: Vec<String>
}

impl ESConfig {
  pub fn new() -> ESConfig {
    ESConfig {
      host: "localhost".to_owned(),
      port: 9200,
      indexes: vec!["honeypot_dev_talents".to_owned()]
    }
  }
}

impl fmt::Display for ESConfig {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "ElasticSearch on {}:{} (indexes: {})",
      self.host, self.port, self.indexes.join(", "))
  }
}

/// Contain instructions about where Honeysearch must
/// listen to for new connections.
#[derive(RustcEncodable, RustcDecodable, Debug)]
pub struct HTTPConfig {
  pub host: String,
  pub port: u32
}

impl HTTPConfig {
  pub fn new() -> HTTPConfig {
    HTTPConfig {
      host: "127.0.0.1".to_owned(),
      port: 3000,
    }
  }
}

impl fmt::Display for HTTPConfig {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "Listening on http://{}...", self.host)
  }
}

/// Container for ESConfig and HTTPConfig.
#[derive(RustcEncodable, RustcDecodable, Debug)]
pub struct Config {
  pub http: HTTPConfig,
  pub es:   ESConfig
}

impl Config {
  /// Return a new `Config` fill with the default values
  pub fn new() -> Config {
    Config {
      es:   ESConfig::new(),
      http: HTTPConfig::new()
    }
  }

  /// Load, parse and return the configuration file
  /// wrapped inside a `Config`.
  pub fn load_config(path: String) -> Config {
    let config_toml = Config::read_file(path).clone();
    Config::parse(config_toml)
  }

  /// Read a file from the given path and return its content
  pub fn read_file(path: String) -> Option<String> {
    let mut config_toml = String::new();

    let mut file = match File::open(&path) {
      Ok(file) => file,
      Err(_)   => return None
    };

    file.read_to_string(&mut config_toml)
        .unwrap_or_else(|err| panic!("Error while reading config: [{}]", err));

    Some(config_toml)
  }

  /// Parse given TOML configuration file and return it
  /// wrapped inside a `Config`.
  pub fn parse(config_toml: Option<String>) -> Config {
    if config_toml.is_none() {
      println!("{} {}", "Requested configuration file cannot be found.",
                        "The default configuration will be loaded.\n");
      return Config::new();
    }

    let config_toml_ = config_toml.unwrap();
    let mut parser   = Parser::new(&*config_toml_);
    let     toml     = parser.parse();

    match toml {
      Some(config) => {
        let config = Value::Table(config);
        toml::decode(config).unwrap()
      },
      None => {
        println!("{:?}", parser.errors);
        panic!("Error while parsing the configuration file.");
      }
    }
  }
}

#[cfg(test)]
#[allow(non_upper_case_globals)]
mod tests {
  use config::*;

  const sample_config: &'static str = r#"
    [es]
    host    = "123.0.123.0"
    port    = 9000
    indexes = ["honeypot_dev_talents"]

    [http]
    host = "1.0.0.127"
    port = 3000
  "#;

  #[test]
  fn test_new() {
    // returns a Config fill with the default hardcoded data
    let config = Config::new();
    assert_eq!(config.es.host,   "localhost".to_owned());
    assert_eq!(config.http.host, "127.0.0.1".to_owned());
  }

  #[test]
  fn test_parse() {
    // returns a Config fill with given TOML configuration file
    let config = Config::parse(Some(sample_config.to_owned()));
    assert_eq!(config.es.host,   "123.0.123.0".to_owned());
    assert_eq!(config.http.host, "1.0.0.127".to_owned());
  }
}
<commit_msg>config: rename default index<commit_after>use toml::{self, Parser, Value};

use std::fs::File;
use std::io::prelude::*;
use std::fmt;

/// Contain the configuration for ElasticSearch.
#[derive(RustcEncodable, RustcDecodable, Debug)]
pub struct ESConfig {
  pub host: String,
  pub port: u32,
  pub indexes: Vec<String>
}

impl ESConfig {
  pub fn new() -> ESConfig {
    ESConfig {
      host: "localhost".to_owned(),
      port: 9200,
      indexes: vec!["my_index".to_owned()]
    }
  }
}

impl fmt::Display for ESConfig {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "ElasticSearch on {}:{} (indexes: {})",
      self.host, self.port, self.indexes.join(", "))
  }
}

/// Contain instructions about where Honeysearch must
/// listen to for new connections.
#[derive(RustcEncodable, RustcDecodable, Debug)]
pub struct HTTPConfig {
  pub host: String,
  pub port: u32
}

impl HTTPConfig {
  pub fn new() -> HTTPConfig {
    HTTPConfig {
      host: "127.0.0.1".to_owned(),
      port: 3000,
    }
  }
}

impl fmt::Display for HTTPConfig {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    write!(f, "Listening on http://{}...", self.host)
  }
}

/// Container for ESConfig and HTTPConfig.
#[derive(RustcEncodable, RustcDecodable, Debug)]
pub struct Config {
  pub http: HTTPConfig,
  pub es:   ESConfig
}

impl Config {
  /// Return a new `Config` fill with the default values
  pub fn new() -> Config {
    Config {
      es:   ESConfig::new(),
      http: HTTPConfig::new()
    }
  }

  /// Load, parse and return the configuration file
  /// wrapped inside a `Config`.
  pub fn load_config(path: String) -> Config {
    let config_toml = Config::read_file(path).clone();
    Config::parse(config_toml)
  }

  /// Read a file from the given path and return its content
  pub fn read_file(path: String) -> Option<String> {
    let mut config_toml = String::new();

    let mut file = match File::open(&path) {
      Ok(file) => file,
      Err(_)   => return None
    };

    file.read_to_string(&mut config_toml)
        .unwrap_or_else(|err| panic!("Error while reading config: [{}]", err));

    Some(config_toml)
  }

  /// Parse given TOML configuration file and return it
  /// wrapped inside a `Config`.
  pub fn parse(config_toml: Option<String>) -> Config {
    if config_toml.is_none() {
      println!("{} {}", "Requested configuration file cannot be found.",
                        "The default configuration will be loaded.\n");
      return Config::new();
    }

    let config_toml_ = config_toml.unwrap();
    let mut parser   = Parser::new(&*config_toml_);
    let     toml     = parser.parse();

    match toml {
      Some(config) => {
        let config = Value::Table(config);
        toml::decode(config).unwrap()
      },
      None => {
        println!("{:?}", parser.errors);
        panic!("Error while parsing the configuration file.");
      }
    }
  }
}

#[cfg(test)]
#[allow(non_upper_case_globals)]
mod tests {
  use config::*;

  const sample_config: &'static str = r#"
    [es]
    host    = "123.0.123.0"
    port    = 9000
    indexes = ["save_meguka"]

    [http]
    host = "1.0.0.127"
    port = 3000
  "#;

  #[test]
  fn test_new() {
    // returns a Config fill with the default hardcoded data
    let config = Config::new();
    assert_eq!(config.es.host,   "localhost".to_owned());
    assert_eq!(config.http.host, "127.0.0.1".to_owned());
  }

  #[test]
  fn test_parse() {
    // returns a Config fill with given TOML configuration file
    let config = Config::parse(Some(sample_config.to_owned()));
    assert_eq!(config.es.host,   "123.0.123.0".to_owned());
    assert_eq!(config.http.host, "1.0.0.127".to_owned());
  }
}
<|endoftext|>


<commit_before>//! A LinkedList that lets you insert elements from the front or the end of the list.
//! TODO: Add the ability to insert in-between a Node.
//! Lots of thanks to reem and Sharp for help with this from the #rust channel

use std::mem;

/// A Node is the basic unit in a LinkedList which stores the payload of type T.
#[derive(Debug,PartialEq)]
struct Node<T> {
    /// The payload of type T that is wrapped aorund a Node.
    pub payload: T,
    /// An Option of a boxed Node<T> that would point to the next Node<T>.
    next: Option<Box<Node<T>>>,
    /// An Option of a boxed Node<T> that would point to the previous Node<T>.
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {

    pub fn new(payload: T) -> Node<T> {
        //! Creates a instance of a `Node` with `next` and `prev` point to a Option::Node.
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&self) -> Option<&T> {
        //! Access to a payload of Node.
        Some(&self.payload)
    }

    pub fn insert_after(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.next, &mut self.next);
        mem::replace(&mut self.next, Some(new))
    }

    pub fn insert_before(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.prev, &mut self.prev);
        mem::replace(&mut self.prev, Some(new))
    }

    pub fn remove_after(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node after the current node.
        match self.next.take() {
            Some(mut next)  => {
                mem::swap(&mut self.next, &mut next.next);
                Some(next)
            },
            None => None,
        }
    }

    pub fn remove_before(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node before the current node.
        match self.prev.take() {
            Some(mut prev)  => {
                mem::swap(&mut self.prev, &mut prev.prev);
                Some(prev)
            },
            None => None,
        }
    }

    pub fn next(&mut self) -> Option<&mut T> {
        //! Goes to the next Node and returns an Option to it.
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *next {
            Some(ref mut next) => {
                mem::swap(&mut next.payload, payload);

                let mut next = &mut **next;     // Cannot completely understand this bit yet.
                mem::swap(&mut next.next, &mut next.prev);

                mem::swap(&mut next.prev, prev);
            },
            None => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }

    pub fn prev(&mut self) -> Option<&mut T> {
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *prev {
            Some(ref mut prev) => {
                mem::swap(&mut prev.payload, payload);

                let mut prev = &mut **prev;     // Still don't understand this bit.
                mem::swap(&mut prev.prev, &mut prev.next);

                mem::swap(&mut prev.next, next);
            },
            None => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }
}

/// A LinkedList is the struct that you would need to use to create a list of elements.
/// It contains a pointer to the first and last node in the list represented as `head and `tail`
/// respectively.
pub struct LinkedList<T> {
    /// First element in the list.
    head: Option<Box<Node<T>>>,
    /// Last element in the list.
    tail: Option<Box<Node<T>>>,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        //! Create a new LinkedList to contain a payloads with type T.
        LinkedList::<T> {
            head: None,
            tail: None,
        }
    }
}

#[test]
fn node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}

#[test]
fn node_insert_after() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    assert_eq!("two", node.next.unwrap().payload);

}

#[test]
fn node_insert_before() {
    let mut node: Node<&str> = Node::new("two");
    node.insert_before(Box::new(Node::new("one")));
    assert_eq!("one", node.prev.unwrap().payload);
}

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

}
<commit_msg>Added tests for remove_before and remove_after<commit_after>//! A LinkedList that lets you insert elements from the front or the end of the list.
//! TODO: Add the ability to insert in-between a Node.
//! Lots of thanks to reem and Sharp for help with this from the #rust channel

use std::mem;

/// A Node is the basic unit in a LinkedList which stores the payload of type T.
#[derive(Debug,PartialEq)]
struct Node<T> {
    /// The payload of type T that is wrapped aorund a Node.
    pub payload: T,
    /// An Option of a boxed Node<T> that would point to the next Node<T>.
    next: Option<Box<Node<T>>>,
    /// An Option of a boxed Node<T> that would point to the previous Node<T>.
    prev: Option<Box<Node<T>>>,
}

impl<T> Node<T> {

    pub fn new(payload: T) -> Node<T> {
        //! Creates a instance of a `Node` with `next` and `prev` point to a Option::Node.
        Node::<T> {
            payload: payload,
            next: None,
            prev: None,
        }
    }

    pub fn payload(&self) -> Option<&T> {
        //! Access to a payload of Node.
        Some(&self.payload)
    }

    pub fn insert_after(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.next, &mut self.next);
        mem::replace(&mut self.next, Some(new))
    }

    pub fn insert_before(&mut self, mut new: Box<Node<T>>) -> Option<Box<Node<T>>> {
        //! Takes a new boxed Node<T> and swaps it with any existing Node after the current one.
        //! We replace any Option::None or Option::Some with a new Option<Box<Node<T>>>
        mem::swap(&mut new.prev, &mut self.prev);
        mem::replace(&mut self.prev, Some(new))
    }

    pub fn remove_after(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node after the current node.
        match self.next.take() {
            Some(mut next)  => {
                mem::swap(&mut self.next, &mut next.next);
                Some(next)
            },
            None => None,
        }
    }

    pub fn remove_before(&mut self) -> Option<Box<Node<T>>> {
        //! Removes the Node before the current node.
        match self.prev.take() {
            Some(mut prev)  => {
                mem::swap(&mut self.prev, &mut prev.prev);
                Some(prev)
            },
            None => None,
        }
    }

    pub fn next(&mut self) -> Option<&mut T> {
        //! Goes to the next Node and returns an Option to it.
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *next {
            Some(ref mut next) => {
                mem::swap(&mut next.payload, payload);

                let mut next = &mut **next;     // Cannot completely understand this bit yet.
                mem::swap(&mut next.next, &mut next.prev);

                mem::swap(&mut next.prev, prev);
            },
            None => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }

    pub fn prev(&mut self) -> Option<&mut T> {
        let Node {
            ref mut payload,
            ref mut prev,
            ref mut next,
        } = *self;

        match *prev {
            Some(ref mut prev) => {
                mem::swap(&mut prev.payload, payload);

                let mut prev = &mut **prev;     // Still don't understand this bit.
                mem::swap(&mut prev.prev, &mut prev.next);

                mem::swap(&mut prev.next, next);
            },
            None => return None,
        }
        mem::swap(prev, next);
        Some(payload)
    }
}

/// A LinkedList is the struct that you would need to use to create a list of elements.
/// It contains a pointer to the first and last node in the list represented as `head and `tail`
/// respectively.
pub struct LinkedList<T> {
    /// First element in the list.
    head: Option<Box<Node<T>>>,
    /// Last element in the list.
    tail: Option<Box<Node<T>>>,
}

impl<T> LinkedList<T> {
    pub fn new() -> LinkedList<T> {
        //! Create a new LinkedList to contain a payloads with type T.
        LinkedList::<T> {
            head: None,
            tail: None,
        }
    }
}

#[test]
fn node_new() {
    let expected = Node {
        payload: "test",
        next: None,
        prev: None,
    };

    let node: Node<&str> = Node::new("test");

    assert_eq!(expected.payload,  node.payload);
    assert_eq!(expected.next,     node.next);
    assert_eq!(expected.prev,     node.prev);
}

#[test]
fn node_payload() {
    let node: Node<&str> = Node::new("test");
    assert_eq!(&"test", node.payload().unwrap());
}

#[test]
fn node_insert_after() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    assert_eq!("two", node.next.unwrap().payload);

}

#[test]
fn node_insert_before() {
    let mut node: Node<&str> = Node::new("two");
    node.insert_before(Box::new(Node::new("one")));
    assert_eq!("one", node.prev.unwrap().payload);
}

#[test]
fn node_remove_next() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_after(Box::new(Node::new("two")));
    node.remove_after();
}

#[test]
fn node_remove_prev() {
    let mut node: Node<&str> = Node::new("one");
    node.insert_before(Box::new(Node::new("two")));
    node.remove_before();
}

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

}
<|endoftext|>


<commit_before>use super::super::{Domain, DspVec, MetaData, RealNumberSpace, ToSliceMut, Vector};
use multicore_support::*;
use numbers::*;
use simd_extensions::*;

/// Operations on real types.
///
/// # Failures
///
/// If one of the methods is called on complex data then `self.len()` will be set to `0`.
/// To avoid this it's recommended to use the `to_real_time_vec`, `to_real_freq_vec`
/// `to_complex_time_vec` and `to_complex_freq_vec` constructor methods since
/// the resulting types will already check at compile time (using the type system)
/// that the data is real.
pub trait RealOps {
    /// Gets the absolute value of all vector elements.
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(1.0, -2.0).to_real_time_vec();
    /// vector.abs();
    /// assert_eq!([1.0, 2.0], vector[..]);
    /// ```
    fn abs(&mut self);
}

/// Operations on real types.
///
/// # Failures
///
/// If one of the methods is called on complex data then `self.len()` will be set to `0`.
/// To avoid this it's recommended to use the `to_real_time_vec`, `to_real_freq_vec`
/// `to_complex_time_vec` and `to_complex_freq_vec` constructor methods since
/// the resulting types will already check at compile time (using the type system)
/// that the data is real.
pub trait ModuloOps<T>
where
    T: RealNumber,
{
    /// Each value in the vector is dividable by the divisor and the remainder
    /// is stored in the resulting
    /// vector. This the same a modulo operation or to phase wrapping.
    ///
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0).to_real_time_vec();
    /// vector.wrap(4.0);
    /// assert_eq!([1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0], vector[..]);
    /// ```
    fn wrap(&mut self, divisor: T);

    /// This function corrects the jumps in the given vector which occur due
    /// to wrap or modulo operations.
    /// This will undo a wrap operation only if the deltas are smaller than half the divisor.
    ///
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.).to_real_time_vec();
    /// vector.unwrap(4.0);
    /// assert_eq!([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], vector[..]);
    /// ```
    fn unwrap(&mut self, divisor: T);
}

/// Recommended to be only used with the CPU feature flags `sse` or `avx`.
///
/// This trait provides alternative implementations for some standard functions which
/// are less accurate but perform faster. Those approximations are written for SSE2 or AVX2 processors.
/// If a processor supports neither of those instruction sets, then the standard functions will be used.
///
/// Information on the error of the approximation and their performance are rough numbers.
/// A detailed table can be obtained by running the `approx_accuracy` example.
///
/// # Failures
///
/// If one of the methods is called on complex data then `self.len()` will be set to `0`.
/// To avoid this it's recommended to use the `to_real_time_vec`, `to_real_freq_vec`
/// `to_complex_time_vec` and `to_complex_freq_vec` constructor methods since
/// the resulting types will already check at compile time (using the type system)
/// that the data is real.
pub trait ApproximatedOps<T>
where
    T: RealNumber,
{
    /// Computes the principal value approximation of natural logarithm of every element in the vector.
    ///
    /// Error should be below `1%` as long as the values in the vector are larger than `1`.
    /// Single core performance should be about `5x` as fast.
    ///
    /// # Example
    ///
    /// ```
    /// # use std::f64;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(2.718281828459045, 7.389056, 20.085537).to_real_time_vec();
    /// vector.ln_approx();
    /// let actual = &vector[0..];
    /// let expected = &[1.0, 2.0, 3.0];
    /// assert_eq!(actual.len(), expected.len());
    /// for i in 0..actual.len() {
    ///        assert!(f64::abs(actual[i] - expected[i]) < 1e-2);
    /// }
    /// ```
    fn ln_approx(&mut self);

    /// Calculates the natural exponential approximation for every vector element.
    ///
    /// Error should be less than `1%`` as long as the values in the vector are small
    /// (e.g. in the range between -10 and 10).
    /// Single core performance should be about `50%` faster.
    ///
    /// # Example
    ///
    /// ```
    /// # use std::f64;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(1.0, 2.0, 3.0).to_real_time_vec();
    /// vector.exp_approx();
    /// let actual = &vector[0..];
    /// let expected = &[2.718281828459045, 7.389056, 20.085537];
    /// assert_eq!(actual.len(), expected.len());
    /// for i in 0..actual.len() {
    ///        assert!(f64::abs(actual[i] - expected[i]) < 1e-4);
    /// }
    /// ```
    fn exp_approx(&mut self);

    /// Calculates the sine approximation of each element in radians.
    ///
    /// Error should be below `1E-6`.
    /// Single core performance should be about `2x` as fast.
    ///
    /// # Example
    ///
    /// ```
    /// use std::f32;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(f32::consts::PI/2.0, -f32::consts::PI/2.0).to_real_time_vec();
    /// vector.sin_approx();
    /// assert_eq!([1.0, -1.0], vector[..]);
    /// ```
    fn sin_approx(&mut self);

    /// Calculates the cosine approximation of each element in radians
    ///
    /// Error should be below `1E-6`.
    /// Single core performance should be about `2x` as fast.
    ///
    /// # Example
    ///
    /// ```
    /// use std::f32;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(2.0 * f32::consts::PI, f32::consts::PI).to_real_time_vec();
    /// vector.cos_approx();
    /// assert_eq!([1.0, -1.0], vector[..]);
    /// ```
    fn cos_approx(&mut self);

    /// Calculates the approximated logarithm to the given base for every vector element.
    ///
    /// Error should be below `1%` as long as the values in the vector are larger than `1`.
    /// Single core performance should be about `5x` as fast.
    ///
    /// # Example
    ///
    /// ```
    /// # use std::f64;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(10.0, 100.0, 1000.0).to_real_time_vec();
    /// vector.log_approx(10.0);
    /// let actual = &vector[0..];
    /// let expected = &[1.0, 2.0, 3.0];
    /// assert_eq!(actual.len(), expected.len());
    /// for i in 0..actual.len() {
    ///        assert!(f64::abs(actual[i] - expected[i]) < 1e-4);
    /// }
    /// ```
    fn log_approx(&mut self, base: T);

    /// Calculates the approximated exponential to the given base for every vector element.
    ///
    /// Error should be less than `1%`` as long as the values in the vector are small
    /// (e.g. in the range between -10 and 10).
    /// Single core performance should be about `5x` as fast.
    ///
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// use std::f32;
    /// let vector: Vec<f32> = vec!(1.0, 2.0, 3.0);
    /// let mut vector = vector.to_real_time_vec();
    /// vector.expf_approx(10.0);
    /// assert!((vector[0] - 10.0).abs() < 1e-3);
    /// assert!((vector[1] - 100.0).abs() < 1e-3);
    /// assert!((vector[2] - 1000.0).abs() < 1e-3);
    /// ```
    fn expf_approx(&mut self, base: T);

    /// Raises every vector element to approximately a floating point power.
    ///
    /// Error should be less than `1%`` as long as the values in the vector are really small
    /// (e.g. in the range between -0.1 and 0.1).
    /// Single core performance should be about `5x` as fast.
    ///
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// use std::f32;
    /// let vector: Vec<f32> = vec!(1.0, 2.0, 3.0);
    /// let mut vector = vector.to_real_time_vec();
    /// vector.powf_approx(3.0);
    /// assert!((vector[0] - 1.0).abs() < 1e-3);
    /// assert!((vector[1] - 8.0).abs() < 1e-3);
    /// assert!((vector[2] - 27.0).abs() < 1e-3);
    /// ```
    fn powf_approx(&mut self, exponent: T);
}

macro_rules! assert_real {
    ($self_: ident) => {
        if $self_.is_complex() {
            $self_.mark_vector_as_invalid();
            return;
        }
    };
}

impl<S, T, N, D> RealOps for DspVec<S, T, N, D>
where
    S: ToSliceMut<T>,
    T: RealNumber,
    N: RealNumberSpace,
    D: Domain,
{
    fn abs(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| (x * x).sqrt(),
            |x, _arg| x.abs(),
            (),
            Complexity::Small
        ));
    }
}

impl<S, T, N, D> ModuloOps<T> for DspVec<S, T, N, D>
where
    S: ToSliceMut<T>,
    T: RealNumber,
    N: RealNumberSpace,
    D: Domain,
{
    fn wrap(&mut self, divisor: T) {
        assert_real!(self);
        self.pure_real_operation(|x, y| x % y, divisor, Complexity::Small);
    }

    fn unwrap(&mut self, divisor: T) {
        assert_real!(self);
        let data_length = self.len();
        let data = self.data.to_slice_mut();
        let mut i = 0;
        let mut j = 1;
        let half = divisor / T::from(2.0).unwrap();
        while j < data_length {
            let mut diff = data[j] - data[i];
            if diff > half {
                diff = diff % divisor;
                diff = diff - divisor;
                data[j] = data[i] + diff;
            } else if diff < -half {
                diff = diff % divisor;
                diff = diff + divisor;
                data[j] = data[i] + diff;
            }

            i += 1;
            j += 1;
        }
    }
}

/// Complexity of all approximation functions. Small, because with the SIMD optimizations
/// threading becomes less beneficial.
const APPROX_COMPLEXITY: Complexity = Complexity::Small;

impl<S, T, N, D> ApproximatedOps<T> for DspVec<S, T, N, D>
where
    S: ToSliceMut<T>,
    T: RealNumber,
    N: RealNumberSpace,
    D: Domain,
{
    fn ln_approx(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| x.ln_approx(),
            |x, _arg| x.ln(),
            (),
            APPROX_COMPLEXITY
        ));
    }

    fn exp_approx(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| x.exp_approx(),
            |x, _arg| x.exp(),
            (),
            APPROX_COMPLEXITY
        ));
    }

    fn sin_approx(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| x.sin_approx(),
            |x, _arg| x.sin(),
            (),
            APPROX_COMPLEXITY
        ));
    }

    fn cos_approx(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| x.cos_approx(),
            |x, _arg| x.cos(),
            (),
            APPROX_COMPLEXITY
        ));
    }

    fn log_approx(&mut self, base: T) {
        assert_real!(self);
        sel_reg!(self.simd_real_operationf::<T>(
            |x, b| x.ln_approx() / b,
            |x, b| x.ln() / b.extract(0),
            base.ln(),
            APPROX_COMPLEXITY
        ));
    }

    fn expf_approx(&mut self, base: T) {
        assert_real!(self);
        // Transform base with:
        // x^y = e^(ln(x)*y)
        sel_reg!(self.simd_real_operationf::<T>(
            |y, x| (x * y).exp_approx(),
            |y, x| (x.extract(0) * y).exp(),
            base.ln(),
            APPROX_COMPLEXITY
        ));
    }

    fn powf_approx(&mut self, exponent: T) {
        assert_real!(self);
        // Transform base with the same equation as for `expf_approx`
        sel_reg!(self.simd_real_operationf::<T>(
            |x, y| (x.ln_approx() * y).exp_approx(),
            |x, y| (x.ln() * y.extract(0)).exp(),
            exponent,
            APPROX_COMPLEXITY
        ));
    }
}
<commit_msg>Setting some doc tests to no_run. The failures are caused by an LLVM error which is triggered bei avx::max and avx::min. However the same code runs fine in a regular test and in fact the doc test doesn't even execute the avx code branch.<commit_after>use super::super::{Domain, DspVec, MetaData, RealNumberSpace, ToSliceMut, Vector};
use multicore_support::*;
use numbers::*;
use simd_extensions::*;

/// Operations on real types.
///
/// # Failures
///
/// If one of the methods is called on complex data then `self.len()` will be set to `0`.
/// To avoid this it's recommended to use the `to_real_time_vec`, `to_real_freq_vec`
/// `to_complex_time_vec` and `to_complex_freq_vec` constructor methods since
/// the resulting types will already check at compile time (using the type system)
/// that the data is real.
pub trait RealOps {
    /// Gets the absolute value of all vector elements.
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(1.0, -2.0).to_real_time_vec();
    /// vector.abs();
    /// assert_eq!([1.0, 2.0], vector[..]);
    /// ```
    fn abs(&mut self);
}

/// Operations on real types.
///
/// # Failures
///
/// If one of the methods is called on complex data then `self.len()` will be set to `0`.
/// To avoid this it's recommended to use the `to_real_time_vec`, `to_real_freq_vec`
/// `to_complex_time_vec` and `to_complex_freq_vec` constructor methods since
/// the resulting types will already check at compile time (using the type system)
/// that the data is real.
pub trait ModuloOps<T>
where
    T: RealNumber,
{
    /// Each value in the vector is dividable by the divisor and the remainder
    /// is stored in the resulting
    /// vector. This the same a modulo operation or to phase wrapping.
    ///
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0).to_real_time_vec();
    /// vector.wrap(4.0);
    /// assert_eq!([1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.0], vector[..]);
    /// ```
    fn wrap(&mut self, divisor: T);

    /// This function corrects the jumps in the given vector which occur due
    /// to wrap or modulo operations.
    /// This will undo a wrap operation only if the deltas are smaller than half the divisor.
    ///
    /// # Example
    ///
    /// ```
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(1.0, 2.0, 3.0, 0.0, 1.0, 2.0, 3.0, 0.).to_real_time_vec();
    /// vector.unwrap(4.0);
    /// assert_eq!([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0], vector[..]);
    /// ```
    fn unwrap(&mut self, divisor: T);
}

/// Recommended to be only used with the CPU feature flags `sse` or `avx`.
///
/// This trait provides alternative implementations for some standard functions which
/// are less accurate but perform faster. Those approximations are written for SSE2 or AVX2 processors.
/// If a processor supports neither of those instruction sets, then the standard functions will be used.
///
/// Information on the error of the approximation and their performance are rough numbers.
/// A detailed table can be obtained by running the `approx_accuracy` example.
///
/// # Failures
///
/// If one of the methods is called on complex data then `self.len()` will be set to `0`.
/// To avoid this it's recommended to use the `to_real_time_vec`, `to_real_freq_vec`
/// `to_complex_time_vec` and `to_complex_freq_vec` constructor methods since
/// the resulting types will already check at compile time (using the type system)
/// that the data is real.
pub trait ApproximatedOps<T>
where
    T: RealNumber,
{
    /// Computes the principal value approximation of natural logarithm of every element in the vector.
    ///
    /// Error should be below `1%` as long as the values in the vector are larger than `1`.
    /// Single core performance should be about `5x` as fast.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use std::f64;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(2.718281828459045, 7.389056, 20.085537).to_real_time_vec();
    /// vector.ln_approx();
    /// let actual = &vector[0..];
    /// let expected = &[1.0, 2.0, 3.0];
    /// assert_eq!(actual.len(), expected.len());
    /// for i in 0..actual.len() {
    ///        assert!(f64::abs(actual[i] - expected[i]) < 1e-2);
    /// }
    /// ```
    fn ln_approx(&mut self);

    /// Calculates the natural exponential approximation for every vector element.
    ///
    /// Error should be less than `1%`` as long as the values in the vector are small
    /// (e.g. in the range between -10 and 10).
    /// Single core performance should be about `50%` faster.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use std::f64;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(1.0, 2.0, 3.0).to_real_time_vec();
    /// vector.exp_approx();
    /// let actual = &vector[0..];
    /// let expected = &[2.718281828459045, 7.389056, 20.085537];
    /// assert_eq!(actual.len(), expected.len());
    /// for i in 0..actual.len() {
    ///        assert!(f64::abs(actual[i] - expected[i]) < 1e-4);
    /// }
    /// ```
    fn exp_approx(&mut self);

    /// Calculates the sine approximation of each element in radians.
    ///
    /// Error should be below `1E-6`.
    /// Single core performance should be about `2x` as fast.
    ///
    /// # Example
    ///
    /// ```
    /// use std::f32;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(f32::consts::PI/2.0, -f32::consts::PI/2.0).to_real_time_vec();
    /// vector.sin_approx();
    /// assert_eq!([1.0, -1.0], vector[..]);
    /// ```
    fn sin_approx(&mut self);

    /// Calculates the cosine approximation of each element in radians
    ///
    /// Error should be below `1E-6`.
    /// Single core performance should be about `2x` as fast.
    ///
    /// # Example
    ///
    /// ```
    /// use std::f32;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(2.0 * f32::consts::PI, f32::consts::PI).to_real_time_vec();
    /// vector.cos_approx();
    /// assert_eq!([1.0, -1.0], vector[..]);
    /// ```
    fn cos_approx(&mut self);

    /// Calculates the approximated logarithm to the given base for every vector element.
    ///
    /// Error should be below `1%` as long as the values in the vector are larger than `1`.
    /// Single core performance should be about `5x` as fast.
    ///
    /// # Example
    ///
    /// ```no_run
    /// # use std::f64;
    /// use basic_dsp_vector::*;
    /// let mut vector = vec!(10.0, 100.0, 1000.0).to_real_time_vec();
    /// vector.log_approx(10.0);
    /// let actual = &vector[0..];
    /// let expected = &[1.0, 2.0, 3.0];
    /// assert_eq!(actual.len(), expected.len());
    /// for i in 0..actual.len() {
    ///        assert!(f64::abs(actual[i] - expected[i]) < 1e-4);
    /// }
    /// ```
    fn log_approx(&mut self, base: T);

    /// Calculates the approximated exponential to the given base for every vector element.
    ///
    /// Error should be less than `1%`` as long as the values in the vector are small
    /// (e.g. in the range between -10 and 10).
    /// Single core performance should be about `5x` as fast.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use basic_dsp_vector::*;
    /// use std::f32;
    /// let vector: Vec<f32> = vec!(1.0, 2.0, 3.0);
    /// let mut vector = vector.to_real_time_vec();
    /// vector.expf_approx(10.0);
    /// assert!((vector[0] - 10.0).abs() < 1e-3);
    /// assert!((vector[1] - 100.0).abs() < 1e-3);
    /// assert!((vector[2] - 1000.0).abs() < 1e-3);
    /// ```
    fn expf_approx(&mut self, base: T);

    /// Raises every vector element to approximately a floating point power.
    ///
    /// Error should be less than `1%`` as long as the values in the vector are really small
    /// (e.g. in the range between -0.1 and 0.1).
    /// Single core performance should be about `5x` as fast.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use basic_dsp_vector::*;
    /// use std::f32;
    /// let vector: Vec<f32> = vec!(1.0, 2.0, 3.0);
    /// let mut vector = vector.to_real_time_vec();
    /// vector.powf_approx(3.0);
    /// assert!((vector[0] - 1.0).abs() < 1e-3);
    /// assert!((vector[1] - 8.0).abs() < 1e-3);
    /// assert!((vector[2] - 27.0).abs() < 1e-3);
    /// ```
    fn powf_approx(&mut self, exponent: T);
}

macro_rules! assert_real {
    ($self_: ident) => {
        if $self_.is_complex() {
            $self_.mark_vector_as_invalid();
            return;
        }
    };
}

impl<S, T, N, D> RealOps for DspVec<S, T, N, D>
where
    S: ToSliceMut<T>,
    T: RealNumber,
    N: RealNumberSpace,
    D: Domain,
{
    fn abs(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| (x * x).sqrt(),
            |x, _arg| x.abs(),
            (),
            Complexity::Small
        ));
    }
}

impl<S, T, N, D> ModuloOps<T> for DspVec<S, T, N, D>
where
    S: ToSliceMut<T>,
    T: RealNumber,
    N: RealNumberSpace,
    D: Domain,
{
    fn wrap(&mut self, divisor: T) {
        assert_real!(self);
        self.pure_real_operation(|x, y| x % y, divisor, Complexity::Small);
    }

    fn unwrap(&mut self, divisor: T) {
        assert_real!(self);
        let data_length = self.len();
        let data = self.data.to_slice_mut();
        let mut i = 0;
        let mut j = 1;
        let half = divisor / T::from(2.0).unwrap();
        while j < data_length {
            let mut diff = data[j] - data[i];
            if diff > half {
                diff = diff % divisor;
                diff = diff - divisor;
                data[j] = data[i] + diff;
            } else if diff < -half {
                diff = diff % divisor;
                diff = diff + divisor;
                data[j] = data[i] + diff;
            }

            i += 1;
            j += 1;
        }
    }
}

/// Complexity of all approximation functions. Small, because with the SIMD optimizations
/// threading becomes less beneficial.
const APPROX_COMPLEXITY: Complexity = Complexity::Small;

impl<S, T, N, D> ApproximatedOps<T> for DspVec<S, T, N, D>
where
    S: ToSliceMut<T>,
    T: RealNumber,
    N: RealNumberSpace,
    D: Domain,
{
    fn ln_approx(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| x.ln_approx(),
            |x, _arg| x.ln(),
            (),
            APPROX_COMPLEXITY
        ));
    }

    fn exp_approx(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| x.exp_approx(),
            |x, _arg| x.exp(),
            (),
            APPROX_COMPLEXITY
        ));
    }

    fn sin_approx(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| x.sin_approx(),
            |x, _arg| x.sin(),
            (),
            APPROX_COMPLEXITY
        ));
    }

    fn cos_approx(&mut self) {
        assert_real!(self);
        sel_reg!(self.simd_real_operation::<T>(
            |x, _arg| x.cos_approx(),
            |x, _arg| x.cos(),
            (),
            APPROX_COMPLEXITY
        ));
    }

    fn log_approx(&mut self, base: T) {
        assert_real!(self);
        sel_reg!(self.simd_real_operationf::<T>(
            |x, b| x.ln_approx() / b,
            |x, b| x.ln() / b.extract(0),
            base.ln(),
            APPROX_COMPLEXITY
        ));
    }

    fn expf_approx(&mut self, base: T) {
        assert_real!(self);
        // Transform base with:
        // x^y = e^(ln(x)*y)
        sel_reg!(self.simd_real_operationf::<T>(
            |y, x| (x * y).exp_approx(),
            |y, x| (x.extract(0) * y).exp(),
            base.ln(),
            APPROX_COMPLEXITY
        ));
    }

    fn powf_approx(&mut self, exponent: T) {
        assert_real!(self);
        // Transform base with the same equation as for `expf_approx`
        sel_reg!(self.simd_real_operationf::<T>(
            |x, y| (x.ln_approx() * y).exp_approx(),
            |x, y| (x.ln() * y.extract(0)).exp(),
            exponent,
            APPROX_COMPLEXITY
        ));
    }
}
<|endoftext|>


<commit_before>use super::{ErrorCode, IndyHandle};

use std::ffi::CString;

use ffi::crypto;

use utils::results::ResultHandler;
use utils::callbacks::ClosureHandler;

pub struct Key {}

impl Key {
    /// Creates key pair in wallet
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `my_key_json` - key information as json
    ///
    /// # Example
    /// my_key_json
    /// {
    ///     "seed": string, // Optional (if not set random one will be used); Seed information that allows deterministic key creation.
    ///     "crypto_type": string, // Optional (if not set then ed25519 curve is used); Currently only 'ed25519' value is supported for this field.
    /// }
    /// # Returns
    /// verkey of generated key pair, also used as key identifier
    pub fn create(wallet_handle: IndyHandle, my_key_json: &str) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let my_key_json = c_str!(my_key_json);

        let err = unsafe {
            crypto::indy_create_key(command_handle, wallet_handle, my_key_json.as_ptr(), cb)
        };
        ResultHandler::one(err, receiver)
    }

    /// Saves/replaces the metadata for the `verkey` in the wallet
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `verkey` - the public key or key id where to store the metadata
    /// * `metadata` - the metadata that will be stored with the key
    pub fn set_metadata(wallet_handle: IndyHandle, verkey: &str, metadata: &str) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let verkey = c_str!(verkey);
        let metadata = c_str!(metadata);

        let err = unsafe {
            crypto::indy_set_key_metadata(command_handle, wallet_handle, verkey.as_ptr(), metadata.as_ptr(), cb)
        };
        ResultHandler::empty(err, receiver)
    }

    /// Retrieves the metadata for the `verkey` in the wallet
    /// # Argument
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `verkey` - the public key or key id to retrieve metadata
    /// # Returns
    /// metadata currently stored with the key; Can be empty if no metadata was saved for this key
    pub fn get_metadata(wallet_handle: IndyHandle, verkey: &str) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let verkey = c_str!(verkey);

        let err = unsafe {
            crypto::indy_get_key_metadata(command_handle, wallet_handle, verkey.as_ptr(), cb)
        };

        ResultHandler::one(err, receiver)
    }
}

pub struct Crypto {}

impl Crypto {
    /// Signs a message with a key
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `signer_vk` - key id or verkey of my key. The key must be created by calling Key::create or Did::new
    /// * `message` - the data to be signed
    /// # Returns
    /// the signature
    pub fn sign(wallet_handle: IndyHandle, signer_vk: &str, message: &[u8]) -> Result<Vec<u8>, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_slice();

        let signer_vk = c_str!(signer_vk);
        let err = unsafe {
            crypto::indy_crypto_sign(command_handle, wallet_handle, signer_vk.as_ptr(),
                             message.as_ptr() as *const u8,
                             message.len() as u32,
                             cb)
        };

        ResultHandler::one(err, receiver)
    }

    /// Verify a signature with a verkey
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `signer_vk` - key id or verkey of my key. The key must be created by calling Key::create or Did::new
    /// * `message` - the data that was signed
    /// * `signature` - the signature to verify
    /// # Returns
    /// true if signature is valid, false otherwise
    pub fn verify(wallet_handle: IndyHandle, signer_vk: &str, message: &[u8], signature: &[u8]) -> Result<bool, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_bool();

        let signer_vk = c_str!(signer_vk);

        let err = unsafe {
            crypto::indy_crypto_verify(command_handle, wallet_handle, signer_vk.as_ptr(),
                               message.as_ptr() as *const u8, message.len() as u32,
                               signature.as_ptr() as *const u8, signature.len() as u32, cb)
        };

        ResultHandler::one(err, receiver)
    }

    /// Encrypt a message by authenticated-encryption scheme.
    ///
    /// Sender can encrypt a confidential message specifically for Recipient, using Sender's public key.
    /// Using Recipient's public key, Sender can compute a shared secret key.
    /// Using Sender's public key and his secret key, Recipient can compute the exact same shared secret key.
    /// That shared secret key can be used to verify that the encrypted message was not tampered with,
    /// before eventually decrypting it.
    ///
    /// Note to use DID keys with this function you can call Did::get_ver_key to get key id (verkey)
    /// for specific DID.
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `signer_vk` - key id or verkey of my key. The key must be created by calling Key::create or Did::new
    /// * `recipient_vk` - key id or verkey of the other party's key
    /// * `message` - the data to be encrypted
    /// # Returns
    /// the encrypted message
    pub fn auth_crypt(wallet_handle: IndyHandle, sender_vk: &str, recipient_vk: &str, message: &[u8]) -> Result<Vec<u8>, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_slice();

        let sender_vk = c_str!(sender_vk);
        let recipient_vk = c_str!(recipient_vk);
        let err = unsafe {
            crypto::indy_crypto_auth_crypt(command_handle, wallet_handle,
                                   sender_vk.as_ptr(),
                                    recipient_vk.as_ptr(),
                                    message.as_ptr() as *const u8,
                                    message.len() as u32, cb)
        };
        ResultHandler::one(err, receiver)
    }

    pub fn auth_decrypt(wallet_handle: IndyHandle, recipient_vk: &str, encrypted_message: &[u8]) -> Result<(String, Vec<u8>), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string_slice();

        let recipient_vk = c_str!(recipient_vk);
        let err = unsafe {
            crypto::indy_crypto_auth_decrypt(command_handle,
                                     wallet_handle,
                                     recipient_vk.as_ptr(),
                                     encrypted_message.as_ptr() as *const u8,
                                     encrypted_message.len() as u32, cb)
        };

        ResultHandler::two(err, receiver)
    }

    pub fn anon_crypt(wallet_handle: IndyHandle, recipient_vk: &str, message: &[u8]) -> Result<Vec<u8>, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_slice();

        let recipient_vk = c_str!(recipient_vk);
        let err = unsafe {
            crypto::indy_crypto_anon_crypt(command_handle,
                                   wallet_handle,
                                   recipient_vk.as_ptr(),
                                   message.as_ptr() as *const u8,
                                    message.len() as u32,
                                    cb)
        };

        ResultHandler::one(err, receiver)
    }

    pub fn anon_decrypt(wallet_handle: IndyHandle, recipient_vk: &str, encrypted_message: &[u8]) -> Result<(String, Vec<u8>), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string_slice();

        let recipient_vk = c_str!(recipient_vk);
        let err = unsafe {
            crypto::indy_crypto_anon_decrypt(command_handle,
                                     wallet_handle,
                                     recipient_vk.as_ptr(),
                                     encrypted_message.as_ptr() as *const u8,
                                     encrypted_message.len() as u32, cb)
        };

        ResultHandler::two(err, receiver)
    }
}
<commit_msg>Added documentation for crypto<commit_after>use super::{ErrorCode, IndyHandle};

use std::ffi::CString;

use ffi::crypto;

use utils::results::ResultHandler;
use utils::callbacks::ClosureHandler;

pub struct Key {}

impl Key {
    /// Creates key pair in wallet
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `my_key_json` - key information as json
    ///
    /// # Example
    /// my_key_json
    /// {
    ///     "seed": string, // Optional (if not set random one will be used); Seed information that allows deterministic key creation.
    ///     "crypto_type": string, // Optional (if not set then ed25519 curve is used); Currently only 'ed25519' value is supported for this field.
    /// }
    /// # Returns
    /// verkey of generated key pair, also used as key identifier
    pub fn create(wallet_handle: IndyHandle, my_key_json: &str) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let my_key_json = c_str!(my_key_json);

        let err = unsafe {
            crypto::indy_create_key(command_handle, wallet_handle, my_key_json.as_ptr(), cb)
        };
        ResultHandler::one(err, receiver)
    }

    /// Saves/replaces the metadata for the `verkey` in the wallet
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `verkey` - the public key or key id where to store the metadata
    /// * `metadata` - the metadata that will be stored with the key
    pub fn set_metadata(wallet_handle: IndyHandle, verkey: &str, metadata: &str) -> Result<(), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec();

        let verkey = c_str!(verkey);
        let metadata = c_str!(metadata);

        let err = unsafe {
            crypto::indy_set_key_metadata(command_handle, wallet_handle, verkey.as_ptr(), metadata.as_ptr(), cb)
        };
        ResultHandler::empty(err, receiver)
    }

    /// Retrieves the metadata for the `verkey` in the wallet
    /// # Argument
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `verkey` - the public key or key id to retrieve metadata
    /// # Returns
    /// metadata currently stored with the key; Can be empty if no metadata was saved for this key
    pub fn get_metadata(wallet_handle: IndyHandle, verkey: &str) -> Result<String, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string();

        let verkey = c_str!(verkey);

        let err = unsafe {
            crypto::indy_get_key_metadata(command_handle, wallet_handle, verkey.as_ptr(), cb)
        };

        ResultHandler::one(err, receiver)
    }
}

pub struct Crypto {}

impl Crypto {
    /// Signs a message with a key
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `signer_vk` - key id or verkey of my key. The key must be created by calling Key::create or Did::new
    /// * `message` - the data to be signed
    /// # Returns
    /// the signature
    pub fn sign(wallet_handle: IndyHandle, signer_vk: &str, message: &[u8]) -> Result<Vec<u8>, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_slice();

        let signer_vk = c_str!(signer_vk);
        let err = unsafe {
            crypto::indy_crypto_sign(command_handle, wallet_handle, signer_vk.as_ptr(),
                             message.as_ptr() as *const u8,
                             message.len() as u32,
                             cb)
        };

        ResultHandler::one(err, receiver)
    }

    /// Verify a signature with a verkey
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `signer_vk` - key id or verkey of my key. The key must be created by calling Key::create or Did::new
    /// * `message` - the data that was signed
    /// * `signature` - the signature to verify
    /// # Returns
    /// true if signature is valid, false otherwise
    pub fn verify(wallet_handle: IndyHandle, signer_vk: &str, message: &[u8], signature: &[u8]) -> Result<bool, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_bool();

        let signer_vk = c_str!(signer_vk);

        let err = unsafe {
            crypto::indy_crypto_verify(command_handle, wallet_handle, signer_vk.as_ptr(),
                               message.as_ptr() as *const u8, message.len() as u32,
                               signature.as_ptr() as *const u8, signature.len() as u32, cb)
        };

        ResultHandler::one(err, receiver)
    }

    /// Encrypt a message by authenticated-encryption scheme.
    ///
    /// Sender can encrypt a confidential message specifically for Recipient, using Sender's public key.
    /// Using Recipient's public key, Sender can compute a shared secret key.
    /// Using Sender's public key and his secret key, Recipient can compute the exact same shared secret key.
    /// That shared secret key can be used to verify that the encrypted message was not tampered with,
    /// before eventually decrypting it.
    ///
    /// Note to use DID keys with this function you can call Did::get_ver_key to get key id (verkey)
    /// for specific DID.
    /// # Arguments
    /// * `wallet_handle` - wallet handle (created by Wallet::open)
    /// * `signer_vk` - key id or verkey of my key. The key must be created by calling Key::create or Did::new
    /// * `recipient_vk` - key id or verkey of the other party's key
    /// * `message` - the data to be encrypted
    /// # Returns
    /// the encrypted message
    pub fn auth_crypt(wallet_handle: IndyHandle, sender_vk: &str, recipient_vk: &str, message: &[u8]) -> Result<Vec<u8>, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_slice();

        let sender_vk = c_str!(sender_vk);
        let recipient_vk = c_str!(recipient_vk);
        let err = unsafe {
            crypto::indy_crypto_auth_crypt(command_handle, wallet_handle,
                                   sender_vk.as_ptr(),
                                    recipient_vk.as_ptr(),
                                    message.as_ptr() as *const u8,
                                    message.len() as u32, cb)
        };
        ResultHandler::one(err, receiver)
    }

    /// Decrypt a message by authenticated-encryption scheme.
    ///
    /// Sender can encrypt a confidential message specifically for Recipient, using Sender's public key.
    /// Using Recipient's public key, Sender can compute a shared secret key.
    /// Using Sender's public key and his secret key, Recipient can compute the exact same shared secret key.
    /// That shared secret key can be used to verify that the encrypted message was not tampered with,
    /// before eventually decrypting it.
    ///
    /// Note to use DID keys with this function you can call Did::get_ver_key to get key id (verkey)
    /// for specific DID.
    ///
    /// # Arguments
    /// `wallet_handle`: wallet handle (created by Wallet::open)
    /// `recipient_vk`: key id or verkey of my key. The key must be created by calling Key::create or Did::new
    /// `encrypted_message`: the message to be decrypted
    ///
    /// # Returns
    /// sender's verkey and decrypted message
    pub fn auth_decrypt(wallet_handle: IndyHandle, recipient_vk: &str, encrypted_message: &[u8]) -> Result<(String, Vec<u8>), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string_slice();

        let recipient_vk = c_str!(recipient_vk);
        let err = unsafe {
            crypto::indy_crypto_auth_decrypt(command_handle,
                                     wallet_handle,
                                     recipient_vk.as_ptr(),
                                     encrypted_message.as_ptr() as *const u8,
                                     encrypted_message.len() as u32, cb)
        };

        ResultHandler::two(err, receiver)
    }

    /// Encrypts a message by anonymous-encryption scheme.
    ///
    /// Sealed boxes are designed to anonymously send messages to a Recipient given its public key.
    /// Only the Recipient can decrypt these messages, using its private key.
    /// While the Recipient can verify the integrity of the message, it cannot verify the identity of the Sender.
    ///
    /// Note to use DID keys with this function you can call Did::get_ver_key to get key id (verkey)
    /// for specific DID.
    ///
    /// # Arguments
    /// `wallet_handle`: wallet handle (created by Wallet::open)
    /// `recipient_vk`: verkey of message recipient
    /// `message`: a pointer to first byte of message that to be encrypted
    ///
    /// # Returns
    /// the encrypted message
    pub fn anon_crypt(wallet_handle: IndyHandle, recipient_vk: &str, message: &[u8]) -> Result<Vec<u8>, ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_slice();

        let recipient_vk = c_str!(recipient_vk);
        let err = unsafe {
            crypto::indy_crypto_anon_crypt(command_handle,
                                   wallet_handle,
                                   recipient_vk.as_ptr(),
                                   message.as_ptr() as *const u8,
                                    message.len() as u32,
                                    cb)
        };

        ResultHandler::one(err, receiver)
    }

    /// Decrypts a message by anonymous-encryption scheme.
    ///
    /// Sealed boxes are designed to anonymously send messages to a Recipient given its public key.
    /// Only the Recipient can decrypt these messages, using its private key.
    /// While the Recipient can verify the integrity of the message, it cannot verify the identity of the Sender.
    ///
    /// Note to use DID keys with this function you can call Did::get_ver_key to get key id (verkey)
    /// for specific DID.
    ///
    /// # Arguments
    /// `wallet_handle`: wallet handle (created by Wallet::open).
    /// `recipient_vk`: key id or verkey of my key. The key must be created by calling Key::create or Did::new
    /// `encrypted_message`: a pointer to first byte of message that to be decrypted
    ///
    /// # Returns
    /// decrypted message
    pub fn anon_decrypt(wallet_handle: IndyHandle, recipient_vk: &str, encrypted_message: &[u8]) -> Result<(String, Vec<u8>), ErrorCode> {
        let (receiver, command_handle, cb) = ClosureHandler::cb_ec_string_slice();

        let recipient_vk = c_str!(recipient_vk);
        let err = unsafe {
            crypto::indy_crypto_anon_decrypt(command_handle,
                                     wallet_handle,
                                     recipient_vk.as_ptr(),
                                     encrypted_message.as_ptr() as *const u8,
                                     encrypted_message.len() as u32, cb)
        };

        ResultHandler::two(err, receiver)
    }
}

<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::default::Default;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};

use digest::Digest;
use ignore::WalkBuilder;
use serde_bytes;
use serde_cbor;
use serde_json;

use sha2;
use sha3;

use error;

#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct Database(Entry);

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Entry {
    Directory(BTreeMap<PathBuf, Entry>),
    File(Metrics),
}

impl Default for Entry {
    fn default() -> Entry {
        Entry::Directory(BTreeMap::default())
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Metrics {
    sha2: HashSum,
    sha3: HashSum,
    size: u64,      // File size
    nul: bool,      // Does the file contain a NUL byte?
    nonascii: bool, // Does the file contain non-ASCII bytes?
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HashSum(#[serde(with = "serde_bytes")] Vec<u8>);

#[derive(Default)]
struct EngineSize(u64);
impl EngineSize {
    fn input(&mut self, input: &[u8]) {
        self.0 += input.len() as u64;
    }
    fn result(self) -> u64 {
        self.0
    }
}

#[derive(Default)]
struct EngineNul(bool);
impl EngineNul {
    fn input(&mut self, input: &[u8]) {
        self.0 = self.0 || input.iter().any(|x| *x == 0);
    }
    fn result(self) -> bool {
        self.0
    }
}

#[derive(Default)]
struct EngineNonascii(bool);
impl EngineNonascii {
    fn input(&mut self, input: &[u8]) {
        self.0 = self.0 || input.iter().any(|x| x & 0x80 != 0);
    }
    fn result(self) -> bool {
        self.0
    }
}

#[derive(Default)]
struct Engines {
    sha2: sha2::Sha256,
    sha3: sha3::Sha3_256,
    size: EngineSize,
    nul: EngineNul,
    nonascii: EngineNonascii,
}

impl Engines {
    fn input(&mut self, input: &[u8]) {
        self.sha2.input(input);
        self.sha3.input(input);
        self.size.input(input);
        self.nul.input(input);
        self.nonascii.input(input);
    }
    fn result(self) -> Metrics {
        Metrics {
            sha2: HashSum(Vec::from(self.sha2.result().as_slice())),
            sha3: HashSum(Vec::from(self.sha3.result().as_slice())),
            size: self.size.result(),
            nul: self.nul.result(),
            nonascii: self.nonascii.result(),
        }
    }
}

fn compute_metrics<P>(path: P) -> Result<Metrics, error::Error>
where
    P: AsRef<Path>
{
    let mut f = File::open(path)?;

    let mut hashers = Engines::default();

    let mut buffer = [0; 4096];
    loop {
        let n = f.read(&mut buffer[..])?;
        if n == 0 { break }
        hashers.input(&buffer[0..n]);
    }
    Ok(hashers.result())
}

trait BTreeMapExt<K, V> where K: Ord, V: Default {
    fn get_mut_default(&mut self, key: K) -> &mut V;
}

impl<K, V> BTreeMapExt<K, V> for BTreeMap<K, V>
where
    K: Ord + Clone,
    V: Default,
{
    fn get_mut_default(&mut self, key: K) -> &mut V {
        if self.contains_key(&key) {
            match self.get_mut(&key) {
                Some(value) => value,
                None => unreachable!(), // Already checked that key exists
            }
        } else {
            {
                // FIXME: Would prefer to avoid the clone
                match self.insert(key.clone(), V::default()) {
                    Some(_) => unreachable!(), // Already checked for key
                    None => (),
                }
            }
            {
                match self.get_mut(&key) {
                    Some(value) => value,
                    None => unreachable!(), // Already checked that key exists
                }
            }
        }
    }
}

impl Entry {
    fn insert(&mut self, path: PathBuf, file: Entry) {
        // Inner nodes in the tree should always be directories. If
        // the node is not a directory, that means we are inserting a
        // duplicate file. However, this function is only called from
        // the directory walker, which makes it impossible to observe
        // any duplicates. (And the database, after construction, is
        // always immutable.)
        match self {
            &mut Entry::Directory(ref mut entries) => {
                let mut components = path.components();
                let count = components.clone().count();
                let first = Path::new(components.next().expect("unreachable").as_os_str()).to_owned();
                let rest = components.as_path().to_owned();
                if count > 1 {
                    let mut subentry = entries.get_mut_default(first);
                    subentry.insert(rest, file);
                } else {
                    match entries.insert(first, file) {
                        Some(_) => unreachable!(), // See above
                        None => (),
                    }
                }
            }
            &mut Entry::File(_) => unreachable!()
        }
    }
}

impl Database {
    fn insert(&mut self, path: PathBuf, entry: Entry) {
        self.0.insert(path, entry);
    }

    pub fn build<P>(path: P) -> Result<Database, error::Error>
    where
        P: AsRef<Path>
    {
        let mut database = Database::default();
        for entry in WalkBuilder::new(&path).build() {
            let entry = entry?;
            if entry.file_type().map_or(false, |t| t.is_file()) {
                let metrics = compute_metrics(entry.path())?;
                let result = Entry::File(metrics);
                let short_path = entry.path().strip_prefix(&path)?;
                database.insert(short_path.to_owned(), result);
            }
        }
        Ok(database)
    }

    pub fn dump_json<P>(&self, path: P) -> Result<(), error::Error>
    where
        P: AsRef<Path>
    {
        let json = serde_json::to_string(self)?;
        let mut f = File::create(path)?;
        write!(f, "{}", json)?;
        Ok(())
    }

    pub fn dump_cbor<P>(&self, path: P) -> Result<(), error::Error>
    where
        P: AsRef<Path>
    {
        let cbor = serde_cbor::to_vec(self)?;
        let mut f = File::create(path)?;
        f.write_all(cbor.as_slice())?;
        Ok(())
    }
}

// impl std::fmt::Display for Database {
//     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
//         for (path, entry) in self.0.iter() {
//             match entry {
//                 &Entry::File(ref hashes) => {
//                     let hash: Vec<_> = hashes.sha2.0.iter().map(
//                         |b| format!("{:02x}", b)).collect();
//                     writeln!(f, "{} {}", hash.join(""), Path::new(path).display())?
//                 }
//             }
//         }
//         Ok(())
//     }
// }
<commit_msg>Fix database creation for individual files.<commit_after>use std::collections::BTreeMap;
use std::default::Default;
use std::fs::File;
use std::io::{Read, Write};
use std::path::{Path, PathBuf};

use digest::Digest;
use ignore::WalkBuilder;
use serde_bytes;
use serde_cbor;
use serde_json;

use sha2;
use sha3;

use error;

#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct Database(Entry);

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Entry {
    Directory(BTreeMap<PathBuf, Entry>),
    File(Metrics),
}

impl Default for Entry {
    fn default() -> Entry {
        Entry::Directory(BTreeMap::default())
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Metrics {
    sha2: HashSum,
    sha3: HashSum,
    size: u64,      // File size
    nul: bool,      // Does the file contain a NUL byte?
    nonascii: bool, // Does the file contain non-ASCII bytes?
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct HashSum(#[serde(with = "serde_bytes")] Vec<u8>);

#[derive(Default)]
struct EngineSize(u64);
impl EngineSize {
    fn input(&mut self, input: &[u8]) {
        self.0 += input.len() as u64;
    }
    fn result(self) -> u64 {
        self.0
    }
}

#[derive(Default)]
struct EngineNul(bool);
impl EngineNul {
    fn input(&mut self, input: &[u8]) {
        self.0 = self.0 || input.iter().any(|x| *x == 0);
    }
    fn result(self) -> bool {
        self.0
    }
}

#[derive(Default)]
struct EngineNonascii(bool);
impl EngineNonascii {
    fn input(&mut self, input: &[u8]) {
        self.0 = self.0 || input.iter().any(|x| x & 0x80 != 0);
    }
    fn result(self) -> bool {
        self.0
    }
}

#[derive(Default)]
struct Engines {
    sha2: sha2::Sha256,
    sha3: sha3::Sha3_256,
    size: EngineSize,
    nul: EngineNul,
    nonascii: EngineNonascii,
}

impl Engines {
    fn input(&mut self, input: &[u8]) {
        self.sha2.input(input);
        self.sha3.input(input);
        self.size.input(input);
        self.nul.input(input);
        self.nonascii.input(input);
    }
    fn result(self) -> Metrics {
        Metrics {
            sha2: HashSum(Vec::from(self.sha2.result().as_slice())),
            sha3: HashSum(Vec::from(self.sha3.result().as_slice())),
            size: self.size.result(),
            nul: self.nul.result(),
            nonascii: self.nonascii.result(),
        }
    }
}

fn compute_metrics<P>(path: P) -> Result<Metrics, error::Error>
where
    P: AsRef<Path>
{
    let mut f = File::open(path)?;

    let mut hashers = Engines::default();

    let mut buffer = [0; 4096];
    loop {
        let n = f.read(&mut buffer[..])?;
        if n == 0 { break }
        hashers.input(&buffer[0..n]);
    }
    Ok(hashers.result())
}

trait BTreeMapExt<K, V> where K: Ord, V: Default {
    fn get_mut_default(&mut self, key: K) -> &mut V;
}

impl<K, V> BTreeMapExt<K, V> for BTreeMap<K, V>
where
    K: Ord + Clone,
    V: Default,
{
    fn get_mut_default(&mut self, key: K) -> &mut V {
        if self.contains_key(&key) {
            match self.get_mut(&key) {
                Some(value) => value,
                None => unreachable!(), // Already checked that key exists
            }
        } else {
            {
                // FIXME: Would prefer to avoid the clone
                match self.insert(key.clone(), V::default()) {
                    Some(_) => unreachable!(), // Already checked for key
                    None => (),
                }
            }
            {
                match self.get_mut(&key) {
                    Some(value) => value,
                    None => unreachable!(), // Already checked that key exists
                }
            }
        }
    }
}

impl Entry {
    fn insert(&mut self, path: PathBuf, file: Entry) {
        // Inner nodes in the tree should always be directories. If
        // the node is not a directory, that means we are inserting a
        // duplicate file. However, this function is only called from
        // the directory walker, which makes it impossible to observe
        // any duplicates. (And the database, after construction, is
        // always immutable.)
        match self {
            &mut Entry::Directory(ref mut entries) => {
                let mut components = path.components();
                let count = components.clone().count();
                let first = Path::new(components.next().expect("unreachable").as_os_str()).to_owned();
                let rest = components.as_path().to_owned();
                if count > 1 {
                    let mut subentry = entries.get_mut_default(first);
                    subentry.insert(rest, file);
                } else {
                    match entries.insert(first, file) {
                        Some(_) => unreachable!(), // See above
                        None => (),
                    }
                }
            }
            &mut Entry::File(_) => unreachable!()
        }
    }
}

impl Database {
    fn insert(&mut self, path: PathBuf, entry: Entry) {
        self.0.insert(path, entry);
    }

    pub fn build<P>(root: P) -> Result<Database, error::Error>
    where
        P: AsRef<Path>,
    {
        let mut database = Database::default();
        for entry in WalkBuilder::new(&root).build() {
            let entry = entry?;
            if entry.file_type().map_or(false, |t| t.is_file()) {
                let metrics = compute_metrics(entry.path())?;
                let result = Entry::File(metrics);
                let short_path = if entry.path() == root.as_ref() {
                    Path::new(entry.path().file_name().expect("unreachable"))
                } else {
                    entry.path().strip_prefix(&root)?
                };
                database.insert(short_path.to_owned(), result);
            }
        }
        Ok(database)
    }

    pub fn dump_json<P>(&self, path: P) -> Result<(), error::Error>
    where
        P: AsRef<Path>
    {
        let json = serde_json::to_string(self)?;
        let mut f = File::create(path)?;
        write!(f, "{}", json)?;
        Ok(())
    }

    pub fn dump_cbor<P>(&self, path: P) -> Result<(), error::Error>
    where
        P: AsRef<Path>
    {
        let cbor = serde_cbor::to_vec(self)?;
        let mut f = File::create(path)?;
        f.write_all(cbor.as_slice())?;
        Ok(())
    }
}

// impl std::fmt::Display for Database {
//     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
//         for (path, entry) in self.0.iter() {
//             match entry {
//                 &Entry::File(ref hashes) => {
//                     let hash: Vec<_> = hashes.sha2.0.iter().map(
//                         |b| format!("{:02x}", b)).collect();
//                     writeln!(f, "{} {}", hash.join(""), Path::new(path).display())?
//                 }
//             }
//         }
//         Ok(())
//     }
// }
<|endoftext|>