<commit_before>// library ~ (core/bundler file)

// Copyright (C) ~ Alex Lyon <arcterus@mail.com>
// Copyright (C) ~ Roy Ivy III <rivy.dev@gmail.com>; MIT license

// * feature-gated external crates (re-shared as public internal modules)
#[cfg(feature = "libc")]
pub extern crate libc;
#[cfg(all(feature = "windows-sys", target_os = "windows"))]
pub extern crate windows_sys;

//## internal modules

mod features; // feature-gated code modules
mod macros; // crate macros (macro_rules-type; exported to `crate::...`)
mod mods; // core cross-platform modules
mod parser; // string parsing modules

pub use uucore_procs::*;

// * cross-platform modules
pub use crate::mods::backup_control;
pub use crate::mods::display;
pub use crate::mods::error;
pub use crate::mods::os;
pub use crate::mods::panic;
pub use crate::mods::quoting_style;
pub use crate::mods::ranges;
pub use crate::mods::version_cmp;

// * string parsing modules
pub use crate::parser::parse_glob;
pub use crate::parser::parse_size;
pub use crate::parser::parse_time;

// * feature-gated modules
#[cfg(feature = "encoding")]
pub use crate::features::encoding;
#[cfg(feature = "fs")]
pub use crate::features::fs;
#[cfg(feature = "fsext")]
pub use crate::features::fsext;
#[cfg(feature = "lines")]
pub use crate::features::lines;
#[cfg(feature = "memo")]
pub use crate::features::memo;
#[cfg(feature = "ringbuffer")]
pub use crate::features::ringbuffer;

// * (platform-specific) feature-gated modules
// ** non-windows (i.e. Unix + Fuchsia)
#[cfg(all(not(windows), feature = "mode"))]
pub use crate::features::mode;
// ** unix-only
#[cfg(all(unix, feature = "entries"))]
pub use crate::features::entries;
#[cfg(all(unix, feature = "perms"))]
pub use crate::features::perms;
#[cfg(all(unix, feature = "pipes"))]
pub use crate::features::pipes;
#[cfg(all(unix, feature = "process"))]
pub use crate::features::process;
#[cfg(all(unix, not(target_os = "fuchsia"), feature = "signals"))]
pub use crate::features::signals;
#[cfg(all(
    unix,
    not(target_os = "android"),
    not(target_os = "fuchsia"),
    not(target_os = "redox"),
    not(target_env = "musl"),
    feature = "utmpx"
))]
pub use crate::features::utmpx;
// ** windows-only
#[cfg(all(windows, feature = "wide"))]
pub use crate::features::wide;

//## core functions

use std::ffi::OsString;
use std::sync::atomic::Ordering;

use once_cell::sync::Lazy;

#[macro_export]
macro_rules! bin {
    ($util:ident) => {
        pub fn main() {
            use std::io::Write;
            uucore::panic::mute_sigpipe_panic(); // suppress extraneous error output for SIGPIPE failures/panics
            let code = $util::uumain(uucore::args_os()); // execute utility code
            std::io::stdout().flush().expect("could not flush stdout"); // (defensively) flush stdout for utility prior to exit; see <https://github.com/rust-lang/rust/issues/23818>
            std::process::exit(code);
        }
    };
}

/// Generate the usage string for clap.
///
/// This function replaces all occurrences of `{}` with the execution phrase
/// and returns the resulting `String`. It does **not** support
/// more advanced formatting features such as `{0}`.
pub fn format_usage(s: &str) -> String {
    s.replace("{}", crate::execution_phrase())
}

pub fn get_utility_is_second_arg() -> bool {
    crate::macros::UTILITY_IS_SECOND_ARG.load(Ordering::SeqCst)
}

pub fn set_utility_is_second_arg() {
    crate::macros::UTILITY_IS_SECOND_ARG.store(true, Ordering::SeqCst);
}

// args_os() can be expensive to call, it copies all of argv before iterating.
// So if we want only the first arg or so it's overkill. We cache it.
static ARGV: Lazy<Vec<OsString>> = Lazy::new(|| wild::args_os().collect());

static UTIL_NAME: Lazy<String> = Lazy::new(|| {
    if get_utility_is_second_arg() {
        &ARGV[1]
    } else {
        &ARGV[0]
    }
    .to_string_lossy()
    .into_owned()
});

/// Derive the utility name.
pub fn util_name() -> &'static str {
    &UTIL_NAME
}

static EXECUTION_PHRASE: Lazy<String> = Lazy::new(|| {
    if get_utility_is_second_arg() {
        ARGV.iter()
            .take(2)
            .map(|os_str| os_str.to_string_lossy().into_owned())
            .collect::<Vec<_>>()
            .join(" ")
    } else {
        ARGV[0].to_string_lossy().into_owned()
    }
});

/// Derive the complete execution phrase for "usage".
pub fn execution_phrase() -> &'static str {
    &EXECUTION_PHRASE
}

pub trait Args: Iterator<Item = OsString> + Sized {
    /// Collects the iterator into a `Vec<String>`, lossily converting the `OsString`s to `Strings`.
    fn collect_lossy(self) -> Vec<String> {
        self.map(|s| s.to_string_lossy().into_owned()).collect()
    }

    /// Collects the iterator into a `Vec<String>`, removing any elements that contain invalid encoding.
    fn collect_ignore(self) -> Vec<String> {
        self.filter_map(|s| s.into_string().ok()).collect()
    }
}

impl<T: Iterator<Item = OsString> + Sized> Args for T {}

pub fn args_os() -> impl Iterator<Item = OsString> {
    ARGV.iter().cloned()
}

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

    fn make_os_vec(os_str: &OsStr) -> Vec<OsString> {
        vec![
            OsString::from("test"),
            OsString::from("สวัสดี"), // spell-checker:disable-line
            os_str.to_os_string(),
        ]
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn test_invalid_utf8_args_lossy(os_str: &OsStr) {
        // assert our string is invalid utf8
        assert!(os_str.to_os_string().into_string().is_err());
        let test_vec = make_os_vec(os_str);
        let collected_to_str = test_vec.clone().into_iter().collect_lossy();
        // conservation of length - when accepting lossy conversion no arguments may be dropped
        assert_eq!(collected_to_str.len(), test_vec.len());
        // first indices identical
        for index in 0..2 {
            assert_eq!(collected_to_str[index], test_vec[index].to_str().unwrap());
        }
        // lossy conversion for string with illegal encoding is done
        assert_eq!(
            *collected_to_str[2],
            os_str.to_os_string().to_string_lossy()
        );
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn test_invalid_utf8_args_ignore(os_str: &OsStr) {
        // assert our string is invalid utf8
        assert!(os_str.to_os_string().into_string().is_err());
        let test_vec = make_os_vec(os_str);
        let collected_to_str = test_vec.clone().into_iter().collect_ignore();
        // assert that the broken entry is filtered out
        assert_eq!(collected_to_str.len(), test_vec.len() - 1);
        // assert that the unbroken indices are converted as expected
        for index in 0..2 {
            assert_eq!(
                collected_to_str.get(index).unwrap(),
                test_vec.get(index).unwrap().to_str().unwrap()
            );
        }
    }

    #[test]
    fn valid_utf8_encoding_args() {
        // create a vector containing only correct encoding
        let test_vec = make_os_vec(&OsString::from("test2"));
        // expect complete conversion without losses, even when lossy conversion is accepted
        let _ = test_vec.into_iter().collect_lossy();
    }

    #[cfg(any(unix, target_os = "redox"))]
    #[test]
    fn invalid_utf8_args_unix() {
        use std::os::unix::ffi::OsStrExt;

        let source = [0x66, 0x6f, 0x80, 0x6f];
        let os_str = OsStr::from_bytes(&source[..]);
        test_invalid_utf8_args_lossy(os_str);
        test_invalid_utf8_args_ignore(os_str);
    }
}
<commit_msg>uucore: add prompt_yes!() and read_yes()<commit_after>// library ~ (core/bundler file)

// Copyright (C) ~ Alex Lyon <arcterus@mail.com>
// Copyright (C) ~ Roy Ivy III <rivy.dev@gmail.com>; MIT license

// * feature-gated external crates (re-shared as public internal modules)
#[cfg(feature = "libc")]
pub extern crate libc;
#[cfg(all(feature = "windows-sys", target_os = "windows"))]
pub extern crate windows_sys;

//## internal modules

mod features; // feature-gated code modules
mod macros; // crate macros (macro_rules-type; exported to `crate::...`)
mod mods; // core cross-platform modules
mod parser; // string parsing modules

pub use uucore_procs::*;

// * cross-platform modules
pub use crate::mods::backup_control;
pub use crate::mods::display;
pub use crate::mods::error;
pub use crate::mods::os;
pub use crate::mods::panic;
pub use crate::mods::quoting_style;
pub use crate::mods::ranges;
pub use crate::mods::version_cmp;

// * string parsing modules
pub use crate::parser::parse_glob;
pub use crate::parser::parse_size;
pub use crate::parser::parse_time;

// * feature-gated modules
#[cfg(feature = "encoding")]
pub use crate::features::encoding;
#[cfg(feature = "fs")]
pub use crate::features::fs;
#[cfg(feature = "fsext")]
pub use crate::features::fsext;
#[cfg(feature = "lines")]
pub use crate::features::lines;
#[cfg(feature = "memo")]
pub use crate::features::memo;
#[cfg(feature = "ringbuffer")]
pub use crate::features::ringbuffer;

// * (platform-specific) feature-gated modules
// ** non-windows (i.e. Unix + Fuchsia)
#[cfg(all(not(windows), feature = "mode"))]
pub use crate::features::mode;
// ** unix-only
#[cfg(all(unix, feature = "entries"))]
pub use crate::features::entries;
#[cfg(all(unix, feature = "perms"))]
pub use crate::features::perms;
#[cfg(all(unix, feature = "pipes"))]
pub use crate::features::pipes;
#[cfg(all(unix, feature = "process"))]
pub use crate::features::process;
#[cfg(all(unix, not(target_os = "fuchsia"), feature = "signals"))]
pub use crate::features::signals;
#[cfg(all(
    unix,
    not(target_os = "android"),
    not(target_os = "fuchsia"),
    not(target_os = "redox"),
    not(target_env = "musl"),
    feature = "utmpx"
))]
pub use crate::features::utmpx;
// ** windows-only
#[cfg(all(windows, feature = "wide"))]
pub use crate::features::wide;

//## core functions

use std::ffi::OsString;
use std::sync::atomic::Ordering;

use once_cell::sync::Lazy;

#[macro_export]
macro_rules! bin {
    ($util:ident) => {
        pub fn main() {
            use std::io::Write;
            uucore::panic::mute_sigpipe_panic(); // suppress extraneous error output for SIGPIPE failures/panics
            let code = $util::uumain(uucore::args_os()); // execute utility code
            std::io::stdout().flush().expect("could not flush stdout"); // (defensively) flush stdout for utility prior to exit; see <https://github.com/rust-lang/rust/issues/23818>
            std::process::exit(code);
        }
    };
}

/// Generate the usage string for clap.
///
/// This function replaces all occurrences of `{}` with the execution phrase
/// and returns the resulting `String`. It does **not** support
/// more advanced formatting features such as `{0}`.
pub fn format_usage(s: &str) -> String {
    s.replace("{}", crate::execution_phrase())
}

pub fn get_utility_is_second_arg() -> bool {
    crate::macros::UTILITY_IS_SECOND_ARG.load(Ordering::SeqCst)
}

pub fn set_utility_is_second_arg() {
    crate::macros::UTILITY_IS_SECOND_ARG.store(true, Ordering::SeqCst);
}

// args_os() can be expensive to call, it copies all of argv before iterating.
// So if we want only the first arg or so it's overkill. We cache it.
static ARGV: Lazy<Vec<OsString>> = Lazy::new(|| wild::args_os().collect());

static UTIL_NAME: Lazy<String> = Lazy::new(|| {
    if get_utility_is_second_arg() {
        &ARGV[1]
    } else {
        &ARGV[0]
    }
    .to_string_lossy()
    .into_owned()
});

/// Derive the utility name.
pub fn util_name() -> &'static str {
    &UTIL_NAME
}

static EXECUTION_PHRASE: Lazy<String> = Lazy::new(|| {
    if get_utility_is_second_arg() {
        ARGV.iter()
            .take(2)
            .map(|os_str| os_str.to_string_lossy().into_owned())
            .collect::<Vec<_>>()
            .join(" ")
    } else {
        ARGV[0].to_string_lossy().into_owned()
    }
});

/// Derive the complete execution phrase for "usage".
pub fn execution_phrase() -> &'static str {
    &EXECUTION_PHRASE
}

pub trait Args: Iterator<Item = OsString> + Sized {
    /// Collects the iterator into a `Vec<String>`, lossily converting the `OsString`s to `Strings`.
    fn collect_lossy(self) -> Vec<String> {
        self.map(|s| s.to_string_lossy().into_owned()).collect()
    }

    /// Collects the iterator into a `Vec<String>`, removing any elements that contain invalid encoding.
    fn collect_ignore(self) -> Vec<String> {
        self.filter_map(|s| s.into_string().ok()).collect()
    }
}

impl<T: Iterator<Item = OsString> + Sized> Args for T {}

pub fn args_os() -> impl Iterator<Item = OsString> {
    ARGV.iter().cloned()
}

/// Read a line from stdin and check whether the first character is `'y'` or `'Y'`
pub fn read_yes() -> bool {
    let mut s = String::new();
    match std::io::stdin().read_line(&mut s) {
        Ok(_) => matches!(s.chars().next(), Some('y' | 'Y')),
        _ => false,
    }
}

/// Prompt the user with a formatted string and returns `true` if they reply `'y'` or `'Y'`
///
/// This macro functions accepts the same syntax as `format!`. The prompt is written to
/// `stderr`. A space is also printed at the end for nice spacing between the prompt and
/// the user input. Any input starting with `'y'` or `'Y'` is interpreted as `yes`.
///
/// # Examples
/// ```
/// use uucore::prompt_yes;
/// let file = "foo.rs";
/// prompt_yes!("Do you want to delete '{}'?", file);
/// ```
/// will print something like below to `stderr` (with `util_name` substituted by the actual
/// util name) and will wait for user input.
/// ```txt
/// util_name: Do you want to delete 'foo.rs'?
/// ```
#[macro_export]
macro_rules! prompt_yes(
    ($($args:tt)+) => ({
        use std::io::Write;
        eprint!("{}: ", uucore::util_name());
        eprint!($($args)+);
        eprint!(" ");
        uucore::crash_if_err!(1, std::io::stderr().flush());
        uucore::read_yes()
    })
);

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

    fn make_os_vec(os_str: &OsStr) -> Vec<OsString> {
        vec![
            OsString::from("test"),
            OsString::from("สวัสดี"), // spell-checker:disable-line
            os_str.to_os_string(),
        ]
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn test_invalid_utf8_args_lossy(os_str: &OsStr) {
        // assert our string is invalid utf8
        assert!(os_str.to_os_string().into_string().is_err());
        let test_vec = make_os_vec(os_str);
        let collected_to_str = test_vec.clone().into_iter().collect_lossy();
        // conservation of length - when accepting lossy conversion no arguments may be dropped
        assert_eq!(collected_to_str.len(), test_vec.len());
        // first indices identical
        for index in 0..2 {
            assert_eq!(collected_to_str[index], test_vec[index].to_str().unwrap());
        }
        // lossy conversion for string with illegal encoding is done
        assert_eq!(
            *collected_to_str[2],
            os_str.to_os_string().to_string_lossy()
        );
    }

    #[cfg(any(unix, target_os = "redox"))]
    fn test_invalid_utf8_args_ignore(os_str: &OsStr) {
        // assert our string is invalid utf8
        assert!(os_str.to_os_string().into_string().is_err());
        let test_vec = make_os_vec(os_str);
        let collected_to_str = test_vec.clone().into_iter().collect_ignore();
        // assert that the broken entry is filtered out
        assert_eq!(collected_to_str.len(), test_vec.len() - 1);
        // assert that the unbroken indices are converted as expected
        for index in 0..2 {
            assert_eq!(
                collected_to_str.get(index).unwrap(),
                test_vec.get(index).unwrap().to_str().unwrap()
            );
        }
    }

    #[test]
    fn valid_utf8_encoding_args() {
        // create a vector containing only correct encoding
        let test_vec = make_os_vec(&OsString::from("test2"));
        // expect complete conversion without losses, even when lossy conversion is accepted
        let _ = test_vec.into_iter().collect_lossy();
    }

    #[cfg(any(unix, target_os = "redox"))]
    #[test]
    fn invalid_utf8_args_unix() {
        use std::os::unix::ffi::OsStrExt;

        let source = [0x66, 0x6f, 0x80, 0x6f];
        let os_str = OsStr::from_bytes(&source[..]);
        test_invalid_utf8_args_lossy(os_str);
        test_invalid_utf8_args_ignore(os_str);
    }
}
<|endoftext|>


<commit_before>use error::*;
use ops;

use std::collections::HashMap;
use std::fmt;
// use std::iter;
use std::slice;

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Symbol {
    Add,
    Sub,
    Mul,
    Div,
    Mod,
}

#[cfg_attr(rustfmt, rustfmt_skip)]
impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Symbol::*;
        write!(f, "{}", match *self {
            Add => "+",
            Sub => "-",
            Mul => "*",
            Div => "/",
            Mod => "%",
        })
    }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Arity {
    Nullary,
    Unary,
    Binary,
    Ternary,
    Multiary, // 2+ arguments
}

impl fmt::Display for Arity {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Arity::*;
        let text = match *self {
            Nullary => "0",
            Unary => "1",
            Binary => "2",
            Ternary => "3",
            Multiary => "at least 2",
        };

        write!(f, "{}", text)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Atom {
    Sym(Symbol),
    // Bool(bool),
    Int(i64),
    // Float(f64),
    //Str(String),
}

impl Atom {
    fn kind(&self) -> &str {
        use self::Atom::*;
        match *self {
            Sym(_) => "sym",
            Int(_) => "int",
        }
    }

    pub fn add(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a + b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Add, self.kind(), x.kind()).into()),
        }
    }

    pub fn sub(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a - b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Sub, self.kind(), x.kind()).into()),
        }
    }

    pub fn mul(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a * b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Mul, self.kind(), x.kind()).into()),
        }
    }

    pub fn div(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => {
                if b == 0 {
                    Err("division by zero".into())
                } else {
                    Ok(Int(a / b))
                }
            },
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Div, self.kind(), x.kind()).into()),
        }
    }

    pub fn modulus(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => {
                if b == 0 {
                    Err("modulus by zero".into())
                } else {
                    Ok(Int(a % b))
                }
            },
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Mod, self.kind(), x.kind()).into()),
        }
    }
}

impl fmt::Display for Atom {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Atom::*;
        match *self {
            Sym(ref t) => write!(f, "{}", t),
            // Bool(ref t) => write!(f, "{}", t),
            Int(ref t) => write!(f, "{}", t),
            // Float(ref t) => write!(f, "{}", t),
            // Str(ref t) => write!(f, "{}", t),
        }
    }
}

impl From<Symbol> for Atom {
    fn from(x: Symbol) -> Self {
        Atom::Sym(x)
    }
}

impl From<i64> for Atom {
    fn from(x: i64) -> Self {
        Atom::Int(x)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Atom(Atom),
    List(List),
}

impl Value {
    fn kind(&self) -> &str {
        use self::Value::*;
        match *self {
            Atom(_) => "atom",
            List(_) => "list",
        }
    }

    fn binary<F>(&self, x: &Self, symbol: Symbol, f: F) -> Result<Value>
        where F: Fn(&Atom, &Atom) -> Result<Atom>
    {
        use self::Value::Atom;
        match (self, x) {
            (&Atom(ref a), &Atom(ref b)) => f(a, b).map(Value::from),
            _ => Err(format!("incompatible types for {}: {}, {}",
                symbol, self.kind(), x.kind()).into()),
        }
    }

    pub fn add(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Add, Atom::add)
    }

    pub fn sub(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Sub, Atom::sub)
    }

    pub fn mul(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Mul, Atom::mul)
    }

    pub fn div(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Div, Atom::div)
    }

    pub fn modulus(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Mod, Atom::modulus)
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Value::*;
        match *self {
            Atom(ref t) => write!(f, "{}", t),
            List(ref t) => write!(f, "{}", t),
        }
    }
}

impl<T> From<T> for Value
    where T: Into<Atom>
{
    fn from(v: T) -> Self {
        Value::Atom(v.into())
    }
}

// Unstable feature iter_arith_traits - issue #34529
// Stabilized by Rust 1.12
// impl iter::Sum<Value> for Value {
//     fn sum<I>(iter: I) -> Self where I: Iterator<Item=Value> {
//         iter.fold(0.into(), |acc, x| acc + x)
//     }
// }

// Unstable feature iter_arith_traits - issue #34529
// Stabilized by Rust 1.12
// impl iter::Mul<Value> for Value {
//     fn mul<I>(iter: I) -> Self where I: Iterator<Item=Value> {
//         iter.fold(1.into(), |acc, x| acc * x)
//     }
// }

#[derive(Clone, Debug, PartialEq)]
pub enum Node {
    Atom(Atom),
    List(List),
    Expr(Expr),
}

impl Node {
    pub fn eval(&self) -> Result<Value> {
        use self::Node::*;
        match *self {
            Atom(a) => Ok(Value::Atom(a)),
            List(ref l) => Ok(Value::List(l.clone())),
            Expr(ref e) => e.eval(),
        }
    }
}

impl<T> From<T> for Node
    where T: Into<Atom>
{
    fn from(v: T) -> Self {
        Node::Atom(v.into())
    }
}

// impl<T> From<T> for Node where T: Into<List> {
//     fn from(l: T) -> Self {
//         Node::List(l.into())
//     }
// }
//
// impl<T> From<T> for Node where T: Into<Expr> {
//     fn from(e: T) -> Self {
//         Node::Expr(e.into())
//     }
// }

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Node::*;
        match *self {
            Atom(ref a) => write!(f, "{}", a),
            List(ref l) => write!(f, "{}", l),
            Expr(ref e) => write!(f, "{}", e),
        }
    }
}

#[derive(Clone, Default, Debug, PartialEq)]
pub struct List {
    inner: Vec<Node>,
}

impl List {
    pub fn new() -> Self {
        List::default()
    }
}

impl From<Vec<Node>> for List {
    fn from(v: Vec<Node>) -> Self {
        List { inner: v }
    }
}

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.inner
            .iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "[ {} ]", elements)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Expr {
    sym: Symbol,
    args: Vec<Node>,
}

impl Expr {
    pub fn new(sym: Symbol, args: Vec<Node>) -> Self {
        Expr {
            sym: sym,
            args: args,
        }
    }

    pub fn sym(&self) -> Symbol {
        self.sym
    }

    pub fn args(&self) -> slice::Iter<Node> {
        self.args.iter()
    }

    pub fn num_args(&self) -> usize {
        self.args.len()
    }

    fn check_arity(&self, arity: Arity) -> bool {
        use self::Arity::*;
        let num_args = self.num_args();
        match arity {
            Nullary => num_args == 0,
            Unary => num_args == 1,
            Binary => num_args == 2,
            Ternary => num_args == 3,
            Multiary => num_args >= 2,
        }
    }

    pub fn eval(&self) -> Result<Value> {
        use self::Symbol::*;
        use self::Arity::*;

        // Arity = number of arguments accepted
        let mut arity = HashMap::new();

        arity.insert(Add, Multiary);
        arity.insert(Sub, Binary);
        arity.insert(Mul, Multiary);
        arity.insert(Div, Binary);
        arity.insert(Mod, Binary);

        let sym = self.sym();

        let expected_arity = match arity.get(&sym) {
            Some(e) => e,
            None => return Err(format!("symbol {} has unknown number of arguments", sym).into()),
        };

        // Check if number of arguments match expected number
        if !self.check_arity(*expected_arity) {
            return Err(format!("{} symbol expected {} arguments, but received {}",
                               sym,
                               expected_arity,
                               self.num_args())
                .into());
        }

        let evaled_args: Result<Vec<_>> = self.args().map(Node::eval).collect();

        // Return the first expr that cannot eval correctly
        match evaled_args {
            Err(e) => Err(e),
            Ok(v) => {
                match sym {
                    Add => ops::add(&v),
                    Sub => ops::sub(&v),
                    Mul => ops::mul(&v),
                    Div => ops::div(&v),
                    Mod => ops::modulus(&v),
                }
            }
        }
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.args
            .iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "( {} {} )", self.sym, elements)
    }
}
<commit_msg>Rearrange Node to bottom of atom.rs<commit_after>use error::*;
use ops;

use std::collections::HashMap;
use std::fmt;
// use std::iter;
use std::slice;

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Symbol {
    Add,
    Sub,
    Mul,
    Div,
    Mod,
}

#[cfg_attr(rustfmt, rustfmt_skip)]
impl fmt::Display for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Symbol::*;
        write!(f, "{}", match *self {
            Add => "+",
            Sub => "-",
            Mul => "*",
            Div => "/",
            Mod => "%",
        })
    }
}

#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
pub enum Arity {
    Nullary,
    Unary,
    Binary,
    Ternary,
    Multiary, // 2+ arguments
}

impl fmt::Display for Arity {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Arity::*;
        let text = match *self {
            Nullary => "0",
            Unary => "1",
            Binary => "2",
            Ternary => "3",
            Multiary => "at least 2",
        };

        write!(f, "{}", text)
    }
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Atom {
    Sym(Symbol),
    // Bool(bool),
    Int(i64),
    // Float(f64),
    //Str(String),
}

impl Atom {
    fn kind(&self) -> &str {
        use self::Atom::*;
        match *self {
            Sym(_) => "sym",
            Int(_) => "int",
        }
    }

    pub fn add(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a + b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Add, self.kind(), x.kind()).into()),
        }
    }

    pub fn sub(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a - b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Sub, self.kind(), x.kind()).into()),
        }
    }

    pub fn mul(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => Ok(Int(a * b)),
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Mul, self.kind(), x.kind()).into()),
        }
    }

    pub fn div(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => {
                if b == 0 {
                    Err("division by zero".into())
                } else {
                    Ok(Int(a / b))
                }
            },
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Div, self.kind(), x.kind()).into()),
        }
    }

    pub fn modulus(&self, x: &Self) -> Result<Atom> {
        use self::Atom::*;
        match (self, x) {
            (&Int(a), &Int(b)) => {
                if b == 0 {
                    Err("modulus by zero".into())
                } else {
                    Ok(Int(a % b))
                }
            },
            _ => Err(format!(
                "incompatible types for {}: {}, {}",
                Symbol::Mod, self.kind(), x.kind()).into()),
        }
    }
}

impl fmt::Display for Atom {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Atom::*;
        match *self {
            Sym(ref t) => write!(f, "{}", t),
            // Bool(ref t) => write!(f, "{}", t),
            Int(ref t) => write!(f, "{}", t),
            // Float(ref t) => write!(f, "{}", t),
            // Str(ref t) => write!(f, "{}", t),
        }
    }
}

impl From<Symbol> for Atom {
    fn from(x: Symbol) -> Self {
        Atom::Sym(x)
    }
}

impl From<i64> for Atom {
    fn from(x: i64) -> Self {
        Atom::Int(x)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Atom(Atom),
    List(List),
}

impl Value {
    fn kind(&self) -> &str {
        use self::Value::*;
        match *self {
            Atom(_) => "atom",
            List(_) => "list",
        }
    }

    fn binary<F>(&self, x: &Self, symbol: Symbol, f: F) -> Result<Value>
        where F: Fn(&Atom, &Atom) -> Result<Atom>
    {
        use self::Value::Atom;
        match (self, x) {
            (&Atom(ref a), &Atom(ref b)) => f(a, b).map(Value::from),
            _ => Err(format!("incompatible types for {}: {}, {}",
                symbol, self.kind(), x.kind()).into()),
        }
    }

    pub fn add(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Add, Atom::add)
    }

    pub fn sub(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Sub, Atom::sub)
    }

    pub fn mul(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Mul, Atom::mul)
    }

    pub fn div(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Div, Atom::div)
    }

    pub fn modulus(&self, x: &Value) -> Result<Value> {
        self.binary(x, Symbol::Mod, Atom::modulus)
    }
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Value::*;
        match *self {
            Atom(ref t) => write!(f, "{}", t),
            List(ref t) => write!(f, "{}", t),
        }
    }
}

impl<T> From<T> for Value
    where T: Into<Atom>
{
    fn from(v: T) -> Self {
        Value::Atom(v.into())
    }
}

// Unstable feature iter_arith_traits - issue #34529
// Stabilized by Rust 1.12
// impl iter::Sum<Value> for Value {
//     fn sum<I>(iter: I) -> Self where I: Iterator<Item=Value> {
//         iter.fold(0.into(), |acc, x| acc + x)
//     }
// }

// Unstable feature iter_arith_traits - issue #34529
// Stabilized by Rust 1.12
// impl iter::Mul<Value> for Value {
//     fn mul<I>(iter: I) -> Self where I: Iterator<Item=Value> {
//         iter.fold(1.into(), |acc, x| acc * x)
//     }
// }

#[derive(Clone, Default, Debug, PartialEq)]
pub struct List {
    inner: Vec<Node>,
}

impl List {
    pub fn new() -> Self {
        List::default()
    }
}

impl From<Vec<Node>> for List {
    fn from(v: Vec<Node>) -> Self {
        List { inner: v }
    }
}

impl fmt::Display for List {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.inner
            .iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "[ {} ]", elements)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Expr {
    sym: Symbol,
    args: Vec<Node>,
}

impl Expr {
    pub fn new(sym: Symbol, args: Vec<Node>) -> Self {
        Expr {
            sym: sym,
            args: args,
        }
    }

    pub fn sym(&self) -> Symbol {
        self.sym
    }

    pub fn args(&self) -> slice::Iter<Node> {
        self.args.iter()
    }

    pub fn num_args(&self) -> usize {
        self.args.len()
    }

    fn check_arity(&self, arity: Arity) -> bool {
        use self::Arity::*;
        let num_args = self.num_args();
        match arity {
            Nullary => num_args == 0,
            Unary => num_args == 1,
            Binary => num_args == 2,
            Ternary => num_args == 3,
            Multiary => num_args >= 2,
        }
    }

    pub fn eval(&self) -> Result<Value> {
        use self::Symbol::*;
        use self::Arity::*;

        // Arity = number of arguments accepted
        let mut arity = HashMap::new();

        arity.insert(Add, Multiary);
        arity.insert(Sub, Binary);
        arity.insert(Mul, Multiary);
        arity.insert(Div, Binary);
        arity.insert(Mod, Binary);

        let sym = self.sym();

        let expected_arity = match arity.get(&sym) {
            Some(e) => e,
            None => return Err(format!("symbol {} has unknown number of arguments", sym).into()),
        };

        // Check if number of arguments match expected number
        if !self.check_arity(*expected_arity) {
            return Err(format!("{} symbol expected {} arguments, but received {}",
                               sym,
                               expected_arity,
                               self.num_args())
                .into());
        }

        let evaled_args: Result<Vec<_>> = self.args().map(Node::eval).collect();

        // Return the first expr that cannot eval correctly
        match evaled_args {
            Err(e) => Err(e),
            Ok(v) => {
                match sym {
                    Add => ops::add(&v),
                    Sub => ops::sub(&v),
                    Mul => ops::mul(&v),
                    Div => ops::div(&v),
                    Mod => ops::modulus(&v),
                }
            }
        }
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let elements = self.args
            .iter()
            .map(ToString::to_string)
            .collect::<Vec<_>>()
            .join(" ");
        write!(f, "( {} {} )", self.sym, elements)
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum Node {
    Atom(Atom),
    List(List),
    Expr(Expr),
}

impl Node {
    pub fn eval(&self) -> Result<Value> {
        use self::Node::*;
        match *self {
            Atom(a) => Ok(Value::Atom(a)),
            List(ref l) => Ok(Value::List(l.clone())),
            Expr(ref e) => e.eval(),
        }
    }
}

impl<T> From<T> for Node
    where T: Into<Atom>
{
    fn from(v: T) -> Self {
        Node::Atom(v.into())
    }
}

// impl<T> From<T> for Node where T: Into<List> {
//     fn from(l: T) -> Self {
//         Node::List(l.into())
//     }
// }
//
// impl<T> From<T> for Node where T: Into<Expr> {
//     fn from(e: T) -> Self {
//         Node::Expr(e.into())
//     }
// }

impl fmt::Display for Node {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Node::*;
        match *self {
            Atom(ref a) => write!(f, "{}", a),
            List(ref l) => write!(f, "{}", l),
            Expr(ref e) => write!(f, "{}", e),
        }
    }
}

<|endoftext|>


<commit_before>use bytes::{Bytes, BytesMut};
use futures::Stream;
use std::sync::Arc;
use std::{fmt, mem};

use context::ActorHttpContext;
use error::Error;
use handler::Responder;
use httprequest::HttpRequest;
use httpresponse::HttpResponse;

/// Type represent streaming body
pub type BodyStream = Box<Stream<Item = Bytes, Error = Error>>;

/// Represents various types of http message body.
pub enum Body {
    /// Empty response. `Content-Length` header is set to `0`
    Empty,
    /// Specific response body.
    Binary(Binary),
    /// Unspecified streaming response. Developer is responsible for setting
    /// right `Content-Length` or `Transfer-Encoding` headers.
    Streaming(BodyStream),
    /// Special body type for actor response.
    Actor(Box<ActorHttpContext>),
}

/// Represents various types of binary body.
/// `Content-Length` header is set to length of the body.
#[derive(Debug, PartialEq)]
pub enum Binary {
    /// Bytes body
    Bytes(Bytes),
    /// Static slice
    Slice(&'static [u8]),
    /// Shared string body
    #[doc(hidden)]
    SharedString(Arc<String>),
    /// Shared vec body
    SharedVec(Arc<Vec<u8>>),
}

impl Body {
    /// Does this body streaming.
    #[inline]
    pub fn is_streaming(&self) -> bool {
        match *self {
            Body::Streaming(_) | Body::Actor(_) => true,
            _ => false,
        }
    }

    /// Is this binary body.
    #[inline]
    pub fn is_binary(&self) -> bool {
        match *self {
            Body::Binary(_) => true,
            _ => false,
        }
    }

    /// Is this binary empy.
    #[inline]
    pub fn is_empty(&self) -> bool {
        match *self {
            Body::Empty => true,
            _ => false,
        }
    }

    /// Create body from slice (copy)
    pub fn from_slice(s: &[u8]) -> Body {
        Body::Binary(Binary::Bytes(Bytes::from(s)))
    }

    /// Is this binary body.
    #[inline]
    pub(crate) fn binary(self) -> Binary {
        match self {
            Body::Binary(b) => b,
            _ => panic!(),
        }
    }
}

impl PartialEq for Body {
    fn eq(&self, other: &Body) -> bool {
        match *self {
            Body::Empty => match *other {
                Body::Empty => true,
                _ => false,
            },
            Body::Binary(ref b) => match *other {
                Body::Binary(ref b2) => b == b2,
                _ => false,
            },
            Body::Streaming(_) | Body::Actor(_) => false,
        }
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Body::Empty => write!(f, "Body::Empty"),
            Body::Binary(ref b) => write!(f, "Body::Binary({:?})", b),
            Body::Streaming(_) => write!(f, "Body::Streaming(_)"),
            Body::Actor(_) => write!(f, "Body::Actor(_)"),
        }
    }
}

impl<T> From<T> for Body
where
    T: Into<Binary>,
{
    fn from(b: T) -> Body {
        Body::Binary(b.into())
    }
}

impl From<Box<ActorHttpContext>> for Body {
    fn from(ctx: Box<ActorHttpContext>) -> Body {
        Body::Actor(ctx)
    }
}

impl Binary {
    #[inline]
    /// Returns `true` if body is empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    #[inline]
    /// Length of body in bytes
    pub fn len(&self) -> usize {
        match *self {
            Binary::Bytes(ref bytes) => bytes.len(),
            Binary::Slice(slice) => slice.len(),
            Binary::SharedString(ref s) => s.len(),
            Binary::SharedVec(ref s) => s.len(),
        }
    }

    /// Create binary body from slice
    pub fn from_slice(s: &[u8]) -> Binary {
        Binary::Bytes(Bytes::from(s))
    }

    /// Convert Binary to a Bytes instance
    pub fn take(&mut self) -> Bytes {
        mem::replace(self, Binary::Slice(b"")).into()
    }
}

impl Clone for Binary {
    fn clone(&self) -> Binary {
        match *self {
            Binary::Bytes(ref bytes) => Binary::Bytes(bytes.clone()),
            Binary::Slice(slice) => Binary::Bytes(Bytes::from(slice)),
            Binary::SharedString(ref s) => Binary::SharedString(s.clone()),
            Binary::SharedVec(ref s) => Binary::SharedVec(s.clone()),
        }
    }
}

impl Into<Bytes> for Binary {
    fn into(self) -> Bytes {
        match self {
            Binary::Bytes(bytes) => bytes,
            Binary::Slice(slice) => Bytes::from(slice),
            Binary::SharedString(s) => Bytes::from(s.as_str()),
            Binary::SharedVec(s) => Bytes::from(AsRef::<[u8]>::as_ref(s.as_ref())),
        }
    }
}

impl From<&'static str> for Binary {
    fn from(s: &'static str) -> Binary {
        Binary::Slice(s.as_ref())
    }
}

impl From<&'static [u8]> for Binary {
    fn from(s: &'static [u8]) -> Binary {
        Binary::Slice(s)
    }
}

impl From<Vec<u8>> for Binary {
    fn from(vec: Vec<u8>) -> Binary {
        Binary::Bytes(Bytes::from(vec))
    }
}

impl From<String> for Binary {
    fn from(s: String) -> Binary {
        Binary::Bytes(Bytes::from(s))
    }
}

impl<'a> From<&'a String> for Binary {
    fn from(s: &'a String) -> Binary {
        Binary::Bytes(Bytes::from(AsRef::<[u8]>::as_ref(&s)))
    }
}

impl From<Bytes> for Binary {
    fn from(s: Bytes) -> Binary {
        Binary::Bytes(s)
    }
}

impl From<BytesMut> for Binary {
    fn from(s: BytesMut) -> Binary {
        Binary::Bytes(s.freeze())
    }
}

impl From<Arc<String>> for Binary {
    fn from(body: Arc<String>) -> Binary {
        Binary::SharedString(body)
    }
}

impl<'a> From<&'a Arc<String>> for Binary {
    fn from(body: &'a Arc<String>) -> Binary {
        Binary::SharedString(Arc::clone(body))
    }
}

impl From<Arc<Vec<u8>>> for Binary {
    fn from(body: Arc<Vec<u8>>) -> Binary {
        Binary::SharedVec(body)
    }
}

impl<'a> From<&'a Arc<Vec<u8>>> for Binary {
    fn from(body: &'a Arc<Vec<u8>>) -> Binary {
        Binary::SharedVec(Arc::clone(body))
    }
}

impl AsRef<[u8]> for Binary {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        match *self {
            Binary::Bytes(ref bytes) => bytes.as_ref(),
            Binary::Slice(slice) => slice,
            Binary::SharedString(ref s) => s.as_bytes(),
            Binary::SharedVec(ref s) => s.as_ref().as_ref(),
        }
    }
}

impl Responder for Binary {
    type Item = HttpResponse;
    type Error = Error;

    fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
        Ok(HttpResponse::build_from(req)
            .content_type("application/octet-stream")
            .body(self))
    }
}

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

    #[test]
    fn test_body_is_streaming() {
        assert_eq!(Body::Empty.is_streaming(), false);
        assert_eq!(Body::Binary(Binary::from("")).is_streaming(), false);
    }

    #[test]
    fn test_is_empty() {
        assert_eq!(Binary::from("").is_empty(), true);
        assert_eq!(Binary::from("test").is_empty(), false);
    }

    #[test]
    fn test_static_str() {
        assert_eq!(Binary::from("test").len(), 4);
        assert_eq!(Binary::from("test").as_ref(), b"test");
    }

    #[test]
    fn test_static_bytes() {
        assert_eq!(Binary::from(b"test".as_ref()).len(), 4);
        assert_eq!(Binary::from(b"test".as_ref()).as_ref(), b"test");
        assert_eq!(Binary::from_slice(b"test".as_ref()).len(), 4);
        assert_eq!(Binary::from_slice(b"test".as_ref()).as_ref(), b"test");
    }

    #[test]
    fn test_vec() {
        assert_eq!(Binary::from(Vec::from("test")).len(), 4);
        assert_eq!(Binary::from(Vec::from("test")).as_ref(), b"test");
    }

    #[test]
    fn test_bytes() {
        assert_eq!(Binary::from(Bytes::from("test")).len(), 4);
        assert_eq!(Binary::from(Bytes::from("test")).as_ref(), b"test");
    }

    #[test]
    fn test_arc_string() {
        let b = Arc::new("test".to_owned());
        assert_eq!(Binary::from(b.clone()).len(), 4);
        assert_eq!(Binary::from(b.clone()).as_ref(), b"test");
        assert_eq!(Binary::from(&b).len(), 4);
        assert_eq!(Binary::from(&b).as_ref(), b"test");
    }

    #[test]
    fn test_string() {
        let b = "test".to_owned();
        assert_eq!(Binary::from(b.clone()).len(), 4);
        assert_eq!(Binary::from(b.clone()).as_ref(), b"test");
        assert_eq!(Binary::from(&b).len(), 4);
        assert_eq!(Binary::from(&b).as_ref(), b"test");
    }

    #[test]
    fn test_shared_vec() {
        let b = Arc::new(Vec::from(&b"test"[..]));
        assert_eq!(Binary::from(b.clone()).len(), 4);
        assert_eq!(Binary::from(b.clone()).as_ref(), &b"test"[..]);
        assert_eq!(Binary::from(&b).len(), 4);
        assert_eq!(Binary::from(&b).as_ref(), &b"test"[..]);
    }

    #[test]
    fn test_bytes_mut() {
        let b = BytesMut::from("test");
        assert_eq!(Binary::from(b.clone()).len(), 4);
        assert_eq!(Binary::from(b).as_ref(), b"test");
    }

    #[test]
    fn test_binary_into() {
        let bytes = Bytes::from_static(b"test");
        let b: Bytes = Binary::from("test").into();
        assert_eq!(b, bytes);
        let b: Bytes = Binary::from(bytes.clone()).into();
        assert_eq!(b, bytes);
    }
}
<commit_msg>impl `From<Cow<'static, [u8]>>` for `Binary` (#611)<commit_after>use bytes::{Bytes, BytesMut};
use futures::Stream;
use std::borrow::Cow;
use std::sync::Arc;
use std::{fmt, mem};

use context::ActorHttpContext;
use error::Error;
use handler::Responder;
use httprequest::HttpRequest;
use httpresponse::HttpResponse;

/// Type represent streaming body
pub type BodyStream = Box<Stream<Item = Bytes, Error = Error>>;

/// Represents various types of http message body.
pub enum Body {
    /// Empty response. `Content-Length` header is set to `0`
    Empty,
    /// Specific response body.
    Binary(Binary),
    /// Unspecified streaming response. Developer is responsible for setting
    /// right `Content-Length` or `Transfer-Encoding` headers.
    Streaming(BodyStream),
    /// Special body type for actor response.
    Actor(Box<ActorHttpContext>),
}

/// Represents various types of binary body.
/// `Content-Length` header is set to length of the body.
#[derive(Debug, PartialEq)]
pub enum Binary {
    /// Bytes body
    Bytes(Bytes),
    /// Static slice
    Slice(&'static [u8]),
    /// Shared string body
    #[doc(hidden)]
    SharedString(Arc<String>),
    /// Shared vec body
    SharedVec(Arc<Vec<u8>>),
}

impl Body {
    /// Does this body streaming.
    #[inline]
    pub fn is_streaming(&self) -> bool {
        match *self {
            Body::Streaming(_) | Body::Actor(_) => true,
            _ => false,
        }
    }

    /// Is this binary body.
    #[inline]
    pub fn is_binary(&self) -> bool {
        match *self {
            Body::Binary(_) => true,
            _ => false,
        }
    }

    /// Is this binary empy.
    #[inline]
    pub fn is_empty(&self) -> bool {
        match *self {
            Body::Empty => true,
            _ => false,
        }
    }

    /// Create body from slice (copy)
    pub fn from_slice(s: &[u8]) -> Body {
        Body::Binary(Binary::Bytes(Bytes::from(s)))
    }

    /// Is this binary body.
    #[inline]
    pub(crate) fn binary(self) -> Binary {
        match self {
            Body::Binary(b) => b,
            _ => panic!(),
        }
    }
}

impl PartialEq for Body {
    fn eq(&self, other: &Body) -> bool {
        match *self {
            Body::Empty => match *other {
                Body::Empty => true,
                _ => false,
            },
            Body::Binary(ref b) => match *other {
                Body::Binary(ref b2) => b == b2,
                _ => false,
            },
            Body::Streaming(_) | Body::Actor(_) => false,
        }
    }
}

impl fmt::Debug for Body {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Body::Empty => write!(f, "Body::Empty"),
            Body::Binary(ref b) => write!(f, "Body::Binary({:?})", b),
            Body::Streaming(_) => write!(f, "Body::Streaming(_)"),
            Body::Actor(_) => write!(f, "Body::Actor(_)"),
        }
    }
}

impl<T> From<T> for Body
where
    T: Into<Binary>,
{
    fn from(b: T) -> Body {
        Body::Binary(b.into())
    }
}

impl From<Box<ActorHttpContext>> for Body {
    fn from(ctx: Box<ActorHttpContext>) -> Body {
        Body::Actor(ctx)
    }
}

impl Binary {
    #[inline]
    /// Returns `true` if body is empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    #[inline]
    /// Length of body in bytes
    pub fn len(&self) -> usize {
        match *self {
            Binary::Bytes(ref bytes) => bytes.len(),
            Binary::Slice(slice) => slice.len(),
            Binary::SharedString(ref s) => s.len(),
            Binary::SharedVec(ref s) => s.len(),
        }
    }

    /// Create binary body from slice
    pub fn from_slice(s: &[u8]) -> Binary {
        Binary::Bytes(Bytes::from(s))
    }

    /// Convert Binary to a Bytes instance
    pub fn take(&mut self) -> Bytes {
        mem::replace(self, Binary::Slice(b"")).into()
    }
}

impl Clone for Binary {
    fn clone(&self) -> Binary {
        match *self {
            Binary::Bytes(ref bytes) => Binary::Bytes(bytes.clone()),
            Binary::Slice(slice) => Binary::Bytes(Bytes::from(slice)),
            Binary::SharedString(ref s) => Binary::SharedString(s.clone()),
            Binary::SharedVec(ref s) => Binary::SharedVec(s.clone()),
        }
    }
}

impl Into<Bytes> for Binary {
    fn into(self) -> Bytes {
        match self {
            Binary::Bytes(bytes) => bytes,
            Binary::Slice(slice) => Bytes::from(slice),
            Binary::SharedString(s) => Bytes::from(s.as_str()),
            Binary::SharedVec(s) => Bytes::from(AsRef::<[u8]>::as_ref(s.as_ref())),
        }
    }
}

impl From<&'static str> for Binary {
    fn from(s: &'static str) -> Binary {
        Binary::Slice(s.as_ref())
    }
}

impl From<&'static [u8]> for Binary {
    fn from(s: &'static [u8]) -> Binary {
        Binary::Slice(s)
    }
}

impl From<Vec<u8>> for Binary {
    fn from(vec: Vec<u8>) -> Binary {
        Binary::Bytes(Bytes::from(vec))
    }
}

impl From<Cow<'static, [u8]>> for Binary {
    fn from(b: Cow<'static, [u8]>) -> Binary {
        match b {
            Cow::Borrowed(s) => Binary::Slice(s),
            Cow::Owned(vec) => Binary::Bytes(Bytes::from(vec)),
        }
    }
}

impl From<String> for Binary {
    fn from(s: String) -> Binary {
        Binary::Bytes(Bytes::from(s))
    }
}

impl From<Cow<'static, str>> for Binary {
    fn from(s: Cow<'static, str>) -> Binary {
        match s {
            Cow::Borrowed(s) => Binary::Slice(s.as_ref()),
            Cow::Owned(s) => Binary::Bytes(Bytes::from(s)),
        }
    }
}

impl<'a> From<&'a String> for Binary {
    fn from(s: &'a String) -> Binary {
        Binary::Bytes(Bytes::from(AsRef::<[u8]>::as_ref(&s)))
    }
}

impl From<Bytes> for Binary {
    fn from(s: Bytes) -> Binary {
        Binary::Bytes(s)
    }
}

impl From<BytesMut> for Binary {
    fn from(s: BytesMut) -> Binary {
        Binary::Bytes(s.freeze())
    }
}

impl From<Arc<String>> for Binary {
    fn from(body: Arc<String>) -> Binary {
        Binary::SharedString(body)
    }
}

impl<'a> From<&'a Arc<String>> for Binary {
    fn from(body: &'a Arc<String>) -> Binary {
        Binary::SharedString(Arc::clone(body))
    }
}

impl From<Arc<Vec<u8>>> for Binary {
    fn from(body: Arc<Vec<u8>>) -> Binary {
        Binary::SharedVec(body)
    }
}

impl<'a> From<&'a Arc<Vec<u8>>> for Binary {
    fn from(body: &'a Arc<Vec<u8>>) -> Binary {
        Binary::SharedVec(Arc::clone(body))
    }
}

impl AsRef<[u8]> for Binary {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        match *self {
            Binary::Bytes(ref bytes) => bytes.as_ref(),
            Binary::Slice(slice) => slice,
            Binary::SharedString(ref s) => s.as_bytes(),
            Binary::SharedVec(ref s) => s.as_ref().as_ref(),
        }
    }
}

impl Responder for Binary {
    type Item = HttpResponse;
    type Error = Error;

    fn respond_to<S>(self, req: &HttpRequest<S>) -> Result<HttpResponse, Error> {
        Ok(HttpResponse::build_from(req)
            .content_type("application/octet-stream")
            .body(self))
    }
}

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

    #[test]
    fn test_body_is_streaming() {
        assert_eq!(Body::Empty.is_streaming(), false);
        assert_eq!(Body::Binary(Binary::from("")).is_streaming(), false);
    }

    #[test]
    fn test_is_empty() {
        assert_eq!(Binary::from("").is_empty(), true);
        assert_eq!(Binary::from("test").is_empty(), false);
    }

    #[test]
    fn test_static_str() {
        assert_eq!(Binary::from("test").len(), 4);
        assert_eq!(Binary::from("test").as_ref(), b"test");
    }

    #[test]
    fn test_cow_str() {
        let cow: Cow<'static, str> = Cow::Borrowed("test");
        assert_eq!(Binary::from(cow.clone()).len(), 4);
        assert_eq!(Binary::from(cow.clone()).as_ref(), b"test");
        let cow: Cow<'static, str> = Cow::Owned("test".to_owned());
        assert_eq!(Binary::from(cow.clone()).len(), 4);
        assert_eq!(Binary::from(cow.clone()).as_ref(), b"test");
    }

    #[test]
    fn test_static_bytes() {
        assert_eq!(Binary::from(b"test".as_ref()).len(), 4);
        assert_eq!(Binary::from(b"test".as_ref()).as_ref(), b"test");
        assert_eq!(Binary::from_slice(b"test".as_ref()).len(), 4);
        assert_eq!(Binary::from_slice(b"test".as_ref()).as_ref(), b"test");
    }

    #[test]
    fn test_vec() {
        assert_eq!(Binary::from(Vec::from("test")).len(), 4);
        assert_eq!(Binary::from(Vec::from("test")).as_ref(), b"test");
    }

    #[test]
    fn test_bytes() {
        assert_eq!(Binary::from(Bytes::from("test")).len(), 4);
        assert_eq!(Binary::from(Bytes::from("test")).as_ref(), b"test");
    }

    #[test]
    fn test_cow_bytes() {
        let cow: Cow<'static, [u8]> = Cow::Borrowed(b"test");
        assert_eq!(Binary::from(cow.clone()).len(), 4);
        assert_eq!(Binary::from(cow.clone()).as_ref(), b"test");
        let cow: Cow<'static, [u8]> = Cow::Owned(Vec::from("test"));
        assert_eq!(Binary::from(cow.clone()).len(), 4);
        assert_eq!(Binary::from(cow.clone()).as_ref(), b"test");
    }

    #[test]
    fn test_arc_string() {
        let b = Arc::new("test".to_owned());
        assert_eq!(Binary::from(b.clone()).len(), 4);
        assert_eq!(Binary::from(b.clone()).as_ref(), b"test");
        assert_eq!(Binary::from(&b).len(), 4);
        assert_eq!(Binary::from(&b).as_ref(), b"test");
    }

    #[test]
    fn test_string() {
        let b = "test".to_owned();
        assert_eq!(Binary::from(b.clone()).len(), 4);
        assert_eq!(Binary::from(b.clone()).as_ref(), b"test");
        assert_eq!(Binary::from(&b).len(), 4);
        assert_eq!(Binary::from(&b).as_ref(), b"test");
    }

    #[test]
    fn test_shared_vec() {
        let b = Arc::new(Vec::from(&b"test"[..]));
        assert_eq!(Binary::from(b.clone()).len(), 4);
        assert_eq!(Binary::from(b.clone()).as_ref(), &b"test"[..]);
        assert_eq!(Binary::from(&b).len(), 4);
        assert_eq!(Binary::from(&b).as_ref(), &b"test"[..]);
    }

    #[test]
    fn test_bytes_mut() {
        let b = BytesMut::from("test");
        assert_eq!(Binary::from(b.clone()).len(), 4);
        assert_eq!(Binary::from(b).as_ref(), b"test");
    }

    #[test]
    fn test_binary_into() {
        let bytes = Bytes::from_static(b"test");
        let b: Bytes = Binary::from("test").into();
        assert_eq!(b, bytes);
        let b: Bytes = Binary::from(bytes.clone()).into();
        assert_eq!(b, bytes);
    }
}
<|endoftext|>


<commit_before>
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver, SendError};

use std::thread;

use serial;
use serial::prelude::*;
use std::io::{Read, Write};

use std::collections::HashMap;

use std::sync::Mutex;

type MsgAndResponseChannel = (String, Sender<String>);

pub struct CommState(Mutex<CommChannelTx>);

impl CommState {
    pub fn get_comm_channel(&self) -> CommChannelTx {
        let comm = self.0.lock().expect("mutex poisoned");
        comm.clone()
    }
}

#[derive(Clone)]
pub struct CommChannelTx(Sender<MsgAndResponseChannel>);

impl CommChannelTx {
    pub fn send(&self, msg: String) -> Result<Receiver<String>, SendError<MsgAndResponseChannel>> {
        let (response_tx, response_rx) = mpsc::channel();

        self.0.send((msg, response_tx))?;

        Ok(response_rx)
    }
}

fn calc_checksum(input: &str) -> u8 {
    input.as_bytes().into_iter().fold(0, |csum, ch| csum ^ ch)
}

fn process_incoming_msg(raw_msg: &str) -> Result<(u64, &str), ()> {
    if raw_msg.len() < 4 {
        return Err(());
    }

    if raw_msg.as_bytes()[raw_msg.len() - 3] as char != '*' {
        return Err(());
    }

    let packet_csum = u8::from_str_radix(&raw_msg[(raw_msg.len() - 2)..], 16).unwrap();

    let msg_str = &raw_msg[..(raw_msg.len() - 3)];
    let calc_csum = calc_checksum(msg_str);

    if packet_csum != calc_csum {
        return Err(());
    }

    let comma_pos = msg_str.find(',').ok_or(())?;
    let transaction_id = msg_str[..comma_pos].parse().map_err(|_| ())?;
    let msg_payload_str = &msg_str[(comma_pos + 1)..];

    Ok((transaction_id, msg_payload_str))
}

fn comm_func<T>(channel_rx: Receiver<MsgAndResponseChannel>, mut comm: T) -> !
    where T: Read + Write
{
    let mut transaction_id_ctr: u64 = 0;
    let mut pending_transactions = HashMap::new();

    let mut current_packet = String::new();

    enum ParserState {
        WaitingForDollar,
        Receiving,
    }

    let mut current_state = ParserState::WaitingForDollar;

    loop {
        // Transmit all pending messages
        while let Ok((msg, resp_tx)) = channel_rx.try_recv() {
            transaction_id_ctr = transaction_id_ctr.wrapping_add(1);

            pending_transactions.insert(transaction_id_ctr, resp_tx);

            let mut out = format!("${},{}*", transaction_id_ctr, msg);
            let csum = calc_checksum(&out[1..(out.len() - 1)]);
            out.push_str(&format!("{:02X}\r\n", csum));

            debug!("server -> mcu: '{}'", &out[..(out.len() - 2)]);

            let _ = comm.write_all(out.as_bytes());
        }

        // Parse all incoming chars
        let mut incoming = [0; 100];
        while let Ok(incoming_len) = comm.read(&mut incoming) {

            debug!("Rx buffer is now: {:?}", incoming.to_vec());

            for i in 0..incoming_len {
                let ch = incoming[i] as char;

                match current_state {
                    ParserState::WaitingForDollar => {
                        if ch == '$' {
                            current_state = ParserState::Receiving;
                        }
                    }
                    ParserState::Receiving => {
                        current_packet.push(ch);

                        let len = current_packet.len();
                        if len >= 2 && &current_packet[(len - 2)..] == "\r\n" {

                            match process_incoming_msg(&current_packet[..(len - 2)]) {
                                Ok((trans_id, payload_str)) => {
                                    debug!("Received trans id {}, payload {}",
                                           trans_id,
                                           payload_str);

                                    if let Some(response_channel) =
                                        pending_transactions.remove(&trans_id) {
                                        let _ = response_channel.send(payload_str.to_string());
                                    } else {
                                        warn!("Unexpected transition id {}!", trans_id);
                                    }
                                }
                                Err(e) => warn!("{:?}", e),
                            }

                            current_packet.clear();
                            current_state = ParserState::WaitingForDollar;
                        }
                    }
                }
            }
        }
    }
}

pub fn init() -> (CommState, thread::JoinHandle<()>) {
    let mut serial_port = serial::open("/dev/ttyUSB0").expect("Could not open serial port.");

    let settings = serial::PortSettings {
        baud_rate: serial::Baud115200,
        char_size: serial::Bits8,
        parity: serial::ParityNone,
        stop_bits: serial::Stop1,
        flow_control: serial::FlowNone,
    };
    serial_port.configure(&settings).expect("Could not configure the serial port.");

    let (channel_tx, channel_rx) = mpsc::channel();

    let join_handle = thread::spawn(|| comm_func(channel_rx, serial_port));

    (CommState(Mutex::new(CommChannelTx(channel_tx))), join_handle)
}
<commit_msg>Improved warning message on RX parsing error<commit_after>
use std::sync::mpsc;
use std::sync::mpsc::{Sender, Receiver, SendError};

use std::thread;

use serial;
use serial::prelude::*;
use std::io::{Read, Write};

use std::collections::HashMap;

use std::sync::Mutex;

type MsgAndResponseChannel = (String, Sender<String>);

pub struct CommState(Mutex<CommChannelTx>);

impl CommState {
    pub fn get_comm_channel(&self) -> CommChannelTx {
        let comm = self.0.lock().expect("mutex poisoned");
        comm.clone()
    }
}

#[derive(Clone)]
pub struct CommChannelTx(Sender<MsgAndResponseChannel>);

impl CommChannelTx {
    pub fn send(&self, msg: String) -> Result<Receiver<String>, SendError<MsgAndResponseChannel>> {
        let (response_tx, response_rx) = mpsc::channel();

        self.0.send((msg, response_tx))?;

        Ok(response_rx)
    }
}

fn calc_checksum(input: &str) -> u8 {
    input.as_bytes().into_iter().fold(0, |csum, ch| csum ^ ch)
}

fn process_incoming_msg(raw_msg: &str) -> Result<(u64, &str), ()> {
    if raw_msg.len() < 4 {
        return Err(());
    }

    if raw_msg.as_bytes()[raw_msg.len() - 3] as char != '*' {
        return Err(());
    }

    let packet_csum = u8::from_str_radix(&raw_msg[(raw_msg.len() - 2)..], 16).unwrap();

    let msg_str = &raw_msg[..(raw_msg.len() - 3)];
    let calc_csum = calc_checksum(msg_str);

    if packet_csum != calc_csum {
        return Err(());
    }

    let comma_pos = msg_str.find(',').ok_or(())?;
    let transaction_id = msg_str[..comma_pos].parse().map_err(|_| ())?;
    let msg_payload_str = &msg_str[(comma_pos + 1)..];

    Ok((transaction_id, msg_payload_str))
}

fn comm_func<T>(channel_rx: Receiver<MsgAndResponseChannel>, mut comm: T) -> !
    where T: Read + Write
{
    let mut transaction_id_ctr: u64 = 0;
    let mut pending_transactions = HashMap::new();

    let mut current_packet = String::new();

    enum ParserState {
        WaitingForDollar,
        Receiving,
    }

    let mut current_state = ParserState::WaitingForDollar;

    loop {
        // Transmit all pending messages
        while let Ok((msg, resp_tx)) = channel_rx.try_recv() {
            transaction_id_ctr = transaction_id_ctr.wrapping_add(1);

            pending_transactions.insert(transaction_id_ctr, resp_tx);

            let mut out = format!("${},{}*", transaction_id_ctr, msg);
            let csum = calc_checksum(&out[1..(out.len() - 1)]);
            out.push_str(&format!("{:02X}\r\n", csum));

            debug!("server -> mcu: '{}'", &out[..(out.len() - 2)]);

            let _ = comm.write_all(out.as_bytes());
        }

        // Parse all incoming chars
        let mut incoming = [0; 100];
        while let Ok(incoming_len) = comm.read(&mut incoming) {

            debug!("Rx buffer is now: {:?}", incoming.to_vec());

            for i in 0..incoming_len {
                let ch = incoming[i] as char;

                match current_state {
                    ParserState::WaitingForDollar => {
                        if ch == '$' {
                            current_state = ParserState::Receiving;
                        }
                    }
                    ParserState::Receiving => {
                        current_packet.push(ch);

                        let len = current_packet.len();
                        if len >= 2 && &current_packet[(len - 2)..] == "\r\n" {

                            match process_incoming_msg(&current_packet[..(len - 2)]) {
                                Ok((trans_id, payload_str)) => {
                                    debug!("Received trans id {}, payload {}",
                                           trans_id,
                                           payload_str);

                                    if let Some(response_channel) =
                                        pending_transactions.remove(&trans_id) {
                                        let _ = response_channel.send(payload_str.to_string());
                                    } else {
                                        warn!("Unexpected transition id {}!", trans_id);
                                    }
                                }
                                Err(_) => warn!("Unexpected response: '{}'", &current_packet[..(len - 2)]),
                            }

                            current_packet.clear();
                            current_state = ParserState::WaitingForDollar;
                        }
                    }
                }
            }
        }
    }
}

pub fn init() -> (CommState, thread::JoinHandle<()>) {
    let mut serial_port = serial::open("/dev/ttyUSB0").expect("Could not open serial port.");

    let settings = serial::PortSettings {
        baud_rate: serial::Baud115200,
        char_size: serial::Bits8,
        parity: serial::ParityNone,
        stop_bits: serial::Stop1,
        flow_control: serial::FlowNone,
    };
    serial_port.configure(&settings).expect("Could not configure the serial port.");

    let (channel_tx, channel_rx) = mpsc::channel();

    let join_handle = thread::spawn(|| comm_func(channel_rx, serial_port));

    (CommState(Mutex::new(CommChannelTx(channel_tx))), join_handle)
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 T. Okubo
// This file is part of vlc-rs.
// Licensed under the MIT license, see the LICENSE file.

use std::ptr::null;
use std::borrow::Cow;
use std::marker::PhantomData;
use sys;
use ::tools::{to_cstr, from_cstr, from_cstr_ref};
use ::libc::{c_void, c_char, c_int};
use ::enums::*;

/// Retrieve libvlc version.
pub fn version() -> Cow<'static, str> {
    unsafe{
        from_cstr_ref(sys::libvlc_get_version()).unwrap()
    }
}

/// Retrieve libvlc compiler version.
pub fn compiler() -> Cow<'static, str> {
    unsafe{
        from_cstr_ref(sys::libvlc_get_compiler()).unwrap()
    }
}

pub struct Instance {
    pub ptr: *mut sys::libvlc_instance_t,
}

impl Instance {
    /// Create and initialize a libvlc instance.
    pub fn new() -> Option<Instance> {
        unsafe{
            let p = sys::libvlc_new(0, null());

            if p.is_null() {
                return None;
            }

            Some(Instance{ptr: p})
        }
    }

    /// Try to start a user interface for the libvlc instance.
    pub fn add_intf(&self, name: &str) -> Result<(), ()> {
        let cstr = to_cstr(name);

        let result = unsafe{
            sys::libvlc_add_intf(self.ptr, cstr.as_ptr())
        };

        if result == 0 { Ok(()) }
        else { Err(()) }
    }

    /// Sets the application name.
    /// LibVLC passes this as the user agent string when a protocol requires it.
    pub fn set_user_agent(&self, name: &str, http: &str) {
        unsafe{
            sys::libvlc_set_user_agent(
                self.ptr, to_cstr(name).as_ptr(), to_cstr(http).as_ptr());
        }
    }

    /// Waits until an interface causes the instance to exit.
    pub fn wait(&self) {
        unsafe{ sys::libvlc_wait(self.ptr) };
    }

    /// Sets some meta-information about the application.
    pub fn set_app_id(&self, id: &str, version: &str, icon: &str) {
        unsafe{
            sys::libvlc_set_app_id(
                self.ptr, to_cstr(id).as_ptr(), to_cstr(version).as_ptr(), to_cstr(icon).as_ptr());
        }
    }

    /// Returns a list of audio filters that are available.
    pub fn audio_filter_list_get(&self) -> Option<ModuleDescriptionList> {
        unsafe{
            let p = sys::libvlc_audio_filter_list_get(self.ptr);
            if p.is_null() { None }
            else { Some(ModuleDescriptionList{ptr: p}) }
        }
    }

    /// Returns a list of video filters that are available.
    pub fn video_filter_list_get(&self) -> Option<ModuleDescriptionList> {
        unsafe{
            let p = sys::libvlc_video_filter_list_get(self.ptr);
            if p.is_null() { None }
            else { Some(ModuleDescriptionList{ptr: p}) }
        }
    }

    /// Set logging callback
    pub fn set_log<F: Fn(LogLevel, Log, Cow<str>) + Send + 'static>(&self, f: F) {
        let cb: Box<Box<Fn(LogLevel, Log, Cow<str>) + Send + 'static>> = Box::new(Box::new(f));

        unsafe{
            sys::libvlc_log_set(self.ptr, logging_cb, Box::into_raw(cb) as *mut _);
        }
    }
}

impl Drop for Instance {
    fn drop(&mut self) {
        unsafe{
            sys::libvlc_release(self.ptr);
        }
    }
}

extern "C" {
    fn vsnprintf(s: *mut c_char, n: usize, fmt: *const c_char, arg: sys::va_list);
}
const BUF_SIZE: usize = 1024; // Write log message to the buffer by vsnprintf.
unsafe extern "C" fn logging_cb(
    data: *mut c_void, level: c_int, ctx: *const sys::libvlc_log_t, fmt: *const c_char, args: sys::va_list) {

    let f: &Box<Fn(LogLevel, Log, Cow<str>) + Send + 'static> = ::std::mem::transmute(data);
    let mut buf: [c_char; BUF_SIZE] = [0; BUF_SIZE];

    vsnprintf(buf.as_mut_ptr(), BUF_SIZE, fmt, args);

    f(::std::mem::transmute(level), Log{ptr: ctx}, from_cstr_ref(buf.as_ptr()).unwrap());
}

/// List of module description.
pub struct ModuleDescriptionList {
    ptr: *mut sys::libvlc_module_description_t,
}

impl Drop for ModuleDescriptionList {
    fn drop(&mut self) {
        unsafe{ sys::libvlc_module_description_list_release(self.ptr) };
    }
}

impl<'a> IntoIterator for &'a ModuleDescriptionList {
    type Item = ModuleDescriptionRef<'a>;
    type IntoIter = ModuleDescriptionListIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        ModuleDescriptionListIter{ptr: self.ptr, _phantomdata: PhantomData}
    }
}

pub struct ModuleDescriptionListIter<'a> {
    ptr: *mut sys::libvlc_module_description_t,
    _phantomdata: PhantomData<&'a sys::libvlc_module_description_t>,
}

/// Description of a module.
/// The strings are owned.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct ModuleDescription {
    pub name:      Option<String>,
    pub shortname: Option<String>,
    pub longname:  Option<String>,
    pub help:      Option<String>,
}

/// Description of a module.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct ModuleDescriptionRef<'a> {
    pub name:      Option<Cow<'a, str>>,
    pub shortname: Option<Cow<'a, str>>,
    pub longname:  Option<Cow<'a, str>>,
    pub help:      Option<Cow<'a, str>>,
}

impl<'a> Iterator for ModuleDescriptionListIter<'a> {
    type Item = ModuleDescriptionRef<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        unsafe{
            if self.ptr.is_null() {
                return None;
            }
            let p = self.ptr;
            self.ptr = (*p).p_next;
            Some(ModuleDescriptionRef{
                name:      from_cstr_ref((*p).psz_name),
                shortname: from_cstr_ref((*p).psz_shortname),
                longname:  from_cstr_ref((*p).psz_longname),
                help:      from_cstr_ref((*p).psz_help),
            })
        }
    }
}

impl<'a> ModuleDescriptionRef<'a> {
    /// Convert to owned strings.
    pub fn into_owned(&'a self) -> ModuleDescription {
        ModuleDescription {
            name:      self.name     .as_ref().map(|s| s.clone().into_owned()),
            shortname: self.shortname.as_ref().map(|s| s.clone().into_owned()),
            longname:  self.name     .as_ref().map(|s| s.clone().into_owned()),
            help:      self.shortname.as_ref().map(|s| s.clone().into_owned()),
        }
    }
}

pub fn errmsg() -> Option<String> {
    unsafe{ from_cstr(sys::libvlc_errmsg()) }
}

pub fn clearerr() {
    unsafe{ sys::libvlc_clearerr() };
}

#[derive(Clone, Debug)]
pub enum Event {
    MediaMetaChanged(Meta),
    MediaSubItemAdded,
    MediaDurationChanged(i64),
    MediaParsedChanged(i32),
    MediaFreed,
    MediaStateChanged(State),
    MediaSubItemTreeAdded,

    MediaPlayerMediaChanged,
    MediaPlayerNothingSpecial,
    MediaPlayerOpening,
    MediaPlayerBuffering(f32),
    MediaPlayerPlaying,
    MediaPlayerPaused,
    MediaPlayerStopped,
    MediaPlayerForward,
    MediaPlayerBackward,
    MediaPlayerEndReached,
    MediaPlayerEncounteredError,
    MediaPlayerTimeChanged,
    MediaPlayerPositionChanged(f32),
    MediaPlayerSeekableChanged,
    MediaPlayerPausableChanged,
    MediaPlayerTitleChanged,
    MediaPlayerSnapshotTaken,
    MediaPlayerLengthChanged,
    MediaPlayerVout,
    MediaPlayerScrambledChanged,

    MediaListItemAdded,
    MediaListWillAddItem,
    MediaListItemDeleted,
    MediaListWillDeleteItem,

    MediaListViewItemAdded,
    MediaListViewWillAddItem,
    MediaListViewItemDeleted,
    MediaListViewWillDeleteItem,

    MediaListPlayerPlayed,
    MediaListPlayerNextItemSet,
    MediaListPlayerStopped,

    MediaDiscovererStarted,
    MediaDiscovererEnded,

    VlmMediaAdded,
    VlmMediaRemoved,
    VlmMediaChanged,
    VlmMediaInstanceStarted,
    VlmMediaInstanceStopped,
    VlmMediaInstanceStatusInit,
    VlmMediaInstanceStatusOpening,
    VlmMediaInstanceStatusPlaying,
    VlmMediaInstanceStatusPause,
    VlmMediaInstanceStatusEnd,
    VlmMediaInstanceStatusError
}

pub struct EventManager<'a> {
    pub ptr: *mut sys::libvlc_event_manager_t,
    pub _phantomdata: ::std::marker::PhantomData<&'a sys::libvlc_event_manager_t>,
}

impl<'a> EventManager<'a> {
    pub fn attach<F>(&self, event_type: EventType, callback: F) -> Result<(), ()>
        where F: Fn(Event, VLCObject) + Send + 'static
    {
        // Explicit type annotation is needed
        let callback: Box<Box<Fn(Event, VLCObject) + Send + 'static>> =
            Box::new(Box::new(callback));

        let result = unsafe{
            sys::libvlc_event_attach(
                self.ptr, event_type as i32, event_manager_callback,
                Box::into_raw(callback) as *mut c_void)
        };

        if result == 0 {
            Ok(())
        }else{
            Err(())
        }
    }
}

unsafe extern "C" fn event_manager_callback(pe: *const sys::libvlc_event_t, data: *mut c_void) {
    let f: &Box<Fn(Event, VLCObject) + Send + 'static> = ::std::mem::transmute(data);

    f(conv_event(pe), VLCObject{_ptr: (*pe).p_obj});
}

// Convert c-style libvlc_event_t to Event
fn conv_event(pe: *const sys::libvlc_event_t) -> Event {
    let event_type: EventType = unsafe{ ::std::mem::transmute((*pe)._type) };

    match event_type {
        EventType::MediaMetaChanged => {
            unsafe{
                Event::MediaMetaChanged((*pe).u.media_meta_changed.meta_type)
            }
        },
        EventType::MediaSubItemAdded => {
            Event::MediaSubItemAdded
        },
        EventType::MediaDurationChanged => {
            unsafe{
                Event::MediaDurationChanged((*pe).u.media_duration_changed.new_duration)
            }
        },
        EventType::MediaParsedChanged => {
            unsafe{
                Event::MediaParsedChanged((*pe).u.media_parsed_changed.new_status)
            }
        },
        EventType::MediaFreed => {
            Event::MediaFreed
        },
        EventType::MediaStateChanged => {
            unsafe{
                Event::MediaStateChanged((*pe).u.media_state_changed.new_state)
            }
        },
        EventType::MediaSubItemTreeAdded => {
            Event::MediaSubItemTreeAdded
        },
        EventType::MediaPlayerMediaChanged => {
            Event::MediaPlayerMediaChanged
        },
        EventType::MediaPlayerNothingSpecial => {
            Event::MediaPlayerNothingSpecial
        },
        EventType::MediaPlayerOpening => {
            Event::MediaPlayerOpening
        },
        EventType::MediaPlayerBuffering => {
            unsafe{
                Event::MediaPlayerBuffering((*pe).u.media_player_buffering.new_cache)
            }
        },
        EventType::MediaPlayerPlaying => {
            Event::MediaPlayerPlaying
        },
        EventType::MediaPlayerPaused => {
            Event::MediaPlayerPaused
        },
        EventType::MediaPlayerStopped => {
            Event::MediaPlayerStopped
        },
        EventType::MediaPlayerForward => {
            Event::MediaPlayerForward
        },
        EventType::MediaPlayerBackward => {
            Event::MediaPlayerBackward
        },
        EventType::MediaPlayerEndReached => {
            Event::MediaPlayerEndReached
        },
        EventType::MediaPlayerEncounteredError => {
            Event::MediaPlayerEncounteredError
        },
        EventType::MediaPlayerTimeChanged => {
            Event::MediaPlayerTimeChanged
        },
        EventType::MediaPlayerPositionChanged => {
            unsafe{
                Event::MediaPlayerPositionChanged((*pe).u.media_player_position_changed.new_position)
            }
        },
        EventType::MediaPlayerSeekableChanged => {
            Event::MediaPlayerSeekableChanged
        },
        EventType::MediaPlayerPausableChanged => {
            Event::MediaPlayerPausableChanged
        },
        EventType::MediaPlayerTitleChanged => {
            Event::MediaPlayerTitleChanged
        },
        EventType::MediaPlayerSnapshotTaken => {
            Event::MediaPlayerSnapshotTaken
        },
        EventType::MediaPlayerLengthChanged => {
            Event::MediaPlayerLengthChanged
        },
        EventType::MediaPlayerVout => {
            Event::MediaPlayerVout
        },
        EventType::MediaPlayerScrambledChanged => {
            Event::MediaPlayerScrambledChanged
        },
        EventType::MediaListItemAdded => {
            Event::MediaListItemAdded
        },
        EventType::MediaListWillAddItem => {
            Event::MediaListWillAddItem
        },
        EventType::MediaListItemDeleted => {
            Event::MediaListItemDeleted
        },
        EventType::MediaListWillDeleteItem => {
            Event::MediaListWillDeleteItem
        },
        EventType::MediaListViewItemAdded => {
            Event::MediaListViewItemAdded
        },
        EventType::MediaListViewWillAddItem => {
            Event::MediaListViewWillAddItem
        },
        EventType::MediaListViewItemDeleted => {
            Event::MediaListViewItemDeleted
        },
        EventType::MediaListViewWillDeleteItem => {
            Event::MediaListViewWillDeleteItem
        },
        EventType::MediaListPlayerPlayed => {
            Event::MediaListPlayerPlayed
        },
        EventType::MediaListPlayerNextItemSet => {
            Event::MediaListPlayerNextItemSet
        },
        EventType::MediaListPlayerStopped => {
            Event::MediaListPlayerStopped
        },
        EventType::MediaDiscovererStarted => {
            Event::MediaDiscovererStarted
        },
        EventType::MediaDiscovererEnded => {
            Event::MediaDiscovererEnded
        },
        EventType::VlmMediaAdded => {
            Event::VlmMediaAdded
        },
        EventType::VlmMediaRemoved => {
            Event::VlmMediaRemoved
        },
        EventType::VlmMediaChanged => {
            Event::VlmMediaChanged
        },
        EventType::VlmMediaInstanceStarted => {
            Event::VlmMediaInstanceStarted
        },
        EventType::VlmMediaInstanceStopped => {
            Event::VlmMediaInstanceStopped
        },
        EventType::VlmMediaInstanceStatusInit => {
            Event::VlmMediaInstanceStatusInit
        },
        EventType::VlmMediaInstanceStatusOpening => {
            Event::VlmMediaInstanceStatusOpening
        },
        EventType::VlmMediaInstanceStatusPlaying => {
            Event::VlmMediaInstanceStatusPlaying
        },
        EventType::VlmMediaInstanceStatusPause => {
            Event::VlmMediaInstanceStatusPause
        },
        EventType::VlmMediaInstanceStatusEnd => {
            Event::VlmMediaInstanceStatusEnd
        },
        EventType::VlmMediaInstanceStatusError => {
            Event::VlmMediaInstanceStatusError
        },
    }
}

pub struct VLCObject {
    _ptr: *mut c_void,
}

pub struct Log {
    pub ptr: *const sys::libvlc_log_t
}

<commit_msg>Use String instead of Cow<str><commit_after>// Copyright (c) 2015 T. Okubo
// This file is part of vlc-rs.
// Licensed under the MIT license, see the LICENSE file.

use std::ptr::null;
use std::borrow::Cow;
use std::marker::PhantomData;
use sys;
use ::tools::{to_cstr, from_cstr, from_cstr_ref};
use ::libc::{c_void, c_char, c_int};
use ::enums::*;

/// Retrieve libvlc version.
pub fn version() -> String {
    unsafe{
        from_cstr_ref(sys::libvlc_get_version()).unwrap().into_owned()
    }
}

/// Retrieve libvlc compiler version.
pub fn compiler() -> String {
    unsafe{
        from_cstr_ref(sys::libvlc_get_compiler()).unwrap().into_owned()
    }
}

pub struct Instance {
    pub ptr: *mut sys::libvlc_instance_t,
}

impl Instance {
    /// Create and initialize a libvlc instance.
    pub fn new() -> Option<Instance> {
        unsafe{
            let p = sys::libvlc_new(0, null());

            if p.is_null() {
                return None;
            }

            Some(Instance{ptr: p})
        }
    }

    /// Try to start a user interface for the libvlc instance.
    pub fn add_intf(&self, name: &str) -> Result<(), ()> {
        let cstr = to_cstr(name);

        let result = unsafe{
            sys::libvlc_add_intf(self.ptr, cstr.as_ptr())
        };

        if result == 0 { Ok(()) }
        else { Err(()) }
    }

    /// Sets the application name.
    /// LibVLC passes this as the user agent string when a protocol requires it.
    pub fn set_user_agent(&self, name: &str, http: &str) {
        unsafe{
            sys::libvlc_set_user_agent(
                self.ptr, to_cstr(name).as_ptr(), to_cstr(http).as_ptr());
        }
    }

    /// Waits until an interface causes the instance to exit.
    pub fn wait(&self) {
        unsafe{ sys::libvlc_wait(self.ptr) };
    }

    /// Sets some meta-information about the application.
    pub fn set_app_id(&self, id: &str, version: &str, icon: &str) {
        unsafe{
            sys::libvlc_set_app_id(
                self.ptr, to_cstr(id).as_ptr(), to_cstr(version).as_ptr(), to_cstr(icon).as_ptr());
        }
    }

    /// Returns a list of audio filters that are available.
    pub fn audio_filter_list_get(&self) -> Option<ModuleDescriptionList> {
        unsafe{
            let p = sys::libvlc_audio_filter_list_get(self.ptr);
            if p.is_null() { None }
            else { Some(ModuleDescriptionList{ptr: p}) }
        }
    }

    /// Returns a list of video filters that are available.
    pub fn video_filter_list_get(&self) -> Option<ModuleDescriptionList> {
        unsafe{
            let p = sys::libvlc_video_filter_list_get(self.ptr);
            if p.is_null() { None }
            else { Some(ModuleDescriptionList{ptr: p}) }
        }
    }

    /// Set logging callback
    pub fn set_log<F: Fn(LogLevel, Log, Cow<str>) + Send + 'static>(&self, f: F) {
        let cb: Box<Box<Fn(LogLevel, Log, Cow<str>) + Send + 'static>> = Box::new(Box::new(f));

        unsafe{
            sys::libvlc_log_set(self.ptr, logging_cb, Box::into_raw(cb) as *mut _);
        }
    }
}

impl Drop for Instance {
    fn drop(&mut self) {
        unsafe{
            sys::libvlc_release(self.ptr);
        }
    }
}

extern "C" {
    fn vsnprintf(s: *mut c_char, n: usize, fmt: *const c_char, arg: sys::va_list);
}
const BUF_SIZE: usize = 1024; // Write log message to the buffer by vsnprintf.
unsafe extern "C" fn logging_cb(
    data: *mut c_void, level: c_int, ctx: *const sys::libvlc_log_t, fmt: *const c_char, args: sys::va_list) {

    let f: &Box<Fn(LogLevel, Log, Cow<str>) + Send + 'static> = ::std::mem::transmute(data);
    let mut buf: [c_char; BUF_SIZE] = [0; BUF_SIZE];

    vsnprintf(buf.as_mut_ptr(), BUF_SIZE, fmt, args);

    f(::std::mem::transmute(level), Log{ptr: ctx}, from_cstr_ref(buf.as_ptr()).unwrap());
}

/// List of module description.
pub struct ModuleDescriptionList {
    ptr: *mut sys::libvlc_module_description_t,
}

impl Drop for ModuleDescriptionList {
    fn drop(&mut self) {
        unsafe{ sys::libvlc_module_description_list_release(self.ptr) };
    }
}

impl<'a> IntoIterator for &'a ModuleDescriptionList {
    type Item = ModuleDescriptionRef<'a>;
    type IntoIter = ModuleDescriptionListIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        ModuleDescriptionListIter{ptr: self.ptr, _phantomdata: PhantomData}
    }
}

pub struct ModuleDescriptionListIter<'a> {
    ptr: *mut sys::libvlc_module_description_t,
    _phantomdata: PhantomData<&'a sys::libvlc_module_description_t>,
}

/// Description of a module.
/// The strings are owned.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct ModuleDescription {
    pub name:      Option<String>,
    pub shortname: Option<String>,
    pub longname:  Option<String>,
    pub help:      Option<String>,
}

/// Description of a module.
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct ModuleDescriptionRef<'a> {
    pub name:      Option<Cow<'a, str>>,
    pub shortname: Option<Cow<'a, str>>,
    pub longname:  Option<Cow<'a, str>>,
    pub help:      Option<Cow<'a, str>>,
}

impl<'a> Iterator for ModuleDescriptionListIter<'a> {
    type Item = ModuleDescriptionRef<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        unsafe{
            if self.ptr.is_null() {
                return None;
            }
            let p = self.ptr;
            self.ptr = (*p).p_next;
            Some(ModuleDescriptionRef{
                name:      from_cstr_ref((*p).psz_name),
                shortname: from_cstr_ref((*p).psz_shortname),
                longname:  from_cstr_ref((*p).psz_longname),
                help:      from_cstr_ref((*p).psz_help),
            })
        }
    }
}

impl<'a> ModuleDescriptionRef<'a> {
    /// Convert to owned strings.
    pub fn into_owned(&'a self) -> ModuleDescription {
        ModuleDescription {
            name:      self.name     .as_ref().map(|s| s.clone().into_owned()),
            shortname: self.shortname.as_ref().map(|s| s.clone().into_owned()),
            longname:  self.name     .as_ref().map(|s| s.clone().into_owned()),
            help:      self.shortname.as_ref().map(|s| s.clone().into_owned()),
        }
    }
}

pub fn errmsg() -> Option<String> {
    unsafe{ from_cstr(sys::libvlc_errmsg()) }
}

pub fn clearerr() {
    unsafe{ sys::libvlc_clearerr() };
}

#[derive(Clone, Debug)]
pub enum Event {
    MediaMetaChanged(Meta),
    MediaSubItemAdded,
    MediaDurationChanged(i64),
    MediaParsedChanged(i32),
    MediaFreed,
    MediaStateChanged(State),
    MediaSubItemTreeAdded,

    MediaPlayerMediaChanged,
    MediaPlayerNothingSpecial,
    MediaPlayerOpening,
    MediaPlayerBuffering(f32),
    MediaPlayerPlaying,
    MediaPlayerPaused,
    MediaPlayerStopped,
    MediaPlayerForward,
    MediaPlayerBackward,
    MediaPlayerEndReached,
    MediaPlayerEncounteredError,
    MediaPlayerTimeChanged,
    MediaPlayerPositionChanged(f32),
    MediaPlayerSeekableChanged,
    MediaPlayerPausableChanged,
    MediaPlayerTitleChanged,
    MediaPlayerSnapshotTaken,
    MediaPlayerLengthChanged,
    MediaPlayerVout,
    MediaPlayerScrambledChanged,

    MediaListItemAdded,
    MediaListWillAddItem,
    MediaListItemDeleted,
    MediaListWillDeleteItem,

    MediaListViewItemAdded,
    MediaListViewWillAddItem,
    MediaListViewItemDeleted,
    MediaListViewWillDeleteItem,

    MediaListPlayerPlayed,
    MediaListPlayerNextItemSet,
    MediaListPlayerStopped,

    MediaDiscovererStarted,
    MediaDiscovererEnded,

    VlmMediaAdded,
    VlmMediaRemoved,
    VlmMediaChanged,
    VlmMediaInstanceStarted,
    VlmMediaInstanceStopped,
    VlmMediaInstanceStatusInit,
    VlmMediaInstanceStatusOpening,
    VlmMediaInstanceStatusPlaying,
    VlmMediaInstanceStatusPause,
    VlmMediaInstanceStatusEnd,
    VlmMediaInstanceStatusError
}

pub struct EventManager<'a> {
    pub ptr: *mut sys::libvlc_event_manager_t,
    pub _phantomdata: ::std::marker::PhantomData<&'a sys::libvlc_event_manager_t>,
}

impl<'a> EventManager<'a> {
    pub fn attach<F>(&self, event_type: EventType, callback: F) -> Result<(), ()>
        where F: Fn(Event, VLCObject) + Send + 'static
    {
        // Explicit type annotation is needed
        let callback: Box<Box<Fn(Event, VLCObject) + Send + 'static>> =
            Box::new(Box::new(callback));

        let result = unsafe{
            sys::libvlc_event_attach(
                self.ptr, event_type as i32, event_manager_callback,
                Box::into_raw(callback) as *mut c_void)
        };

        if result == 0 {
            Ok(())
        }else{
            Err(())
        }
    }
}

unsafe extern "C" fn event_manager_callback(pe: *const sys::libvlc_event_t, data: *mut c_void) {
    let f: &Box<Fn(Event, VLCObject) + Send + 'static> = ::std::mem::transmute(data);

    f(conv_event(pe), VLCObject{_ptr: (*pe).p_obj});
}

// Convert c-style libvlc_event_t to Event
fn conv_event(pe: *const sys::libvlc_event_t) -> Event {
    let event_type: EventType = unsafe{ ::std::mem::transmute((*pe)._type) };

    match event_type {
        EventType::MediaMetaChanged => {
            unsafe{
                Event::MediaMetaChanged((*pe).u.media_meta_changed.meta_type)
            }
        },
        EventType::MediaSubItemAdded => {
            Event::MediaSubItemAdded
        },
        EventType::MediaDurationChanged => {
            unsafe{
                Event::MediaDurationChanged((*pe).u.media_duration_changed.new_duration)
            }
        },
        EventType::MediaParsedChanged => {
            unsafe{
                Event::MediaParsedChanged((*pe).u.media_parsed_changed.new_status)
            }
        },
        EventType::MediaFreed => {
            Event::MediaFreed
        },
        EventType::MediaStateChanged => {
            unsafe{
                Event::MediaStateChanged((*pe).u.media_state_changed.new_state)
            }
        },
        EventType::MediaSubItemTreeAdded => {
            Event::MediaSubItemTreeAdded
        },
        EventType::MediaPlayerMediaChanged => {
            Event::MediaPlayerMediaChanged
        },
        EventType::MediaPlayerNothingSpecial => {
            Event::MediaPlayerNothingSpecial
        },
        EventType::MediaPlayerOpening => {
            Event::MediaPlayerOpening
        },
        EventType::MediaPlayerBuffering => {
            unsafe{
                Event::MediaPlayerBuffering((*pe).u.media_player_buffering.new_cache)
            }
        },
        EventType::MediaPlayerPlaying => {
            Event::MediaPlayerPlaying
        },
        EventType::MediaPlayerPaused => {
            Event::MediaPlayerPaused
        },
        EventType::MediaPlayerStopped => {
            Event::MediaPlayerStopped
        },
        EventType::MediaPlayerForward => {
            Event::MediaPlayerForward
        },
        EventType::MediaPlayerBackward => {
            Event::MediaPlayerBackward
        },
        EventType::MediaPlayerEndReached => {
            Event::MediaPlayerEndReached
        },
        EventType::MediaPlayerEncounteredError => {
            Event::MediaPlayerEncounteredError
        },
        EventType::MediaPlayerTimeChanged => {
            Event::MediaPlayerTimeChanged
        },
        EventType::MediaPlayerPositionChanged => {
            unsafe{
                Event::MediaPlayerPositionChanged((*pe).u.media_player_position_changed.new_position)
            }
        },
        EventType::MediaPlayerSeekableChanged => {
            Event::MediaPlayerSeekableChanged
        },
        EventType::MediaPlayerPausableChanged => {
            Event::MediaPlayerPausableChanged
        },
        EventType::MediaPlayerTitleChanged => {
            Event::MediaPlayerTitleChanged
        },
        EventType::MediaPlayerSnapshotTaken => {
            Event::MediaPlayerSnapshotTaken
        },
        EventType::MediaPlayerLengthChanged => {
            Event::MediaPlayerLengthChanged
        },
        EventType::MediaPlayerVout => {
            Event::MediaPlayerVout
        },
        EventType::MediaPlayerScrambledChanged => {
            Event::MediaPlayerScrambledChanged
        },
        EventType::MediaListItemAdded => {
            Event::MediaListItemAdded
        },
        EventType::MediaListWillAddItem => {
            Event::MediaListWillAddItem
        },
        EventType::MediaListItemDeleted => {
            Event::MediaListItemDeleted
        },
        EventType::MediaListWillDeleteItem => {
            Event::MediaListWillDeleteItem
        },
        EventType::MediaListViewItemAdded => {
            Event::MediaListViewItemAdded
        },
        EventType::MediaListViewWillAddItem => {
            Event::MediaListViewWillAddItem
        },
        EventType::MediaListViewItemDeleted => {
            Event::MediaListViewItemDeleted
        },
        EventType::MediaListViewWillDeleteItem => {
            Event::MediaListViewWillDeleteItem
        },
        EventType::MediaListPlayerPlayed => {
            Event::MediaListPlayerPlayed
        },
        EventType::MediaListPlayerNextItemSet => {
            Event::MediaListPlayerNextItemSet
        },
        EventType::MediaListPlayerStopped => {
            Event::MediaListPlayerStopped
        },
        EventType::MediaDiscovererStarted => {
            Event::MediaDiscovererStarted
        },
        EventType::MediaDiscovererEnded => {
            Event::MediaDiscovererEnded
        },
        EventType::VlmMediaAdded => {
            Event::VlmMediaAdded
        },
        EventType::VlmMediaRemoved => {
            Event::VlmMediaRemoved
        },
        EventType::VlmMediaChanged => {
            Event::VlmMediaChanged
        },
        EventType::VlmMediaInstanceStarted => {
            Event::VlmMediaInstanceStarted
        },
        EventType::VlmMediaInstanceStopped => {
            Event::VlmMediaInstanceStopped
        },
        EventType::VlmMediaInstanceStatusInit => {
            Event::VlmMediaInstanceStatusInit
        },
        EventType::VlmMediaInstanceStatusOpening => {
            Event::VlmMediaInstanceStatusOpening
        },
        EventType::VlmMediaInstanceStatusPlaying => {
            Event::VlmMediaInstanceStatusPlaying
        },
        EventType::VlmMediaInstanceStatusPause => {
            Event::VlmMediaInstanceStatusPause
        },
        EventType::VlmMediaInstanceStatusEnd => {
            Event::VlmMediaInstanceStatusEnd
        },
        EventType::VlmMediaInstanceStatusError => {
            Event::VlmMediaInstanceStatusError
        },
    }
}

pub struct VLCObject {
    _ptr: *mut c_void,
}

pub struct Log {
    pub ptr: *const sys::libvlc_log_t
}

<|endoftext|>


<commit_before>use std::io::TcpStream;

pub trait Data
{
    fn process_request_data(&self, mut request: TcpStream);
}
<commit_msg>Updated trait<commit_after>use std::io::TcpStream;

pub trait Data
{
    fn process_request_data(&mut self, mut request: TcpStream);
}
<|endoftext|>