<commit_before>extern crate rand;
extern crate num;

use num::{FromPrimitive,
          Float,
          Num,
          NumCast,
          One,
          Zero};

pub fn mean<T>(v: &[T]) -> T
    where T: Copy + FromPrimitive + Num + NumCast
{
    let len = FromPrimitive::from_usize(v.len()).unwrap();
    v.iter().fold(Zero::zero(), |acc: T, elem| acc + *elem) / len
}

pub fn median<T>(v: &[T]) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0);
    let mut scratch = Vec::with_capacity(v.len());
    scratch.extend(v.iter());
    quicksort(&mut scratch);

    let mid = scratch.len() / 2;
    if scratch.len() % 2 == 1 {
        *scratch[mid]
    } else {
        (*scratch[mid] + *scratch[mid-1]) / FromPrimitive::from_i32(2).unwrap()
    }
}

fn sum_square_deviations<T>(v: &[T], c: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    let c = match c {
        Some(c) => c,
        None => mean(v),
    };

    let sum = v.iter().map( |x| (*x - c) * (*x - c) ).fold(Zero::zero(), |acc, elem| acc + elem);
    assert!(sum >= Zero::zero(), "negative sum of square root deviations");
    sum
}

pub fn sample_variance<T>(v: &[T], xbar: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 1, "sample variance requires at least two data points");
    let len: T = FromPrimitive::from_usize(v.len()).unwrap();
    let sum = sum_square_deviations(v, xbar);
    sum / (len - One::one())
}

pub fn population_variance<T>(v: &[T], mu: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0, "population variance requires at least one data point");
    let len: T = FromPrimitive::from_usize(v.len()).unwrap();
    let sum = sum_square_deviations(v, mu);
    sum / len
}

pub fn sample_standard_deviation<T>(v: &[T], xbar: Option<T>) -> T
    where T: Float + FromPrimitive
{
    let svar = sample_variance(v, xbar);
    svar.sqrt()
}

pub fn population_standard_deviation<T>(v: &[T], mu: Option<T>) -> T
    where T: Float + FromPrimitive
{
    let pvar = population_variance(v, mu);
    pvar.sqrt()
}

#[inline(always)]
fn select_pivot<T>(v: &mut [T]) where T: Copy {
    let idx = rand::random::<usize>() % v.len();
    let tmp = v[0];
    v[0] = v[idx];
    v[idx] = tmp;
}

fn partition<T>(v: &mut [T]) -> usize where T: PartialOrd + Copy {
    select_pivot(v);
    let pivot = v[0];
    let mut i = 0;
    let mut j = 0;
    let end = v.len() - 1;
    while i < end {
        i += 1;
        if v[i] < pivot {
            v[j] = v[i];
            j += 1;
            v[i] = v[j];
        }

    }
    v[j] = pivot;
    j

}

fn quicksort<T>(v: &mut [T]) where T: PartialOrd + Copy {
    if v.len() <= 1 {
        return
    }
    let pivot = partition(v);
    quicksort(&mut v[..pivot]);
    quicksort(&mut v[(pivot+1)..]);
}

// Unit tests for private functions must be in the same module.
#[test]
fn test_qsort_empty() {
    let mut vec: Vec<f64> = vec![];
    quicksort(&mut vec);
    assert_eq!(vec, vec![]);
}

#[test]
fn test_qsort_small() {
    let len = 10;
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len { vec.push(rand::random::<f64>()); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_large() {
    let len = 1_000_000;
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len { vec.push(rand::random::<f64>()); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_sorted() {
    let len = 1_000;
    let mut vec = Vec::with_capacity(len);
    for n in 0..len { vec.push(n); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_reverse_sorted() {
    let len = 1_000;
    let mut vec = Vec::with_capacity(len);
    for n in 0..len { vec.push(len-n); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[cfg(test)]
mod tests {
    extern crate rand;
    extern crate num;

    use super::*;
    use num::Float;

    #[test]
    fn test_mean() {
        let vec = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        assert_eq!(mean(&vec), 1.375);
    }

    #[test]
    fn test_median() {
        let vec = vec![1.0, 3.0];
        assert_eq!(median(&vec), 2.0);
        let vec = vec![1.0, 3.0, 5.0];
        assert_eq!(median(&vec), 3.0);
        let vec = vec![1.0, 3.0, 5.0, 7.0];
        assert_eq!(median(&vec), 4.0);
    }

    #[test]
    fn test_sample_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.428571;
        let epsilon = 1e-6;
        assert!((expected - sample_variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.25;
        let epsilon = 1e-6;
        assert!((expected - population_variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_sample_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.195229;
        let epsilon = 1e-6;
        assert!((expected - sample_standard_deviation(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.118034;
        let epsilon = 1e-6;
        assert!((expected - population_standard_deviation(&v, None)).abs() < epsilon);
    }
}
<commit_msg>rename sample_* to * to encourage a good default choice.<commit_after>extern crate rand;
extern crate num;

use num::{FromPrimitive,
          Float,
          Num,
          NumCast,
          One,
          Zero};

pub fn mean<T>(v: &[T]) -> T
    where T: Copy + FromPrimitive + Num + NumCast
{
    let len = FromPrimitive::from_usize(v.len()).unwrap();
    v.iter().fold(Zero::zero(), |acc: T, elem| acc + *elem) / len
}

pub fn median<T>(v: &[T]) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0);
    let mut scratch = Vec::with_capacity(v.len());
    scratch.extend(v.iter());
    quicksort(&mut scratch);

    let mid = scratch.len() / 2;
    if scratch.len() % 2 == 1 {
        *scratch[mid]
    } else {
        (*scratch[mid] + *scratch[mid-1]) / FromPrimitive::from_i32(2).unwrap()
    }
}

fn sum_square_deviations<T>(v: &[T], c: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    let c = match c {
        Some(c) => c,
        None => mean(v),
    };

    let sum = v.iter().map( |x| (*x - c) * (*x - c) ).fold(Zero::zero(), |acc, elem| acc + elem);
    assert!(sum >= Zero::zero(), "negative sum of square root deviations");
    sum
}

pub fn variance<T>(v: &[T], xbar: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 1, "variance requires at least two data points");
    let len: T = FromPrimitive::from_usize(v.len()).unwrap();
    let sum = sum_square_deviations(v, xbar);
    sum / (len - One::one())
}

pub fn population_variance<T>(v: &[T], mu: Option<T>) -> T
    where T: Copy + FromPrimitive + Num + NumCast + PartialOrd
{
    assert!(v.len() > 0, "population variance requires at least one data point");
    let len: T = FromPrimitive::from_usize(v.len()).unwrap();
    let sum = sum_square_deviations(v, mu);
    sum / len
}

pub fn standard_deviation<T>(v: &[T], xbar: Option<T>) -> T
    where T: Float + FromPrimitive
{
    let var = variance(v, xbar);
    var.sqrt()
}

pub fn population_standard_deviation<T>(v: &[T], mu: Option<T>) -> T
    where T: Float + FromPrimitive
{
    let pvar = population_variance(v, mu);
    pvar.sqrt()
}

#[inline(always)]
fn select_pivot<T>(v: &mut [T]) where T: Copy {
    let idx = rand::random::<usize>() % v.len();
    let tmp = v[0];
    v[0] = v[idx];
    v[idx] = tmp;
}

fn partition<T>(v: &mut [T]) -> usize where T: PartialOrd + Copy {
    select_pivot(v);
    let pivot = v[0];
    let mut i = 0;
    let mut j = 0;
    let end = v.len() - 1;
    while i < end {
        i += 1;
        if v[i] < pivot {
            v[j] = v[i];
            j += 1;
            v[i] = v[j];
        }

    }
    v[j] = pivot;
    j

}

fn quicksort<T>(v: &mut [T]) where T: PartialOrd + Copy {
    if v.len() <= 1 {
        return
    }
    let pivot = partition(v);
    quicksort(&mut v[..pivot]);
    quicksort(&mut v[(pivot+1)..]);
}

// Unit tests for private functions must be in the same module.
#[test]
fn test_qsort_empty() {
    let mut vec: Vec<f64> = vec![];
    quicksort(&mut vec);
    assert_eq!(vec, vec![]);
}

#[test]
fn test_qsort_small() {
    let len = 10;
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len { vec.push(rand::random::<f64>()); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_large() {
    let len = 1_000_000;
    let mut vec = Vec::with_capacity(len);
    for _ in 0..len { vec.push(rand::random::<f64>()); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_sorted() {
    let len = 1_000;
    let mut vec = Vec::with_capacity(len);
    for n in 0..len { vec.push(n); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[test]
fn test_qsort_reverse_sorted() {
    let len = 1_000;
    let mut vec = Vec::with_capacity(len);
    for n in 0..len { vec.push(len-n); }
    quicksort(&mut vec);
    for i in 0..(len-1) {
        assert!(vec[i] < vec[i+1], "sorted vectors must be monotonically increasing");
    }
}

#[cfg(test)]
mod tests {
    extern crate rand;
    extern crate num;

    use super::*;
    use num::Float;

    #[test]
    fn test_mean() {
        let vec = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        assert_eq!(mean(&vec), 1.375);
    }

    #[test]
    fn test_median() {
        let vec = vec![1.0, 3.0];
        assert_eq!(median(&vec), 2.0);
        let vec = vec![1.0, 3.0, 5.0];
        assert_eq!(median(&vec), 3.0);
        let vec = vec![1.0, 3.0, 5.0, 7.0];
        assert_eq!(median(&vec), 4.0);
    }

    #[test]
    fn test_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.428571;
        let epsilon = 1e-6;
        assert!((expected - variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_variance() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.25;
        let epsilon = 1e-6;
        assert!((expected - population_variance(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.195229;
        let epsilon = 1e-6;
        assert!((expected - standard_deviation(&v, None)).abs() < epsilon);
    }

    #[test]
    fn test_population_standard_deviation() {
        let v = vec![0.0, 0.25, 0.25, 1.25, 1.5, 1.75, 2.75, 3.25];
        // result is within `epsilon` of expected value
        let expected = 1.118034;
        let epsilon = 1e-6;
        assert!((expected - population_standard_deviation(&v, None)).abs() < epsilon);
    }
}
<|endoftext|>


<commit_before>// (c) 2015-2016 Joost Yervante Damad <joost@damad.be>

use std::fmt;
use std::fs::File;
use std::io::Read;

extern crate rustysexp;
use rustysexp::Sexp;
use rustysexp::Atom;

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

fn err<T>(msg: &str) -> ERes<T> {
    Err(String::from(msg))
}

#[derive(Debug)]
pub struct Module {
    name: String,
    elements: Vec<Element>
}

impl Module {
    fn new(name: &String) -> Module {
        Module { name: name.clone(), elements: vec![] }
    }
    fn append(&mut self, e: Element) {
        self.elements.push(e)
    }
}

impl fmt::Display for Module {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(module {}\n", self.name));
        for e in &self.elements {
            try!(write!(f, "{}\n", e))
        };
        write!(f, ")")
    }
}

#[derive(Debug)]
pub enum Element {
    Layer(String),
    Descr(String),
    FpText(FpText),
    Pad,
    FpPoly,
    FpLine,
    FpCircle
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Layer(ref s) => write!(f, "(layer {})", s),
            Element::Descr(ref s) => write!(f, "(descr \"{}\")", s),
            Element::FpText(ref p) => write!(f, "{}", p),
            Element::Pad => write!(f, "(pad)"),
            Element::FpPoly => write!(f, "(fp_poly)"),
            Element::FpLine => write!(f, "(fp_line)"),
            Element::FpCircle => write!(f, "(fp_circle)"),
        }
    }
}

#[derive(Debug)]
pub struct FpText {
    name: String,
    value: String,
    at: At,
    layer: String,
    effects: Effects,
    hide: bool,
}

impl FpText {
    fn new(name: &String, value: &String) -> FpText {
        FpText {
            name: name.clone(),
            value: value.clone(),
            at: At::new(0.,0.,0.),
            layer: String::from("cow"),
            effects: Effects::new(),
            hide: false
        }
    }
    fn set_at(&mut self, at: &At) {
        self.at.set(at)
    }
}

impl fmt::Display for FpText {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(fp_text {} \"{}\" {} (layer {}){} {})", self.name, self.value, self.at, self.layer, if self.hide { " hide" } else { "" }, self.effects)
    }
}

#[derive(Debug)]
pub struct At {
    x: f64,
    y: f64,
    rot: f64
}

impl At {
    fn new(x:f64 ,y:f64, rot:f64) -> At {
        At { x:x, y:y, rot:rot }
    }
    fn set(&mut self, at: &At) {
        self.x = at.x;
        self.y = at.y;
        self.rot = at.rot;
    }
}

impl fmt::Display for At {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.rot == 0.0 {
            write!(f, "(at {} {})", self.x, self.y)
        } else {
            write!(f, "(at {} {} {})", self.x, self.y, self.rot)
        }
    }
}

#[derive(Debug)]
pub struct Effects {
    todo: String
}

impl Effects {
    fn new() -> Effects {
        Effects { todo: String::from("todo") }
    }
}

impl fmt::Display for Effects {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(effects)")
    }
}

#[derive(Debug)]
pub enum XyType {
    Xy,
    Start,
    End,
}

#[derive(Debug)]
pub struct Xy {
    x: f64,
    y: f64,
    t: XyType,
}

impl fmt::Display for Xy {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.t {
            XyType::Xy => write!(f,"(xy {} {})", self.x, self.y),
            XyType::Start => write!(f,"(start {} {})", self.x, self.y),
            XyType::End => write!(f,"(end {} {})", self.x, self.y),
        }
    }
}

#[derive(Debug)]
enum Part {
    At(At),
    Layer(String),
    Hide,
    Effects(Effects),
    Layers(Vec<String>),
    Width(f64),
    Xy(Xy),
    Pts(Vec<Xy>),
}

impl fmt::Display for Part {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Part::At(ref at)           => write!(f, "{}", at),
            Part::Layer(ref layer)     => write!(f, "(layer {})", layer),
            Part::Hide                 => write!(f, "hide"),
            Part::Effects(ref effects) => write!(f, "{}", effects),
            Part::Layers(_)            => write!(f, "(layers TODO"),
            Part::Width(ref w)         => write!(f, "(width {}", w),
            Part::Xy(ref xy)           => write!(f, "{}", xy),
            Part::Pts(_)               => write!(f, "(pts TODO)"),

        }
    }
}

// (at 0.0 -4.0) (at -2.575 -1.625 180)
fn parse_part_at(v: &Vec<Sexp>) -> ERes<Part> {
    match v.len() {
        3 => {
            let x = try!(try!(v[1].atom()).f());
            let y = try!(try!(v[2].atom()).f());
            Ok(Part::At(At::new(x, y, 0.0)))
        }
        4 => {
            let x = try!(try!(v[1].atom()).f());
            let y = try!(try!(v[2].atom()).f());
            let rot = try!(try!(v[4].atom()).f());
            Ok(Part::At(At::new(x, y, rot)))
        }
        _ => err("at with wrong length")
    }
}

fn parse_part_layer(v: &Vec<Sexp>) -> ERes<Part> {
    let layer = try!(try!(v[1].atom()).string());
    Ok(Part::Layer(layer))
}

fn parse_part_effects(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_layers(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_width(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_pts(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_xy(t: XyType, v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_list(v: &Vec<Sexp>) -> ERes<Part> {
    match &try!(try!(v[0].atom()).string())[..] {
        "at" => parse_part_at(v),
        "layer" => parse_part_layer(v),
        "effects" => parse_part_effects(v),
        "layers" => parse_part_layers(v),
        "width" => parse_part_width(v),
        "start" => parse_part_xy(XyType::Start, v),
        "end" => parse_part_xy(XyType::End, v),
        "pts" => parse_part_pts(v),
        x => Err(format!("unknown part {}", x))
    }
}

fn parse_part(part: &Sexp) -> ERes<Part> {
    match *part {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "hide" => Ok(Part::Hide),
                x => Err(format!("unknown part in element: {}", x))
            }
        },
        Sexp::List(ref v) => parse_part_list(&v),
        ref x => Err(format!("unknown part in element: {}", x))
    }
}

fn parse_parts(v: &[Sexp]) -> ERes<Vec<Part>> {
    let mut res = Vec::new();
    for e in v {
        res.push(try!(parse_part(e)))
    }
    Ok(res)
}

fn parse_layer(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::S(ref s)) => {
            Ok(Element::Layer(s.clone()))
        }
        ref x => Err(format!("unexpected element in layer: {}", x))
    }
}

fn parse_descr(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::Q(ref s)) => {
            Ok(Element::Descr(s.clone()))
        }
        ref x => Err(format!("unexpected element in descr: {}", x))
    }
}
fn parse_fp_text(v: &Vec<Sexp>) -> ERes<Element> {
    let name = try!(match v[1] {
        Sexp::Atom(Atom::S(ref s)) => Ok(s),
        ref x => err("expecting name for fp_text")
    });
    let value = try!(match v[2] {
        Sexp::Atom(Atom::Q(ref s)) => Ok(s),
        ref x => err("expecting value for fp_text")
    });
    let mut fp = FpText::new(name, value);
    let parts = try!(parse_parts(&v[3..]));
    for part in &parts[..] {
        match *part {
            Part::At(ref at) => {
                fp.set_at(at)
            },
            Part::Layer(ref layer) => {
                fp.layer = layer.clone()
            }
            Part::Hide => {
                fp.hide = true
            },
            ref x => {
                println!("ignoring {}", x)
            }
        }
    }
    Ok(Element::FpText(fp))
}
fn parse_pad(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::Pad)
}
fn parse_fp_poly(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpPoly)
}
fn parse_fp_line(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpLine)
}
fn parse_fp_circle(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpCircle)
}

fn parse_element_list(v: &Vec<Sexp>) -> ERes<Element> {
    match v[0] {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "layer" => parse_layer(v),
                "descr" => parse_descr(v),
                "fp_text" => parse_fp_text(v),
                "pad" => parse_pad(v),
                "fp_poly" => parse_fp_poly(v),
                "fp_line" => parse_fp_line(v),
                "fp_circle" => parse_fp_circle(v),
                x => Err(format!("unknown element in module: {}", x))
            }
        }
        _ => err("expecting atom")
    }
}

fn parse_element(s: &Sexp) -> ERes<Element> {
    match *s {
        Sexp::List(ref v) => parse_element_list(&v),
        _ => err("expecting element list in module")
    }
}

fn parse_module_list(v: &Vec<Sexp>) -> ERes<Module> {
    let mut module = (match v[0] {
        Sexp::Atom(Atom::S(ref s)) if s == "module" => {
            match v[1] {
                Sexp::Atom(Atom::S(ref s)) => {
                    Ok(Module::new(s))
                }
                ref x => return Err(format!("expecting module name got {}", x))
            }
        }
        _ => err("expecting module")
    }).unwrap();
    for e in &v[2..] {
        let el = try!(parse_element(e));
        module.append(el)
    }
    Ok(module)
}

fn parse_module(s: Sexp) -> ERes<Module> {
    match s {
        Sexp::List(v) => parse_module_list(&v),
        _ => err("expecting top level list")
    }
}

fn parse(s: &str) -> ERes<Module> {
    match rustysexp::parse_str(s) {
        Ok(s) => parse_module(s),
        Err(x) => Err(format!("IOError: {}", 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_str(s: &str) -> Module {
    parse(s).unwrap()
}

pub fn parse_file(name: &str) -> Module {
    let s = read_file(name).unwrap();
    parse(&s[..]).unwrap()
}

<commit_msg>implement Effects parsing<commit_after>// (c) 2015-2016 Joost Yervante Damad <joost@damad.be>

use std::fmt;
use std::fs::File;
use std::io::Read;

extern crate rustysexp;
use rustysexp::Sexp;
use rustysexp::Atom;

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

fn err<T>(msg: &str) -> ERes<T> {
    Err(String::from(msg))
}

#[derive(Debug)]
pub struct Module {
    name: String,
    elements: Vec<Element>
}

impl Module {
    fn new(name: &String) -> Module {
        Module { name: name.clone(), elements: vec![] }
    }
    fn append(&mut self, e: Element) {
        self.elements.push(e)
    }
}

impl fmt::Display for Module {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(module {}\n", self.name));
        for e in &self.elements {
            try!(write!(f, "{}\n", e))
        };
        write!(f, ")")
    }
}

#[derive(Debug)]
pub enum Element {
    Layer(String),
    Descr(String),
    FpText(FpText),
    Pad,
    FpPoly,
    FpLine,
    FpCircle
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Layer(ref s) => write!(f, "(layer {})", s),
            Element::Descr(ref s) => write!(f, "(descr \"{}\")", s),
            Element::FpText(ref p) => write!(f, "{}", p),
            Element::Pad => write!(f, "(pad)"),
            Element::FpPoly => write!(f, "(fp_poly)"),
            Element::FpLine => write!(f, "(fp_line)"),
            Element::FpCircle => write!(f, "(fp_circle)"),
        }
    }
}

#[derive(Debug)]
pub struct FpText {
    name: String,
    value: String,
    at: At,
    layer: String,
    effects: Effects,
    hide: bool,
}

impl FpText {
    fn new(name: &String, value: &String) -> FpText {
        FpText {
            name: name.clone(),
            value: value.clone(),
            at: At::new(0.,0.,0.),
            layer: String::from("cow"),
            effects: Effects::new(),
            hide: false
        }
    }
    fn set_at(&mut self, at: &At) {
        self.at.set(at)
    }
    fn set_effects(&mut self, effects: &Effects) {
        self.effects.clone_from(effects)
    }
}

impl fmt::Display for FpText {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(fp_text {} \"{}\" {} (layer {}){} {})", self.name, self.value, self.at, self.layer, if self.hide { " hide" } else { "" }, self.effects)
    }
}

#[derive(Debug)]
pub struct At {
    x: f64,
    y: f64,
    rot: f64
}

impl At {
    fn new(x:f64 ,y:f64, rot:f64) -> At {
        At { x:x, y:y, rot:rot }
    }
    fn set(&mut self, at: &At) {
        self.x = at.x;
        self.y = at.y;
        self.rot = at.rot;
    }
}

impl fmt::Display for At {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.rot == 0.0 {
            write!(f, "(at {} {})", self.x, self.y)
        } else {
            write!(f, "(at {} {} {})", self.x, self.y, self.rot)
        }
    }
}

#[derive(Clone)]
#[derive(Debug)]
pub struct Font {
    size: Xy,
    thickness: f64,
}

impl Font {
    fn new() -> Font {
        Font { size: Xy::new(0.0, 0.0, XyType::Size), thickness: 0.0 }
    }
}

impl fmt::Display for Font {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(font (size {} {}) (thickness {}))", self.size.x, self.size.y, self.thickness)
    }
}

#[derive(Clone)]
#[derive(Debug)]
pub struct Effects {
    font: Font
}

impl Effects {
    fn new() -> Effects {
        Effects { font: Font::new() }
    }
    fn from_font(font: Font) -> Effects {
        Effects { font: font }
    }
}

impl fmt::Display for Effects {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "(effects (font (size {} {}) (thickness {})))", self.font.size.x, self.font.size.y, self.font.thickness)
    }
}

#[derive(PartialEq)]
#[derive(Clone)]
#[derive(Debug)]
pub enum XyType {
    Xy,
    Start,
    End,
    Size,
}

#[derive(Clone)]
#[derive(Debug)]
pub struct Xy {
    x: f64,
    y: f64,
    t: XyType,
}

impl Xy {
    fn new(x: f64, y: f64, t: XyType) -> Xy {
        Xy { x:x, y:y, t:t }
    }
}

impl fmt::Display for Xy {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self.t {
            XyType::Xy => write!(f,"(xy {} {})", self.x, self.y),
            XyType::Start => write!(f,"(start {} {})", self.x, self.y),
            XyType::End => write!(f,"(end {} {})", self.x, self.y),
            XyType::Size => write!(f,"(size {} {})", self.x, self.y),
        }
    }
}

#[derive(Debug)]
enum Part {
    At(At),
    Layer(String),
    Hide,
    Effects(Effects),
    Layers(Vec<String>),
    Width(f64),
    Xy(Xy),
    Pts(Vec<Xy>),
    Thickness(f64),
}

impl fmt::Display for Part {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Part::At(ref at)           => write!(f, "{}", at),
            Part::Layer(ref layer)     => write!(f, "(layer {})", layer),
            Part::Hide                 => write!(f, "hide"),
            Part::Effects(ref effects) => write!(f, "{}", effects),
            Part::Layers(_)            => write!(f, "(layers TODO"),
            Part::Width(ref w)         => write!(f, "(width {}", w),
            Part::Xy(ref xy)           => write!(f, "{}", xy),
            Part::Pts(_)               => write!(f, "(pts TODO)"),
            Part::Thickness(ref x)     => write!(f, "(thickness {})", x),

        }
    }
}

// (at 0.0 -4.0) (at -2.575 -1.625 180)
fn parse_part_at(v: &Vec<Sexp>) -> ERes<Part> {
    match v.len() {
        3 => {
            let x = try!(try!(v[1].atom()).f());
            let y = try!(try!(v[2].atom()).f());
            Ok(Part::At(At::new(x, y, 0.0)))
        }
        4 => {
            let x = try!(try!(v[1].atom()).f());
            let y = try!(try!(v[2].atom()).f());
            let rot = try!(try!(v[4].atom()).f());
            Ok(Part::At(At::new(x, y, rot)))
        }
        _ => err("at with wrong length")
    }
}

fn parse_part_layer(v: &Vec<Sexp>) -> ERes<Part> {
    let layer = try!(try!(v[1].atom()).string());
    Ok(Part::Layer(layer))
}

fn parse_part_effects(v: &Vec<Sexp>) -> ERes<Part> {
    let l = try!(v[1].list());
    for x in &l[..] {
        println!("effects el: {}", x)
    }
    let f = try!(try!(l[0].atom()).string());
    if &f[..] != "font" {
        return err("expecting font")
    }
    let parts = try!(parse_parts(&l[1..]));
    let mut font = Font::new();
    for part in &parts[..] {
        println!("part: {}", part);
        try!(match *part {
            Part::Xy(ref xy) if xy.t == XyType::Size => {
                font.size.x = xy.x;
                font.size.y = xy.y;
                Ok(())
            }
            Part::Thickness(ref t) => {
                font.thickness = *t;
                Ok(())
            }
            ref x => Err(format!("unknown element in font: {}", x))
        })
    }
    Ok(Part::Effects(Effects::from_font(font)))
}

fn parse_part_layers(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_width(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_thickness(v: &Vec<Sexp>) -> ERes<Part> {
    let f = try!(try!(v[1].atom()).f());
    Ok(Part::Thickness(f))
}

fn parse_part_pts(v: &Vec<Sexp>) -> ERes<Part> {
    Ok(Part::Hide)
}

fn parse_part_xy(t: XyType, v: &Vec<Sexp>) -> ERes<Part> {
    let x = try!(try!(v[1].atom()).f());
    let y = try!(try!(v[2].atom()).f());
    Ok(Part::Xy(Xy::new(x,y,t)))
}

fn parse_part_list(v: &Vec<Sexp>) -> ERes<Part> {
    let name = &try!(try!(v[0].atom()).string())[..];
    println!("name: {}", name);
    match name {
        "at" => parse_part_at(v),
        "layer" => parse_part_layer(v),
        "effects" => parse_part_effects(v),
        "layers" => parse_part_layers(v),
        "width" => parse_part_width(v),
        "start" => parse_part_xy(XyType::Start, v),
        "end" => parse_part_xy(XyType::End, v),
        "size" => parse_part_xy(XyType::Size, v),
        "pts" => parse_part_pts(v),
        "thickness" => parse_part_thickness(v),
        x => Err(format!("unknown part {}", x))
    }
}

fn parse_part(part: &Sexp) -> ERes<Part> {
    match *part {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "hide" => Ok(Part::Hide),
                x => Err(format!("unknown part in element: {}", x))
            }
        },
        Sexp::List(ref v) => parse_part_list(&v),
        ref x => Err(format!("unknown part in element: {}", x))
    }
}

fn parse_parts(v: &[Sexp]) -> ERes<Vec<Part>> {
    let mut res = Vec::new();
    for e in v {
        res.push(try!(parse_part(e)))
    }
    for x in &res[..] {
        println!("pp: {}", x)
    }

    Ok(res)
}

fn parse_layer(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::S(ref s)) => {
            Ok(Element::Layer(s.clone()))
        }
        ref x => Err(format!("unexpected element in layer: {}", x))
    }
}

fn parse_descr(v: &Vec<Sexp>) -> ERes<Element> {
    match v[1] {
        Sexp::Atom(Atom::Q(ref s)) => {
            Ok(Element::Descr(s.clone()))
        }
        ref x => Err(format!("unexpected element in descr: {}", x))
    }
}
fn parse_fp_text(v: &Vec<Sexp>) -> ERes<Element> {
    let name = try!(match v[1] {
        Sexp::Atom(Atom::S(ref s)) => Ok(s),
        ref x => err("expecting name for fp_text")
    });
    let value = try!(match v[2] {
        Sexp::Atom(Atom::Q(ref s)) => Ok(s),
        ref x => err("expecting value for fp_text")
    });
    let parts = try!(parse_parts(&v[3..]));
    let mut fp = FpText::new(name, value);
    for part in &parts[..] {
        match *part {
            Part::At(ref at) => {
                fp.set_at(at)
            },
            Part::Layer(ref layer) => {
                fp.layer = layer.clone()
            }
            Part::Hide => {
                fp.hide = true
            },
            Part::Effects(ref effects) => {
                fp.set_effects(effects)
            }
            ref x => {
                println!("ignoring {}", x)
            }
        }
    }
    Ok(Element::FpText(fp))
}
fn parse_pad(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::Pad)
}
fn parse_fp_poly(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpPoly)
}
fn parse_fp_line(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpLine)
}
fn parse_fp_circle(v: &Vec<Sexp>) -> ERes<Element> {
    Ok(Element::FpCircle)
}

fn parse_element_list(v: &Vec<Sexp>) -> ERes<Element> {
    match v[0] {
        Sexp::Atom(Atom::S(ref s)) => {
            match &s[..] {
                "layer" => parse_layer(v),
                "descr" => parse_descr(v),
                "fp_text" => parse_fp_text(v),
                "pad" => parse_pad(v),
                "fp_poly" => parse_fp_poly(v),
                "fp_line" => parse_fp_line(v),
                "fp_circle" => parse_fp_circle(v),
                x => Err(format!("unknown element in module: {}", x))
            }
        }
        _ => err("expecting atom")
    }
}

fn parse_element(s: &Sexp) -> ERes<Element> {
    match *s {
        Sexp::List(ref v) => parse_element_list(&v),
        _ => err("expecting element list in module")
    }
}

fn parse_module_list(v: &Vec<Sexp>) -> ERes<Module> {
    let mut module = (match v[0] {
        Sexp::Atom(Atom::S(ref s)) if s == "module" => {
            match v[1] {
                Sexp::Atom(Atom::S(ref s)) => {
                    Ok(Module::new(s))
                }
                ref x => return Err(format!("expecting module name got {}", x))
            }
        }
        _ => err("expecting module")
    }).unwrap();
    for e in &v[2..] {
        let el = try!(parse_element(e));
        module.append(el)
    }
    Ok(module)
}

fn parse_module(s: Sexp) -> ERes<Module> {
    match s {
        Sexp::List(v) => parse_module_list(&v),
        _ => err("expecting top level list")
    }
}

fn parse(s: &str) -> ERes<Module> {
    match rustysexp::parse_str(s) {
        Ok(s) => parse_module(s),
        Err(x) => Err(format!("IOError: {}", 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_str(s: &str) -> Module {
    parse(s).unwrap()
}

pub fn parse_file(name: &str) -> Module {
    let s = read_file(name).unwrap();
    parse(&s[..]).unwrap()
}

<|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, f: F) where F: Fn(&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>(&mut self, f: F) where F: Fn(&mut JsonObjectEncoder) {
        self.buffer.push(b'{');
        {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b'}');
    }

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

}

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:Fn(&mut JsonEncoder)>(&mut self, name: &str, f: F) {
        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:Fn(&mut JsonArrayEncoder)>(&mut self, name: &str, f: F) {
        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:Fn(&mut JsonEncoder)>(&mut self, f: F) {
        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:Fn(&mut JsonObjectEncoder)>(&mut self, f: F) {
        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());
}
<commit_msg>Function can be used to write out top-level objects<commit_after>#![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, f: F) where F: Fn(&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>(&mut self, f: F) where F: Fn(&mut JsonObjectEncoder) {
        self.buffer.push(b'{');
        {
            f(&mut JsonObjectEncoder {js: self, needs_sep: false});
        }
        self.buffer.push(b'}');
    }

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

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

}

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:Fn(&mut JsonEncoder)>(&mut self, name: &str, f: F) {
        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:Fn(&mut JsonArrayEncoder)>(&mut self, name: &str, f: F) {
        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:Fn(&mut JsonEncoder)>(&mut self, f: F) {
        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:Fn(&mut JsonObjectEncoder)>(&mut self, f: F) {
        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());
}
<|endoftext|>


<commit_before>#![feature(struct_variant, globs, macro_rules)]

use std::io;

pub use result::*;
pub use tokens::*;

pub mod tokens;
pub mod result;

struct Buf {
    data: Vec<u8>,
    marks: Vec<uint>,
    pos: uint,
    sized: bool
}

struct Mark<'a> {
    buf: &'a mut Buf
}

impl<'a> Mark<'a> {
    fn set(&mut self) {
        self.buf.marks.push(self.buf.pos);
    }

    fn unset(&mut self) {
        assert!(self.buf.marks.len() > 0);
        self.buf.marks.pop();
    }

    fn reset(&mut self) {
        assert!(self.buf.marks.len() > 0);
        self.buf.pos = self.buf.marks.pop().unwrap();
    }
}

impl Buf {
    #[inline]
    fn new_existing(data: Vec<u8>) -> Buf {
        Buf { data: data, marks: Vec::new(), pos: 0, sized: true }
    }

    #[inline]
    fn new() -> Buf {
        Buf { data: Vec::new(), marks: Vec::new(), pos: 0, sized: false }
    }

    fn read_from<R: Reader>(&mut self, source: &mut R) -> io::IoResult<u8> {
        if self.pos < self.data.len() {
            let ch = self.data[self.pos];
            self.pos += 1;
            Ok(ch)
        } else if self.sized {
            Err(io::IoError { kind: io::EndOfFile, desc: "buffer exhausted", detail: None })
        } else {
            source.read_byte().map(|c| {
                self.data.push(c);
                self.pos += 1;
                c
            })
        }
    }

    #[inline]
    fn unread(&mut self, n: uint) {
        assert!(n <= self.pos);
        self.pos -= n;
    }

    #[inline]
    fn rewind(&mut self) {
        self.pos = 0;
    }

    #[inline]
    fn consume(&mut self) {
        self.data.clear();
        self.pos = 0;
    }

    #[inline]
    fn mark(&mut self) -> Mark {
        Mark { buf: self }
    }
}

struct BufStack {
    bufs: Vec<Buf>
}

impl BufStack {
    #[inline]
    fn new() -> BufStack { BufStack { bufs: Vec::new() } }

    #[inline]
    fn push(&mut self, data: Vec<u8>) {
        self.bufs.push(Buf::new_existing(data))
    }

    #[inline]
    fn push_new(&mut self) {
        self.bufs.push(Buf::new());
    }

    #[inline]
    fn peek(&mut self) -> &mut Buf {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap()
    }

    fn pop(&mut self) {
        assert!(self.bufs.len() > 0);
        self.bufs.pop();
    }

    fn rewind(&mut self) {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().rewind();
    }

    fn consume(&mut self) {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().consume();
    }

    fn read_from<R: Reader>(&mut self, source: &mut R) -> io::IoResult<u8> {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().read_from(source)
    }

    fn unread(&mut self, n: uint) {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().unread(n);
    }

    fn mark(&mut self) -> Mark {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().mark()
    }
}

pub struct MarkdownParser<R> {
    source: R,
    stack: BufStack
}

impl<R: Reader> MarkdownParser<R> {
    pub fn new(r: R) -> MarkdownParser<R> {
        MarkdownParser {
            source: r,
            stack: BufStack::new()
        }
    }

    pub fn tokens(self) -> MarkdownTokens<R> {
        MarkdownTokens { parser: self }
    }
}

pub struct MarkdownTokens<R> {
    parser: MarkdownParser<R>
}

impl<R: Reader> Iterator<Block> for MarkdownTokens<R> {
    #[inline]
    fn next(&mut self) -> Option<Block> {
        self.parser.next().to_result().ok()
    }
}

macro_rules! first_of(
    ($e:expr) => ($e);
    ($e:expr or $f:expr $(or $more:expr)*) => (
        $e.or_else(|| first_of!($f $(or $more)*))
    )
)

macro_rules! try_reset(
    ($_self:ident; $e:expr) => ({
        $_self.mark().set();
        match $e {
            NoParse => { $_self.mark().reset(); return NoParse }
            r => { $_self.mark().unset(); r }
        }
    })
)

macro_rules! check_reset(
    ($_self:ident; $e:expr) => ({
        $_self.mark().set();
        match $e {
            NoParse => { $_self.mark().reset(); NoParse }
            r => { $_self.mark().unset(); r }
        }
    })
)

macro_rules! try_parse(
    ($e:expr) => (
        match $e {
            NoParse => return NoParse,
            r => r
        }
    )
)

macro_rules! try_err(
    ($e:expr) => (
        match $e {
            Failure(e) => return Failure(e),
            PartialSuccess(r, e) => return PartialSuccess(r, e),
            r => r
        }
    )
)

macro_rules! try_err_f(
    ($e:expr) => (
        match $e {
            Failure(e) => return Failure(e),
            PartialSuccess(_, e) => return Failure(e),
            r => r
        }
    )
)

macro_rules! iotry_err(
    ($e:expr) => (
        match $e {
            Ok(r) => Success(r),
            Err(e) => return Failure(MarkdownError::from_io(e))
        }
    )
)

macro_rules! attempt(
    ($e:expr) => (
        match $e {
            NoParse => Success(()),
            o => o
        }
    )
)

enum ParseResult<T> {
    NoParse,
    Success(T),
    PartialSuccess(T, MarkdownError),
    Failure(MarkdownError)
}

impl<T> ParseResult<T> {
    #[inline]
    fn from_io(r: io::IoResult<T>) -> ParseResult<T> {
        match r {
            Ok(r) => Success(r),
            Err(e) => Failure(MarkdownError::from_io(e))
        }
    }

    #[inline]
    fn is_np(&self) -> bool {
        match *self {
            NoParse => true,
            _ => false
        }
    }

    #[inline]
    fn unwrap(self) -> T {
        match self {
            Success(r) => r,
            PartialSuccess(r, _) => r,
            Failure(e) => fail!("unwrapping failure: {}", e),
            NoParse => fail!("unwrapping NoParse")
        }
    }

    #[inline]
    fn or_else(self, f: || -> ParseResult<T>) -> ParseResult<T> {
        match self {
            NoParse => f(),
            r => r
        }
    }

    fn to_md_result(self) -> MarkdownResult<T> {
        match self {
            Success(r) => result::Success(r),
            PartialSuccess(r, e) => result::PartialSuccess(r, e),
            Failure(e) => result::Failure(e),
            NoParse => fail!("NoParse is converted to MarkdownResult")
        }
    }
}

macro_rules! parse_error(
    ($s:expr) => (Failure(ParseError(std::str::Slice($s))));
    ($s:expr, $($arg:expr),+) => (Failure(ParseError(std::str::Owned(format!($s, $($arg),+)))))
)

impl<R: Reader> MarkdownParser<R> {
    pub fn read_while_possible(&mut self) -> (Document, Option<MarkdownError>) {
        let mut result = Vec::new();
        loop {
            match self.parse_block() {
                Success(token) => result.push(token),
                PartialSuccess(token, err) => {
                    result.push(token);
                    match err {
                        IoError(ref cause) if cause.kind == io::EndOfFile => break,
                        err => return (result, Some(err))
                    }
                }
                Failure(IoError(ref cause)) if cause.kind == io::EndOfFile => break,
                Failure(err) => return (result, Some(err)),
                NoParse => fail!("unexpected NoParse")
            }
        }
        (result, None)
    }

    #[inline]
    pub fn next(&mut self) -> MarkdownResult<Block> { self.parse_block().to_md_result() }

    #[inline]
    fn push_existing(&mut self, buf: Vec<u8>) { self.stack.push(buf); }

    #[inline]
    fn push_buf(&mut self) { self.stack.push_new(); }

    #[inline]
    fn pop_buf(&mut self) { self.stack.pop(); }

    #[inline]
    fn read_byte(&mut self) -> io::IoResult<u8> { self.stack.read_from(&mut self.source) }

    #[inline]
    fn read_byte_pr(&mut self) -> ParseResult<u8> { ParseResult::from_io(self.read_byte()) }

    fn read_line_pr(&mut self, target: &mut Vec<u8>) -> ParseResult<()> {
        loop {
            let b = iotry_err!(self.read_byte()).unwrap();
            target.push(b);
            if b == b'\n' { break; }
        }
        Success(())
    }

    #[inline]
    fn unread_bytes(&mut self, n: uint) { self.stack.unread(n); }

    #[inline]
    fn unread_byte(&mut self) { self.unread_bytes(1); }

    #[inline]
    fn consume(&mut self) { self.stack.consume(); }

    #[inline]
    fn backtrack(&mut self) { self.stack.rewind(); }

    #[inline]
    fn mark(&mut self) -> Mark { self.stack.mark() }

    fn read_char(&mut self, ch: u8) -> ParseResult<()> {
        match self.read_byte() {
            Ok(c) if c == ch => Success(()),
            Ok(_) => NoParse,
            Err(e) => Failure(MarkdownError::from_io(e))
        }
    }

    fn try_read_char(&mut self, ch: u8) -> ParseResult<()> {
        match self.read_byte() {
            Ok(c) if c == ch => Success(()),
            Ok(_) => { self.unread_byte(); NoParse }
            Err(e) => Failure(MarkdownError::from_io(e))
        }
    }

    fn parse_block(&mut self) -> ParseResult<Block> {
        first_of! {
            self.block_quote() or
            self.block_code() or
            self.horizontal_rule() or
            self.heading() or
            self.ordered_list() or
            self.unordered_list() or
            self.paragraph() or
            self.parse_error("a block")
        }
    }

    fn block_quote(&mut self) -> ParseResult<Block> {
        fn block_quote_prefix<R: Reader>(this: &mut MarkdownParser<R>) -> ParseResult<()> {
            try_reset!(this; this.skip_initial_spaces());
            try_reset!(this; this.read_char(b'>'));
            attempt!(this.try_read_char(b' ')) // optional space after >
        }

        try_parse!(try_err_f!(block_quote_prefix(self)));
        self.backtrack();

        let mut buf = Vec::new();
        loop {
            try_err_f!(block_quote_prefix(self));
            try_err_f!(self.read_line_pr(&mut buf));

            // break if there is an empty line followed by non-quote line after this line
            match try_err_f!(self.try_parse_empty_line()) {
                Success(_) => {
                    self.mark().set();
                    match try_err_f!(block_quote_prefix(self)) {
                        NoParse => { self.mark().reset(); break }
                        _ => self.mark().reset()
                    }
                }
                _ => {}
            }
        }

        self.push_existing(buf);
        let (result, err) = self.read_while_possible();
        self.pop_buf();
        self.consume();

        match err {
            Some(e) => if result.is_empty() {
                Failure(e)
            } else {
                PartialSuccess(BlockQuote(result), e)
            },
            None => Success(BlockQuote(result))
        }
    }

    fn block_code(&mut self) -> ParseResult<Block> {
        fn block_code_prefix<R: Reader>(this: &mut MarkdownParser<R>) -> ParseResult<()> {
            try_reset!(this; this.skip_initial_spaces());
            try_reset!(this; this.read_char(b'>'));
            Success(())
        }

        try_parse!(try_err_f!(block_code_prefix(self)));
        self.backtrack();

        let mut buf = Vec::new();
        loop {
            match try_err_f!(block_code_prefix(self)) {
                NoParse => {  // no prefix, check for emptiness
                    self.mark().set();
                    match try_err_f!(self.try_parse_empty_line()) {
                        // non-empty line without prefix
                        NoParse => { self.mark().reset(); break }
                        // empty line without prefix, add newline
                        _ => { self.mark().unset(); buf.push(b'\n') }
                    }
                }
                // prefix is ok, read everything else
                _ => { try_err_f!(self.read_line_pr(&mut buf)); }
            }
        }

        // TODO: handle UTF-8 decoding error
        Success(BlockCode { tag: None, content: String::from_utf8(buf).unwrap() })
    }

    fn try_parse_empty_line(&mut self) -> ParseResult<()> {
        self.mark().set();
        loop {
            // TODO: is it important that the mark can be left set?
            match iotry_err!(self.read_byte()).unwrap() {
                b' ' => {},
                b'\n' => { self.mark().unset(); return Success(()) }
                _ => { self.mark().reset(); return NoParse }
            }
        }
    }

    fn skip_initial_spaces(&mut self) -> ParseResult<()> {
        let mut n: u8 = 0;
        loop {
            if n >= 4 {
                return NoParse;
            }
            match self.read_byte() {
                Ok(b' ') => n += 1,  // increase counter and continue
                Ok(_) => { self.unread_byte(); break },   // not a space and less than 4 spaces
                Err(e) => return Failure(MarkdownError::from_io(e))
            }
        }
        Success(())
    }

    fn horizontal_rule(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn heading(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn ordered_list(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn unordered_list(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn paragraph(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn parse_error<T>(&mut self, what: &str) -> ParseResult<T> {
        parse_error!("unable to parse {}; current buffer contents: {}", what, self.stack.peek().data)
    }
}
<commit_msg>More appropriate error handling<commit_after>#![feature(struct_variant, globs, macro_rules)]

use std::io;

pub use result::*;
pub use tokens::*;

pub mod tokens;
pub mod result;

struct Buf {
    data: Vec<u8>,
    marks: Vec<uint>,
    pos: uint,
    sized: bool
}

struct Mark<'a> {
    buf: &'a mut Buf
}

impl<'a> Mark<'a> {
    fn set(&mut self) {
        self.buf.marks.push(self.buf.pos);
    }

    fn unset(&mut self) {
        assert!(self.buf.marks.len() > 0);
        self.buf.marks.pop();
    }

    fn reset(&mut self) {
        assert!(self.buf.marks.len() > 0);
        self.buf.pos = self.buf.marks.pop().unwrap();
    }
}

impl Buf {
    #[inline]
    fn new_existing(data: Vec<u8>) -> Buf {
        Buf { data: data, marks: Vec::new(), pos: 0, sized: true }
    }

    #[inline]
    fn new() -> Buf {
        Buf { data: Vec::new(), marks: Vec::new(), pos: 0, sized: false }
    }

    fn read_from<R: Reader>(&mut self, source: &mut R) -> io::IoResult<u8> {
        if self.pos < self.data.len() {
            let ch = self.data[self.pos];
            self.pos += 1;
            Ok(ch)
        } else if self.sized {
            Err(io::IoError { kind: io::EndOfFile, desc: "buffer exhausted", detail: None })
        } else {
            source.read_byte().map(|c| {
                self.data.push(c);
                self.pos += 1;
                c
            })
        }
    }

    #[inline]
    fn unread(&mut self, n: uint) {
        assert!(n <= self.pos);
        self.pos -= n;
    }

    #[inline]
    fn rewind(&mut self) {
        self.pos = 0;
    }

    #[inline]
    fn consume(&mut self) {
        self.data.clear();
        self.marks.clear();
        self.pos = 0;
    }

    #[inline]
    fn mark(&mut self) -> Mark {
        Mark { buf: self }
    }
}

struct BufStack {
    bufs: Vec<Buf>
}

impl BufStack {
    #[inline]
    fn new() -> BufStack { BufStack { bufs: Vec::new() } }

    #[inline]
    fn push(&mut self, data: Vec<u8>) {
        self.bufs.push(Buf::new_existing(data))
    }

    #[inline]
    fn push_new(&mut self) {
        self.bufs.push(Buf::new());
    }

    #[inline]
    fn peek(&mut self) -> &mut Buf {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap()
    }

    fn pop(&mut self) {
        assert!(self.bufs.len() > 0);
        self.bufs.pop();
    }

    fn rewind(&mut self) {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().rewind();
    }

    fn consume(&mut self) {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().consume();
    }

    fn read_from<R: Reader>(&mut self, source: &mut R) -> io::IoResult<u8> {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().read_from(source)
    }

    fn unread(&mut self, n: uint) {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().unread(n);
    }

    fn mark(&mut self) -> Mark {
        assert!(self.bufs.len() > 0);
        self.bufs.mut_last().unwrap().mark()
    }
}

pub struct MarkdownParser<R> {
    source: R,
    stack: BufStack
}

impl<R: Reader> MarkdownParser<R> {
    pub fn new(r: R) -> MarkdownParser<R> {
        MarkdownParser {
            source: r,
            stack: BufStack::new()
        }
    }

    pub fn tokens(self) -> MarkdownTokens<R> {
        MarkdownTokens { parser: self }
    }
}

pub struct MarkdownTokens<R> {
    parser: MarkdownParser<R>
}

impl<R: Reader> Iterator<Block> for MarkdownTokens<R> {
    #[inline]
    fn next(&mut self) -> Option<Block> {
        self.parser.next().to_result().ok()
    }
}

macro_rules! first_of(
    ($e:expr) => ($e);
    ($e:expr or $f:expr $(or $more:expr)*) => (
        $e.or_else(|| first_of!($f $(or $more)*))
    )
)

macro_rules! try_reset(
    ($_self:ident; $e:expr) => ({
        $_self.mark().set();
        match $e {
            NoParse => { $_self.mark().reset(); return NoParse }
            r => { $_self.mark().unset(); r }
        }
    })
)

macro_rules! check_reset(
    ($_self:ident; $e:expr) => ({
        $_self.mark().set();
        match $e {
            NoParse => { $_self.mark().reset(); NoParse }
            r => { $_self.mark().unset(); r }
        }
    })
)

macro_rules! try_parse(
    ($e:expr) => (
        match $e {
            NoParse => return NoParse,
            r => r
        }
    )
)

macro_rules! try_err(
    ($e:expr) => (
        match $e {
            Failure(e) => return Failure(e),
            PartialSuccess(r, e) => return PartialSuccess(r, e),
            r => r
        }
    )
)

macro_rules! try_err_f(
    ($e:expr) => (
        match $e {
            Failure(e) => return Failure(e),
            PartialSuccess(_, e) => return Failure(e),
            r => r
        }
    )
)

macro_rules! iotry_err(
    ($e:expr) => (
        match $e {
            Ok(r) => Success(r),
            Err(e) => return Failure(MarkdownError::from_io(e))
        }
    )
)

macro_rules! break_err(
    ($e:expr) => (
        match $e {
            Failure(_) => break,
            PartialSuccess(_, _) => break,
            o => o
        }
    );
    ($e:expr; -> $err:ident) => (
        match $e {
            Failure(e) => { $err = Some(e); break }
            PartialSuccess(_, e) => { $err = Some(e); break }
            o => o
        }
    )
)

macro_rules! attempt(
    ($e:expr) => (
        match $e {
            NoParse => Success(()),
            o => o
        }
    )
)

enum ParseResult<T> {
    NoParse,
    Success(T),
    PartialSuccess(T, MarkdownError),
    Failure(MarkdownError)
}

impl<T> ParseResult<T> {
    #[inline]
    fn from_io(r: io::IoResult<T>) -> ParseResult<T> {
        match r {
            Ok(r) => Success(r),
            Err(e) => Failure(MarkdownError::from_io(e))
        }
    }

    #[inline]
    fn is_np(&self) -> bool {
        match *self {
            NoParse => true,
            _ => false
        }
    }

    #[inline]
    fn unwrap(self) -> T {
        match self {
            Success(r) => r,
            PartialSuccess(r, _) => r,
            Failure(e) => fail!("unwrapping failure: {}", e),
            NoParse => fail!("unwrapping NoParse")
        }
    }

    #[inline]
    fn or_else(self, f: || -> ParseResult<T>) -> ParseResult<T> {
        match self {
            NoParse => f(),
            r => r
        }
    }

    fn to_md_result(self) -> MarkdownResult<T> {
        match self {
            Success(r) => result::Success(r),
            PartialSuccess(r, e) => result::PartialSuccess(r, e),
            Failure(e) => result::Failure(e),
            NoParse => fail!("NoParse is converted to MarkdownResult")
        }
    }
}

macro_rules! parse_error(
    ($s:expr) => (Failure(ParseError(std::str::Slice($s))));
    ($s:expr, $($arg:expr),+) => (Failure(ParseError(std::str::Owned(format!($s, $($arg),+)))))
)

impl<R: Reader> MarkdownParser<R> {
    pub fn read_while_possible(&mut self) -> (Document, Option<MarkdownError>) {
        let mut result = Vec::new();
        loop {
            match self.parse_block() {
                Success(token) => result.push(token),
                PartialSuccess(token, err) => {
                    result.push(token);
                    match err {
                        IoError(ref cause) if cause.kind == io::EndOfFile => break,
                        err => return (result, Some(err))
                    }
                }
                Failure(IoError(ref cause)) if cause.kind == io::EndOfFile => break,
                Failure(err) => return (result, Some(err)),
                NoParse => fail!("unexpected NoParse")
            }
        }
        (result, None)
    }

    #[inline]
    pub fn next(&mut self) -> MarkdownResult<Block> { self.parse_block().to_md_result() }

    #[inline]
    fn push_existing(&mut self, buf: Vec<u8>) { self.stack.push(buf); }

    #[inline]
    fn push_buf(&mut self) { self.stack.push_new(); }

    #[inline]
    fn pop_buf(&mut self) { self.stack.pop(); }

    #[inline]
    fn read_byte(&mut self) -> io::IoResult<u8> { self.stack.read_from(&mut self.source) }

    #[inline]
    fn read_byte_pr(&mut self) -> ParseResult<u8> { ParseResult::from_io(self.read_byte()) }

    fn read_line_pr(&mut self, target: &mut Vec<u8>) -> ParseResult<()> {
        loop {
            let b = iotry_err!(self.read_byte()).unwrap();
            target.push(b);
            if b == b'\n' { break; }
        }
        Success(())
    }

    #[inline]
    fn unread_bytes(&mut self, n: uint) { self.stack.unread(n); }

    #[inline]
    fn unread_byte(&mut self) { self.unread_bytes(1); }

    #[inline]
    fn consume(&mut self) { self.stack.consume(); }

    #[inline]
    fn backtrack(&mut self) { self.stack.rewind(); }

    #[inline]
    fn mark(&mut self) -> Mark { self.stack.mark() }

    fn read_char(&mut self, ch: u8) -> ParseResult<()> {
        match self.read_byte() {
            Ok(c) if c == ch => Success(()),
            Ok(_) => NoParse,
            Err(e) => Failure(MarkdownError::from_io(e))
        }
    }

    fn try_read_char(&mut self, ch: u8) -> ParseResult<()> {
        match self.read_byte() {
            Ok(c) if c == ch => Success(()),
            Ok(_) => { self.unread_byte(); NoParse }
            Err(e) => Failure(MarkdownError::from_io(e))
        }
    }

    fn parse_block(&mut self) -> ParseResult<Block> {
        first_of! {
            self.block_quote() or
            self.block_code() or
            self.horizontal_rule() or
            self.heading() or
            self.ordered_list() or
            self.unordered_list() or
            self.paragraph() or
            self.parse_error("a block")
        }
    }

    fn block_quote(&mut self) -> ParseResult<Block> {
        fn block_quote_prefix<R: Reader>(this: &mut MarkdownParser<R>) -> ParseResult<()> {
            try_reset!(this; this.skip_initial_spaces());
            try_reset!(this; this.read_char(b'>'));
            attempt!(this.try_read_char(b' ')) // optional space after >
        }

        try_parse!(try_err_f!(block_quote_prefix(self)));
        self.backtrack();

        let mut buf = Vec::new();
        let mut err0 = None;
        loop {
            break_err!(block_quote_prefix(self); -> err0);
            break_err!(self.read_line_pr(&mut buf); -> err0);

            // break if there is an empty line followed by non-quote line after this line
            match break_err!(self.try_parse_empty_line(); -> err0) {
                Success(_) => {
                    self.mark().set();
                    match break_err!(block_quote_prefix(self); -> err0) {
                        NoParse => { self.mark().reset(); break }
                        _ => self.mark().reset()
                    }
                }
                _ => {}
            }
        }

        self.push_existing(buf);
        let (result, err) = self.read_while_possible();
        self.pop_buf();
        self.consume();

        // TODO: validate this table and errors priority
        match (err0, err, result.is_empty()) {
            (_,       Some(e), true) => Failure(e),
            (_,       Some(e), false) => PartialSuccess(BlockQuote(result), e),
            (Some(e), None,    _) => PartialSuccess(BlockQuote(result), e),
            (None,    None,    _) => Success(BlockQuote(result))
        }
    }

    fn block_code(&mut self) -> ParseResult<Block> {
        fn block_code_prefix<R: Reader>(this: &mut MarkdownParser<R>) -> ParseResult<()> {
            try_reset!(this; this.skip_initial_spaces());
            try_reset!(this; this.read_char(b'>'));
            Success(())
        }

        try_parse!(try_err_f!(block_code_prefix(self)));
        self.backtrack();

        let mut buf = Vec::new();
        let mut err = None;
        loop {
            match break_err!(block_code_prefix(self); -> err) {
                NoParse => {  // no prefix, check for emptiness
                    self.mark().set();
                    match break_err!(self.try_parse_empty_line(); -> err) {
                        // non-empty line without prefix
                        NoParse => { self.mark().reset(); break }
                        // empty line without prefix, add newline
                        _ => { self.mark().unset(); buf.push(b'\n') }
                    }
                }
                // prefix is ok, read everything else
                _ => { break_err!(self.read_line_pr(&mut buf); -> err); }
            }
        }

        self.consume();

        // TODO: handle UTF-8 decoding error
        let result = BlockCode { tag: None, content: String::from_utf8(buf).unwrap() };
        match err {
            Some(e) => PartialSuccess(result, e),
            None => Success(result)
        }
    }

    fn try_parse_empty_line(&mut self) -> ParseResult<()> {
        self.mark().set();
        loop {
            // TODO: is it important that the mark can be left set?
            match iotry_err!(self.read_byte()).unwrap() {
                b' ' => {},
                b'\n' => { self.mark().unset(); return Success(()) }
                _ => { self.mark().reset(); return NoParse }
            }
        }
    }

    fn skip_initial_spaces(&mut self) -> ParseResult<()> {
        let mut n: u8 = 0;
        loop {
            if n >= 4 {
                return NoParse;
            }
            match self.read_byte() {
                Ok(b' ') => n += 1,  // increase counter and continue
                Ok(_) => { self.unread_byte(); break },   // not a space and less than 4 spaces
                Err(e) => return Failure(MarkdownError::from_io(e))
            }
        }
        Success(())
    }

    fn horizontal_rule(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn heading(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn ordered_list(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn unordered_list(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn paragraph(&mut self) -> ParseResult<Block> {
        NoParse
    }

    fn parse_error<T>(&mut self, what: &str) -> ParseResult<T> {
        parse_error!("unable to parse {}; current buffer contents: {}", what, self.stack.peek().data)
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

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

// like Into trait but works from a ref avoiding consumption or expensive clone
pub trait IntoSexp {
    fn into_sexp(&self) -> Sexp;
}

#[derive(Debug, Clone)]
pub struct Sexp {
    pub element:Element,
    pub meta:Meta,
}

pub struct Compact<'a> {
    what:&'a Sexp,
}

pub fn compact<'a>(e:&'a Sexp) -> Compact<'a> {
    Compact { what:e }
}

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

#[derive(Debug, Clone)]
pub struct Meta {
    indent:String,
    nl:usize,
    after_list:String,
}

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

impl Sexp {

    pub fn new_empty() -> Sexp {
        Sexp { element:Element::Empty, meta:Meta { indent:String::from(""), nl:0, after_list:String::from(""), } }
    }

    pub fn new(element:Element, indent:String, nl:usize, after_list:String) -> Sexp {
        Sexp { element:element, meta:Meta { indent:indent, nl:nl, after_list:after_list, }, }
    }

    pub fn from<T:IntoSexp>(t:&T) -> Sexp {
        t.into_sexp()
    }

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

    pub fn string(&self) -> ERes<&String> {
        match self.element {
            Element::String(ref s) => Ok(s),
            _ => Err(format!("not a string: {}", self))
        }
    }

    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> {
        try!(write!(f, "{}", self.meta.indent));
        try!(match self.element {
            Element::String(ref s) => {
                if s.contains("(") || s.contains(" ") {
                    write!(f,"\"{}\"", s)
                } else {
                    write!(f,"{}", s)
                }
            },
            Element::List(ref v) => {
                try!(write!(f, "("));
                let mut prev_nl = 0;
                for (i, x) in v.iter().enumerate() {
                    let s = if i == 0 || x.meta.indent.len() > 0 || prev_nl > 0 { "" } else { " " };
                    try!(write!(f, "{}{}", s, x));
                    prev_nl = x.meta.nl;
                }
                write!(f, "{})", self.meta.after_list)
            },
            Element::Empty => Ok(())
        });
        for _ in 0..self.meta.nl {
            try!(writeln!(f,""));
        }
        Ok(())
    }
}

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

pub fn display_string(s:&String) -> String {
    if s.contains("(") || s.contains(" ") || s.len() == 0 {
        format!("\"{}\"", s)
    } else {
        s.clone()
    }
}

pub fn parse_str(sexp: &str) -> Result<Sexp, String> {
    if sexp.len() == 0 {
        return Ok(Sexp::new_empty())
    }
    match parse_sexp(&sexp.as_bytes()[..]) {
        nom::IResult::Done(_, c) => Ok(c),
        nom::IResult::Error(err) => {
            match err {
                nom::Err::Position(kind,p) =>
                    Err(format!("parse error: {:?} |{}|", kind, str::from_utf8(p).unwrap())),
                _ => Err(format!("parse error"))
            }
        },
        nom::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<(Element,Option<&[u8]>) >,
       map!(alt!(parse_qstring | parse_bare_string), |x| (Element::String(x), None))
       );

named!(parse_list<(Element,Option<&[u8]>) >,
       chain!(
           char!('(') ~
               v: many0!(parse_sexp) ~
               after_list: opt!(nom::multispace) ~ // sometimes there is space after a closing bracket, this would not be caught by parse_sexp
               char!(')'),
           || (Element::List(v), after_list) )
       );

// TODO: consider lines with just spaces and a nl as also nl
named!(line_ending<usize>,
       chain!(
           opt!(nom::space) ~
               c: opt!(is_a!(b"\r\n"))
               , || match c { None => 0, Some(ref x) => x.len(), }
               )
       );

named!(parse_sexp<Sexp>,
           chain!(
               indent: opt!(nom::space) ~
                   s_after_list: alt!(parse_list | parse_string) ~
                   nl: line_ending
                   ,
               || {
                   let s = s_after_list.0.clone();
                   let after_list = s_after_list.1;
                   let indent = match indent {
                       None => String::new(),
                       Some(x) => String::from(str::from_utf8(x).unwrap()),
                   };
                   let after_list = match after_list {
                       None => String::new(),
                       Some(x) => String::from(str::from_utf8(x).unwrap()),
                   };
                   Sexp::new(s, indent, nl, after_list)
               })
       );

// internal tests
#[test]
fn test_qstring1() {
    let x = parse_string(&b"\"hello world\""[..]);
    match x {
        nom::IResult::Done(_,y) => {
            let (e, _) = y;
            match e {
                Element::String(f) => assert_eq!(String::from("hello world"), f),
                _ => panic!("not string"),
            }
        },
        _ => panic!("parser not done"),
    }
}

/*
#[test]
#[should_panic(expected="assertion failed: `(left == right)` (left: `Incomplete(Size(1))`, right: `Done([], \"hello\")`)")]
fn test_qstring2() {
    parse_string(&b"\"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();
    }
    #[allow(dead_code)]
    fn check_compact(s: &str, o:&str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", compact(&e));
        assert_eq!(o, t)
    }

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

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

    #[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: Alt |)|\"")]
    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)))") }

    #[test]
    fn test_multiline() {
        check_parse("\
(hello \"test it\"
    (foo bar)
    (mars venus)
)
")
    }

    #[test]
    fn test_multiline2() {
        check_parse("\
(hello world
  mad
    (world)
  not)")
    }

    #[test]
    fn test_multiline_two_empty() {
        check_parse("\
(hello

world)")
    }

    #[test]
    fn test_compact1() {
        check_compact("( hello
world \"foo
  bar\"
     (baz)
)", "(hello world \"foo
  bar\" (baz))")
    }

    #[test]
    fn test_fail_pcb() {
        check_parse("\
(kicad_pcb (version 4) (host pcbnew \"(2015-05-31 BZR 5692)-product\")
  (general
  )
)")
    }
}

<commit_msg>trait test<commit_after>#[macro_use]
extern crate nom;

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

// like Into trait but works from a ref avoiding consumption or expensive clone
pub trait IntoSexp {
    fn into_sexp(&self) -> Sexp;
}

pub trait FromSexp {
   fn from(&Sexp) -> Self;
}

#[derive(Debug, Clone)]
pub struct Sexp {
    pub element:Element,
    pub meta:Meta,
}

pub struct Compact<'a> {
    what:&'a Sexp,
}

pub fn compact<'a>(e:&'a Sexp) -> Compact<'a> {
    Compact { what:e }
}

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

#[derive(Debug, Clone)]
pub struct Meta {
    indent:String,
    nl:usize,
    after_list:String,
}

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

impl Sexp {

    pub fn new_empty() -> Sexp {
        Sexp { element:Element::Empty, meta:Meta { indent:String::from(""), nl:0, after_list:String::from(""), } }
    }

    pub fn new(element:Element, indent:String, nl:usize, after_list:String) -> Sexp {
        Sexp { element:element, meta:Meta { indent:indent, nl:nl, after_list:after_list, }, }
    }

    pub fn from<T:IntoSexp>(t:&T) -> Sexp {
        t.into_sexp()
    }

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

    pub fn string(&self) -> ERes<&String> {
        match self.element {
            Element::String(ref s) => Ok(s),
            _ => Err(format!("not a string: {}", self))
        }
    }

    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> {
        try!(write!(f, "{}", self.meta.indent));
        try!(match self.element {
            Element::String(ref s) => {
                if s.contains("(") || s.contains(" ") {
                    write!(f,"\"{}\"", s)
                } else {
                    write!(f,"{}", s)
                }
            },
            Element::List(ref v) => {
                try!(write!(f, "("));
                let mut prev_nl = 0;
                for (i, x) in v.iter().enumerate() {
                    let s = if i == 0 || x.meta.indent.len() > 0 || prev_nl > 0 { "" } else { " " };
                    try!(write!(f, "{}{}", s, x));
                    prev_nl = x.meta.nl;
                }
                write!(f, "{})", self.meta.after_list)
            },
            Element::Empty => Ok(())
        });
        for _ in 0..self.meta.nl {
            try!(writeln!(f,""));
        }
        Ok(())
    }
}

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

pub fn display_string(s:&String) -> String {
    if s.contains("(") || s.contains(" ") || s.len() == 0 {
        format!("\"{}\"", s)
    } else {
        s.clone()
    }
}

pub fn parse_str(sexp: &str) -> Result<Sexp, String> {
    if sexp.len() == 0 {
        return Ok(Sexp::new_empty())
    }
    match parse_sexp(&sexp.as_bytes()[..]) {
        nom::IResult::Done(_, c) => Ok(c),
        nom::IResult::Error(err) => {
            match err {
                nom::Err::Position(kind,p) =>
                    Err(format!("parse error: {:?} |{}|", kind, str::from_utf8(p).unwrap())),
                _ => Err(format!("parse error"))
            }
        },
        nom::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<(Element,Option<&[u8]>) >,
       map!(alt!(parse_qstring | parse_bare_string), |x| (Element::String(x), None))
       );

named!(parse_list<(Element,Option<&[u8]>) >,
       chain!(
           char!('(') ~
               v: many0!(parse_sexp) ~
               after_list: opt!(nom::multispace) ~ // sometimes there is space after a closing bracket, this would not be caught by parse_sexp
               char!(')'),
           || (Element::List(v), after_list) )
       );

// TODO: consider lines with just spaces and a nl as also nl
named!(line_ending<usize>,
       chain!(
           opt!(nom::space) ~
               c: opt!(is_a!(b"\r\n"))
               , || match c { None => 0, Some(ref x) => x.len(), }
               )
       );

named!(parse_sexp<Sexp>,
           chain!(
               indent: opt!(nom::space) ~
                   s_after_list: alt!(parse_list | parse_string) ~
                   nl: line_ending
                   ,
               || {
                   let s = s_after_list.0.clone();
                   let after_list = s_after_list.1;
                   let indent = match indent {
                       None => String::new(),
                       Some(x) => String::from(str::from_utf8(x).unwrap()),
                   };
                   let after_list = match after_list {
                       None => String::new(),
                       Some(x) => String::from(str::from_utf8(x).unwrap()),
                   };
                   Sexp::new(s, indent, nl, after_list)
               })
       );

// internal tests
#[test]
fn test_qstring1() {
    let x = parse_string(&b"\"hello world\""[..]);
    match x {
        nom::IResult::Done(_,y) => {
            let (e, _) = y;
            match e {
                Element::String(f) => assert_eq!(String::from("hello world"), f),
                _ => panic!("not string"),
            }
        },
        _ => panic!("parser not done"),
    }
}

/*
#[test]
#[should_panic(expected="assertion failed: `(left == right)` (left: `Incomplete(Size(1))`, right: `Done([], \"hello\")`)")]
fn test_qstring2() {
    parse_string(&b"\"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();
    }
    #[allow(dead_code)]
    fn check_compact(s: &str, o:&str) {
        let e = parse_str(s).unwrap();
        let t = format!("{}", compact(&e));
        assert_eq!(o, t)
    }

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

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

    #[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: Alt |)|\"")]
    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)))") }

    #[test]
    fn test_multiline() {
        check_parse("\
(hello \"test it\"
    (foo bar)
    (mars venus)
)
")
    }

    #[test]
    fn test_multiline2() {
        check_parse("\
(hello world
  mad
    (world)
  not)")
    }

    #[test]
    fn test_multiline_two_empty() {
        check_parse("\
(hello

world)")
    }

    #[test]
    fn test_compact1() {
        check_compact("( hello
world \"foo
  bar\"
     (baz)
)", "(hello world \"foo
  bar\" (baz))")
    }

    #[test]
    fn test_fail_pcb() {
        check_parse("\
(kicad_pcb (version 4) (host pcbnew \"(2015-05-31 BZR 5692)-product\")
  (general
  )
)")
    }
}

<|endoftext|>