<commit_before>use super::{Buf, MutBuf};
use std::{cmp, fmt, mem, ptr, slice};
use std::rt::heap;

/// Buf backed by a continous chunk of memory. Maintains a read cursor and a
/// write cursor. When reads and writes reach the end of the allocated buffer,
/// wraps around to the start.
pub struct RingBuf {
    ptr: *mut u8,  // Pointer to the memory
    cap: usize,     // Capacity of the buffer
    pos: usize,     // Offset of read cursor
    len: usize      // Number of bytes to read
}

// TODO: There are most likely many optimizations that can be made
impl RingBuf {
    pub fn new(mut capacity: usize) -> RingBuf {
        // Handle the 0 length buffer case
        if capacity == 0 {
            return RingBuf {
                ptr: ptr::null_mut(),
                cap: 0,
                pos: 0,
                len: 0
            }
        }

        // Round to the next power of 2 for better alignment
        capacity = capacity.next_power_of_two();

        // Allocate the memory
        let ptr = unsafe { heap::allocate(capacity, mem::min_align_of::<u8>()) };

        RingBuf {
            ptr: ptr as *mut u8,
            cap: capacity,
            pos: 0,
            len: 0
        }
    }

    pub fn is_full(&self) -> bool {
        self.cap == self.len
    }

    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    pub fn capacity(&self) -> usize {
        self.cap
    }

    fn read_remaining(&self) -> usize {
        self.len
    }

    fn write_remaining(&self) -> usize {
        self.cap - self.len
    }

    fn advance_reader(&mut self, mut cnt: usize) {
        if self.cap == 0 {
            return;
        }
        cnt = cmp::min(cnt, self.read_remaining());

        self.pos += cnt;
        self.pos %= self.cap;
        self.len -= cnt;
    }

    fn advance_writer(&mut self, mut cnt: usize) {
        cnt = cmp::min(cnt, self.write_remaining());
        self.len += cnt;
    }

    fn as_slice(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(self.ptr as *const u8, self.cap)
        }
    }

    fn as_mut_slice(&mut self) -> &mut [u8] {
        unsafe {
            slice::from_raw_parts_mut(self.ptr, self.cap)
        }
    }
}

impl Clone for RingBuf {
    fn clone(&self) -> RingBuf {
        use std::cmp;

        let mut ret = RingBuf::new(self.cap);

        ret.pos = self.pos;
        ret.len = self.len;

        unsafe {
            let to = self.pos + self.len;

            if to > self.cap {
                ptr::copy(ret.ptr, self.ptr as *const u8, to % self.cap);
            }

            ptr::copy(
                ret.ptr.offset(self.pos as isize),
                self.ptr.offset(self.pos as isize) as *const u8,
                cmp::min(self.len, self.cap - self.pos));
        }

        ret
    }

    // TODO: an improved version of clone_from is possible that potentially
    // re-uses the buffer
}

impl fmt::Debug for RingBuf {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "RingBuf[.. {}]", self.len)
    }
}

impl Drop for RingBuf {
    fn drop(&mut self) {
        if self.cap > 0 {
            unsafe {
                heap::deallocate(self.ptr, self.cap, mem::min_align_of::<u8>())
            }
        }
    }
}

impl Buf for RingBuf {

    fn remaining(&self) -> usize {
        self.read_remaining()
    }

    fn bytes(&self) -> &[u8] {
        let mut to = self.pos + self.len;

        if to > self.cap {
            to = self.cap
        }

        &self.as_slice()[self.pos .. to]
    }

    fn advance(&mut self, cnt: usize) {
        self.advance_reader(cnt)
    }
}

impl MutBuf for RingBuf {

    fn remaining(&self) -> usize {
        self.write_remaining()
    }

    fn advance(&mut self, cnt: usize) {
        self.advance_writer(cnt)
    }

    fn mut_bytes(&mut self) -> &mut [u8] {
        if self.cap == 0 {
            return self.as_mut_slice();
        }
        let mut from;
        let mut to;

        from = self.pos + self.len;
        from %= self.cap;

        to = from + <Self as MutBuf>::remaining(&self);

        if to >= self.cap {
            to = self.cap;
        }

        &mut self.as_mut_slice()[from..to]
    }
}

unsafe impl Send for RingBuf { }
<commit_msg>Add Read and Write to RingBuf<commit_after>use super::{Buf, MutBuf};
use std::{cmp, fmt, mem, ptr, slice};
use std::rt::heap;
use std::io;

/// Buf backed by a continous chunk of memory. Maintains a read cursor and a
/// write cursor. When reads and writes reach the end of the allocated buffer,
/// wraps around to the start.
pub struct RingBuf {
    ptr: *mut u8,  // Pointer to the memory
    cap: usize,     // Capacity of the buffer
    pos: usize,     // Offset of read cursor
    len: usize      // Number of bytes to read
}

// TODO: There are most likely many optimizations that can be made
impl RingBuf {
    pub fn new(mut capacity: usize) -> RingBuf {
        // Handle the 0 length buffer case
        if capacity == 0 {
            return RingBuf {
                ptr: ptr::null_mut(),
                cap: 0,
                pos: 0,
                len: 0
            }
        }

        // Round to the next power of 2 for better alignment
        capacity = capacity.next_power_of_two();

        // Allocate the memory
        let ptr = unsafe { heap::allocate(capacity, mem::min_align_of::<u8>()) };

        RingBuf {
            ptr: ptr as *mut u8,
            cap: capacity,
            pos: 0,
            len: 0
        }
    }

    pub fn is_full(&self) -> bool {
        self.cap == self.len
    }

    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    pub fn capacity(&self) -> usize {
        self.cap
    }

    fn read_remaining(&self) -> usize {
        self.len
    }

    fn write_remaining(&self) -> usize {
        self.cap - self.len
    }

    fn advance_reader(&mut self, mut cnt: usize) {
        if self.cap == 0 {
            return;
        }
        cnt = cmp::min(cnt, self.read_remaining());

        self.pos += cnt;
        self.pos %= self.cap;
        self.len -= cnt;
    }

    fn advance_writer(&mut self, mut cnt: usize) {
        cnt = cmp::min(cnt, self.write_remaining());
        self.len += cnt;
    }

    fn as_slice(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(self.ptr as *const u8, self.cap)
        }
    }

    fn as_mut_slice(&mut self) -> &mut [u8] {
        unsafe {
            slice::from_raw_parts_mut(self.ptr, self.cap)
        }
    }
}

impl Clone for RingBuf {
    fn clone(&self) -> RingBuf {
        use std::cmp;

        let mut ret = RingBuf::new(self.cap);

        ret.pos = self.pos;
        ret.len = self.len;

        unsafe {
            let to = self.pos + self.len;

            if to > self.cap {
                ptr::copy(ret.ptr, self.ptr as *const u8, to % self.cap);
            }

            ptr::copy(
                ret.ptr.offset(self.pos as isize),
                self.ptr.offset(self.pos as isize) as *const u8,
                cmp::min(self.len, self.cap - self.pos));
        }

        ret
    }

    // TODO: an improved version of clone_from is possible that potentially
    // re-uses the buffer
}

impl fmt::Debug for RingBuf {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "RingBuf[.. {}]", self.len)
    }
}

impl Drop for RingBuf {
    fn drop(&mut self) {
        if self.cap > 0 {
            unsafe {
                heap::deallocate(self.ptr, self.cap, mem::min_align_of::<u8>())
            }
        }
    }
}

impl Buf for RingBuf {

    fn remaining(&self) -> usize {
        self.read_remaining()
    }

    fn bytes(&self) -> &[u8] {
        let mut to = self.pos + self.len;

        if to > self.cap {
            to = self.cap
        }

        &self.as_slice()[self.pos .. to]
    }

    fn advance(&mut self, cnt: usize) {
        self.advance_reader(cnt)
    }
}

impl MutBuf for RingBuf {

    fn remaining(&self) -> usize {
        self.write_remaining()
    }

    fn advance(&mut self, cnt: usize) {
        self.advance_writer(cnt)
    }

    fn mut_bytes(&mut self) -> &mut [u8] {
        if self.cap == 0 {
            return self.as_mut_slice();
        }
        let mut from;
        let mut to;

        from = self.pos + self.len;
        from %= self.cap;

        to = from + <Self as MutBuf>::remaining(&self);

        if to >= self.cap {
            to = self.cap;
        }

        &mut self.as_mut_slice()[from..to]
    }
}

impl io::Read for RingBuf {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        if !MutBuf::has_remaining(self) {
            return Ok(0);
        }

        Ok(self.read_slice(buf))
    }
}

impl io::Write for RingBuf {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        if !Buf::has_remaining(self) {
            return Ok(0);
        }

        Ok(self.write_slice(buf))
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

unsafe impl Send for RingBuf { }
<|endoftext|>


<commit_before>// (c) 2016-2017 Productize SPRL <joost@productize.be>

use std::fmt;
use std::result;
use std::str::FromStr;
use std::mem;

use Result;

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

impl Into<Sexp> for Vec<Sexp> {
    fn into(self:Vec<Sexp>) -> Sexp {
        Sexp::List(self)
    }
}

impl Into<Sexp> for String {
    fn into(self:String) -> Sexp {
        Sexp::String(self)
    }
}

impl<'a> From<&'a str> for Sexp {
    fn from(t:&str) -> Sexp {
        Sexp::String(t.into())
    }
}

impl Into<Sexp> for i64 {
    fn into(self:i64) -> Sexp {
        Sexp::String(format!("{}", self))
    }
}

impl Into<Sexp> for f64 {
    fn into(self:f64) -> Sexp {
        Sexp::String(format!("{}", self))
    }
}

/*
impl<'a> From<(&'a str, &'a String)> for Sexp {
    fn from(kv:(&str, &String)) -> Sexp {
        let (name,value) = kv;
        let mut v = vec![];
        v.push(name.into());
        v.push(value.as_str().into());
        v.into()
    }
}

impl<'a> From<(&'a str, &'a f64)> for Sexp {
    fn from(kv:(&str, &f64)) -> Sexp {
        let (name,value) = kv;
        let mut v = vec![];
        v.push(name.into());
        v.push(format!("{}", value).into());
        v.into()
    }
}*/

impl<'a, T:fmt::Display> From<(&'a str, &'a T)> for Sexp {
    fn from(kv:(&str, &T)) -> Sexp {
        let (name,value) = kv;
        let mut v = vec![];
        v.push(name.into());
        v.push(format!("{}", value).into());
        v.into()
    }
}

/// a symbolic-expression
/// Can be a string or a list or nothing
#[derive(Debug, Clone, PartialEq)]
pub enum Sexp {
    /// plain String symbolic-expression
    String(String),
    /// list symbolic-expression
    List(Vec<Sexp>),
    /// empty, trivial symbolic-expression
    Empty,
}

// Following the KiCad file formats specification chapter 4.4 - Identifiers and Strings:
// A string may not contain an actual newline or carriage return,
// but it may use an escape sequence to encode a // newline, such as \n.
// If a string has any of the following conditions, then it must be quoted
// with a leading and trailing double quote
// character, otherwise it is acceptable to not quote the string:
// 1. has one or more of the following 4 separator bytes: ASCII space,
// tab, '(', or ')'.
// 2. has one or more of the following bytes: '%', '{', or '}'.
// 3. has a length of zero bytes, and you need a place holder for the field,
//  then use "".
// 4. includes a byte of '-', and this byte is not in the first position of
// the string.
//

// Joost remark: kicad no longer seems to follow Rule 4.
// so we don't either

/// encode a string according to the guidelines given by Kicad
pub fn encode_string(s: &str) -> String {
    // fn rule_4(s:&str) -> bool {
    // s.contains('-') && s.len() > 1 && s.as_bytes()[0] != 45
    // }
    if s.contains('(') || s.contains(' ') || s.contains(')') || s.contains('\t') ||
       s.contains('{') || s.contains('}') || s.contains('}') || s.contains('%') ||
       s.is_empty()
    // || rule_4(s)
    {
        format!("\"{}\"", s)
    } else {
        String::from(s)
    }
}

impl Sexp {
    /// create an empty symbolic-expression
    #[deprecated(since="4.0.0", note="please use `Sexp::default()` instead")]
    pub fn new_empty() -> Sexp {
        Sexp::Empty
    }

    /// create a String type symbolic-expression
    #[deprecated(since="4.0.3", note="please use `.into()` instead")]
    pub fn new_string<T>(s: T) -> Sexp
        where T: fmt::Display
    {
        format!("{}", s).into()
    }

    /// create a list type symbolic-expression
    #[deprecated(since="4.0.3", note="please use `.into()` instead")]
    pub fn new_list(v: Vec<Sexp>) -> Sexp {
        Sexp::List(v)
    }

    /// create a list type symbolic-expression where
    /// the first element of the list is a string that indicates
    /// the name, the remainder is filled in via the provided
    /// fill function
    pub fn new_named_list<F>(name: &str, fill: F) -> Sexp
        where F: Fn(&mut Vec<Sexp>)
    {
        let mut v = vec![];
        v.push(name.into());
        fill(&mut v);
        Sexp::List(v)
    }

    /// create a list type symbolic-expression where
    /// the first element of the list is a string that indicates
    /// the name
    #[deprecated(since="4.0.3", note="please use `.into()` instead")]
    pub fn new_named<T>(name: &str, value: T) -> Sexp
        where T: fmt::Display
    {
        let mut v = vec![];
        v.push(format!("{}", name).into());
        v.push(format!("{}", value).into());
        v.into()
    }

    /// create a list type symbolic-expression where
    /// the first element of the list is a string that indicates
    /// the name, and the second is another symbolic-expression
    /// created via the IntoSexp trait
    pub fn new_named_sexp<T>(name: &str, value: &T) -> Sexp
        where T: IntoSexp
    {
        let mut v = vec![];
        v.push(name.into());
        v.push(value.into_sexp());
        Sexp::List(v)
    }

    /// if the expression is a list, take out the list and swap it with Empty
    pub fn take_list(&mut self) -> Result<Vec<Sexp>> {
        let mut e = Sexp::Empty;
        mem::swap(&mut e, self);
        match e {
            Sexp::List(v) => Ok(v),
            _ => Err(format!("Not a list: {}", e).into()),
        }
    }

    /// if the expression is a string, take it out and swap it with Empty
    pub fn take_string(&mut self) -> Result<String> {
        let mut e = Sexp::Empty;
        mem::swap(&mut e, self);
        match e {
            Sexp::String(s) => Ok(s),
            _ => Err(format!("Not a string: {}", e).into()),
        }
    }

    /// create a symbolic-expression via the IntoSexp trait
    pub fn from<T: IntoSexp>(t: &T) -> Sexp {
        t.into_sexp()
    }

    /// access the symbolic-expression as if it is a List
    pub fn list(&self) -> Result<&Vec<Sexp>> {
        match *self {
            Sexp::List(ref v) => Ok(v),
            _ => Err(format!("not a list: {}", self).into()),
        }
    }

    /// access the symbolic-expression as if it is a String
    pub fn string(&self) -> Result<&String> {
        match *self {
            Sexp::String(ref s) => Ok(s),
            _ => Err(format!("not a string: {}", self).into()),
        }
    }

    /// is this expression a string
    pub fn is_string(&self) -> bool {
        match *self {
            Sexp::String(_) => true,
            _ => false,
        }
    }

    /// is this expression a list
    pub fn is_list(&self) -> bool {
        match *self {
            Sexp::List(_) => true,
            _ => false,
        }
    }

    /// access the symbolic-expression as if it is a String
    /// that is a f64
    pub fn f(&self) -> Result<f64> {
        let s = self.string()?;
        let f = f64::from_str(s)?;
        Ok(f)
    }

    /// access the symbolic-expression as if it is a String
    /// that is an i64
    pub fn i(&self) -> Result<i64> {
        let s = self.string()?;
        let i = i64::from_str(s)?;
        Ok(i)
    }

    /// access the symbolic-expression as if it is a List
    /// assuming the first element is a String and return that
    pub fn list_name(&self) -> Result<&String> {
        let l = self.list()?;
        let l = &l[..];
        let a = l[0].string()?;
        Ok(a)
    }

    /// access the symbolic-expression as if it is a named List
    /// where the name is provided and returns the remaining elements
    /// after the name as a slice
    pub fn slice_atom(&self, s: &str) -> Result<&[Sexp]> {
        let v = self.list()?;
        let v2 = &v[..];
        let st = v2[0].string()?;
        if st != s {
            return Err(format!("list {} doesn't start with {}, but with {}", self, s, st).into());
        };
        Ok(&v[1..])
    }

    /// access the symbolic-expression as if it is a named List
    /// with two elements where the name is provided and returns
    /// the next element in the list
    pub fn named_value(&self, s: &str) -> Result<&Sexp> {
        let v = self.list()?;
        if v.len() != 2 {
            return Err(format!("list {} is not a named_value", s).into());
        }
        let l = self.slice_atom(s)?;
        Ok(&l[0])
    }

    /// as named_value but converted to i64
    pub fn named_value_i(&self, s: &str) -> Result<i64> {
        self.named_value(s)?.i()
    }

    /// as named_value but converted to f64
    pub fn named_value_f(&self, s: &str) -> Result<f64> {
        self.named_value(s)?.f()
    }

    /// as named_value but converted to String
    pub fn named_value_string(&self, s: &str) -> Result<&String> {
        self.named_value(s)?.string()
    }

    /// get the symbolic-expression as a list which starts
    /// with a string that indicates the name and has num more
    /// elements, returns those elements
    pub fn slice_atom_num(&self, s: &str, num: usize) -> Result<&[Sexp]> {
        let v = self.list()?;
        let v2 = &v[..];
        let st = v2[0].string()?;
        if st != s {
            return Err(format!("list doesn't start with {}, but with {}", s, st).into());
        };
        if v.len() != (num + 1) {
            return Err(format!("list ({}) doesn't have {} elements but {}",
                                     s,
                                     num,
                                     v.len() - 1).into());
        }
        Ok(&v[1..])
    }
}

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

impl Default for Sexp {
    fn default() -> Sexp {
        Sexp::Empty
    }
}
<commit_msg>more clever list code<commit_after>// (c) 2016-2017 Productize SPRL <joost@productize.be>

use std::fmt;
use std::result;
use std::str::FromStr;
use std::mem;

use Result;

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

impl Into<Sexp> for Vec<Sexp> {
    fn into(self:Vec<Sexp>) -> Sexp {
        Sexp::List(self)
    }
}

impl Into<Sexp> for String {
    fn into(self:String) -> Sexp {
        Sexp::String(self)
    }
}

impl<'a> From<&'a str> for Sexp {
    fn from(t:&str) -> Sexp {
        Sexp::String(t.into())
    }
}

impl Into<Sexp> for i64 {
    fn into(self:i64) -> Sexp {
        Sexp::String(format!("{}", self))
    }
}

impl Into<Sexp> for f64 {
    fn into(self:f64) -> Sexp {
        Sexp::String(format!("{}", self))
    }
}

impl<'a, T:fmt::Display> From<(&'a str, &'a T)> for Sexp {
    fn from(kv:(&str, &T)) -> Sexp {
        let (name,value) = kv;
        let mut v = vec![];
        v.push(name.into());
        v.push(format!("{}", value).into());
        v.into()
    }
}

/// a symbolic-expression
/// Can be a string or a list or nothing
#[derive(Debug, Clone, PartialEq)]
pub enum Sexp {
    /// plain String symbolic-expression
    String(String),
    /// list symbolic-expression
    List(Vec<Sexp>),
    /// empty, trivial symbolic-expression
    Empty,
}

// Following the KiCad file formats specification chapter 4.4 - Identifiers and Strings:
// A string may not contain an actual newline or carriage return,
// but it may use an escape sequence to encode a // newline, such as \n.
// If a string has any of the following conditions, then it must be quoted
// with a leading and trailing double quote
// character, otherwise it is acceptable to not quote the string:
// 1. has one or more of the following 4 separator bytes: ASCII space,
// tab, '(', or ')'.
// 2. has one or more of the following bytes: '%', '{', or '}'.
// 3. has a length of zero bytes, and you need a place holder for the field,
//  then use "".
// 4. includes a byte of '-', and this byte is not in the first position of
// the string.
//

// Joost remark: kicad no longer seems to follow Rule 4.
// so we don't either

/// encode a string according to the guidelines given by Kicad
pub fn encode_string(s: &str) -> String {
    // fn rule_4(s:&str) -> bool {
    // s.contains('-') && s.len() > 1 && s.as_bytes()[0] != 45
    // }
    if s.contains('(') || s.contains(' ') || s.contains(')') || s.contains('\t') ||
       s.contains('{') || s.contains('}') || s.contains('}') || s.contains('%') ||
       s.is_empty()
    // || rule_4(s)
    {
        format!("\"{}\"", s)
    } else {
        String::from(s)
    }
}

impl Sexp {
    /// create an empty symbolic-expression
    #[deprecated(since="4.0.0", note="please use `Sexp::default()` instead")]
    pub fn new_empty() -> Sexp {
        Sexp::Empty
    }

    /// create a String type symbolic-expression
    #[deprecated(since="4.0.3", note="please use `.into()` instead")]
    pub fn new_string<T>(s: T) -> Sexp
        where T: fmt::Display
    {
        format!("{}", s).into()
    }

    /// create a list type symbolic-expression
    #[deprecated(since="4.0.3", note="please use `.into()` instead")]
    pub fn new_list(v: Vec<Sexp>) -> Sexp {
        Sexp::List(v)
    }

    /// create an empty list type symbolic-expression
    pub fn start(name:&str) -> Sexp {
        let mut v = vec![];
        v.push(Sexp::String(name.into()));
        Sexp::List(v)
    }

    /// push an element in a list
    pub fn push<T:Into<Sexp>>(&mut self, element:T) {
        match *self {
            Sexp::List(ref mut v) => {
                v.push(element.into())
            }
            _ => {
                panic!("Only use push on lists!")
            }
        }
    }

    /// create a list type symbolic-expression where
    /// the first element of the list is a string that indicates
    /// the name, the remainder is filled in via the provided
    /// fill function
    pub fn new_named_list<F>(name: &str, fill: F) -> Sexp
        where F: Fn(&mut Vec<Sexp>)
    {
        let mut v = vec![];
        v.push(name.into());
        fill(&mut v);
        Sexp::List(v)
    }

    /// create a list type symbolic-expression where
    /// the first element of the list is a string that indicates
    /// the name
    #[deprecated(since="4.0.3", note="please use `.into()` instead")]
    pub fn new_named<T>(name: &str, value: T) -> Sexp
        where T: fmt::Display
    {
        let mut v = vec![];
        v.push(format!("{}", name).into());
        v.push(format!("{}", value).into());
        v.into()
    }

    /// create a list type symbolic-expression where
    /// the first element of the list is a string that indicates
    /// the name, and the second is another symbolic-expression
    /// created via the IntoSexp trait
    pub fn new_named_sexp<T>(name: &str, value: &T) -> Sexp
        where T: IntoSexp
    {
        let mut v = vec![];
        v.push(name.into());
        v.push(value.into_sexp());
        Sexp::List(v)
    }

    /// if the expression is a list, take out the list and swap it with Empty
    pub fn take_list(&mut self) -> Result<Vec<Sexp>> {
        let mut e = Sexp::Empty;
        mem::swap(&mut e, self);
        match e {
            Sexp::List(v) => Ok(v),
            _ => Err(format!("Not a list: {}", e).into()),
        }
    }

    /// if the expression is a string, take it out and swap it with Empty
    pub fn take_string(&mut self) -> Result<String> {
        let mut e = Sexp::Empty;
        mem::swap(&mut e, self);
        match e {
            Sexp::String(s) => Ok(s),
            _ => Err(format!("Not a string: {}", e).into()),
        }
    }

    /// create a symbolic-expression via the IntoSexp trait
    pub fn from<T: IntoSexp>(t: &T) -> Sexp {
        t.into_sexp()
    }

    /// access the symbolic-expression as if it is a List
    pub fn list(&self) -> Result<&Vec<Sexp>> {
        match *self {
            Sexp::List(ref v) => Ok(v),
            _ => Err(format!("not a list: {}", self).into()),
        }
    }

    /// access the symbolic-expression as if it is a String
    pub fn string(&self) -> Result<&String> {
        match *self {
            Sexp::String(ref s) => Ok(s),
            _ => Err(format!("not a string: {}", self).into()),
        }
    }

    /// is this expression a string
    pub fn is_string(&self) -> bool {
        match *self {
            Sexp::String(_) => true,
            _ => false,
        }
    }

    /// is this expression a list
    pub fn is_list(&self) -> bool {
        match *self {
            Sexp::List(_) => true,
            _ => false,
        }
    }

    /// access the symbolic-expression as if it is a String
    /// that is a f64
    pub fn f(&self) -> Result<f64> {
        let s = self.string()?;
        let f = f64::from_str(s)?;
        Ok(f)
    }

    /// access the symbolic-expression as if it is a String
    /// that is an i64
    pub fn i(&self) -> Result<i64> {
        let s = self.string()?;
        let i = i64::from_str(s)?;
        Ok(i)
    }

    /// access the symbolic-expression as if it is a List
    /// assuming the first element is a String and return that
    pub fn list_name(&self) -> Result<&String> {
        let l = self.list()?;
        let l = &l[..];
        let a = l[0].string()?;
        Ok(a)
    }

    /// access the symbolic-expression as if it is a named List
    /// where the name is provided and returns the remaining elements
    /// after the name as a slice
    pub fn slice_atom(&self, s: &str) -> Result<&[Sexp]> {
        let v = self.list()?;
        let v2 = &v[..];
        let st = v2[0].string()?;
        if st != s {
            return Err(format!("list {} doesn't start with {}, but with {}", self, s, st).into());
        };
        Ok(&v[1..])
    }

    /// access the symbolic-expression as if it is a named List
    /// with two elements where the name is provided and returns
    /// the next element in the list
    pub fn named_value(&self, s: &str) -> Result<&Sexp> {
        let v = self.list()?;
        if v.len() != 2 {
            return Err(format!("list {} is not a named_value", s).into());
        }
        let l = self.slice_atom(s)?;
        Ok(&l[0])
    }

    /// as named_value but converted to i64
    pub fn named_value_i(&self, s: &str) -> Result<i64> {
        self.named_value(s)?.i()
    }

    /// as named_value but converted to f64
    pub fn named_value_f(&self, s: &str) -> Result<f64> {
        self.named_value(s)?.f()
    }

    /// as named_value but converted to String
    pub fn named_value_string(&self, s: &str) -> Result<&String> {
        self.named_value(s)?.string()
    }

    /// get the symbolic-expression as a list which starts
    /// with a string that indicates the name and has num more
    /// elements, returns those elements
    pub fn slice_atom_num(&self, s: &str, num: usize) -> Result<&[Sexp]> {
        let v = self.list()?;
        let v2 = &v[..];
        let st = v2[0].string()?;
        if st != s {
            return Err(format!("list doesn't start with {}, but with {}", s, st).into());
        };
        if v.len() != (num + 1) {
            return Err(format!("list ({}) doesn't have {} elements but {}",
                                     s,
                                     num,
                                     v.len() - 1).into());
        }
        Ok(&v[1..])
    }
}

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

impl Default for Sexp {
    fn default() -> Sexp {
        Sexp::Empty
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fs::{create_dir, remove_dir_all};
use std::path::Path;

use glob::glob;
use tera::{Tera, Context};

use errors::{Result, ResultExt};
use config::{Config, get_config};
use page::Page;
use utils::create_file;

#[derive(Debug)]
pub struct Site {
    config: Config,
    pages: HashMap<String, Page>,
    sections: HashMap<String, Vec<String>>,
    templates: Tera,
    live_reload: bool,
}

impl Site {
    pub fn new(livereload: bool) -> Result<Site> {
        let tera = Tera::new("templates/**/*").chain_err(|| "Error parsing templates")?;
        let mut site = Site {
            config: get_config(),
            pages: HashMap::new(),
            sections: HashMap::new(),
            templates: tera,
            live_reload: livereload,
        };
        site.parse_site()?;

        Ok(site)
    }

    /// Reads all .md files in the `content` directory and create pages
    /// out of them
    fn parse_site(&mut self) -> Result<()> {
        // First step: do all the articles and group article by sections
        // hardcoded pattern so can't error
        for entry in glob("content/**/*.md").unwrap().filter_map(|e| e.ok()) {
            let page = Page::from_file(&entry.as_path(), &self.config)?;

            for section in &page.sections {
                self.sections.entry(section.clone()).or_insert(vec![]).push(page.slug.clone());
            }

            self.pages.insert(page.slug.clone(), page);
        }

        Ok(())
    }

    // Inject live reload script tag if in live reload mode
    fn inject_livereload(&self, html: String) -> String {
        if self.live_reload {
            return html.replace(
                "",
                r#""#
            );
        }

        html
    }

    /// Re-parse and re-generate the site
    /// Very dumb for now, ideally it would only rebuild what changed
    pub fn rebuild(&mut self) -> Result<()> {
        self.parse_site()?;
        self.build()
    }

    /// Builds the site to the `public` directory after deleting it
    pub fn build(&self) -> Result<()> {
        if Path::new("public").exists() {
            // Delete current `public` directory so we can start fresh
            remove_dir_all("public").chain_err(|| "Couldn't delete `public` directory")?;
        }

        // Start from scratch
        create_dir("public")?;
        let public = Path::new("public");

        let mut pages = vec![];
        // First we render the pages themselves
        for page in self.pages.values() {
            // Copy the nesting of the content directory if we have sections for that page
            let mut current_path = public.to_path_buf();

            // This loop happens when the page doesn't have a set URL
            for section in &page.sections {
                current_path.push(section);

                if !current_path.exists() {
                    create_dir(&current_path)?;
                }
            }

            // if we have a url already set, use that as base
            if let Some(ref url) = page.meta.url {
                current_path.push(url);
            }

            // Make sure the folder exists
            create_dir(&current_path)?;
            // Finally, create a index.html file there with the page rendered

            let output = page.render_html(&self.templates, &self.config)?;
            create_file(current_path.join("index.html"), &self.inject_livereload(output))?;
            pages.push(page);
        }

        // Then the section pages
        // The folders have already been created in the page loop so no need to `create_dir` here
//        for (section, slugs) in &self.sections {
//            // TODO
//        }

        // And finally the index page
        let mut context = Context::new();
        pages.sort_by(|a, b| a.partial_cmp(b).unwrap());
        context.add("pages", &pages);
        context.add("config", &self.config);
        let index = self.templates.render("index.html", &context)?;
        create_file(public.join("index.html"), &self.inject_livereload(index))?;

        self.render_sitemap()?;

        Ok(())
    }

    pub fn render_sitemap(&self) -> Result<()> {
        let tpl = String::from_utf8(include_bytes!("templates/sitemap.xml").to_vec()).unwrap();
        let mut context = Context::new();
        context.add("pages", &self.pages.values().collect::<Vec<&Page>>());
        let sitemap = Tera::one_off(&tpl, &context, false)?;

        let public = Path::new("public");
        create_file(public.join("sitemap.xml"), &sitemap)?;

        Ok(())
    }
}
<commit_msg>Render categories and tags<commit_after>use std::collections::HashMap;
use std::iter::FromIterator;
use std::fs::{create_dir, remove_dir_all};
use std::path::Path;

use glob::glob;
use tera::{Tera, Context};
use slug::slugify;

use errors::{Result, ResultExt};
use config::{Config, get_config};
use page::Page;
use utils::create_file;

#[derive(Debug, PartialEq)]
enum RenderList {
    Tags,
    Categories,
}

/// A tag or category
#[derive(Debug, Serialize, PartialEq)]
struct ListItem {
    name: String,
    slug: String,
    count: usize,
}

impl ListItem {
    pub fn new(name: &str, count: usize) -> ListItem {
        ListItem {
            name: name.to_string(),
            slug: slugify(name),
            count: count,
        }
    }
}

#[derive(Debug)]
pub struct Site {
    config: Config,
    pages: HashMap<String, Page>,
    sections: HashMap<String, Vec<String>>,
    templates: Tera,
    live_reload: bool,
}

impl Site {
    pub fn new(livereload: bool) -> Result<Site> {
        let tera = Tera::new("templates/**/*").chain_err(|| "Error parsing templates")?;
        let mut site = Site {
            config: get_config(),
            pages: HashMap::new(),
            sections: HashMap::new(),
            templates: tera,
            live_reload: livereload,
        };
        site.parse_site()?;

        Ok(site)
    }

    /// Reads all .md files in the `content` directory and create pages
    /// out of them
    fn parse_site(&mut self) -> Result<()> {
        // First step: do all the articles and group article by sections
        // hardcoded pattern so can't error
        for entry in glob("content/**/*.md").unwrap().filter_map(|e| e.ok()) {
            let page = Page::from_file(&entry.as_path(), &self.config)?;

            for section in &page.sections {
                self.sections.entry(section.clone()).or_insert(vec![]).push(page.slug.clone());
            }

            self.pages.insert(page.slug.clone(), page);
        }

        Ok(())
    }

    // Inject live reload script tag if in live reload mode
    fn inject_livereload(&self, html: String) -> String {
        if self.live_reload {
            return html.replace(
                "",
                r#""#
            );
        }

        html
    }

    /// Re-parse and re-generate the site
    /// Very dumb for now, ideally it would only rebuild what changed
    pub fn rebuild(&mut self) -> Result<()> {
        self.parse_site()?;
        self.build()
    }

    /// Builds the site to the `public` directory after deleting it
    pub fn build(&self) -> Result<()> {
        if Path::new("public").exists() {
            // Delete current `public` directory so we can start fresh
            remove_dir_all("public").chain_err(|| "Couldn't delete `public` directory")?;
        }

        // Start from scratch
        create_dir("public")?;
        let public = Path::new("public");

        let mut pages = vec![];
        let mut category_pages: HashMap<String, Vec<&Page>> = HashMap::new();
        let mut tag_pages: HashMap<String, Vec<&Page>> = HashMap::new();
        // First we render the pages themselves
        for page in self.pages.values() {
            // Copy the nesting of the content directory if we have sections for that page
            let mut current_path = public.to_path_buf();

            // This loop happens when the page doesn't have a set URL
            for section in &page.sections {
                current_path.push(section);

                if !current_path.exists() {
                    create_dir(&current_path)?;
                }
            }

            // if we have a url already set, use that as base
            if let Some(ref url) = page.meta.url {
                current_path.push(url);
            }

            // Make sure the folder exists
            create_dir(&current_path)?;
            // Finally, create a index.html file there with the page rendered
            let output = page.render_html(&self.templates, &self.config)?;
            create_file(current_path.join("index.html"), &self.inject_livereload(output))?;
            pages.push(page);

            if let Some(ref category) = page.meta.category {
                category_pages.entry(category.to_string()).or_insert(vec![]).push(page);
            }
            if let Some(ref tags) = page.meta.tags {
                for tag in tags {
                    tag_pages.entry(tag.to_string()).or_insert(vec![]).push(page);
                }
            }
        }

        // Outputting categories and pages
        self.render_categories_and_tags(RenderList::Categories, &category_pages)?;
        self.render_categories_and_tags(RenderList::Tags, &tag_pages)?;

        // And finally the index page
        let mut context = Context::new();
        pages.sort_by(|a, b| a.partial_cmp(b).unwrap());
        context.add("pages", &pages);
        context.add("config", &self.config);
        let index = self.templates.render("index.html", &context)?;
        create_file(public.join("index.html"), &self.inject_livereload(index))?;

        self.render_sitemap()?;
        // TODO: render rss feed

        Ok(())
    }
    /// Render the /{categories, list} pages and each individual category/tag page
    fn render_categories_and_tags(&self, kind: RenderList, container: &HashMap<String, Vec<&Page>>) -> Result<()> {
        if container.is_empty() {
            return Ok(());
        }

        let (name, list_tpl_name, single_tpl_name, var_name) = if kind == RenderList::Categories {
            ("categories", "categories.html", "category.html", "category")
        } else {
            ("tags", "tags.html", "tag.html", "tag")
        };

        let public = Path::new("public");
        let mut output_path = public.to_path_buf();
        output_path.push(name);
        create_dir(&output_path)?;

        // First we render the list of categories/tags page
        let mut sorted_container = vec![];
        for (item, count) in Vec::from_iter(container).into_iter().map(|(a, b)| (a, b.len())) {
            sorted_container.push(ListItem::new(item, count));
        }
        sorted_container.sort_by(|a, b| b.count.cmp(&a.count));

        let mut context = Context::new();
        context.add(name, &sorted_container);
        context.add("config", &self.config);

        let list_output = self.templates.render(list_tpl_name, &context)?;
        create_file(output_path.join("index.html"), &self.inject_livereload(list_output))?;

        // and then each individual item
        for (item_name, mut pages) in container.clone() {
            let mut context = Context::new();
            pages.sort_by(|a, b| a.partial_cmp(b).unwrap());
            let slug = slugify(&item_name);
            context.add(var_name, &item_name);
            context.add(&format!("{}_slug", var_name), &slug);
            context.add("pages", &pages);
            context.add("config", &self.config);
            let single_output = self.templates.render(single_tpl_name, &context)?;

            create_dir(&output_path.join(&slug))?;
            create_file(
                output_path.join(&slug).join("index.html"),
                &self.inject_livereload(single_output)
            )?;
        }

        Ok(())
    }

    pub fn render_sitemap(&self) -> Result<()> {
        let tpl = String::from_utf8(include_bytes!("templates/sitemap.xml").to_vec()).unwrap();
        let mut context = Context::new();
        context.add("pages", &self.pages.values().collect::<Vec<&Page>>());
        let sitemap = Tera::one_off(&tpl, &context, false)?;

        let public = Path::new("public");
        create_file(public.join("sitemap.xml"), &sitemap)?;

        Ok(())
    }
}
<|endoftext|>


<commit_before>// mrusty. mruby bindings for Rust
// Copyright (C) 2016  Dragoș Tiselice
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use super::mruby::*;

/// A `macro` useful to run mruby specs.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate mrusty;
/// use mrusty::*;
///
/// # fn main() {
/// spec!("
///     describe Class do
///       context 'when 1' do
///         subject { 1 }
///
///         it { is_expected.to eql 1 }
///       end
///
///       context 'when 1' do
///         subject { 1 }
///         let(:one) { 1 }
///
///         it 'won\\'t' do
///           expect(1).to eql one
///         end
///       end
///     end
/// ");
/// # }
/// ```
#[macro_export]
macro_rules! spec {
    ( $script:expr ) => {
        #[test]
        fn spec() {
            let spec = Spec::new($script);

            assert!(spec.run());
        }
    }
}

pub struct Spec<'a> {
    script: &'a str,
    mruby: MRubyType
}

impl<'a> Spec<'a> {
    pub fn new(script: &str) -> Spec {
        let mruby = MRuby::new();

        mruby.filename("spec");

        mruby.run(include_str!("spec/matchers/eq.rb")).unwrap();
        mruby.run(include_str!("spec/context.rb")).unwrap();
        mruby.run(include_str!("spec/example.rb")).unwrap();
        mruby.run(include_str!("spec/expect.rb")).unwrap();
        mruby.run(include_str!("spec/spec.rb")).unwrap();

        Spec {
            script: script,
            mruby: mruby
        }
    }

    pub fn run(&self) -> bool {
        self.mruby.run(self.script).unwrap().to_bool().unwrap()
    }
}

spec!("
    describe Class do
      context 'when 1' do
        subject { 1 }

        it { is_expected.to eql 1 }
      end

      context 'when 1' do
        subject { 1 }
        let(:one) { 1 }

        it 'won\\'t' do
          expect(1).to eql one
        end
      end
    end
");
<commit_msg>Added types to macro.<commit_after>// mrusty. mruby bindings for Rust
// Copyright (C) 2016  Dragoș Tiselice
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use super::mruby::*;

use std::any::Any;

/// A `macro` useful to run mruby specs.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate mrusty;
/// use mrusty::*;
///
/// # fn main() {
/// struct Cont;
///
/// impl MRubyFile for Cont {
///     fn require(mruby: MRubyType) {
///         mruby.def_class::<Cont>("Container");
///     }
/// }
///
/// describe!(Cont, "
///     describe Class do
///       context 'when 1' do
///         subject { 1 }
///
///         it { is_expected.to eql 1 }
///       end
///
///       context 'when 1' do
///         subject { 1 }
///         let(:one) { 1 }
///
///         it 'won\\'t' do
///           expect(1).to eql one
///         end
///       end
///     end
/// ");
/// # }
/// ```
#[macro_export]
macro_rules! describe {
    ( $t:ty, $spec:expr ) => {
        #[test]
        fn spec() {
            let spec = Spec::new::<$t>($spec);

            assert!(spec.run());
        }
    }
}

pub struct Spec {
    script: String,
    target: String,
    mruby: MRubyType
}

impl Spec {
    pub fn new<T: MRubyFile + Any>(script: &str) -> Spec {
        let mruby = MRuby::new();

        T::require(mruby.clone());

        mruby.filename("spec");

        mruby.run(include_str!("spec/matchers/eq.rb")).unwrap();
        mruby.run(include_str!("spec/context.rb")).unwrap();
        mruby.run(include_str!("spec/example.rb")).unwrap();
        mruby.run(include_str!("spec/expect.rb")).unwrap();
        mruby.run(include_str!("spec/spec.rb")).unwrap();

        let name = mruby.class_name::<T>().unwrap();

        Spec {
            script: script.to_string(),
            target: name,
            mruby: mruby
        }
    }

    pub fn run(&self) -> bool {
        let describe = format!("
            describe {} do
              {}
            end
        ", self.target, self.script);

        self.mruby.run(&describe).unwrap().to_bool().unwrap()
    }
}
<|endoftext|>


<commit_before>//! A trait for defining Rust _tasks_ to be executed in a background thread.

use std::marker::{Send, Sized};
use std::mem;
use std::os::raw::c_void;

use js::{Value, JsFunction};
use mem::Handle;
use mem::Managed;
use scope::{Scope, RootScope};
use vm::JsResult;
use vm::internal::Isolate;
use neon_runtime;
use neon_runtime::raw;

/// A Rust task that can be executed in a background thread.
pub trait Task: Send + Sized {
    /// The task's result type, which is sent back to the main thread to communicate a successful result back to JavaScript.
    type Output: Send;

    /// The task's error type, which is sent back to the main thread to communicate a task failure back to JavaScript.
    type Error: Send;

    /// The type of JavaScript value that gets produced to the asynchronous callback on the main thread after the task is completed.
    type JsEvent: Value;

    /// Perform the task, producing either a successful `Output` or an unsuccessful `Error`. This method is executed in a background thread as part of libuv's built-in thread pool.
    fn perform(&self) -> Result<Self::Output, Self::Error>;

    /// Convert the result of the task to a JavaScript value to be passed to the asynchronous callback. This method is executed on the main thread at some point after the background task is completed.
    fn complete<'a, T: Scope<'a>>(self, scope: &'a mut T, result: Result<Self::Output, Self::Error>) -> JsResult<Self::JsEvent>;

    /// Schedule a task to be executed on a background thread.
    fn schedule(self, callback: Handle<JsFunction>) {
        let boxed_self = Box::new(self);
        let self_raw = Box::into_raw(boxed_self);
        let callback_raw = callback.to_raw();
        unsafe {
            neon_runtime::task::schedule(mem::transmute(self_raw),
                                         perform_task::<Self>,
                                         complete_task::<Self>,
                                         callback_raw);
        }
    }
}

unsafe extern "C" fn perform_task<T: Task>(task: *mut c_void) -> *mut c_void {
    let task: Box<T> = Box::from_raw(mem::transmute(task));
    let result = task.perform();
    Box::into_raw(task);
    mem::transmute(Box::into_raw(Box::new(result)))
}

unsafe extern "C" fn complete_task<T: Task>(task: *mut c_void, result: *mut c_void, out: &mut raw::Local) {
    let result: Result<T::Output, T::Error> = *Box::from_raw(mem::transmute(result));
    let task: Box<T> = Box::from_raw(mem::transmute(task));

    // The neon::Task::complete() method installs an outer v8::HandleScope
    // that is responsible for managing the out pointer, so it's safe to
    // create the RootScope here without creating a local v8::HandleScope.
    let mut scope = RootScope::new(Isolate::current());
    if let Ok(result) = task.complete(&mut scope, result) {
        *out = result.to_raw();
    }
}
<commit_msg>Document callback's signature<commit_after>//! A trait for defining Rust _tasks_ to be executed in a background thread.

use std::marker::{Send, Sized};
use std::mem;
use std::os::raw::c_void;

use js::{Value, JsFunction};
use mem::Handle;
use mem::Managed;
use scope::{Scope, RootScope};
use vm::JsResult;
use vm::internal::Isolate;
use neon_runtime;
use neon_runtime::raw;

/// A Rust task that can be executed in a background thread.
pub trait Task: Send + Sized {
    /// The task's result type, which is sent back to the main thread to communicate a successful result back to JavaScript.
    type Output: Send;

    /// The task's error type, which is sent back to the main thread to communicate a task failure back to JavaScript.
    type Error: Send;

    /// The type of JavaScript value that gets produced to the asynchronous callback on the main thread after the task is completed.
    type JsEvent: Value;

    /// Perform the task, producing either a successful `Output` or an unsuccessful `Error`. This method is executed in a background thread as part of libuv's built-in thread pool.
    fn perform(&self) -> Result<Self::Output, Self::Error>;

    /// Convert the result of the task to a JavaScript value to be passed to the asynchronous callback. This method is executed on the main thread at some point after the background task is completed.
    fn complete<'a, T: Scope<'a>>(self, scope: &'a mut T, result: Result<Self::Output, Self::Error>) -> JsResult<Self::JsEvent>;

    /// Schedule a task to be executed on a background thread.
    ///
    /// `callback` should have the following signature:
    ///
    /// ```js
    /// function callback(err, value) {}
    /// ```
    fn schedule(self, callback: Handle<JsFunction>) {
        let boxed_self = Box::new(self);
        let self_raw = Box::into_raw(boxed_self);
        let callback_raw = callback.to_raw();
        unsafe {
            neon_runtime::task::schedule(mem::transmute(self_raw),
                                         perform_task::<Self>,
                                         complete_task::<Self>,
                                         callback_raw);
        }
    }
}

unsafe extern "C" fn perform_task<T: Task>(task: *mut c_void) -> *mut c_void {
    let task: Box<T> = Box::from_raw(mem::transmute(task));
    let result = task.perform();
    Box::into_raw(task);
    mem::transmute(Box::into_raw(Box::new(result)))
}

unsafe extern "C" fn complete_task<T: Task>(task: *mut c_void, result: *mut c_void, out: &mut raw::Local) {
    let result: Result<T::Output, T::Error> = *Box::from_raw(mem::transmute(result));
    let task: Box<T> = Box::from_raw(mem::transmute(task));

    // The neon::Task::complete() method installs an outer v8::HandleScope
    // that is responsible for managing the out pointer, so it's safe to
    // create the RootScope here without creating a local v8::HandleScope.
    let mut scope = RootScope::new(Isolate::current());
    if let Ok(result) = task.complete(&mut scope, result) {
        *out = result.to_raw();
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use std::time::{Instant, Duration};

/// RAII timer to measure how long phases take.
#[derive(Debug)]
pub struct Timer<'a> {
    output: bool,
    name: &'a str,
    start: Instant,
}

impl<'a> Timer<'a> {
    /// Creates a Timer with the given name, and starts it. By default,
    /// will print to stderr when it is `drop`'d
    pub fn new(name: &'a str) -> Self {
        Timer {
            output: true,
            name,
            start: Instant::now()
        }
    }

    /// Sets whether or not the Timer will print a mesage
    /// when it is dropped.
    pub fn with_output(mut self, output: bool) -> Self {
        self.output = output;
        self
    }

    /// Returns the time elapsed since the timer's creation
    pub fn elapsed(&self) -> Duration {
        Instant::now() - self.start
    }

    fn print_elapsed(&mut self) {
        if self.output {
            let elapsed = self.elapsed();
            let time = (elapsed.as_secs() as f32) * 1e3
                       + (elapsed.subsec_nanos() as f32) / 1e6;
            let stderr = io::stderr();
            // Arbitrary output format, subject to change.
            writeln!(stderr.lock(),
                     "  time: {:>9.3} ms.\t{}",
                     time, self.name)
                     .expect("timer write should not fail");
        }
    }
}

impl<'a> Drop for Timer<'a> {
    fn drop(&mut self) {
        self.print_elapsed();
    }
}
<commit_msg>We can afford the exra cycles to use double precision floats here<commit_after>use std::io::{self, Write};
use std::time::{Instant, Duration};

/// RAII timer to measure how long phases take.
#[derive(Debug)]
pub struct Timer<'a> {
    output: bool,
    name: &'a str,
    start: Instant,
}

impl<'a> Timer<'a> {
    /// Creates a Timer with the given name, and starts it. By default,
    /// will print to stderr when it is `drop`'d
    pub fn new(name: &'a str) -> Self {
        Timer {
            output: true,
            name,
            start: Instant::now()
        }
    }

    /// Sets whether or not the Timer will print a mesage
    /// when it is dropped.
    pub fn with_output(mut self, output: bool) -> Self {
        self.output = output;
        self
    }

    /// Returns the time elapsed since the timer's creation
    pub fn elapsed(&self) -> Duration {
        Instant::now() - self.start
    }

    fn print_elapsed(&mut self) {
        if self.output {
            let elapsed = self.elapsed();
            let time = (elapsed.as_secs() as f64) * 1e3
                       + (elapsed.subsec_nanos() as f64) / 1e6;
            let stderr = io::stderr();
            // Arbitrary output format, subject to change.
            writeln!(stderr.lock(),
                     "  time: {:>9.3} ms.\t{}",
                     time, self.name)
                     .expect("timer write should not fail");
        }
    }
}

impl<'a> Drop for Timer<'a> {
    fn drop(&mut self) {
        self.print_elapsed();
    }
}
<|endoftext|>


<commit_before>use std::ffi::{CString, NulError};
use std::os::raw;

#[derive(Debug)]
pub struct NullError(usize);

impl From<NulError> for NullError {
    fn from(e: NulError) -> NullError {
        NullError(e.nul_position())
    }
}

impl From<NullError> for ::std::io::Error {
    fn from(e: NullError) -> ::std::io::Error {
        ::std::io::Error::new(::std::io::ErrorKind::Other, format!("{}", e))
    }
}

impl ::std::error::Error for NullError {
    fn description(&self) -> &str { "non-final null byte found" }
}

impl ::std::fmt::Display for NullError {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "non-final null byte at {}", self.0)
    }
}

pub enum CowCString<'a> {
    Owned(CString),
    Ref(&'a raw::c_char)
}

impl<'a> CowCString<'a> {
    /// Checks for last byte and avoids alocatting if its zero.
    ///
    /// Non-last null bytes still result in an error.
    pub fn from_bytes(slice: &'a [u8]) -> Result<CowCString<'a>, NullError> {
        Ok(if slice.len() == 0 {
            static ZERO: raw::c_char = 0;
            CowCString::Ref(&ZERO)
        } else if let Some(&0) = slice.last() {
            // check for inner nulls
            for (c, i) in slice.iter().zip(0..slice.len()-2) {
                if *c == 0 {
                    return Err(NullError(i));
                }
            }
            CowCString::Ref(unsafe {::std::mem::transmute(slice.get_unchecked(0))})
        } else {
            CowCString::Owned(try!(CString::new(slice)))
        })
    }
}

pub trait CStringAsRef {
    fn cstring_ref(&self) -> &raw::c_char;
}

impl CStringAsRef for CString {
    fn cstring_ref(&self) -> &raw::c_char {
        unsafe { &*self.as_ptr() }
    }
}

impl<'a> CStringAsRef for CowCString<'a> {
    fn cstring_ref(&self) -> &raw::c_char {
        match self {
            &CowCString::Ref(r) => r,
            &CowCString::Owned(ref o) => o.cstring_ref()
        }
    }
}
<commit_msg>fixed one clippy warning<commit_after>use std::ffi::{CString, NulError};
use std::os::raw;

#[derive(Debug)]
pub struct NullError(usize);

impl From<NulError> for NullError {
    fn from(e: NulError) -> NullError {
        NullError(e.nul_position())
    }
}

impl From<NullError> for ::std::io::Error {
    fn from(e: NullError) -> ::std::io::Error {
        ::std::io::Error::new(::std::io::ErrorKind::Other, format!("{}", e))
    }
}

impl ::std::error::Error for NullError {
    fn description(&self) -> &str { "non-final null byte found" }
}

impl ::std::fmt::Display for NullError {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "non-final null byte at {}", self.0)
    }
}

pub enum CowCString<'a> {
    Owned(CString),
    Ref(&'a raw::c_char)
}

impl<'a> CowCString<'a> {
    /// Checks for last byte and avoids alocatting if its zero.
    ///
    /// Non-last null bytes still result in an error.
    pub fn from_bytes(slice: &'a [u8]) -> Result<CowCString<'a>, NullError> {
        Ok(if slice.len() == 0 {
            static ZERO: raw::c_char = 0;
            CowCString::Ref(&ZERO)
        } else if let Some(&0) = slice.last() {
            // check for inner nulls
            for (c, i) in slice.iter().zip(0..slice.len()-2) {
                if *c == 0 {
                    return Err(NullError(i));
                }
            }
            CowCString::Ref(unsafe {::std::mem::transmute(slice.get_unchecked(0))})
        } else {
            CowCString::Owned(try!(CString::new(slice)))
        })
    }
}

pub trait CStringAsRef {
    fn cstring_ref(&self) -> &raw::c_char;
}

impl CStringAsRef for CString {
    fn cstring_ref(&self) -> &raw::c_char {
        unsafe { &*self.as_ptr() }
    }
}

impl<'a> CStringAsRef for CowCString<'a> {
    fn cstring_ref(&self) -> &raw::c_char {
        match *self {
            CowCString::Ref(r) => r,
            CowCString::Owned(ref o) => o.cstring_ref()
        }
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "alloc")]
use lib::std::vec::Vec;

#[cfg(feature = "std")]
/// Helper trait to show a byte slice as a hex dump
pub trait HexDisplay {
  /// Converts the value of `self` to a hex dump, returning the owned
  /// string.
  fn to_hex(&self, chunk_size: usize) -> String;

  /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned
  /// string.
  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String;
}

#[cfg(feature = "std")]
static CHARS: &'static [u8] = b"0123456789abcdef";

#[cfg(feature = "std")]
impl HexDisplay for [u8] {
  #[allow(unused_variables)]
  fn to_hex(&self, chunk_size: usize) -> String {
    self.to_hex_from(chunk_size, 0)
  }

  #[allow(unused_variables)]
  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    let mut v = Vec::with_capacity(self.len() * 3);
    let mut i = from;
    for chunk in self.chunks(chunk_size) {
      let s = format!("{:08x}", i);
      for &ch in s.as_bytes().iter() {
        v.push(ch);
      }
      v.push(b'\t');

      i += chunk_size;

      for &byte in chunk {
        v.push(CHARS[(byte >> 4) as usize]);
        v.push(CHARS[(byte & 0xf) as usize]);
        v.push(b' ');
      }
      if chunk_size > chunk.len() {
        for j in 0..(chunk_size - chunk.len()) {
          v.push(b' ');
          v.push(b' ');
          v.push(b' ');
        }
      }
      v.push(b'\t');

      for &byte in chunk {
        if (byte >= 32 && byte <= 126) || byte >= 128 {
          v.push(byte);
        } else {
          v.push(b'.');
        }
      }
      v.push(b'\n');
    }

    String::from_utf8_lossy(&v[..]).into_owned()
  }
}

#[cfg(feature = "std")]
impl HexDisplay for str {
  #[allow(unused_variables)]
  fn to_hex(&self, chunk_size: usize) -> String {
    self.to_hex_from(chunk_size, 0)
  }

  #[allow(unused_variables)]
  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    self.as_bytes().to_hex_from(chunk_size, from)
  }
}

#[doc(hidden)]
#[macro_export]
macro_rules! nom_line (
  () => (line!());
);

#[doc(hidden)]
#[macro_export]
macro_rules! nom_println (
  ($($args:tt)*) => (println!($($args)*));
);

#[doc(hidden)]
#[macro_export]
macro_rules! nom_stringify (
  ($($args:tt)*) => (stringify!($($args)*));
);

/// Prints a message if the parser fails
///
/// The message prints the `Error` or `Incomplete`
/// and the parser's calling code
///
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///    named!(f, dbg!( tag!( "abcd" ) ) );
///
///    let a = &b"efgh"[..];
///
///    // Will print the following message:
///    // Error(Position(0, [101, 102, 103, 104])) at l.5 by ' tag ! ( "abcd" ) '
///    f(a);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! dbg (
  ($i: expr, $submac:ident!( $($args:tt)* )) => (
    {
      use $crate::lib::std::result::Result::*;
      let l = nom_line!();
      match $submac!($i, $($args)*) {
        Err(e) => {
          nom_println!("Err({:?}) at l.{} by ' {} '", e, l, nom_stringify!($submac!($($args)*)));
          Err(e)
        },
        a => a,
      }
    }
  );

  ($i:expr, $f:ident) => (
      dbg!($i, call!($f));
  );
);

/// Prints a message and the input if the parser fails
///
/// The message prints the `Error` or `Incomplete`
/// and the parser's calling code.
///
/// It also displays the input in hexdump format
///
/// ```ignore
/// # #[macro_use] extern crate nom;
/// # fn main() {
///    named!(f, dbg_dmp!( tag!( "abcd" ) ) );
///
///    let a = &b"efghijkl"[..];
///
///    // Will print the following message:
///    // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
///    // 00000000        65 66 67 68 69 6a 6b 6c         efghijkl
///    f(a);
/// # }
#[macro_export(local_inner_macros)]
#[cfg(feature = "std")]
macro_rules! dbg_dmp (
  ($i: expr, $submac:ident!( $($args:tt)* )) => (
    {
      use $crate::HexDisplay;
      let l = nom_line!();
      match $submac!($i, $($args)*) {
        Err(e) => {
          nom_println!("Error({:?}) at l.{} by ' {} '\n{}", e, l, nom_stringify!($submac!($($args)*)), $i.to_hex(8));
          Err(e)
        },
        a => a,
      }
    }
  );

  ($i:expr, $f:ident) => (
      dbg_dmp!($i, call!($f));
  );
);

<commit_msg>port dbg_dmp to functions<commit_after>#[cfg(feature = "alloc")]
use lib::std::vec::Vec;
#[cfg(feature = "std")]
use internal::IResult;
#[cfg(feature = "std")]
use std::fmt::Debug;

#[cfg(feature = "std")]
/// Helper trait to show a byte slice as a hex dump
pub trait HexDisplay {
  /// Converts the value of `self` to a hex dump, returning the owned
  /// string.
  fn to_hex(&self, chunk_size: usize) -> String;

  /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned
  /// string.
  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String;
}

#[cfg(feature = "std")]
static CHARS: &'static [u8] = b"0123456789abcdef";

#[cfg(feature = "std")]
impl HexDisplay for [u8] {
  #[allow(unused_variables)]
  fn to_hex(&self, chunk_size: usize) -> String {
    self.to_hex_from(chunk_size, 0)
  }

  #[allow(unused_variables)]
  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    let mut v = Vec::with_capacity(self.len() * 3);
    let mut i = from;
    for chunk in self.chunks(chunk_size) {
      let s = format!("{:08x}", i);
      for &ch in s.as_bytes().iter() {
        v.push(ch);
      }
      v.push(b'\t');

      i += chunk_size;

      for &byte in chunk {
        v.push(CHARS[(byte >> 4) as usize]);
        v.push(CHARS[(byte & 0xf) as usize]);
        v.push(b' ');
      }
      if chunk_size > chunk.len() {
        for j in 0..(chunk_size - chunk.len()) {
          v.push(b' ');
          v.push(b' ');
          v.push(b' ');
        }
      }
      v.push(b'\t');

      for &byte in chunk {
        if (byte >= 32 && byte <= 126) || byte >= 128 {
          v.push(byte);
        } else {
          v.push(b'.');
        }
      }
      v.push(b'\n');
    }

    String::from_utf8_lossy(&v[..]).into_owned()
  }
}

#[cfg(feature = "std")]
impl HexDisplay for str {
  #[allow(unused_variables)]
  fn to_hex(&self, chunk_size: usize) -> String {
    self.to_hex_from(chunk_size, 0)
  }

  #[allow(unused_variables)]
  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    self.as_bytes().to_hex_from(chunk_size, from)
  }
}

#[doc(hidden)]
#[macro_export]
macro_rules! nom_line (
  () => (line!());
);

#[doc(hidden)]
#[macro_export]
macro_rules! nom_println (
  ($($args:tt)*) => (println!($($args)*));
);

#[doc(hidden)]
#[macro_export]
macro_rules! nom_stringify (
  ($($args:tt)*) => (stringify!($($args)*));
);

/// Prints a message if the parser fails
///
/// The message prints the `Error` or `Incomplete`
/// and the parser's calling code
///
/// ```
/// # #[macro_use] extern crate nom;
/// # fn main() {
///    named!(f, dbg!( tag!( "abcd" ) ) );
///
///    let a = &b"efgh"[..];
///
///    // Will print the following message:
///    // Error(Position(0, [101, 102, 103, 104])) at l.5 by ' tag ! ( "abcd" ) '
///    f(a);
/// # }
/// ```
#[macro_export(local_inner_macros)]
macro_rules! dbg (
  ($i: expr, $submac:ident!( $($args:tt)* )) => (
    {
      use $crate::lib::std::result::Result::*;
      let l = nom_line!();
      match $submac!($i, $($args)*) {
        Err(e) => {
          nom_println!("Err({:?}) at l.{} by ' {} '", e, l, nom_stringify!($submac!($($args)*)));
          Err(e)
        },
        a => a,
      }
    }
  );

  ($i:expr, $f:ident) => (
      dbg!($i, call!($f));
  );
);

/// Prints a message and the input if the parser fails
///
/// The message prints the `Error` or `Incomplete`
/// and the parser's calling code.
///
/// It also displays the input in hexdump format
///
/// ```rust
/// use nom::{util::dbg_dmp, bytes::complete::tag};
///
/// fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
///   dbg_dmp(tag("abcd"))(i)
/// }
///
///   let a = &b"efghijkl"[..];
///
/// // Will print the following message:
/// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
/// // 00000000        65 66 67 68 69 6a 6b 6c         efghijkl
/// f(a);
/// ```
#[cfg(feature = "std")]
fn dbg_dmp<'a, F, O, E: Debug>(f: F, context: &'static str) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O, E>
  where F: Fn(&'a [u8]) -> IResult<&'a [u8], O, E> {
  move |i: &'a [u8]| {
      match f(i) {
        Err(e) => {
          println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8));
          Err(e)
        },
        a => a,
      }
  }
}

/// Prints a message and the input if the parser fails
///
/// The message prints the `Error` or `Incomplete`
/// and the parser's calling code.
///
/// It also displays the input in hexdump format
///
/// ```ignore
/// # #[macro_use] extern crate nom;
/// # fn main() {
///    named!(f, dbg_dmp!( tag!( "abcd" ) ) );
///
///    let a = &b"efghijkl"[..];
///
///    // Will print the following message:
///    // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
///    // 00000000        65 66 67 68 69 6a 6b 6c         efghijkl
///    f(a);
/// # }
#[macro_export(local_inner_macros)]
#[cfg(feature = "std")]
macro_rules! dbg_dmp (
  ($i: expr, $submac:ident!( $($args:tt)* )) => (
    {
      use $crate::HexDisplay;
      let l = nom_line!();
      match $submac!($i, $($args)*) {
        Err(e) => {
          nom_println!("Error({:?}) at l.{} by ' {} '\n{}", e, l, nom_stringify!($submac!($($args)*)), $i.to_hex(8));
          Err(e)
        },
        a => a,
      }
    }
  );

  ($i:expr, $f:ident) => (
      dbg_dmp!($i, call!($f));
  );
);

<|endoftext|>