<commit_before>use std::io::buffered::BufferedStream;
use std::io::net::ip::SocketAddr;
use std::io::net::tcp::TcpStream;
use std::vec::bytes::push_bytes;

pub enum Result {
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Error(~str),
  Status(~str)
}

fn read_char(io: &mut BufferedStream<TcpStream>) -> char {
  match io.read_byte() {
    Some(ch) => ch as char,
    None     => fail!()
  }
}

fn parse_data(len: uint, io: &mut BufferedStream<TcpStream>) -> Result {
  let res =
    if (len > 0) {
      let bytes = io.read_bytes(len);
      assert!(bytes.len() == len);
      Data(bytes)
    } else {
      Data(~[])
    };
  assert!(io.read_byte() == Some(13));
  assert!(io.read_byte() == Some(10));
  return res;
}

fn parse_list(len: uint, io: &mut BufferedStream<TcpStream>) -> Result {
  List(std::vec::from_fn(len, |_| { parse_response(io) }))
}

fn parse_int_line(io: &mut BufferedStream<TcpStream>) -> int {
  let mut i: int = 0;
  let mut digits: uint = 0;
  let mut negative: bool = false;

  loop {
    let ch = read_char(io);
    match ch {
      '0' .. '9' => {
        digits += 1;
        i = (i * 10) + (ch as int - '0' as int);
        },
      '-' => {
        if negative { fail!() }
        negative = true
        },
      '\r' => {
        assert!(read_char(io) == '\n');
        break
        },
      '\n' => break,
      _ => fail!()
    }
  }

  if digits == 0 { fail!() }

  if negative { -i }
  else { i }
}

fn parse_n(io: &mut BufferedStream<TcpStream>, f: |uint, &mut BufferedStream<TcpStream>| -> Result) -> Result {
  match parse_int_line(io) {
    -1 => Nil,
    len if len >= 0 => f(len as uint, io),
    _ => fail!()
  }
}

fn parse_status(io: &mut BufferedStream<TcpStream>) -> Result {
  match io.read_line() {
    Some(line) => Status(line),
    None       => fail!()
  }
}

fn parse_error(io: &mut BufferedStream<TcpStream>) -> Result {
  match io.read_line() {
    Some(line) => Error(line),
    None       => fail!()
  }
}

fn parse_response(io: &mut BufferedStream<TcpStream>) -> Result {
  match read_char(io) {
    '$' => parse_n(io, parse_data),
    '*' => parse_n(io, parse_list),
    '+' => parse_status(io),
    '-' => parse_error(io),
    ':' => Int(parse_int_line(io)),
    _   => fail!()
  }
}

fn prepare_cmd(cmd: ~[~str]) -> ~[u8] {
  let mut res: ~[u8] = ~[];
  push_bytes(&mut res, bytes!("*"));
  push_bytes(&mut res, cmd.len().to_str().into_bytes());
  push_bytes(&mut res, bytes!("\r\n"));
  for c in cmd.iter() {
    push_bytes(&mut res, bytes!("$"));
    push_bytes(&mut res, c.len().to_str().into_bytes());
    push_bytes(&mut res, bytes!("\r\n"));
    push_bytes(&mut res, c.as_bytes());
    push_bytes(&mut res, bytes!("\r\n"));
  }
  res
}

fn send_query(cmd: &[u8], io: &mut BufferedStream<TcpStream>) {
  io.write(cmd);
  io.flush();
}

fn recv_query(io: &mut BufferedStream<TcpStream>) -> Result {
  parse_response(io)
}

fn query(cmd: &[u8], io: &mut BufferedStream<TcpStream>) -> Result {
  send_query(cmd, io);
  let res = recv_query(io);
  res
}

fn main() {
  let addr = from_str::<SocketAddr>("127.0.0.1:6379").unwrap();
  let tcp_stream = TcpStream::connect(addr).unwrap();
  let mut reader = BufferedStream::new(tcp_stream);

  let cmd = prepare_cmd(~[~"SET", ~"def", ~"abc"]);

  for i in std::iter::range(1, 100_000) {
    query(cmd, &mut reader);
  }
}
<commit_msg>Introduce a CommandWriter<commit_after>use std::io::buffered::BufferedStream;
use std::io::net::ip::SocketAddr;
use std::io::net::tcp::TcpStream;
use std::vec::bytes::push_bytes;

pub enum Result {
  Nil,
  Int(int),
  Data(~[u8]),
  List(~[Result]),
  Error(~str),
  Status(~str)
}

fn read_char(io: &mut BufferedStream<TcpStream>) -> char {
  match io.read_byte() {
    Some(ch) => ch as char,
    None     => fail!()
  }
}

fn parse_data(len: uint, io: &mut BufferedStream<TcpStream>) -> Result {
  let res =
    if (len > 0) {
      let bytes = io.read_bytes(len);
      assert!(bytes.len() == len);
      Data(bytes)
    } else {
      Data(~[])
    };
  assert!(io.read_byte() == Some(13));
  assert!(io.read_byte() == Some(10));
  return res;
}

fn parse_list(len: uint, io: &mut BufferedStream<TcpStream>) -> Result {
  List(std::vec::from_fn(len, |_| { parse_response(io) }))
}

fn parse_int_line(io: &mut BufferedStream<TcpStream>) -> int {
  let mut i: int = 0;
  let mut digits: uint = 0;
  let mut negative: bool = false;

  loop {
    let ch = read_char(io);
    match ch {
      '0' .. '9' => {
        digits += 1;
        i = (i * 10) + (ch as int - '0' as int);
        },
      '-' => {
        if negative { fail!() }
        negative = true
        },
      '\r' => {
        assert!(read_char(io) == '\n');
        break
        },
      '\n' => break,
      _ => fail!()
    }
  }

  if digits == 0 { fail!() }

  if negative { -i }
  else { i }
}

fn parse_n(io: &mut BufferedStream<TcpStream>, f: |uint, &mut BufferedStream<TcpStream>| -> Result) -> Result {
  match parse_int_line(io) {
    -1 => Nil,
    len if len >= 0 => f(len as uint, io),
    _ => fail!()
  }
}

fn parse_status(io: &mut BufferedStream<TcpStream>) -> Result {
  match io.read_line() {
    Some(line) => Status(line),
    None       => fail!()
  }
}

fn parse_error(io: &mut BufferedStream<TcpStream>) -> Result {
  match io.read_line() {
    Some(line) => Error(line),
    None       => fail!()
  }
}

fn parse_response(io: &mut BufferedStream<TcpStream>) -> Result {
  match read_char(io) {
    '$' => parse_n(io, parse_data),
    '*' => parse_n(io, parse_list),
    '+' => parse_status(io),
    '-' => parse_error(io),
    ':' => Int(parse_int_line(io)),
    _   => fail!()
  }
}

struct CommandWriter {
  buf: ~[u8]
}

impl CommandWriter {
  fn new() -> CommandWriter {
    CommandWriter { buf: ~[] }
  }

  fn args(&mut self, n: uint) {
    self.write_char('*');
    self.write_uint(n);
    self.write_crnl();
  }

  fn arg(&mut self, arg: &str) {
    self.write_char('$');
    self.write_uint(arg.len());
    self.write_crnl();
    self.write_str(arg);
    self.write_crnl();
  }

  fn write_crnl(&mut self) {
    self.write_byte(13);
    self.write_byte(10);
  }

  fn write_uint(&mut self, n: uint) {
    if n < 10 {
      self.write_byte('0' as u8 + (n as u8));
    }
    else {
      push_bytes(&mut self.buf, n.to_str().into_bytes());
    }
  }

  fn write_str(&mut self, s: &str) {
    push_bytes(&mut self.buf, s.as_bytes());
  }

  fn write_char(&mut self, s: char) {
    self.buf.push(s as u8);
  }

  fn write_byte(&mut self, b: u8) {
    self.buf.push(b);
  }

  fn with_buf<T>(&self, f: |&[u8]| -> T) -> T {
    f(self.buf.as_slice())
  }
}

fn execute(cmd: &[u8], io: &mut BufferedStream<TcpStream>) -> Result {
  io.write(cmd);
  io.flush();
  parse_response(io)
}

pub struct Redis<'a> {
  priv io: &'a mut BufferedStream<TcpStream>
}

impl<'a> Redis<'a> {
  pub fn get(&mut self, key: &str) -> Result {
    let mut cwr = CommandWriter::new();
    cwr.args(2);
    cwr.arg("GET");
    cwr.arg(key);
    cwr.with_buf(|cmd| execute(cmd, self.io))
  }

  pub fn set(&mut self, key: &str, val: &str) -> Result {
    let mut cwr = CommandWriter::new();
    cwr.args(3);
    cwr.arg("SET");
    cwr.arg(key);
    cwr.arg(val);
    cwr.with_buf(|cmd| execute(cmd, self.io))
  }
}

fn main() {
  let addr = from_str::<SocketAddr>("127.0.0.1:6379").unwrap();
  let tcp_stream = TcpStream::connect(addr).unwrap();
  let mut reader = BufferedStream::new(tcp_stream);
  let mut redis = Redis { io: &mut reader };

  //let x = redis.get("key");
  //println!("{:?}", x);

  for i in std::iter::range(1, 100_000) {
    redis.set("key", "abc");
  }
}
<|endoftext|>


<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>make Layout::new pub<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    pub fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    l[0].i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string()).clone();
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string()).clone();
    let desc = try!(l[1].string()).clone();
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()).clone())
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>


<commit_before>import std.os.libc;
import std._str;
import std._vec;

type stdio_reader = state obj {
                          fn getc() -> int;
                          fn ungetc(int i);
};

fn new_stdio_reader(str path) -> stdio_reader {
    state obj stdio_FILE_reader(os.libc.FILE f) {
        fn getc() -> int {
            ret os.libc.fgetc(f);
        }
        fn ungetc(int i) {
            os.libc.ungetc(i, f);
        }
        drop {
            os.libc.fclose(f);
        }
    }
    auto FILE = os.libc.fopen(_str.buf(path), _str.buf("r"));
    check (FILE as uint != 0u);
    ret stdio_FILE_reader(FILE);
}

type buf_reader = state obj {
                        fn read() -> vec[u8];
};

type buf_writer = state obj {
                        fn write(vec[u8] v);
};

fn default_bufsz() -> uint {
    ret 4096u;
}

fn new_buf() -> vec[u8] {
    ret _vec.alloc[u8](default_bufsz());
}

fn new_buf_reader(str path) -> buf_reader {

    state obj fd_buf_reader(int fd, mutable vec[u8] buf) {

        fn read() -> vec[u8] {

            // Ensure our buf is singly-referenced.
            if (_vec.rustrt.refcount[u8](buf) != 1u) {
                buf = new_buf();
            }

            auto len = default_bufsz();
            auto vbuf = _vec.buf[u8](buf);
            auto count = os.libc.read(fd, vbuf, len);

            if (count < 0) {
                log "error filling buffer";
                log sys.rustrt.last_os_error();
                fail;
            }

            _vec.len_set[u8](buf, count as uint);
            ret buf;
        }

        drop {
            os.libc.close(fd);
        }
    }

    auto fd = os.libc.open(_str.buf(path),
                           os.libc_constants.O_RDONLY() |
                           os.libc_constants.O_BINARY(),
                           0u);

    if (fd < 0) {
        log "error opening file for reading";
        log sys.rustrt.last_os_error();
        fail;
    }
    ret fd_buf_reader(fd, new_buf());
}

tag fileflag {
    append;
    create;
    truncate;
}

fn writefd(int fd, vec[u8] v) {
    auto len = _vec.len[u8](v);
    auto count = 0u;
    auto vbuf;
    while (count < len) {
        vbuf = _vec.buf_off[u8](v, count);
        auto nout = os.libc.write(fd, vbuf, len);
        if (nout < 0) {
            log "error dumping buffer";
            log sys.rustrt.last_os_error();
            fail;
        }
        count += nout as uint;
    }
}

fn new_buf_writer(str path, vec[fileflag] flags) -> buf_writer {

    state obj fd_buf_writer(int fd) {

        fn write(vec[u8] v) {
            writefd(fd, v);
        }

        drop {
            os.libc.close(fd);
        }
    }

    let int fflags =
        os.libc_constants.O_WRONLY() |
        os.libc_constants.O_BINARY();

    for (fileflag f in flags) {
        alt (f) {
            case (append)   { fflags |= os.libc_constants.O_APPEND(); }
            case (create)   { fflags |= os.libc_constants.O_CREAT(); }
            case (truncate) { fflags |= os.libc_constants.O_TRUNC(); }
        }
    }

    auto fd = os.libc.open(_str.buf(path),
                           fflags,
                           os.libc_constants.S_IRUSR() |
                           os.libc_constants.S_IWUSR());

    if (fd < 0) {
        log "error opening file for writing";
        log sys.rustrt.last_os_error();
        fail;
    }
    ret fd_buf_writer(fd);
}

type writer =
    state obj {
          fn write_str(str s);
          fn write_int(int n);
          fn write_uint(uint n);
    };

fn file_writer(str path,
               vec[fileflag] flags)
    -> writer
{
    state obj fw(buf_writer out) {
        fn write_str(str s)   { out.write(_str.bytes(s)); }
        fn write_int(int n)   { out.write(_str.bytes(_int.to_str(n, 10u))); }
        fn write_uint(uint n) { out.write(_str.bytes(_uint.to_str(n, 10u))); }
    }
    ret fw(new_buf_writer(path, flags));
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>Add stdout_writer and string_writer to std.io<commit_after>import std.os.libc;
import std._str;
import std._vec;

type stdio_reader = state obj {
                          fn getc() -> int;
                          fn ungetc(int i);
};

fn new_stdio_reader(str path) -> stdio_reader {
    state obj stdio_FILE_reader(os.libc.FILE f) {
        fn getc() -> int {
            ret os.libc.fgetc(f);
        }
        fn ungetc(int i) {
            os.libc.ungetc(i, f);
        }
        drop {
            os.libc.fclose(f);
        }
    }
    auto FILE = os.libc.fopen(_str.buf(path), _str.buf("r"));
    check (FILE as uint != 0u);
    ret stdio_FILE_reader(FILE);
}

type buf_reader = state obj {
                        fn read() -> vec[u8];
};

type buf_writer = state obj {
                        fn write(vec[u8] v);
};

fn default_bufsz() -> uint {
    ret 4096u;
}

fn new_buf() -> vec[u8] {
    ret _vec.alloc[u8](default_bufsz());
}

fn new_buf_reader(str path) -> buf_reader {

    state obj fd_buf_reader(int fd, mutable vec[u8] buf) {

        fn read() -> vec[u8] {

            // Ensure our buf is singly-referenced.
            if (_vec.rustrt.refcount[u8](buf) != 1u) {
                buf = new_buf();
            }

            auto len = default_bufsz();
            auto vbuf = _vec.buf[u8](buf);
            auto count = os.libc.read(fd, vbuf, len);

            if (count < 0) {
                log "error filling buffer";
                log sys.rustrt.last_os_error();
                fail;
            }

            _vec.len_set[u8](buf, count as uint);
            ret buf;
        }

        drop {
            os.libc.close(fd);
        }
    }

    auto fd = os.libc.open(_str.buf(path),
                           os.libc_constants.O_RDONLY() |
                           os.libc_constants.O_BINARY(),
                           0u);

    if (fd < 0) {
        log "error opening file for reading";
        log sys.rustrt.last_os_error();
        fail;
    }
    ret fd_buf_reader(fd, new_buf());
}

tag fileflag {
    append;
    create;
    truncate;
}

// FIXME move into fd_buf_writer
fn writefd(int fd, vec[u8] v) {
    auto len = _vec.len[u8](v);
    auto count = 0u;
    auto vbuf;
    while (count < len) {
        vbuf = _vec.buf_off[u8](v, count);
        auto nout = os.libc.write(fd, vbuf, len);
        if (nout < 0) {
            log "error dumping buffer";
            log sys.rustrt.last_os_error();
            fail;
        }
        count += nout as uint;
    }
}

state obj fd_buf_writer(int fd, bool must_close) {
    fn write(vec[u8] v) {
        writefd(fd, v);
    }

    drop {
        if (must_close) {os.libc.close(fd);}
    }
}

fn file_buf_writer(str path, vec[fileflag] flags) -> buf_writer {
    let int fflags =
        os.libc_constants.O_WRONLY() |
        os.libc_constants.O_BINARY();

    for (fileflag f in flags) {
        alt (f) {
            case (append)   { fflags |= os.libc_constants.O_APPEND(); }
            case (create)   { fflags |= os.libc_constants.O_CREAT(); }
            case (truncate) { fflags |= os.libc_constants.O_TRUNC(); }
        }
    }

    auto fd = os.libc.open(_str.buf(path),
                           fflags,
                           os.libc_constants.S_IRUSR() |
                           os.libc_constants.S_IWUSR());

    if (fd < 0) {
        log "error opening file for writing";
        log sys.rustrt.last_os_error();
        fail;
    }
    ret fd_buf_writer(fd, true);
}

type writer =
    state obj {
          impure fn write_str(str s);
          impure fn write_int(int n);
          impure fn write_uint(uint n);
    };

state obj new_writer(buf_writer out) {
    impure fn write_str(str s)   { out.write(_str.bytes(s)); }
    impure fn write_int(int n)   { out.write(_str.bytes(_int.to_str(n, 10u))); }
    impure fn write_uint(uint n) { out.write(_str.bytes(_uint.to_str(n, 10u))); }
}

fn file_writer(str path, vec[fileflag] flags) -> writer {
    ret new_writer(file_buf_writer(path, flags));
}

// FIXME it would be great if this could be a const named stdout
fn stdout_writer() -> writer {
    ret new_writer(fd_buf_writer(1, false));
}

type str_writer =
    state obj {
          fn get_writer() -> writer;
          fn get_str() -> str;
    };

type str_buf = @rec(mutable str buf);

// TODO awkward! it's not possible to implement a writer with an extra method
fn string_writer() -> str_writer {
    auto buf = @rec(mutable buf = "");
    state obj str_writer_writer(str_buf buf) {
        impure fn write_str(str s)   { buf.buf += s; }
        impure fn write_int(int n)   { buf.buf += _int.to_str(n, 10u); }
        impure fn write_uint(uint n) { buf.buf += _uint.to_str(n, 10u); }
    }
    state obj str_writer_wrap(writer wr, str_buf buf) {
        fn get_writer() -> writer {ret wr;}
        fn get_str() -> str {ret buf.buf;}
    }
    ret str_writer_wrap(str_writer_writer(buf), buf);
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>#![cfg(feature = "ds")]

extern crate rusoto_core;
extern crate rusoto_ds;

use rusoto_core::Region;
use rusoto_ds::{
    DescribeDirectoriesRequest, DescribeTrustsRequest, DirectoryService, DirectoryServiceClient,
};

#[test]
fn should_describe_trusts() {
    let client = DirectoryServiceClient::new(Region::UsEast1);
    let request = DescribeTrustsRequest::default();

    client.describe_trusts(request).sync().unwrap();
}

#[test]
fn should_describe_directories() {
    let client = DirectoryServiceClient::new(Region::UsEast1);
    let request = DescribeDirectoriesRequest::default();

    client.describe_directories(request).sync().unwrap();
}
<commit_msg>fix ds integration tests<commit_after>#![cfg(feature = "ds")]

extern crate rusoto_core;
extern crate rusoto_ds;

use rusoto_core::Region;
use rusoto_ds::{
    DescribeDirectoriesRequest, DescribeTrustsRequest, DirectoryService, DirectoryServiceClient,
};

#[test]
fn should_describe_trusts() {
    let client = DirectoryServiceClient::new(Region::UsWest2);
    let request = DescribeTrustsRequest::default();

    client.describe_trusts(request).sync().unwrap();
}

#[test]
fn should_describe_directories() {
    let client = DirectoryServiceClient::new(Region::UsWest2);
    let request = DescribeDirectoriesRequest::default();

    client.describe_directories(request).sync().unwrap();
}
<|endoftext|>


<commit_before>//! # Logger
//!
//! Loggers are thread-safe and reference counted, so can be freely
//! passed around the code.
//!
//! Each logger is built with a set of key-values.
//!
//! Child loggers are build from existing loggers, and copy
//! all the key-values from their parents
//!
//! Loggers form hierarchies sharing a drain. Setting a drain on
//! any logger will change it on all loggers in given hierarchy.
use super::{OwnedKeyValue, Level, BorrowedKeyValue};
use std::sync::Arc;
use std::cell::RefCell;
use std::io;

use drain;

use chrono;

thread_local! {
    static TL_BUF: RefCell<Vec<u8>> = RefCell::new(Vec::with_capacity(128))
}

// TODO: Implement custom clone, that starts with a new buffer
#[derive(Clone)]
/// Logger
pub struct Logger {
    drain: Arc<drain::Drain>,
    values: Vec<OwnedKeyValue>,
}

pub trait IntoMsg {
    fn as_str(&self) -> &str;
}
/*
impl IntoMsg for str {
    fn as_str(&self) -> &str {
       self.as_str()
    }
}*/

impl<'a> IntoMsg for &'a str {
    fn as_str(&self) -> &str {
        self
    }
}

impl IntoMsg for String {
    fn as_str(&self) -> &str {
        (self as &String).as_str()
    }
}

impl Logger {
    /// Build a root logger
    ///
    /// All children and their children and so on form one hierarchy
    /// sharing a common drain.
    ///
    /// Use `o!` macro to help build `values`
    ///
    /// ```
    /// #[macro_use]
    /// extern crate slog;
    ///
    /// fn main() {
    ///     let root = slog::Logger::new_root(o!("key1" => "value1", "key2" => "value2"), slog::drain::discard());
    /// }
    pub fn new_root<D : 'static+drain::Drain+Sized>(values: &[OwnedKeyValue], d : D) -> Logger {
        Logger {
            drain: Arc::new(d),
            values: values.to_vec(),
        }
    }

    /// Build a child logger
    ///
    /// Child logger copies all existing values from the parent.
    ///
    /// All children, their children and so on, form one hierarchy sharing
    /// a common drain.
    ///
    /// Use `o!` macro to help build `values`
    ///
    /// ```
    /// #[macro_use]
    /// extern crate slog;
    /// use slog::drain::IntoLogger;
    ///
    /// fn main() {
    ///     let root = slog::drain::discard().into_logger(o!("key1" => "value1", "key2" => "value2"));
    ///     let log = root.new(o!("key" => "value"));
    /// }
    pub fn new(&self, values: &[OwnedKeyValue]) -> Logger {
        let mut new_values = self.values.clone();
        new_values.extend_from_slice(values);
        Logger {
            drain: self.drain.clone(),
            values: new_values,
        }
    }

    /// Log one logging record
    ///
    /// Use specific logging functions instead.
    pub fn log(&self, lvl: Level, msg: &IntoMsg, values: &[BorrowedKeyValue]) {

        let mut info = RecordInfo::new(lvl, msg);

        // By default errors in loggers are ignored
        TL_BUF.with(|buf| {
            let mut buf = buf.borrow_mut();
            let _ = self.drain.log(&mut *buf, &mut info, self.values.as_slice(), values);
            // TODO: Double check if this will not zero the old bytes as it costs time
            buf.clear();
        });
    }

    /// Log critical level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn critical<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Critical, &msg, values);
    }

    /// Log error level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn error<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Error, &msg, values);
    }

    /// Log warning level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn warn<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Warning, &msg, values);
    }

    /// Log info level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn info<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Info, &msg, values);
    }

    /// Log debug level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn debug<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Debug, &msg, values);
    }

    /// Log trace level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn trace<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Trace, &msg, values);
    }
}

/// Common information about a logging record
pub struct RecordInfo<'a> {
    ts: RefCell<Option<chrono::DateTime<chrono::UTC>>>,
    /// Logging level
    level: Level,
    /// Message
    msg: &'a IntoMsg,
}

impl<'a> RecordInfo<'a> {
    /// Create a new `RecordInfo` with a current timestamp
    pub fn new(level: Level, msg: &'a IntoMsg) -> Self {
        RecordInfo {
            ts: RefCell::new(None),
            level: level,
            msg: msg,
        }
    }

    /// Timestamp
    ///
    /// Lazily evaluated timestamp
    pub fn ts(&self) -> chrono::DateTime<chrono::UTC> {
        let mut ts = self.ts.borrow_mut();
        match *ts {
            None => {
                let now = chrono::UTC::now();
                *ts = Some(now);
                now
            },
            Some(ts) => ts
        }
    }

    /// Set timestamp
    pub fn set_ts(&self, ts : chrono::DateTime<chrono::UTC>) {
        *self.ts.borrow_mut() = Some(ts);
    }

    /// Get a log record message
    pub fn msg(&self) -> &str {
        self.msg.as_str()
    }

    /// Get record logging level
    pub fn level(&self) -> Level {
        self.level
    }
}
<commit_msg>Improve abstract of msg<commit_after>//! # Logger
//!
//! Loggers are thread-safe and reference counted, so can be freely
//! passed around the code.
//!
//! Each logger is built with a set of key-values.
//!
//! Child loggers are build from existing loggers, and copy
//! all the key-values from their parents
//!
//! Loggers form hierarchies sharing a drain. Setting a drain on
//! any logger will change it on all loggers in given hierarchy.
use super::{OwnedKeyValue, Level, BorrowedKeyValue};
use std::sync::Arc;
use std::cell::RefCell;
use std::io;

use drain;

use chrono;

thread_local! {
    static TL_BUF: RefCell<Vec<u8>> = RefCell::new(Vec::with_capacity(128))
}

// TODO: Implement custom clone, that starts with a new buffer
#[derive(Clone)]
/// Logger
pub struct Logger {
    drain: Arc<drain::Drain>,
    values: Vec<OwnedKeyValue>,
}

pub trait IntoMsg {
    fn as_str(&self) -> &str;
}

impl<T : AsRef<str>> IntoMsg for T {
    fn as_str(&self) -> &str {
        self.as_ref()
    }
}

impl Logger {
    /// Build a root logger
    ///
    /// All children and their children and so on form one hierarchy
    /// sharing a common drain.
    ///
    /// Use `o!` macro to help build `values`
    ///
    /// ```
    /// #[macro_use]
    /// extern crate slog;
    ///
    /// fn main() {
    ///     let root = slog::Logger::new_root(o!("key1" => "value1", "key2" => "value2"), slog::drain::discard());
    /// }
    pub fn new_root<D : 'static+drain::Drain+Sized>(values: &[OwnedKeyValue], d : D) -> Logger {
        Logger {
            drain: Arc::new(d),
            values: values.to_vec(),
        }
    }

    /// Build a child logger
    ///
    /// Child logger copies all existing values from the parent.
    ///
    /// All children, their children and so on, form one hierarchy sharing
    /// a common drain.
    ///
    /// Use `o!` macro to help build `values`
    ///
    /// ```
    /// #[macro_use]
    /// extern crate slog;
    /// use slog::drain::IntoLogger;
    ///
    /// fn main() {
    ///     let root = slog::drain::discard().into_logger(o!("key1" => "value1", "key2" => "value2"));
    ///     let log = root.new(o!("key" => "value"));
    /// }
    pub fn new(&self, values: &[OwnedKeyValue]) -> Logger {
        let mut new_values = self.values.clone();
        new_values.extend_from_slice(values);
        Logger {
            drain: self.drain.clone(),
            values: new_values,
        }
    }

    /// Log one logging record
    ///
    /// Use specific logging functions instead.
    pub fn log(&self, lvl: Level, msg: &IntoMsg, values: &[BorrowedKeyValue]) {

        let mut info = RecordInfo::new(lvl, msg);

        // By default errors in loggers are ignored
        TL_BUF.with(|buf| {
            let mut buf = buf.borrow_mut();
            let _ = self.drain.log(&mut *buf, &mut info, self.values.as_slice(), values);
            // TODO: Double check if this will not zero the old bytes as it costs time
            buf.clear();
        });
    }

    /// Log critical level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn critical<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Critical, &msg, values);
    }

    /// Log error level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn error<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Error, &msg, values);
    }

    /// Log warning level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn warn<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Warning, &msg, values);
    }

    /// Log info level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn info<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Info, &msg, values);
    }

    /// Log debug level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn debug<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Debug, &msg, values);
    }

    /// Log trace level record
    ///
    /// Use `b!` macro to help build `values`
    pub fn trace<M : IntoMsg>(&self, msg: M, values: &[BorrowedKeyValue]) {
        self.log(Level::Trace, &msg, values);
    }
}

/// Common information about a logging record
pub struct RecordInfo<'a> {
    ts: RefCell<Option<chrono::DateTime<chrono::UTC>>>,
    /// Logging level
    level: Level,
    /// Message
    msg: &'a IntoMsg,
}

impl<'a> RecordInfo<'a> {
    /// Create a new `RecordInfo` with a current timestamp
    pub fn new(level: Level, msg: &'a IntoMsg) -> Self {
        RecordInfo {
            ts: RefCell::new(None),
            level: level,
            msg: msg,
        }
    }

    /// Timestamp
    ///
    /// Lazily evaluated timestamp
    pub fn ts(&self) -> chrono::DateTime<chrono::UTC> {
        let mut ts = self.ts.borrow_mut();
        match *ts {
            None => {
                let now = chrono::UTC::now();
                *ts = Some(now);
                now
            },
            Some(ts) => ts
        }
    }

    /// Set timestamp
    pub fn set_ts(&self, ts : chrono::DateTime<chrono::UTC>) {
        *self.ts.borrow_mut() = Some(ts);
    }

    /// Get a log record message
    pub fn msg(&self) -> &str {
        self.msg.as_str()
    }

    /// Get record logging level
    pub fn level(&self) -> Level {
        self.level
    }
}
<|endoftext|>


<commit_before>// Vector/Point macros
macro_rules! n_pointvector {
    (ops $lhs:ident; $rhs:ident {$($field:ident),*}) => {
        impl<F: Float> ::std::ops::Add<$rhs<F>> for $lhs<F> {
            type Output = $lhs<F>;

            fn add(self, rhs: $rhs<F>) -> $lhs<F> {
                $lhs {
                    $($field: self.$field + rhs.$field),*
                }
            }
        }

        impl<F: Float> ::std::ops::Sub<$rhs<F>> for $lhs<F> {
            type Output = $lhs<F>;

            fn sub(self, rhs: $rhs<F>) -> $lhs<F> {
                $lhs {
                    $($field: self.$field - rhs.$field),*
                }
            }
        }
    };

    (float ops $name:ident {$($field:ident),+}) => {
        impl<F: Float> Mul<F> for $name<F> {
            type Output = $name<F>;

            fn mul(self, rhs: F) -> $name<F> {
                $name {
                    $($field: self.$field * rhs),+
                }
            }
        }

        impl<F: Float> Div<F> for $name<F> {
            type Output = $name<F>;

            fn div(self, rhs: F) -> $name<F> {
                $name {
                    $($field: self.$field / rhs),+
                }
            }
        }

        impl<F: Float> Neg for $name<F> {
            type Output = $name<F>;

            fn neg(self) -> $name<F> {
                $name {
                    $($field: -self.$field),+
                }
            }
        }
    };

    (struct $dims:expr; $name:ident {$($field:ident: $f_ty:ident),+} $sibling:ident) => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F: Float> {
            $(pub $field: F),+
        }

        impl<F: Float> $name<F> {
            pub fn new($($field: F),+) -> $name<F> {
                $name {
                    $($field: $field),+
                }
            }
        }

        impl<F: Float> ::std::convert::Into<[F; $dims]> for $name<F> {
            fn into(self) -> [F; $dims] {
                [$(self.$field),*]
            }
        }

        impl<F: Float> ::std::convert::Into<($($f_ty),*)> for $name<F> {
            fn into(self) -> ($($f_ty),*) {
                ($(self.$field),*)
            }
        }

        impl<F: Float> ::std::convert::From<$sibling<F>> for $name<F> {
            fn from(sib: $sibling<F>) -> $name<F> {
                $name {
                    $($field: sib.$field),*
                }
            }
        }

        n_pointvector!(ops $name; $sibling {$($field),+});
        n_pointvector!(ops $name; $name {$($field),+});
        n_pointvector!(float ops $name {$($field),+});
    };

    ($dims:expr; $p_name:ident, $v_name:ident {$($field:ident),+}) => {
        n_pointvector!(struct $dims; $p_name {$($field: F),+} $v_name);
        n_pointvector!(struct $dims; $v_name {$($field: F),+} $p_name);

        impl<F: Float + FromPrimitive> $v_name<F> {
            pub fn len(self) -> F {
                ($(self.$field.powi(2) +)+ F::from_f32(0.0).unwrap()).sqrt()
            }

            pub fn normalize(self) -> $v_name<F> {
                self / self.len()
            }
        }
    }
}

// Polynomial Macros
macro_rules! count {
    ($idc:tt) => (1);
    ($($element:tt),*) => {{$(count!($element) +)* 0}};
}

macro_rules! n_bezier {
    ($name:ident {
        $($field:ident: $weight:expr),+
    } derived {
        $($dleft:ident - $dright:ident: $dweight:expr),+
    }) => {
        #[derive(Debug, Clone)]
        pub struct $name<F> where F: ::num::Float + ::num::FromPrimitive {
            $(pub $field: F),+
        }

        impl<F> $name<F> where F: ::num::Float + ::num::FromPrimitive {
            pub fn new($($field: F),+) -> $name<F> {
                $name {
                    $($field: $field),+
                }
            }

            pub fn interp(&self, t: F) -> F {
                $crate::check_t_bounds(t);
                self.interp_unbounded(t)
            }

            pub fn interp_unbounded(&self, t: F) -> F {
                let t1 = F::from_f32(1.0).unwrap() - t;
                const COUNT: i32 = count!($($field),+) - 1;
                let mut factor = COUNT + 1;

                $(
                    factor -= 1;
                    let $field =
                        t1.powi(factor) *
                        t.powi(COUNT-factor) *
                        self.$field *
                        F::from_i32($weight).unwrap();
                )+
                $($field +)+ F::from_f32(0.0).unwrap()
            }

            pub fn slope(&self, t: F) -> F {
                $crate::check_t_bounds(t);
                self.slope_unbounded(t)
            }

            pub fn slope_unbounded(&self, t: F) -> F {
                let t1 = F::from_f32(1.0).unwrap() - t;
                const COUNT: i32 = count!($($dleft),+) - 1;
                let mut factor = COUNT + 1;

                $(
                    factor -= 1;
                    let $dleft =
                        t1.powi(factor) *
                        t.powi(COUNT-factor) *
                        (self.$dleft - self.$dright) *
                        F::from_i32($dweight * (COUNT + 1)).unwrap();
                )+
                $($dleft +)+ F::from_f32(0.0).unwrap()
            }
        }

        impl<F> ::std::ops::Deref for $name<F> where F: ::num::Float + ::num::FromPrimitive {
            type Target = [F];
            fn deref(&self) -> &[F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts(self as *const $name<F> as *const F, count!($($field),+))
                }
            }
        }

        impl<F> ::std::ops::DerefMut for $name<F> where F: ::num::Float + ::num::FromPrimitive {
            fn deref_mut(&mut self) -> &mut [F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts_mut(self as *mut $name<F> as *mut F, count!($($field),+))
                }
            }
        }
    }
}

macro_rules! bez_composite {
    ($name:ident<$poly:ident> {
        $($field:ident: $($n_field:ident),+;)+
    } -> <$point:ident; $vector:ident>;
        $($dim:ident = $($dfield:ident),+;)+) =>
    {
        #[derive(Debug, Clone)]
        pub struct $name<F: ::num::Float + ::num::FromPrimitive> {
            $(pub $field: $point<F>),+
        }

        impl<F: ::num::Float + ::num::FromPrimitive> $name<F> {
            pub fn new($($($n_field: F),+),+) -> $name<F> {
                $name {
                    $($field: $point::new($($n_field),+)),+
                }
            }

            pub fn interp(&self, t: F) -> $point<F> {
                $crate::check_t_bounds(t);
                self.interp_unbounded(t)
            }

            pub fn interp_unbounded(&self, t: F) -> $point<F> {
                $(let $dim = $poly::new($(self.$dfield.$dim),+);)+
                $point::new($($dim.interp_unbounded(t)),+)
            }

            pub fn slope(&self, t: F) -> $vector<F> {
                $crate::check_t_bounds(t);
                self.slope_unbounded(t)
            }

            pub fn slope_unbounded(&self, t: F) -> $vector<F> {
                $(let $dim = $poly::new($(self.$dfield.$dim),+);)+
                $vector::new($($dim.slope_unbounded(t)),+)
            }
        }
    };
}<commit_msg>Added `Copy` implementations for bezier polynomials and curves.<commit_after>// Vector/Point macros
macro_rules! n_pointvector {
    (ops $lhs:ident; $rhs:ident {$($field:ident),*}) => {
        impl<F: Float> ::std::ops::Add<$rhs<F>> for $lhs<F> {
            type Output = $lhs<F>;

            fn add(self, rhs: $rhs<F>) -> $lhs<F> {
                $lhs {
                    $($field: self.$field + rhs.$field),*
                }
            }
        }

        impl<F: Float> ::std::ops::Sub<$rhs<F>> for $lhs<F> {
            type Output = $lhs<F>;

            fn sub(self, rhs: $rhs<F>) -> $lhs<F> {
                $lhs {
                    $($field: self.$field - rhs.$field),*
                }
            }
        }
    };

    (float ops $name:ident {$($field:ident),+}) => {
        impl<F: Float> Mul<F> for $name<F> {
            type Output = $name<F>;

            fn mul(self, rhs: F) -> $name<F> {
                $name {
                    $($field: self.$field * rhs),+
                }
            }
        }

        impl<F: Float> Div<F> for $name<F> {
            type Output = $name<F>;

            fn div(self, rhs: F) -> $name<F> {
                $name {
                    $($field: self.$field / rhs),+
                }
            }
        }

        impl<F: Float> Neg for $name<F> {
            type Output = $name<F>;

            fn neg(self) -> $name<F> {
                $name {
                    $($field: -self.$field),+
                }
            }
        }
    };

    (struct $dims:expr; $name:ident {$($field:ident: $f_ty:ident),+} $sibling:ident) => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F: Float> {
            $(pub $field: F),+
        }

        impl<F: Float> $name<F> {
            pub fn new($($field: F),+) -> $name<F> {
                $name {
                    $($field: $field),+
                }
            }
        }

        impl<F: Float> ::std::convert::Into<[F; $dims]> for $name<F> {
            fn into(self) -> [F; $dims] {
                [$(self.$field),*]
            }
        }

        impl<F: Float> ::std::convert::Into<($($f_ty),*)> for $name<F> {
            fn into(self) -> ($($f_ty),*) {
                ($(self.$field),*)
            }
        }

        impl<F: Float> ::std::convert::From<$sibling<F>> for $name<F> {
            fn from(sib: $sibling<F>) -> $name<F> {
                $name {
                    $($field: sib.$field),*
                }
            }
        }

        n_pointvector!(ops $name; $sibling {$($field),+});
        n_pointvector!(ops $name; $name {$($field),+});
        n_pointvector!(float ops $name {$($field),+});
    };

    ($dims:expr; $p_name:ident, $v_name:ident {$($field:ident),+}) => {
        n_pointvector!(struct $dims; $p_name {$($field: F),+} $v_name);
        n_pointvector!(struct $dims; $v_name {$($field: F),+} $p_name);

        impl<F: Float + FromPrimitive> $v_name<F> {
            pub fn len(self) -> F {
                ($(self.$field.powi(2) +)+ F::from_f32(0.0).unwrap()).sqrt()
            }

            pub fn normalize(self) -> $v_name<F> {
                self / self.len()
            }
        }
    }
}

// Polynomial Macros
macro_rules! count {
    ($idc:tt) => (1);
    ($($element:tt),*) => {{$(count!($element) +)* 0}};
}

macro_rules! n_bezier {
    ($name:ident {
        $($field:ident: $weight:expr),+
    } derived {
        $($dleft:ident - $dright:ident: $dweight:expr),+
    }) => {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F> where F: ::num::Float + ::num::FromPrimitive {
            $(pub $field: F),+
        }

        impl<F> $name<F> where F: ::num::Float + ::num::FromPrimitive {
            pub fn new($($field: F),+) -> $name<F> {
                $name {
                    $($field: $field),+
                }
            }

            pub fn interp(&self, t: F) -> F {
                $crate::check_t_bounds(t);
                self.interp_unbounded(t)
            }

            pub fn interp_unbounded(&self, t: F) -> F {
                let t1 = F::from_f32(1.0).unwrap() - t;
                const COUNT: i32 = count!($($field),+) - 1;
                let mut factor = COUNT + 1;

                $(
                    factor -= 1;
                    let $field =
                        t1.powi(factor) *
                        t.powi(COUNT-factor) *
                        self.$field *
                        F::from_i32($weight).unwrap();
                )+
                $($field +)+ F::from_f32(0.0).unwrap()
            }

            pub fn slope(&self, t: F) -> F {
                $crate::check_t_bounds(t);
                self.slope_unbounded(t)
            }

            pub fn slope_unbounded(&self, t: F) -> F {
                let t1 = F::from_f32(1.0).unwrap() - t;
                const COUNT: i32 = count!($($dleft),+) - 1;
                let mut factor = COUNT + 1;

                $(
                    factor -= 1;
                    let $dleft =
                        t1.powi(factor) *
                        t.powi(COUNT-factor) *
                        (self.$dleft - self.$dright) *
                        F::from_i32($dweight * (COUNT + 1)).unwrap();
                )+
                $($dleft +)+ F::from_f32(0.0).unwrap()
            }
        }

        impl<F> ::std::ops::Deref for $name<F> where F: ::num::Float + ::num::FromPrimitive {
            type Target = [F];
            fn deref(&self) -> &[F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts(self as *const $name<F> as *const F, count!($($field),+))
                }
            }
        }

        impl<F> ::std::ops::DerefMut for $name<F> where F: ::num::Float + ::num::FromPrimitive {
            fn deref_mut(&mut self) -> &mut [F] {
                use std::slice;
                unsafe {
                    slice::from_raw_parts_mut(self as *mut $name<F> as *mut F, count!($($field),+))
                }
            }
        }
    }
}

macro_rules! bez_composite {
    ($name:ident<$poly:ident> {
        $($field:ident: $($n_field:ident),+;)+
    } -> <$point:ident; $vector:ident>;
        $($dim:ident = $($dfield:ident),+;)+) =>
    {
        #[derive(Debug, Clone, Copy)]
        pub struct $name<F: ::num::Float + ::num::FromPrimitive> {
            $(pub $field: $point<F>),+
        }

        impl<F: ::num::Float + ::num::FromPrimitive> $name<F> {
            pub fn new($($($n_field: F),+),+) -> $name<F> {
                $name {
                    $($field: $point::new($($n_field),+)),+
                }
            }

            pub fn interp(&self, t: F) -> $point<F> {
                $crate::check_t_bounds(t);
                self.interp_unbounded(t)
            }

            pub fn interp_unbounded(&self, t: F) -> $point<F> {
                $(let $dim = $poly::new($(self.$dfield.$dim),+);)+
                $point::new($($dim.interp_unbounded(t)),+)
            }

            pub fn slope(&self, t: F) -> $vector<F> {
                $crate::check_t_bounds(t);
                self.slope_unbounded(t)
            }

            pub fn slope_unbounded(&self, t: F) -> $vector<F> {
                $(let $dim = $poly::new($(self.$dfield.$dim),+);)+
                $vector::new($($dim.slope_unbounded(t)),+)
            }
        }
    };
}<|endoftext|>


<commit_before>
use pair::Pair;
use error::NcclError;
use token::{Token, TokenKind};

#[derive(Debug)]
pub struct Parser {
    current: usize,
    path: Vec<String>,
    indent: usize,
    tokens: Vec<Token>,
    pair: Pair,
    line: u64,
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Self {
        Parser {
            current: 0,
            path: vec![],
            indent: 0,
            tokens: tokens,
            pair: Pair::new("__top_level__"),
            line: 1,
        }
    }

    pub fn new_with(tokens: Vec<Token>, pair: Pair) -> Self {
        let mut r = Parser {
            current: 0,
            path: vec![],
            indent: 0,
            tokens: tokens,
            pair: Pair::new("__top_level__"),
            line: 1
        };
        r.pair.add_pair(pair);
        r
    }

    // faked you out with that Scanner, didn't I?
    // you thought this was going to be recursive descent. YOU WERE WRONG!
    pub fn parse(mut self) -> Result<Pair, Vec<NcclError>> {
        let mut i = 0;

        while i < self.tokens.len() {
            match self.tokens[i].kind {
                TokenKind::Value => { // add to path respective of self.index
                    if self.indent <= self.path.len() {
                        let mut new = self.path[0..self.indent].to_owned();
                        new.push(self.tokens[i].lexeme.clone());
                        self.path = new;
                    } else {
                        self.path.push(self.tokens[i].lexeme.clone());
                    }

                    self.pair.add_slice(&self.path);

                    if i + 2 <= self.tokens.len() && self.tokens[i + 2].kind == TokenKind::Value {
                        self.path.clear();
                        self.indent = 0;
                    }
                },

                TokenKind::Indent => { // set new self.index
                    let mut indent = 0;

                    while self.tokens[i].kind == TokenKind::Indent {
                        indent += 1;
                        i += 1;
                    }

                    i -= 1;

                    self.indent = indent;
                },

                TokenKind::Newline => { // reset self.index
                    self.indent = 0;
                    self.line += 1;
                },

                TokenKind::EOF => break,
            }
            i += 1;
        }

        Ok(self.pair)
    }
}

<commit_msg>make parse_file_with work<commit_after>
use pair::Pair;
use error::NcclError;
use token::{Token, TokenKind};

#[derive(Debug)]
pub struct Parser {
    current: usize,
    path: Vec<String>,
    indent: usize,
    tokens: Vec<Token>,
    pair: Pair,
    line: u64,
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Self {
        Parser {
            current: 0,
            path: vec![],
            indent: 0,
            tokens: tokens,
            pair: Pair::new("__top_level__"),
            line: 1,
        }
    }

    pub fn new_with(tokens: Vec<Token>, pair: Pair) -> Self {
        Parser {
            current: 0,
            path: vec![],
            indent: 0,
            tokens: tokens,
            pair: pair,
            line: 1
        }
    }

    // faked you out with that Scanner, didn't I?
    // you thought this was going to be recursive descent. YOU WERE WRONG!
    pub fn parse(mut self) -> Result<Pair, Vec<NcclError>> {
        let mut i = 0;

        while i < self.tokens.len() {
            match self.tokens[i].kind {
                TokenKind::Value => { // add to path respective of self.index
                    if self.indent <= self.path.len() {
                        let mut new = self.path[0..self.indent].to_owned();
                        new.push(self.tokens[i].lexeme.clone());
                        self.path = new;
                    } else {
                        self.path.push(self.tokens[i].lexeme.clone());
                    }

                    self.pair.add_slice(&self.path);

                    if i + 2 <= self.tokens.len() && self.tokens[i + 2].kind == TokenKind::Value {
                        self.path.clear();
                        self.indent = 0;
                    }
                },

                TokenKind::Indent => { // set new self.index
                    let mut indent = 0;

                    while self.tokens[i].kind == TokenKind::Indent {
                        indent += 1;
                        i += 1;
                    }

                    i -= 1;

                    self.indent = indent;
                },

                TokenKind::Newline => { // reset self.index
                    self.indent = 0;
                    self.line += 1;
                },

                TokenKind::EOF => break,
            }
            i += 1;
        }

        Ok(self.pair)
    }
}

<|endoftext|>


<commit_before>use std::str::from_utf8;
use std::result::Result;
use nom::{IResult,eof};

/*
 * Core structs
 */

#[derive(Debug,PartialEq,Eq)]
pub struct TarEntry<'a> {
    pub header:   PosixHeader<'a>,
    pub contents: &'a str
}

#[derive(Debug,PartialEq,Eq)]
pub struct PosixHeader<'a> {
    pub name:     &'a str,
    pub mode:     &'a str,
    pub uid:      u64,
    pub gid:      u64,
    pub size:     u64,
    pub mtime:    u64,
    pub chksum:   &'a str,
    pub typeflag: TypeFlag,
    pub linkname: &'a str,
    pub ustar:    ExtraHeader<'a>
}

/* TODO: support vendor specific + sparse */
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum TypeFlag {
    NormalFile,
    HardLink,
    SymbolicLink,
    CharacterSpecial,
    BlockSpecial,
    Directory,
    FIFO,
    ContiguousFile,
    PaxInterexchangeFormat,
    PaxExtendedAttributes,
    VendorSpecific
}

#[derive(Debug,PartialEq,Eq)]
pub enum ExtraHeader<'a> {
    UStar(UStarHeader<'a>),
    Padding
}

#[derive(Debug,PartialEq,Eq)]
pub struct UStarHeader<'a> {
    pub magic:    &'a str,
    pub version:  &'a str,
    pub uname:    &'a str,
    pub gname:    &'a str,
    pub devmajor: u64,
    pub devminor: u64,
    pub extra:    UStarExtraHeader<'a>
}

#[derive(Debug,PartialEq,Eq)]
pub enum UStarExtraHeader<'a> {
    PosixUStar(PosixUStarHeader<'a>),
    Pax(PaxHeader<'a>)
}

#[derive(Debug,PartialEq,Eq)]
pub struct PosixUStarHeader<'a> {
    pub prefix: &'a str
}

#[derive(Debug,PartialEq,Eq)]
pub struct PaxHeader<'a> {
    pub atime:      u64,
    pub ctime:      u64,
    pub offset:     u64,
    pub longnames:  &'a str,
    pub sparse:     [Sparse; 4],
    pub isextended: bool,
    pub realsize:   u64
}

#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub struct Sparse {
    pub offset:   u64,
    pub numbytes: u64
}

#[derive(Debug,PartialEq,Eq)]
pub struct Padding;

/*
 * Useful macros
 */

macro_rules! take_str_eat_garbage (
    ( $i:expr, $size:expr ) => (
        chain!($i,
            s: map_res!(take_until!("\0"), from_utf8) ~
            take!($size - s.len()),
            ||{
                s
            }
        )
    );
);

named!(parse_str4<&[u8], &str>, take_str_eat_garbage!(4));
named!(parse_str8<&[u8], &str>, take_str_eat_garbage!(8));
named!(parse_str32<&[u8], &str>, take_str_eat_garbage!(32));
named!(parse_str100<&[u8], &str>, take_str_eat_garbage!(100));
named!(parse_str155<&[u8], &str>, take_str_eat_garbage!(155));

/*
 * Octal string parsing
 */

pub fn octal_to_u64(s: &str) -> Result<u64, &'static str> {
    let mut u = 0;

    for c in s.chars() {
        if c < '0' || c > '7' {
            return Err("invalid octal string received");
        }
        u *= 8;
        u += (c as u64) - ('0' as u64);
    }

    Ok(u)
}

fn parse_octal(i: &[u8], n: usize) -> IResult<&[u8], u64> {
    map_res!(i, take_str_eat_garbage!(n), octal_to_u64)
}

named!(parse_octal8<&[u8], u64>, apply!(parse_octal, 8));
named!(parse_octal12<&[u8], u64>, apply!(parse_octal, 12));

/*
 * TypeFlag parsing
 */

fn char_to_type_flag(c: char) -> TypeFlag {
    match c {
        '0' | '\0' => TypeFlag::NormalFile,
        '1' => TypeFlag::HardLink,
        '2' => TypeFlag::SymbolicLink,
        '3' => TypeFlag::CharacterSpecial,
        '4' => TypeFlag::BlockSpecial,
        '5' => TypeFlag::Directory,
        '6' => TypeFlag::FIFO,
        '7' => TypeFlag::ContiguousFile,
        'g' => TypeFlag::PaxInterexchangeFormat,
        'x' => TypeFlag::PaxExtendedAttributes,
        'A' ... 'Z' => TypeFlag::VendorSpecific,
        _ => TypeFlag::NormalFile
    }
}

fn bytes_to_type_flag(i: &[u8]) -> Result<TypeFlag, &'static str> {
    Ok(char_to_type_flag(i[0] as char))
}

named!(parse_type_flag<&[u8], TypeFlag>, map_res!(take!(1), bytes_to_type_flag));

/*
 * Sparse parsing
 */

fn parse_one_sparse(i: &[u8]) -> IResult<&[u8], Sparse> {
    chain!(i,
        offset:   parse_octal12 ~
        numbytes: parse_octal12,
        ||{
            Sparse {
                offset:   offset,
                numbytes: numbytes
            }
        }
    )
}

fn parse_sparse(i: &[u8]) -> IResult<&[u8], [Sparse; 4]> {
    count!(i, parse_one_sparse, Sparse, 4)
}

/*
 * Boolean parsing
 */

fn to_bool(i: &[u8]) -> Result<bool, &'static str> {
    Ok(i[0] != 0)
}

named!(parse_bool<&[u8], bool>, map_res!(take!(1), to_bool));

/*
 * UStar PAX extended parsing
 */

fn parse_ustar00_extra_pax(i: &[u8]) -> IResult<&[u8], UStarExtraHeader> {
    chain!(i,
        atime:      parse_octal12 ~
        ctime:      parse_octal12 ~
        offset:     parse_octal12 ~
        longnames:  parse_str4    ~
        take!(1)                  ~
        sparse:     parse_sparse  ~
        isextended: parse_bool    ~
        realsize:   parse_octal12 ~
        take!(17), /* padding to 512 */
        ||{
            UStarExtraHeader::Pax(PaxHeader {
                atime:      atime,
                ctime:      ctime,
                offset:     offset,
                longnames:  longnames,
                sparse:     sparse,
                isextended: isextended,
                realsize:   realsize
            })
        }
    )
}

/*
 * UStar Posix parsing
 */

fn parse_ustar00_extra_posix(i: &[u8]) -> IResult<&[u8], UStarExtraHeader> {
    chain!(i,
        prefix: parse_str155 ~
        take!(12),
        ||{
            UStarExtraHeader::PosixUStar(PosixUStarHeader {
                prefix: prefix
            })
        }
    )
}

fn parse_ustar00_extra(i: &[u8], flag: TypeFlag) -> IResult<&[u8], UStarExtraHeader> {
    match flag {
        TypeFlag::PaxInterexchangeFormat => parse_ustar00_extra_pax(i),
        _ => parse_ustar00_extra_posix(i)
    }
}

fn parse_ustar00(i: &[u8], flag: TypeFlag) -> IResult<&[u8], ExtraHeader> {
    chain!(i,
        tag!("00")             ~
        uname:    parse_str32  ~
        gname:    parse_str32  ~
        devmajor: parse_octal8 ~
        devminor: parse_octal8 ~
        extra:    apply!(parse_ustar00_extra, flag),
        ||{
            ExtraHeader::UStar(UStarHeader {
                magic:    "ustar\0",
                version:  "00",
                uname:    uname,
                gname:    gname,
                devmajor: devmajor,
                devminor: devminor,
                extra:    extra
            })
        }
    )
}

fn parse_ustar(i: &[u8], flag: TypeFlag) -> IResult<&[u8], ExtraHeader> {
    chain!(i,
        tag!("ustar\0") ~
        ustar: apply!(parse_ustar00, flag),
        ||{
            ustar
        }
    )
}

/*
 * Posix tar archive header parsing
 */

fn parse_posix(i: &[u8]) -> IResult<&[u8], ExtraHeader> {
    chain!(i,
        take!(255), /* padding to 512 */
        ||{
            ExtraHeader::Padding
        }
    )
}

fn parse_header(i: &[u8]) -> IResult<&[u8], PosixHeader> {
    chain!(i,
        name:     parse_str100    ~
        mode:     parse_str8      ~
        uid:      parse_octal8    ~
        gid:      parse_octal8    ~
        size:     parse_octal12   ~
        mtime:    parse_octal12   ~
        chksum:   parse_str8      ~
        typeflag: parse_type_flag ~
        linkname: parse_str100    ~
        ustar:    alt!(apply!(parse_ustar, typeflag) | parse_posix),
        ||{
            PosixHeader {
                name:     name,
                mode:     mode,
                uid:      uid,
                gid:      gid,
                size:     size,
                mtime:    mtime,
                chksum:   chksum,
                typeflag: typeflag,
                linkname: linkname,
                ustar:    ustar
            }
        }
    )
}

/*
 * Contents parsing
 */

fn parse_contents(i: &[u8], size: u64) -> IResult<&[u8], &str> {
    let trailing = size % 512;
    let padding = match trailing {
        0 => 0,
        t => 512 - t
    };
    chain!(i,
        contents: take_str!(size as usize) ~
        take!(padding as usize),
        ||{
            contents
        }
    )
}

/*
 * Tar entry header + contents parsing
 */

fn parse_entry(i: &[u8]) -> IResult<&[u8], TarEntry> {
    chain!(i,
        header:   parse_header ~
        contents: apply!(parse_contents, header.size),
        ||{
            TarEntry {
                header: header,
                contents: contents
            }
        }
    )
}

/*
 * Tar archive parsing
 */

fn filter_entries(entries: Vec<TarEntry>) -> Result<Vec<TarEntry>, &'static str> {
    /* Filter out empty entries */
    Ok(entries.into_iter().filter(|e| e.header.name != "").collect::<Vec<TarEntry>>())
}

pub fn parse_tar(i: &[u8]) -> IResult<&[u8], Vec<TarEntry>> {
    chain!(i,
        entries: map_res!(many0!(parse_entry), filter_entries) ~
        eof,
        ||{
            entries
        }
    )
}

/*
 * Tests
 */

#[cfg(test)]
mod tests {
    use super::*;
    use std::str::from_utf8;
    use nom::IResult;

    #[test]
    fn octal_to_u64_ok_test() {
        assert_eq!(octal_to_u64("756"), Ok(494));
        assert_eq!(octal_to_u64(""), Ok(0));
    }

    #[test]
    fn octal_to_u64_error_test() {
        assert_eq!(octal_to_u64("1238"), Err("invalid octal string received"));
        assert_eq!(octal_to_u64("a"), Err("invalid octal string received"));
        assert_eq!(octal_to_u64("A"), Err("invalid octal string received"));
    }

    #[test]
    fn take_str_eat_garbage_test() {
        let s = b"foobar\0\0\0\0baz";
        let baz = b"baz";
        assert_eq!(take_str_eat_garbage!(&s[..], 10), IResult::Done(&baz[..], "foobar"));
    }
}
<commit_msg>work on extra sparse<commit_after>use std::str::from_utf8;
use std::result::Result;
use nom::{IResult,eof};

/*
 * Core structs
 */

#[derive(Debug,PartialEq,Eq)]
pub struct TarEntry<'a> {
    pub header:   PosixHeader<'a>,
    pub contents: &'a str
}

#[derive(Debug,PartialEq,Eq)]
pub struct PosixHeader<'a> {
    pub name:     &'a str,
    pub mode:     &'a str,
    pub uid:      u64,
    pub gid:      u64,
    pub size:     u64,
    pub mtime:    u64,
    pub chksum:   &'a str,
    pub typeflag: TypeFlag,
    pub linkname: &'a str,
    pub ustar:    ExtraHeader<'a>
}

/* TODO: support vendor specific + sparse */
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum TypeFlag {
    NormalFile,
    HardLink,
    SymbolicLink,
    CharacterSpecial,
    BlockSpecial,
    Directory,
    FIFO,
    ContiguousFile,
    PaxInterexchangeFormat,
    PaxExtendedAttributes,
    VendorSpecific
}

#[derive(Debug,PartialEq,Eq)]
pub enum ExtraHeader<'a> {
    UStar(UStarHeader<'a>),
    Padding
}

#[derive(Debug,PartialEq,Eq)]
pub struct UStarHeader<'a> {
    pub magic:    &'a str,
    pub version:  &'a str,
    pub uname:    &'a str,
    pub gname:    &'a str,
    pub devmajor: u64,
    pub devminor: u64,
    pub extra:    UStarExtraHeader<'a>
}

#[derive(Debug,PartialEq,Eq)]
pub enum UStarExtraHeader<'a> {
    PosixUStar(PosixUStarHeader<'a>),
    Pax(PaxHeader<'a>)
}

#[derive(Debug,PartialEq,Eq)]
pub struct PosixUStarHeader<'a> {
    pub prefix: &'a str
}

#[derive(Debug,PartialEq,Eq)]
pub struct PaxHeader<'a> {
    pub atime:         u64,
    pub ctime:         u64,
    pub offset:        u64,
    pub longnames:     &'a str,
    pub sparse:        [Sparse; 4],
    pub isextended:    bool,
    pub realsize:      u64,
    pub extra_sparses: Vec<Sparse>
}

#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub struct Sparse {
    pub offset:   u64,
    pub numbytes: u64
}

#[derive(Debug,PartialEq,Eq)]
pub struct Padding;

/*
 * Useful macros
 */

macro_rules! take_str_eat_garbage (
    ( $i:expr, $size:expr ) => (
        chain!($i,
            s: map_res!(take_until!("\0"), from_utf8) ~
            take!($size - s.len()),
            ||{
                s
            }
        )
    );
);

named!(parse_str4<&[u8], &str>, take_str_eat_garbage!(4));
named!(parse_str8<&[u8], &str>, take_str_eat_garbage!(8));
named!(parse_str32<&[u8], &str>, take_str_eat_garbage!(32));
named!(parse_str100<&[u8], &str>, take_str_eat_garbage!(100));
named!(parse_str155<&[u8], &str>, take_str_eat_garbage!(155));

/*
 * Octal string parsing
 */

pub fn octal_to_u64(s: &str) -> Result<u64, &'static str> {
    let mut u = 0;

    for c in s.chars() {
        if c < '0' || c > '7' {
            return Err("invalid octal string received");
        }
        u *= 8;
        u += (c as u64) - ('0' as u64);
    }

    Ok(u)
}

fn parse_octal(i: &[u8], n: usize) -> IResult<&[u8], u64> {
    map_res!(i, take_str_eat_garbage!(n), octal_to_u64)
}

named!(parse_octal8<&[u8], u64>, apply!(parse_octal, 8));
named!(parse_octal12<&[u8], u64>, apply!(parse_octal, 12));

/*
 * TypeFlag parsing
 */

fn char_to_type_flag(c: char) -> TypeFlag {
    match c {
        '0' | '\0' => TypeFlag::NormalFile,
        '1' => TypeFlag::HardLink,
        '2' => TypeFlag::SymbolicLink,
        '3' => TypeFlag::CharacterSpecial,
        '4' => TypeFlag::BlockSpecial,
        '5' => TypeFlag::Directory,
        '6' => TypeFlag::FIFO,
        '7' => TypeFlag::ContiguousFile,
        'g' => TypeFlag::PaxInterexchangeFormat,
        'x' => TypeFlag::PaxExtendedAttributes,
        'A' ... 'Z' => TypeFlag::VendorSpecific,
        _ => TypeFlag::NormalFile
    }
}

fn bytes_to_type_flag(i: &[u8]) -> Result<TypeFlag, &'static str> {
    Ok(char_to_type_flag(i[0] as char))
}

named!(parse_type_flag<&[u8], TypeFlag>, map_res!(take!(1), bytes_to_type_flag));

/*
 * Sparse parsing
 */

fn parse_one_sparse(i: &[u8]) -> IResult<&[u8], Sparse> {
    chain!(i,
        offset:   parse_octal12 ~
        numbytes: parse_octal12,
        ||{
            Sparse {
                offset:   offset,
                numbytes: numbytes
            }
        }
    )
}

fn parse_sparse(i: &[u8]) -> IResult<&[u8], [Sparse; 4]> {
    count!(i, parse_one_sparse, Sparse, 4)
}

fn add_to_vec(extra: [Sparse; 21], sparses: &mut Vec<Sparse>) -> Result<&'static str, &'static str> {
    for sparse in &extra[..] {
        if sparse.offset == 0 {
            break;
        } else {
            sparses.push(*sparse);
        }
    }
    Ok("")
}

fn parse_extra_sparses<'a>(i: &'a [u8], isextended: bool, sparses: &'a mut Vec<Sparse>) -> IResult<'a, &'a [u8], &'a mut Vec<Sparse>> {
    if isextended {
        chain!(i,
            map_res!(count!(parse_one_sparse, Sparse, 21), apply!(add_to_vec, sparses)) ~
            extended:      parse_bool                                                   ~
            take!(7) /* padding to 512 */                                               ~
            extra_sparses: apply!(parse_extra_sparses, extended, sparses),
            ||{
                extra_sparses
            }
        )
    } else {
        IResult::Done(i, sparses)
    }
}

/*
 * Boolean parsing
 */

fn to_bool(i: &[u8]) -> Result<bool, &'static str> {
    Ok(i[0] != 0)
}

named!(parse_bool<&[u8], bool>, map_res!(take!(1), to_bool));

/*
 * UStar PAX extended parsing
 */

fn parse_ustar00_extra_pax(i: &[u8]) -> IResult<&[u8], UStarExtraHeader> {
    let sparses : Vec<Sparse> = Vec::new();
    chain!(i,
        atime:         parse_octal12 ~
        ctime:         parse_octal12 ~
        offset:        parse_octal12 ~
        longnames:     parse_str4    ~
        take!(1)                     ~
        sparse:        parse_sparse  ~
        isextended:    parse_bool    ~
        realsize:      parse_octal12 ~
        take!(17)                    ~ /* padding to 512 */
        apply!(parse_extra_sparses, isextended, &mut sparses),
        ||{
            UStarExtraHeader::Pax(PaxHeader {
                atime:         atime,
                ctime:         ctime,
                offset:        offset,
                longnames:     longnames,
                sparse:        sparse,
                isextended:    isextended,
                realsize:      realsize,
                extra_sparses: sparses
            })
        }
    )
}

/*
 * UStar Posix parsing
 */

fn parse_ustar00_extra_posix(i: &[u8]) -> IResult<&[u8], UStarExtraHeader> {
    chain!(i,
        prefix: parse_str155 ~
        take!(12),
        ||{
            UStarExtraHeader::PosixUStar(PosixUStarHeader {
                prefix: prefix
            })
        }
    )
}

fn parse_ustar00_extra(i: &[u8], flag: TypeFlag) -> IResult<&[u8], UStarExtraHeader> {
    match flag {
        TypeFlag::PaxInterexchangeFormat => parse_ustar00_extra_pax(i),
        _ => parse_ustar00_extra_posix(i)
    }
}

fn parse_ustar00(i: &[u8], flag: TypeFlag) -> IResult<&[u8], ExtraHeader> {
    chain!(i,
        tag!("00")             ~
        uname:    parse_str32  ~
        gname:    parse_str32  ~
        devmajor: parse_octal8 ~
        devminor: parse_octal8 ~
        extra:    apply!(parse_ustar00_extra, flag),
        ||{
            ExtraHeader::UStar(UStarHeader {
                magic:    "ustar\0",
                version:  "00",
                uname:    uname,
                gname:    gname,
                devmajor: devmajor,
                devminor: devminor,
                extra:    extra
            })
        }
    )
}

fn parse_ustar(i: &[u8], flag: TypeFlag) -> IResult<&[u8], ExtraHeader> {
    chain!(i,
        tag!("ustar\0") ~
        ustar: apply!(parse_ustar00, flag),
        ||{
            ustar
        }
    )
}

/*
 * Posix tar archive header parsing
 */

fn parse_posix(i: &[u8]) -> IResult<&[u8], ExtraHeader> {
    chain!(i,
        take!(255), /* padding to 512 */
        ||{
            ExtraHeader::Padding
        }
    )
}

fn parse_header(i: &[u8]) -> IResult<&[u8], PosixHeader> {
    chain!(i,
        name:     parse_str100    ~
        mode:     parse_str8      ~
        uid:      parse_octal8    ~
        gid:      parse_octal8    ~
        size:     parse_octal12   ~
        mtime:    parse_octal12   ~
        chksum:   parse_str8      ~
        typeflag: parse_type_flag ~
        linkname: parse_str100    ~
        ustar:    alt!(apply!(parse_ustar, typeflag) | parse_posix),
        ||{
            PosixHeader {
                name:     name,
                mode:     mode,
                uid:      uid,
                gid:      gid,
                size:     size,
                mtime:    mtime,
                chksum:   chksum,
                typeflag: typeflag,
                linkname: linkname,
                ustar:    ustar
            }
        }
    )
}

/*
 * Contents parsing
 */

fn parse_contents(i: &[u8], size: u64) -> IResult<&[u8], &str> {
    let trailing = size % 512;
    let padding = match trailing {
        0 => 0,
        t => 512 - t
    };
    chain!(i,
        contents: take_str!(size as usize) ~
        take!(padding as usize),
        ||{
            contents
        }
    )
}

/*
 * Tar entry header + contents parsing
 */

fn parse_entry(i: &[u8]) -> IResult<&[u8], TarEntry> {
    chain!(i,
        header:   parse_header ~
        contents: apply!(parse_contents, header.size),
        ||{
            TarEntry {
                header: header,
                contents: contents
            }
        }
    )
}

/*
 * Tar archive parsing
 */

fn filter_entries(entries: Vec<TarEntry>) -> Result<Vec<TarEntry>, &'static str> {
    /* Filter out empty entries */
    Ok(entries.into_iter().filter(|e| e.header.name != "").collect::<Vec<TarEntry>>())
}

pub fn parse_tar(i: &[u8]) -> IResult<&[u8], Vec<TarEntry>> {
    chain!(i,
        entries: map_res!(many0!(parse_entry), filter_entries) ~
        eof,
        ||{
            entries
        }
    )
}

/*
 * Tests
 */

#[cfg(test)]
mod tests {
    use super::*;
    use std::str::from_utf8;
    use nom::IResult;

    #[test]
    fn octal_to_u64_ok_test() {
        assert_eq!(octal_to_u64("756"), Ok(494));
        assert_eq!(octal_to_u64(""), Ok(0));
    }

    #[test]
    fn octal_to_u64_error_test() {
        assert_eq!(octal_to_u64("1238"), Err("invalid octal string received"));
        assert_eq!(octal_to_u64("a"), Err("invalid octal string received"));
        assert_eq!(octal_to_u64("A"), Err("invalid octal string received"));
    }

    #[test]
    fn take_str_eat_garbage_test() {
        let s = b"foobar\0\0\0\0baz";
        let baz = b"baz";
        assert_eq!(take_str_eat_garbage!(&s[..], 10), IResult::Done(&baz[..], "foobar"));
    }
}
<|endoftext|>


<commit_before>use std::error::Error;

use {Ident, Value};

#[deriving(PartialEq, Show)]
/// Possible errors encountered when parsing EDN.
pub enum ParserError {
    /// The parser reached the end of the input unexpectedly.
    Eof,
    /// The parser found a token invalid for this position.
    InvalidToken(char)
}

impl Error for ParserError {
    fn description(&self) -> &str { "EDN parser error" }
}

pub type ParserResult = Result<Value, ParserError>;

pub struct Parser<T: Iterator<char>> {
    inp: T,
    ch: Option<char>
}

impl<T: Iterator<char>> Parser<T> {
    pub fn new(mut inp: T) -> Parser<T> {
        let ch = inp.next();
        Parser {
            inp: inp,
            ch: ch
        }
    }

    fn is_eof(&self) -> bool {
        self.ch.is_none()
    }

    fn bump(&mut self) {
        self.ch = self.inp.next()
    }

    fn consume_ws(&mut self) {
        loop {
            if self.is_eof() { break }
            let ch = self.ch.unwrap();
            // The EDN "spec" is very vague about what constitutes whitespace, but
            // tools.reader.edn uses Java's Character.isWhitespace method which has
            // identical semantics to Rust's char::is_whitespace method (*cough*
            // hopefully).
            // FIXME: verify that ^^^
            if ch.is_whitespace() || ch == ',' {
                self.bump();
            } else {
                break
            }
        }
    }

    fn at_symbol(&self) -> bool {
        if let Some(ch) = self.ch {
            is_ident_start_ch(ch)
        } else {
            false
        }
    }

    fn at_keyword(&self) -> bool {
        if let Some(':') = self.ch { true } else { false }
    }

    fn parse_ident(&mut self) -> Result<Ident, ParserError> {
        if self.is_eof() { return Err(ParserError::Eof) }

        let mut ident = String::with_capacity(16);
        let mut prefix = None;
        let ch = self.ch.unwrap();
        // It's important that parse_symbol respects the symbol starting character
        // restrictions itself, because parse_ident is also needed for parsing
        // keywords (which don't have those restrictions).
        if !is_ident_ch(ch) { return Err(ParserError::InvalidToken(ch)) }

        loop {
            if self.is_eof() { break; }
            let ch = self.ch.unwrap();
            if ch == '/' {
                prefix = Some(ident);
                ident = String::with_capacity(16);
                self.bump();
                continue;
            }
            if !is_ident_ch(ch) { break; }
            ident.push(self.ch.unwrap());
            self.bump();
        }
        if ident.len() == 0 { return Err(ParserError::InvalidToken('/')) }
        Ok(Ident {
            name: ident,
            prefix: prefix
        })
    }

    fn parse_symbol(&mut self) -> ParserResult {
        let ident = try!(self.parse_ident());
        if ident.prefix.is_none() {
            Ok(match &*ident.name {
                "nil" => Value::Nil,
                "true" => Value::Bool(true),
                "false" => Value::Bool(false),
                _ => Value::Symbol(ident)
            })
        } else {
            Ok(Value::Symbol(ident))
        }
    }

    fn parse_keyword(&mut self) -> ParserResult {
        self.bump();
        Ok(Value::Keyword(try!(self.parse_ident())))
    }

    pub fn parse_value(&mut self) -> ParserResult {
        self.consume_ws();

        if self.is_eof() { return Err(ParserError::Eof) }
        if self.at_symbol() { return self.parse_symbol() }
        if self.at_keyword() { return self.parse_keyword() }

        unimplemented!()
    }
}

fn is_ident_start_ch(ch: char) -> bool {
    match ch {
        'a'...'z' | 'A'...'Z' => true,
        '*' | '!' | '_' | '?' | '$' | '%' | '&' | '=' | '<' | '>' => true,
        '-' | '+' | '.' => true, // can also start a number literal, watch out!
        _ => false
    }
}

fn is_ident_ch(ch: char) -> bool {
    is_ident_start_ch(ch) || ch == ':' || ch == '#' || (ch >= '0' && ch <= '9')
}

#[cfg(test)]
mod test {
    use {Ident, Value};
    use super::*;

    macro_rules! assert_val {
        ($str:expr, $val:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert_eq!(parser.parse_value(), Ok($val))
        })
    }

    macro_rules! assert_err {
        ($str:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert!(parser.parse_value().is_err())
        });
        ($str:expr, $val:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert_eq!(parser.parse_value(), Err($val))
        })
    }

    #[test]
    fn test_parse_eof() {
        assert_err!("", ParserError::Eof);
        assert_err!("    ", ParserError::Eof);
        assert_err!(",", ParserError::Eof);
    }

    #[test]
    fn test_parse_nil() {
        assert_val!("nil", Value::Nil);
        assert_val!("nil ", Value::Nil);
    }

    #[test]
    fn test_parse_bool() {
        assert_val!("true", Value::Bool(true));
        assert_val!("false", Value::Bool(false));
        assert_val!("false,", Value::Bool(false));
    }

    #[test]
    fn test_parse_symbol() {
        assert_val!("foo", Value::Symbol(Ident::simple("foo")));
        assert_val!("foo#", Value::Symbol(Ident::simple("foo#")));
        assert_val!("foo9", Value::Symbol(Ident::simple("foo9")));
        assert_val!("-foo", Value::Symbol(Ident::simple("-foo")));
        assert_val!("foo/bar", Value::Symbol(Ident::prefixed("bar", "foo")));
        assert_err!("foo/", ParserError::InvalidToken('/'));
        // FIXME: the parser doesn't handle this correctly right now
        // assert_err!("/bar", ParserError::InvalidToken('/'));

        // tools.reader.edn parses this as a symbol
        // assert_val!("ᛰ", Value::Symbol(Ident::simple("ᛰ")));
    }

    #[test]
    fn test_parse_keyword() {
        assert_err!(":", ParserError::Eof);
        assert_err!(": foo", ParserError::InvalidToken(' '));
        assert_val!(":foo", Value::Keyword(Ident::simple("foo")));
        assert_val!(":-foo", Value::Keyword(Ident::simple("-foo")));
        assert_val!(":1234", Value::Keyword(Ident::simple("1234")));
        assert_val!(":12aaa", Value::Keyword(Ident::simple("12aaa")));
    }
}
<commit_msg>Parse string literals<commit_after>use std::error::Error;

use {Ident, Value};

#[deriving(PartialEq, Show)]
/// Possible errors encountered when parsing EDN.
pub enum ParserError {
    /// The parser reached the end of the input unexpectedly.
    Eof,
    /// The parser read an unknown string escape
    InvalidEscape,
    /// The parser found a token invalid for this position.
    InvalidToken(char)
}

impl Error for ParserError {
    fn description(&self) -> &str { "EDN parser error" }
}

pub type ParserResult = Result<Value, ParserError>;

pub struct Parser<T: Iterator<char>> {
    inp: T,
    ch: Option<char>
}

impl<T: Iterator<char>> Parser<T> {
    pub fn new(mut inp: T) -> Parser<T> {
        let ch = inp.next();
        Parser {
            inp: inp,
            ch: ch
        }
    }

    fn is_eof(&self) -> bool {
        self.ch.is_none()
    }

    fn bump(&mut self) {
        self.ch = self.inp.next()
    }

    fn consume_ws(&mut self) {
        loop {
            if self.is_eof() { break }
            let ch = self.ch.unwrap();
            // The EDN "spec" is very vague about what constitutes whitespace, but
            // tools.reader.edn uses Java's Character.isWhitespace method which has
            // identical semantics to Rust's char::is_whitespace method (*cough*
            // hopefully).
            // FIXME: verify that ^^^
            if ch.is_whitespace() || ch == ',' {
                self.bump();
            } else {
                break
            }
        }
    }

    fn at_symbol(&self) -> bool {
        if let Some(ch) = self.ch {
            is_ident_start_ch(ch)
        } else {
            false
        }
    }

    fn at_keyword(&self) -> bool {
        if let Some(':') = self.ch { true } else { false }
    }

    fn parse_ident(&mut self) -> Result<Ident, ParserError> {
        if self.is_eof() { return Err(ParserError::Eof) }

        let mut ident = String::with_capacity(16);
        let mut prefix = None;
        let ch = self.ch.unwrap();
        // It's important that parse_symbol respects the symbol starting character
        // restrictions itself, because parse_ident is also needed for parsing
        // keywords (which don't have those restrictions).
        if !is_ident_ch(ch) { return Err(ParserError::InvalidToken(ch)) }

        loop {
            if self.is_eof() { break; }
            let ch = self.ch.unwrap();
            if ch == '/' {
                prefix = Some(ident);
                ident = String::with_capacity(16);
                self.bump();
                continue;
            }
            if !is_ident_ch(ch) { break; }
            ident.push(self.ch.unwrap());
            self.bump();
        }
        if ident.len() == 0 { return Err(ParserError::InvalidToken('/')) }
        Ok(Ident {
            name: ident,
            prefix: prefix
        })
    }

    fn parse_string_escape(&mut self) -> Result<char, ParserError> {
        self.bump();
        if self.is_eof() { return Err(ParserError::Eof) }
        let ch = self.ch.unwrap();
        match ch {
            't' => Ok('\t'),
            'r' => Ok('\r'),
            'n' => Ok('\n'),
            '\\' => Ok('\\'),
            '"' => Ok('"'),
            _ => Err(ParserError::InvalidEscape)
        }
    }

    fn parse_string(&mut self) -> ParserResult {
        let mut out = String::with_capacity(32);
        loop {
            self.bump();
            if self.is_eof() { return Err(ParserError::Eof) }
            let ch = self.ch.unwrap();
            if ch == '"' { break }
            if ch == '\\' {
                out.push(try!(self.parse_string_escape()));
                continue;
            }
            out.push(self.ch.unwrap())
        }
        Ok(Value::String(out))
    }

    fn parse_symbol(&mut self) -> ParserResult {
        let ident = try!(self.parse_ident());
        if ident.prefix.is_none() {
            Ok(match &*ident.name {
                "nil" => Value::Nil,
                "true" => Value::Bool(true),
                "false" => Value::Bool(false),
                _ => Value::Symbol(ident)
            })
        } else {
            Ok(Value::Symbol(ident))
        }
    }

    fn parse_keyword(&mut self) -> ParserResult {
        self.bump();
        Ok(Value::Keyword(try!(self.parse_ident())))
    }

    pub fn parse_value(&mut self) -> ParserResult {
        self.consume_ws();

        if self.is_eof() { return Err(ParserError::Eof) }
        let ch = self.ch.unwrap();
        if ch == '"' { return self.parse_string() }
        if self.at_symbol() { return self.parse_symbol() }
        if self.at_keyword() { return self.parse_keyword() }

        unimplemented!()
    }
}

fn is_ident_start_ch(ch: char) -> bool {
    match ch {
        'a'...'z' | 'A'...'Z' => true,
        '*' | '!' | '_' | '?' | '$' | '%' | '&' | '=' | '<' | '>' => true,
        '-' | '+' | '.' => true, // can also start a number literal, watch out!
        _ => false
    }
}

fn is_ident_ch(ch: char) -> bool {
    is_ident_start_ch(ch) || ch == ':' || ch == '#' || (ch >= '0' && ch <= '9')
}

#[cfg(test)]
mod test {
    use {Ident, Value};
    use super::*;

    macro_rules! assert_val {
        ($str:expr, $val:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert_eq!(parser.parse_value(), Ok($val))
        })
    }

    macro_rules! assert_err {
        ($str:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert!(parser.parse_value().is_err())
        });
        ($str:expr, $val:expr) => ({
            let inp = $str.into_string();
            let mut parser = Parser::new(inp.chars());
            assert_eq!(parser.parse_value(), Err($val))
        })
    }

    #[test]
    fn test_parse_eof() {
        assert_err!("", ParserError::Eof);
        assert_err!("    ", ParserError::Eof);
        assert_err!(",", ParserError::Eof);
    }

    #[test]
    fn test_parse_nil() {
        assert_val!("nil", Value::Nil);
        assert_val!("nil ", Value::Nil);
    }

    #[test]
    fn test_parse_bool() {
        assert_val!("true", Value::Bool(true));
        assert_val!("false", Value::Bool(false));
        assert_val!("false,", Value::Bool(false));
    }

    #[test]
    fn test_parse_str() {
        assert_err!(r#" "foo "#, ParserError::Eof);
        assert_val!(r#" "" "#, Value::String("".into_string()));
        assert_val!(r#" "foo" "#, Value::String("foo".into_string()));
        assert_val!(r#" "\n" "#, Value::String("\n".into_string()));
        assert_val!(r#" "\"" "#, Value::String("\"".into_string()));
        // multi-line
        assert_val!(" \"foo\nbar\" ", Value::String("foo\nbar".into_string()));
    }

    #[test]
    fn test_parse_symbol() {
        assert_val!("foo", Value::Symbol(Ident::simple("foo")));
        assert_val!("foo#", Value::Symbol(Ident::simple("foo#")));
        assert_val!("foo9", Value::Symbol(Ident::simple("foo9")));
        assert_val!("-foo", Value::Symbol(Ident::simple("-foo")));
        assert_val!("foo/bar", Value::Symbol(Ident::prefixed("bar", "foo")));
        assert_err!("foo/", ParserError::InvalidToken('/'));
        // FIXME: the parser doesn't handle this correctly right now
        // assert_err!("/bar", ParserError::InvalidToken('/'));

        // tools.reader.edn parses this as a symbol
        // assert_val!("ᛰ", Value::Symbol(Ident::simple("ᛰ")));
    }

    #[test]
    fn test_parse_keyword() {
        assert_err!(":", ParserError::Eof);
        assert_err!(": foo", ParserError::InvalidToken(' '));
        assert_val!(":foo", Value::Keyword(Ident::simple("foo")));
        assert_val!(":-foo", Value::Keyword(Ident::simple("-foo")));
        assert_val!(":1234", Value::Keyword(Ident::simple("1234")));
        assert_val!(":12aaa", Value::Keyword(Ident::simple("12aaa")));
    }
}
<|endoftext|>


<commit_before>use notify::op;
use std::path::{Path, PathBuf};
use std::time::{SystemTime};

/// Info about a path and its corresponding `notify` event
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct PathOp {
    pub path: PathBuf,
    pub op: Option<op::Op>,
    pub cookie: Option<u32>,
    pub time: SystemTime,
}

impl PathOp {
    pub fn new(path: &Path, op: Option<op::Op>, cookie: Option<u32>) -> PathOp {
        PathOp {
            path: path.to_path_buf(),
            op: op,
            cookie: cookie,
            time: SystemTime::now(),
        }
    }

    pub fn is_create(op_: op::Op) -> bool {
        op_.contains(op::CREATE)
    }

    pub fn is_remove(op_: op::Op) -> bool {
        op_.contains(op::REMOVE)
    }

    pub fn is_rename(op_: op::Op) -> bool {
        op_.contains(op::RENAME)
    }

    pub fn is_write(op_: op::Op) -> bool {
        let mut write_or_close_write = op::WRITE;
        write_or_close_write.toggle(op::CLOSE_WRITE);
        op_.intersects(write_or_close_write)
    }

    pub fn is_meta(op_: op::Op) -> bool {
        op_.contains(op::CHMOD)
    }
}
<commit_msg>[pathop] Revert changes adding a time field<commit_after>use notify::op;
use std::path::{Path, PathBuf};

/// Info about a path and its corresponding `notify` event
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
pub struct PathOp {
    pub path: PathBuf,
    pub op: Option<op::Op>,
    pub cookie: Option<u32>,
}

impl PathOp {
    pub fn new(path: &Path, op: Option<op::Op>, cookie: Option<u32>) -> PathOp {
        PathOp {
            path: path.to_path_buf(),
            op: op,
            cookie: cookie,
        }
    }

    pub fn is_create(op_: op::Op) -> bool {
        op_.contains(op::CREATE)
    }

    pub fn is_remove(op_: op::Op) -> bool {
        op_.contains(op::REMOVE)
    }

    pub fn is_rename(op_: op::Op) -> bool {
        op_.contains(op::RENAME)
    }

    pub fn is_write(op_: op::Op) -> bool {
        let mut write_or_close_write = op::WRITE;
        write_or_close_write.toggle(op::CLOSE_WRITE);
        op_.intersects(write_or_close_write)
    }

    pub fn is_meta(op_: op::Op) -> bool {
        op_.contains(op::CHMOD)
    }
}
<|endoftext|>