<commit_before>#![allow(dead_code)]

extern crate rand;

use std::collections::HashMap;
use std::fmt;
use self::rand::{thread_rng, Rng};

#[derive(Debug)]
pub struct Sentence(Vec<String>);
pub type Prefix = (String, String);
#[derive(Debug)]
pub struct Database(HashMap<Prefix, Vec<String>>);

pub enum MarkovError {
  InsufficientLength,
  NoCompletion(Prefix)
}

impl fmt::Debug for MarkovError {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match *self {
      MarkovError::InsufficientLength => {
        write!(f, "Insufficient sentence length!")
      },

      MarkovError::NoCompletion(ref p) => {
        write!(f, "No completion available for (\"{}\", \"{}\")!", p.0, p.1)
      }
    }
  }
}

impl From<String> for Sentence {
  /// Transform a String first into a sequence of words, and then
  /// the Sentence type, by way of splitting on whitespace and
  /// and collecting as a Vec.
  fn from(sentence: String) -> Sentence {
    let words = sentence
      .split_whitespace()
      .map(|e| String::from(e))
      .collect::<Vec<String>>();

    Sentence(words)
  }
}

impl<'a> From<&'a str> for Sentence {
  /// Transform a &str into a sequence of words,
  /// and then the Sentence type.
  fn from(sentence: &'a str) -> Sentence {
    let words = sentence
      .split_whitespace()
      .map(|e| String::from(e))
      .collect::<Vec<String>>();

    Sentence(words)
  }
}

impl Clone for Sentence {
  fn clone(&self) -> Sentence {
    // Yes I'm meming in source code now.
    let ref insine = self.0;
    Sentence(insine.clone())
  }
}

impl Database {
  pub fn new() -> Database {
    Database(HashMap::<Prefix, Vec<String>>::new())
  }

  /// Take a Sentence and add it to the database for text generation.
  pub fn parse(&mut self, sen: Sentence) -> Result<(), MarkovError> {
    let Sentence(ref raw) = sen;

    // Be sure there's enough elements.
    if raw.len() < 3 {
      return Err(MarkovError::InsufficientLength)
    }

    // This sucks but I'm not sure there's a nicer way to do it.
    for ind in 1 .. (raw.len() - 1) {
      let prefix = (raw[ind - 1].clone(), raw[ind].clone());
      let next = raw[ind + 1].clone();

      if !self.0.contains_key(&prefix) {
        self.0.insert(prefix, vec![next]);
      }

      else {
        let mut existing = self.0.get_mut(&prefix).unwrap();
        existing.push(next);
      }
    }

    Ok(())
  }

  /// Get the completions for a Prefix.
  pub fn complete(&self, prefix: &Prefix) -> Option<&Vec<String>> {
    if let Some(value) = self.0.get(&prefix) {
      Some(value)
    }

    else {
      None
    }
  }

  /// Get a random completion for a Prefix.
  pub fn rand_complete(&self, prefix: &Prefix) -> Option<&String> {
    if let Some(completions) = self.0.get(&prefix) {
      thread_rng().choose(&completions)
    }

    else {
      None
    }
  }

  /// Generate some markov text starting from a Prefix.
  pub fn generate(&self, prefix: &Prefix, n: usize) -> Result<String, MarkovError> {
    let mut output = String::new();
    let mut generator: Prefix = prefix.clone();

    output.push_str(&*prefix.0);
    output.push(' ');
    output.push_str(&*prefix.1);

    for _ in 0..n {
      if let Some(word) = self.rand_complete(&generator) {
        output.push(' ');
        output.push_str(&*word);
        generator = (generator.1, word.clone())
      }

      else {
        if output.len() == 0 {
          return Err(MarkovError::NoCompletion(generator.clone()))
        }
      }
    }

    Ok(output)
  }
}
<commit_msg>Added prefix randomizer.<commit_after>#![allow(dead_code)]

extern crate rand;

use std::collections::HashMap;
use std::fmt;
use self::rand::{thread_rng, Rng};

#[derive(Debug)]
pub struct Sentence(Vec<String>);
pub type Prefix = (String, String);
#[derive(Debug)]
pub struct Database(HashMap<Prefix, Vec<String>>);

pub enum MarkovError {
  InsufficientLength,
  NoCompletion(Prefix)
}

impl fmt::Debug for MarkovError {
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    match *self {
      MarkovError::InsufficientLength => {
        write!(f, "Insufficient sentence length!")
      },

      MarkovError::NoCompletion(ref p) => {
        write!(f, "No completion available for (\"{}\", \"{}\")!", p.0, p.1)
      }
    }
  }
}

impl From<String> for Sentence {
  /// Transform a String first into a sequence of words, and then
  /// the Sentence type, by way of splitting on whitespace and
  /// and collecting as a Vec.
  fn from(sentence: String) -> Sentence {
    let words = sentence
      .split_whitespace()
      .map(|e| String::from(e))
      .collect::<Vec<String>>();

    Sentence(words)
  }
}

impl<'a> From<&'a str> for Sentence {
  /// Transform a &str into a sequence of words,
  /// and then the Sentence type.
  fn from(sentence: &'a str) -> Sentence {
    let words = sentence
      .split_whitespace()
      .map(|e| String::from(e))
      .collect::<Vec<String>>();

    Sentence(words)
  }
}

impl Clone for Sentence {
  fn clone(&self) -> Sentence {
    // Yes I'm meming in source code now.
    let ref insine = self.0;
    Sentence(insine.clone())
  }
}

impl Database {
  pub fn new() -> Database {
    Database(HashMap::<Prefix, Vec<String>>::new())
  }

  /// Take a Sentence and add it to the database for text generation.
  pub fn parse(&mut self, sen: Sentence) -> Result<(), MarkovError> {
    let Sentence(ref raw) = sen;

    // Be sure there's enough elements.
    if raw.len() < 3 {
      return Err(MarkovError::InsufficientLength)
    }

    // This sucks but I'm not sure there's a nicer way to do it.
    for ind in 1 .. (raw.len() - 1) {
      let prefix = (raw[ind - 1].clone(), raw[ind].clone());
      let next = raw[ind + 1].clone();

      if !self.0.contains_key(&prefix) {
        self.0.insert(prefix, vec![next]);
      }

      else {
        let mut existing = self.0.get_mut(&prefix).unwrap();
        existing.push(next);
      }
    }

    Ok(())
  }

  pub fn rand_prefix(&self) -> Option<Prefix> {
    if self.0.is_empty() {
      None
    }

    else {
      let mut rng = thread_rng();
      match rand::sample(&mut rng, self.0.iter(), 1).iter().nth(0) {
        Some(p) => Some(p.0.clone()),
        None => None
      }
    }
  }

  /// Get the completions for a Prefix.
  pub fn complete(&self, prefix: &Prefix) -> Option<&Vec<String>> {
    if let Some(value) = self.0.get(&prefix) {
      Some(value)
    }

    else {
      None
    }
  }

  /// Get a random completion for a Prefix.
  pub fn rand_complete(&self, prefix: &Prefix) -> Option<&String> {
    if let Some(completions) = self.0.get(&prefix) {
      thread_rng().choose(&completions)
    }

    else {
      None
    }
  }

  /// Generate some markov text starting from a Prefix.
  pub fn generate(&self, prefix: &Prefix, n: usize) -> Result<String, MarkovError> {
    let mut output = String::new();
    let mut generator: Prefix = prefix.clone();

    output.push_str(&*prefix.0);
    output.push(' ');
    output.push_str(&*prefix.1);

    for _ in 0..n {
      if let Some(word) = self.rand_complete(&generator) {
        output.push(' ');
        output.push_str(&*word);
        generator = (generator.1, word.clone())
      }

      else {
        if output.len() == 0 {
          return Err(MarkovError::NoCompletion(generator.clone()))
        }
      }
    }

    Ok(output)
  }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

use nom::{IResult, multispace};

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

#[derive(Debug, Clone)]
pub enum Sexp {
    String(String),
    List(Vec<Sexp>),
    Empty,
}

pub type ERes<T> = Result<T, String>;

impl Sexp {
    pub fn list(&self) -> ERes<&Vec<Sexp> > {
        match *self {
            Sexp::List(ref v) => Ok(v),
            ref x => Err(format!("not a list: {}", x))
        }
    }

    pub fn string(&self) -> ERes<&String> {
        match *self {
            Sexp::String(ref s) => Ok(s),
            ref x => Err(format!("not a string: {}", x))
        }
    }

    pub fn f(&self) -> ERes<f64> {
        let s = try!(self.string());
        match f64::from_str(&s) {
            Ok(f) => Ok(f),
            _ => Err(format!("Error parsing float"))
        }
    }

    pub fn i(&self) -> ERes<i64> {
        let s = try!(self.string());
        match i64::from_str(&s) {
            Ok(f) => Ok(f),
            _ => Err(format!("Error parsing int"))
        }
    }

    pub fn list_name(&self) -> ERes<&String> {
        let l = try!(self.list());
        let l = &l[..];
        let a = try!(l[0].string());
        Ok(a)
    }

    pub fn slice_atom(&self, s:&str) -> ERes<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return Err(format!("list doesn't start with {}, but with {}", s, st))
        };
        Ok(&v[1..])
    }
}

impl fmt::Display for Sexp {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Sexp::String(ref s) => {
                if s.contains("(") || s.contains(" ") {
                    write!(f,"\"{}\"", s)
                } else {
                    write!(f,"{}", s)
                }
            },
            Sexp::List(ref v) => {
                try!(write!(f, "("));
                for (i, x) in v.iter().enumerate() {
                    let s = if i == 0 { "" } else { " " };
                    try!(write!(f, "{}{}", s, x));
                }
                write!(f, ")")
            },
            Sexp::Empty => Ok(())
        }
    }
}

pub fn parse_str(sexp: &str) -> Result<Sexp, String> {
    if sexp.len() == 0 {
        return Ok(Sexp::Empty)
    }
    match parse_sexp(&sexp.as_bytes()[..]) {
        IResult::Done(_, c) => Ok(c),
        x          => Err(format!("parse error: {:?}", x))
    }
}

fn read_file(name: &str) -> Result<String, std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_file(name: &str) -> ERes<Sexp> {
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("{:?}", x))
    });
    parse_str(&s[..])
}

named!(parse_qstring<String>,
       map_res!(
           map_res!(
               delimited!(char!('\"'), is_not!("\""), char!('\"')),
               str::from_utf8),
           FromStr::from_str)
       );

named!(parse_bare_string<String>,
       map_res!(
           map_res!(
               is_not!(b")( \r\n"),
               str::from_utf8),
           FromStr::from_str)
       );

named!(parse_string<String>,
       alt!(parse_qstring | parse_bare_string)
       );

named!(parse_list<Vec<Sexp> >,
       chain!(
           char!('(') ~
           v: many0!(parse_sexp) ~
           char!(')'),
           || v)
       );

named!(parse_sexp<Sexp>,
       chain!(
           opt!(multispace) ~
           s: alt!(map!(parse_list,Sexp::List) | map!(parse_string,Sexp::String))
               ,|| s)
       );

// internal tests
#[test]
fn test_qstring1() {
    assert_eq!(parse_string(&b"\"hello world\""[..]), IResult::Done(&b""[..], String::from("hello world")));
}

#[test]
#[should_panic(expected="assertion failed: `(left == right)` (left: `Incomplete(Size(1))`, right: `Done([], \"hello\")`)")]
fn test_qstring2() {
    assert_eq!(parse_string(&b"\"hello"[..]), IResult::Done(&b""[..], String::from("hello")));
}

#[test]
fn test_string1() {
    assert_eq!(parse_string(&b"hello world"[..]), IResult::Done(&b" world"[..], String::from("hello")));
}

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

    #[allow(dead_code)]
    fn check_parse_res(s: &str, o:&str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", e);
        assert_eq!(o, t)
    }
    #[allow(dead_code)]
    fn check_parse(s: &str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", e);
        assert_eq!(s, t)
    }

    #[allow(dead_code)]
    fn parse_fail(s: &str) {
        parse_str(s).unwrap();
    }

    #[test]
    fn test_empty() { check_parse("") }

    #[test]
    fn test_minimal() { check_parse("()") }

    #[test]
    fn test_string() { check_parse("hello") }

    #[test]
    fn test_qstring_a() { check_parse_res("\"hello\"", "hello") }

    #[test]
    fn test_qstring_a2() { check_parse("\"hello world\"") }

    #[test]
    fn test_qstring_a3() { check_parse("\"hello(world)\"") }

    #[test]
    fn test_number() { check_parse("1.3") }

    #[test]
    fn test_float_vs_int() { check_parse("2.0") }

    #[test]
    fn test_double() { check_parse("(())") }

    #[test]
    fn test_br_string() { check_parse("(world)") }

    #[test]
    fn test_br_qstring() { check_parse_res("(\"world\")", "(world)") }

    #[test]
    fn test_br_int() { check_parse("(42)") }

    #[test]
    fn test_br_float() { check_parse("(12.7)") }

    #[test]
    fn test_br_qbrstring() { check_parse("(\"(()\")") }

    #[test]
    fn test_number_string() { check_parse("567A_WZ") }

    #[test]
    #[should_panic(expected="called `Result::unwrap()` on an `Err` value: \"parse error: Incomplete(Size(2))\"")]
    fn test_invalid1() { parse_fail("(") }

    #[test]
    #[should_panic(expected="called `Result::unwrap()` on an `Err` value: \"parse error: Error(Position(Alt, [41]))\"")]
    fn test_invalid2() { parse_fail(")") }

    #[test]
    #[should_panic(expected="called `Result::unwrap()` on an `Err` value: \"parse error: Incomplete(Size(1))\"")]
    fn test_invalid3() { parse_fail("\"hello") }

    #[test]
    fn test_complex() { check_parse("(module SWITCH_3W_SIDE_MMP221-R (layer F.Cu) (descr \"\") (pad 1 thru_hole rect (size 1.2 1.2) (at -2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 2 thru_hole rect (size 1.2 1.2) (at 0.0 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 3 thru_hole rect (size 1.2 1.2) (at 2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 5 thru_hole rect (size 1.2 1.2) (at 0.0 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 6 thru_hole rect (size 1.2 1.2) (at -2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 4 thru_hole rect (size 1.2 1.2) (at 2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (fp_line (start -4.5 -1.75) (end 4.5 -1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 -1.75) (end 4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 1.75) (end -4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start -4.5 1.75) (end -4.5 -1.75) (layer F.SilkS) (width 0.127)))") }
}

<commit_msg>error handling simplify<commit_after>#[macro_use]
extern crate nom;

use nom::{IResult, multispace};

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

#[derive(Debug, Clone)]
pub enum Sexp {
    String(String),
    List(Vec<Sexp>),
    Empty,
}

pub type ERes<T> = Result<T, String>;

impl Sexp {
    pub fn list(&self) -> ERes<&Vec<Sexp> > {
        match *self {
            Sexp::List(ref v) => Ok(v),
            ref x => Err(format!("not a list: {}", x))
        }
    }

    pub fn string(&self) -> ERes<&String> {
        match *self {
            Sexp::String(ref s) => Ok(s),
            ref x => Err(format!("not a string: {}", x))
        }
    }

    pub fn f(&self) -> ERes<f64> {
        let s = try!(self.string());
        match f64::from_str(&s) {
            Ok(f) => Ok(f),
            _ => Err(format!("Error parsing float"))
        }
    }

    pub fn i(&self) -> ERes<i64> {
        let s = try!(self.string());
        match i64::from_str(&s) {
            Ok(f) => Ok(f),
            _ => Err(format!("Error parsing int"))
        }
    }

    pub fn list_name(&self) -> ERes<&String> {
        let l = try!(self.list());
        let l = &l[..];
        let a = try!(l[0].string());
        Ok(a)
    }

    pub fn slice_atom(&self, s:&str) -> ERes<&[Sexp]> {
        let v = try!(self.list());
        let v2 =&v[..];
        let st = try!(v2[0].string());
        if st != s {
            return Err(format!("list doesn't start with {}, but with {}", s, st))
        };
        Ok(&v[1..])
    }
}

impl fmt::Display for Sexp {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Sexp::String(ref s) => {
                if s.contains("(") || s.contains(" ") {
                    write!(f,"\"{}\"", s)
                } else {
                    write!(f,"{}", s)
                }
            },
            Sexp::List(ref v) => {
                try!(write!(f, "("));
                for (i, x) in v.iter().enumerate() {
                    let s = if i == 0 { "" } else { " " };
                    try!(write!(f, "{}{}", s, x));
                }
                write!(f, ")")
            },
            Sexp::Empty => Ok(())
        }
    }
}

pub fn parse_str(sexp: &str) -> Result<Sexp, String> {
    if sexp.len() == 0 {
        return Ok(Sexp::Empty)
    }
    match parse_sexp(&sexp.as_bytes()[..]) {
        IResult::Done(_, c) => Ok(c),
        IResult::Error(x) => Err(format!("parse error: {:?}", x)),
        IResult::Incomplete(x) => Err(format!("incomplete: {:?}", x)),
    }
}

fn read_file(name: &str) -> Result<String, std::io::Error> {
    let mut f = try!(File::open(name));
    let mut s = String::new();
    try!(f.read_to_string(&mut s));
    Ok(s)
}

pub fn parse_file(name: &str) -> ERes<Sexp> {
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("{:?}", x))
    });
    parse_str(&s[..])
}

named!(parse_qstring<String>,
       map_res!(
           map_res!(
               delimited!(char!('\"'), is_not!("\""), char!('\"')),
               str::from_utf8),
           FromStr::from_str)
       );

named!(parse_bare_string<String>,
       map_res!(
           map_res!(
               is_not!(b")( \r\n"),
               str::from_utf8),
           FromStr::from_str)
       );

named!(parse_string<String>,
       alt!(parse_qstring | parse_bare_string)
       );

named!(parse_list<Vec<Sexp> >,
       chain!(
           char!('(') ~
           v: many0!(parse_sexp) ~
           char!(')'),
           || v)
       );

named!(parse_sexp<Sexp>,
       chain!(
           opt!(multispace) ~
           s: alt!(map!(parse_list,Sexp::List) | map!(parse_string,Sexp::String))
               ,|| s)
       );

// internal tests
#[test]
fn test_qstring1() {
    assert_eq!(parse_string(&b"\"hello world\""[..]), IResult::Done(&b""[..], String::from("hello world")));
}

#[test]
#[should_panic(expected="assertion failed: `(left == right)` (left: `Incomplete(Size(1))`, right: `Done([], \"hello\")`)")]
fn test_qstring2() {
    assert_eq!(parse_string(&b"\"hello"[..]), IResult::Done(&b""[..], String::from("hello")));
}

#[test]
fn test_string1() {
    assert_eq!(parse_string(&b"hello world"[..]), IResult::Done(&b" world"[..], String::from("hello")));
}

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

    #[allow(dead_code)]
    fn check_parse_res(s: &str, o:&str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", e);
        assert_eq!(o, t)
    }
    #[allow(dead_code)]
    fn check_parse(s: &str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", e);
        assert_eq!(s, t)
    }

    #[allow(dead_code)]
    fn parse_fail(s: &str) {
        parse_str(s).unwrap();
    }

    #[test]
    fn test_empty() { check_parse("") }

    #[test]
    fn test_minimal() { check_parse("()") }

    #[test]
    fn test_string() { check_parse("hello") }

    #[test]
    fn test_qstring_a() { check_parse_res("\"hello\"", "hello") }

    #[test]
    fn test_qstring_a2() { check_parse("\"hello world\"") }

    #[test]
    fn test_qstring_a3() { check_parse("\"hello(world)\"") }

    #[test]
    fn test_number() { check_parse("1.3") }

    #[test]
    fn test_float_vs_int() { check_parse("2.0") }

    #[test]
    fn test_double() { check_parse("(())") }

    #[test]
    fn test_br_string() { check_parse("(world)") }

    #[test]
    fn test_br_qstring() { check_parse_res("(\"world\")", "(world)") }

    #[test]
    fn test_br_int() { check_parse("(42)") }

    #[test]
    fn test_br_float() { check_parse("(12.7)") }

    #[test]
    fn test_br_qbrstring() { check_parse("(\"(()\")") }

    #[test]
    fn test_number_string() { check_parse("567A_WZ") }

    #[test]
    #[should_panic(expected="called `Result::unwrap()` on an `Err` value: \"incomplete: Size(2)\"")]
    fn test_invalid1() { parse_fail("(") }

    #[test]
    #[should_panic(expected="called `Result::unwrap()` on an `Err` value: \"parse error: Position(Alt, [41])\"")]
    fn test_invalid2() { parse_fail(")") }

    #[test]
    #[should_panic(expected="called `Result::unwrap()` on an `Err` value: \"incomplete: Size(1)\"")]
    fn test_invalid3() { parse_fail("\"hello") }

    #[test]
    fn test_complex() { check_parse("(module SWITCH_3W_SIDE_MMP221-R (layer F.Cu) (descr \"\") (pad 1 thru_hole rect (size 1.2 1.2) (at -2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 2 thru_hole rect (size 1.2 1.2) (at 0.0 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 3 thru_hole rect (size 1.2 1.2) (at 2.5 -1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 5 thru_hole rect (size 1.2 1.2) (at 0.0 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 6 thru_hole rect (size 1.2 1.2) (at -2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (pad 4 thru_hole rect (size 1.2 1.2) (at 2.5 1.6 0) (layers *.Cu *.Mask) (drill 0.8)) (fp_line (start -4.5 -1.75) (end 4.5 -1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 -1.75) (end 4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start 4.5 1.75) (end -4.5 1.75) (layer F.SilkS) (width 0.127)) (fp_line (start -4.5 1.75) (end -4.5 -1.75) (layer F.SilkS) (width 0.127)))") }
}

<|endoftext|>


<commit_before>use std::fs::File;
use std::io::Read;

const NEWLINE: u8 = 10;
const QUOTE: u8 = 34;
const COMMA: u8 = 44;

enum CSVState {
    Start,
    NonQuotedValue,
    NonQuotedQuote,
    QuotedValue,
    QuoteQuote,
    Error,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CSVError {
    pub line: i32,
    pub col: i32,
}

pub fn errors_for_csv(file: File) -> Vec<CSVError> {
    let mut state = CSVState::Start;
    let mut line = 1;
    let mut col = 0;

    let mut errors: Vec<CSVError> = Vec::new();

    for byte in file.bytes() {
        let b = byte.unwrap();

        match (&state, b) {
            // At the start of a field, are we a quoted field or not?
            (&CSVState::Start, QUOTE) => {
                state = CSVState::QuotedValue;
            },
            (&CSVState::Start, _) => {
                state = CSVState::NonQuotedValue;
            },

            // In a non-quoted field, watch for quotes
            (&CSVState::NonQuotedValue, COMMA) => {
                state = CSVState::Start;
            }
            (&CSVState::NonQuotedValue, NEWLINE) => {
                state = CSVState::Start;
            }
            (&CSVState::NonQuotedValue, QUOTE) => {
                state = CSVState::NonQuotedQuote;
            }

            // A quote in a non-quoted field needs a matching quote to
            // close it out.
            (&CSVState::NonQuotedQuote, QUOTE) => {
                state = CSVState::NonQuotedValue;
            }
            (&CSVState::NonQuotedQuote, COMMA) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Error;
            }
            (&CSVState::NonQuotedQuote, NEWLINE) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Start;
            }

            // In a quoted field, watch for quotes or newlines
            (&CSVState::QuotedValue, QUOTE) => {
                state = CSVState::QuoteQuote;
            },
            (&CSVState::QuotedValue, NEWLINE) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Start;
            },

            // A quote in a quote needs a quote immediately following
            // to be an escaped quote. If there's a comma or newline
            // following, it means that the field is done. Otherwise,
            // it's an error.
            (&CSVState::QuoteQuote, QUOTE) => {
                state = CSVState::QuotedValue;
            },
            (&CSVState::QuoteQuote, COMMA) => {
                state = CSVState::Start;
            },
            (&CSVState::QuoteQuote, NEWLINE) => {
                state = CSVState::Start;
            },
            (&CSVState::QuoteQuote, _) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Error;
            },

            // If we're in an error state, once we reach a newline, we
            // start over.
            (&CSVState::Error, NEWLINE) => {
                state = CSVState::Start;
            },
            _ => ()
        };

        if b == 10 {
            line = line + 1;
            col = 0;
        } else {
            col = col + 1;
        }
    }

    errors
}
<commit_msg>Handle DOS line endings (CRLF)<commit_after>use std::fs::File;
use std::io::Read;

const LF: u8 = 10;
const CR: u8 = 13;
const QUOTE: u8 = 34;
const COMMA: u8 = 44;

enum CSVState {
    Start,
    NonQuotedValue,
    NonQuotedQuote,
    QuotedValue,
    QuoteQuote,
    ExpectLF,
    Error,
}

#[derive(Debug, PartialEq, Eq)]
pub struct CSVError {
    pub line: i32,
    pub col: i32,
}

pub fn errors_for_csv(file: File) -> Vec<CSVError> {
    let mut state = CSVState::Start;
    let mut line = 1;
    let mut col = 0;

    let mut errors: Vec<CSVError> = Vec::new();

    for byte in file.bytes() {
        let b = byte.unwrap();

        match (&state, b) {
            // At the start of a field, are we a quoted field or not?
            (&CSVState::Start, QUOTE) => {
                state = CSVState::QuotedValue;
            },
            (&CSVState::Start, _) => {
                state = CSVState::NonQuotedValue;
            },

            // In a non-quoted field, watch for quotes
            (&CSVState::NonQuotedValue, COMMA) => {
                state = CSVState::Start;
            }
            (&CSVState::NonQuotedValue, CR) => {
                state = CSVState::ExpectLF;
            }
            (&CSVState::NonQuotedValue, LF) => {
                state = CSVState::Start;
            }
            (&CSVState::NonQuotedValue, QUOTE) => {
                state = CSVState::NonQuotedQuote;
            }

            // A quote in a non-quoted field needs a matching quote to
            // close it out.
            (&CSVState::NonQuotedQuote, QUOTE) => {
                state = CSVState::NonQuotedValue;
            }
            (&CSVState::NonQuotedQuote, COMMA) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Error;
            }
            (&CSVState::NonQuotedQuote, CR) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Start;
            }
            (&CSVState::NonQuotedQuote, LF) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Start;
            }

            // In a quoted field, watch for quotes or newlines
            (&CSVState::QuotedValue, QUOTE) => {
                state = CSVState::QuoteQuote;
            },
            (&CSVState::QuotedValue, CR) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Start;
            },
            (&CSVState::QuotedValue, LF) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Start;
            },

            // A quote in a quote needs a quote immediately following
            // to be an escaped quote. If there's a comma or newline
            // following, it means that the field is done. Otherwise,
            // it's an error.
            (&CSVState::QuoteQuote, QUOTE) => {
                state = CSVState::QuotedValue;
            },
            (&CSVState::QuoteQuote, COMMA) => {
                state = CSVState::Start;
            },
            (&CSVState::QuoteQuote, CR) => {
                state = CSVState::ExpectLF;
            },
            (&CSVState::QuoteQuote, LF) => {
                state = CSVState::Start;
            },
            (&CSVState::QuoteQuote, _) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Error;
            },

            // If we're looking at CR, we need a LF to follow
            (&CSVState::ExpectLF, LF) => {
                state = CSVState::Start;
            },
            (&CSVState::ExpectLF, _) => {
                errors.push(CSVError { line: line, col: col });
                state = CSVState::Error;
            },

            // If we're in an error state, once we reach a newline, we
            // start over.
            (&CSVState::Error, LF) => {
                state = CSVState::Start;
            },
            _ => ()
        };

        if b == 10 {
            line = line + 1;
            col = 0;
        } else {
            col = col + 1;
        }
    }

    errors
}
<|endoftext|>


<commit_before>//! Rust bindings to the libcurl C library
//!
//! This crate contains bindings for an HTTP/HTTPS client which is powered by
//! [libcurl], the same library behind the `curl` command line tool. The API
//! currently closely matches that of libcurl itself, except that a Rustic layer
//! of safety is applied on top.
//!
//! [libcurl]: https://curl.haxx.se/libcurl/
//!
//! # The "Easy" API
//!
//! The easiest way to send a request is to use the `Easy` api which corresponds
//! to `CURL` in libcurl. This handle supports a wide variety of options and can
//! be used to make a single blocking request in a thread. Callbacks can be
//! specified to deal with data as it arrives and a handle can be reused to
//! cache connections and such.
//!
//! ```rust,no_run
//! use std::io::{stdout, Write};
//!
//! use curl::easy::Easy;
//!
//! // Write the contents of rust-lang.org to stdout
//! let mut easy = Easy::new();
//! easy.url("https://www.rust-lang.org/").unwrap();
//! easy.write_function(|data| {
//!     stdout().write_all(data).unwrap();
//!     Ok(data.len())
//! }).unwrap();
//! easy.perform().unwrap();
//! ```
//!
//! # What about multiple concurrent HTTP requests?
//!
//! One option you have currently is to send multiple requests in multiple
//! threads, but otherwise libcurl has a "multi" interface for doing this
//! operation. Initial bindings of this interface can be found in the `multi`
//! module, but feedback is welcome!
//!
//! # Where does libcurl come from?
//!
//! This crate links to the `curl-sys` crate which is in turn responsible for
//! acquiring and linking to the libcurl library. Currently this crate will
//! build libcurl from source if one is not already detected on the system.
//!
//! There is a large number of releases for libcurl, all with different sets of
//! capabilities. Robust programs may wish to inspect `Version::get()` to test
//! what features are implemented in the linked build of libcurl at runtime.
//!
//! # Initialization
//!
//! The underlying libcurl library must be initialized before use and has
//! certain requirements on how this is done. Check the documentation for
//! [`init`] for more details.

#![deny(missing_docs, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/curl/0.4")]

use std::ffi::CStr;
use std::str;
use std::sync::Once;

pub use crate::error::{Error, FormError, MultiError, ShareError};
mod error;

pub use crate::version::{Protocols, Version};
mod version;

pub mod easy;
pub mod multi;
mod panic;

/// Initializes the underlying libcurl library.
///
/// The underlying libcurl library must be initialized before use, and must be
/// done so on the main thread before any other threads are created by the
/// program. This crate will do this for you automatically in the following
/// scenarios:
///
/// - Creating a new [`Easy`][easy::Easy] or [`Multi`][multi::Multi] handle
/// - At program startup on Windows, macOS, Linux, Android, or FreeBSD systems
///
/// This should be sufficient for most applications and scenarios, but in any
/// other case, it is strongly recommended that you call this function manually
/// as soon as your program starts.
///
/// Calling this function more than once is harmless and has no effect.
#[inline]
pub fn init() {
    /// Used to prevent concurrent or duplicate initialization.
    static INIT: Once = Once::new();

    /// An exported constructor function. On supported platforms, this will be
    /// invoked automatically before the program's `main` is called.
    #[cfg_attr(
        any(target_os = "linux", target_os = "freebsd", target_os = "android"),
        link_section = ".init_array"
    )]
    #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
    #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
    static INIT_CTOR: extern "C" fn() = init_inner;

    /// This is the body of our constructor function.
    #[cfg_attr(
        any(target_os = "linux", target_os = "android"),
        link_section = ".text.startup"
    )]
    extern "C" fn init_inner() {
        INIT.call_once(|| {
            #[cfg(need_openssl_init)]
            openssl_sys::init();

            unsafe {
                assert_eq!(curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL), 0);
            }

            // Note that we explicitly don't schedule a call to
            // `curl_global_cleanup`. The documentation for that function says
            //
            // > You must not call it when any other thread in the program (i.e.
            // > a thread sharing the same memory) is running. This doesn't just
            // > mean no other thread that is using libcurl.
            //
            // We can't ever be sure of that, so unfortunately we can't call the
            // function.
        });
    }

    // We invoke our init function through our static to ensure the symbol isn't
    // optimized away by a bug: https://github.com/rust-lang/rust/issues/47384
    INIT_CTOR();
}

unsafe fn opt_str<'a>(ptr: *const libc::c_char) -> Option<&'a str> {
    if ptr.is_null() {
        None
    } else {
        Some(str::from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap())
    }
}

fn cvt(r: curl_sys::CURLcode) -> Result<(), Error> {
    if r == curl_sys::CURLE_OK {
        Ok(())
    } else {
        Err(Error::new(r))
    }
}
<commit_msg>Initialize openssl-probe env vars if curl requires init (#418)<commit_after>//! Rust bindings to the libcurl C library
//!
//! This crate contains bindings for an HTTP/HTTPS client which is powered by
//! [libcurl], the same library behind the `curl` command line tool. The API
//! currently closely matches that of libcurl itself, except that a Rustic layer
//! of safety is applied on top.
//!
//! [libcurl]: https://curl.haxx.se/libcurl/
//!
//! # The "Easy" API
//!
//! The easiest way to send a request is to use the `Easy` api which corresponds
//! to `CURL` in libcurl. This handle supports a wide variety of options and can
//! be used to make a single blocking request in a thread. Callbacks can be
//! specified to deal with data as it arrives and a handle can be reused to
//! cache connections and such.
//!
//! ```rust,no_run
//! use std::io::{stdout, Write};
//!
//! use curl::easy::Easy;
//!
//! // Write the contents of rust-lang.org to stdout
//! let mut easy = Easy::new();
//! easy.url("https://www.rust-lang.org/").unwrap();
//! easy.write_function(|data| {
//!     stdout().write_all(data).unwrap();
//!     Ok(data.len())
//! }).unwrap();
//! easy.perform().unwrap();
//! ```
//!
//! # What about multiple concurrent HTTP requests?
//!
//! One option you have currently is to send multiple requests in multiple
//! threads, but otherwise libcurl has a "multi" interface for doing this
//! operation. Initial bindings of this interface can be found in the `multi`
//! module, but feedback is welcome!
//!
//! # Where does libcurl come from?
//!
//! This crate links to the `curl-sys` crate which is in turn responsible for
//! acquiring and linking to the libcurl library. Currently this crate will
//! build libcurl from source if one is not already detected on the system.
//!
//! There is a large number of releases for libcurl, all with different sets of
//! capabilities. Robust programs may wish to inspect `Version::get()` to test
//! what features are implemented in the linked build of libcurl at runtime.
//!
//! # Initialization
//!
//! The underlying libcurl library must be initialized before use and has
//! certain requirements on how this is done. Check the documentation for
//! [`init`] for more details.

#![deny(missing_docs, missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/curl/0.4")]

use std::ffi::CStr;
use std::str;
use std::sync::Once;

pub use crate::error::{Error, FormError, MultiError, ShareError};
mod error;

pub use crate::version::{Protocols, Version};
mod version;

pub mod easy;
pub mod multi;
mod panic;

/// Initializes the underlying libcurl library.
///
/// The underlying libcurl library must be initialized before use, and must be
/// done so on the main thread before any other threads are created by the
/// program. This crate will do this for you automatically in the following
/// scenarios:
///
/// - Creating a new [`Easy`][easy::Easy] or [`Multi`][multi::Multi] handle
/// - At program startup on Windows, macOS, Linux, Android, or FreeBSD systems
///
/// This should be sufficient for most applications and scenarios, but in any
/// other case, it is strongly recommended that you call this function manually
/// as soon as your program starts.
///
/// Calling this function more than once is harmless and has no effect.
#[inline]
pub fn init() {
    /// Used to prevent concurrent or duplicate initialization.
    static INIT: Once = Once::new();

    /// An exported constructor function. On supported platforms, this will be
    /// invoked automatically before the program's `main` is called.
    #[cfg_attr(
        any(target_os = "linux", target_os = "freebsd", target_os = "android"),
        link_section = ".init_array"
    )]
    #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
    #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
    static INIT_CTOR: extern "C" fn() = init_inner;

    /// This is the body of our constructor function.
    #[cfg_attr(
        any(target_os = "linux", target_os = "android"),
        link_section = ".text.startup"
    )]
    extern "C" fn init_inner() {
        INIT.call_once(|| {
            #[cfg(need_openssl_init)]
            openssl_probe::init_ssl_cert_env_vars();
            #[cfg(need_openssl_init)]
            openssl_sys::init();

            unsafe {
                assert_eq!(curl_sys::curl_global_init(curl_sys::CURL_GLOBAL_ALL), 0);
            }

            // Note that we explicitly don't schedule a call to
            // `curl_global_cleanup`. The documentation for that function says
            //
            // > You must not call it when any other thread in the program (i.e.
            // > a thread sharing the same memory) is running. This doesn't just
            // > mean no other thread that is using libcurl.
            //
            // We can't ever be sure of that, so unfortunately we can't call the
            // function.
        });
    }

    // We invoke our init function through our static to ensure the symbol isn't
    // optimized away by a bug: https://github.com/rust-lang/rust/issues/47384
    INIT_CTOR();
}

unsafe fn opt_str<'a>(ptr: *const libc::c_char) -> Option<&'a str> {
    if ptr.is_null() {
        None
    } else {
        Some(str::from_utf8(CStr::from_ptr(ptr).to_bytes()).unwrap())
    }
}

fn cvt(r: curl_sys::CURLcode) -> Result<(), Error> {
    if r == curl_sys::CURLE_OK {
        Ok(())
    } else {
        Err(Error::new(r))
    }
}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![feature(core)]
#![feature(unsafe_destructor)]
#![warn(missing_docs)]

//! Synchronization primitives based on spinning

#![no_std]

#[cfg(test)]
extern crate std;

#[macro_use]
extern crate core;

pub use mutex::*;
pub use rw_lock::*;

mod mutex;
mod rw_lock;

#[cfg(not(test))]
mod std {
    pub use core::*;
}
<commit_msg>Use no_std feature<commit_after>#![crate_type = "lib"]
#![feature(core)]
#![feature(no_std, unsafe_destructor)]
#![warn(missing_docs)]

//! Synchronization primitives based on spinning

#![no_std]

#[cfg(test)]
extern crate std;

#[macro_use]
extern crate core;

pub use mutex::*;
pub use rw_lock::*;

mod mutex;
mod rw_lock;

#[cfg(not(test))]
mod std {
    pub use core::*;
}
<|endoftext|>


<commit_before>#![crate_name = "shader_version"]
#![deny(missing_docs)]
#![feature(globs)]

//! A helper library for detecting and picking compatible shaders.

pub mod opengl;
pub mod glsl;

<commit_msg>Reexported `OpenGL` at top level<commit_after>#![crate_name = "shader_version"]
#![deny(missing_docs)]
#![feature(globs)]

//! A helper library for detecting and picking compatible shaders.

pub use opengl::OpenGL;

pub mod opengl;
pub mod glsl;

<|endoftext|>


<commit_before>//! Crate `etcd` provides a client for [etcd](https://github.com/coreos/etcd), a distributed
//! key-value store from [CoreOS](https://coreos.com/).
//!
//! The client uses etcd's v2 API. Support for the v3 API is planned, and will be added via
//! separate types for backwards compatibility and to support both APIs simultaneously.
//!
//! The client uses asynchronous I/O, backed by the `futures` and `tokio-core` crates, and requires
//! both to be used alongside. Functions that return futures currently return them boxed. As soon
//! as Rust's [impl Trait](https://github.com/rust-lang/rust/issues/34511) feature is stabilized,
//! this crate's API will be updated to use it.
//!
//! The client is thoroughly tested against etcd 2.3.7.
//!
//! # Usage
//!
//! `Client` is an HTTP client required for all API calls. It can be constructed to use HTTP or
//! HTTPS, and supports authenticating to the etcd cluster via HTTP basic authentication (username
//! and password) and/or X.509 client certificates.
//!
//! To get basic information about the versions of etcd running in a cluster, use the
//! `Client::versions` method. All other API calls are made by passing a `Client` reference to the
//! functions in the `kv` and `stats` modules. These modules contain functions for API calls to the
//! primary key-value store API and statistics API, respectively. The membership and
//! authentication APIs are not yet supported, but planned.
//!
//! # Examples
//!
//! Basic usage:
//!
//! ```no_run
//! extern crate etcd;
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use etcd::Client;
//! use etcd::kv::{self, Action};
//! use futures::Future;
//! use tokio_core::reactor::Core;
//!
//! fn main() {
//!     // Create a `Core`, which is the event loop which will drive futures to completion.
//!     let mut core = Core::new().unwrap();
//!     // Get a "handle" to the event loop that the client can use to schedule work.
//!     let handle = core.handle();
//!
//!     // Create a client to access a single cluster member. Addresses of multiple cluster
//!     // members can be provided and the client will try each one in sequence until it
//!     // receives a successful response.
//!     let client = Client::new(&handle, &["http://etcd.example.com:2379"], None).unwrap();
//!
//!     // Set the key "/foo" to the value "bar" with no expiration.
//!     let work = kv::set(&client, "/foo", "bar", None).and_then(|_| {
//!         // Once the key has been set, ask for details about it.
//!         let get_request = kv::get(&client, "/foo", kv::GetOptions::default());
//!
//!         get_request.and_then(|response| {
//!             // The information returned tells you what kind of operation was performed.
//!             assert_eq!(response.data.action, Action::Get);
//!
//!             // The value of the key is what we set it to previously.
//!             assert_eq!(response.data.node.value, Some("bar".to_string()));
//!
//!             // Each API call also returns information about the etcd cluster extracted from
//!             // HTTP response headers.
//!             assert!(response.cluster_info.etcd_index.is_some());
//!
//!             Ok(())
//!         })
//!     });
//!
//!     // Start the event loop, driving the asynchronous code to completion.
//!     core.run(work).unwrap();
//! }
//! ```
//!
//! # Cargo features
//!
//! Crate `etcd` has one Cargo feature, `tls`, which adds HTTPS support via the `Client::https`
//! constructor. This feature is enabled by default.

#![deny(missing_debug_implementations, missing_docs, warnings)]

extern crate futures;
#[macro_use]
extern crate hyper;
#[cfg(feature = "tls")]
extern crate hyper_tls;
#[cfg(feature = "tls")]
extern crate native_tls;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate tokio_timer;
extern crate url;

pub use client::{BasicAuth, Client, ClusterInfo, Health, Response};
pub use error::{ApiError, Error};
pub use version::VersionInfo;

pub mod kv;
pub mod members;
pub mod stats;

mod async;
mod client;
mod error;
mod http;
mod options;
mod version;
<commit_msg>Update some documentation.<commit_after>//! Crate `etcd` provides a client for [etcd](https://github.com/coreos/etcd), a distributed
//! key-value store from [CoreOS](https://coreos.com/).
//!
//! The client uses etcd's v2 API. Support for the v3 API is planned, and will be added via
//! separate types for backwards compatibility and to support both APIs simultaneously.
//!
//! The client uses asynchronous I/O, backed by the `futures` and `tokio-core` crates, and requires
//! both to be used alongside. Functions that return futures currently return them boxed. As soon
//! as Rust's [impl Trait](https://github.com/rust-lang/rust/issues/34511) feature is stabilized,
//! this crate's API will be updated to use it.
//!
//! The client is tested against etcd 2.3.7.
//!
//! # Usage
//!
//! `Client` is an HTTP client required for all API calls. It can be constructed to use HTTP or
//! HTTPS, and supports authenticating to the etcd cluster via HTTP basic authentication (username
//! and password) and/or X.509 client certificates.
//!
//! To get basic information about the versions of etcd running in a cluster, use the
//! `Client::versions` method. All other API calls are made by passing a `Client` reference to the
//! functions in the `kv`, `members`, and `stats` modules. These modules contain functions for API
//! calls to the primary key-value store API, the cluster membership API, and statistics API,
//! respectively. The authentication API is not yet supported, but planned.
//!
//! # Examples
//!
//! Basic usage:
//!
//! ```no_run
//! extern crate etcd;
//! extern crate futures;
//! extern crate tokio_core;
//!
//! use etcd::Client;
//! use etcd::kv::{self, Action};
//! use futures::Future;
//! use tokio_core::reactor::Core;
//!
//! fn main() {
//!     // Create a `Core`, which is the event loop which will drive futures to completion.
//!     let mut core = Core::new().unwrap();
//!     // Get a "handle" to the event loop that the client can use to schedule work.
//!     let handle = core.handle();
//!
//!     // Create a client to access a single cluster member. Addresses of multiple cluster
//!     // members can be provided and the client will try each one in sequence until it
//!     // receives a successful response.
//!     let client = Client::new(&handle, &["http://etcd.example.com:2379"], None).unwrap();
//!
//!     // Set the key "/foo" to the value "bar" with no expiration.
//!     let work = kv::set(&client, "/foo", "bar", None).and_then(|_| {
//!         // Once the key has been set, ask for details about it.
//!         let get_request = kv::get(&client, "/foo", kv::GetOptions::default());
//!
//!         get_request.and_then(|response| {
//!             // The information returned tells you what kind of operation was performed.
//!             assert_eq!(response.data.action, Action::Get);
//!
//!             // The value of the key is what we set it to previously.
//!             assert_eq!(response.data.node.value, Some("bar".to_string()));
//!
//!             // Each API call also returns information about the etcd cluster extracted from
//!             // HTTP response headers.
//!             assert!(response.cluster_info.etcd_index.is_some());
//!
//!             Ok(())
//!         })
//!     });
//!
//!     // Start the event loop, driving the asynchronous code to completion.
//!     core.run(work).unwrap();
//! }
//! ```
//!
//! # Cargo features
//!
//! Crate `etcd` has one Cargo feature, `tls`, which adds HTTPS support via the `Client::https`
//! constructor. This feature is enabled by default.

#![deny(missing_debug_implementations, missing_docs, warnings)]

extern crate futures;
#[macro_use]
extern crate hyper;
#[cfg(feature = "tls")]
extern crate hyper_tls;
#[cfg(feature = "tls")]
extern crate native_tls;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate tokio_core;
extern crate tokio_timer;
extern crate url;

pub use client::{BasicAuth, Client, ClusterInfo, Health, Response};
pub use error::{ApiError, Error};
pub use version::VersionInfo;

pub mod kv;
pub mod members;
pub mod stats;

mod async;
mod client;
mod error;
mod http;
mod options;
mod version;
<|endoftext|>


<commit_before>use components::{Attribute, ConstantPoolItem, Field, Method, Utf8Info};
use primitives::{PrimitiveIterator, U1, U2, U4};

use std::fs::File;
use std::io::{Error as IoError, Read};
use std::rc::Rc;
use std::string::FromUtf8Error;

pub mod components;
pub mod primitives;

pub type ParserResult<T> = Result<T, ParserError>;

#[derive(Debug)]
pub enum ParserError {
    UnknownConstantPoolTag(U1),
    UnexpectedConstantPoolItem(&'static str),
    ConstantPoolIndexOutOfBounds(usize),
    InvalidUtf8(FromUtf8Error),
    Io(IoError),
}

impl From<IoError> for ParserError {
    fn from(error: IoError) -> ParserError {
        ParserError::Io(error)
    }
}

impl From<FromUtf8Error> for ParserError {
    fn from(error: FromUtf8Error) -> ParserError {
        ParserError::InvalidUtf8(error)
    }
}

macro_rules! populate_vec {
    ($length:ident, $supplier:expr) => {
        {
            let mut temp_vec = vec![];
            for _ in 0..$length {
                temp_vec.push(try!($supplier));
            }

            temp_vec
        }
    }
}

macro_rules! rc_populate_vec {
    ($length:ident, $supplier:expr) => {
        {
            let mut temp_vec = vec![];
            for _ in 0..$length {
                temp_vec.push(Rc::new(try!($supplier)));
            }

            temp_vec
        }
    }
}

#[derive(Debug)]
pub struct ClassFile {
    pub magic: U4,
    pub minor_version: U2,
    pub major_version: U2,
    pub constant_pool_count: U2,
    pub constant_pool: Vec<ConstantPoolItem>,
    pub access_flags: U2,
    pub this_class: U2,
    pub super_class: U2,
    pub interfaces_count: U2,
    pub interfaces: Vec<U2>,
    pub fields_count: U2,
    pub fields: Vec<Rc<Field>>,
    pub methods_count: U2,
    pub methods: Vec<Rc<Method>>,
    pub attributes_count: U2,
    pub attributes: Vec<Rc<Attribute>>,
}

impl ClassFile {
    pub fn from(file: File) -> ParserResult<ClassFile> {
        let mut bytes = file.bytes();

        let magic = try!(bytes.next_u4());
        let minor_version = try!(bytes.next_u2());
        let major_version = try!(bytes.next_u2());

        let constant_pool_count = try!(bytes.next_u2());
        let actual_constant_pool_count = constant_pool_count - 1;
        let constant_pool = populate_vec!(actual_constant_pool_count,
                                          ConstantPoolItem::from(&mut bytes));

        let access_flags = try!(bytes.next_u2());
        let this_class = try!(bytes.next_u2());
        let super_class = try!(bytes.next_u2());

        let interfaces_count = try!(bytes.next_u2());
        let interfaces = populate_vec!(interfaces_count, bytes.next_u2());

        let fields_count = try!(bytes.next_u2());
        let fields = rc_populate_vec!(fields_count, Field::from(&mut bytes, &constant_pool));

        let methods_count = try!(bytes.next_u2());
        let methods = rc_populate_vec!(methods_count, Method::from(&mut bytes, &constant_pool));

        let attributes_count = try!(bytes.next_u2());
        let attributes = rc_populate_vec!(attributes_count,
                                          Attribute::from(&mut bytes, &constant_pool));

        Ok(ClassFile {
            magic: magic,
            minor_version: minor_version,
            major_version: major_version,
            constant_pool_count: constant_pool_count,
            constant_pool: constant_pool,
            access_flags: access_flags,
            this_class: this_class,
            super_class: super_class,
            interfaces_count: interfaces_count,
            interfaces: interfaces,
            fields_count: fields_count,
            fields: fields,
            methods_count: methods_count,
            methods: methods,
            attributes_count: attributes_count,
            attributes: attributes,
        })
    }

    pub fn classname(&self) -> ParserResult<Rc<Utf8Info>> {
        let this_class = self.this_class;
        let constant_pool = &self.constant_pool;

        let class_info = try!(ConstantPoolItem::retrieve_class_info(this_class as usize,
                                                                    constant_pool));
        let utf8_info = try!(ConstantPoolItem::retrieve_utf8_info(class_info.name_index as usize,
                                                                  constant_pool));

        Ok(utf8_info)
    }

    pub fn maybe_resolve_main_method(&self) -> Option<Rc<Method>> {
        for method in &self.methods {
            if method.name.eq("main") {
                return Some(method.clone());
            }
        }

        None
    }
}

#[cfg(test)]
mod tests {

    extern crate spectral;

    use self::spectral::prelude::*;

    use super::ClassFile;
    use super::components::{Attribute, AccessFlags, ConstantPoolItem};

    use std::fs::File;
    use std::path::PathBuf;

    const MANIFEST_DIR: &'static str = env!("CARGO_MANIFEST_DIR");

    #[test]
    fn can_successfully_parse_magic() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.magic).is_equal_to(&0xCAFEBABE);
    }

    #[test]
    fn can_successfully_parse_version() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.minor_version).is_equal_to(&0);
        assert_that(&classfile.major_version).is_equal_to(&52);
    }

    #[test]
    fn can_successfully_parse_constant_pool() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.constant_pool_count).is_equal_to(&26);
        assert_that(&classfile.constant_pool).has_length(25);
    }

    #[test]
    fn can_successfully_parse_access_flags() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        let access_flags = classfile.access_flags;
        asserting("class is public")
            .that(&access_flags)
            .matches(|val| AccessFlags::is_public(*val));
        asserting("class is super").that(&access_flags).matches(|val| AccessFlags::is_super(*val));
    }

    #[test]
    fn can_successfully_parse_class_references() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        let this_class = classfile.this_class;
        let super_class = classfile.super_class;
        let constant_pool = classfile.constant_pool;

        assert_that(&ConstantPoolItem::retrieve_class_info(this_class as usize, &constant_pool))
            .is_ok();
        assert_that(&ConstantPoolItem::retrieve_class_info(super_class as usize, &constant_pool))
            .is_ok();
    }

    #[test]
    fn can_successfully_parse_interfaces() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.interfaces_count).is_equal_to(&0);
        assert_that(&classfile.interfaces).has_length(0);
    }

    #[test]
    fn can_successfully_parse_fields() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.fields_count).is_equal_to(&0);
        assert_that(&classfile.fields).has_length(0);
    }

    #[test]
    fn can_successfully_parse_methods() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.methods_count).is_equal_to(&3);
        assert_that(&classfile.methods)
            .has_length(3)
            .mapped_contains(|val| &**val.name, &"<init>")
            .mapped_contains(|val| &**val.name, &"main")
            .mapped_contains(|val| &**val.name, &"println");

        let method_attributes: Vec<_> =
            classfile.methods.iter().flat_map(|val| &val.attributes).collect();
        asserting("at least one method has the code attribute")
            .that(&method_attributes)
            .matching_contains(|val| match ***val {
                Attribute::Code(..) => true,
                _ => false,
            });
    }

    #[test]
    fn can_successfully_parse_class_attributes() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.attributes_count).is_equal_to(&1);
        assert_that(&classfile.attributes).has_length(1);
    }

    #[test]
    fn can_resolve_main_method_if_present() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.maybe_resolve_main_method()).is_some();
    }

    #[test]
    fn can_retrieve_classname() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        let classname = classfile.classname().unwrap();
        assert_that(&classname.to_string()).is_equal_to(&"HelloWorld".to_string());
    }

    fn open_test_resource(resource_path: &str) -> File {
        let mut file_path = PathBuf::from(MANIFEST_DIR);
        file_path.push("test-resources/");
        file_path.push(resource_path);

        File::open(file_path).unwrap()
    }

}
<commit_msg>Can now pass in any method name to be resolved<commit_after>use components::{Attribute, ConstantPoolItem, Field, Method, Utf8Info};
use primitives::{PrimitiveIterator, U1, U2, U4};

use std::fs::File;
use std::io::{Error as IoError, Read};
use std::rc::Rc;
use std::string::FromUtf8Error;

pub mod components;
pub mod primitives;

pub type ParserResult<T> = Result<T, ParserError>;

#[derive(Debug)]
pub enum ParserError {
    UnknownConstantPoolTag(U1),
    UnexpectedConstantPoolItem(&'static str),
    ConstantPoolIndexOutOfBounds(usize),
    InvalidUtf8(FromUtf8Error),
    Io(IoError),
}

impl From<IoError> for ParserError {
    fn from(error: IoError) -> ParserError {
        ParserError::Io(error)
    }
}

impl From<FromUtf8Error> for ParserError {
    fn from(error: FromUtf8Error) -> ParserError {
        ParserError::InvalidUtf8(error)
    }
}

macro_rules! populate_vec {
    ($length:ident, $supplier:expr) => {
        {
            let mut temp_vec = vec![];
            for _ in 0..$length {
                temp_vec.push(try!($supplier));
            }

            temp_vec
        }
    }
}

macro_rules! rc_populate_vec {
    ($length:ident, $supplier:expr) => {
        {
            let mut temp_vec = vec![];
            for _ in 0..$length {
                temp_vec.push(Rc::new(try!($supplier)));
            }

            temp_vec
        }
    }
}

#[derive(Debug)]
pub struct ClassFile {
    pub magic: U4,
    pub minor_version: U2,
    pub major_version: U2,
    pub constant_pool_count: U2,
    pub constant_pool: Vec<ConstantPoolItem>,
    pub access_flags: U2,
    pub this_class: U2,
    pub super_class: U2,
    pub interfaces_count: U2,
    pub interfaces: Vec<U2>,
    pub fields_count: U2,
    pub fields: Vec<Rc<Field>>,
    pub methods_count: U2,
    pub methods: Vec<Rc<Method>>,
    pub attributes_count: U2,
    pub attributes: Vec<Rc<Attribute>>,
}

impl ClassFile {
    pub fn from(file: File) -> ParserResult<ClassFile> {
        let mut bytes = file.bytes();

        let magic = try!(bytes.next_u4());
        let minor_version = try!(bytes.next_u2());
        let major_version = try!(bytes.next_u2());

        let constant_pool_count = try!(bytes.next_u2());
        let actual_constant_pool_count = constant_pool_count - 1;
        let constant_pool = populate_vec!(actual_constant_pool_count,
                                          ConstantPoolItem::from(&mut bytes));

        let access_flags = try!(bytes.next_u2());
        let this_class = try!(bytes.next_u2());
        let super_class = try!(bytes.next_u2());

        let interfaces_count = try!(bytes.next_u2());
        let interfaces = populate_vec!(interfaces_count, bytes.next_u2());

        let fields_count = try!(bytes.next_u2());
        let fields = rc_populate_vec!(fields_count, Field::from(&mut bytes, &constant_pool));

        let methods_count = try!(bytes.next_u2());
        let methods = rc_populate_vec!(methods_count, Method::from(&mut bytes, &constant_pool));

        let attributes_count = try!(bytes.next_u2());
        let attributes = rc_populate_vec!(attributes_count,
                                          Attribute::from(&mut bytes, &constant_pool));

        Ok(ClassFile {
            magic: magic,
            minor_version: minor_version,
            major_version: major_version,
            constant_pool_count: constant_pool_count,
            constant_pool: constant_pool,
            access_flags: access_flags,
            this_class: this_class,
            super_class: super_class,
            interfaces_count: interfaces_count,
            interfaces: interfaces,
            fields_count: fields_count,
            fields: fields,
            methods_count: methods_count,
            methods: methods,
            attributes_count: attributes_count,
            attributes: attributes,
        })
    }

    pub fn classname(&self) -> ParserResult<Rc<Utf8Info>> {
        let this_class = self.this_class;
        let constant_pool = &self.constant_pool;

        let class_info = try!(ConstantPoolItem::retrieve_class_info(this_class as usize,
                                                                    constant_pool));
        let utf8_info = try!(ConstantPoolItem::retrieve_utf8_info(class_info.name_index as usize,
                                                                  constant_pool));

        Ok(utf8_info)
    }

    pub fn maybe_resolve_main_method(&self) -> Option<Rc<Method>> {
        self.maybe_resolve_method(&"main")
    }

    pub fn maybe_resolve_method(&self, name: &str) -> Option<Rc<Method>> {
        for method in &self.methods {
            if method.name.eq(name) {
                return Some(method.clone());
            }
        }

        None
    }
}

#[cfg(test)]
mod tests {

    extern crate spectral;

    use self::spectral::prelude::*;

    use super::ClassFile;
    use super::components::{Attribute, AccessFlags, ConstantPoolItem};

    use std::fs::File;
    use std::path::PathBuf;

    const MANIFEST_DIR: &'static str = env!("CARGO_MANIFEST_DIR");

    #[test]
    fn can_successfully_parse_magic() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.magic).is_equal_to(&0xCAFEBABE);
    }

    #[test]
    fn can_successfully_parse_version() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.minor_version).is_equal_to(&0);
        assert_that(&classfile.major_version).is_equal_to(&52);
    }

    #[test]
    fn can_successfully_parse_constant_pool() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.constant_pool_count).is_equal_to(&26);
        assert_that(&classfile.constant_pool).has_length(25);
    }

    #[test]
    fn can_successfully_parse_access_flags() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        let access_flags = classfile.access_flags;
        asserting("class is public")
            .that(&access_flags)
            .matches(|val| AccessFlags::is_public(*val));
        asserting("class is super").that(&access_flags).matches(|val| AccessFlags::is_super(*val));
    }

    #[test]
    fn can_successfully_parse_class_references() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        let this_class = classfile.this_class;
        let super_class = classfile.super_class;
        let constant_pool = classfile.constant_pool;

        assert_that(&ConstantPoolItem::retrieve_class_info(this_class as usize, &constant_pool))
            .is_ok();
        assert_that(&ConstantPoolItem::retrieve_class_info(super_class as usize, &constant_pool))
            .is_ok();
    }

    #[test]
    fn can_successfully_parse_interfaces() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.interfaces_count).is_equal_to(&0);
        assert_that(&classfile.interfaces).has_length(0);
    }

    #[test]
    fn can_successfully_parse_fields() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.fields_count).is_equal_to(&0);
        assert_that(&classfile.fields).has_length(0);
    }

    #[test]
    fn can_successfully_parse_methods() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.methods_count).is_equal_to(&3);
        assert_that(&classfile.methods)
            .has_length(3)
            .mapped_contains(|val| &**val.name, &"<init>")
            .mapped_contains(|val| &**val.name, &"main")
            .mapped_contains(|val| &**val.name, &"println");

        let method_attributes: Vec<_> =
            classfile.methods.iter().flat_map(|val| &val.attributes).collect();
        asserting("at least one method has the code attribute")
            .that(&method_attributes)
            .matching_contains(|val| match ***val {
                Attribute::Code(..) => true,
                _ => false,
            });
    }

    #[test]
    fn can_successfully_parse_class_attributes() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.attributes_count).is_equal_to(&1);
        assert_that(&classfile.attributes).has_length(1);
    }

    #[test]
    fn can_resolve_main_method_if_present() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        assert_that(&classfile.maybe_resolve_main_method()).is_some();
    }

    #[test]
    fn can_retrieve_classname() {
        let test_file = open_test_resource("classfile/HelloWorld.class");
        let classfile = ClassFile::from(test_file).unwrap();

        let classname = classfile.classname().unwrap();
        assert_that(&classname.to_string()).is_equal_to(&"HelloWorld".to_string());
    }

    fn open_test_resource(resource_path: &str) -> File {
        let mut file_path = PathBuf::from(MANIFEST_DIR);
        file_path.push("test-resources/");
        file_path.push(resource_path);

        File::open(file_path).unwrap()
    }

}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#![feature(box_syntax)]
#![feature(compiler_fences)]
#![feature(rustc_private)]
#![feature(try_from)]
#![feature(nll)]

extern crate arena;
extern crate crossbeam;
extern crate x86intrin;
#[macro_use]
extern crate lazy_static;
extern crate byteorder;

pub mod util;
pub mod env;
#[macro_use]
pub mod result;
pub mod slice;
pub mod comparator;
pub mod dbformat;
pub mod config;
pub mod skiplist;
pub mod iterator;
pub mod memtable;
pub mod write_batch;
pub mod log_format;
pub mod log_writer;
pub mod log_reader;
pub mod version_edit;
<commit_msg>Remove compiler_fences flag<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#![feature(box_syntax)]
#![feature(rustc_private)]
#![feature(try_from)]
#![feature(nll)]

extern crate arena;
extern crate crossbeam;
extern crate x86intrin;
#[macro_use]
extern crate lazy_static;
extern crate byteorder;

pub mod util;
pub mod env;
#[macro_use]
pub mod result;
pub mod slice;
pub mod comparator;
pub mod dbformat;
pub mod config;
pub mod skiplist;
pub mod iterator;
pub mod memtable;
pub mod write_batch;
pub mod log_format;
pub mod log_writer;
pub mod log_reader;
pub mod version_edit;
<|endoftext|>


<commit_before>//! This crate searches for the solutions to logic puzzles.
//! The puzzle rules are expressed as constraints.

extern crate bit_set;

pub use puzzle::Puzzle;

/// A puzzle variable token.
#[derive(Copy,Clone,Debug,Eq,PartialEq)]
pub struct VarToken(usize);

/// The type of a puzzle variable's value (i.e. the candidate type).
pub type Val = i32;

mod puzzle;
<commit_msg>Add solution type.<commit_after>//! This crate searches for the solutions to logic puzzles.
//! The puzzle rules are expressed as constraints.

extern crate bit_set;

use std::ops::Index;

pub use puzzle::Puzzle;

/// A puzzle variable token.
#[derive(Copy,Clone,Debug,Eq,PartialEq)]
pub struct VarToken(usize);

/// The type of a puzzle variable's value (i.e. the candidate type).
pub type Val = i32;

/// A dictionary mapping puzzle variables to the solution value.
#[derive(Debug)]
pub struct Solution {
    vars: Vec<Val>,
}

mod puzzle;

impl Index<VarToken> for Solution {
    type Output = Val;
    fn index(&self, var: VarToken) -> &Val {
        let VarToken(idx) = var;
        &self.vars[idx]
    }
}
<|endoftext|>


<commit_before>#![feature(vec_push_all)]

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    #[inline(always)]
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline(always)]
    pub fn with_capacity(capa: usize) -> JsonEncoder {
        JsonEncoder{buffer: Vec::with_capacity(capa)}
    }

    #[inline(always)]
    pub fn encode_raw(&mut self, raw: &[u8]) {
        self.buffer.push_all(raw);
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.buffer
    }

    pub fn with_buf<F>(&mut self, mut f: F) where F: FnMut(&mut Vec<u8>) {
        f(&mut self.buffer);
    }

    #[inline(always)]
    pub fn encode_str_noescape(&mut self, raw_str: &str) {
        self.buffer.push(b'"');
        self.buffer.push_all(raw_str.as_bytes());
        self.buffer.push(b'"');
    }

    fn escape_bytes(&mut self, bytes: &[u8]) {
        let mut start = 0;

        for (i, byte) in bytes.iter().enumerate() {
            let escaped = match *byte {
                b'"' => b"\\\"",
                b'\\' => b"\\\\",
                b'\x08' => b"\\b",
                b'\x0c' => b"\\f",
                b'\n' => b"\\n",
                b'\r' => b"\\r",
                b'\t' => b"\\t",
                _ => {
                    continue;
                }
            };

            if start < i {
                self.encode_raw(&bytes[start..i]);
            }

            self.encode_raw(escaped);

            start = i + 1;
        }

        if start != bytes.len() {
            self.encode_raw(&bytes[start..]);
        }
    }

    pub fn encode_decimal_str(&mut self, value: u64) {
        self.buffer.push(b'"');
        self.encode_u64_decimal(value);
        self.buffer.push(b'"');
    }

    // encodes as decimal string
    #[inline(always)]
    fn encode_u64_decimal(&mut self, value: u64) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 20;

        if value == 0 {
            self.buffer.push(b'0');
            return;
        }

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    #[inline(always)]
    pub fn encode_str(&mut self, s: &str) {
        self.buffer.push(b'"');
        self.escape_bytes(s.as_bytes());
        self.buffer.push(b'"');
    }

    #[inline(always)]
    pub fn encode_i32(&mut self, value: i32) {
        if value == 0 {
            self.buffer.push(b'0');
        } else if value > 0 {
            self.encode_u31(value as u32);
        } else {
            self.buffer.push(b'-');
            self.encode_u31((-value) as u32);
        }
    }

    // encodes a 31-bit unsigned integer != 0
    fn encode_u31(&mut self, value: u32) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 10;
        debug_assert!(value != 0);

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    pub fn encode_obj<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonObjectEncoder) -> T {
        self.buffer.push(b'{');
        let t = {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false})
        };
        self.buffer.push(b'}');
        t
    }

    pub fn encode_array<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonArrayEncoder) -> T {
        self.buffer.push(b'[');
        let t = {
            f(&mut JsonArrayEncoder {js: self, needs_sep: false})
        };
        self.buffer.push(b']');
        t
    }

    pub fn encode_array_nobrackets<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonArrayEncoder) -> T {
        f(&mut JsonArrayEncoder {js: self, needs_sep: false})
    }

    pub fn obj_single_str_field(name: &str, s: &str) -> Vec<u8> {
        let mut js = JsonEncoder::with_capacity(name.len() + s.len() + 2 + 2 + 1 + 2);
        js.encode_obj(|jso| jso.encode_field_str(name, s));
        js.into_vec()
    }

}

pub struct JsonObjectEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonObjectEncoder<'a> {
    // XXX: name MAY NOT include escapable characters
    #[inline(always)]
    pub fn encode_field<F, T>(&mut self, name: &str, mut f: F) -> T where F: FnMut(&mut JsonEncoder) -> T {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        self.js.encode_str_noescape(name);
        self.js.buffer.push(b':');

        f(self.js)
    }

    #[inline(always)]
    pub fn encode_field_array<F, T>(&mut self, name: &str, mut f: F) -> T where F: FnMut(&mut JsonArrayEncoder) -> T {
        self.encode_field(name, |js| js.encode_array(|jsa| f(jsa)))
    }

    #[inline(always)]
    pub fn encode_field_i32(&mut self, name: &str, val: i32) {
        self.encode_field(name, |js| js.encode_i32(val));
    }

    #[inline(always)]
    pub fn encode_field_str(&mut self, name: &str, s: &str) {
        self.encode_field(name, |js| js.encode_str(s));
    }

}

pub struct JsonArrayEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonArrayEncoder<'a> {
    #[inline(always)]
    pub fn encode_elm<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonEncoder) -> T {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        f(self.js)
    }

    #[inline(always)]
    pub fn encode_elm_i32(&mut self, val: i32) {
        self.encode_elm(|js| js.encode_i32(val));
    }

    #[inline(always)]
    pub fn encode_elm_str(&mut self, s: &str) {
        self.encode_elm(|js| js.encode_str(s));
    }

    #[inline(always)]
    pub fn encode_elm_obj<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonObjectEncoder) -> T {
        self.encode_elm(|js| js.encode_obj(|jso| f(jso)))
    }
}

#[test]
fn test_json_obj_encoder() {
    use std::str;

    let mut js = JsonEncoder::new();
    js.encode_obj(|_|{});
    assert_eq!(b"{}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
    });
    assert_eq!(b"{\"total\":31}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
    });
    assert_eq!(b"{\"total\":31,\"next\":\"abc\"}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
        jso.encode_field("tags", |js| {
                js.encode_array(|jsa| {
                        jsa.encode_elm(|js| js.encode_i32(1));
                        jsa.encode_elm(|js| js.encode_i32(2));
                });
        });
    });
    assert_eq!("{\"total\":31,\"next\":\"abc\",\"tags\":[1,2]}", str::from_utf8(&js.into_vec()[..]).unwrap());

    let json = JsonEncoder::obj_single_str_field("total", "abcdef");
    assert_eq!(b"{\"total\":\"abcdef\"}", &json[..]);
}
<commit_msg>Add some inlines<commit_after>#![feature(vec_push_all)]

pub struct JsonEncoder {
    buffer: Vec<u8>
}

impl JsonEncoder {
    #[inline]
    pub fn new() -> JsonEncoder {
        JsonEncoder{buffer: Vec::new()}
    }

    #[inline]
    pub fn with_capacity(capa: usize) -> JsonEncoder {
        JsonEncoder{buffer: Vec::with_capacity(capa)}
    }

    #[inline]
    pub fn encode_raw(&mut self, raw: &[u8]) {
        self.buffer.push_all(raw);
    }

    #[inline]
    pub fn into_vec(self) -> Vec<u8> {
        self.buffer
    }

    #[inline]
    pub fn with_buf<F>(&mut self, mut f: F) where F: FnMut(&mut Vec<u8>) {
        f(&mut self.buffer);
    }

    #[inline]
    pub fn encode_str_noescape(&mut self, raw_str: &str) {
        self.buffer.push(b'"');
        self.buffer.push_all(raw_str.as_bytes());
        self.buffer.push(b'"');
    }

    #[inline]
    fn escape_bytes(&mut self, bytes: &[u8]) {
        let mut start = 0;

        for (i, byte) in bytes.iter().enumerate() {
            let escaped = match *byte {
                b'"' => b"\\\"",
                b'\\' => b"\\\\",
                b'\x08' => b"\\b",
                b'\x0c' => b"\\f",
                b'\n' => b"\\n",
                b'\r' => b"\\r",
                b'\t' => b"\\t",
                _ => {
                    continue;
                }
            };

            if start < i {
                self.encode_raw(&bytes[start..i]);
            }

            self.encode_raw(escaped);

            start = i + 1;
        }

        if start != bytes.len() {
            self.encode_raw(&bytes[start..]);
        }
    }

    #[inline]
    pub fn encode_decimal_str(&mut self, value: u64) {
        self.buffer.push(b'"');
        self.encode_u64_decimal(value);
        self.buffer.push(b'"');
    }

    // encodes as decimal string
    #[inline]
    fn encode_u64_decimal(&mut self, value: u64) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 20;

        if value == 0 {
            self.buffer.push(b'0');
            return;
        }

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    #[inline]
    pub fn encode_str(&mut self, s: &str) {
        self.buffer.push(b'"');
        self.escape_bytes(s.as_bytes());
        self.buffer.push(b'"');
    }

    #[inline]
    pub fn encode_i32(&mut self, value: i32) {
        if value == 0 {
            self.buffer.push(b'0');
        } else if value > 0 {
            self.encode_u31(value as u32);
        } else {
            self.buffer.push(b'-');
            self.encode_u31((-value) as u32);
        }
    }

    // encodes a 31-bit unsigned integer != 0
    #[inline]
    fn encode_u31(&mut self, value: u32) {
        const CHARS: &'static [u8] = b"0123456789";
        const MAX_DIGITS: usize = 10;
        debug_assert!(value != 0);

        let mut digits: [u8; MAX_DIGITS] = [b'0'; MAX_DIGITS];
        let mut i = MAX_DIGITS;
        let mut n = value;
        while n > 0 {
            i -= 1;
            digits[i] = CHARS[(n % 10) as usize];
            n = n / 10;
        }

        self.encode_raw(&digits[i..]);
    }

    #[inline]
    pub fn encode_obj<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonObjectEncoder) -> T {
        self.buffer.push(b'{');
        let t = {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false})
        };
        self.buffer.push(b'}');
        t
    }

    #[inline]
    pub fn encode_array<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonArrayEncoder) -> T {
        self.buffer.push(b'[');
        let t = {
            f(&mut JsonArrayEncoder {js: self, needs_sep: false})
        };
        self.buffer.push(b']');
        t
    }

    #[inline]
    pub fn encode_array_nobrackets<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonArrayEncoder) -> T {
        f(&mut JsonArrayEncoder {js: self, needs_sep: false})
    }

    #[inline]
    pub fn obj_single_str_field(name: &str, s: &str) -> Vec<u8> {
        let mut js = JsonEncoder::with_capacity(name.len() + s.len() + 2 + 2 + 1 + 2);
        js.encode_obj(|jso| jso.encode_field_str(name, s));
        js.into_vec()
    }

}

pub struct JsonObjectEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonObjectEncoder<'a> {
    // XXX: name MAY NOT include escapable characters
    #[inline]
    pub fn encode_field<F, T>(&mut self, name: &str, mut f: F) -> T where F: FnMut(&mut JsonEncoder) -> T {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        self.js.encode_str_noescape(name);
        self.js.buffer.push(b':');

        f(self.js)
    }

    #[inline]
    pub fn encode_field_array<F, T>(&mut self, name: &str, mut f: F) -> T where F: FnMut(&mut JsonArrayEncoder) -> T {
        self.encode_field(name, |js| js.encode_array(|jsa| f(jsa)))
    }

    #[inline]
    pub fn encode_field_i32(&mut self, name: &str, val: i32) {
        self.encode_field(name, |js| js.encode_i32(val));
    }

    #[inline]
    pub fn encode_field_str(&mut self, name: &str, s: &str) {
        self.encode_field(name, |js| js.encode_str(s));
    }

}

pub struct JsonArrayEncoder<'a> {
    js: &'a mut JsonEncoder,
    needs_sep: bool,
}

impl<'a> JsonArrayEncoder<'a> {
    #[inline]
    pub fn encode_elm<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonEncoder) -> T {
        if self.needs_sep {
            self.js.buffer.push(b',');
        } else {
            self.needs_sep = true;
        }
        f(self.js)
    }

    #[inline]
    pub fn encode_elm_i32(&mut self, val: i32) {
        self.encode_elm(|js| js.encode_i32(val));
    }

    #[inline]
    pub fn encode_elm_str(&mut self, s: &str) {
        self.encode_elm(|js| js.encode_str(s));
    }

    #[inline]
    pub fn encode_elm_obj<F, T>(&mut self, mut f: F) -> T where F: FnMut(&mut JsonObjectEncoder) -> T {
        self.encode_elm(|js| js.encode_obj(|jso| f(jso)))
    }
}

#[test]
fn test_json_obj_encoder() {
    use std::str;

    let mut js = JsonEncoder::new();
    js.encode_obj(|_|{});
    assert_eq!(b"{}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
    });
    assert_eq!(b"{\"total\":31}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
    });
    assert_eq!(b"{\"total\":31,\"next\":\"abc\"}", &js.into_vec()[..]);

    let mut js = JsonEncoder::new();
    js.encode_obj(|jso| {
        jso.encode_field("total", |js| js.encode_i32(31));
        jso.encode_field("next", |js| js.encode_str("abc"));
        jso.encode_field("tags", |js| {
                js.encode_array(|jsa| {
                        jsa.encode_elm(|js| js.encode_i32(1));
                        jsa.encode_elm(|js| js.encode_i32(2));
                });
        });
    });
    assert_eq!("{\"total\":31,\"next\":\"abc\",\"tags\":[1,2]}", str::from_utf8(&js.into_vec()[..]).unwrap());

    let json = JsonEncoder::obj_single_str_field("total", "abcdef");
    assert_eq!(b"{\"total\":\"abcdef\"}", &json[..]);
}
<|endoftext|>