<commit_before>
#[derive(Debug)]
#[cfg(feature = "std")]
/// Serialization Error
pub enum Error {
    /// `io::Error` (no available in ![no_std] mode)
    Io(std::io::Error),
    /// `fmt::Error`
    Fmt(std::fmt::Error),
    /// Other error
    Other,
}

#[derive(Debug)]
#[cfg(not(feature = "std"))]
/// Serialization Error
pub enum Error {
    /// `fmt::Error`
    Fmt(core::fmt::Error),
    /// Other error
    Other,
}

/// Serialization `Result`
pub type Result<T=()> = result::Result<T, Error>;

#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<core::fmt::Error> for Error {
    fn from(_: core::fmt::Error) -> Error {
        Error::Other
    }
}

#[cfg(feature = "std")]
impl From<Error> for std::io::Error {
    fn from(e: Error) -> std::io::Error {
        match e {
            Error::Io(e) => e,
            Error::Fmt(_) => std::io::Error::new(std::io::ErrorKind::Other, "formatting error"),
            Error::Other => std::io::Error::new(std::io::ErrorKind::Other, "other error"),
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref e) => e.description(),
            Error::Fmt(_) => "formatting error",
            Error::Other => "serialization error",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Io(ref e) => Some(e),
            Error::Fmt(ref e) => Some(e),
            Error::Other => None,
        }
    }
}

#[cfg(feature = "std")]
impl core::fmt::Display for Error {
    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::Io(ref e) => e.fmt(fmt),
            Error::Fmt(ref e) => e.fmt(fmt),
            Error::Other => fmt.write_str("Other serialization error"),
        }
    }
}

macro_rules! impl_default_as_fmt{
    ($t:ty, $f:ident) => {
        /// Emit $t
        fn $f(&mut self, key : &str, val : $t)
            -> Result {
                self.emit_arguments(key, &format_args!("{}", val))
            }
    };
}

/// Serializer
///
/// Drains using `Format` will internally use
/// types implementing this trait.
pub trait Serializer {

    /// Emit usize
    impl_default_as_fmt!(usize, emit_usize);
    /// Emit isize
    impl_default_as_fmt!(isize, emit_isize);
    /// Emit bool
    impl_default_as_fmt!(bool, emit_bool);
    /// Emit char
    impl_default_as_fmt!(char, emit_char);
    /// Emit u8
    impl_default_as_fmt!(u8, emit_u8);
    /// Emit i8
    impl_default_as_fmt!(i8, emit_i8);
    /// Emit u16
    impl_default_as_fmt!(u16, emit_u16);
    /// Emit i16
    impl_default_as_fmt!(i16, emit_i16);
    /// Emit u32
    impl_default_as_fmt!(u32, emit_u32);
    /// Emit i32
    impl_default_as_fmt!(i32, emit_i32);
    /// Emit f32
    impl_default_as_fmt!(f32, emit_f32);
    /// Emit u64
    impl_default_as_fmt!(u64, emit_u64);
    /// Emit i64
    impl_default_as_fmt!(i64, emit_i64);
    /// Emit f64
    impl_default_as_fmt!(f64, emit_f64);
    /// Emit str
    impl_default_as_fmt!(&str, emit_str);

    /// Emit `()`
    fn emit_unit(&mut self, key: &str) -> Result {
        self.emit_arguments(key, &format_args!("()"))
    }

    /// Emit `None`
    fn emit_none(&mut self, key: &str) -> Result {
        self.emit_arguments(key, &format_args!(""))
    }

    /// Emit `fmt::Arguments`
    ///
    /// This is the only method that has to implemented, but for
    /// performance and type-retaining reason most serious `Serializer`s
    /// will want to implement all other methods as well.
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> Result;
}

/// Serializer that formats all arguments as fmt::Arguments
/// ans and passes them to a given closure.
pub struct AsFmtSerializer<F>(pub F)
    where F : for <'a, 'b> FnMut(&'b str, fmt::Arguments<'a>) -> Result;

impl<F> Serializer for AsFmtSerializer<F>
    where F : for <'a, 'b> FnMut(&'b str, fmt::Arguments<'a>) -> Result
{
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> Result {
        (self.0)(key, *val)
    }
}

/// Value that can be serialized
pub trait Value {
    /// Serialize self into `Serializer`
    ///
    /// Structs implementing this trait should generally
    /// only call respective methods of `serializer`.
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result;
}

/// Value that can be serialized
pub trait Key {
    /// To text representation
    fn as_str(&self) -> &str;
}

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

impl Key for str {
    fn as_str(&self) -> &str {
        &self
    }
}

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

macro_rules! impl_value_for{
    ($t:ty, $f:ident) => {
        impl Value for $t {
            fn serialize(&self, _record : &Record, key : &str, serializer : &mut Serializer)
                         -> Result {
                serializer.$f(key, *self)
            }
        }
    };
}

impl_value_for!(usize, emit_usize);
impl_value_for!(isize, emit_isize);
impl_value_for!(bool, emit_bool);
impl_value_for!(char, emit_char);
impl_value_for!(u8, emit_u8);
impl_value_for!(i8, emit_i8);
impl_value_for!(u16, emit_u16);
impl_value_for!(i16, emit_i16);
impl_value_for!(u32, emit_u32);
impl_value_for!(i32, emit_i32);
impl_value_for!(f32, emit_f32);
impl_value_for!(u64, emit_u64);
impl_value_for!(i64, emit_i64);
impl_value_for!(f64, emit_f64);

impl Value for () {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_unit(key)
    }
}

impl Value for str {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self)
    }
}

impl<'a> Value for &'a str {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self)
    }
}

impl<'a> Value for fmt::Arguments<'a> {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_arguments(key, self)
    }
}

impl Value for String {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self.as_str())
    }
}

impl<T: Value> Value for Option<T> {
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        match *self {
            Some(ref s) => s.serialize(record, key, serializer),
            None => serializer.emit_none(key),
        }
    }
}

impl Value for Box<Value + Send + 'static> {
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for Arc<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for Rc<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for core::num::Wrapping<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        self.0.serialize(record, key, serializer)
    }
}

impl<V: 'static + Value, F> Value for F
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (self)(record).serialize(record, key, serializer)
    }
}

/// Explicit lazy-closure `Value`
pub struct FnValue<V: 'static + Value, F>(pub F)
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V;

impl<V: 'static + Value, F> Value for FnValue<V, F>
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (self.0)(record).serialize(record, key, serializer)
    }
}

/// Handle passed to `PushFnValue` closure
///
/// It makes sure only one value is serialized, and will automatically emit
/// `()` if nothing else was serialized.
pub struct PushFnSerializer<'a> {
    record: &'a Record<'a>,
    key: &'a str,
    serializer: &'a mut Serializer,
    done: bool,
}

impl<'a> PushFnSerializer<'a> {
    /// Serialize a value
    ///
    /// This consumes `self` to prevent serializing one value multiple times
    pub fn serialize<'b, S: 'b + Value>(mut self, s: S) -> Result {
        self.done = true;
        s.serialize(self.record, self.key, self.serializer)
    }
}

impl<'a> Drop for PushFnSerializer<'a> {
    fn drop(&mut self) {
        if !self.done {
            // unfortunately this gives no change to return serialization errors
            let _ = self.serializer.emit_unit(self.key);
        }
    }
}

/// Lazy `Value` that writes to Serializer
///
/// It's more natural for closures used as lazy values to return `Serialize`
/// implementing type, but sometimes that forces an allocation (eg. Strings)
///
/// In some cases it might make sense for another closure form to be used - one
/// taking a serializer as an argument, which avoids lifetimes / allocation issues.
///
/// Generally this method should be used if it avoids a big allocation of
/// `Serialize`-implementing type in performance-critical logging statement.
///
/// ```
/// #[macro_use]
/// extern crate slog;
/// use slog::{PushFnValue, Logger, Discard};
///
/// fn main() {
///     let _root = Logger::root(Discard, o!( ));
///     info!(_root, "foo"; "writer_closure" => PushFnValue(|_ , s| {
///                    let generated_string = format!("{}", 1);
///                    s.serialize(generated_string.as_str())
///             }));
/// }
/// ```
pub struct PushFnValue<F>(pub F)
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>, PushFnSerializer<'c>) -> Result;

impl<F> Value for PushFnValue<F>
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>, PushFnSerializer<'c>) -> Result
{
    fn serialize(&self, record: &Record, key: &str, serializer: &mut Serializer)
        -> Result {
        let ser = PushFnSerializer {
            record: record,
            key: key,
            serializer: serializer,
            done: false,
        };
        (self.0)(record, ser)
    }
}

/// Key-value pair(s) that can be serialized
///
/// Zero, one or more key value pairs chained together
pub trait KV {
    /// Serialize self into `Serializer`
    ///
    /// Structs implementing this trait should generally
    /// only call respective methods of `serializer`.
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
                 -> Result;

    /// Split into tuple of `(first, rest)`
    fn split_first(&self) -> Option<(&KV, &KV)>;
}

/// Single pair `Key` and `Value`
pub struct SingleKV<K, V>(pub K, pub V)
    where K : Key, V : Value;

impl<K, V> KV for SingleKV<K, V>
    where K : Key,
          V : Value
{
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            self.1.serialize(record, self.0.as_str(), serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        Some((self, &STATIC_TERMINATOR_UNIT))
    }
}

impl KV for () {
    fn serialize(&self,
                 _record: &Record,
                 _serializer: &mut Serializer)
        -> Result {
            Ok(())
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        None
    }
}

impl<T: KV, R: KV> KV for (T, R) {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            try!(self.0.serialize(record, serializer));
            self.1.serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        Some((&self.0, &self.1))
    }
}
<commit_msg>Add `Box<KV>` and `Arc<KV>` support<commit_after>
#[derive(Debug)]
#[cfg(feature = "std")]
/// Serialization Error
pub enum Error {
    /// `io::Error` (no available in ![no_std] mode)
    Io(std::io::Error),
    /// `fmt::Error`
    Fmt(std::fmt::Error),
    /// Other error
    Other,
}

#[derive(Debug)]
#[cfg(not(feature = "std"))]
/// Serialization Error
pub enum Error {
    /// `fmt::Error`
    Fmt(core::fmt::Error),
    /// Other error
    Other,
}

/// Serialization `Result`
pub type Result<T=()> = result::Result<T, Error>;

#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
    fn from(err: std::io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<core::fmt::Error> for Error {
    fn from(_: core::fmt::Error) -> Error {
        Error::Other
    }
}

#[cfg(feature = "std")]
impl From<Error> for std::io::Error {
    fn from(e: Error) -> std::io::Error {
        match e {
            Error::Io(e) => e,
            Error::Fmt(_) => std::io::Error::new(std::io::ErrorKind::Other, "formatting error"),
            Error::Other => std::io::Error::new(std::io::ErrorKind::Other, "other error"),
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref e) => e.description(),
            Error::Fmt(_) => "formatting error",
            Error::Other => "serialization error",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match *self {
            Error::Io(ref e) => Some(e),
            Error::Fmt(ref e) => Some(e),
            Error::Other => None,
        }
    }
}

#[cfg(feature = "std")]
impl core::fmt::Display for Error {
    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::Io(ref e) => e.fmt(fmt),
            Error::Fmt(ref e) => e.fmt(fmt),
            Error::Other => fmt.write_str("Other serialization error"),
        }
    }
}

macro_rules! impl_default_as_fmt{
    ($t:ty, $f:ident) => {
        /// Emit $t
        fn $f(&mut self, key : &str, val : $t)
            -> Result {
                self.emit_arguments(key, &format_args!("{}", val))
            }
    };
}

/// Serializer
///
/// Drains using `Format` will internally use
/// types implementing this trait.
pub trait Serializer {

    /// Emit usize
    impl_default_as_fmt!(usize, emit_usize);
    /// Emit isize
    impl_default_as_fmt!(isize, emit_isize);
    /// Emit bool
    impl_default_as_fmt!(bool, emit_bool);
    /// Emit char
    impl_default_as_fmt!(char, emit_char);
    /// Emit u8
    impl_default_as_fmt!(u8, emit_u8);
    /// Emit i8
    impl_default_as_fmt!(i8, emit_i8);
    /// Emit u16
    impl_default_as_fmt!(u16, emit_u16);
    /// Emit i16
    impl_default_as_fmt!(i16, emit_i16);
    /// Emit u32
    impl_default_as_fmt!(u32, emit_u32);
    /// Emit i32
    impl_default_as_fmt!(i32, emit_i32);
    /// Emit f32
    impl_default_as_fmt!(f32, emit_f32);
    /// Emit u64
    impl_default_as_fmt!(u64, emit_u64);
    /// Emit i64
    impl_default_as_fmt!(i64, emit_i64);
    /// Emit f64
    impl_default_as_fmt!(f64, emit_f64);
    /// Emit str
    impl_default_as_fmt!(&str, emit_str);

    /// Emit `()`
    fn emit_unit(&mut self, key: &str) -> Result {
        self.emit_arguments(key, &format_args!("()"))
    }

    /// Emit `None`
    fn emit_none(&mut self, key: &str) -> Result {
        self.emit_arguments(key, &format_args!(""))
    }

    /// Emit `fmt::Arguments`
    ///
    /// This is the only method that has to implemented, but for
    /// performance and type-retaining reason most serious `Serializer`s
    /// will want to implement all other methods as well.
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> Result;
}

/// Serializer that formats all arguments as fmt::Arguments
/// ans and passes them to a given closure.
pub struct AsFmtSerializer<F>(pub F)
    where F : for <'a, 'b> FnMut(&'b str, fmt::Arguments<'a>) -> Result;

impl<F> Serializer for AsFmtSerializer<F>
    where F : for <'a, 'b> FnMut(&'b str, fmt::Arguments<'a>) -> Result
{
    fn emit_arguments(&mut self, key: &str, val: &fmt::Arguments) -> Result {
        (self.0)(key, *val)
    }
}

/// Value that can be serialized
pub trait Value {
    /// Serialize self into `Serializer`
    ///
    /// Structs implementing this trait should generally
    /// only call respective methods of `serializer`.
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result;
}

/// Value that can be serialized
pub trait Key {
    /// To text representation
    fn as_str(&self) -> &str;
}

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

impl Key for str {
    fn as_str(&self) -> &str {
        &self
    }
}

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

macro_rules! impl_value_for{
    ($t:ty, $f:ident) => {
        impl Value for $t {
            fn serialize(&self, _record : &Record, key : &str, serializer : &mut Serializer)
                         -> Result {
                serializer.$f(key, *self)
            }
        }
    };
}

impl_value_for!(usize, emit_usize);
impl_value_for!(isize, emit_isize);
impl_value_for!(bool, emit_bool);
impl_value_for!(char, emit_char);
impl_value_for!(u8, emit_u8);
impl_value_for!(i8, emit_i8);
impl_value_for!(u16, emit_u16);
impl_value_for!(i16, emit_i16);
impl_value_for!(u32, emit_u32);
impl_value_for!(i32, emit_i32);
impl_value_for!(f32, emit_f32);
impl_value_for!(u64, emit_u64);
impl_value_for!(i64, emit_i64);
impl_value_for!(f64, emit_f64);

impl Value for () {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_unit(key)
    }
}

impl Value for str {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self)
    }
}

impl<'a> Value for &'a str {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self)
    }
}

impl<'a> Value for fmt::Arguments<'a> {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_arguments(key, self)
    }
}

impl Value for String {
    fn serialize(&self,
                 _record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        serializer.emit_str(key, self.as_str())
    }
}

impl<T: Value> Value for Option<T> {
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        match *self {
            Some(ref s) => s.serialize(record, key, serializer),
            None => serializer.emit_none(key),
        }
    }
}

impl Value for Box<Value + Send + 'static> {
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for Arc<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for Rc<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (**self).serialize(record, key, serializer)
    }
}

impl<T> Value for core::num::Wrapping<T>
    where T: Value
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        self.0.serialize(record, key, serializer)
    }
}

impl<V: 'static + Value, F> Value for F
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (self)(record).serialize(record, key, serializer)
    }
}

/// Explicit lazy-closure `Value`
pub struct FnValue<V: 'static + Value, F>(pub F)
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V;

impl<V: 'static + Value, F> Value for FnValue<V, F>
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>) -> V
{
    fn serialize(&self,
                 record: &Record,
                 key: &str,
                 serializer: &mut Serializer)
                 -> Result {
        (self.0)(record).serialize(record, key, serializer)
    }
}

/// Handle passed to `PushFnValue` closure
///
/// It makes sure only one value is serialized, and will automatically emit
/// `()` if nothing else was serialized.
pub struct PushFnSerializer<'a> {
    record: &'a Record<'a>,
    key: &'a str,
    serializer: &'a mut Serializer,
    done: bool,
}

impl<'a> PushFnSerializer<'a> {
    /// Serialize a value
    ///
    /// This consumes `self` to prevent serializing one value multiple times
    pub fn serialize<'b, S: 'b + Value>(mut self, s: S) -> Result {
        self.done = true;
        s.serialize(self.record, self.key, self.serializer)
    }
}

impl<'a> Drop for PushFnSerializer<'a> {
    fn drop(&mut self) {
        if !self.done {
            // unfortunately this gives no change to return serialization errors
            let _ = self.serializer.emit_unit(self.key);
        }
    }
}

/// Lazy `Value` that writes to Serializer
///
/// It's more natural for closures used as lazy values to return `Serialize`
/// implementing type, but sometimes that forces an allocation (eg. Strings)
///
/// In some cases it might make sense for another closure form to be used - one
/// taking a serializer as an argument, which avoids lifetimes / allocation issues.
///
/// Generally this method should be used if it avoids a big allocation of
/// `Serialize`-implementing type in performance-critical logging statement.
///
/// ```
/// #[macro_use]
/// extern crate slog;
/// use slog::{PushFnValue, Logger, Discard};
///
/// fn main() {
///     let _root = Logger::root(Discard, o!( ));
///     info!(_root, "foo"; "writer_closure" => PushFnValue(|_ , s| {
///                    let generated_string = format!("{}", 1);
///                    s.serialize(generated_string.as_str())
///             }));
/// }
/// ```
pub struct PushFnValue<F>(pub F)
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>, PushFnSerializer<'c>) -> Result;

impl<F> Value for PushFnValue<F>
    where F: 'static + for<'c, 'd> Fn(&'c Record<'d>, PushFnSerializer<'c>) -> Result
{
    fn serialize(&self, record: &Record, key: &str, serializer: &mut Serializer)
        -> Result {
        let ser = PushFnSerializer {
            record: record,
            key: key,
            serializer: serializer,
            done: false,
        };
        (self.0)(record, ser)
    }
}

/// Key-value pair(s) that can be serialized
///
/// Zero, one or more key value pairs chained together
pub trait KV {
    /// Serialize self into `Serializer`
    ///
    /// Structs implementing this trait should generally
    /// only call respective methods of `serializer`.
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
                 -> Result;

    /// Split into tuple of `(first, rest)`
    fn split_first(&self) -> Option<(&KV, &KV)>;
}

/// Single pair `Key` and `Value`
pub struct SingleKV<K, V>(pub K, pub V)
    where K : Key, V : Value;

impl<K, V> KV for SingleKV<K, V>
    where K : Key,
          V : Value
{
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            self.1.serialize(record, self.0.as_str(), serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        Some((self, &STATIC_TERMINATOR_UNIT))
    }
}

impl KV for () {
    fn serialize(&self,
                 _record: &Record,
                 _serializer: &mut Serializer)
        -> Result {
            Ok(())
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        None
    }
}

impl<T: KV, R: KV> KV for (T, R) {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            try!(self.0.serialize(record, serializer));
            self.1.serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        Some((&self.0, &self.1))
    }
}

impl<T> KV for Box<T>
where T : KV+?Sized {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            (**self).serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        (**self).split_first()
    }
}

impl<T> KV for Arc<T>
where T : KV+?Sized {
    fn serialize(&self,
                 record: &Record,
                 serializer: &mut Serializer)
        -> Result {
            (**self).serialize(record, serializer)
        }

    fn split_first(&self) -> Option<(&KV, &KV)> {
        (**self).split_first()
    }
}
<|endoftext|>


<commit_before>pub const AT_NULL: u64 = 0;
pub const AT_IGNORE: u64 = 1;
pub const AT_EXECFD: u64 = 2;
pub const AT_PHDR: u64 = 3;
pub const AT_PHENT: u64 = 4;
pub const AT_PHNUM: u64 = 5;
pub const AT_PAGESZ: u64 = 6;
pub const AT_BASE: u64 = 7;
pub const AT_FLAGS: u64 = 8;
pub const AT_ENTRY: u64 = 9;
pub const AT_NOTELF: u64 = 10;
pub const AT_UID: u64 = 11;
pub const AT_EUID: u64 = 12;
pub const AT_GID: u64 = 13;
pub const AT_EGID: u64 = 14;
pub const AT_PLATFORM: u64 = 15;
pub const AT_HWCAP: u64 = 16;
pub const AT_CLKTCK: u64 = 17;
pub const AT_FPUCW: u64 = 18;
pub const AT_DCACHEBSIZE: u64 = 19;
pub const AT_ICACHEBSIZE: u64 = 20;
pub const AT_UCACHEBSIZE: u64 = 21;
pub const AT_IGNOREPPC: u64 = 22;
pub const AT_SECURE: u64 = 23;
pub const AT_BASE_PLATFORM: u64 = 24;
pub const AT_RANDOM: u64 = 25;
pub const AT_HWCAP2: u64 = 26;
pub const AT_EXECFN: u64 = 31;
pub const AT_SYSINFO: u64 = 32;
pub const AT_SYSINFO_EHDR: u64 = 33;
pub const AT_L1I_CACHESHAPE: u64 = 34;
pub const AT_L1D_CACHESHAPE: u64 = 35;
pub const AT_L2_CACHESHAPE: u64 = 36;
pub const AT_L3_CACHESHAPE: u64 = 37;

pub const AUX_CNT: usize = 38;

#[repr(C)]
pub struct Auxv {
    pub a_type: u64,
    pub a_val: u64
}

pub unsafe fn from_raw (auxv: *const Auxv) -> Vec<u64> {
    let mut aux: Vec<u64> = vec![0; AUX_CNT];
    let mut i: isize = 0;
    while (&*auxv.offset(i)).a_val != AT_NULL {
        let auxv_t = &*auxv.offset(i);
        // musl wants the aux a_val array to be indexed by AT_<TYPE>
        aux[auxv_t.a_type as usize] = auxv_t.a_val;
        i += 1;
    }
    aux
}

#[inline(always)]
fn str_of_at (at: u64) -> &'static str {
    match at {
        AT_NULL => "AT_NULL",
        AT_IGNORE => "AT_IGNORE",
        AT_EXECFD => "AT_EXECFD",
        AT_PHDR => "AT_PHDR",
        AT_PHENT => "AT_PHENT",
        AT_PHNUM => "AT_PHNUM",
        AT_PAGESZ => "AT_PAGESZ",
        AT_BASE => "AT_BASE",
        AT_FLAGS => "AT_FLAGS",
        AT_ENTRY => "AT_ENTRY",
        AT_NOTELF => "AT_NOTELF",
        AT_UID => "AT_UID",
        AT_EUID => "AT_EUID",
        AT_GID => "AT_GID",
        AT_EGID => "AT_EGID",
        AT_PLATFORM => "AT_PLATFORM",
        AT_HWCAP => "AT_HWCAP",
        AT_CLKTCK => "AT_CLKTCK",
        AT_FPUCW => "AT_FPUCW",
        AT_DCACHEBSIZE => "AT_DCACHEBSIZE",
        AT_ICACHEBSIZE => "AT_ICACHEBSIZE",
        AT_UCACHEBSIZE => "AT_UCACHEBSIZE",
        AT_IGNOREPPC => "AT_IGNOREPPC",
        AT_SECURE => "AT_SECURE",
        AT_BASE_PLATFORM => "AT_BASE_PLATFORM",
        AT_RANDOM => "AT_RANDOM",
        AT_HWCAP2 => "AT_HWCAP2",
        AT_EXECFN => "AT_EXECFN",
        AT_SYSINFO => "AT_SYSINFO",
        AT_SYSINFO_EHDR => "AT_SYSINFO_EHDR",
        AT_L1I_CACHESHAPE => "AT_L1I_CACHESHAPE",
        AT_L1D_CACHESHAPE => "AT_L1D_CACHESHAPE",
        AT_L2_CACHESHAPE => "AT_L2_CACHESHAPE",
        AT_L3_CACHESHAPE => "AT_L3_CACHESHAPE",
        _ => "UNKNOWN_AT_TYPE",
    }
}

pub fn show (auxvs: &Vec<u64>) {
    for (i, auxv) in auxvs.iter().enumerate() {
        if *auxv != 0 {
            println!("{}: 0x{:x}", str_of_at(i as u64), auxv)
        }
    }
}
<commit_msg>style: change fn name<commit_after>pub const AT_NULL: u64 = 0;
pub const AT_IGNORE: u64 = 1;
pub const AT_EXECFD: u64 = 2;
pub const AT_PHDR: u64 = 3;
pub const AT_PHENT: u64 = 4;
pub const AT_PHNUM: u64 = 5;
pub const AT_PAGESZ: u64 = 6;
pub const AT_BASE: u64 = 7;
pub const AT_FLAGS: u64 = 8;
pub const AT_ENTRY: u64 = 9;
pub const AT_NOTELF: u64 = 10;
pub const AT_UID: u64 = 11;
pub const AT_EUID: u64 = 12;
pub const AT_GID: u64 = 13;
pub const AT_EGID: u64 = 14;
pub const AT_PLATFORM: u64 = 15;
pub const AT_HWCAP: u64 = 16;
pub const AT_CLKTCK: u64 = 17;
pub const AT_FPUCW: u64 = 18;
pub const AT_DCACHEBSIZE: u64 = 19;
pub const AT_ICACHEBSIZE: u64 = 20;
pub const AT_UCACHEBSIZE: u64 = 21;
pub const AT_IGNOREPPC: u64 = 22;
pub const AT_SECURE: u64 = 23;
pub const AT_BASE_PLATFORM: u64 = 24;
pub const AT_RANDOM: u64 = 25;
pub const AT_HWCAP2: u64 = 26;
pub const AT_EXECFN: u64 = 31;
pub const AT_SYSINFO: u64 = 32;
pub const AT_SYSINFO_EHDR: u64 = 33;
pub const AT_L1I_CACHESHAPE: u64 = 34;
pub const AT_L1D_CACHESHAPE: u64 = 35;
pub const AT_L2_CACHESHAPE: u64 = 36;
pub const AT_L3_CACHESHAPE: u64 = 37;

pub const AUX_CNT: usize = 38;

#[repr(C)]
pub struct Auxv {
    pub a_type: u64,
    pub a_val: u64
}

pub unsafe fn from_raw (auxv: *const Auxv) -> Vec<u64> {
    let mut aux: Vec<u64> = vec![0; AUX_CNT];
    let mut i: isize = 0;
    while (&*auxv.offset(i)).a_val != AT_NULL {
        let auxv_t = &*auxv.offset(i);
        // musl wants the aux a_val array to be indexed by AT_<TYPE>
        aux[auxv_t.a_type as usize] = auxv_t.a_val;
        i += 1;
    }
    aux
}

#[inline(always)]
fn str_of_idx (idx: u64) -> &'static str {
    match idx {
        AT_NULL => "AT_NULL",
        AT_IGNORE => "AT_IGNORE",
        AT_EXECFD => "AT_EXECFD",
        AT_PHDR => "AT_PHDR",
        AT_PHENT => "AT_PHENT",
        AT_PHNUM => "AT_PHNUM",
        AT_PAGESZ => "AT_PAGESZ",
        AT_BASE => "AT_BASE",
        AT_FLAGS => "AT_FLAGS",
        AT_ENTRY => "AT_ENTRY",
        AT_NOTELF => "AT_NOTELF",
        AT_UID => "AT_UID",
        AT_EUID => "AT_EUID",
        AT_GID => "AT_GID",
        AT_EGID => "AT_EGID",
        AT_PLATFORM => "AT_PLATFORM",
        AT_HWCAP => "AT_HWCAP",
        AT_CLKTCK => "AT_CLKTCK",
        AT_FPUCW => "AT_FPUCW",
        AT_DCACHEBSIZE => "AT_DCACHEBSIZE",
        AT_ICACHEBSIZE => "AT_ICACHEBSIZE",
        AT_UCACHEBSIZE => "AT_UCACHEBSIZE",
        AT_IGNOREPPC => "AT_IGNOREPPC",
        AT_SECURE => "AT_SECURE",
        AT_BASE_PLATFORM => "AT_BASE_PLATFORM",
        AT_RANDOM => "AT_RANDOM",
        AT_HWCAP2 => "AT_HWCAP2",
        AT_EXECFN => "AT_EXECFN",
        AT_SYSINFO => "AT_SYSINFO",
        AT_SYSINFO_EHDR => "AT_SYSINFO_EHDR",
        AT_L1I_CACHESHAPE => "AT_L1I_CACHESHAPE",
        AT_L1D_CACHESHAPE => "AT_L1D_CACHESHAPE",
        AT_L2_CACHESHAPE => "AT_L2_CACHESHAPE",
        AT_L3_CACHESHAPE => "AT_L3_CACHESHAPE",
        _ => "UNKNOWN_AT_TYPE",
    }
}

pub fn show (auxvs: &Vec<u64>) {
    for (i, auxv) in auxvs.iter().enumerate() {
        if *auxv != 0 {
            println!("{}: 0x{:x}", str_of_idx(i as u64), auxv)
        }
    }
}
<|endoftext|>


<commit_before>use primitives::{Consumed, Parser, ParseError, ParseResult, Error, State, Stream};
use combinator::{FnParser, many, Many, Map, ParserExt, With};
use std::borrow::IntoCow;

macro_rules! impl_char_parser {
    ($name: ident ($($ty_var: ident),*), $inner_type: ty) => {
    #[derive(Clone)]
    pub struct $name<I $(,$ty_var)*>($inner_type)
        where I: Stream<Item=char> $(, $ty_var : Parser<Input=I>)*;
    impl <I $(,$ty_var)*> Parser for $name<I $(,$ty_var)*>
        where I: Stream<Item=char> $(, $ty_var : Parser<Input=I>)* {
        type Input = I;
        type Output = <$inner_type as Parser>::Output;
        fn parse_state(&mut self, input: State<<Self as Parser>::Input>) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input> {
            self.0.parse_state(input)
        }
    }
}
}

///Parses any character
pub fn any_char<I>(input: State<I>) -> ParseResult<char, I>
    where I: Stream<Item=char> {
    input.uncons_char()
}

#[derive(Clone)]
pub struct Satisfy<I, Pred> { pred: Pred }

impl <I, Pred> Parser for Satisfy<I, Pred>
    where I: Stream<Item=char>, Pred: FnMut(char) -> bool {

    type Input = I;
    type Output = char;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<char, I> {
        match input.clone().uncons_char() {
            Ok((c, s)) => {
                if (self.pred)(c) { Ok((c, s)) }
                else {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                }
            }
            Err(err) => Err(err)
        }
    }
}

///Parses a character and succeeds depending on the result of `pred`
///
/// ```
/// # extern crate "parser-combinators" as pc;
/// # use pc::*;
/// # fn main() {
/// let result = satisfy(|c| c == '!')
///     .parse("!")
///     .map(|x| x.0);
/// assert_eq!(result, Ok('!'));
/// # }
/// ```
pub fn satisfy<I, Pred>(pred: Pred) -> Satisfy<I, Pred>
    where I: Stream<Item=char>, Pred: FnMut(char) -> bool {
    Satisfy { pred: pred }
}

impl_char_parser! { Digit(), FnParser<I, char, fn (State<I>) -> ParseResult<char, I>> }
///Parses a digit from a stream containing characters
pub fn digit<I>() -> Digit<I>
        where I: Stream<Item=char> {
    fn digit_<I>(input: State<I>) -> ParseResult<char, I>
        where I: Stream<Item=char> {
        match input.clone().uncons_char() {
            Ok((c, rest)) => {
                if c.is_digit(10) { Ok((c, rest)) }
                else {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Message("Expected digit".into_cow()))))
                }
            }
            Err(err) => Err(err)
        }
    }
    Digit(FnParser(digit_ as fn (_) -> _))
}

impl_char_parser! { Space(), Satisfy<I, fn (char) -> bool> }
///Parses whitespace
pub fn space<I>() -> Space<I>
    where I: Stream<Item=char> {
    Space(satisfy(CharExt::is_whitespace as fn (char) -> bool))
}

impl_char_parser! { Spaces(), Many<Vec<()>, Map<Space<I>, fn (char)>> }
///Skips over zero or more spaces
pub fn spaces<I>() -> Spaces<I>
    where I: Stream<Item=char> {
    Spaces(many(space().map(static_fn!((_, char) -> () { () }))))
}

impl_char_parser! { NewLine(), Satisfy<I, fn (char) -> bool> }
///Parses a newline character
pub fn newline<I>() -> NewLine<I>
    where I: Stream<Item=char> {
    NewLine(satisfy(static_fn!((ch, char) -> bool { ch == '\n' })))
}

impl_char_parser! { CrLf(), With<Satisfy<I, fn (char) -> bool>, NewLine<I>> }
///Parses carriage return and newline, returning the newline character.
pub fn crlf<I>() -> CrLf<I>
    where I: Stream<Item=char> {
    CrLf(satisfy(static_fn!((ch, char) -> bool { ch == '\r' }) as fn (char) -> bool)
        .with(newline()))
}

impl_char_parser! { Tab(), Satisfy<I, fn (char) -> bool> }
///Parses a tab character
pub fn tab<I>() -> Tab<I>
    where I: Stream<Item=char> {
    Tab(satisfy(static_fn!((ch, char) -> bool { ch == '\t' })))
}

impl_char_parser! { Upper(), Satisfy<I, fn (char) -> bool> }
///Parses an uppercase letter
pub fn upper<I>() -> Upper<I>
    where I: Stream<Item=char> {
    Upper(satisfy(static_fn!((ch, char) -> bool { ch.is_uppercase()})))
}

impl_char_parser! { Lower(), Satisfy<I, fn (char) -> bool> }
///Parses an uppercase letter
pub fn lower<I>() -> Lower<I>
    where I: Stream<Item=char> {
    Lower(satisfy(static_fn!((ch, char) -> bool { ch.is_lowercase() })))
}

impl_char_parser! { AlphaNum(), Satisfy<I, fn (char) -> bool> }
///Parses either an alphabet letter or digit
pub fn alpha_num<I>() -> AlphaNum<I>
    where I: Stream<Item=char> {
    AlphaNum(satisfy(static_fn!((ch, char) -> bool { ch.is_alphanumeric() })))
}

impl_char_parser! { Letter(), Satisfy<I, fn (char) -> bool> }
///Parses an alphabet letter
pub fn letter<I>() -> Letter<I>
    where I: Stream<Item=char> {
    Letter(satisfy(static_fn!((ch, char) -> bool { ch.is_alphabetic() })))
}

impl_char_parser! { OctDigit(), Satisfy<I, fn (char) -> bool> }
///Parses an octal digit
pub fn oct_digit<I>() -> OctDigit<I>
    where I: Stream<Item=char> {
    OctDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(8) })))
}

impl_char_parser! { HexDigit(), Satisfy<I, fn (char) -> bool> }
///Parses a hexdecimal digit with uppercase and lowercase
pub fn hex_digit<I>() -> HexDigit<I>
    where I: Stream<Item=char> {
    HexDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(0x10) })))
}

#[derive(Clone)]
pub struct StringP<'a, I> { s: &'a str }
impl <'a, I> Parser for StringP<'a, I>
    where I: Stream<Item=char> {
    type Input = I;
    type Output = &'a str;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<&'a str, I> {
        let start = input.position;
        let mut input = Consumed::Empty(input);
        for (i, c) in self.s.chars().enumerate() {
            match input.combine(|input| input.uncons_char()) {
                Ok((other, rest)) => {
                    if c != other {
                        let error = ParseError::new(start, Error::Expected(self.s.to_string().into_cow()));
                        return Err(if i == 0 { Consumed::Empty(error) } else { Consumed::Consumed(error) });
                    }
                    input = rest;
                }
                Err(error) => {
                    return error.combine(move |mut error| {
                        error.position = start;
                        Err(if i == 0 { Consumed::Empty(error) } else { Consumed::Consumed(error) })
                    })
                }
            }
        }
        Ok((self.s, input))
    }
}

///Parses the string `s`
///
/// ```
/// # extern crate "parser-combinators" as pc;
/// # use pc::*;
/// # fn main() {
/// let result = string("rust")
///     .parse("rust")
///     .map(|x| x.0);
/// assert_eq!(result, Ok("rust"));
/// # }
/// ```
pub fn string<I>(s: &str) -> StringP<I>
    where I: Stream<Item=char> {
    StringP { s: s }
}
<commit_msg>Added a proper error message to the space parser<commit_after>use primitives::{Consumed, Parser, ParseError, ParseResult, Error, State, Stream};
use combinator::{Expected, FnParser, many, Many, Map, ParserExt, With};
use std::borrow::IntoCow;

macro_rules! impl_char_parser {
    ($name: ident ($($ty_var: ident),*), $inner_type: ty) => {
    #[derive(Clone)]
    pub struct $name<I $(,$ty_var)*>($inner_type)
        where I: Stream<Item=char> $(, $ty_var : Parser<Input=I>)*;
    impl <I $(,$ty_var)*> Parser for $name<I $(,$ty_var)*>
        where I: Stream<Item=char> $(, $ty_var : Parser<Input=I>)* {
        type Input = I;
        type Output = <$inner_type as Parser>::Output;
        fn parse_state(&mut self, input: State<<Self as Parser>::Input>) -> ParseResult<<Self as Parser>::Output, <Self as Parser>::Input> {
            self.0.parse_state(input)
        }
    }
}
}

///Parses any character
pub fn any_char<I>(input: State<I>) -> ParseResult<char, I>
    where I: Stream<Item=char> {
    input.uncons_char()
}

#[derive(Clone)]
pub struct Satisfy<I, Pred> { pred: Pred }

impl <I, Pred> Parser for Satisfy<I, Pred>
    where I: Stream<Item=char>, Pred: FnMut(char) -> bool {

    type Input = I;
    type Output = char;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<char, I> {
        match input.clone().uncons_char() {
            Ok((c, s)) => {
                if (self.pred)(c) { Ok((c, s)) }
                else {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                }
            }
            Err(err) => Err(err)
        }
    }
}

///Parses a character and succeeds depending on the result of `pred`
///
/// ```
/// # extern crate "parser-combinators" as pc;
/// # use pc::*;
/// # fn main() {
/// let result = satisfy(|c| c == '!')
///     .parse("!")
///     .map(|x| x.0);
/// assert_eq!(result, Ok('!'));
/// # }
/// ```
pub fn satisfy<I, Pred>(pred: Pred) -> Satisfy<I, Pred>
    where I: Stream<Item=char>, Pred: FnMut(char) -> bool {
    Satisfy { pred: pred }
}

impl_char_parser! { Digit(), FnParser<I, char, fn (State<I>) -> ParseResult<char, I>> }
///Parses a digit from a stream containing characters
pub fn digit<I>() -> Digit<I>
        where I: Stream<Item=char> {
    fn digit_<I>(input: State<I>) -> ParseResult<char, I>
        where I: Stream<Item=char> {
        match input.clone().uncons_char() {
            Ok((c, rest)) => {
                if c.is_digit(10) { Ok((c, rest)) }
                else {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Message("Expected digit".into_cow()))))
                }
            }
            Err(err) => Err(err)
        }
    }
    Digit(FnParser(digit_ as fn (_) -> _))
}

impl_char_parser! { Space(), Expected<Satisfy<I, fn (char) -> bool>> }
///Parses whitespace
pub fn space<I>() -> Space<I>
    where I: Stream<Item=char> {
    Space(satisfy(CharExt::is_whitespace as fn (char) -> bool)
        .expected("whitespace"))
}
impl_char_parser! { Spaces(), Many<Vec<()>, Map<Space<I>, fn (char)>> }
///Skips over zero or more spaces
pub fn spaces<I>() -> Spaces<I>
    where I: Stream<Item=char> {
    Spaces(many(space().map(static_fn!((_, char) -> () { () }))))
}

impl_char_parser! { NewLine(), Satisfy<I, fn (char) -> bool> }
///Parses a newline character
pub fn newline<I>() -> NewLine<I>
    where I: Stream<Item=char> {
    NewLine(satisfy(static_fn!((ch, char) -> bool { ch == '\n' })))
}

impl_char_parser! { CrLf(), With<Satisfy<I, fn (char) -> bool>, NewLine<I>> }
///Parses carriage return and newline, returning the newline character.
pub fn crlf<I>() -> CrLf<I>
    where I: Stream<Item=char> {
    CrLf(satisfy(static_fn!((ch, char) -> bool { ch == '\r' }) as fn (char) -> bool)
        .with(newline()))
}

impl_char_parser! { Tab(), Satisfy<I, fn (char) -> bool> }
///Parses a tab character
pub fn tab<I>() -> Tab<I>
    where I: Stream<Item=char> {
    Tab(satisfy(static_fn!((ch, char) -> bool { ch == '\t' })))
}

impl_char_parser! { Upper(), Satisfy<I, fn (char) -> bool> }
///Parses an uppercase letter
pub fn upper<I>() -> Upper<I>
    where I: Stream<Item=char> {
    Upper(satisfy(static_fn!((ch, char) -> bool { ch.is_uppercase()})))
}

impl_char_parser! { Lower(), Satisfy<I, fn (char) -> bool> }
///Parses an uppercase letter
pub fn lower<I>() -> Lower<I>
    where I: Stream<Item=char> {
    Lower(satisfy(static_fn!((ch, char) -> bool { ch.is_lowercase() })))
}

impl_char_parser! { AlphaNum(), Satisfy<I, fn (char) -> bool> }
///Parses either an alphabet letter or digit
pub fn alpha_num<I>() -> AlphaNum<I>
    where I: Stream<Item=char> {
    AlphaNum(satisfy(static_fn!((ch, char) -> bool { ch.is_alphanumeric() })))
}

impl_char_parser! { Letter(), Satisfy<I, fn (char) -> bool> }
///Parses an alphabet letter
pub fn letter<I>() -> Letter<I>
    where I: Stream<Item=char> {
    Letter(satisfy(static_fn!((ch, char) -> bool { ch.is_alphabetic() })))
}

impl_char_parser! { OctDigit(), Satisfy<I, fn (char) -> bool> }
///Parses an octal digit
pub fn oct_digit<I>() -> OctDigit<I>
    where I: Stream<Item=char> {
    OctDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(8) })))
}

impl_char_parser! { HexDigit(), Satisfy<I, fn (char) -> bool> }
///Parses a hexdecimal digit with uppercase and lowercase
pub fn hex_digit<I>() -> HexDigit<I>
    where I: Stream<Item=char> {
    HexDigit(satisfy(static_fn!((ch, char) -> bool { ch.is_digit(0x10) })))
}

#[derive(Clone)]
pub struct StringP<'a, I> { s: &'a str }
impl <'a, I> Parser for StringP<'a, I>
    where I: Stream<Item=char> {
    type Input = I;
    type Output = &'a str;
    fn parse_state(&mut self, input: State<I>) -> ParseResult<&'a str, I> {
        let start = input.position;
        let mut input = Consumed::Empty(input);
        for (i, c) in self.s.chars().enumerate() {
            match input.combine(|input| input.uncons_char()) {
                Ok((other, rest)) => {
                    if c != other {
                        let error = ParseError::new(start, Error::Expected(self.s.to_string().into_cow()));
                        return Err(if i == 0 { Consumed::Empty(error) } else { Consumed::Consumed(error) });
                    }
                    input = rest;
                }
                Err(error) => {
                    return error.combine(move |mut error| {
                        error.position = start;
                        Err(if i == 0 { Consumed::Empty(error) } else { Consumed::Consumed(error) })
                    })
                }
            }
        }
        Ok((self.s, input))
    }
}

///Parses the string `s`
///
/// ```
/// # extern crate "parser-combinators" as pc;
/// # use pc::*;
/// # fn main() {
/// let result = string("rust")
///     .parse("rust")
///     .map(|x| x.0);
/// assert_eq!(result, Ok("rust"));
/// # }
/// ```
pub fn string<I>(s: &str) -> StringP<I>
    where I: Stream<Item=char> {
    StringP { s: s }
}

#[cfg(test)]
mod tests {
    use super::space;
    use primitives::{Error, Parser};
    use std::borrow::IntoCow;

    #[test]
    fn space_error() {
        let result = space()
            .parse("");
        assert!(result.is_err());
        assert_eq!(result.unwrap_err().errors, vec![Error::Expected("whitespace".into_cow())]);

    }
}
<|endoftext|>


<commit_before>use std::fmt::Show;

#[derive(PartialEq, Copy)]
pub struct Dice {
    pub d4s: usize,
    pub d6s: usize,
    pub d8s: usize,
    pub d10s: usize,
    pub d12s: usize,
    pub d20s: usize,
    pub modifier: isize
}

impl Show for Dice {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let mut buff = String::new();
        if self.d4s != 0 {
            buff.push_str(format!("{}d4 ", self.d4s).as_slice());
        }
        if self.d6s != 0 {
            buff.push_str(format!("{}d6 ", self.d6s).as_slice());
        }
        if self.d8s != 0 {
            buff.push_str(format!("{}d8 ", self.d8s).as_slice());
        }
        if self.d10s != 0 {
            buff.push_str(format!("{}d10 ", self.d10s).as_slice());
        }
        if self.d12s != 0 {
            buff.push_str(format!("{}d12 ", self.d12s).as_slice());
        }
        if self.d20s != 0 {
            buff.push_str(format!("{}d20 ", self.d20s).as_slice());
        }
        if self.modifier > 0 {
            buff.push_str(format!("+{}", self.modifier).as_slice());
        }
        if self.modifier < 0 {
            buff.push_str(format!("-{}", self.modifier).as_slice());
        }
        write!(f, "{}", buff.as_slice().trim())
    }
}
<commit_msg>fixed bugged Show trait impl for dice w/ neg modifier<commit_after>use std::fmt::Show;
use std::num::SignedInt;

#[derive(PartialEq, Copy)]
pub struct Dice {
    pub d4s: usize,
    pub d6s: usize,
    pub d8s: usize,
    pub d10s: usize,
    pub d12s: usize,
    pub d20s: usize,
    pub modifier: isize
}

impl Show for Dice {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        let mut buff = String::new();
        if self.d4s != 0 {
            buff.push_str(format!("{}d4 ", self.d4s).as_slice());
        }
        if self.d6s != 0 {
            buff.push_str(format!("{}d6 ", self.d6s).as_slice());
        }
        if self.d8s != 0 {
            buff.push_str(format!("{}d8 ", self.d8s).as_slice());
        }
        if self.d10s != 0 {
            buff.push_str(format!("{}d10 ", self.d10s).as_slice());
        }
        if self.d12s != 0 {
            buff.push_str(format!("{}d12 ", self.d12s).as_slice());
        }
        if self.d20s != 0 {
            buff.push_str(format!("{}d20 ", self.d20s).as_slice());
        }
        if self.modifier > 0 {
            buff.push_str(format!("+{}", self.modifier).as_slice());
        }
        if self.modifier < 0 {
            buff.push_str(format!("-{}", self.modifier.abs()).as_slice());
        }
        write!(f, "{}", buff.as_slice().trim())
    }
}
<|endoftext|>


<commit_before>use funcs::*;
use env::*;
use atom::*;
use errors::*;
use errors::Error::*;

fn eval_procedure(p: &Procedure, args: &[Atom], env: &mut Env) ->  AtomResult {
    try!(env.apply(&p.params, &args[1..]));

    let res = p.body.iter()
        .map(|node| eval(&node, env))
        .last().unwrap_or(Err(InvalidArguments));

    env.pop();

    res
}

fn eval_macro(p: &Procedure, args: &[Atom], env: &mut Env) -> AtomResult {
    //println!("about to eval: {:?}\n with args {:?}", p, args);
    try!(env.apply(&p.params, args));
    let res = p.body.iter()
        .map(|node| {
            //println!("res: {}", node);
            eval(&node, env)
        })
        .last().unwrap_or(Err(InvalidArguments));

    //println!("macro eval res: {:?}", res);
    env.pop();

    res
}

fn define(args: &[Atom], env: &mut Env) -> AtomResult {
    if args.len() != 2 {
        return Err(Error::InvalidArguments);
    }

    if let Atom::Symbol(ref key) = args[0] {
        let value = try!(eval(&args[1], env));
        env.set(key.clone(), value);
        Ok(Atom::Nil)
    } else {
        Err(Error::InvalidArguments)
    }
}

fn quote(list: &[Atom]) -> AtomResult {
    list.first().map(|atom| atom.clone()).ok_or(InvalidArguments)
}

fn collect_body(l: &[Atom]) -> Vec<Atom> {
    l.iter().skip(2).map(|x| x.clone()).collect()
}

fn macroexpand(list: &[Atom], env: &Env) -> AtomResult {
    Err(NotImplemented)
}

fn do_form(list: &[Atom], env: &mut Env) -> AtomResult {
    list.iter()
        .map(|node| eval(&node, env))
        .last().unwrap_or(Err(InvalidArguments))
}

fn make_proc(list: &[Atom]) -> AtomResult {
    if let Atom::List(ref p) = list[1] {
        Ok(Atom::Function(Function::Proc(Procedure{ params: p.clone(),
                                                    body: collect_body(list)})))
    } else {
        Err(InvalidArguments)
    }
}

fn macro_form(params: &Atom, list: Vec<Atom>) -> AtomResult {
    if let Atom::List(ref p) = *params {
        // println!("args: {:?}", p);
        // println!("body: {:?}", list);

        Ok(Atom::Function(Function::Macro(Procedure{ params: p.clone(),
                                                     body: list})))
    } else {
        Err(InvalidArguments)
    }
}

fn if_form(list: &[Atom], env: &mut Env) -> AtomResult {
    if list.len() < 2 {
        Err(InvalidArguments)
    } else {
        eval(&list[0], env)
            .and_then(|p| {
                let truthy = match p {
                    Atom::Boolean(b) => b,
                    Atom::Nil => false,
                    _ => true
                };
                if truthy {
                    eval(&list[1], env)
                } else if list.len() > 2 {
                    eval(&list[2], env)
                } else {
                    Ok(Atom::Boolean(false))
                }
            })
    }
}

fn eval_special_forms(f: Form, list: &[Atom], env: &mut Env) -> AtomResult {
    use atom::Form::*;
    match f {
        Def => {
            define(&list[1..], env)
        },
        Do => {
            do_form(&list[1..], env)
        },
        Macro => {
            panic!("ds");
            //macro_form(list)
        }
        Fn => {
            make_proc(&list)
        },
        Quote => {
            quote(&list[1..])
        },
        If => {
            if_form(&list[1..], env)
        },
        MacroExpand => {
            macroexpand(&list[1..], env)
        },
        _ => Err(InvalidArguments)
    }
}

fn eval_node(atom: &Atom, list: &[Atom], env: &mut Env) -> AtomResult {
    match *atom {
        Atom::Form(Form::QuasiQuote) => Ok(Atom::List(list.iter().map(|n| n.clone()).collect())),
        Atom::Symbol(_) =>  {
            let args: Vec<Atom> = try!(list.iter().map(|n| eval(n, env)).collect());
            eval_node(&args[0], &args, env)
        },
        Atom::Form(f) => eval_special_forms(f, list, env),
        Atom::Function(ref func) => {
            match *func {
                Function::Proc(ref p) => {
                    eval_procedure(p, list, env)
                }
                Function::Native(native) => {
                    eval_native(native, &list[1..], env)
                },
                Function::Macro(ref m) => {
                    eval_macro(m, &list[1..], env)
                        .and_then(|n| eval(&n, env))
                }
            }
        }
        _ => {
            Err(Error::NotAFunction)
        }
    }
}

pub fn eval(node: &Atom, env: &mut Env) -> Result<Atom, Error> {
    //println!("eval: {}", node);
    match *node {
        Atom::List(ref list) if !list.is_empty() => {
            eval(&list[0], env).and_then(|first| eval_node(&first, list, env))
        },
        Atom::Symbol(ref s) => {
            Ok(env.get(s).unwrap_or(Atom::Nil))
        }
        _ => Ok(node.clone())
    }
}

fn expand_quasiquote(atom: &Atom) -> AtomResult {
    //println!("expand_quasiquote: {}", atom);
    if !atom.is_pair() { // ()
        return Ok(Atom::List(vec![Atom::Form(Form::Quote), atom.clone()]))
    }

    if let Atom::List(ref list) = *atom {
        if let Atom::Form(Form::Unquote) = list[0] {
            // ~x
            return Ok(list[1].clone())
        }

        if let Atom::List(ref sublist) = list[0] {
            // (())
            println!("WARNING I HOPE WE DONT GET HERE");
            match sublist[0] {
                Atom::Form(Form::Splice) => {
                    // ((splice x) y)
                    let mut v = vec![];
                    v.push(sublist[1].clone());
                    for i in list.iter().skip(1) {
                        v.push(i.clone())
                    }
                    return Ok(Atom::List(v))
                }
                _ => ()
            }
        }
        let v = Atom::List(try!(list.iter().map(|n| expand_quasiquote(&n)).collect()));
        //println!("expanded list: {}", v);
        return Ok(v)
    } else {
        println!("arg");
        Err(Error::Parser)
    }
}

pub fn expand(node: &Atom, env: &mut Env, depth: i32) -> AtomResult {
    match *node {
        Atom::List(ref list) => {
            list.first().ok_or(Error::Parser)
                .and_then(|n| expand(n, env, depth + 1))
                .and_then(|n| expand_node(&n, &list[0..], env, depth + 1))
        },
        Atom::Symbol(ref sym) => {
            //println!("resolving sym: {}", sym);
            Ok(env.get(sym).unwrap_or(Atom::Nil))
        },
        _ => Ok(node.clone())
    }
}

pub fn expand_node(node: &Atom, list: &[Atom], env: &mut Env, depth: i32) -> AtomResult {
    match *node {
        Atom::Form(Form::Quote) => {
            Ok(list[1].clone())
        }
        Atom::Form(Form::Unquote) => {
            //println!("unquote: {}", node);
            Ok(node.clone())
        },
        Atom::Form(Form::Macro) => {
            let exps: Vec<Atom> = try!(list.iter().skip(3).map(|n| expand(&n, env, depth + 1)).collect());
            let m = try!(macro_form(&list[2], exps));

            if let Atom::Symbol(ref k) = list[1] {
                env.set(k.clone(), m);
                Ok(Atom::Nil)
            } else {
                Err(Error::InvalidArguments)
            }
        },
        Atom::Function(ref func) => {
            match *func {
                Function::Macro(ref m) => {
                    // println!("eval_macro");
                    eval_macro(m, &list[1..], env).and_then(|a| {
                        // println!("and_then expand: {}", a);
                        expand(&a, env, depth + 1)})
                },
                _ => {
                    Ok(Atom::List(try!(list.iter().map(|n| expand(n, env, depth + 1)).collect())))
                }
            }
        },
        Atom::Form(Form::QuasiQuote) => {
            expand_quasiquote(&list[1])
        }
        _ => {
            Ok(Atom::List(try!(list.iter().map(|n| expand(n, env, depth + 1)).collect())))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use parser::*;
    use atom::*;
    use env::Env;

    #[test]
    fn if_special_form() {
        let x = eval(&tokenize("(if (= 1 1) true false)").unwrap(), &mut Env::new()).unwrap();

        assert_eq!(Atom::from(true), x);
    }

    #[test]
    fn if_special_form_false() {
        let x = eval(&tokenize("(if (= 1 2) true false)").unwrap(), &mut Env::new()).unwrap();

        assert_eq!(Atom::Boolean(false), x);
    }

    #[test]
    fn if_no_else() {
        let x = teval("(if (= 1 1) true)");

        assert_eq!(Atom::Boolean(true), x);
    }

    fn tassert(v: &str) {
        assert_eq!(Atom::Boolean(true), teval(v));
    }

    fn trefute(v: &str) {
        assert_eq!(Atom::Boolean(false), teval(v));
    }

    #[test]
    fn comparisons() {
        tassert("(= 1 1 1 1)");
        trefute("(= 1 0 1 1)");
        tassert("(< 1 5 10)");
        trefute("(< 5 1 20)");
        tassert("(<= 1 1 1 5)");
        trefute("(<= 5 2 1 5)");
        tassert("(> 5 3 2 1)");
        trefute("(> 5 3 2 10)");
        tassert("(>= 5 5 5 3)");
        trefute("(>= 5 5 5 10)");
    }
    use number::Number;

    fn num(i: i64) -> Atom {
        Atom::Number(Number::Integer(i))
    }

    #[test]
    fn adds() {
        assert_eq!(num(5), teval("(+ 2 3)"));
        assert_eq!(num(25), teval("(+ 5 5 5 5 5)"));
    }

    #[test]
    fn subs() {
        assert_eq!(num(0), teval("(- 5 5)"));
        assert_eq!(num(5), teval("(- 20 10 5)"));
    }

    #[test]
    fn muls() {
        assert_eq!(num(0), teval("(* 5 5 5 0)"));
        assert_eq!(num(5), teval("(* 1 5)"));
        assert_eq!(num(-5), teval("(* -1 5)"));
    }

    fn teval(s: &str) -> Atom {
        eval(&tokenize(s).unwrap(), &mut Env::new()).unwrap()
    }

    fn teval_env(s: &str, env: &mut Env) -> AtomResult {
        eval(&tokenize(s).unwrap(), env)
    }

    #[test]
    fn symbol_resolving() {
        let mut env = Env::new();

        teval_env("(def foo 5)", &mut env).unwrap();

        assert_eq!(num(0), teval_env("(- foo 5)", &mut env).unwrap());
    }

    #[test]
    fn no_def_func() {
        assert_eq!(teval("3"), teval("((fn (a b) (+ a b)) 1 2)"));
    }

    // #[test]
    // fn first_and_rest() {
    //     assert_eq!(num(0), teval("(first (list 0 1 2))"));
    //     assert_eq!(teval("(list 1 2)"), teval("(rest (list 0 1 2))"));
    // }

    #[test]
    fn simple_func() {
        let mut env = Env::new();
        let _ = eval(&tokenize("(def f (fn (r b) (+ r b)))").unwrap(), &mut env).unwrap();
        let res = eval(&tokenize("(f 2 3)").unwrap(), &mut env).unwrap();

        assert_eq!(num(5), res);
    }

    #[test]
    fn quote_func() {
        assert_eq!(teval("'(1 2)"), teval("(quote (1 2))"));
        assert_eq!(teval("'a"), teval("(quote a)"));
    }

    #[test]
    fn do_func() {
        assert_eq!(teval("4"), teval("(do (+ 1 2) (+ 2 2))"));
    }

    #[test]
     fn simple_macro() {
         let mut env = Env::new();
         teval_env("(defmacro m () '(+ 3 5))", &mut env).unwrap();
         assert_eq!(teval("'(+ 3 5)"), teval_env("(macroexpand '(m))", &mut env).unwrap());

         teval_env("(def mm (macro () (+ 3 5)))", &mut env).unwrap();
         assert_eq!(teval("8"), teval_env("(macroexpand '(mm))", &mut env).unwrap());

         assert_eq!(teval("8"), teval_env("(m)", &mut env).unwrap());
         assert_eq!(teval("8"), teval_env("(mm)", &mut env).unwrap());
     }

    #[test]
    fn more_complex_macro() {
        let mut env = Env::new();
        teval_env("(defmacro unless (p a b) `(if (not ~p) ~a ~b)", &mut env).unwrap();
        assert_eq!(teval("3"), teval_env("(unless false 3 5)", &mut env).unwrap());
    }
}
<commit_msg>fix quote<commit_after>use funcs::*;
use env::*;
use atom::*;
use errors::*;
use errors::Error::*;

fn eval_procedure(p: &Procedure, args: &[Atom], env: &mut Env) ->  AtomResult {
    try!(env.apply(&p.params, &args[1..]));

    let res = p.body.iter()
        .map(|node| eval(&node, env))
        .last().unwrap_or(Err(InvalidArguments));

    env.pop();

    res
}

fn eval_macro(p: &Procedure, args: &[Atom], env: &mut Env) -> AtomResult {
    //println!("about to eval: {:?}\n with args {:?}", p, args);
    try!(env.apply(&p.params, args));
    let res = p.body.iter()
        .map(|node| {
            //println!("res: {}", node);
            eval(&node, env)
        })
        .last().unwrap_or(Err(InvalidArguments));

    //println!("macro eval res: {:?}", res);
    env.pop();

    res
}

fn define(args: &[Atom], env: &mut Env) -> AtomResult {
    if args.len() != 2 {
        return Err(Error::InvalidArguments);
    }

    if let Atom::Symbol(ref key) = args[0] {
        let value = try!(eval(&args[1], env));
        env.set(key.clone(), value);
        Ok(Atom::Nil)
    } else {
        Err(Error::InvalidArguments)
    }
}

fn quote(list: &[Atom]) -> AtomResult {
    list.first().map(|atom| atom.clone()).ok_or(InvalidArguments)
}

fn collect_body(l: &[Atom]) -> Vec<Atom> {
    l.iter().skip(2).map(|x| x.clone()).collect()
}

fn macroexpand(list: &[Atom], env: &Env) -> AtomResult {
    Err(NotImplemented)
}

fn do_form(list: &[Atom], env: &mut Env) -> AtomResult {
    list.iter()
        .map(|node| eval(&node, env))
        .last().unwrap_or(Err(InvalidArguments))
}

fn make_proc(list: &[Atom]) -> AtomResult {
    if let Atom::List(ref p) = list[1] {
        Ok(Atom::Function(Function::Proc(Procedure{ params: p.clone(),
                                                    body: collect_body(list)})))
    } else {
        Err(InvalidArguments)
    }
}

fn macro_form(params: &Atom, list: Vec<Atom>) -> AtomResult {
    if let Atom::List(ref p) = *params {
        // println!("args: {:?}", p);
        // println!("body: {:?}", list);

        Ok(Atom::Function(Function::Macro(Procedure{ params: p.clone(),
                                                     body: list})))
    } else {
        Err(InvalidArguments)
    }
}

fn if_form(list: &[Atom], env: &mut Env) -> AtomResult {
    if list.len() < 2 {
        Err(InvalidArguments)
    } else {
        eval(&list[0], env)
            .and_then(|p| {
                let truthy = match p {
                    Atom::Boolean(b) => b,
                    Atom::Nil => false,
                    _ => true
                };
                if truthy {
                    eval(&list[1], env)
                } else if list.len() > 2 {
                    eval(&list[2], env)
                } else {
                    Ok(Atom::Boolean(false))
                }
            })
    }
}

fn eval_special_forms(f: Form, list: &[Atom], env: &mut Env) -> AtomResult {
    use atom::Form::*;
    match f {
        Def => {
            define(&list[1..], env)
        },
        Do => {
            do_form(&list[1..], env)
        },
        Macro => {
            panic!("ds");
            //macro_form(list)
        }
        Fn => {
            make_proc(&list)
        },
        Quote => {
            quote(&list[1..])
        },
        If => {
            if_form(&list[1..], env)
        },
        MacroExpand => {
            macroexpand(&list[1..], env)
        },
        _ => Err(InvalidArguments)
    }
}

fn eval_node(atom: &Atom, list: &[Atom], env: &mut Env) -> AtomResult {
    match *atom {
        Atom::Form(Form::QuasiQuote) => Ok(Atom::List(list.iter().map(|n| n.clone()).collect())),
        Atom::Symbol(_) =>  {
            let args: Vec<Atom> = try!(list.iter().map(|n| eval(n, env)).collect());
            eval_node(&args[0], &args, env)
        },
        Atom::Form(f) => eval_special_forms(f, list, env),
        Atom::Function(ref func) => {
            match *func {
                Function::Proc(ref p) => {
                    eval_procedure(p, list, env)
                }
                Function::Native(native) => {
                    eval_native(native, &list[1..], env)
                },
                Function::Macro(ref m) => {
                    eval_macro(m, &list[1..], env)
                        .and_then(|n| eval(&n, env))
                }
            }
        }
        _ => {
            Err(Error::NotAFunction)
        }
    }
}

pub fn eval(node: &Atom, env: &mut Env) -> Result<Atom, Error> {
    //println!("eval: {}", node);
    match *node {
        Atom::List(ref list) if !list.is_empty() => {
            eval(&list[0], env).and_then(|first| eval_node(&first, list, env))
        },
        Atom::Symbol(ref s) => {
            Ok(env.get(s).unwrap_or(Atom::Nil))
        }
        _ => Ok(node.clone())
    }
}

fn expand_quasiquote(atom: &Atom) -> AtomResult {
    //println!("expand_quasiquote: {}", atom);
    if !atom.is_pair() { // ()
        return Ok(Atom::List(vec![Atom::Form(Form::Quote), atom.clone()]))
    }

    if let Atom::List(ref list) = *atom {
        if let Atom::Form(Form::Unquote) = list[0] {
            // ~x
            return Ok(list[1].clone())
        }

        if let Atom::List(ref sublist) = list[0] {
            // (())
            println!("WARNING I HOPE WE DONT GET HERE");
            match sublist[0] {
                Atom::Form(Form::Splice) => {
                    // ((splice x) y)
                    let mut v = vec![];
                    v.push(sublist[1].clone());
                    for i in list.iter().skip(1) {
                        v.push(i.clone())
                    }
                    return Ok(Atom::List(v))
                }
                _ => ()
            }
        }
        let v = Atom::List(try!(list.iter().map(|n| expand_quasiquote(&n)).collect()));
        //println!("expanded list: {}", v);
        return Ok(v)
    } else {
        println!("arg");
        Err(Error::Parser)
    }
}

pub fn expand(node: &Atom, env: &mut Env, depth: i32) -> AtomResult {
    match *node {
        Atom::List(ref list) => {
            list.first().ok_or(Error::Parser)
                .and_then(|n| expand(n, env, depth + 1))
                .and_then(|n| expand_node(&n, &list[0..], env, depth + 1))
        },
        Atom::Symbol(ref sym) => {
            Ok(env.get(sym).unwrap_or(Atom::Nil))
        },
        _ => Ok(node.clone())
    }
}

pub fn expand_node(node: &Atom, list: &[Atom], env: &mut Env, depth: i32) -> AtomResult {
    match *node {
        Atom::Form(Form::Quote) => {
            Ok(Atom::List(list.iter().map(|n| n.clone()).collect()))
        }
        Atom::Form(Form::Unquote) => {
            //println!("unquote: {}", node);
            Ok(node.clone())
        },
        Atom::Form(Form::Macro) => {
            let exps: Vec<Atom> = try!(list.iter().skip(3).map(|n| expand(&n, env, depth + 1)).collect());
            let m = try!(macro_form(&list[2], exps));

            if let Atom::Symbol(ref k) = list[1] {
                env.set(k.clone(), m);
                Ok(Atom::Nil)
            } else {
                Err(Error::InvalidArguments)
            }
        },
        Atom::Function(ref func) => {
            match *func {
                Function::Macro(ref m) => {
                    // println!("eval_macro");
                    eval_macro(m, &list[1..], env).and_then(|a| {
                        // println!("and_then expand: {}", a);
                        expand(&a, env, depth + 1)})
                },
                _ => {
                    Ok(Atom::List(try!(list.iter().map(|n| expand(n, env, depth + 1)).collect())))
                }
            }
        },
        Atom::Form(Form::QuasiQuote) => {
            expand_quasiquote(&list[1])
        }
        _ => {
            Ok(Atom::List(try!(list.iter().map(|n| expand(n, env, depth + 1)).collect())))
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use parser::*;
    use atom::*;
    use env::Env;

    #[test]
    fn if_special_form() {
        let x = eval(&tokenize("(if (= 1 1) true false)").unwrap(), &mut Env::new()).unwrap();

        assert_eq!(Atom::from(true), x);
    }

    #[test]
    fn if_special_form_false() {
        let x = eval(&tokenize("(if (= 1 2) true false)").unwrap(), &mut Env::new()).unwrap();

        assert_eq!(Atom::Boolean(false), x);
    }

    #[test]
    fn if_no_else() {
        let x = teval("(if (= 1 1) true)");

        assert_eq!(Atom::Boolean(true), x);
    }

    fn tassert(v: &str) {
        assert_eq!(Atom::Boolean(true), teval(v));
    }

    fn trefute(v: &str) {
        assert_eq!(Atom::Boolean(false), teval(v));
    }

    #[test]
    fn comparisons() {
        tassert("(= 1 1 1 1)");
        trefute("(= 1 0 1 1)");
        tassert("(< 1 5 10)");
        trefute("(< 5 1 20)");
        tassert("(<= 1 1 1 5)");
        trefute("(<= 5 2 1 5)");
        tassert("(> 5 3 2 1)");
        trefute("(> 5 3 2 10)");
        tassert("(>= 5 5 5 3)");
        trefute("(>= 5 5 5 10)");
    }
    use number::Number;

    fn num(i: i64) -> Atom {
        Atom::Number(Number::Integer(i))
    }

    #[test]
    fn adds() {
        assert_eq!(num(5), teval("(+ 2 3)"));
        assert_eq!(num(25), teval("(+ 5 5 5 5 5)"));
    }

    #[test]
    fn subs() {
        assert_eq!(num(0), teval("(- 5 5)"));
        assert_eq!(num(5), teval("(- 20 10 5)"));
    }

    #[test]
    fn muls() {
        assert_eq!(num(0), teval("(* 5 5 5 0)"));
        assert_eq!(num(5), teval("(* 1 5)"));
        assert_eq!(num(-5), teval("(* -1 5)"));
    }

    fn teval(s: &str) -> Atom {
        let mut env = Env::new();
        tokenize(s).and_then(|n| expand(&n, &mut env, 0))
            .and_then(|n| eval(&n, &mut env)).unwrap()
    }

    fn teval_env(s: &str, env: &mut Env) -> AtomResult {
        tokenize(s).and_then(|n| expand(&n, env, 0))
            .and_then(|n| eval(&n, env))
        //eval(&tokenize(s).unwrap(), env)
    }

    #[test]
    fn symbol_resolving() {
        let mut env = Env::new();

        teval_env("(def foo 5)", &mut env).unwrap();

        assert_eq!(num(0), teval_env("(- foo 5)", &mut env).unwrap());
    }

    #[test]
    fn no_def_func() {
        assert_eq!(teval("3"), teval("((fn (a b) (+ a b)) 1 2)"));
    }

    // #[test]
    // fn first_and_rest() {
    //     assert_eq!(num(0), teval("(first (list 0 1 2))"));
    //     assert_eq!(teval("(list 1 2)"), teval("(rest (list 0 1 2))"));
    // }

    #[test]
    fn simple_func() {
        let mut env = Env::new();
        let _ = eval(&tokenize("(def f (fn (r b) (+ r b)))").unwrap(), &mut env).unwrap();
        let res = eval(&tokenize("(f 2 3)").unwrap(), &mut env).unwrap();

        assert_eq!(num(5), res);
    }

    #[test]
    fn quote_func() {
        assert_eq!(teval("'(1 2)"), teval("(quote (1 2))"));
        assert_eq!(teval("'a"), teval("(quote a)"));
    }

    #[test]
    fn do_func() {
        assert_eq!(teval("4"), teval("(do (+ 1 2) (+ 2 2))"));
    }

    // #[test]
    //  fn simple_macro() {
    //      let mut env = Env::new();
    //      teval_env("(defmacro m () '(+ 3 5))", &mut env).unwrap();
    //      assert_eq!(teval("'(+ 3 5)"), teval_env("(macroexpand '(m))", &mut env).unwrap());

    //      teval_env("(def mm (macro () (+ 3 5)))", &mut env).unwrap();
    //      assert_eq!(teval("8"), teval_env("(macroexpand '(mm))", &mut env).unwrap());

    //      assert_eq!(teval("8"), teval_env("(m)", &mut env).unwrap());
    //      assert_eq!(teval("8"), teval_env("(mm)", &mut env).unwrap());
    //  }

    #[test]
    fn more_complex_macro() {
        let mut env = Env::new();
        teval_env("(defmacro unless (p a b) `(if (not ~p) ~a ~b))", &mut env).unwrap();
        assert_eq!(teval("3"), teval_env("(unless false 3 5)", &mut env).unwrap());
    }
}
<|endoftext|>


<commit_before>use std::{ io, fs, cmp };
use std::ops::Range;
use std::path::Path;
use std::io::SeekFrom;
use futures::{ Future, Stream, Poll, Async };
use tokio_io::AsyncRead;
use tokio_io::io::Window;
use tokio::fs::file::File as TokioFile;
use bytes::BytesMut;
use hyper;
use ::error;

#[cfg(feature = "sendfile")] use tokio::net::TcpStream;
#[cfg(feature = "sendfile")] use std::sync::Arc;
#[cfg(feature = "sendfile")] use futures::sync::BiLock;
#[cfg(feature = "sendfile")] use ::sendfile::SendFileFut;

pub struct File {
    fd: TokioFile,
    chunk_length: usize,
    pub length: u64
}

impl File {
    #[inline]
    pub fn new(fd: TokioFile, chunk_length: usize, length: u64) -> Self {
        File { fd, chunk_length, length }
    }

    pub fn read(self, range: Range<u64>) -> ReadStream {
        let take = range.end - range.start;
        let buf = BytesMut::with_capacity(cmp::min(self.chunk_length, take as _));
        ReadStream { fd: self.fd, range, buf }
    }

    #[cfg(feature = "sendfile")]
    #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
    pub fn sendfile(self, range: Range<u64>, socket: Arc<BiLock<TcpStream>>) -> io::Result<SendFileFut> {
        unsafe fn as_fs_file(t: TokioFile) -> fs::File {
            struct PubTokioFile {
                std: Option<fs::File>
            }

            mem::transmute::<_, PubTokioFile>(t).std.unwrap()
        }

        Ok(SendFileFut {
            socket,
            fd: unsafe { as_fs_file(self.fd) },
            offset: range.start as _,
            end: range.end as _
        })
    }
}

#[inline]
pub fn try_clone(fd: TokioFile) -> TryClone {
    TryClone(fd)
}

pub struct TryClone(TokioFile);

impl Stream for TryClone {
    type Item = TokioFile;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let fd = try_ready!(self.0.poll_try_clone());
        Ok(Async::Ready(Some(fd)))
    }
}

pub struct ReadStream {
    fd: TokioFile,
    range: Range<u64>,
    buf: BytesMut
}

impl Stream for ReadStream {
    type Item = hyper::Result<hyper::Chunk>;
    type Error = error::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let want_len = self.range.end - self.range.start;

        if want_len > 0 {
            try_ready!(self.fd.poll_seek(SeekFrom::Start(self.range.start)));
            let read_len = try_ready!(self.fd.read_buf(&mut self.buf));

            self.range.start += read_len as u64;

            let chunk = self.buf.take().freeze();
            Ok(Async::Ready(Some(Ok(chunk.into()))))
        } else {
            Ok(Async::Ready(None))
        }
    }
}

#[cfg(test)]
mod test {
    extern crate tempdir;

    use std::fs;
    use std::io::Write;
    use futures::{ Future, Stream };
    use self::tempdir::TempDir;
    use super::*;

    #[test]
    fn test_file() {
        let tmp = TempDir::new("webdir_test_file").unwrap();

        {
            fs::File::create(tmp.path().join("test")).unwrap()
                .write_all(&[42; 1024]).unwrap();
        }

        let fd = fs::File::open(tmp.path().join("test")).unwrap();
        let len = fd.metadata().unwrap().len();

        let fd = File::new(fd, len as _, 1 << 16).unwrap();
        let fut = fd.read(32..1021).unwrap()
            .map(|chunk| chunk.unwrap().to_vec())
            .concat2();

        let output = fut.wait().unwrap();

        assert_eq!(output, &[42; 989][..]);
    }
}
<commit_msg>[Fixed] ReadStream loop<commit_after>use std::{ io, fs, cmp };
use std::ops::Range;
use std::path::Path;
use std::io::SeekFrom;
use futures::{ Future, Stream, Poll, Async };
use tokio_io::AsyncRead;
use tokio_io::io::Window;
use tokio::fs::file::File as TokioFile;
use bytes::BytesMut;
use hyper;
use ::error;

#[cfg(feature = "sendfile")] use tokio::net::TcpStream;
#[cfg(feature = "sendfile")] use std::sync::Arc;
#[cfg(feature = "sendfile")] use futures::sync::BiLock;
#[cfg(feature = "sendfile")] use ::sendfile::SendFileFut;

pub struct File {
    fd: TokioFile,
    chunk_length: usize,
    pub length: u64
}

impl File {
    #[inline]
    pub fn new(fd: TokioFile, chunk_length: usize, length: u64) -> Self {
        File { fd, chunk_length, length }
    }

    pub fn read(self, range: Range<u64>) -> ReadStream {
        let take = range.end - range.start;
        let cap = cmp::min(self.chunk_length, take as _);
        let buf = BytesMut::with_capacity(cap);
        ReadStream { fd: self.fd, range, buf, cap }
    }

    #[cfg(feature = "sendfile")]
    #[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
    pub fn sendfile(self, range: Range<u64>, socket: Arc<BiLock<TcpStream>>) -> io::Result<SendFileFut> {
        unsafe fn as_fs_file(t: TokioFile) -> fs::File {
            struct PubTokioFile {
                std: Option<fs::File>
            }

            mem::transmute::<_, PubTokioFile>(t).std.unwrap()
        }

        Ok(SendFileFut {
            socket,
            fd: unsafe { as_fs_file(self.fd) },
            offset: range.start as _,
            end: range.end as _
        })
    }
}

#[inline]
pub fn try_clone(fd: TokioFile) -> TryClone {
    TryClone(fd)
}

pub struct TryClone(TokioFile);

impl Stream for TryClone {
    type Item = TokioFile;
    type Error = io::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let fd = try_ready!(self.0.poll_try_clone());
        Ok(Async::Ready(Some(fd)))
    }
}

pub struct ReadStream {
    fd: TokioFile,
    range: Range<u64>,
    buf: BytesMut,
    cap: usize
}

impl Stream for ReadStream {
    type Item = hyper::Result<hyper::Chunk>;
    type Error = error::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let want_len = cmp::min((self.range.end - self.range.start) as _, self.cap);

        if want_len > 0 {
            self.buf.reserve(want_len);

            try_ready!(self.fd.poll_seek(SeekFrom::Start(self.range.start)));
            let read_len = try_ready!(self.fd.read_buf(&mut self.buf));

            self.range.start += read_len as u64;

            let chunk = self.buf.take().freeze();
            Ok(Async::Ready(Some(Ok(chunk.into()))))
        } else {
            Ok(Async::Ready(None))
        }
    }
}

#[cfg(test)]
mod test {
    extern crate tempdir;

    use std::fs;
    use std::io::Write;
    use futures::{ Future, Stream };
    use self::tempdir::TempDir;
    use super::*;

    #[test]
    fn test_file() {
        let tmp = TempDir::new("webdir_test_file").unwrap();

        {
            fs::File::create(tmp.path().join("test")).unwrap()
                .write_all(&[42; 1024]).unwrap();
        }

        let fd = fs::File::open(tmp.path().join("test")).unwrap();
        let len = fd.metadata().unwrap().len();

        let fd = File::new(fd, len as _, 1 << 16).unwrap();
        let fut = fd.read(32..1021).unwrap()
            .map(|chunk| chunk.unwrap().to_vec())
            .concat2();

        let output = fut.wait().unwrap();

        assert_eq!(output, &[42; 989][..]);
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//================================================
// Macros
//================================================

// link! _________________________________________

#[cfg(feature="runtime")]
macro_rules! link {
    (@LOAD: #[cfg($cfg:meta)] fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        #[cfg($cfg)]
        pub fn $name(library: &mut super::SharedLibrary) {
            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
            library.functions.$name = symbol.map(|s| *s);
        }

        #[cfg(not($cfg))]
        pub fn $name(_: &mut super::SharedLibrary) {}
    );

    (@LOAD: fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        link!(@LOAD: #[cfg(feature="runtime")] fn $name($($pname: $pty), *) $(-> $ret)*);
    );

    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        use std::cell::{RefCell};
        use std::sync::{Arc};

        /// The set of functions loaded dynamically.
        #[derive(Debug)]
        pub struct Functions {
            $($(#[cfg($cfg)])* pub $name: Option<unsafe extern fn($($pname: $pty), *) $(-> $ret)*>,)+
        }

        impl Default for Functions {
            fn default() -> Functions {
                unsafe { std::mem::zeroed() }
            }
        }

        /// A dynamically loaded instance of the `libclang` library.
        #[derive(Debug)]
        pub struct SharedLibrary {
            library: libloading::Library,
            pub functions: Functions,
        }

        impl SharedLibrary {
            //- Constructors -----------------------------

            fn new(library: libloading::Library) -> SharedLibrary {
                SharedLibrary { library: library, functions: Functions::default() }
            }
        }

        thread_local!(static LIBRARY: RefCell<Option<Arc<SharedLibrary>>> = RefCell::new(None));

        /// Returns whether a `libclang` shared library is loaded on this thread.
        pub fn is_loaded() -> bool {
            LIBRARY.with(|l| l.borrow().is_some())
        }

        fn with_library<T, F>(f: F) -> Option<T> where F: FnOnce(&SharedLibrary) -> T {
            LIBRARY.with(|l| {
                match l.borrow().as_ref() {
                    Some(library) => Some(f(&library)),
                    _ => None,
                }
            })
        }

        $(
            #[cfg_attr(feature="clippy", allow(too_many_arguments))]
            $(#[cfg($cfg)])*
            pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
                let f = with_library(|l| {
                    match l.functions.$name {
                        Some(f) => f,
                        _ => panic!(concat!("function not loaded: ", stringify!($name))),
                    }
                }).expect("a `libclang` shared library is not loaded on this thread");
                f($($pname), *)
            }

            $(#[cfg($cfg)])*
            pub mod $name {
                pub fn is_loaded() -> bool {
                    super::with_library(|l| l.functions.$name.is_some()).unwrap_or(false)
                }
            }
        )+

        mod load {
            $(link!(@LOAD: $(#[cfg($cfg)])* fn $name($($pname: $pty), *) $(-> $ret)*);)+
        }

        /// Loads a `libclang` shared library and returns the library instance.
        ///
        /// This function does not attempt to load any functions from the shared library. The caller
        /// is responsible for loading the functions they require.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library could not be found
        /// * the `libclang` shared library could not be opened
        pub fn load_manually() -> Result<SharedLibrary, String> {
            #[path="../build.rs"]
            mod build;

            let file = try!(build::find_shared_library());
            let library = libloading::Library::new(&file).map_err(|_| {
                format!("the `libclang` shared library could not be opened: {}", file.display())
            });
            let mut library = SharedLibrary::new(try!(library));
            $(load::$name(&mut library);)+
            Ok(library)
        }

        /// Loads a `libclang` shared library for use in the current thread.
        ///
        /// This functions attempts to load all the functions in the shared library. Whether a
        /// function has been loaded can be tested by calling the `is_loaded` function on the
        /// module with the same name as the function (e.g., `clang_createIndex::is_loaded()` for
        /// the `clang_createIndex` function).
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library could not be found
        /// * the `libclang` shared library could not be opened
        #[allow(dead_code)]
        pub fn load() -> Result<(), String> {
            let library = Arc::new(try!(load_manually()));
            LIBRARY.with(|l| *l.borrow_mut() = Some(library));
            Ok(())
        }

        /// Unloads the `libclang` shared library in use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library is not in use in the current thread
        pub fn unload() -> Result<(), String> {
            let library = set_library(None);
            if library.is_some() {
                Ok(())
            } else {
                Err("a `libclang` shared library is not in use in the current thread".into())
            }
        }

        /// Returns the library instance stored in TLS.
        ///
        /// This functions allows for sharing library instances between threads.
        pub fn get_library() -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| l.borrow_mut().clone())
        }

        /// Sets the library instance stored in TLS and returns the previous library.
        ///
        /// This functions allows for sharing library instances between threads.
        pub fn set_library(library: Option<Arc<SharedLibrary>>) -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| mem::replace(&mut *l.borrow_mut(), library))
        }
    )
}

#[cfg(not(feature="runtime"))]
macro_rules! link {
    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        extern { $($(#[cfg($cfg)])* pub fn $name($($pname: $pty), *) $(-> $ret)*;)+ }
    )
}
<commit_msg>Create dummy is_loaded function to emulate runtime API (#59)<commit_after>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//================================================
// Macros
//================================================

// link! _________________________________________

#[cfg(feature="runtime")]
macro_rules! link {
    (@LOAD: #[cfg($cfg:meta)] fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        #[cfg($cfg)]
        pub fn $name(library: &mut super::SharedLibrary) {
            let symbol = unsafe { library.library.get(stringify!($name).as_bytes()) }.ok();
            library.functions.$name = symbol.map(|s| *s);
        }

        #[cfg(not($cfg))]
        pub fn $name(_: &mut super::SharedLibrary) {}
    );

    (@LOAD: fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*) => (
        link!(@LOAD: #[cfg(feature="runtime")] fn $name($($pname: $pty), *) $(-> $ret)*);
    );

    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        use std::cell::{RefCell};
        use std::sync::{Arc};

        /// The set of functions loaded dynamically.
        #[derive(Debug)]
        pub struct Functions {
            $($(#[cfg($cfg)])* pub $name: Option<unsafe extern fn($($pname: $pty), *) $(-> $ret)*>,)+
        }

        impl Default for Functions {
            fn default() -> Functions {
                unsafe { std::mem::zeroed() }
            }
        }

        /// A dynamically loaded instance of the `libclang` library.
        #[derive(Debug)]
        pub struct SharedLibrary {
            library: libloading::Library,
            pub functions: Functions,
        }

        impl SharedLibrary {
            //- Constructors -----------------------------

            fn new(library: libloading::Library) -> SharedLibrary {
                SharedLibrary { library: library, functions: Functions::default() }
            }
        }

        thread_local!(static LIBRARY: RefCell<Option<Arc<SharedLibrary>>> = RefCell::new(None));

        /// Returns whether a `libclang` shared library is loaded on this thread.
        pub fn is_loaded() -> bool {
            LIBRARY.with(|l| l.borrow().is_some())
        }

        fn with_library<T, F>(f: F) -> Option<T> where F: FnOnce(&SharedLibrary) -> T {
            LIBRARY.with(|l| {
                match l.borrow().as_ref() {
                    Some(library) => Some(f(&library)),
                    _ => None,
                }
            })
        }

        $(
            #[cfg_attr(feature="clippy", allow(too_many_arguments))]
            $(#[cfg($cfg)])*
            pub unsafe fn $name($($pname: $pty), *) $(-> $ret)* {
                let f = with_library(|l| {
                    match l.functions.$name {
                        Some(f) => f,
                        _ => panic!(concat!("function not loaded: ", stringify!($name))),
                    }
                }).expect("a `libclang` shared library is not loaded on this thread");
                f($($pname), *)
            }

            $(#[cfg($cfg)])*
            pub mod $name {
                pub fn is_loaded() -> bool {
                    super::with_library(|l| l.functions.$name.is_some()).unwrap_or(false)
                }
            }
        )+

        mod load {
            $(link!(@LOAD: $(#[cfg($cfg)])* fn $name($($pname: $pty), *) $(-> $ret)*);)+
        }

        /// Loads a `libclang` shared library and returns the library instance.
        ///
        /// This function does not attempt to load any functions from the shared library. The caller
        /// is responsible for loading the functions they require.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library could not be found
        /// * the `libclang` shared library could not be opened
        pub fn load_manually() -> Result<SharedLibrary, String> {
            #[path="../build.rs"]
            mod build;

            let file = try!(build::find_shared_library());
            let library = libloading::Library::new(&file).map_err(|_| {
                format!("the `libclang` shared library could not be opened: {}", file.display())
            });
            let mut library = SharedLibrary::new(try!(library));
            $(load::$name(&mut library);)+
            Ok(library)
        }

        /// Loads a `libclang` shared library for use in the current thread.
        ///
        /// This functions attempts to load all the functions in the shared library. Whether a
        /// function has been loaded can be tested by calling the `is_loaded` function on the
        /// module with the same name as the function (e.g., `clang_createIndex::is_loaded()` for
        /// the `clang_createIndex` function).
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library could not be found
        /// * the `libclang` shared library could not be opened
        #[allow(dead_code)]
        pub fn load() -> Result<(), String> {
            let library = Arc::new(try!(load_manually()));
            LIBRARY.with(|l| *l.borrow_mut() = Some(library));
            Ok(())
        }

        /// Unloads the `libclang` shared library in use in the current thread.
        ///
        /// # Failures
        ///
        /// * a `libclang` shared library is not in use in the current thread
        pub fn unload() -> Result<(), String> {
            let library = set_library(None);
            if library.is_some() {
                Ok(())
            } else {
                Err("a `libclang` shared library is not in use in the current thread".into())
            }
        }

        /// Returns the library instance stored in TLS.
        ///
        /// This functions allows for sharing library instances between threads.
        pub fn get_library() -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| l.borrow_mut().clone())
        }

        /// Sets the library instance stored in TLS and returns the previous library.
        ///
        /// This functions allows for sharing library instances between threads.
        pub fn set_library(library: Option<Arc<SharedLibrary>>) -> Option<Arc<SharedLibrary>> {
            LIBRARY.with(|l| mem::replace(&mut *l.borrow_mut(), library))
        }
    )
}

#[cfg(not(feature="runtime"))]
macro_rules! link {
    ($($(#[cfg($cfg:meta)])* pub fn $name:ident($($pname:ident: $pty:ty), *) $(-> $ret:ty)*;)+) => (
        extern { $($(#[cfg($cfg)])* pub fn $name($($pname: $pty), *) $(-> $ret)*;)+ }

        $($(#[cfg($cfg)])*
        pub mod $name {
            pub fn is_loaded() -> bool { true }
        })+
    )
}
<|endoftext|>