<commit_before>use std;
use std::slice::bytes;

pub use caveat::{Caveat, Predicate};

use serialize::base64::{self, FromBase64, ToBase64};

pub use sodiumoxide::crypto::auth::hmacsha256::{Key, Tag, TAGBYTES};
use sodiumoxide::crypto::auth::hmacsha256::authenticate;

// Macaroons personalize the HMAC key using the string
// "macaroons-key-generator" padded to 32-bytes with zeroes
const KEY_GENERATOR: &'static [u8; 32] = b"macaroons-key-generator\0\0\0\0\0\0\0\0\0";

const PACKET_PREFIX_LENGTH: usize = 4;
const MAX_PACKET_LENGTH:    usize = 65535;

pub struct Token {
  pub location:   Vec<u8>,
  pub identifier: Vec<u8>,
  pub caveats:    Vec<Caveat>,
  pub tag:        Tag
}

struct Packet {
  pub id:     Vec<u8>,
  pub value:  Vec<u8>,
  pub length: usize
}

impl Token {
  pub fn new(key: Vec<u8>, identifier: Vec<u8>, location: Vec<u8>) -> Token {
    let Tag(personalized_key) = authenticate(&key, &Key(*KEY_GENERATOR));
    let tag = authenticate(&identifier, &Key(personalized_key));

    Token {
      location:   location,
      identifier: identifier,
      caveats:    Vec::new(),
      tag:        tag
    }
  }

  pub fn deserialize(macaroon: Vec<u8>) -> Result<Token, &'static str> {
    let mut location:   Option<Vec<u8>> = None;
    let mut identifier: Option<Vec<u8>> = None;
    let mut caveats:    Vec<Caveat>     = Vec::new();
    let mut tag:        Option<Tag>     = None;

    let token_data = match macaroon.as_slice().from_base64() {
      Ok(bytes) => bytes,
      _         => return Err("couldn't parse base64")
    };

    let mut index: usize = 0;

    while index < token_data.len() {
      let packet = match Token::depacketize(&token_data, index) {
        Ok(p)       => p,
        Err(reason) => return Err(reason)
      };

      index += packet.length;

      match packet.id.as_slice() {
        b"location"   => location   = Some(packet.value),
        b"identifier" => identifier = Some(packet.value),
        b"cid"        => caveats.push(Caveat::new(Predicate(packet.value))),
        b"signature"  => {
          if packet.value.len() != TAGBYTES {
            return Err("invalid signature length")
          }

          let mut signature_bytes = [0u8; TAGBYTES];
          bytes::copy_memory(&mut signature_bytes, &packet.value[..TAGBYTES]);

          tag = Some(Tag(signature_bytes))
        },
        _ => return Err("unrecognized packet type")
      }
    }

    if location   == None { return Err("no 'location' found"); }
    if identifier == None { return Err("no 'identifier' found"); }
    if tag        == None { return Err("no 'signature' found"); }

    let token = Token {
      location:   location.unwrap(),
      identifier: identifier.unwrap(),
      caveats:    caveats,
      tag:        tag.unwrap()
    };

    Ok(token)
  }

  fn depacketize(data: &Vec<u8>, index: usize) -> Result<Packet, &'static str> {
    // TODO: parse this length without involving any UTF-8 conversions
    let length_str = match std::str::from_utf8(&data[index .. index + PACKET_PREFIX_LENGTH]) {
      Ok(string) => string,
      _          => return Err("couldn't stringify packet length")
    };

    let packet_length: usize = match std::num::from_str_radix(length_str, 16) {
      Ok(length) => length,
      _          => return Err("couldn't parse packet length")
    };

    let mut packet_bytes = data[index + PACKET_PREFIX_LENGTH .. index + packet_length].to_vec();

    let pos = match packet_bytes.iter().position(|&byte| byte == b' ') {
      Some(i) => i,
      None    => return Err("malformed packet")
    };

    let mut value = packet_bytes.split_off(pos);
    value.remove(0);

    match value.pop().unwrap() {
      b'\n' => (),
      _     => return Err("packet not newline terminated")
    }

    Ok(Packet { id: packet_bytes, value: value, length: packet_length })
  }

  pub fn add_caveat(&self, caveat: Caveat) -> Token {
    caveat.append(self)
  }

  pub fn serialize(&self) -> Vec<u8> {
    // TODO: estimate capacity and use Vec::with_capacity
    let mut result: Vec<u8> = Vec::new();

    Token::packetize(&mut result, "location",   &self.location);
    Token::packetize(&mut result, "identifier", &self.identifier);

    for caveat in self.caveats.iter() {
      let Predicate(predicate_bytes) = caveat.predicate.clone();
      Token::packetize(&mut result, "cid", &predicate_bytes);
    }

    let Tag(signature_bytes) = self.tag;
    let mut signature_vec = Vec::new();
    signature_vec.push_all(&signature_bytes);

    Token::packetize(&mut result, "signature", &signature_vec);

    result.to_base64(base64::URL_SAFE).into_bytes()
  }

  fn packetize(result: &mut Vec<u8>, field: &str, value: &Vec<u8>) {
    let field_bytes: Vec<u8> = String::from_str(field).into_bytes();
    let packet_length = PACKET_PREFIX_LENGTH + field_bytes.len() + value.len() + 2;

    if packet_length > MAX_PACKET_LENGTH {
      panic!("packet too large to serialize");
    }

    let mut pkt_line = format!("{:04x}{} ", packet_length, field).into_bytes();
    result.append(&mut pkt_line);
    result.append(&mut value.clone());
    result.push('\n' as u8);
  }
}
<commit_msg>Use bytechar<commit_after>use std;
use std::slice::bytes;

pub use caveat::{Caveat, Predicate};

use serialize::base64::{self, FromBase64, ToBase64};

pub use sodiumoxide::crypto::auth::hmacsha256::{Key, Tag, TAGBYTES};
use sodiumoxide::crypto::auth::hmacsha256::authenticate;

// Macaroons personalize the HMAC key using the string
// "macaroons-key-generator" padded to 32-bytes with zeroes
const KEY_GENERATOR: &'static [u8; 32] = b"macaroons-key-generator\0\0\0\0\0\0\0\0\0";

const PACKET_PREFIX_LENGTH: usize = 4;
const MAX_PACKET_LENGTH:    usize = 65535;

pub struct Token {
  pub location:   Vec<u8>,
  pub identifier: Vec<u8>,
  pub caveats:    Vec<Caveat>,
  pub tag:        Tag
}

struct Packet {
  pub id:     Vec<u8>,
  pub value:  Vec<u8>,
  pub length: usize
}

impl Token {
  pub fn new(key: Vec<u8>, identifier: Vec<u8>, location: Vec<u8>) -> Token {
    let Tag(personalized_key) = authenticate(&key, &Key(*KEY_GENERATOR));
    let tag = authenticate(&identifier, &Key(personalized_key));

    Token {
      location:   location,
      identifier: identifier,
      caveats:    Vec::new(),
      tag:        tag
    }
  }

  pub fn deserialize(macaroon: Vec<u8>) -> Result<Token, &'static str> {
    let mut location:   Option<Vec<u8>> = None;
    let mut identifier: Option<Vec<u8>> = None;
    let mut caveats:    Vec<Caveat>     = Vec::new();
    let mut tag:        Option<Tag>     = None;

    let token_data = match macaroon.as_slice().from_base64() {
      Ok(bytes) => bytes,
      _         => return Err("couldn't parse base64")
    };

    let mut index: usize = 0;

    while index < token_data.len() {
      let packet = match Token::depacketize(&token_data, index) {
        Ok(p)       => p,
        Err(reason) => return Err(reason)
      };

      index += packet.length;

      match packet.id.as_slice() {
        b"location"   => location   = Some(packet.value),
        b"identifier" => identifier = Some(packet.value),
        b"cid"        => caveats.push(Caveat::new(Predicate(packet.value))),
        b"signature"  => {
          if packet.value.len() != TAGBYTES {
            return Err("invalid signature length")
          }

          let mut signature_bytes = [0u8; TAGBYTES];
          bytes::copy_memory(&mut signature_bytes, &packet.value[..TAGBYTES]);

          tag = Some(Tag(signature_bytes))
        },
        _ => return Err("unrecognized packet type")
      }
    }

    if location   == None { return Err("no 'location' found"); }
    if identifier == None { return Err("no 'identifier' found"); }
    if tag        == None { return Err("no 'signature' found"); }

    let token = Token {
      location:   location.unwrap(),
      identifier: identifier.unwrap(),
      caveats:    caveats,
      tag:        tag.unwrap()
    };

    Ok(token)
  }

  fn depacketize(data: &Vec<u8>, index: usize) -> Result<Packet, &'static str> {
    // TODO: parse this length without involving any UTF-8 conversions
    let length_str = match std::str::from_utf8(&data[index .. index + PACKET_PREFIX_LENGTH]) {
      Ok(string) => string,
      _          => return Err("couldn't stringify packet length")
    };

    let packet_length: usize = match std::num::from_str_radix(length_str, 16) {
      Ok(length) => length,
      _          => return Err("couldn't parse packet length")
    };

    let mut packet_bytes = data[index + PACKET_PREFIX_LENGTH .. index + packet_length].to_vec();

    let pos = match packet_bytes.iter().position(|&byte| byte == b' ') {
      Some(i) => i,
      None    => return Err("malformed packet")
    };

    let mut value = packet_bytes.split_off(pos);
    value.remove(0);

    match value.pop().unwrap() {
      b'\n' => (),
      _     => return Err("packet not newline terminated")
    }

    Ok(Packet { id: packet_bytes, value: value, length: packet_length })
  }

  pub fn add_caveat(&self, caveat: Caveat) -> Token {
    caveat.append(self)
  }

  pub fn serialize(&self) -> Vec<u8> {
    // TODO: estimate capacity and use Vec::with_capacity
    let mut result: Vec<u8> = Vec::new();

    Token::packetize(&mut result, "location",   &self.location);
    Token::packetize(&mut result, "identifier", &self.identifier);

    for caveat in self.caveats.iter() {
      let Predicate(predicate_bytes) = caveat.predicate.clone();
      Token::packetize(&mut result, "cid", &predicate_bytes);
    }

    let Tag(signature_bytes) = self.tag;
    let mut signature_vec = Vec::new();
    signature_vec.push_all(&signature_bytes);

    Token::packetize(&mut result, "signature", &signature_vec);

    result.to_base64(base64::URL_SAFE).into_bytes()
  }

  fn packetize(result: &mut Vec<u8>, field: &str, value: &Vec<u8>) {
    let field_bytes: Vec<u8> = String::from_str(field).into_bytes();
    let packet_length = PACKET_PREFIX_LENGTH + field_bytes.len() + value.len() + 2;

    if packet_length > MAX_PACKET_LENGTH {
      panic!("packet too large to serialize");
    }

    let mut pkt_line = format!("{:04x}{} ", packet_length, field).into_bytes();
    result.append(&mut pkt_line);
    result.append(&mut value.clone());
    result.push(b'\n');
  }
}
<|endoftext|>


<commit_before>extern crate base64;

use self::base64::encode;
use http::retrieve_asset;
use regex::Regex;
use url::{ParseError, Url};
use std::{
    io::{stderr, Write},
    collections::HashMap,
};

lazy_static! {
    static ref HAS_PROTOCOL: Regex = Regex::new(r"^[a-z0-9]+:").unwrap();
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
    static ref EMPTY_STRING: String = String::new();
}

const MAGIC: [[&[u8]; 2]; 19] = [
    // Image
    [b"GIF87a", b"image/gif"],
    [b"GIF89a", b"image/gif"],
    [b"\xFF\xD8\xFF", b"image/jpeg"],
    [b"\x89PNG\x0D\x0A\x1A\x0A", b"image/png"],
    [b"<?xml ", b"image/svg+xml"],
    [b"<svg ", b"image/svg+xml"],
    [b"RIFF....WEBPVP8 ", b"image/webp"],
    [b"\x00\x00\x01\x00", b"image/x-icon"],
    // Audio
    [b"ID3", b"audio/mpeg"],
    [b"\xFF\x0E", b"audio/mpeg"],
    [b"\xFF\x0F", b"audio/mpeg"],
    [b"OggS", b"audio/ogg"],
    [b"RIFF....WAVEfmt ", b"audio/wav"],
    [b"fLaC", b"audio/x-flac"],
    // Video
    [b"RIFF....AVI LIST", b"video/avi"],
    [b"....ftyp", b"video/mp4"],
    [b"\x00\x00\x01\x0B", b"video/mpeg"],
    [b"....moov", b"video/quicktime"],
    [b"\x1A\x45\xDF\xA3", b"video/webm"],
];

pub fn data_to_dataurl(mime: &str, data: &[u8]) -> String {
    let mimetype = if mime.is_empty() {
        detect_mimetype(data)
    } else {
        mime.to_string()
    };
    format!("data:{};base64,{}", mimetype, encode(data))
}

pub fn detect_mimetype(data: &[u8]) -> String {
    for item in MAGIC.iter() {
        if data.starts_with(item[0]) {
            return String::from_utf8(item[1].to_vec()).unwrap();
        }
    }
    "".to_owned()
}

pub fn url_has_protocol<T: AsRef<str>>(url: T) -> bool {
    HAS_PROTOCOL.is_match(url.as_ref().to_lowercase().as_str())
}

pub fn is_data_url<T: AsRef<str>>(url: T) -> Result<bool, ParseError> {
    Url::parse(url.as_ref()).and_then(|u| Ok(u.scheme() == "data"))
}

pub fn is_valid_url<T: AsRef<str>>(path: T) -> bool {
    REGEX_URL.is_match(path.as_ref())
}

pub fn resolve_url<T: AsRef<str>, U: AsRef<str>>(from: T, to: U) -> Result<String, ParseError> {
    let result = if is_valid_url(to.as_ref()) {
        to.as_ref().to_string()
    } else {
        Url::parse(from.as_ref())?
            .join(to.as_ref())?
            .as_ref()
            .to_string()
    };
    Ok(result)
}

pub fn resolve_css_imports(
    cache: &mut HashMap<String, String>,
    css_string: &str,
    as_dataurl: bool,
    href: &str,
    opt_user_agent: &str,
    opt_silent: bool,
    opt_insecure: bool,
) -> String {
    let mut resolved_css = String::from(css_string);
    let re = Regex::new(r###"(?P<import>@import )?url\((?P<to_repl>"?(?P<url>[^"]+)"?)\)"###).unwrap();

    for link in re.captures_iter(&css_string) {
        let target_link = link.name("url").unwrap().as_str();

        // Generate absolute URL for content
        let embedded_url = match resolve_url(href, target_link) {
            Ok(url) => url,
            Err(_) => continue, // Malformed URL
        };

        // Download the asset.  If it's more CSS, resolve that too
        let content = match link.name("import") {

            // The link is an @import link
            Some(_) => retrieve_asset(
                        cache,
                        &embedded_url,
                        false,      // Formating as data URL will be done later
                        "text/css", // Expect CSS
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    )
                    .map(|(content, _)| resolve_css_imports(
                        cache,
                        &content,
                        true, //NOW, convert to data URL
                        &embedded_url,
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    )),

            // The link is some other, non-@import link
            None => retrieve_asset(
                        cache,
                        &embedded_url,
                        true, // Format as data URL
                        "",   // Unknown MIME type
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    ).map(|(a, _)| a),

        }.unwrap_or_else(|e| {
            writeln!(
                stderr(),
                "Warning: {}",
                e,
            ).unwrap();

            //If failed to resolve, replace with absolute URL
            embedded_url
        });

        let replacement = format!("\"{}\"", &content);

        let t = resolved_css
            .replace(link.name("to_repl").unwrap().as_str(), &replacement)
            .to_string();
        resolved_css = t.clone();
    }

    if as_dataurl {
        data_to_dataurl("text/css", resolved_css.as_bytes())
    } else {
        resolved_css
    }
}
<commit_msg>EMPTY_STRING no longer used<commit_after>extern crate base64;

use self::base64::encode;
use http::retrieve_asset;
use regex::Regex;
use url::{ParseError, Url};
use std::{
    io::{stderr, Write},
    collections::HashMap,
};

lazy_static! {
    static ref HAS_PROTOCOL: Regex = Regex::new(r"^[a-z0-9]+:").unwrap();
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
}

const MAGIC: [[&[u8]; 2]; 19] = [
    // Image
    [b"GIF87a", b"image/gif"],
    [b"GIF89a", b"image/gif"],
    [b"\xFF\xD8\xFF", b"image/jpeg"],
    [b"\x89PNG\x0D\x0A\x1A\x0A", b"image/png"],
    [b"<?xml ", b"image/svg+xml"],
    [b"<svg ", b"image/svg+xml"],
    [b"RIFF....WEBPVP8 ", b"image/webp"],
    [b"\x00\x00\x01\x00", b"image/x-icon"],
    // Audio
    [b"ID3", b"audio/mpeg"],
    [b"\xFF\x0E", b"audio/mpeg"],
    [b"\xFF\x0F", b"audio/mpeg"],
    [b"OggS", b"audio/ogg"],
    [b"RIFF....WAVEfmt ", b"audio/wav"],
    [b"fLaC", b"audio/x-flac"],
    // Video
    [b"RIFF....AVI LIST", b"video/avi"],
    [b"....ftyp", b"video/mp4"],
    [b"\x00\x00\x01\x0B", b"video/mpeg"],
    [b"....moov", b"video/quicktime"],
    [b"\x1A\x45\xDF\xA3", b"video/webm"],
];

pub fn data_to_dataurl(mime: &str, data: &[u8]) -> String {
    let mimetype = if mime.is_empty() {
        detect_mimetype(data)
    } else {
        mime.to_string()
    };
    format!("data:{};base64,{}", mimetype, encode(data))
}

pub fn detect_mimetype(data: &[u8]) -> String {
    for item in MAGIC.iter() {
        if data.starts_with(item[0]) {
            return String::from_utf8(item[1].to_vec()).unwrap();
        }
    }
    "".to_owned()
}

pub fn url_has_protocol<T: AsRef<str>>(url: T) -> bool {
    HAS_PROTOCOL.is_match(url.as_ref().to_lowercase().as_str())
}

pub fn is_data_url<T: AsRef<str>>(url: T) -> Result<bool, ParseError> {
    Url::parse(url.as_ref()).and_then(|u| Ok(u.scheme() == "data"))
}

pub fn is_valid_url<T: AsRef<str>>(path: T) -> bool {
    REGEX_URL.is_match(path.as_ref())
}

pub fn resolve_url<T: AsRef<str>, U: AsRef<str>>(from: T, to: U) -> Result<String, ParseError> {
    let result = if is_valid_url(to.as_ref()) {
        to.as_ref().to_string()
    } else {
        Url::parse(from.as_ref())?
            .join(to.as_ref())?
            .as_ref()
            .to_string()
    };
    Ok(result)
}

pub fn resolve_css_imports(
    cache: &mut HashMap<String, String>,
    css_string: &str,
    as_dataurl: bool,
    href: &str,
    opt_user_agent: &str,
    opt_silent: bool,
    opt_insecure: bool,
) -> String {
    let mut resolved_css = String::from(css_string);
    let re = Regex::new(r###"(?P<import>@import )?url\((?P<to_repl>"?(?P<url>[^"]+)"?)\)"###).unwrap();

    for link in re.captures_iter(&css_string) {
        let target_link = link.name("url").unwrap().as_str();

        // Generate absolute URL for content
        let embedded_url = match resolve_url(href, target_link) {
            Ok(url) => url,
            Err(_) => continue, // Malformed URL
        };

        // Download the asset.  If it's more CSS, resolve that too
        let content = match link.name("import") {

            // The link is an @import link
            Some(_) => retrieve_asset(
                        cache,
                        &embedded_url,
                        false,      // Formating as data URL will be done later
                        "text/css", // Expect CSS
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    )
                    .map(|(content, _)| resolve_css_imports(
                        cache,
                        &content,
                        true, //NOW, convert to data URL
                        &embedded_url,
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    )),

            // The link is some other, non-@import link
            None => retrieve_asset(
                        cache,
                        &embedded_url,
                        true, // Format as data URL
                        "",   // Unknown MIME type
                        opt_user_agent,
                        opt_silent,
                        opt_insecure,
                    ).map(|(a, _)| a),

        }.unwrap_or_else(|e| {
            writeln!(
                stderr(),
                "Warning: {}",
                e,
            ).unwrap();

            //If failed to resolve, replace with absolute URL
            embedded_url
        });

        let replacement = format!("\"{}\"", &content);

        let t = resolved_css
            .replace(link.name("to_repl").unwrap().as_str(), &replacement)
            .to_string();
        resolved_css = t.clone();
    }

    if as_dataurl {
        data_to_dataurl("text/css", resolved_css.as_bytes())
    } else {
        resolved_css
    }
}
<|endoftext|>


<commit_before>extern crate blas;
use self::blas::ddot;
use std::cmp::min;

use std::f64;

pub fn dot(x: &[f64], y: &[f64]) -> f64 {
    let n: i32 = min(x.len() as i32, y.len() as i32);

    unsafe { ddot(n, x, 1, y, 1) }
}

pub fn argmaxima(vals: &[f64]) -> (f64, Vec<usize>) {
    let mut max = f64::MIN;
    let mut ixs = vec![];

    for (i, &v) in vals.iter().enumerate() {
        if (v - max).abs() < 1e-7 {
            ixs.push(i);
        } else if v > max {
            max = v;
            ixs.clear();
            ixs.push(i);
        }
    }

    (max, ixs)
}

// TODO: Pass by iterator so that we don't have to collect before passing.
pub fn sub2ind(dims: &[usize], inds: &[usize]) -> usize {
    let d_it = dims.iter().rev().skip(1);
    let i_it = inds.iter().rev().skip(1);

    d_it.zip(i_it).fold(inds.last().cloned().unwrap(), |acc, (d, i)| i + d * acc)
}

pub fn cartesian_product<T: Clone>(lists: &Vec<Vec<T>>) -> Vec<Vec<T>> {
    fn partial_cartesian<T: Clone>(u: Vec<Vec<T>>, v: &Vec<T>) -> Vec<Vec<T>> {
        u.into_iter()
            .flat_map(|xs| {
                v.iter()
                    .cloned()
                    .map(|y| {
                        let mut vec = xs.clone();
                        vec.push(y);
                        vec
                    })
                    .collect::<Vec<_>>()
            })
            .collect()
    }

    match lists.split_first() {
        Some((head, tail)) => {
            let init: Vec<Vec<T>> = head.iter().cloned().map(|n| vec![n]).collect();

            tail.iter().cloned().fold(init, |vec, list| partial_cartesian(vec, &list))
        }
        None => vec![],
    }
}

#[cfg(test)]
mod tests {
    use super::{sub2ind, cartesian_product};

    #[test]
    fn test_sub2ind() {
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![3, 0, 0]), 3);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 0, 5]), 177);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 5, 5]), 202);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![0, 0, 11]), 385);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![5, 0, 11]), 390);
    }

    #[test]
    #[should_panic]
    fn test_sub2ind_empty() {
        sub2ind(&vec![], &vec![]);
    }

    #[test]
    fn test_cartesian_product() {
        let to_combine = vec![vec![0.0, 1.0, 2.0], vec![7.0, 8.0, 9.0]];

        let combs = cartesian_product(&to_combine);

        assert_eq!(combs[0], vec![0.0, 7.0]);
        assert_eq!(combs[1], vec![0.0, 8.0]);
        assert_eq!(combs[2], vec![0.0, 9.0]);

        assert_eq!(combs[3], vec![1.0, 7.0]);
        assert_eq!(combs[4], vec![1.0, 8.0]);
        assert_eq!(combs[5], vec![1.0, 9.0]);

        assert_eq!(combs[6], vec![2.0, 7.0]);
        assert_eq!(combs[7], vec![2.0, 8.0]);
        assert_eq!(combs[8], vec![2.0, 9.0]);
    }
}
<commit_msg>Add openblas_src crate in src/utils.rs<commit_after>extern crate blas;
extern crate openblas_src;

use self::blas::ddot;
use std::cmp::min;

use std::f64;

pub fn dot(x: &[f64], y: &[f64]) -> f64 {
    let n: i32 = min(x.len() as i32, y.len() as i32);

    unsafe { ddot(n, x, 1, y, 1) }
}

pub fn argmaxima(vals: &[f64]) -> (f64, Vec<usize>) {
    let mut max = f64::MIN;
    let mut ixs = vec![];

    for (i, &v) in vals.iter().enumerate() {
        if (v - max).abs() < 1e-7 {
            ixs.push(i);
        } else if v > max {
            max = v;
            ixs.clear();
            ixs.push(i);
        }
    }

    (max, ixs)
}

// TODO: Pass by iterator so that we don't have to collect before passing.
pub fn sub2ind(dims: &[usize], inds: &[usize]) -> usize {
    let d_it = dims.iter().rev().skip(1);
    let i_it = inds.iter().rev().skip(1);

    d_it.zip(i_it).fold(inds.last().cloned().unwrap(), |acc, (d, i)| i + d * acc)
}

pub fn cartesian_product<T: Clone>(lists: &Vec<Vec<T>>) -> Vec<Vec<T>> {
    fn partial_cartesian<T: Clone>(u: Vec<Vec<T>>, v: &Vec<T>) -> Vec<Vec<T>> {
        u.into_iter()
            .flat_map(|xs| {
                v.iter()
                    .cloned()
                    .map(|y| {
                        let mut vec = xs.clone();
                        vec.push(y);
                        vec
                    })
                    .collect::<Vec<_>>()
            })
            .collect()
    }

    match lists.split_first() {
        Some((head, tail)) => {
            let init: Vec<Vec<T>> = head.iter().cloned().map(|n| vec![n]).collect();

            tail.iter().cloned().fold(init, |vec, list| partial_cartesian(vec, &list))
        }
        None => vec![],
    }
}

#[cfg(test)]
mod tests {
    use super::{sub2ind, cartesian_product};

    #[test]
    fn test_sub2ind() {
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![3, 0, 0]), 3);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 0, 5]), 177);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![2, 5, 5]), 202);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![0, 0, 11]), 385);
        assert_eq!(sub2ind(&vec![5, 7, 12], &vec![5, 0, 11]), 390);
    }

    #[test]
    #[should_panic]
    fn test_sub2ind_empty() {
        sub2ind(&vec![], &vec![]);
    }

    #[test]
    fn test_cartesian_product() {
        let to_combine = vec![vec![0.0, 1.0, 2.0], vec![7.0, 8.0, 9.0]];

        let combs = cartesian_product(&to_combine);

        assert_eq!(combs[0], vec![0.0, 7.0]);
        assert_eq!(combs[1], vec![0.0, 8.0]);
        assert_eq!(combs[2], vec![0.0, 9.0]);

        assert_eq!(combs[3], vec![1.0, 7.0]);
        assert_eq!(combs[4], vec![1.0, 8.0]);
        assert_eq!(combs[5], vec![1.0, 9.0]);

        assert_eq!(combs[6], vec![2.0, 7.0]);
        assert_eq!(combs[7], vec![2.0, 8.0]);
        assert_eq!(combs[8], vec![2.0, 9.0]);
    }
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use syntax::ast::*;
use syntax::codemap::{ExpnInfo, Span, ExpnFormat};
use rustc::ast_map::Node::NodeExpr;
use rustc::middle::def_id::DefId;
use rustc::middle::ty;
use std::borrow::Cow;

// module DefPaths for certain structs/enums we check for
pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"];
pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"];
pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"];
pub const VEC_PATH:    [&'static str; 3] = ["collections", "vec", "Vec"];
pub const LL_PATH:     [&'static str; 3] = ["collections", "linked_list", "LinkedList"];

/// returns true if the macro that expanded the crate was outside of
/// the current crate or was a compiler plugin
pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
    // no ExpnInfo = no macro
    opt_info.map_or(false, |info| {
        if info.callee.format == ExpnFormat::CompilerExpansion {
            if info.callee.name == "closure expansion" {
                return false;
            }
        } else if info.callee.format == ExpnFormat::MacroAttribute {
            // these are all plugins
            return true;
        }
        // no span for the callee = external macro
        info.callee.span.map_or(true, |span| {
            // no snippet = external macro or compiler-builtin expansion
            cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code|
                // macro doesn't start with "macro_rules"
                // = compiler plugin
                !code.starts_with("macro_rules")
            )
        })
    })
}

/// invokes in_macro with the expansion info of the given span
/// slightly heavy, try to use this after other checks have already happened
pub fn in_external_macro(cx: &Context, span: Span) -> bool {
    cx.sess().codemap().with_expn_info(span.expn_id,
            |info| in_macro(cx, info))
}

/// check if a DefId's path matches the given absolute type path
/// usage e.g. with
/// `match_def_path(cx, id, &["core", "option", "Option"])`
pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool {
    cx.tcx.with_path(def_id, |iter| iter.zip(path).all(|(nm, p)| nm.name() == p))
}

/// check if type is struct or enum type with given def path
pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool {
    match ty.sty {
        ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => {
            match_def_path(cx, adt.did, path)
        }
        _ => {
            false
        }
    }
}

/// check if method call given in "expr" belongs to given trait
pub fn match_trait_method(cx: &Context, expr: &Expr, path: &[&str]) -> bool {
    let method_call = ty::MethodCall::expr(expr.id);
    let trt_id = cx.tcx.tables
                       .borrow().method_map.get(&method_call)
                       .and_then(|callee| cx.tcx.trait_of_item(callee.def_id));
    if let Some(trt_id) = trt_id {
        match_def_path(cx, trt_id, path)
    } else {
        false
    }
}

/// match a Path against a slice of segment string literals, e.g.
/// `match_path(path, &["std", "rt", "begin_unwind"])`
pub fn match_path(path: &Path, segments: &[&str]) -> bool {
    path.segments.iter().rev().zip(segments.iter().rev()).all(
        |(a, b)| &a.identifier.name == b)
}

/// convert a span to a code snippet if available, otherwise use default, e.g.
/// `snippet(cx, expr.span, "..")`
pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> {
    cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default))
}

/// convert a span (from a block) to a code snippet if available, otherwise use default, e.g.
/// `snippet(cx, expr.span, "..")`
/// This trims the code of indentation, except for the first line
/// Use it for blocks or block-like things which need to be printed as such
pub fn snippet_block<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> {
    let snip = snippet(cx, span, default);
    trim_multiline(snip, true)
}

/// Trim indentation from a multiline string
/// with possibility of ignoring the first line
pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> {
    let s_space = trim_multiline_inner(s, ignore_first, ' ');
    let s_tab = trim_multiline_inner(s_space, ignore_first, '\t');
    trim_multiline_inner(s_tab, ignore_first, ' ')
}

fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> {
    let x = s.lines().skip(ignore_first as usize)
             .filter_map(|l| { if l.len() > 0 { // ignore empty lines
                                Some(l.char_indices()
                                      .find(|&(_,x)| x != ch)
                                      .unwrap_or((l.len(), ch)).0)
                               } else {None}})
             .min().unwrap_or(0);
    if x > 0 {
        Cow::Owned(s.lines().enumerate().map(|(i,l)| if (ignore_first && i == 0) ||
                                                         l.len() == 0 {
                                                        l
                                                     } else {
                                                        l.split_at(x).1
                                                     }).collect::<Vec<_>>()
                                       .join("\n"))
    } else {
        s
    }
}

/// get a parent expr if any – this is useful to constrain a lint
pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> {
    let map = &cx.tcx.map;
    let node_id : NodeId = e.id;
    let parent_id : NodeId = map.get_parent_node(node_id);
    if node_id == parent_id { return None; }
    map.find(parent_id).and_then(|node|
        if let NodeExpr(parent) = node { Some(parent) } else { None } )
}

#[cfg(not(feature="structured_logging"))]
pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) {
    cx.span_lint(lint, sp, msg);
    if cx.current_level(lint) != Level::Allow {
        cx.sess().fileline_help(sp, &format!("for further information visit \
            https://github.com/Manishearth/rust-clippy/wiki#{}",
            lint.name_lower()))
    }
}

#[cfg(feature="structured_logging")]
pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) {
    // lint.name / lint.desc is can give details of the lint
    // cx.sess().codemap() has all these nice functions for line/column/snippet details
    // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string
    cx.span_lint(lint, sp, msg);
    if cx.current_level(lint) != Level::Allow {
        cx.sess().fileline_help(sp, &format!("for further information visit \
            https://github.com/Manishearth/rust-clippy/wiki#{}",
            lint.name_lower()))
    }
}

pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span,
        msg: &str, help: &str) {
    span_lint(cx, lint, span, msg);
    if cx.current_level(lint) != Level::Allow {
        cx.sess().fileline_help(span, &format!("{}\nfor further information \
            visit https://github.com/Manishearth/rust-clippy/wiki#{}",
            help, lint.name_lower()))
    }
}

/// return the base type for references and raw pointers
pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty {
    match ty.sty {
        ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty),
        _ => ty
    }
}

/// return the base type for references and raw pointers, and count reference depth
pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) {
    fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) {
        match ty.sty {
            ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1),
            _ => (ty, depth)
        }
    }
    inner(ty, 0)
}

/// Produce a nested chain of if-lets and ifs from the patterns:
///
///     if_let_chain! {
///         [
///             Some(y) = x,
///             y.len() == 2,
///             Some(z) = y,
///         ],
///         {
///             block
///         }
///     }
///
/// becomes
///
///     if let Some(y) = x {
///         if y.len() == 2 {
///             if let Some(z) = y {
///                 block
///             }
///         }
///     }
#[macro_export]
macro_rules! if_let_chain {
    ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => {
        if let $pat = $expr {
           if_let_chain!{ [$($tt)+], $block }
        }
    };
    ([let $pat:pat = $expr:expr], $block:block) => {
        if let $pat = $expr {
           $block
        }
    };
    ([$expr:expr, $($tt:tt)+], $block:block) => {
        if $expr {
           if_let_chain!{ [$($tt)+], $block }
        }
    };
    ([$expr:expr], $block:block) => {
        if $expr {
           $block
        }
    };
}
<commit_msg>rustup, the ExpnInfo stuff changed<commit_after>use rustc::lint::*;
use syntax::ast::*;
use syntax::codemap::{ExpnInfo, Span, ExpnFormat};
use rustc::ast_map::Node::NodeExpr;
use rustc::middle::def_id::DefId;
use rustc::middle::ty;
use std::borrow::Cow;

// module DefPaths for certain structs/enums we check for
pub const OPTION_PATH: [&'static str; 3] = ["core", "option", "Option"];
pub const RESULT_PATH: [&'static str; 3] = ["core", "result", "Result"];
pub const STRING_PATH: [&'static str; 3] = ["collections", "string", "String"];
pub const VEC_PATH:    [&'static str; 3] = ["collections", "vec", "Vec"];
pub const LL_PATH:     [&'static str; 3] = ["collections", "linked_list", "LinkedList"];

/// returns true if the macro that expanded the crate was outside of
/// the current crate or was a compiler plugin
pub fn in_macro(cx: &Context, opt_info: Option<&ExpnInfo>) -> bool {
    // no ExpnInfo = no macro
    opt_info.map_or(false, |info| {
        match info.callee.format {
            ExpnFormat::CompilerExpansion(..) => {
                if info.callee.name() == "closure expansion" {
                    return false;
                }
            },
            ExpnFormat::MacroAttribute(..) => {
                // these are all plugins
                return true;
            },
            _ => (),
        }
        // no span for the callee = external macro
        info.callee.span.map_or(true, |span| {
            // no snippet = external macro or compiler-builtin expansion
            cx.sess().codemap().span_to_snippet(span).ok().map_or(true, |code|
                // macro doesn't start with "macro_rules"
                // = compiler plugin
                !code.starts_with("macro_rules")
            )
        })
    })
}

/// invokes in_macro with the expansion info of the given span
/// slightly heavy, try to use this after other checks have already happened
pub fn in_external_macro(cx: &Context, span: Span) -> bool {
    cx.sess().codemap().with_expn_info(span.expn_id,
            |info| in_macro(cx, info))
}

/// check if a DefId's path matches the given absolute type path
/// usage e.g. with
/// `match_def_path(cx, id, &["core", "option", "Option"])`
pub fn match_def_path(cx: &Context, def_id: DefId, path: &[&str]) -> bool {
    cx.tcx.with_path(def_id, |iter| iter.zip(path).all(|(nm, p)| nm.name() == p))
}

/// check if type is struct or enum type with given def path
pub fn match_type(cx: &Context, ty: ty::Ty, path: &[&str]) -> bool {
    match ty.sty {
        ty::TyEnum(ref adt, _) | ty::TyStruct(ref adt, _) => {
            match_def_path(cx, adt.did, path)
        }
        _ => {
            false
        }
    }
}

/// check if method call given in "expr" belongs to given trait
pub fn match_trait_method(cx: &Context, expr: &Expr, path: &[&str]) -> bool {
    let method_call = ty::MethodCall::expr(expr.id);
    let trt_id = cx.tcx.tables
                       .borrow().method_map.get(&method_call)
                       .and_then(|callee| cx.tcx.trait_of_item(callee.def_id));
    if let Some(trt_id) = trt_id {
        match_def_path(cx, trt_id, path)
    } else {
        false
    }
}

/// match a Path against a slice of segment string literals, e.g.
/// `match_path(path, &["std", "rt", "begin_unwind"])`
pub fn match_path(path: &Path, segments: &[&str]) -> bool {
    path.segments.iter().rev().zip(segments.iter().rev()).all(
        |(a, b)| &a.identifier.name == b)
}

/// convert a span to a code snippet if available, otherwise use default, e.g.
/// `snippet(cx, expr.span, "..")`
pub fn snippet<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> {
    cx.sess().codemap().span_to_snippet(span).map(From::from).unwrap_or(Cow::Borrowed(default))
}

/// convert a span (from a block) to a code snippet if available, otherwise use default, e.g.
/// `snippet(cx, expr.span, "..")`
/// This trims the code of indentation, except for the first line
/// Use it for blocks or block-like things which need to be printed as such
pub fn snippet_block<'a>(cx: &Context, span: Span, default: &'a str) -> Cow<'a, str> {
    let snip = snippet(cx, span, default);
    trim_multiline(snip, true)
}

/// Trim indentation from a multiline string
/// with possibility of ignoring the first line
pub fn trim_multiline(s: Cow<str>, ignore_first: bool) -> Cow<str> {
    let s_space = trim_multiline_inner(s, ignore_first, ' ');
    let s_tab = trim_multiline_inner(s_space, ignore_first, '\t');
    trim_multiline_inner(s_tab, ignore_first, ' ')
}

fn trim_multiline_inner(s: Cow<str>, ignore_first: bool, ch: char) -> Cow<str> {
    let x = s.lines().skip(ignore_first as usize)
             .filter_map(|l| { if l.len() > 0 { // ignore empty lines
                                Some(l.char_indices()
                                      .find(|&(_,x)| x != ch)
                                      .unwrap_or((l.len(), ch)).0)
                               } else {None}})
             .min().unwrap_or(0);
    if x > 0 {
        Cow::Owned(s.lines().enumerate().map(|(i,l)| if (ignore_first && i == 0) ||
                                                         l.len() == 0 {
                                                        l
                                                     } else {
                                                        l.split_at(x).1
                                                     }).collect::<Vec<_>>()
                                       .join("\n"))
    } else {
        s
    }
}

/// get a parent expr if any – this is useful to constrain a lint
pub fn get_parent_expr<'c>(cx: &'c Context, e: &Expr) -> Option<&'c Expr> {
    let map = &cx.tcx.map;
    let node_id : NodeId = e.id;
    let parent_id : NodeId = map.get_parent_node(node_id);
    if node_id == parent_id { return None; }
    map.find(parent_id).and_then(|node|
        if let NodeExpr(parent) = node { Some(parent) } else { None } )
}

#[cfg(not(feature="structured_logging"))]
pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) {
    cx.span_lint(lint, sp, msg);
    if cx.current_level(lint) != Level::Allow {
        cx.sess().fileline_help(sp, &format!("for further information visit \
            https://github.com/Manishearth/rust-clippy/wiki#{}",
            lint.name_lower()))
    }
}

#[cfg(feature="structured_logging")]
pub fn span_lint(cx: &Context, lint: &'static Lint, sp: Span, msg: &str) {
    // lint.name / lint.desc is can give details of the lint
    // cx.sess().codemap() has all these nice functions for line/column/snippet details
    // http://doc.rust-lang.org/syntax/codemap/struct.CodeMap.html#method.span_to_string
    cx.span_lint(lint, sp, msg);
    if cx.current_level(lint) != Level::Allow {
        cx.sess().fileline_help(sp, &format!("for further information visit \
            https://github.com/Manishearth/rust-clippy/wiki#{}",
            lint.name_lower()))
    }
}

pub fn span_help_and_lint(cx: &Context, lint: &'static Lint, span: Span,
        msg: &str, help: &str) {
    span_lint(cx, lint, span, msg);
    if cx.current_level(lint) != Level::Allow {
        cx.sess().fileline_help(span, &format!("{}\nfor further information \
            visit https://github.com/Manishearth/rust-clippy/wiki#{}",
            help, lint.name_lower()))
    }
}

/// return the base type for references and raw pointers
pub fn walk_ptrs_ty(ty: ty::Ty) -> ty::Ty {
    match ty.sty {
        ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => walk_ptrs_ty(tm.ty),
        _ => ty
    }
}

/// return the base type for references and raw pointers, and count reference depth
pub fn walk_ptrs_ty_depth(ty: ty::Ty) -> (ty::Ty, usize) {
    fn inner(ty: ty::Ty, depth: usize) -> (ty::Ty, usize) {
        match ty.sty {
            ty::TyRef(_, ref tm) | ty::TyRawPtr(ref tm) => inner(tm.ty, depth + 1),
            _ => (ty, depth)
        }
    }
    inner(ty, 0)
}

/// Produce a nested chain of if-lets and ifs from the patterns:
///
///     if_let_chain! {
///         [
///             Some(y) = x,
///             y.len() == 2,
///             Some(z) = y,
///         ],
///         {
///             block
///         }
///     }
///
/// becomes
///
///     if let Some(y) = x {
///         if y.len() == 2 {
///             if let Some(z) = y {
///                 block
///             }
///         }
///     }
#[macro_export]
macro_rules! if_let_chain {
    ([let $pat:pat = $expr:expr, $($tt:tt)+], $block:block) => {
        if let $pat = $expr {
           if_let_chain!{ [$($tt)+], $block }
        }
    };
    ([let $pat:pat = $expr:expr], $block:block) => {
        if let $pat = $expr {
           $block
        }
    };
    ([$expr:expr, $($tt:tt)+], $block:block) => {
        if $expr {
           if_let_chain!{ [$($tt)+], $block }
        }
    };
    ([$expr:expr], $block:block) => {
        if $expr {
           $block
        }
    };
}
<|endoftext|>


<commit_before>//! Types representing for data which will be retrieved from the driver.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the driver to these types.

use linear_map::LinearMap;

/// The type which represents the key for maps used throughout the Ardite
/// codebase.
///
/// Functions similarly to an object key in JavaScript.
pub type Key = String;

/// Represents a [JSON pointer][1] to a document property. Examples of a
/// pointer in this context include `/hello/world` or `/a/b/c/d`.
///
/// These pointers are represented as a list of keys.
///
/// [1]: https://duckduckgo.com/?q=json+pointer&atb=v1&ia=about
pub type Pointer = Vec<Key>;

/// Ordered representation of a map of key/value pairs, like a JSON object.
/// Backed by a linear map to maintain order and have high performance for
/// small objects.
// TODO: newtype pattern?
pub type Object = LinearMap<Key, Value>;

/// Ordered array of values, like a JSON array.
// TODO: newtype pattern?
pub type Array = Vec<Value>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
#[derive(PartialEq, Clone, Debug)]
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// An integer numeric value.
  I64(i64),
  /// A floating point numeric value.
  F64(f64),
  /// A list of characters.
  String(String),
  /// A map of key/value pairs.
  Object(Object),
  /// A list of values.
  Array(Array)
}

impl Value {
  /// Gets a value at a specific point. Helpful for retrieving nested values.
  pub fn get(&self, mut pointer: Pointer) -> Option<&Value> {
    match *self {
      Value::Object(ref map) => {
        if pointer.is_empty() {
          Some(self)
        } else if let Some(value) = map.get(&pointer.remove(0)) {
          value.get(pointer)
        } else {
          None
        }
      },
      Value::Array(ref vec) => {
        if pointer.is_empty() {
          Some(self)
        } else if let Some(value) = pointer.remove(0).parse::<usize>().ok().map_or(None, |i| vec.get(i)) {
          value.get(pointer)
        } else {
          None
        }
      },
      _ => if pointer.is_empty() { Some(self) } else { None }
    }
  }

  /// Converts a value into a JSON string for distribution.
  pub fn to_json(&self) -> String {
    match *self {
      Value::Null => "null".to_owned(),
      Value::Boolean(value) => if value { "true".to_owned() } else { "false".to_owned() },
      Value::I64(value) => value.to_string(),
      Value::F64(value) => value.to_string(),
      Value::String(ref value) => "\"".to_owned() + &escape_string_for_json(value) + "\"",
      Value::Object(ref map) => {
        let mut json = "{".to_owned();
        for (key, value) in map {
          json.push_str("\"");
          json.push_str(&escape_string_for_json(key));
          json.push_str("\":");
          json.push_str(&value.to_json());
          json.push_str(",");
        }
        // Remove the last comma.
        json.pop();
        json.push_str("}");
        json
      },
      Value::Array(ref vec) => {
        let mut json = "[".to_owned();
        for item in vec {
          json.push_str(&item.to_json());
          json.push_str(",");
        }
        // Remove the last comma.
        json.pop();
        json.push_str("]");
        json
      }
    }
  }
}

impl Serialize for Value {
  #[inline]
  fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
    match *self {
      Value::Null => serializer.serialize_unit(),
      Value::Boolean(value) => serializer.serialize_bool(value),
      Value::I64(value) => serializer.serialize_i64(value),
      Value::F64(value) => serializer.serialize_f64(value),
      Value::String(ref value) => serializer.serialize_str(&value),
      Value::Array(ref value) => value.serialize(serializer),
      Value::Object(ref value) => value.serialize(serializer)
    }
  }
}

impl<V> From<Option<V>> for Value where V: Into<Value> {
  fn from(option: Option<V>) -> Self {
    match option {
      None => Value::Null,
      Some(value) => value.into()
    }
  }
}

impl From<bool> for Value {
  fn from(boolean: bool) -> Self {
    Value::Boolean(boolean)
  }
}

impl From<i64> for Value {
  fn from(number: i64) -> Self {
    Value::I64(number)
  }
}

impl From<f64> for Value {
  fn from(number: f64) -> Self {
    Value::F64(number)
  }
}

impl From<String> for Value {
  fn from(string: String) -> Self {
    Value::String(string)
  }
}

impl<'a> From<&'a str> for Value {
  fn from(string: &'a str) -> Self {
    Value::from(string.to_owned())
  }
}

/// Takes a string and escapes it for use within a JSON encoded object. Read,
/// inside quotes.
fn escape_string_for_json(string: &str) -> String {
  string.replace("\"", "\\\"").replace("\n", "\\n")
}

/// An iterator of values. Used by drivers to convert their own iterator
/// implementations into a single type.
pub struct ValueIter<'a> {
  iter: Box<Iterator<Item=Value> + 'a>
}

impl<'a> ValueIter<'a> {
  /// Create a new value iterator.
  pub fn new<I>(iter: I) -> Self where I: Iterator<Item=Value> + 'a {
    ValueIter {
      iter: Box::new(iter)
    }
  }
}

impl<'a> Iterator for ValueIter<'a> {
  type Item = Value;

  #[inline]
  fn next(&mut self) -> Option<Value> {
    self.iter.next()
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn test_get_primitive() {
    assert_eq!(value!().get(point![]).cloned(), Some(value!()));
    assert_eq!(value!().get(point!["hello"]).cloned(), None);
    assert_eq!(value!().get(point!["a", "b", "c", "d", "e"]).cloned(), None);
    assert_eq!(value!(true).get(point![]).cloned(), Some(value!(true)));
    assert_eq!(value!(true).get(point!["hello"]).cloned(), None);
    assert_eq!(value!(36).get(point![]).cloned(), Some(value!(36)));
    assert_eq!(value!(36).get(point!["hello"]).cloned(), None);
    assert_eq!(value!("world").get(point![]).cloned(), Some(value!("world")));
    assert_eq!(value!("world").get(point!["hello"]).cloned(), None);
  }

  #[test]
  fn test_get_object() {
    let object = value!({
      "hello" => true,
      "world" => 8,
      "yolo" => "swag",
      "5" => (),
      "moon" => {
        "hello" => "yoyo"
      }
    });
    assert_eq!(object.get(point![]).cloned(), Some(object.clone()));
    assert_eq!(object.get(point!["hello"]).cloned(), Some(value!(true)));
    assert_eq!(object.get(point!["yolo"]).cloned(), Some(value!("swag")));
    assert_eq!(object.get(point!["5"]).cloned(), Some(value!()));
    assert_eq!(object.get(point!["world", "hello"]).cloned(), None);
    assert_eq!(object.get(point!["moon", "hello"]).cloned(), Some(value!("yoyo")));
    assert_eq!(object.get(point!["moon", "nope"]).cloned(), None);
  }

  #[test]
  fn test_get_array() {
    let array = value!([
      false,
      64,
      {
        "hello" => true,
        "world" => false,
        "moon" => {
          "goodbye" => "yoyo"
        }
      },
      [[1, 2, 3], 4, 5 ]
    ]);
    assert_eq!(array.get(point![]).cloned(), Some(array.clone()));
    assert_eq!(array.get(point!["0"]).cloned(), Some(value!(false)));
    assert_eq!(array.get(point!["1"]).cloned(), Some(value!(64)));
    assert_eq!(array.get(point!["2", "hello"]).cloned(), Some(value!(true)));
    assert_eq!(array.get(point!["2", "moon", "goodbye"]).cloned(), Some(value!("yoyo")));
    assert_eq!(array.get(point!["length"]).cloned(), None);
    assert_eq!(array.get(point!["3", "0", "1"]).cloned(), Some(value!(2)));
  }

  #[test]
  fn test_to_json() {
    assert_eq!(&value!().to_json(), "null");
    assert_eq!(&value!(true).to_json(), "true");
    assert_eq!(&value!(false).to_json(), "false");
    assert_eq!(&value!(7).to_json(), "7");
    assert_eq!(&value!(6.667).to_json(), "6.667");
    assert_eq!(&value!("Hello,\n\"world\"!").to_json(), r#""Hello,\n\"world\"!""#);
    assert_eq!(&value!({
      "hello" => "world",
      "foo" => true,
      "null" => (),
      "goodbye" => {
        "moon" => 2
      }
    }).to_json(), r#"{"hello":"world","foo":true,"null":null,"goodbye":{"moon":2}}"#);
    assert_eq!(
      &value!(["world", 3.333, { "hello" => "world" }, (), (), [1, 2, 3], ()]).to_json(),
      r#"["world",3.333,{"hello":"world"},null,null,[1,2,3],null]"#
    );
  }
}
<commit_msg>fix(value): add imports for serialize<commit_after>//! Types representing for data which will be retrieved from the driver.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the driver to these types.

use linear_map::LinearMap;
use serde::ser::{Serialize, Serializer};

/// The type which represents the key for maps used throughout the Ardite
/// codebase.
///
/// Functions similarly to an object key in JavaScript.
pub type Key = String;

/// Represents a [JSON pointer][1] to a document property. Examples of a
/// pointer in this context include `/hello/world` or `/a/b/c/d`.
///
/// These pointers are represented as a list of keys.
///
/// [1]: https://duckduckgo.com/?q=json+pointer&atb=v1&ia=about
pub type Pointer = Vec<Key>;

/// Ordered representation of a map of key/value pairs, like a JSON object.
/// Backed by a linear map to maintain order and have high performance for
/// small objects.
// TODO: newtype pattern?
pub type Object = LinearMap<Key, Value>;

/// Ordered array of values, like a JSON array.
// TODO: newtype pattern?
pub type Array = Vec<Value>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
#[derive(PartialEq, Clone, Debug)]
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// An integer numeric value.
  I64(i64),
  /// A floating point numeric value.
  F64(f64),
  /// A list of characters.
  String(String),
  /// A map of key/value pairs.
  Object(Object),
  /// A list of values.
  Array(Array)
}

impl Value {
  /// Gets a value at a specific point. Helpful for retrieving nested values.
  pub fn get(&self, mut pointer: Pointer) -> Option<&Value> {
    match *self {
      Value::Object(ref map) => {
        if pointer.is_empty() {
          Some(self)
        } else if let Some(value) = map.get(&pointer.remove(0)) {
          value.get(pointer)
        } else {
          None
        }
      },
      Value::Array(ref vec) => {
        if pointer.is_empty() {
          Some(self)
        } else if let Some(value) = pointer.remove(0).parse::<usize>().ok().map_or(None, |i| vec.get(i)) {
          value.get(pointer)
        } else {
          None
        }
      },
      _ => if pointer.is_empty() { Some(self) } else { None }
    }
  }

  /// Converts a value into a JSON string for distribution.
  pub fn to_json(&self) -> String {
    match *self {
      Value::Null => "null".to_owned(),
      Value::Boolean(value) => if value { "true".to_owned() } else { "false".to_owned() },
      Value::I64(value) => value.to_string(),
      Value::F64(value) => value.to_string(),
      Value::String(ref value) => "\"".to_owned() + &escape_string_for_json(value) + "\"",
      Value::Object(ref map) => {
        let mut json = "{".to_owned();
        for (key, value) in map {
          json.push_str("\"");
          json.push_str(&escape_string_for_json(key));
          json.push_str("\":");
          json.push_str(&value.to_json());
          json.push_str(",");
        }
        // Remove the last comma.
        json.pop();
        json.push_str("}");
        json
      },
      Value::Array(ref vec) => {
        let mut json = "[".to_owned();
        for item in vec {
          json.push_str(&item.to_json());
          json.push_str(",");
        }
        // Remove the last comma.
        json.pop();
        json.push_str("]");
        json
      }
    }
  }
}

impl Serialize for Value {
  #[inline]
  fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
    match *self {
      Value::Null => serializer.serialize_unit(),
      Value::Boolean(value) => serializer.serialize_bool(value),
      Value::I64(value) => serializer.serialize_i64(value),
      Value::F64(value) => serializer.serialize_f64(value),
      Value::String(ref value) => serializer.serialize_str(&value),
      Value::Array(ref value) => value.serialize(serializer),
      Value::Object(ref value) => value.serialize(serializer)
    }
  }
}

impl<V> From<Option<V>> for Value where V: Into<Value> {
  fn from(option: Option<V>) -> Self {
    match option {
      None => Value::Null,
      Some(value) => value.into()
    }
  }
}

impl From<bool> for Value {
  fn from(boolean: bool) -> Self {
    Value::Boolean(boolean)
  }
}

impl From<i64> for Value {
  fn from(number: i64) -> Self {
    Value::I64(number)
  }
}

impl From<f64> for Value {
  fn from(number: f64) -> Self {
    Value::F64(number)
  }
}

impl From<String> for Value {
  fn from(string: String) -> Self {
    Value::String(string)
  }
}

impl<'a> From<&'a str> for Value {
  fn from(string: &'a str) -> Self {
    Value::from(string.to_owned())
  }
}

/// Takes a string and escapes it for use within a JSON encoded object. Read,
/// inside quotes.
fn escape_string_for_json(string: &str) -> String {
  string.replace("\"", "\\\"").replace("\n", "\\n")
}

/// An iterator of values. Used by drivers to convert their own iterator
/// implementations into a single type.
pub struct ValueIter<'a> {
  iter: Box<Iterator<Item=Value> + 'a>
}

impl<'a> ValueIter<'a> {
  /// Create a new value iterator.
  pub fn new<I>(iter: I) -> Self where I: Iterator<Item=Value> + 'a {
    ValueIter {
      iter: Box::new(iter)
    }
  }
}

impl<'a> Iterator for ValueIter<'a> {
  type Item = Value;

  #[inline]
  fn next(&mut self) -> Option<Value> {
    self.iter.next()
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn test_get_primitive() {
    assert_eq!(value!().get(point![]).cloned(), Some(value!()));
    assert_eq!(value!().get(point!["hello"]).cloned(), None);
    assert_eq!(value!().get(point!["a", "b", "c", "d", "e"]).cloned(), None);
    assert_eq!(value!(true).get(point![]).cloned(), Some(value!(true)));
    assert_eq!(value!(true).get(point!["hello"]).cloned(), None);
    assert_eq!(value!(36).get(point![]).cloned(), Some(value!(36)));
    assert_eq!(value!(36).get(point!["hello"]).cloned(), None);
    assert_eq!(value!("world").get(point![]).cloned(), Some(value!("world")));
    assert_eq!(value!("world").get(point!["hello"]).cloned(), None);
  }

  #[test]
  fn test_get_object() {
    let object = value!({
      "hello" => true,
      "world" => 8,
      "yolo" => "swag",
      "5" => (),
      "moon" => {
        "hello" => "yoyo"
      }
    });
    assert_eq!(object.get(point![]).cloned(), Some(object.clone()));
    assert_eq!(object.get(point!["hello"]).cloned(), Some(value!(true)));
    assert_eq!(object.get(point!["yolo"]).cloned(), Some(value!("swag")));
    assert_eq!(object.get(point!["5"]).cloned(), Some(value!()));
    assert_eq!(object.get(point!["world", "hello"]).cloned(), None);
    assert_eq!(object.get(point!["moon", "hello"]).cloned(), Some(value!("yoyo")));
    assert_eq!(object.get(point!["moon", "nope"]).cloned(), None);
  }

  #[test]
  fn test_get_array() {
    let array = value!([
      false,
      64,
      {
        "hello" => true,
        "world" => false,
        "moon" => {
          "goodbye" => "yoyo"
        }
      },
      [[1, 2, 3], 4, 5 ]
    ]);
    assert_eq!(array.get(point![]).cloned(), Some(array.clone()));
    assert_eq!(array.get(point!["0"]).cloned(), Some(value!(false)));
    assert_eq!(array.get(point!["1"]).cloned(), Some(value!(64)));
    assert_eq!(array.get(point!["2", "hello"]).cloned(), Some(value!(true)));
    assert_eq!(array.get(point!["2", "moon", "goodbye"]).cloned(), Some(value!("yoyo")));
    assert_eq!(array.get(point!["length"]).cloned(), None);
    assert_eq!(array.get(point!["3", "0", "1"]).cloned(), Some(value!(2)));
  }

  #[test]
  fn test_to_json() {
    assert_eq!(&value!().to_json(), "null");
    assert_eq!(&value!(true).to_json(), "true");
    assert_eq!(&value!(false).to_json(), "false");
    assert_eq!(&value!(7).to_json(), "7");
    assert_eq!(&value!(6.667).to_json(), "6.667");
    assert_eq!(&value!("Hello,\n\"world\"!").to_json(), r#""Hello,\n\"world\"!""#);
    assert_eq!(&value!({
      "hello" => "world",
      "foo" => true,
      "null" => (),
      "goodbye" => {
        "moon" => 2
      }
    }).to_json(), r#"{"hello":"world","foo":true,"null":null,"goodbye":{"moon":2}}"#);
    assert_eq!(
      &value!(["world", 3.333, { "hello" => "world" }, (), (), [1, 2, 3], ()]).to_json(),
      r#"["world",3.333,{"hello":"world"},null,null,[1,2,3],null]"#
    );
  }
}
<|endoftext|>


<commit_before>use SChunks;
use std::fs::File;
use std::io::{Error, Write};

/// This function takes as parameter a file name and a vector of chaunks.
/// The function will create a file, and append to the buffer each chunk.
pub fn write_file(local_file: &mut File, chunks: &SChunks) -> Result<(), Error> {

    // Get the access to the chunks
    let chunks_m = chunks.lock().unwrap();

    // For each ones, write it into the file buffer
    for chunk in chunks_m.iter() {
        match local_file.write_all(chunk) {
            Ok(_) => (),
            // Exit if there is an error
            Err(error) => return Err(error),
        }
    }

    // Return a positive result if the remote content has been saved
    Ok(())
}<commit_msg>Update the module, comments from @jean-serge<commit_after>use SChunks;
use std::fs::File;
use std::io::{Error, Write};

/// This function fills the buffer of a given local file, with the content of chunks.
pub fn write_file(local_file_buf: &mut File, chunks: &SChunks) -> Result<(), Error> {

    // Get the access to the chunks
    let chunks_m = chunks.lock().unwrap();

    // For each ones, write it into the file buffer
    for chunk in chunks_m.iter() {
        match local_file_buf.write_all(chunk) {
            Ok(_) => (),
            Err(error) => return Err(error),
        }
    }

    // Return a positive result if the remote content has been saved
    Ok(())
}<|endoftext|>


<commit_before>// DOCS

#![allow(unstable)]
#![feature(plugin)]
#[plugin] extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

pub struct Property {
    params: HashMap<String, String>,
    raw_value: String,
    prop_group: Option<String>
}

impl Property {
    fn new(params: HashMap<String, String>, raw_value: String, prop_group: Option<String>) -> Property {
        Property {
            params: params,
            raw_value: raw_value,
            prop_group: prop_group
        }
    }

    /// Get property group. E.g. a contentline like `foo.FN:Markus` would result in the group being
    /// `"foo"`.
    pub fn get_prop_group(&self) -> &Option<String> {
        &self.prop_group
    }

    /// Get parameters.
    pub fn get_params(&self) -> &HashMap<String, String> {
        &self.params
    }

    /// Get value as unparsed string.
    pub fn get_raw_value(&self) -> &String {
        &self.raw_value
    }

    /// Get value as unescaped string.
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.get_raw_value())
    }
}

pub struct Component {
    /// The name of the component, such as `VCARD` or `VEVENT`.
    pub name: String,

    /// The component's properties.
    pub props: HashMap<String, Vec<Property>>,

    /// The component's child- or sub-components.
    pub subcomponents: Vec<Component>
}

impl Component {
    fn new(name: String) -> Component {
        Component {
            name: name,
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    /// Retrieve one property (from many) by key. Returns `None` if nothing is found.
    pub fn single_prop(&self, key: &str) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    /// Retrieve a mutable vector of properties for this key. Creates one (and inserts it into the
    /// component) if none exists.
    pub fn all_props_mut(&mut self, key: &str) -> &mut Vec<Property> {
        match self.props.entry(String::from_str(key)) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.insert(vec![])
        }
    }

    /// Retrieve properties by key. Returns an empty slice if key doesn't exist.
    pub fn all_props(&self, key: &str) -> &[Property] {
        static EMPTY: &'static [Property] = &[];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

#[pub]
component -> Component
    = name:component_begin
      ps:props
      cs:components?
      component_end {
        let mut rv = Component::new(name);

        match cs {
            Some(components) => { rv.subcomponents = components; },
            None => ()
        };

        for (k, v) in ps.into_iter() {
            rv.all_props_mut(k).push(v);
        };

        rv
    }

component_begin -> String
    = "BEGIN:" v:value __ { v.to_string() }

component_end -> String
    = "END:" v:value __ { v.to_string() }

components -> Vec<Component>
    = cs:component ++ eols __ { cs }

props -> Vec<(&'input str, Property)>
    = ps:prop ++ eols __ { ps }

prop -> (&'input str, Property)
    = !"BEGIN:" !"END:" g:group? k:name p:params ":" v:value {
        (k, Property::new(p, v, g))
    }

group -> String
    = g:group_name "." { g }

group_name -> String
    = group_char+ { match_str.to_string() }

name -> &'input str
    = iana_token+ { match_str }

params -> HashMap<String, String>
    = ps:(";" p:param {p})* {
        let mut rv: HashMap<String, String> = HashMap::new();
        for (k, v) in ps.into_iter() {
            rv.insert(k.to_string(), v.to_string());
        };
        rv
    }

param -> (&'input str, &'input str)
    // FIXME: Doesn't handle comma-separated values
    = k:param_name v:("=" v:param_value { v })? {
        (k, match v {
            Some(x) => x,
            None => ""
        })
    }

param_name -> &'input str
    = iana_token+ { match_str }

param_value -> &'input str
    = x:(quoted_string / param_text) { x }

param_text -> &'input str
    = safe_char* { match_str }

value -> String
    = value_char+ { match_str.to_string() }

quoted_string -> &'input str
    = dquote x:quoted_content dquote { x }

quoted_content -> &'input str
    = qsafe_char* { match_str }

iana_token = ([a-zA-Z0-9] / "-")+
group_char = ([a-zA-Z0-9] / "-")
qsafe_char = !dquote !ctl value_char
safe_char = !";" !":" qsafe_char

value_char = !eol .

eol = "\r\n" / "\n" / "\r"
dquote = "\""
eols = eol+
ctl =
    // "\x00-1F" / "\x7F"
    // FIXME: https://github.com/kevinmehall/rust-peg/issues/41
    "\x00" / "\x01" / "\x02" / "\x03" / "\x04" / "\x05" / "\x06" / "\x07" / "\x08" / "\t" / "\n" /
    "\x0b" / "\x0c" / "\r" / "\x0e" / "\x0f" / "\x10" / "\x11" / "\x12" / "\x13" / "\x14" / "\x15"
    / "\x16" / "\x17" / "\x18" / "\x19" / "\x1a" / "\x1b" / "\x1c" / "\x1d" / "\x1e" / "\x7f"

whitespace = " " / "\t"
__ = (eol / whitespace)*

"#);

/// Parse a component. The error value is a human-readable message.
pub fn parse_component(s: &String) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = s
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r ", "").replace("\r\t", "");

    parser::component(unfolded.as_slice())
}

/// Escape text for a VObject property value.
pub fn escape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

/// Unescape text from a VObject property value.
pub fn unescape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}
<commit_msg>Replace list with byte-range<commit_after>// DOCS

#![allow(unstable)]
#![feature(plugin)]
#[plugin] extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

pub struct Property {
    params: HashMap<String, String>,
    raw_value: String,
    prop_group: Option<String>
}

impl Property {
    fn new(params: HashMap<String, String>, raw_value: String, prop_group: Option<String>) -> Property {
        Property {
            params: params,
            raw_value: raw_value,
            prop_group: prop_group
        }
    }

    /// Get property group. E.g. a contentline like `foo.FN:Markus` would result in the group being
    /// `"foo"`.
    pub fn get_prop_group(&self) -> &Option<String> {
        &self.prop_group
    }

    /// Get parameters.
    pub fn get_params(&self) -> &HashMap<String, String> {
        &self.params
    }

    /// Get value as unparsed string.
    pub fn get_raw_value(&self) -> &String {
        &self.raw_value
    }

    /// Get value as unescaped string.
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.get_raw_value())
    }
}

pub struct Component {
    /// The name of the component, such as `VCARD` or `VEVENT`.
    pub name: String,

    /// The component's properties.
    pub props: HashMap<String, Vec<Property>>,

    /// The component's child- or sub-components.
    pub subcomponents: Vec<Component>
}

impl Component {
    fn new(name: String) -> Component {
        Component {
            name: name,
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    /// Retrieve one property (from many) by key. Returns `None` if nothing is found.
    pub fn single_prop(&self, key: &str) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    /// Retrieve a mutable vector of properties for this key. Creates one (and inserts it into the
    /// component) if none exists.
    pub fn all_props_mut(&mut self, key: &str) -> &mut Vec<Property> {
        match self.props.entry(String::from_str(key)) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.insert(vec![])
        }
    }

    /// Retrieve properties by key. Returns an empty slice if key doesn't exist.
    pub fn all_props(&self, key: &str) -> &[Property] {
        static EMPTY: &'static [Property] = &[];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

#[pub]
component -> Component
    = name:component_begin
      ps:props
      cs:components?
      component_end {
        let mut rv = Component::new(name);

        match cs {
            Some(components) => { rv.subcomponents = components; },
            None => ()
        };

        for (k, v) in ps.into_iter() {
            rv.all_props_mut(k).push(v);
        };

        rv
    }

component_begin -> String
    = "BEGIN:" v:value __ { v.to_string() }

component_end -> String
    = "END:" v:value __ { v.to_string() }

components -> Vec<Component>
    = cs:component ++ eols __ { cs }

props -> Vec<(&'input str, Property)>
    = ps:prop ++ eols __ { ps }

prop -> (&'input str, Property)
    = !"BEGIN:" !"END:" g:group? k:name p:params ":" v:value {
        (k, Property::new(p, v, g))
    }

group -> String
    = g:group_name "." { g }

group_name -> String
    = group_char+ { match_str.to_string() }

name -> &'input str
    = iana_token+ { match_str }

params -> HashMap<String, String>
    = ps:(";" p:param {p})* {
        let mut rv: HashMap<String, String> = HashMap::new();
        for (k, v) in ps.into_iter() {
            rv.insert(k.to_string(), v.to_string());
        };
        rv
    }

param -> (&'input str, &'input str)
    // FIXME: Doesn't handle comma-separated values
    = k:param_name v:("=" v:param_value { v })? {
        (k, match v {
            Some(x) => x,
            None => ""
        })
    }

param_name -> &'input str
    = iana_token+ { match_str }

param_value -> &'input str
    = x:(quoted_string / param_text) { x }

param_text -> &'input str
    = safe_char* { match_str }

value -> String
    = value_char+ { match_str.to_string() }

quoted_string -> &'input str
    = dquote x:quoted_content dquote { x }

quoted_content -> &'input str
    = qsafe_char* { match_str }

iana_token = ([a-zA-Z0-9] / "-")+
group_char = ([a-zA-Z0-9] / "-")
qsafe_char = !dquote !ctl value_char
safe_char = !";" !":" qsafe_char

value_char = !eol .

eol = "\r\n" / "\n" / "\r"
dquote = "\""
eols = eol+
ctl = [\u{00}-\u{1F}] / "\u{7F}"

whitespace = " " / "\t"
__ = (eol / whitespace)*

"#);

/// Parse a component. The error value is a human-readable message.
pub fn parse_component(s: &String) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = s
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r ", "").replace("\r\t", "");

    parser::component(unfolded.as_slice())
}

/// Escape text for a VObject property value.
pub fn escape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

/// Unescape text from a VObject property value.
pub fn unescape_chars(s: &String) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::io::BufReader;
use std::io::SeekFrom;
use std::fs::File;

/*
from __future__ import division, print_function, unicode_literals

import numpy as np

try:
    from sklearn.externals import joblib
except:
    joblib = None

from word2vec.utils import unitvec

class WordVectors(object):

    def __init__(self, vocab, vectors, clusters=None):
        """
        Initialize a WordVectors class based on vocabulary and vectors
        This initializer precomputes the vectors of the vectors
        Parameters
        ----------
        vocab : np.array
            1d array with the vocabulary
        vectors : np.array
            2d array with the vectors calculated by word2vec
        clusters : word2vec.WordClusters (optional)
            1d array with the clusters calculated by word2vec
        """
        self.vocab = vocab
        self.vectors = vectors
        self.clusters = clusters

        self.vocab_hash = {}
        for i, word in enumerate(vocab):
            self.vocab_hash[word] = i

    def ix(self, word):
        """
        Returns the index on self.vocab and `self.vectors` for `word`
        """
        return self.vocab_hash[word]

    def __getitem__(self, word):
        return self.get_vector(word)

    def __contains__(self, word):
        return word in self.vocab_hash

    def get_vector(self, word):
        """
        Returns the (vectors) vector for `word` in the vocabulary
        """
        idx = self.ix(word)
        return self.vectors[idx]

    def cosine(self, word, n=10):
        """
        Cosine similarity.
        metric = dot(vectors_of_vectors, vectors_of_target_vector)
        Uses a precomputed vectors of the vectors
        Parameters
        ----------
        word : string
        n : int, optional (default 10)
            number of neighbors to return
        Returns
        -------
        2 numpy.array:
            1. position in self.vocab
            2. cosine similarity
        """
        metrics = np.dot(self.vectors, self[word].T)
        best = np.argsort(metrics)[::-1][1:n+1]
        best_metrics = metrics[best]
        return best, best_metrics

    def analogy(self, pos, neg, n=10):
        """
        Analogy similarity.
        Parameters
        ----------
        pos : list
        neg : list
        Returns
        -------
        2 numpy.array:
            1. position in self.vocab
            2. cosine similarity
        Example
        -------
            `king - man + woman = queen` will be:
            `pos=['king', 'woman'], neg=['man']`
        """
        exclude = pos + neg
        pos = [(word, 1.0) for word in pos]
        neg = [(word, -1.0) for word in neg]

        mean = []
        for word, direction in pos + neg:
            mean.append(direction * self[word])
        mean = np.array(mean).mean(axis=0)

        metrics = np.dot(self.vectors, mean)
        best = metrics.argsort()[::-1][:n + len(exclude)]

        exclude_idx = [np.where(best == self.ix(word)) for word in exclude if
                       self.ix(word) in best]
        new_best = np.delete(best, exclude_idx)
        best_metrics = metrics[new_best]
        return new_best[:n], best_metrics[:n]

    def generate_response(self, indexes, metrics, clusters=True):
        '''
        Generates a pure python (no numpy) response based on numpy arrays
        returned by `self.cosine` and `self.analogy`
        '''
        if self.clusters and clusters:
            return np.rec.fromarrays((self.vocab[indexes], metrics,
                                     self.clusters.clusters[indexes]),
                                     names=('word', 'metric', 'cluster'))
        else:
            return np.rec.fromarrays((self.vocab[indexes], metrics),
                                     names=('word', 'metric'))

    def to_mmap(self, fname):
        if not joblib:
            raise Exception("sklearn is needed to save as mmap")

        joblib.dump(self, fname)

    @classmethod
    def from_binary(cls, fname, vocabUnicodeSize=78, desired_vocab=None, encoding="utf-8"):
        """
        Create a WordVectors class based on a word2vec binary file
        Parameters
        ----------
        fname : path to file
        vocabUnicodeSize: the maximum string length (78, by default)
        desired_vocab: if set, this will ignore any word and vector that
                       doesn't fall inside desired_vocab.
        Returns
        -------
        WordVectors instance
        """
        with open(fname, 'rb') as fin:
            header = fin.readline()
            vocab_size, vector_size = list(map(int, header.split()))

            vocab = np.empty(vocab_size, dtype='<U%s' % vocabUnicodeSize)
            vectors = np.empty((vocab_size, vector_size), dtype=np.float)
            binary_len = np.dtype(np.float32).itemsize * vector_size
            for i in range(vocab_size):
                # read word
                word = b''
                while True:
                    ch = fin.read(1)
                    if ch == b' ':
                        break
                    word += ch
                include = desired_vocab is None or word in desired_vocab
                if include:
                    vocab[i] = word.decode(encoding)

                # read vector
                vector = np.fromstring(fin.read(binary_len), dtype=np.float32)
                if include:
                    vectors[i] = unitvec(vector)
                fin.read(1)  # newline

            if desired_vocab is not None:
                vectors = vectors[vocab != '', :]
                vocab = vocab[vocab != '']
        return cls(vocab=vocab, vectors=vectors)

    @classmethod
    def from_text(cls, fname, vocabUnicodeSize=78, desired_vocab=None, encoding="utf-8"):
        """
        Create a WordVectors class based on a word2vec text file
        Parameters
        ----------
        fname : path to file
        vocabUnicodeSize: the maximum string length (78, by default)
        desired_vocab: if set, this will ignore any word and vector that
                       doesn't fall inside desired_vocab.
        Returns
        -------
        WordVectors instance
        """
        with open(fname, 'rb') as fin:
            header = fin.readline()
            vocab_size, vector_size = list(map(int, header.split()))

            vocab = np.empty(vocab_size, dtype='<U%s' % vocabUnicodeSize)
            vectors = np.empty((vocab_size, vector_size), dtype=np.float)
            for i, line in enumerate(fin):
                line = line.decode(encoding).strip()
                parts = line.split(' ')
                word = parts[0]
                include = desired_vocab is None or word in desired_vocab
                if include:
                    vector = np.array(parts[1:], dtype=np.float)
                    vocab[i] = word
                    vectors[i] = unitvec(vector)

            if desired_vocab is not None:
                vectors = vectors[vocab != '', :]
                vocab = vocab[vocab != '']
        return cls(vocab=vocab, vectors=vectors)

    @classmethod
    def from_mmap(cls, fname):
        """
        Create a WordVectors class from a memory map
        Parameters
        ----------
        fname : path to file
        Returns
        -------
        WordVectors instance
        """
        memmaped = joblib.load(fname, mmap_mode='r+')
        return cls(vocab=memmaped.vocab, vectors=memmaped.vectors)
 */

pub struct WordVector {
    vocabulary: Vec<String>,
    vectors: Vec<String>,
    clusters: Option<Vec<String>>
}

impl WordVector{
	pub fn load_from_binary(file_name: &str) -> WordVector
	{
		let mut file = File::open(file_name).unwrap();
		let mut reader = BufReader::new(file);
		let mut header = String::new();
		reader.read_line(&mut header).unwrap();
		let mut header_info = header.split_whitespace().map(|x| x.parse::<usize>().unwrap()).take(2);
		let vocabulary_size = header_info.next().unwrap();
		let vector_size = header_info.next().unwrap();
		let vector_length: u64 = 4 * vector_size as u64;
		let mut vectors: Vec<Vec<f32>> = vec![Vec::new(); vector_size];
		let mut vocabulary = vec![String::new(); vocabulary_size];
		for i in 0..vocabulary_size{
			let mut word_bytes: Vec<u8> = Vec::new();
			let mut vector_bytes: Vec<u8> = Vec::new();
			reader.read_until(b' ', &mut word_bytes).unwrap();
			word_bytes.pop();
			let word = String::from_utf8(word_bytes).unwrap();
			vocabulary[i] = word;
			{
			    let reader_ref = reader.by_ref();
			    let mut chunk = reader_ref.take(vector_length);
                let result = chunk.read_to_end(&mut vector_bytes);
                // to do: parse result
			}
			reader.seek(SeekFrom::Current(1));
		}
		WordVector{
			vocabulary: vocabulary,
			vectors: Vec::new(),
			clusters: None
		}

	}
}<commit_msg>Add ability to parse vector, create function for getting index from word<commit_after>use std::io;
use std::io::prelude::*;
use std::io::BufReader;
use std::io::SeekFrom;
use std::fs::File;
use std::mem;

/*
from __future__ import division, print_function, unicode_literals

import numpy as np

try:
    from sklearn.externals import joblib
except:
    joblib = None

from word2vec.utils import unitvec

class WordVectors(object):

    def __init__(self, vocab, vectors, clusters=None):
        """
        Initialize a WordVectors class based on vocabulary and vectors
        This initializer precomputes the vectors of the vectors
        Parameters
        ----------
        vocab : np.array
            1d array with the vocabulary
        vectors : np.array
            2d array with the vectors calculated by word2vec
        clusters : word2vec.WordClusters (optional)
            1d array with the clusters calculated by word2vec
        """
        self.vocab = vocab
        self.vectors = vectors
        self.clusters = clusters

        self.vocab_hash = {}
        for i, word in enumerate(vocab):
            self.vocab_hash[word] = i

    def ix(self, word):
        """
        Returns the index on self.vocab and `self.vectors` for `word`
        """
        return self.vocab_hash[word]

    def __getitem__(self, word):
        return self.get_vector(word)

    def __contains__(self, word):
        return word in self.vocab_hash

    def get_vector(self, word):
        """
        Returns the (vectors) vector for `word` in the vocabulary
        """
        idx = self.ix(word)
        return self.vectors[idx]

    def analogy(self, pos, neg, n=10):
        """
        Analogy similarity.
        Parameters
        ----------
        pos : list
        neg : list
        Returns
        -------
        2 numpy.array:
            1. position in self.vocab
            2. cosine similarity
        Example
        -------
            `king - man + woman = queen` will be:
            `pos=['king', 'woman'], neg=['man']`
        """
        exclude = pos + neg
        pos = [(word, 1.0) for word in pos]
        neg = [(word, -1.0) for word in neg]

        mean = []
        for word, direction in pos + neg:
            mean.append(direction * self[word])
        mean = np.array(mean).mean(axis=0)

        metrics = np.dot(self.vectors, mean)
        best = metrics.argsort()[::-1][:n + len(exclude)]

        exclude_idx = [np.where(best == self.ix(word)) for word in exclude if
                       self.ix(word) in best]
        new_best = np.delete(best, exclude_idx)
        best_metrics = metrics[new_best]
        return new_best[:n], best_metrics[:n]

    def generate_response(self, indexes, metrics, clusters=True):
        '''
        Generates a pure python (no numpy) response based on numpy arrays
        returned by `self.cosine` and `self.analogy`
        '''
        if self.clusters and clusters:
            return np.rec.fromarrays((self.vocab[indexes], metrics,
                                     self.clusters.clusters[indexes]),
                                     names=('word', 'metric', 'cluster'))
        else:
            return np.rec.fromarrays((self.vocab[indexes], metrics),
                                     names=('word', 'metric'))

    def to_mmap(self, fname):
        if not joblib:
            raise Exception("sklearn is needed to save as mmap")

        joblib.dump(self, fname)

    @classmethod
    def from_binary(cls, fname, vocabUnicodeSize=78, desired_vocab=None, encoding="utf-8"):
        """
        Create a WordVectors class based on a word2vec binary file
        Parameters
        ----------
        fname : path to file
        vocabUnicodeSize: the maximum string length (78, by default)
        desired_vocab: if set, this will ignore any word and vector that
                       doesn't fall inside desired_vocab.
        Returns
        -------
        WordVectors instance
        """
        with open(fname, 'rb') as fin:
            header = fin.readline()
            vocab_size, vector_size = list(map(int, header.split()))

            vocab = np.empty(vocab_size, dtype='<U%s' % vocabUnicodeSize)
            vectors = np.empty((vocab_size, vector_size), dtype=np.float)
            binary_len = np.dtype(np.float32).itemsize * vector_size
            for i in range(vocab_size):
                # read word
                word = b''
                while True:
                    ch = fin.read(1)
                    if ch == b' ':
                        break
                    word += ch
                include = desired_vocab is None or word in desired_vocab
                if include:
                    vocab[i] = word.decode(encoding)

                # read vector
                vector = np.fromstring(fin.read(binary_len), dtype=np.float32)
                if include:
                    vectors[i] = unitvec(vector)
                fin.read(1)  # newline

            if desired_vocab is not None:
                vectors = vectors[vocab != '', :]
                vocab = vocab[vocab != '']
        return cls(vocab=vocab, vectors=vectors)

    @classmethod
    def from_text(cls, fname, vocabUnicodeSize=78, desired_vocab=None, encoding="utf-8"):
        """
        Create a WordVectors class based on a word2vec text file
        Parameters
        ----------
        fname : path to file
        vocabUnicodeSize: the maximum string length (78, by default)
        desired_vocab: if set, this will ignore any word and vector that
                       doesn't fall inside desired_vocab.
        Returns
        -------
        WordVectors instance
        """
        with open(fname, 'rb') as fin:
            header = fin.readline()
            vocab_size, vector_size = list(map(int, header.split()))

            vocab = np.empty(vocab_size, dtype='<U%s' % vocabUnicodeSize)
            vectors = np.empty((vocab_size, vector_size), dtype=np.float)
            for i, line in enumerate(fin):
                line = line.decode(encoding).strip()
                parts = line.split(' ')
                word = parts[0]
                include = desired_vocab is None or word in desired_vocab
                if include:
                    vector = np.array(parts[1:], dtype=np.float)
                    vocab[i] = word
                    vectors[i] = unitvec(vector)

            if desired_vocab is not None:
                vectors = vectors[vocab != '', :]
                vocab = vocab[vocab != '']
        return cls(vocab=vocab, vectors=vectors)

    @classmethod
    def from_mmap(cls, fname):
        """
        Create a WordVectors class from a memory map
        Parameters
        ----------
        fname : path to file
        Returns
        -------
        WordVectors instance
        """
        memmaped = joblib.load(fname, mmap_mode='r+')
        return cls(vocab=memmaped.vocab, vectors=memmaped.vectors)
 */

pub struct WordVector {
    vocabulary: Vec<String>,
    vectors: Vec<Vec<f32>>,
    clusters: Option<Vec<String>>
}

impl WordVector{
	pub fn load_from_binary(file_name: &str) -> WordVector
	{
		let mut file = File::open(file_name).unwrap();
		let mut reader = BufReader::new(file);
		let mut header = String::new();
		reader.read_line(&mut header).unwrap();
		let mut header_info = header.split_whitespace().map(|x| x.parse::<usize>().unwrap()).take(2);
		let vocabulary_size = header_info.next().unwrap();
		let vector_size = header_info.next().unwrap();
		let vector_length: u64 = 4 * vector_size as u64;
		let mut vectors: Vec<Vec<f32>> = vec![Vec::new(); vector_size];
		let mut vocabulary = vec![String::new(); vocabulary_size];
		for i in 0..vocabulary_size{
			let mut word_bytes: Vec<u8> = Vec::new();
			let mut vector_bytes: Vec<u8> = Vec::new();
			reader.read_until(b' ', &mut word_bytes).unwrap();
			word_bytes.pop();
			let word = String::from_utf8(word_bytes).unwrap();
			vocabulary[i] = word;
			let mut current_vector = Vec::new();
			for j in 0..vector_size{
				let mut buf: [u8; 4] = [0; 4];
				reader.read(&mut buf);
				unsafe{
					let b = mem::transmute::<[u8; 4], f32>(buf);
					current_vector.push(b);
				}
			}
			vectors.push(current_vector);
			reader.seek(SeekFrom::Current(1));
		}
		WordVector{
			vocabulary: vocabulary,
			vectors: vectors,
			clusters: None
		}
	}

	pub fn get_index(&self, word: &str) -> Option<usize>
	{
		return self.vocabulary.iter().position(|x| x == word);
	}
	/*
	 def cosine(self, word, n=10):
        """
        Cosine similarity.
        metric = dot(vectors_of_vectors, vectors_of_target_vector)
        Uses a precomputed vectors of the vectors
        Parameters
        ----------
        word : string
        n : int, optional (default 10)
            number of neighbors to return
        Returns
        -------
        2 numpy.array:
            1. position in self.vocab
            2. cosine similarity
        """
        metrics = np.dot(self.vectors, self[word].T)
        best = np.argsort(metrics)[::-1][1:n+1]
        best_metrics = metrics[best]
        return best, best_metrics
	*/

}<|endoftext|>