<commit_before>use std::collections::VecDeque;
use std::collections::HashSet;

/// A graph is represeted by as a weighted
/// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix)
pub struct Graph {
  /// The underlaying graph represented here with weights as an i32 (should
  /// probably be generic) the graph is represented as an
  /// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix) of
  /// Optionals, where None indicates that there doesn't exist a vertex and
  /// Some<i32> indicates that There is a vertex of weight i32.
  graph: Vec<Vec<Option<i32>>>
}
impl Graph {
  /// `new` allows for initializing the graph struct with a given adjecency matrix
  ///
  /// ## Arguments
  /// * `input` - an adjecency matrix in made out of a two-dimensional `Vec` of
  ///    weights. Weights are represented as `i32`:s and can thus be positive or
  ///    negative numbers.
  ///
  /// ## Example
  /// ```ignore
  ///  let rawgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None],
  ///                      vec![   None,  Some(0),     None,     None,     None,     None],
  ///                      vec![   None,     None,  Some(0),     None,     None,     None],
  ///                      vec![   None,     None,     None,  Some(0), Some(50),     None],
  ///                      vec![   None,     None, Some(20),     None,  Some(0), Some(50)],
  ///                      vec![   None,     None,     None,     None,     None,  Some(0)]];
  /// let g = Graph::new(rawgraph);
  /// ```
  pub fn new(input: Vec<Vec<Option<i32>>>) -> Graph { Graph { graph: input } }

  /*
  1  procedure BFS(G,v) is
  2      let Q be a queue
  3      Q.push(v)
  4      label v as discovered
  5      while Q is not empty
  6         v ← Q.pop()
  7         for all edges from v to w in G.adjacentEdges(v) do
  8             if w is not labeled as discovered
  9                 Q.push(w)
  10                label w as discovered
  */
  /// `breadth_first_search` implements breadth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is breadth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn breadth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    let mut q: VecDeque<usize> = VecDeque::new();
    let mut discovered: HashSet<usize> = HashSet::new();
    let mut prev: Vec<usize> = Vec::with_capacity(self.graph.len());
    let mut pathfound = false;
    for _ in (0..self.graph.len()) { prev.push(0); }

    q.push_back(start);
    discovered.insert(start);

    while !q.is_empty() {
      let v = q.pop_front();
      match v {
        None => {}, // q is empty
        Some(v) => { // we are working on a new layer, branch the queue?
          if !discovered.contains(&v) {
            discovered.insert(v);
          }
          if v == target {
            pathfound = true;
          }
          for i in (0..self.graph[v].len()) {
            match self.graph[v][i] {
              None => {}, // no vertex between v and i
              Some(_) => {
                if !discovered.contains(&i) {
                  q.push_back(i);
                  prev[i]=v; //track prev (v) on i
                }
              }
            }
          }
        }
      }
    }
    if pathfound {
      let mut path: VecDeque<usize> = VecDeque::new();
      let mut curr = target;
      // backtrack over the prev array to construct the path
      while curr != start {
        path.push_front(curr);
        curr = prev[curr];
      }
      path.push_front(start);
      return Some(path)
    }
    return None
  }
}

#[test]
fn breadth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);
  match res {
    None => {
      println!("bfs search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Bfs returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn breadth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("bfs search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Bfs returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}
<commit_msg>Moved the actual searching into an inner function<commit_after>use std::collections::VecDeque;
use std::collections::HashSet;

/// A graph is represeted by as a weighted
/// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix)
pub struct Graph {
  /// The underlaying graph represented here with weights as an i32 (should
  /// probably be generic) the graph is represented as an
  /// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix) of
  /// Optionals, where None indicates that there doesn't exist a vertex and
  /// Some<i32> indicates that There is a vertex of weight i32.
  graph: Vec<Vec<Option<i32>>>
}
impl Graph {
  /// `new` allows for initializing the graph struct with a given adjecency matrix
  ///
  /// ## Arguments
  /// * `input` - an adjecency matrix in made out of a two-dimensional `Vec` of
  ///    weights. Weights are represented as `i32`:s and can thus be positive or
  ///    negative numbers.
  ///
  /// ## Example
  /// ```ignore
  ///  let rawgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None],
  ///                      vec![   None,  Some(0),     None,     None,     None,     None],
  ///                      vec![   None,     None,  Some(0),     None,     None,     None],
  ///                      vec![   None,     None,     None,  Some(0), Some(50),     None],
  ///                      vec![   None,     None, Some(20),     None,  Some(0), Some(50)],
  ///                      vec![   None,     None,     None,     None,     None,  Some(0)]];
  /// let g = Graph::new(rawgraph);
  /// ```
  pub fn new(input: Vec<Vec<Option<i32>>>) -> Graph { Graph { graph: input } }

  /*
  1  procedure BFS(G,v) is
  2      let Q be a queue
  3      Q.push(v)
  4      label v as discovered
  5      while Q is not empty
  6         v ← Q.pop()
  7         for all edges from v to w in G.adjacentEdges(v) do
  8             if w is not labeled as discovered
  9                 Q.push(w)
  10                label w as discovered
  */
  /// `breadth_first_search` implements breadth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is breadth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn breadth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    return self.inner_search(start, target, true)
  }

  fn inner_search(&self, start: usize, target: usize, bfs: bool) -> Option<VecDeque<usize>>  {
    let mut q: VecDeque<usize> = VecDeque::new();
    let mut discovered: HashSet<usize> = HashSet::new();
    let mut prev: Vec<usize> = Vec::with_capacity(self.graph.len());
    let mut pathfound = false;
    for _ in (0..self.graph.len()) { prev.push(0); }

    q.push_back(start);
    discovered.insert(start);

    while !q.is_empty() {
      let mut v: Option<usize>;
      if bfs {
        v = q.pop_front()
      } else {
        v = q.pop_back();
      }
      match v {
        None => {}, // q is empty
        Some(v) => { // we are working on a new layer, branch the queue?
          if !discovered.contains(&v) {
            discovered.insert(v);
          }
          if v == target {
            pathfound = true;
          }
          for i in (0..self.graph[v].len()) {
            match self.graph[v][i] {
              None => {}, // no vertex between v and i
              Some(_) => {
                if !discovered.contains(&i) {
                  q.push_back(i);
                  prev[i]=v; //track prev (v) on i
                }
              }
            }
          }
        }
      }
    }
    if pathfound {
      let mut path: VecDeque<usize> = VecDeque::new();
      let mut curr = target;
      // backtrack over the prev array to construct the path
      while curr != start {
        path.push_front(curr);
        curr = prev[curr];
      }
      path.push_front(start);
      return Some(path)
    }
    return None
  }
}

#[test]
fn breadth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);
  match res {
    None => {
      println!("bfs search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Bfs returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn breadth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("bfs search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Bfs returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}
<|endoftext|>


<commit_before>extern crate crypto;
extern crate byteorder;
extern crate rand;

use crypto::digest::Digest;
use crypto::sha2::Sha256;
use crypto::hmac::Hmac;
use crypto::mac::{Mac};
use crypto::aes::KeySize;
use crypto::aes_gcm::AesGcm;
use crypto::aead::{AeadEncryptor, AeadDecryptor};
use crypto::curve25519::{curve25519, curve25519_base};

use byteorder::{ByteOrder, BigEndian};
use rand::{OsRng, Rng};

const DHLEN : usize = 32;
const HASHLEN : usize = 32;
//const BLOCKLEN : usize = 64;
const MACLEN : usize = 16;
const CIPHERKEYLEN : usize = 32;

fn copy_memory(data: &[u8], out: &mut [u8]) {
    for count in 0..data.len() {out[count] = data[count];}
}

pub struct KeyPair {
    privkey: [u8; DHLEN],
    pubkey: [u8; DHLEN]
}

pub fn generate_keypair() -> KeyPair {
    let mut privkey = [0u8; 32];
    let mut rng = OsRng::new().unwrap();
    rng.fill_bytes(&mut privkey);
    let pubkey = curve25519_base(&privkey);
    KeyPair{privkey : privkey, pubkey : pubkey}
}

fn dh(keypair : &KeyPair, pubkey: &[u8]) -> [u8; DHLEN] {
    curve25519(&keypair.privkey, pubkey)
}

pub fn hash(data: &[u8], out: &mut [u8]) {
    let mut h = Sha256::new();
    h.input(data);
    h.result(out);
}

fn hmac_hash(key: &[u8], data: &[u8], out: &mut [u8]) {
    let mut hmac = Hmac::new(Sha256::new(), key);
    hmac.input(data);
    hmac.raw_result(out);
}

fn hkdf(chaining_key: &[u8], data: &[u8], out: &mut [u8]) {
    let mut temp_key = [0u8; HASHLEN];
    let mut in2  = [0u8; HASHLEN];
    hmac_hash(chaining_key, data, &mut temp_key);
    hmac_hash(&temp_key, &[1u8], &mut out[0..HASHLEN]);
    copy_memory(out as &[u8], &mut in2);
    in2[HASHLEN] = 2;
    hmac_hash(&temp_key, &in2, &mut out[HASHLEN..2*HASHLEN]);
}

fn encrypt(key: &[u8], nonce: u64, authtext: &[u8], plaintext: &[u8], out: &mut[u8]) {
    let mut nonce_bytes = [0u8; 12];
    BigEndian::write_u64(&mut nonce_bytes[4..], nonce);
    let mut cipher = AesGcm::new(KeySize::KeySize256, key, &nonce_bytes, authtext);
    let mut tag = [0u8; MACLEN];
    cipher.encrypt(plaintext, out, &mut tag);
    copy_memory(&tag, &mut out[plaintext.len()..]);
}

fn decrypt(key: &[u8], nonce: u64, authtext: &[u8], ciphertext: &[u8], out: &mut[u8]) -> bool {
    let mut nonce_bytes = [0u8; 12];
    BigEndian::write_u64(&mut nonce_bytes[4..], nonce);
    let mut cipher = AesGcm::new(KeySize::KeySize256, key, &nonce_bytes, authtext);
    let tag = [0u8; MACLEN];
    cipher.decrypt(ciphertext, out, &tag)
}

pub enum Token {E, S, Dhee, Dhes, Dhse, Dhss}

pub enum NoiseError {DecryptError}

pub struct CipherState {
    k: [u8; CIPHERKEYLEN],
    n: u64
}

struct SymmetricState {
    cipherstate : CipherState,
    has_key : bool,
    ck: [u8; HASHLEN],
    h: [u8; HASHLEN]
}

pub struct HandshakeState {
    symmetricstate: SymmetricState,
    s: KeyPair,
    e: KeyPair,
    rs: [u8; DHLEN],
    re: [u8; DHLEN],
}

impl CipherState {

    fn new() -> CipherState {
        CipherState{k : [0; CIPHERKEYLEN], n:0}
    }

    pub fn encrypt_and_increment(&mut self, authtext: &[u8], plaintext: &[u8], out: &mut [u8]) {
        encrypt(&self.k, self.n, authtext, plaintext, out);
        self.n += 1;
    }

    pub fn decrypt_and_increment(&mut self, authtext: &[u8], ciphertext: &[u8], out: &mut [u8]) -> bool {
        if !decrypt(&self.k, self.n, authtext, ciphertext, out) {
            self.n += 1;
            return false;
        }
        self.n += 1;
        true
    }
}

impl SymmetricState {

    fn new(handshake_name: &[u8]) -> SymmetricState {
        let mut hname = [0u8; HASHLEN];
        match handshake_name.len() {
            0 ... HASHLEN => copy_memory(handshake_name, &mut hname),
            _ => hash(handshake_name, &mut hname)
        }
        let cipherstate = CipherState::new();
        SymmetricState{cipherstate: cipherstate, has_key : false, ck : hname, h: hname}
    }

    fn mix_key(&mut self, data: &[u8]) {
        let mut hkdf_output = [0u8; 2*HASHLEN];
        hkdf(&self.ck, data, &mut hkdf_output);
        copy_memory(&hkdf_output[0..HASHLEN], &mut self.ck);
        copy_memory(&hkdf_output[HASHLEN..HASHLEN+CIPHERKEYLEN], &mut self.cipherstate.k);
        self.cipherstate.n = 0;
        self.has_key = true;
    }

    fn mix_hash(&mut self, data: &[u8]) {
        let mut buffer = [0u8; 65535];
        copy_memory(&data, &mut buffer);
        copy_memory(&self.h, &mut buffer[data.len()..data.len() + HASHLEN]);
        hash(&buffer, &mut self.h);
    }

    fn encrypt_and_hash(&mut self, plaintext: &[u8], out: &mut [u8]) -> usize {
        if self.has_key {
            self.cipherstate.encrypt_and_increment(&self.h, plaintext, out);
            self.mix_hash(&out[..plaintext.len() + MACLEN]);
            return plaintext.len() + MACLEN;
        } else {
            copy_memory(plaintext, out);
            self.mix_hash(plaintext);
            return plaintext.len();
        }
    }

    fn decrypt_and_hash(&mut self, data: &[u8], out: &mut [u8]) -> bool {
        if self.has_key {
            if !self.cipherstate.decrypt_and_increment(&self.h, data, out) {
                return false;
            }
            self.mix_hash(data);
        } else {
            copy_memory(data, out);
            self.mix_hash(data);
        }
        true
    }

    fn split(&self) -> (CipherState, CipherState) {
        let mut hkdf_output = [0u8; 2*HASHLEN];
        hkdf(&self.ck, &[0u8; 0], &mut hkdf_output);
        let mut c1 = CipherState::new();
        let mut c2 = CipherState::new();
        copy_memory( &hkdf_output[0..CIPHERKEYLEN], &mut c1.k);
        copy_memory( &hkdf_output[HASHLEN..HASHLEN+CIPHERKEYLEN], &mut c2.k);
        (c1, c2)
    }

}

impl HandshakeState {

    pub fn new(handshake_name: &[u8], new_s : KeyPair, new_e : KeyPair, new_rs: [u8; 32], new_re : [u8; 32] ) -> HandshakeState {
        let symmetricstate = SymmetricState::new(handshake_name);
        HandshakeState{symmetricstate: symmetricstate, s: new_s, e: new_e, rs: new_rs, re: new_re}
    }

    pub fn write_handshake_message(&mut self,
                               descriptor: &[Token],
                               last: bool,
                               payload: &[u8],
                               out: &mut [u8]) -> Option<(CipherState, CipherState)> {
        let mut index = 0;
        for token in descriptor {
            match *token {
                Token::E => {
                    self.e = generate_keypair();
                    index += self.symmetricstate.encrypt_and_hash(&self.e.pubkey, &mut out[index..]);
                },
                Token::S => index += self.symmetricstate.encrypt_and_hash(&self.s.pubkey, &mut out[index..]),
                Token::Dhee => self.symmetricstate.mix_key(&dh(&self.e, &self.re)),
                Token::Dhes => self.symmetricstate.mix_key(&dh(&self.e, &self.rs)),
                Token::Dhse => self.symmetricstate.mix_key(&dh(&self.s, &self.re)),
                Token::Dhss => self.symmetricstate.mix_key(&dh(&self.s, &self.rs)),
            }
        }
        self.symmetricstate.encrypt_and_hash(payload, &mut out[index..]);
        match last {
            true => Some(self.symmetricstate.split()),
            false => None
        }
    }

    pub fn read_handshake_message(&mut self,
                              buffer: &[u8],
                              descriptor: &[Token],
                              last: bool,
                              out: &mut [u8]) -> Result<Option<(CipherState, CipherState)>, NoiseError> {
        let mut ptr = buffer;
        for token in descriptor {
            match *token {
                Token::E | Token::S => {
                    let data = match self.symmetricstate.has_key {
                        true =>  {let temp = &ptr[..DHLEN+16]; ptr = &ptr[DHLEN+16..]; temp}
                        false => {let temp = &ptr[..DHLEN];    ptr = &ptr[DHLEN..];    temp}
                    };
                    if !self.symmetricstate.decrypt_and_hash(data, match *token {
                            Token::E => &mut self.re,
                            Token::S => &mut self.rs,
                            _ => unreachable!()}) {
                        return Err(NoiseError::DecryptError);
                    }
                },
                Token::Dhee => self.symmetricstate.mix_key(&dh(&self.e, &self.re)),
                Token::Dhes => self.symmetricstate.mix_key(&dh(&self.s, &self.re)),
                Token::Dhse => self.symmetricstate.mix_key(&dh(&self.e, &self.rs)),
                Token::Dhss => self.symmetricstate.mix_key(&dh(&self.s, &self.rs)),
            }
        }
        if !self.symmetricstate.decrypt_and_hash(ptr, out) {
            return Err(NoiseError::DecryptError);
        }
        match last {
            true => Ok(Some(self.symmetricstate.split())),
            false => Ok(None)
        }
    }

}

#[cfg(test)]
mod tests {

    extern crate rustc_serialize;

    use super::*;
    use self::rustc_serialize::hex::ToHex;

    #[test]
    fn crypto_tests() {

        // SHA256 test
        let mut output = [0u8; 32];
        HASH("abc".as_bytes(), &mut output);
        assert!(output.to_hex() == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");

    }
}
<commit_msg>Add HMAC And 25519 tests<commit_after>extern crate crypto;
extern crate byteorder;
extern crate rand;

use crypto::digest::Digest;
use crypto::sha2::Sha256;
use crypto::hmac::Hmac;
use crypto::mac::{Mac};
use crypto::aes::KeySize;
use crypto::aes_gcm::AesGcm;
use crypto::aead::{AeadEncryptor, AeadDecryptor};
use crypto::curve25519::{curve25519, curve25519_base};

use byteorder::{ByteOrder, BigEndian};
use rand::{OsRng, Rng};

const DHLEN : usize = 32;
const HASHLEN : usize = 32;
//const BLOCKLEN : usize = 64;
const MACLEN : usize = 16;
const CIPHERKEYLEN : usize = 32;

fn copy_memory(data: &[u8], out: &mut [u8]) {
    for count in 0..data.len() {out[count] = data[count];}
}

pub struct KeyPair {
    privkey: [u8; DHLEN],
    pubkey: [u8; DHLEN]
}

pub fn generate_keypair() -> KeyPair {
    let mut privkey = [0u8; 32];
    let mut rng = OsRng::new().unwrap();
    rng.fill_bytes(&mut privkey);
    let pubkey = curve25519_base(&privkey);
    KeyPair{privkey : privkey, pubkey : pubkey}
}

fn dh(keypair : &KeyPair, pubkey: &[u8]) -> [u8; DHLEN] {
    curve25519(&keypair.privkey, pubkey)
}

fn hash(data: &[u8], out: &mut [u8]) {
    let mut h = Sha256::new();
    h.input(data);
    h.result(out);
}

fn hmac_hash(key: &[u8], data: &[u8], out: &mut [u8]) {
    let mut hmac = Hmac::new(Sha256::new(), key);
    hmac.input(data);
    hmac.raw_result(out);
}

fn hkdf(chaining_key: &[u8], data: &[u8], out: &mut [u8]) {
    let mut temp_key = [0u8; HASHLEN];
    let mut in2  = [0u8; HASHLEN];
    hmac_hash(chaining_key, data, &mut temp_key);
    hmac_hash(&temp_key, &[1u8], &mut out[0..HASHLEN]);
    copy_memory(out as &[u8], &mut in2);
    in2[HASHLEN] = 2;
    hmac_hash(&temp_key, &in2, &mut out[HASHLEN..2*HASHLEN]);
}

fn encrypt(key: &[u8], nonce: u64, authtext: &[u8], plaintext: &[u8], out: &mut[u8]) {
    let mut nonce_bytes = [0u8; 12];
    BigEndian::write_u64(&mut nonce_bytes[4..], nonce);
    let mut cipher = AesGcm::new(KeySize::KeySize256, key, &nonce_bytes, authtext);
    let mut tag = [0u8; MACLEN];
    cipher.encrypt(plaintext, out, &mut tag);
    copy_memory(&tag, &mut out[plaintext.len()..]);
}

fn decrypt(key: &[u8], nonce: u64, authtext: &[u8], ciphertext: &[u8], out: &mut[u8]) -> bool {
    let mut nonce_bytes = [0u8; 12];
    BigEndian::write_u64(&mut nonce_bytes[4..], nonce);
    let mut cipher = AesGcm::new(KeySize::KeySize256, key, &nonce_bytes, authtext);
    let tag = [0u8; MACLEN];
    cipher.decrypt(ciphertext, out, &tag)
}

pub enum Token {E, S, Dhee, Dhes, Dhse, Dhss}

pub enum NoiseError {DecryptError}

pub struct CipherState {
    k: [u8; CIPHERKEYLEN],
    n: u64
}

struct SymmetricState {
    cipherstate : CipherState,
    has_key : bool,
    ck: [u8; HASHLEN],
    h: [u8; HASHLEN]
}

pub struct HandshakeState {
    symmetricstate: SymmetricState,
    s: KeyPair,
    e: KeyPair,
    rs: [u8; DHLEN],
    re: [u8; DHLEN],
}

impl CipherState {

    pub fn encrypt_and_increment(&mut self, authtext: &[u8], plaintext: &[u8], out: &mut [u8]) {
        encrypt(&self.k, self.n, authtext, plaintext, out);
        self.n += 1;
    }

    pub fn decrypt_and_increment(&mut self, authtext: &[u8], ciphertext: &[u8], out: &mut [u8]) -> bool {
        if !decrypt(&self.k, self.n, authtext, ciphertext, out) {
            self.n += 1;
            return false;
        }
        self.n += 1;
        true
    }
}

impl SymmetricState {

    fn new(handshake_name: &[u8]) -> SymmetricState {
        let mut hname = [0u8; HASHLEN];
        match handshake_name.len() {
            0 ... HASHLEN => copy_memory(handshake_name, &mut hname),
            _ => hash(handshake_name, &mut hname)
        }
        let cipherstate = CipherState{k : [0; CIPHERKEYLEN], n:0};
        SymmetricState{cipherstate: cipherstate, has_key : false, ck : hname, h: hname}
    }

    fn mix_key(&mut self, data: &[u8]) {
        let mut hkdf_output = [0u8; 2*HASHLEN];
        hkdf(&self.ck, data, &mut hkdf_output);
        copy_memory(&hkdf_output[0..HASHLEN], &mut self.ck);
        copy_memory(&hkdf_output[HASHLEN..HASHLEN+CIPHERKEYLEN], &mut self.cipherstate.k);
        self.cipherstate.n = 0;
        self.has_key = true;
    }

    fn mix_hash(&mut self, data: &[u8]) {
        let mut buffer = [0u8; 65535];
        copy_memory(&data, &mut buffer);
        copy_memory(&self.h, &mut buffer[data.len()..data.len() + HASHLEN]);
        hash(&buffer, &mut self.h);
    }

    fn encrypt_and_hash(&mut self, plaintext: &[u8], out: &mut [u8]) -> usize {
        if self.has_key {
            self.cipherstate.encrypt_and_increment(&self.h, plaintext, out);
            self.mix_hash(&out[..plaintext.len() + MACLEN]);
            return plaintext.len() + MACLEN;
        } else {
            copy_memory(plaintext, out);
            self.mix_hash(plaintext);
            return plaintext.len();
        }
    }

    fn decrypt_and_hash(&mut self, data: &[u8], out: &mut [u8]) -> bool {
        if self.has_key {
            if !self.cipherstate.decrypt_and_increment(&self.h, data, out) {
                return false;
            }
            self.mix_hash(data);
        } else {
            copy_memory(data, out);
            self.mix_hash(data);
        }
        true
    }

    fn split(&self) -> (CipherState, CipherState) {
        let mut hkdf_output = [0u8; 2*HASHLEN];
        hkdf(&self.ck, &[0u8; 0], &mut hkdf_output);
        let mut c1 = CipherState{k : [0; CIPHERKEYLEN], n:0};
        let mut c2 = CipherState{k : [0; CIPHERKEYLEN], n:0};
        copy_memory( &hkdf_output[0..CIPHERKEYLEN], &mut c1.k);
        copy_memory( &hkdf_output[HASHLEN..HASHLEN+CIPHERKEYLEN], &mut c2.k);
        (c1, c2)
    }

}

impl HandshakeState {

    pub fn new(handshake_name: &[u8], new_s : KeyPair, new_e : KeyPair, new_rs: [u8; 32], new_re : [u8; 32] ) -> HandshakeState {
        let symmetricstate = SymmetricState::new(handshake_name);
        HandshakeState{symmetricstate: symmetricstate, s: new_s, e: new_e, rs: new_rs, re: new_re}
    }

    pub fn write_handshake_message(&mut self,
                               descriptor: &[Token],
                               last: bool,
                               payload: &[u8],
                               out: &mut [u8]) -> Option<(CipherState, CipherState)> {
        let mut index = 0;
        for token in descriptor {
            match *token {
                Token::E => {
                    self.e = generate_keypair();
                    index += self.symmetricstate.encrypt_and_hash(&self.e.pubkey, &mut out[index..]);
                },
                Token::S => index += self.symmetricstate.encrypt_and_hash(&self.s.pubkey, &mut out[index..]),
                Token::Dhee => self.symmetricstate.mix_key(&dh(&self.e, &self.re)),
                Token::Dhes => self.symmetricstate.mix_key(&dh(&self.e, &self.rs)),
                Token::Dhse => self.symmetricstate.mix_key(&dh(&self.s, &self.re)),
                Token::Dhss => self.symmetricstate.mix_key(&dh(&self.s, &self.rs)),
            }
        }
        self.symmetricstate.encrypt_and_hash(payload, &mut out[index..]);
        match last {
            true => Some(self.symmetricstate.split()),
            false => None
        }
    }

    pub fn read_handshake_message(&mut self,
                              buffer: &[u8],
                              descriptor: &[Token],
                              last: bool,
                              out: &mut [u8]) -> Result<Option<(CipherState, CipherState)>, NoiseError> {
        let mut ptr = buffer;
        for token in descriptor {
            match *token {
                Token::E | Token::S => {
                    let data = match self.symmetricstate.has_key {
                        true =>  {let temp = &ptr[..DHLEN+16]; ptr = &ptr[DHLEN+16..]; temp}
                        false => {let temp = &ptr[..DHLEN];    ptr = &ptr[DHLEN..];    temp}
                    };
                    if !self.symmetricstate.decrypt_and_hash(data, match *token {
                            Token::E => &mut self.re,
                            Token::S => &mut self.rs,
                            _ => unreachable!()}) {
                        return Err(NoiseError::DecryptError);
                    }
                },
                Token::Dhee => self.symmetricstate.mix_key(&dh(&self.e, &self.re)),
                Token::Dhes => self.symmetricstate.mix_key(&dh(&self.s, &self.re)),
                Token::Dhse => self.symmetricstate.mix_key(&dh(&self.e, &self.rs)),
                Token::Dhss => self.symmetricstate.mix_key(&dh(&self.s, &self.rs)),
            }
        }
        if !self.symmetricstate.decrypt_and_hash(ptr, out) {
            return Err(NoiseError::DecryptError);
        }
        match last {
            true => Ok(Some(self.symmetricstate.split())),
            false => Ok(None)
        }
    }

}

#[cfg(test)]
mod tests {

    extern crate rustc_serialize;

    use super::*;
    use super::hash;
    use super::hmac_hash;
    use super::dh;
    use super::copy_memory;
    use self::rustc_serialize::hex::{FromHex, ToHex};

    #[test]
    fn crypto_tests() {

        // SHA256 test
        {
            let mut output = [0u8; 32];
            hash("abc".as_bytes(), &mut output);
            assert!(output.to_hex() == "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
        }

        // HMAC-SHA256 test - RFC 4231
        {
            let key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".from_hex().unwrap();
            let data = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd".from_hex().unwrap();
            let mut output = [0u8; 32];
            hmac_hash(&key, &data, &mut output);
            println!("{}, {}, {}", key.len(), data.len(), output.to_hex());
            assert!(output.to_hex() == "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe");
        }

        // Curve25519 test - draft-curves-10
        {
            let scalar = "a546e36bf0527c9d3b16154b82465edd62144c0ac1fc5a18506a2244ba449ac4".from_hex().unwrap();
            let mut keypair = KeyPair{privkey: [0; 32], pubkey: [0; 32]};
            copy_memory(&scalar, &mut keypair.privkey);
            let public = "e6db6867583030db3594c1a424b15f7c726624ec26b3353b10a903a6d0ab1c4c".from_hex().unwrap();
            let output = dh(&keypair, &public);
            assert!(output.to_hex() == "c3da55379de9c6908e94ea4df28d084f32eccf03491c71f754b4075577a28552");
        }

    }
}
<|endoftext|>


<commit_before>//! The goal of this crate is to provide Rust bindings to the Web APIs and to allow
//! a high degree of interoperability between Rust and JavaScript.
//!
//! ## Examples
//!
//! You can directly embed JavaScript code into Rust:
//!
//! ```rust
//! let message = "Hello, 世界!";
//! let result = js! {
//!     alert( @{message} );
//!     return 2 + 2 * 2;
//! };
//!
//! println!( "2 + 2 * 2 = {:?}", result );
//! ```
//!
//! Even closures are supported:
//!
//! ```rust
//! let print_hello = |name: String| {
//!     println!( "Hello, {}!", name );
//! };
//!
//! js! {
//!     var print_hello = @{print_hello};
//!     print_hello( "Bob" );
//!     print_hello.drop(); // Necessary to clean up the closure on Rust's side.
//! }
//! ```
//!
//! You can also pass arbitrary structures thanks to [serde]:
//!
//! ```rust
//! #[derive(Serialize)]
//! struct Person {
//!     name: String,
//!     age: i32
//! }
//!
//! js_serializable!( Person );
//!
//! js! {
//!     var person = @{person};
//!     console.log( person.name + " is " + person.age + " years old." );
//! };
//! ```
//!
//! [serde]: https://serde.rs/
//!
//! This crate also exposes a number of Web APIs, for example:
//!
//! ```rust
//! let button = document().query_selector( "#hide-button" ).unwrap();
//! button.add_event_listener( move |_: ClickEvent| {
//!     for anchor in document().query_selector_all( "#main a" ) {
//!         js!( @{anchor}.style = "display: none;"; );
//!     }
//! });
//! ```

#![deny(
    missing_docs,
    missing_debug_implementations,
    trivial_numeric_casts,
    unused_import_braces,
    unused_qualifications
)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(not(feature = "nightly"), deny(unstable_features))]
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
#![recursion_limit="1500"]

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde as serde_crate;

#[cfg(any(test, feature = "serde_json"))]
extern crate serde_json;

#[cfg(all(test, feature = "serde"))]
#[macro_use]
extern crate serde_derive;

#[macro_use]
mod webcore;
mod webapi;
mod ecosystem;

pub use webcore::initialization::{
    initialize,
    event_loop
};
pub use webcore::value::{
    Undefined,
    Null,
    Value,
    Reference
};
pub use webcore::number::Number;
pub use webcore::object::Object;
pub use webcore::array::Array;

pub use webcore::unsafe_typed_array::UnsafeTypedArray;
pub use webcore::once::Once;

#[cfg(feature = "serde")]
/// A module with serde-related APIs.
pub mod serde {
    pub use ecosystem::serde::{
        ConversionError,
        Serde
    };
}

/// A module with bindings to the Web APIs.
pub mod web {
    pub use webapi::window::{
        Window,
        window
    };
    pub use webapi::document::{
        Document,
        document
    };
    pub use webapi::global::{
        set_timeout,
        alert
    };
    pub use webapi::cross_origin_setting::CrossOriginSetting;
    pub use webapi::date::Date;
    pub use webapi::event_target::{IEventTarget, EventTarget, EventListenerHandle};
    pub use webapi::node::{INode, Node, CloneKind};
    pub use webapi::element::{IElement, Element};
    pub use webapi::text_node::TextNode;
    pub use webapi::html_element::{IHtmlElement, HtmlElement};
    pub use webapi::window_or_worker::IWindowOrWorker;
    pub use webapi::token_list::TokenList;
    pub use webapi::node_list::NodeList;
    pub use webapi::string_map::StringMap;
    pub use webapi::storage::Storage;
    pub use webapi::location::Location;
    pub use webapi::array_buffer::ArrayBuffer;
    pub use webapi::typed_array::TypedArray;
    pub use webapi::file_reader::{FileReader, FileReaderResult};

    /// A module containing error types.
    pub mod error {
        pub use webapi::node::NotFoundError;
    }

    /// A module containing HTML DOM elements.
    pub mod html_element {
        pub use webapi::html_elements::ImageElement;
        pub use webapi::html_elements::InputElement;
    }

    /// A module containing JavaScript DOM events.
    pub mod event {
        pub use webapi::event::{
            ConcreteEvent,

            IEvent,
            IKeyboardEvent,
            IUiEvent,
            IMouseEvent,
            IFocusEvent,
            IProgressEvent,

            EventPhase,
            KeyboardLocation,
            ModifierKey,
            MouseButton,

            ChangeEvent,
            KeypressEvent,
            KeydownEvent,
            KeyupEvent,
            ClickEvent,
            DoubleClickEvent,
            FocusEvent,
            BlurEvent,
            HashChangeEvent,
            ResourceLoadEvent,
            ResourceAbortEvent,
            ResourceErrorEvent,
            ProgressEvent,
            LoadStartEvent,
            LoadEndEvent,
            ProgressLoadEvent,
            ProgressAbortEvent,
            ProgressErrorEvent,
            InputEvent
        };
    }
}

/// A module containing stable counterparts to currently
/// unstable Rust features.
pub mod unstable {
    pub use webcore::try_from::{
        TryFrom,
        TryInto
    };

    pub use webcore::void::Void;
}

#[doc(hidden)]
pub mod private {
    pub use webcore::ffi::exports::*;
    pub use webcore::serialization::{
        JsSerializable,
        JsSerializableOwned,
        PreallocatedArena,
        SerializedValue
    };

    pub use webcore::newtype::{
        IntoNewtype,
        Newtype
    };

    pub use webcore::value::{
        FromReference,
        FromReferenceUnchecked
    };

    #[cfg(feature = "serde")]
    pub use ecosystem::serde::{
        to_value,
        from_value
    };

    // This is to prevent an unused_mut warnings in macros, because an `allow` doesn't work apparently?
    #[allow(dead_code)]
    #[inline(always)]
    pub fn noop< T >( _: &mut T ) {}
}
<commit_msg>exported RequestAnimationFrameHandle<commit_after>//! The goal of this crate is to provide Rust bindings to the Web APIs and to allow
//! a high degree of interoperability between Rust and JavaScript.
//!
//! ## Examples
//!
//! You can directly embed JavaScript code into Rust:
//!
//! ```rust
//! let message = "Hello, 世界!";
//! let result = js! {
//!     alert( @{message} );
//!     return 2 + 2 * 2;
//! };
//!
//! println!( "2 + 2 * 2 = {:?}", result );
//! ```
//!
//! Even closures are supported:
//!
//! ```rust
//! let print_hello = |name: String| {
//!     println!( "Hello, {}!", name );
//! };
//!
//! js! {
//!     var print_hello = @{print_hello};
//!     print_hello( "Bob" );
//!     print_hello.drop(); // Necessary to clean up the closure on Rust's side.
//! }
//! ```
//!
//! You can also pass arbitrary structures thanks to [serde]:
//!
//! ```rust
//! #[derive(Serialize)]
//! struct Person {
//!     name: String,
//!     age: i32
//! }
//!
//! js_serializable!( Person );
//!
//! js! {
//!     var person = @{person};
//!     console.log( person.name + " is " + person.age + " years old." );
//! };
//! ```
//!
//! [serde]: https://serde.rs/
//!
//! This crate also exposes a number of Web APIs, for example:
//!
//! ```rust
//! let button = document().query_selector( "#hide-button" ).unwrap();
//! button.add_event_listener( move |_: ClickEvent| {
//!     for anchor in document().query_selector_all( "#main a" ) {
//!         js!( @{anchor}.style = "display: none;"; );
//!     }
//! });
//! ```

#![deny(
    missing_docs,
    missing_debug_implementations,
    trivial_numeric_casts,
    unused_import_braces,
    unused_qualifications
)]
#![cfg_attr(feature = "dev", allow(unstable_features))]
#![cfg_attr(feature = "dev", feature(plugin))]
#![cfg_attr(feature = "dev", plugin(clippy))]
#![cfg_attr(not(feature = "nightly"), deny(unstable_features))]
#![cfg_attr(feature = "nightly", feature(core_intrinsics))]
#![recursion_limit="1500"]

#[cfg(feature = "serde")]
#[macro_use]
extern crate serde as serde_crate;

#[cfg(any(test, feature = "serde_json"))]
extern crate serde_json;

#[cfg(all(test, feature = "serde"))]
#[macro_use]
extern crate serde_derive;

#[macro_use]
mod webcore;
mod webapi;
mod ecosystem;

pub use webcore::initialization::{
    initialize,
    event_loop
};
pub use webcore::value::{
    Undefined,
    Null,
    Value,
    Reference
};
pub use webcore::number::Number;
pub use webcore::object::Object;
pub use webcore::array::Array;

pub use webcore::unsafe_typed_array::UnsafeTypedArray;
pub use webcore::once::Once;

#[cfg(feature = "serde")]
/// A module with serde-related APIs.
pub mod serde {
    pub use ecosystem::serde::{
        ConversionError,
        Serde
    };
}

/// A module with bindings to the Web APIs.
pub mod web {
    pub use webapi::window::{
        Window,
        window
    };
    pub use webapi::document::{
        Document,
        document
    };
    pub use webapi::global::{
        set_timeout,
        alert
    };
    pub use webapi::cross_origin_setting::CrossOriginSetting;
    pub use webapi::date::Date;
    pub use webapi::event_target::{IEventTarget, EventTarget, EventListenerHandle};
    pub use webapi::window::RequestAnimationFrameHandle;
    pub use webapi::node::{INode, Node, CloneKind};
    pub use webapi::element::{IElement, Element};
    pub use webapi::text_node::TextNode;
    pub use webapi::html_element::{IHtmlElement, HtmlElement};
    pub use webapi::window_or_worker::IWindowOrWorker;
    pub use webapi::token_list::TokenList;
    pub use webapi::node_list::NodeList;
    pub use webapi::string_map::StringMap;
    pub use webapi::storage::Storage;
    pub use webapi::location::Location;
    pub use webapi::array_buffer::ArrayBuffer;
    pub use webapi::typed_array::TypedArray;
    pub use webapi::file_reader::{FileReader, FileReaderResult};

    /// A module containing error types.
    pub mod error {
        pub use webapi::node::NotFoundError;
    }

    /// A module containing HTML DOM elements.
    pub mod html_element {
        pub use webapi::html_elements::ImageElement;
        pub use webapi::html_elements::InputElement;
    }

    /// A module containing JavaScript DOM events.
    pub mod event {
        pub use webapi::event::{
            ConcreteEvent,

            IEvent,
            IKeyboardEvent,
            IUiEvent,
            IMouseEvent,
            IFocusEvent,
            IProgressEvent,

            EventPhase,
            KeyboardLocation,
            ModifierKey,
            MouseButton,

            ChangeEvent,
            KeypressEvent,
            KeydownEvent,
            KeyupEvent,
            ClickEvent,
            DoubleClickEvent,
            FocusEvent,
            BlurEvent,
            HashChangeEvent,
            ResourceLoadEvent,
            ResourceAbortEvent,
            ResourceErrorEvent,
            ProgressEvent,
            LoadStartEvent,
            LoadEndEvent,
            ProgressLoadEvent,
            ProgressAbortEvent,
            ProgressErrorEvent,
            InputEvent
        };
    }
}

/// A module containing stable counterparts to currently
/// unstable Rust features.
pub mod unstable {
    pub use webcore::try_from::{
        TryFrom,
        TryInto
    };

    pub use webcore::void::Void;
}

#[doc(hidden)]
pub mod private {
    pub use webcore::ffi::exports::*;
    pub use webcore::serialization::{
        JsSerializable,
        JsSerializableOwned,
        PreallocatedArena,
        SerializedValue
    };

    pub use webcore::newtype::{
        IntoNewtype,
        Newtype
    };

    pub use webcore::value::{
        FromReference,
        FromReferenceUnchecked
    };

    #[cfg(feature = "serde")]
    pub use ecosystem::serde::{
        to_value,
        from_value
    };

    // This is to prevent an unused_mut warnings in macros, because an `allow` doesn't work apparently?
    #[allow(dead_code)]
    #[inline(always)]
    pub fn noop< T >( _: &mut T ) {}
}
<|endoftext|>


<commit_before>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_name = "sodiumoxide"]
#![crate_type = "lib"]
#![warn(missing_docs)]
#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]
#![feature(libc, collections)]

/* workaround: the rust compiler doesn't recognize
   the features path, test and io yet, still it warns
   about using them */
#![allow(unused_features)]
#![feature(path, test, io)]

extern crate "libsodium-sys" as ffi;
extern crate libc;

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        ffi::sodium_init() == 0
    }
}

#[macro_use]
mod utils;

pub mod randombytes;

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;
    pub mod verify;
}

<commit_msg>Added #![feature(core)] to silence waring<commit_after>/*!
Rust bindings to the [sodium library](https://github.com/jedisct1/libsodium).

Sodium is a portable implementation of Dan Bernsteins [NaCl: Networking and
Cryptography library](http://nacl.cr.yp.to)

For most users, if you want public-key (asymmetric) cryptography you should use
the functions in `crypto::asymmetricbox` for encryption/decryption.

If you want secret-key (symmetric) cryptography you should be using the
functions in `crypto::secretbox` for encryption/decryption.

For public-key signatures you should use the functions in `crypto::sign` for
signature creation and verification.

Unless you know what you're doing you most certainly don't want to use the
functions in `crypto::scalarmult`, `crypto::stream`, `crypto::auth` and
`crypto::onetimeauth`.

## Thread Safety
All functions in this library are thread-safe provided that the `init()`
function has been called during program execution.

If `init()` hasn't been called then all functions except the random-number
generation functions and the key-generation functions are thread-safe.

# Public-key cryptography
 `crypto::asymmetricbox`

 `crypto::sign`

# Secret-key cryptography
 `crypto::secretbox`

 `crypto::stream`

 `crypto::auth`

 `crypto::onetimeauth`

# Low-level functions
 `crypto::hash`

 `crypto::verify`

 `crypto::shorthash`
 */
#![crate_name = "sodiumoxide"]
#![crate_type = "lib"]
#![warn(missing_docs)]
#![warn(non_upper_case_globals)]
#![warn(non_camel_case_types)]
#![warn(unused_qualifications)]
#![feature(libc, collections, core)]

/* workaround: the rust compiler doesn't recognize
   the features path, test and io yet, still it warns
   about using them */
#![allow(unused_features)]
#![feature(path, test, io)]

extern crate "libsodium-sys" as ffi;
extern crate libc;

/**
 * `init()` initializes the sodium library and chooses faster versions of
 * the primitives if possible. `init()` also makes the random number generation
 * functions (`gen_key`, `gen_keypair`, `gen_nonce`, `randombytes`, `randombytes_into`)
 * thread-safe
 */
pub fn init() -> bool {
    unsafe {
        ffi::sodium_init() == 0
    }
}

#[macro_use]
mod utils;

pub mod randombytes;

/**
 * Cryptographic functions
 */
pub mod crypto {
    pub mod asymmetricbox;
    pub mod sign;
    pub mod scalarmult;
    pub mod auth;
    pub mod hash;
    pub mod secretbox;
    pub mod onetimeauth;
    pub mod stream;
    pub mod shorthash;
    pub mod verify;
}

<|endoftext|>


<commit_before>#![feature(io)]
#![feature(path)]
#![feature(fs)]
#![feature(collections)]
#![feature(core)]

use std::fs::{File};
use std::string::String;
use std::str::StrExt;
use std::path::AsPath;
use std::error::FromError;
use std::io::{Read, BufReader, Write};
use std::vec::Vec;
use std::num::ParseIntError;
use std::mem;

pub enum Error {
    IO,
    Parse,
    DataType,
    FieldType,
    Malformed,
    NotImplemented
}

impl FromError<std::io::Error> for Error {
    fn from_error(_: std::io::Error) -> Error {
        Error::IO
    }
}

impl FromError<ParseIntError> for Error {
    fn from_error(_: ParseIntError) -> Error {
        Error::Parse
    }
}

pub enum DataType {
    XDRFloat,
    FloatLE,
}

impl DataType {
    fn from_str(s: &str) -> Result<DataType, Error> {
        match s {
            "float_le" => Ok(DataType::FloatLE),
//            "xdr_float" => Ok(DataType::XDRFloat),
            _ => Err(Error::DataType)
        }
    }
}

pub enum FieldType {
    Uniform
}

impl FieldType {
    fn from_str(s: &str) -> Result<FieldType, Error> {
        match s {
            "uniform" => Ok(FieldType::Uniform),
            _ => Err(Error::FieldType)
        }
    }
}

pub struct AVSFile<'a> {
    pub ndim: usize,
    pub sizes: Vec<usize>,
    pub data_type: DataType,
    pub field_type: FieldType,
    reader: Box<Read + 'a>
}

impl<'a> AVSFile<'a> {
    pub fn write<W: Write, T>(
                writer: &mut W, ndim: usize, dims: &[usize], data: &[T])
                    -> Result<(), Error> {
        // header
        try!(writer.write_fmt(format_args!("# AVS FLD file (written by avsfldrs github.com/greyhill/avsfldrs)\n")));
        try!(writer.write_fmt(format_args!("ndim={}\n", ndim)));
        try!(writer.write_fmt(format_args!("veclen=1\n")));
        try!(writer.write_fmt(format_args!("nspace={}\n", ndim)));
        try!(writer.write_fmt(format_args!("field=uniform\n")));
        try!(writer.write_fmt(format_args!("data=float_le\n"))); // TODO
        for (id, size) in dims.iter().enumerate() {
            try!(writer.write_fmt(format_args!("dim{}={}\n", id+1, size)));
        }
        try!(writer.write_fmt(format_args!("{}{}", 12 as char, 12 as char)));
        try!(writer.write_all(unsafe { mem::transmute(data) }));
        Err(Error::IO)
    }

    pub fn read<T>(self: &mut Self) -> Result<Box<[T]>, Error> {
        let size = self.sizes.iter().fold(1 as usize, |l, r| l * *r);
        let mut buf_u8 = Vec::<u8>::with_capacity(mem::size_of::<T>()*size);
        try!(self.reader.read_to_end(&mut buf_u8));
        let buf: Vec<T> = unsafe { mem::transmute(buf_u8) };
        Ok(buf.into_boxed_slice())
    }

    pub fn open<P: AsPath>(path: &P) -> Result<AVSFile, Error> {
        let mut reader = BufReader::new(try!(File::open(path)));

        let mut ndim: Option<usize> = None;
        let mut sizes = Vec::<Option<usize>>::new();
        let mut data_type: Option<DataType> = None;
        let mut field_type: Option<FieldType> = None;
        let mut external: Option<String> = None;

        let mut line = String::new();
        let mut last_char: u8 = 0;
        loop {
            let mut new_char_buf: [u8;1] = [ 0u8 ];
            try!(reader.read(&mut new_char_buf));

            // break on two chr 14s
            let new_char = new_char_buf[0];
            if (new_char, last_char) == (12u8, 12u8) {
                break;
            }
            last_char = new_char;

            line.push(new_char as char);

            // new line; process the line and discard
            if new_char == 10 {
                let tokens: Vec<&str> = line.split('=')
                    .map(|s| s.trim()).collect();
                match &tokens[..] {
                    ["ndim", s] => {
                        let nd = try!(s.parse::<usize>());
                        ndim = Some(nd);
                        for _ in 0..nd {
                            sizes.push(None);
                        }
                    },
                    ["dim1", s] => sizes[0] = Some(try!(s.parse::<usize>())),
                    ["dim2", s] => sizes[1] = Some(try!(s.parse::<usize>())),
                    ["dim3", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim4", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim5", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim6", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim7", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["data", s] =>
                        data_type = Some(try!(DataType::from_str(s))),
                    ["field", s] =>
                        field_type = Some(try!(FieldType::from_str(s))),
                    ["variable 1 file", s] =>
                        external = Some(String::from_str(s)),
                    _ => {}
                }
            }
            // hack?  code smell?  need borrow in previous block to expire
            if new_char == 10 {
                line.clear();
            }
        }

        match external {
            None => {
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
            Some(path) => {
                let new_reader = BufReader::new(try!(File::open(&path)));
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(new_reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
        }
    }
}

<commit_msg>oops, fixed return value for AVSFile::write<commit_after>#![feature(io)]
#![feature(path)]
#![feature(fs)]
#![feature(collections)]
#![feature(core)]

use std::fs::{File};
use std::string::String;
use std::str::StrExt;
use std::path::AsPath;
use std::error::FromError;
use std::io::{Read, BufReader, Write};
use std::vec::Vec;
use std::num::ParseIntError;
use std::mem;

pub enum Error {
    IO,
    Parse,
    DataType,
    FieldType,
    Malformed,
    NotImplemented
}

impl FromError<std::io::Error> for Error {
    fn from_error(_: std::io::Error) -> Error {
        Error::IO
    }
}

impl FromError<ParseIntError> for Error {
    fn from_error(_: ParseIntError) -> Error {
        Error::Parse
    }
}

pub enum DataType {
    XDRFloat,
    FloatLE,
}

impl DataType {
    fn from_str(s: &str) -> Result<DataType, Error> {
        match s {
            "float_le" => Ok(DataType::FloatLE),
//            "xdr_float" => Ok(DataType::XDRFloat),
            _ => Err(Error::DataType)
        }
    }
}

pub enum FieldType {
    Uniform
}

impl FieldType {
    fn from_str(s: &str) -> Result<FieldType, Error> {
        match s {
            "uniform" => Ok(FieldType::Uniform),
            _ => Err(Error::FieldType)
        }
    }
}

pub struct AVSFile<'a> {
    pub ndim: usize,
    pub sizes: Vec<usize>,
    pub data_type: DataType,
    pub field_type: FieldType,
    reader: Box<Read + 'a>
}

impl<'a> AVSFile<'a> {
    pub fn write<W: Write, T>(
                writer: &mut W, ndim: usize, dims: &[usize], data: &[T])
                    -> Result<(), Error> {
        // header
        try!(writer.write_fmt(format_args!("# AVS FLD file (written by avsfldrs github.com/greyhill/avsfldrs)\n")));
        try!(writer.write_fmt(format_args!("ndim={}\n", ndim)));
        try!(writer.write_fmt(format_args!("veclen=1\n")));
        try!(writer.write_fmt(format_args!("nspace={}\n", ndim)));
        try!(writer.write_fmt(format_args!("field=uniform\n")));
        try!(writer.write_fmt(format_args!("data=float_le\n"))); // TODO
        for (id, size) in dims.iter().enumerate() {
            try!(writer.write_fmt(format_args!("dim{}={}\n", id+1, size)));
        }
        try!(writer.write_fmt(format_args!("{}{}", 12 as char, 12 as char)));
        try!(writer.write_all(unsafe { mem::transmute(data) }));
        Ok(())
    }

    pub fn read<T>(self: &mut Self) -> Result<Box<[T]>, Error> {
        let size = self.sizes.iter().fold(1 as usize, |l, r| l * *r);
        let mut buf_u8 = Vec::<u8>::with_capacity(mem::size_of::<T>()*size);
        try!(self.reader.read_to_end(&mut buf_u8));
        let buf: Vec<T> = unsafe { mem::transmute(buf_u8) };
        Ok(buf.into_boxed_slice())
    }

    pub fn open<P: AsPath>(path: &P) -> Result<AVSFile, Error> {
        let mut reader = BufReader::new(try!(File::open(path)));

        let mut ndim: Option<usize> = None;
        let mut sizes = Vec::<Option<usize>>::new();
        let mut data_type: Option<DataType> = None;
        let mut field_type: Option<FieldType> = None;
        let mut external: Option<String> = None;

        let mut line = String::new();
        let mut last_char: u8 = 0;
        loop {
            let mut new_char_buf: [u8;1] = [ 0u8 ];
            try!(reader.read(&mut new_char_buf));

            // break on two chr 14s
            let new_char = new_char_buf[0];
            if (new_char, last_char) == (12u8, 12u8) {
                break;
            }
            last_char = new_char;

            line.push(new_char as char);

            // new line; process the line and discard
            if new_char == 10 {
                let tokens: Vec<&str> = line.split('=')
                    .map(|s| s.trim()).collect();
                match &tokens[..] {
                    ["ndim", s] => {
                        let nd = try!(s.parse::<usize>());
                        ndim = Some(nd);
                        for _ in 0..nd {
                            sizes.push(None);
                        }
                    },
                    ["dim1", s] => sizes[0] = Some(try!(s.parse::<usize>())),
                    ["dim2", s] => sizes[1] = Some(try!(s.parse::<usize>())),
                    ["dim3", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim4", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim5", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim6", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["dim7", s] => sizes[2] = Some(try!(s.parse::<usize>())),
                    ["data", s] =>
                        data_type = Some(try!(DataType::from_str(s))),
                    ["field", s] =>
                        field_type = Some(try!(FieldType::from_str(s))),
                    ["variable 1 file", s] =>
                        external = Some(String::from_str(s)),
                    _ => {}
                }
            }
            // hack?  code smell?  need borrow in previous block to expire
            if new_char == 10 {
                line.clear();
            }
        }

        match external {
            None => {
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
            Some(path) => {
                let new_reader = BufReader::new(try!(File::open(&path)));
                let mut tr = AVSFile {
                    ndim: try!(ndim.ok_or(Error::Malformed)),
                    sizes: Vec::<usize>::new(),
                    data_type: try!(data_type.ok_or(Error::Malformed)),
                    field_type: try!(field_type.ok_or(Error::Malformed)),
                    reader: Box::new(new_reader),
                };
                for idx in 0..ndim.unwrap() {
                    tr.sizes.push(
                        try!(sizes[idx].ok_or(Error::Malformed)));
                }
                Ok(tr)
            },
        }
    }
}

<|endoftext|>


<commit_before>extern crate hyper;
extern crate url;
extern crate serde;
extern crate serde_json;

use std::error::Error as StdError;
use std::io::{Read, Write};
use std::io::Error as IoError;
use std::time::Duration;

use serde::de::Deserialize;
use hyper::client::Request as HyperRequest;
use hyper::client::Response as HyperResponse;
use hyper::method::Method;
use hyper::net::Fresh;

#[doc(no_inline)]
pub use hyper::header::{Headers, Header, HeaderFormat, UserAgent};
#[doc(no_inline)]
pub use url::Url;
#[doc(no_inline)]
pub use hyper::error::Error as HyperError;
#[doc(no_inline)]
pub use hyper::status::StatusCode;

#[derive(Debug)]
pub enum Error {
    UnsuccessfulResponse(Response),
    Json(serde_json::error::Error),
    Hyper(HyperError),
}

impl StdError for Error {
    fn description(&self) -> &str {
        "ease error"
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::Json(ref error)  => Some(error),
            Error::Hyper(ref error) => Some(error),
            _                       => None,
        }
    }
}

impl From<HyperError> for Error {
    fn from(h: HyperError) -> Error {
        Error::Hyper(h)
    }
}

impl From<IoError> for Error {
    fn from(i: IoError) -> Error {
        Error::Hyper(HyperError::Io(i))
    }
}

#[derive(Debug)]
pub struct Response {
    pub hyper_response: HyperResponse,
    pub body: String,
}

impl Response {
    fn from_hyper_response(mut hyper_response: HyperResponse) -> Result<Response, IoError> {
        let mut body = String::new();
        hyper_response.read_to_string(&mut body).map(|_| {
            Response {
                hyper_response: hyper_response,
                body: body,
            }
        })
    }

    /// Deserializes the body of the response from JSON into
    /// a `T`.
    pub fn from_json<T: Deserialize>(&self) -> Result<T, Error> {
        serde_json::from_str(&*self.body).map_err(|e| Error::Json(e))
    }
}

#[derive(Clone)]
pub struct Request<'a> {
    url: Url,
    params: Option<Vec<(&'a str, &'a str)>>,
    body: Option<String>,
    read_timeout: Option<Duration>,
    headers: Option<Headers>,
}

impl<'a> Request<'a> {
    pub fn new(url: Url) -> Request<'a> {
        Request {
            url: url,
            params: None,
            body: None,
            read_timeout: None,
            headers: None,
        }
    }

    /// Sets one parameter. On a GET or DELETE request, this parameter will
    /// be stored in the URL. On a POST or PUT request, it is stored in the
    /// body of the request. Hence, if you call this method on a POST or
    /// PUT request, you cannot also call `body`.
    pub fn param(&mut self, key: &'a str, value: &'a str) -> &mut Request<'a> {
        if let Some(ref mut p) = self.params {
            p.push((key, value));
        } else {
            let mut v = Vec::new();
            v.push((key, value));
            self.params = Some(v);
        }
        self
    }

    /// Sets many parameters. On a GET or DELETE request, these parameters will
    /// be stored in the URL. On a POST or PUT request, they are stored in the
    /// body of the request. Hence, if you call this method on a POST or
    /// PUT request, you cannot also call `body`.
    pub fn params<T>(&mut self, values: T) -> &mut Request<'a>
        where T: IntoIterator<Item = (&'a str, &'a str)>
    {
        if let Some(ref mut p) = self.params {
            for value in values {
                p.push(value);
            }
        } else {
            let mut v = Vec::new();
            for value in values {
                v.push(value);
            }
            self.params = Some(v);
        }
        self
    }

    /// Writes a `String` to the body of the request. Don't call this
    /// method if you also call `param` on a PUT or POST request.
    pub fn body(&mut self, body: String) -> &mut Request<'a> {
        self.body = Some(body);
        self
    }

    /// Sets a header for the request.
    pub fn header<H: Header + HeaderFormat>(&mut self, header: H) -> &mut Request<'a> {
        if let Some(ref mut h) = self.headers {
            h.set(header);
        } else {
            let mut v = Headers::new();
            v.set(header);
            self.headers = Some(v);
        }
        self
    }

    /// Sets a read timeout for the response.
    pub fn read_timeout(&mut self, timeout: Duration) -> &mut Request<'a> {
        self.read_timeout = Some(timeout);
        self
    }

    fn send_request(&mut self, mut req: HyperRequest<Fresh>) -> Result<Response, Error> {
        if let Some(headers) = self.headers.as_ref() {
            req.headers_mut().extend(headers.iter());
        }

        let _ = req.set_read_timeout(self.read_timeout);

        let mut req = try!(req.start());

        if let Some(body) = self.body.as_ref() {
            try!(req.write_all(body.as_bytes()));
        }

        let resp = try!(req.send());
        let resp = try!(Response::from_hyper_response(resp));

        if resp.hyper_response.status.is_success() {
            Ok(resp)
        } else {
            Err(Error::UnsuccessfulResponse(resp))
        }
    }

    /// Sends a GET request and returns either an error
    /// or a `String` of the response.
    pub fn get(&mut self) -> Result<Response, Error> {
        let mut url = self.url.clone();

        if let Some(ref params) = self.params {
            url.query_pairs_mut().extend_pairs(params.into_iter().map(|&x| x));
        }

        let req = try!(HyperRequest::new(Method::Get, url));
        self.send_request(req)
    }

    /// Sends a DELETE request and returns either an error
    /// or a `String` of the response.
    pub fn delete(&mut self) -> Result<Response, Error> {
        let mut url = self.url.clone();

        if let Some(ref params) = self.params {
            url.query_pairs_mut().extend_pairs(params.into_iter().map(|&x| x));
        }

        let req = try!(HyperRequest::new(Method::Delete, url));
        self.send_request(req)
    }

    /// Sends a POST request and returns either an error
    /// or a `String` of the response.
    pub fn post(&mut self) -> Result<Response, Error> {
        let url = self.url.clone();

        if let Some(ref params) = self.params {
            let mut serializer = url::form_urlencoded::Serializer::new(String::new());
            serializer.extend_pairs(params);
            self.body = Some(serializer.finish());
        }

        let req = try!(HyperRequest::new(Method::Post, url));
        self.send_request(req)
    }

    /// Sends a PUT request and returns either an error
    /// or a `String` of the response.
    pub fn put(&mut self) -> Result<Response, Error> {
        let url = self.url.clone();

        if let Some(ref params) = self.params {
            let mut serializer = url::form_urlencoded::Serializer::new(String::new());
            serializer.extend_pairs(params);
            self.body = Some(serializer.finish());
        }

        let req = try!(HyperRequest::new(Method::Put, url));
        self.send_request(req)
    }
}
<commit_msg>error: implement the Display trait<commit_after>extern crate hyper;
extern crate url;
extern crate serde;
extern crate serde_json;

use std::error::Error as StdError;
use std::fmt::{self, Display, Formatter};
use std::io::{Read, Write};
use std::io::Error as IoError;
use std::time::Duration;

use serde::de::Deserialize;
use hyper::client::Request as HyperRequest;
use hyper::client::Response as HyperResponse;
use hyper::method::Method;
use hyper::net::Fresh;

#[doc(no_inline)]
pub use hyper::header::{Headers, Header, HeaderFormat, UserAgent};
#[doc(no_inline)]
pub use url::Url;
#[doc(no_inline)]
pub use hyper::error::Error as HyperError;
#[doc(no_inline)]
pub use hyper::status::StatusCode;

#[derive(Debug)]
pub enum Error {
    UnsuccessfulResponse(Response),
    Json(serde_json::error::Error),
    Hyper(HyperError),
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            Error::UnsuccessfulResponse(ref rsp)    => write!(f, "server response failed: {:?}", rsp),
            Error::Json(ref error)                  => write!(f, "json parse error: {}", error),
            Error::Hyper(ref error)                 => write!(f, "HTTP communication error: {}", error),
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        "ease error"
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::Json(ref error)  => Some(error),
            Error::Hyper(ref error) => Some(error),
            _                       => None,
        }
    }
}

impl From<HyperError> for Error {
    fn from(h: HyperError) -> Error {
        Error::Hyper(h)
    }
}

impl From<IoError> for Error {
    fn from(i: IoError) -> Error {
        Error::Hyper(HyperError::Io(i))
    }
}

#[derive(Debug)]
pub struct Response {
    pub hyper_response: HyperResponse,
    pub body: String,
}

impl Response {
    fn from_hyper_response(mut hyper_response: HyperResponse) -> Result<Response, IoError> {
        let mut body = String::new();
        hyper_response.read_to_string(&mut body).map(|_| {
            Response {
                hyper_response: hyper_response,
                body: body,
            }
        })
    }

    /// Deserializes the body of the response from JSON into
    /// a `T`.
    pub fn from_json<T: Deserialize>(&self) -> Result<T, Error> {
        serde_json::from_str(&*self.body).map_err(|e| Error::Json(e))
    }
}

#[derive(Clone)]
pub struct Request<'a> {
    url: Url,
    params: Option<Vec<(&'a str, &'a str)>>,
    body: Option<String>,
    read_timeout: Option<Duration>,
    headers: Option<Headers>,
}

impl<'a> Request<'a> {
    pub fn new(url: Url) -> Request<'a> {
        Request {
            url: url,
            params: None,
            body: None,
            read_timeout: None,
            headers: None,
        }
    }

    /// Sets one parameter. On a GET or DELETE request, this parameter will
    /// be stored in the URL. On a POST or PUT request, it is stored in the
    /// body of the request. Hence, if you call this method on a POST or
    /// PUT request, you cannot also call `body`.
    pub fn param(&mut self, key: &'a str, value: &'a str) -> &mut Request<'a> {
        if let Some(ref mut p) = self.params {
            p.push((key, value));
        } else {
            let mut v = Vec::new();
            v.push((key, value));
            self.params = Some(v);
        }
        self
    }

    /// Sets many parameters. On a GET or DELETE request, these parameters will
    /// be stored in the URL. On a POST or PUT request, they are stored in the
    /// body of the request. Hence, if you call this method on a POST or
    /// PUT request, you cannot also call `body`.
    pub fn params<T>(&mut self, values: T) -> &mut Request<'a>
        where T: IntoIterator<Item = (&'a str, &'a str)>
    {
        if let Some(ref mut p) = self.params {
            for value in values {
                p.push(value);
            }
        } else {
            let mut v = Vec::new();
            for value in values {
                v.push(value);
            }
            self.params = Some(v);
        }
        self
    }

    /// Writes a `String` to the body of the request. Don't call this
    /// method if you also call `param` on a PUT or POST request.
    pub fn body(&mut self, body: String) -> &mut Request<'a> {
        self.body = Some(body);
        self
    }

    /// Sets a header for the request.
    pub fn header<H: Header + HeaderFormat>(&mut self, header: H) -> &mut Request<'a> {
        if let Some(ref mut h) = self.headers {
            h.set(header);
        } else {
            let mut v = Headers::new();
            v.set(header);
            self.headers = Some(v);
        }
        self
    }

    /// Sets a read timeout for the response.
    pub fn read_timeout(&mut self, timeout: Duration) -> &mut Request<'a> {
        self.read_timeout = Some(timeout);
        self
    }

    fn send_request(&mut self, mut req: HyperRequest<Fresh>) -> Result<Response, Error> {
        if let Some(headers) = self.headers.as_ref() {
            req.headers_mut().extend(headers.iter());
        }

        let _ = req.set_read_timeout(self.read_timeout);

        let mut req = try!(req.start());

        if let Some(body) = self.body.as_ref() {
            try!(req.write_all(body.as_bytes()));
        }

        let resp = try!(req.send());
        let resp = try!(Response::from_hyper_response(resp));

        if resp.hyper_response.status.is_success() {
            Ok(resp)
        } else {
            Err(Error::UnsuccessfulResponse(resp))
        }
    }

    /// Sends a GET request and returns either an error
    /// or a `String` of the response.
    pub fn get(&mut self) -> Result<Response, Error> {
        let mut url = self.url.clone();

        if let Some(ref params) = self.params {
            url.query_pairs_mut().extend_pairs(params.into_iter().map(|&x| x));
        }

        let req = try!(HyperRequest::new(Method::Get, url));
        self.send_request(req)
    }

    /// Sends a DELETE request and returns either an error
    /// or a `String` of the response.
    pub fn delete(&mut self) -> Result<Response, Error> {
        let mut url = self.url.clone();

        if let Some(ref params) = self.params {
            url.query_pairs_mut().extend_pairs(params.into_iter().map(|&x| x));
        }

        let req = try!(HyperRequest::new(Method::Delete, url));
        self.send_request(req)
    }

    /// Sends a POST request and returns either an error
    /// or a `String` of the response.
    pub fn post(&mut self) -> Result<Response, Error> {
        let url = self.url.clone();

        if let Some(ref params) = self.params {
            let mut serializer = url::form_urlencoded::Serializer::new(String::new());
            serializer.extend_pairs(params);
            self.body = Some(serializer.finish());
        }

        let req = try!(HyperRequest::new(Method::Post, url));
        self.send_request(req)
    }

    /// Sends a PUT request and returns either an error
    /// or a `String` of the response.
    pub fn put(&mut self) -> Result<Response, Error> {
        let url = self.url.clone();

        if let Some(ref params) = self.params {
            let mut serializer = url::form_urlencoded::Serializer::new(String::new());
            serializer.extend_pairs(params);
            self.body = Some(serializer.finish());
        }

        let req = try!(HyperRequest::new(Method::Put, url));
        self.send_request(req)
    }
}
<|endoftext|>


<commit_before>//! Cripes: Grammar Manipulation Toolkit
// Copyright (C) 2015-2016 Collin J. Sutton
#![crate_type = "rlib"]
#![crate_name = "cripes"]
#![warn(missing_docs)]

// These features (`alloc`, `heap_api`, `unsize`, `coerce_unsized`, and
// `core_intrinsics`) are used in the implementation of
// `util::flex_box::FlexBox`, a reusable `Box`-like container.
#![feature(alloc)]
#![feature(heap_api)]
#![feature(unsize)]
#![feature(coerce_unsized)]
#![feature(core_intrinsics)]

// `range_contains`, `inclusive_range`, and `inclusive_range_syntax` are
// required in the `pattern` module, where we use them for checking whether
// particular atoms are members of a range in an atom class.
#![feature(range_contains)]
#![feature(inclusive_range_syntax)]
#![cfg_attr(feature = "pattern_class", feature(inclusive_range))]

// `conservative_impl_trait` is used to provide iterators from various types
// without resorting to unwieldy workarounds or viral proliferation of
// lifetime parameters.
#![feature(conservative_impl_trait)]

// `stmt_expr_attributes` is used to enable debug output crate-wide using crate
// feature "debug".
#![feature(stmt_expr_attributes)]

// `TryFrom` is used when converting `regex_syntax::Expr`s to structural
// patterns, because there are some features of regex_syntax that we simply
// don't support.
#![cfg_attr(feature = "regex", feature(try_from))]

#[macro_use] extern crate cripes_macros;

extern crate num_traits;
extern crate bit_set;
extern crate smallvec;
extern crate arrayvec;
extern crate itertools;

#[cfg(feature="regex")]
extern crate regex_syntax;

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate error_chain;

pub mod util;
pub mod symbol;
pub mod pattern;
pub mod automaton;
//pub mod grammar;
<commit_msg>lib.rs: add missing #![feature(unicode)]<commit_after>//! Cripes: Grammar Manipulation Toolkit
// Copyright (C) 2015-2016 Collin J. Sutton
#![crate_type = "rlib"]
#![crate_name = "cripes"]
#![warn(missing_docs)]

// `unicode` is used for encoding `char`s to UTF-8 in `pattern/codegen.rs`.
#![feature(unicode)]

// These features (`alloc`, `heap_api`, `unsize`, `coerce_unsized`, and
// `core_intrinsics`) are used in the implementation of
// `util::flex_box::FlexBox`, a reusable `Box`-like container.
#![feature(alloc)]
#![feature(heap_api)]
#![feature(unsize)]
#![feature(coerce_unsized)]
#![feature(core_intrinsics)]

// `range_contains`, `inclusive_range`, and `inclusive_range_syntax` are
// required in the `pattern` module, where we use them for checking whether
// particular atoms are members of a range in an atom class.
#![feature(range_contains)]
#![feature(inclusive_range_syntax)]
#![cfg_attr(feature = "pattern_class", feature(inclusive_range))]

// `conservative_impl_trait` is used to provide iterators from various types
// without resorting to unwieldy workarounds or viral proliferation of
// lifetime parameters.
#![feature(conservative_impl_trait)]

// `stmt_expr_attributes` is used to enable debug output crate-wide using crate
// feature "debug".
#![feature(stmt_expr_attributes)]

// `TryFrom` is used when converting `regex_syntax::Expr`s to structural
// patterns, because there are some features of regex_syntax that we simply
// don't support.
#![cfg_attr(feature = "regex", feature(try_from))]

#[macro_use] extern crate cripes_macros;

extern crate num_traits;
extern crate bit_set;
extern crate smallvec;
extern crate arrayvec;
extern crate itertools;

#[cfg(feature="regex")]
extern crate regex_syntax;

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate error_chain;

pub mod util;
pub mod symbol;
pub mod pattern;
pub mod automaton;
//pub mod grammar;
<|endoftext|>


<commit_before>//! Compile time optimized maps
#![crate_id="github.com/sfackler/rust-phf/phf"]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/rust-phf/doc")]
#![crate_type="rlib"]
#![crate_type="dylib"]
#![warn(missing_doc)]

use std::fmt;
use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::slice;

/// An immutable map constructed at compile time.
///
/// `PhfMap`s may be created with the `phf_map` macro:
///
/// ```rust
/// # #[feature(phase)];
/// extern crate phf;
/// #[phase(syntax)]
/// extern crate phf_mac;
///
/// use phf::PhfMap;
///
/// static my_map: PhfMap<int> = phf_map!(
///    "hello" => 10,
///    "world" => 11,
/// );
///
/// # fn main() {}
/// ```
///
/// # Note
///
/// The fields of this struct are public so that they may be initialized by the
/// `phf_map` macro. They are subject to change at any time and should never
/// be accessed directly.
pub struct PhfMap<T> {
    #[doc(hidden)]
    k1: u64,
    #[doc(hidden)]
    k2: u64,
    #[doc(hidden)]
    disps: &'static [(uint, uint)],
    #[doc(hidden)]
    entries: &'static [(&'static str, T)],
}

static LOG_MAX_SIZE: uint = 21;

#[doc(hidden)]
pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE;

#[doc(hidden)]
#[inline]
pub fn hash(s: &str, k1: u64, k2: u64) -> (uint, uint, uint) {
    let hash = SipHasher::new_with_keys(k1, k2).hash(&s);
    let mask = (MAX_SIZE - 1) as u64;

    ((hash & mask) as uint,
     ((hash >> LOG_MAX_SIZE) & mask) as uint,
     ((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint)
}

#[doc(hidden)]
#[inline]
pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint {
    d2 + f1 * d1 + f2
}

impl<T> Container for PhfMap<T> {
    fn len(&self) -> uint {
        self.entries.len()
    }
}

impl<'a, T> Map<&'a str, T> for PhfMap<T> {
    fn find<'a>(&'a self, key: & &str) -> Option<&'a T> {
        let (g, f1, f2) = hash(*key, self.k1, self.k2);
        let (d1, d2) = self.disps[g % self.disps.len()];
        let (s, ref value) = self.entries[displace(f1, f2, d1, d2) %
                                          self.entries.len()];
        if s == *key {
            Some(value)
        } else {
            None
        }
    }
}

impl<T: fmt::Show> fmt::Show for PhfMap<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.buf.write_char('{'));
        let mut first = true;
        for (k, v) in self.entries() {
            if !first {
                try!(fmt.buf.write_str(", "));
            }
            try!(write!(fmt.buf, "{}: {}", k, v))
            first = false;
        }
        fmt.buf.write_char('}')
    }
}

impl<T> PhfMap<T> {
    /// Returns an iterator over the key/value pairs in the map.
    ///
    /// Entries are retuned in an arbitrary order.
    pub fn entries<'a>(&'a self) -> PhfMapEntries<'a, T> {
        PhfMapEntries { iter: self.entries.iter() }
    }

    /// Returns an iterator over the keys in the map.
    ///
    /// Keys are returned in an arbitrary order.
    pub fn keys<'a>(&'a self) -> PhfMapKeys<'a, T> {
        PhfMapKeys { iter: self.entries() }
    }

    /// Returns an iterator over the values in the map.
    ///
    /// Values are returned in an arbitrary order.
    pub fn values<'a>(&'a self) -> PhfMapValues<'a, T> {
        PhfMapValues { iter: self.entries() }
    }
}

/// An iterator over the key/value pairs in a `PhfMap`.
pub struct PhfMapEntries<'a, T> {
    priv iter: slice::Items<'a, (&'static str, T)>,
}

impl<'a, T> Iterator<(&'static str, &'a T)> for PhfMapEntries<'a, T> {
    fn next(&mut self) -> Option<(&'static str, &'a T)> {
        self.iter.next().map(|&(key, ref value)| (key, value))
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the keys in a `PhfMap`.
pub struct PhfMapKeys<'a, T> {
    priv iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'static str> for PhfMapKeys<'a, T> {
    fn next(&mut self) -> Option<&'static str> {
        self.iter.next().map(|(key, _)| key)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the values in a `PhfMap`.
pub struct PhfMapValues<'a, T> {
    priv iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'a T> for PhfMapValues<'a, T> {
    fn next(&mut self) -> Option<&'a T> {
        self.iter.next().map(|(_, value)| value)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}
<commit_msg>Update for visibility overhaul<commit_after>//! Compile time optimized maps
#![crate_id="github.com/sfackler/rust-phf/phf"]
#![doc(html_root_url="http://www.rust-ci.org/sfackler/rust-phf/doc")]
#![crate_type="rlib"]
#![crate_type="dylib"]
#![warn(missing_doc)]

use std::fmt;
use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::slice;

/// An immutable map constructed at compile time.
///
/// `PhfMap`s may be created with the `phf_map` macro:
///
/// ```rust
/// # #[feature(phase)];
/// extern crate phf;
/// #[phase(syntax)]
/// extern crate phf_mac;
///
/// use phf::PhfMap;
///
/// static my_map: PhfMap<int> = phf_map!(
///    "hello" => 10,
///    "world" => 11,
/// );
///
/// # fn main() {}
/// ```
///
/// # Note
///
/// The fields of this struct are public so that they may be initialized by the
/// `phf_map` macro. They are subject to change at any time and should never
/// be accessed directly.
pub struct PhfMap<T> {
    #[doc(hidden)]
    pub k1: u64,
    #[doc(hidden)]
    pub k2: u64,
    #[doc(hidden)]
    pub disps: &'static [(uint, uint)],
    #[doc(hidden)]
    pub entries: &'static [(&'static str, T)],
}

static LOG_MAX_SIZE: uint = 21;

#[doc(hidden)]
pub static MAX_SIZE: uint = 1 << LOG_MAX_SIZE;

#[doc(hidden)]
#[inline]
pub fn hash(s: &str, k1: u64, k2: u64) -> (uint, uint, uint) {
    let hash = SipHasher::new_with_keys(k1, k2).hash(&s);
    let mask = (MAX_SIZE - 1) as u64;

    ((hash & mask) as uint,
     ((hash >> LOG_MAX_SIZE) & mask) as uint,
     ((hash >> (2 * LOG_MAX_SIZE)) & mask) as uint)
}

#[doc(hidden)]
#[inline]
pub fn displace(f1: uint, f2: uint, d1: uint, d2: uint) -> uint {
    d2 + f1 * d1 + f2
}

impl<T> Container for PhfMap<T> {
    fn len(&self) -> uint {
        self.entries.len()
    }
}

impl<'a, T> Map<&'a str, T> for PhfMap<T> {
    fn find<'a>(&'a self, key: & &str) -> Option<&'a T> {
        let (g, f1, f2) = hash(*key, self.k1, self.k2);
        let (d1, d2) = self.disps[g % self.disps.len()];
        let (s, ref value) = self.entries[displace(f1, f2, d1, d2) %
                                          self.entries.len()];
        if s == *key {
            Some(value)
        } else {
            None
        }
    }
}

impl<T: fmt::Show> fmt::Show for PhfMap<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(fmt.buf.write_char('{'));
        let mut first = true;
        for (k, v) in self.entries() {
            if !first {
                try!(fmt.buf.write_str(", "));
            }
            try!(write!(fmt.buf, "{}: {}", k, v))
            first = false;
        }
        fmt.buf.write_char('}')
    }
}

impl<T> PhfMap<T> {
    /// Returns an iterator over the key/value pairs in the map.
    ///
    /// Entries are retuned in an arbitrary order.
    pub fn entries<'a>(&'a self) -> PhfMapEntries<'a, T> {
        PhfMapEntries { iter: self.entries.iter() }
    }

    /// Returns an iterator over the keys in the map.
    ///
    /// Keys are returned in an arbitrary order.
    pub fn keys<'a>(&'a self) -> PhfMapKeys<'a, T> {
        PhfMapKeys { iter: self.entries() }
    }

    /// Returns an iterator over the values in the map.
    ///
    /// Values are returned in an arbitrary order.
    pub fn values<'a>(&'a self) -> PhfMapValues<'a, T> {
        PhfMapValues { iter: self.entries() }
    }
}

/// An iterator over the key/value pairs in a `PhfMap`.
pub struct PhfMapEntries<'a, T> {
    iter: slice::Items<'a, (&'static str, T)>,
}

impl<'a, T> Iterator<(&'static str, &'a T)> for PhfMapEntries<'a, T> {
    fn next(&mut self) -> Option<(&'static str, &'a T)> {
        self.iter.next().map(|&(key, ref value)| (key, value))
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the keys in a `PhfMap`.
pub struct PhfMapKeys<'a, T> {
    iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'static str> for PhfMapKeys<'a, T> {
    fn next(&mut self) -> Option<&'static str> {
        self.iter.next().map(|(key, _)| key)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

/// An iterator over the values in a `PhfMap`.
pub struct PhfMapValues<'a, T> {
    iter: PhfMapEntries<'a, T>,
}

impl<'a, T> Iterator<&'a T> for PhfMapValues<'a, T> {
    fn next(&mut self) -> Option<&'a T> {
        self.iter.next().map(|(_, value)| value)
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}
<|endoftext|>


<commit_before>//! Implementation of the `Synth` struct for basic polyphonic, multi-oscillator envelope synthesis.

extern crate envelope as envelope_lib;
extern crate gaussian;
pub extern crate instrument;
extern crate panning;
extern crate pitch_calc as pitch;
extern crate time_calc as time;
extern crate rand;
extern crate rustc_serialize;
extern crate sample;
extern crate utils;

pub use dynamic::Synth as Dynamic;
pub use envelope::{Envelope, Point};
pub use envelope::Trait as EnvelopeTrait;
pub use oscillator::{AmpEnvelope, FreqEnvelope, Oscillator, Waveform};
pub use synth::Synth;

pub mod dynamic;
pub mod envelope;
pub mod oscillator;
mod synth;

#[cfg(feature="dsp-chain")]
mod dsp_node;

#[cfg(feature="serde_serialization")]
mod serde;
<commit_msg>Remove now unused rustc_serialize crate.<commit_after>//! Implementation of the `Synth` struct for basic polyphonic, multi-oscillator envelope synthesis.

extern crate envelope as envelope_lib;
extern crate gaussian;
pub extern crate instrument;
extern crate panning;
extern crate pitch_calc as pitch;
extern crate time_calc as time;
extern crate rand;
extern crate sample;
extern crate utils;

pub use dynamic::Synth as Dynamic;
pub use envelope::{Envelope, Point};
pub use envelope::Trait as EnvelopeTrait;
pub use oscillator::{AmpEnvelope, FreqEnvelope, Oscillator, Waveform};
pub use synth::Synth;

pub mod dynamic;
pub mod envelope;
pub mod oscillator;
mod synth;

#[cfg(feature="dsp-chain")]
mod dsp_node;

#[cfg(feature="serde_serialization")]
mod serde;
<|endoftext|>