<commit_before>//! Contains the different types of values understood by XML-RPC.

use utils::{escape_xml, format_datetime};

use base64::encode;
use iso8601::DateTime;

use std::collections::BTreeMap;
use std::io::{self, Write};

/// The possible XML-RPC values.
///
/// Nested values can be accessed by using [`get`](#method.get) method and Rust's square-bracket
/// indexing operator.
///
/// A string index can be used to access a value in a `Struct`, and a `usize` index can be used to
/// access an element of an `Array`.
///
/// # Examples
///
/// ```
/// # use std::collections::BTreeMap;
/// # use xmlrpc::{Value, Index};
/// let nothing = Value::Nil;
///
/// let person = Value::Struct(vec![
///     ("name".to_string(), Value::from("John Doe")),
///     ("age".to_string(), Value::from(37)),
///     ("children".to_string(), Value::Array(vec![
///         Value::from("Mark"),
///         Value::from("Jennyfer")
///     ])),
/// ].into_iter().collect());
///
/// // get
/// assert_eq!(nothing.get("name"), None);
/// assert_eq!(person.get("name"), Some(&Value::from("John Doe")));
/// assert_eq!(person.get("SSN"), None);
///
/// // index
/// assert_eq!(nothing["name"], Value::Nil);
/// assert_eq!(person["name"], Value::from("John Doe"));
/// assert_eq!(person["age"], Value::Int(37));
/// assert_eq!(person["SSN"], Value::Nil);
/// assert_eq!(person["children"][0], Value::from("Mark"));
/// assert_eq!(person["children"][0]["age"], Value::Nil);
/// assert_eq!(person["children"][2], Value::Nil);
///
/// // extract values
/// assert_eq!(person["name"].as_str(), Some("John Doe"));
/// assert_eq!(person["age"].as_i32(), Some(37));
/// assert_eq!(person["age"].as_bool(), None);
/// assert_eq!(person["children"].as_array().unwrap().len(), 2);
/// ```
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// `<i4>` or `<int>`, 32-bit signed integer.
    Int(i32),
    /// `<i8>`, 64-bit signed integer.
    ///
    /// This is an XMLRPC extension and may not be supported by all clients / servers.
    Int64(i64),
    /// `<boolean>`, 0 == `false`, 1 == `true`.
    Bool(bool),
    /// `<string>`
    // FIXME zero-copy? `Cow<'static, ..>`?
    String(String),
    /// `<double>`
    Double(f64),
    /// `<dateTime.iso8601>`, an ISO 8601 formatted date/time value.
    DateTime(DateTime),
    /// `<base64>`, base64-encoded binary data.
    Base64(Vec<u8>),

    /// `<struct>`, a mapping of named values.
    Struct(BTreeMap<String, Value>),
    /// `<array>`, a list of arbitrary (heterogeneous) values.
    Array(Vec<Value>),

    /// `<nil/>`, the empty (Unit) value.
    ///
    /// This is an XMLRPC [extension][ext] and may not be supported by all clients / servers.
    ///
    /// [ext]: https://web.archive.org/web/20050911054235/http://ontosys.com/xml-rpc/extensions.php
    Nil,
}

impl Value {
    /// Formats this `Value` as an XML `<value>` element.
    ///
    /// # Errors
    ///
    /// Any error reported by the writer will be propagated to the caller.
    pub fn write_as_xml<W: Write>(&self, fmt: &mut W) -> io::Result<()> {
        writeln!(fmt, "<value>")?;

        match *self {
            Value::Int(i) => {
                writeln!(fmt, "<i4>{}</i4>", i)?;
            }
            Value::Int64(i) => {
                writeln!(fmt, "<i8>{}</i8>", i)?;
            }
            Value::Bool(b) => {
                writeln!(fmt, "<boolean>{}</boolean>", if b { "1" } else { "0" })?;
            }
            Value::String(ref s) => {
                writeln!(fmt, "<string>{}</string>", escape_xml(s))?;
            }
            Value::Double(d) => {
                writeln!(fmt, "<double>{}</double>", d)?;
            }
            Value::DateTime(date_time) => {
                writeln!(fmt, "<dateTime.iso8601>{}</dateTime.iso8601>", format_datetime(&date_time))?;
            }
            Value::Base64(ref data) => {
                writeln!(fmt, "<base64>{}</base64>", encode(data))?;
            }
            Value::Struct(ref map) => {
                writeln!(fmt, "<struct>")?;
                for (ref name, ref value) in map {
                    writeln!(fmt, "<member>")?;
                    writeln!(fmt, "<name>{}</name>", escape_xml(name))?;
                    value.write_as_xml(fmt)?;
                    writeln!(fmt, "</member>")?;
                }
                writeln!(fmt, "</struct>")?;
            }
            Value::Array(ref array) => {
                writeln!(fmt, "<array>")?;
                writeln!(fmt, "<data>")?;
                for value in array {
                    value.write_as_xml(fmt)?;
                }
                writeln!(fmt, "</data>")?;
                writeln!(fmt, "</array>")?;
            }
            Value::Nil => {
                writeln!(fmt, "<nil/>")?;
            }
        }

        writeln!(fmt, "</value>")?;
        Ok(())
    }

    /// Returns an inner struct or array value indexed by `index`.
    ///
    /// Returns `None` if the member doesn't exist or `self` is neither a struct nor an array.
    ///
    /// You can also use Rust's square-bracket indexing syntax to perform this operation if you want
    /// a default value instead of an `Option`. Refer to the top-level [examples](#examples) for
    /// details.
    pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
        index.get(self)
    }

    /// If the `Value` is a normal integer (`Value::Int`), returns associated value. Returns `None`
    /// otherwise.
    ///
    /// In particular, `None` is also returned if `self` is a `Value::Int64`. Use [`as_i64`] to
    /// handle this case.
    ///
    /// [`as_i64`]: #method.as_i64
    pub fn as_i32(&self) -> Option<i32> {
        match *self {
            Value::Int(i) => Some(i),
            _ => None
        }
    }

    /// If the `Value` is an integer, returns associated value. Returns `None` otherwise.
    ///
    /// This works with both `Value::Int` and `Value::Int64`.
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Int(i) => Some(i64::from(i)),
            Value::Int64(i) => Some(i),
            _ => None
        }
    }

    /// If the `Value` is a boolean, returns associated value. Returns `None` otherwise.
    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            Value::Bool(b) => Some(b),
            _ => None
        }
    }

    /// If the `Value` is a string, returns associated value. Returns `None` otherwise.
    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Value::String(ref s) => Some(s),
            _ => None
        }
    }

    /// If the `Value` is a floating point number, returns associated value. Returns `None`
    /// otherwise.
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::Double(d) => Some(d),
            _ => None
        }
    }

    /// If the `Value` is a date/time, returns associated value. Returns `None` otherwise.
    pub fn as_datetime(&self) -> Option<DateTime> {
        match *self {
            Value::DateTime(dt) => Some(dt),
            _ => None
        }
    }

    /// If the `Value` is base64 binary data, returns associated value. Returns `None` otherwise.
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match *self {
            Value::Base64(ref data) => Some(data),
            _ => None
        }
    }

    /// If the `Value` is a struct, returns associated map. Returns `None` otherwise.
    pub fn as_struct(&self) -> Option<&BTreeMap<String, Value>> {
        match *self {
            Value::Struct(ref map) => Some(map),
            _ => None
        }
    }

    /// If the `Value` is an array, returns associated slice. Returns `None` otherwise.
    pub fn as_array(&self) -> Option<&[Value]> {
        match *self {
            Value::Array(ref array) => Some(array),
            _ => None
        }
    }
}

impl From<i32> for Value {
    fn from(other: i32) -> Self {
        Value::Int(other)
    }
}

impl From<i64> for Value {
    fn from(other: i64) -> Self {
        Value::Int64(other)
    }
}

impl From<bool> for Value {
    fn from(other: bool) -> Self {
        Value::Bool(other)
    }
}

impl From<String> for Value {
    fn from(other: String) -> Self {
        Value::String(other)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(other: &'a str) -> Self {
        Value::String(other.to_string())
    }
}

impl From<f64> for Value {
    fn from(other: f64) -> Self {
        Value::Double(other)
    }
}

impl From<DateTime> for Value {
    fn from(other: DateTime) -> Self {
        Value::DateTime(other)
    }
}

impl From<Vec<u8>> for Value {
    fn from(other: Vec<u8>) -> Self {
        Value::Base64(other)
    }
}

/// A type that can be used to index into a `Value`.
pub trait Index {
    /// Gets an inner value of a given value represented by self.
    #[doc(hidden)]
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value>;
}

impl Index for str {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for String {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for usize {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Array(ref array) = *value {
            array.get(*self)
        } else {
            None
        }
    }
}

impl<'a, I> Index for &'a I where I: Index + ?Sized {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        (*self).get(value)
    }
}

impl<I> ::std::ops::Index<I> for Value where I: Index {
    type Output = Value;
    fn index(&self, index: I) -> &Self::Output {
        index.get(self).unwrap_or(&Value::Nil)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::str;
    use std::collections::BTreeMap;

    #[test]
    fn escapes_strings() {
        let mut output: Vec<u8> = Vec::new();

        Value::from("<xml> string").write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<string><xml>&nbsp;string</string>\n</value>\n");
    }

    #[test]
    fn escapes_struct_member_names() {
        let mut output: Vec<u8> = Vec::new();
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("x&<x".to_string(), Value::from(true));

        Value::Struct(map).write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<struct>\n<member>\n<name>x&<x</name>\n<value>\n<boolean>1</boolean>\n</value>\n</member>\n</struct>\n</value>\n");
    }

    #[test]
    fn access_nested_values() {
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("name".to_string(), Value::from("John Doe"));
        map.insert("age".to_string(), Value::from(37));
        map.insert("children".to_string(), Value::Array(vec![Value::from("Mark"), Value::from("Jennyfer")]));
        let value = Value::Struct(map);

        assert_eq!(value.get("name"), Some(&Value::from("John Doe")));
        assert_eq!(value.get("age"), Some(&Value::from(37)));
        assert_eq!(value.get("birthdate"), None);
        assert_eq!(Value::Nil.get("age"), None);
        assert_eq!(value["name"], Value::from("John Doe"));
        assert_eq!(value["age"], Value::from(37));
        assert_eq!(value["birthdate"], Value::Nil);
        assert_eq!(Value::Nil["age"], Value::Nil);
        assert_eq!(value["children"][0], Value::from("Mark"));
        assert_eq!(value["children"][1], Value::from("Jennyfer"));
        assert_eq!(value["children"][2], Value::Nil);

        assert_eq!(value["age"].as_i32(), Some(37));
        assert_eq!(value["children"][0].as_str(), Some("Mark"));
    }
}
<commit_msg>Seal the Index trait like serde_json does<commit_after>//! Contains the different types of values understood by XML-RPC.

use utils::{escape_xml, format_datetime};

use base64::encode;
use iso8601::DateTime;

use std::collections::BTreeMap;
use std::io::{self, Write};

/// The possible XML-RPC values.
///
/// Nested values can be accessed by using [`get`](#method.get) method and Rust's square-bracket
/// indexing operator.
///
/// A string index can be used to access a value in a `Struct`, and a `usize` index can be used to
/// access an element of an `Array`.
///
/// # Examples
///
/// ```
/// # use std::collections::BTreeMap;
/// # use xmlrpc::{Value, Index};
/// let nothing = Value::Nil;
///
/// let person = Value::Struct(vec![
///     ("name".to_string(), Value::from("John Doe")),
///     ("age".to_string(), Value::from(37)),
///     ("children".to_string(), Value::Array(vec![
///         Value::from("Mark"),
///         Value::from("Jennyfer")
///     ])),
/// ].into_iter().collect());
///
/// // get
/// assert_eq!(nothing.get("name"), None);
/// assert_eq!(person.get("name"), Some(&Value::from("John Doe")));
/// assert_eq!(person.get("SSN"), None);
///
/// // index
/// assert_eq!(nothing["name"], Value::Nil);
/// assert_eq!(person["name"], Value::from("John Doe"));
/// assert_eq!(person["age"], Value::Int(37));
/// assert_eq!(person["SSN"], Value::Nil);
/// assert_eq!(person["children"][0], Value::from("Mark"));
/// assert_eq!(person["children"][0]["age"], Value::Nil);
/// assert_eq!(person["children"][2], Value::Nil);
///
/// // extract values
/// assert_eq!(person["name"].as_str(), Some("John Doe"));
/// assert_eq!(person["age"].as_i32(), Some(37));
/// assert_eq!(person["age"].as_bool(), None);
/// assert_eq!(person["children"].as_array().unwrap().len(), 2);
/// ```
#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// `<i4>` or `<int>`, 32-bit signed integer.
    Int(i32),
    /// `<i8>`, 64-bit signed integer.
    ///
    /// This is an XMLRPC extension and may not be supported by all clients / servers.
    Int64(i64),
    /// `<boolean>`, 0 == `false`, 1 == `true`.
    Bool(bool),
    /// `<string>`
    // FIXME zero-copy? `Cow<'static, ..>`?
    String(String),
    /// `<double>`
    Double(f64),
    /// `<dateTime.iso8601>`, an ISO 8601 formatted date/time value.
    DateTime(DateTime),
    /// `<base64>`, base64-encoded binary data.
    Base64(Vec<u8>),

    /// `<struct>`, a mapping of named values.
    Struct(BTreeMap<String, Value>),
    /// `<array>`, a list of arbitrary (heterogeneous) values.
    Array(Vec<Value>),

    /// `<nil/>`, the empty (Unit) value.
    ///
    /// This is an XMLRPC [extension][ext] and may not be supported by all clients / servers.
    ///
    /// [ext]: https://web.archive.org/web/20050911054235/http://ontosys.com/xml-rpc/extensions.php
    Nil,
}

impl Value {
    /// Formats this `Value` as an XML `<value>` element.
    ///
    /// # Errors
    ///
    /// Any error reported by the writer will be propagated to the caller.
    pub fn write_as_xml<W: Write>(&self, fmt: &mut W) -> io::Result<()> {
        writeln!(fmt, "<value>")?;

        match *self {
            Value::Int(i) => {
                writeln!(fmt, "<i4>{}</i4>", i)?;
            }
            Value::Int64(i) => {
                writeln!(fmt, "<i8>{}</i8>", i)?;
            }
            Value::Bool(b) => {
                writeln!(fmt, "<boolean>{}</boolean>", if b { "1" } else { "0" })?;
            }
            Value::String(ref s) => {
                writeln!(fmt, "<string>{}</string>", escape_xml(s))?;
            }
            Value::Double(d) => {
                writeln!(fmt, "<double>{}</double>", d)?;
            }
            Value::DateTime(date_time) => {
                writeln!(fmt, "<dateTime.iso8601>{}</dateTime.iso8601>", format_datetime(&date_time))?;
            }
            Value::Base64(ref data) => {
                writeln!(fmt, "<base64>{}</base64>", encode(data))?;
            }
            Value::Struct(ref map) => {
                writeln!(fmt, "<struct>")?;
                for (ref name, ref value) in map {
                    writeln!(fmt, "<member>")?;
                    writeln!(fmt, "<name>{}</name>", escape_xml(name))?;
                    value.write_as_xml(fmt)?;
                    writeln!(fmt, "</member>")?;
                }
                writeln!(fmt, "</struct>")?;
            }
            Value::Array(ref array) => {
                writeln!(fmt, "<array>")?;
                writeln!(fmt, "<data>")?;
                for value in array {
                    value.write_as_xml(fmt)?;
                }
                writeln!(fmt, "</data>")?;
                writeln!(fmt, "</array>")?;
            }
            Value::Nil => {
                writeln!(fmt, "<nil/>")?;
            }
        }

        writeln!(fmt, "</value>")?;
        Ok(())
    }

    /// Returns an inner struct or array value indexed by `index`.
    ///
    /// Returns `None` if the member doesn't exist or `self` is neither a struct nor an array.
    ///
    /// You can also use Rust's square-bracket indexing syntax to perform this operation if you want
    /// a default value instead of an `Option`. Refer to the top-level [examples](#examples) for
    /// details.
    pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
        index.get(self)
    }

    /// If the `Value` is a normal integer (`Value::Int`), returns associated value. Returns `None`
    /// otherwise.
    ///
    /// In particular, `None` is also returned if `self` is a `Value::Int64`. Use [`as_i64`] to
    /// handle this case.
    ///
    /// [`as_i64`]: #method.as_i64
    pub fn as_i32(&self) -> Option<i32> {
        match *self {
            Value::Int(i) => Some(i),
            _ => None
        }
    }

    /// If the `Value` is an integer, returns associated value. Returns `None` otherwise.
    ///
    /// This works with both `Value::Int` and `Value::Int64`.
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Int(i) => Some(i64::from(i)),
            Value::Int64(i) => Some(i),
            _ => None
        }
    }

    /// If the `Value` is a boolean, returns associated value. Returns `None` otherwise.
    pub fn as_bool(&self) -> Option<bool> {
        match *self {
            Value::Bool(b) => Some(b),
            _ => None
        }
    }

    /// If the `Value` is a string, returns associated value. Returns `None` otherwise.
    pub fn as_str(&self) -> Option<&str> {
        match *self {
            Value::String(ref s) => Some(s),
            _ => None
        }
    }

    /// If the `Value` is a floating point number, returns associated value. Returns `None`
    /// otherwise.
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::Double(d) => Some(d),
            _ => None
        }
    }

    /// If the `Value` is a date/time, returns associated value. Returns `None` otherwise.
    pub fn as_datetime(&self) -> Option<DateTime> {
        match *self {
            Value::DateTime(dt) => Some(dt),
            _ => None
        }
    }

    /// If the `Value` is base64 binary data, returns associated value. Returns `None` otherwise.
    pub fn as_bytes(&self) -> Option<&[u8]> {
        match *self {
            Value::Base64(ref data) => Some(data),
            _ => None
        }
    }

    /// If the `Value` is a struct, returns associated map. Returns `None` otherwise.
    pub fn as_struct(&self) -> Option<&BTreeMap<String, Value>> {
        match *self {
            Value::Struct(ref map) => Some(map),
            _ => None
        }
    }

    /// If the `Value` is an array, returns associated slice. Returns `None` otherwise.
    pub fn as_array(&self) -> Option<&[Value]> {
        match *self {
            Value::Array(ref array) => Some(array),
            _ => None
        }
    }
}

impl From<i32> for Value {
    fn from(other: i32) -> Self {
        Value::Int(other)
    }
}

impl From<i64> for Value {
    fn from(other: i64) -> Self {
        Value::Int64(other)
    }
}

impl From<bool> for Value {
    fn from(other: bool) -> Self {
        Value::Bool(other)
    }
}

impl From<String> for Value {
    fn from(other: String) -> Self {
        Value::String(other)
    }
}

impl<'a> From<&'a str> for Value {
    fn from(other: &'a str) -> Self {
        Value::String(other.to_string())
    }
}

impl From<f64> for Value {
    fn from(other: f64) -> Self {
        Value::Double(other)
    }
}

impl From<DateTime> for Value {
    fn from(other: DateTime) -> Self {
        Value::DateTime(other)
    }
}

impl From<Vec<u8>> for Value {
    fn from(other: Vec<u8>) -> Self {
        Value::Base64(other)
    }
}

mod sealed {
    /// A trait that is only nameable (and thus implementable) inside this crate.
    pub trait Sealed {}
    impl<T: ? Sized> Sealed for T {}
}

/// A type that can be used to index into a [`Value`].
///
/// You can use Rust's regular indexing syntax to access components of [`Value`]s. Refer to the
/// examples on [`Value`] for details.
///
/// This trait can not be implemented by custom types.
///
/// [`Value`]: enum.Value.html
pub trait Index: sealed::Sealed {
    /// Gets an inner value of a given value represented by self.
    #[doc(hidden)]
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value>;
}

impl Index for str {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for String {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Struct(ref map) = *value {
            map.get(self)
        } else {
            None
        }
    }
}

impl Index for usize {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        if let Value::Array(ref array) = *value {
            array.get(*self)
        } else {
            None
        }
    }
}

impl<'a, I> Index for &'a I where I: Index + ?Sized {
    fn get<'v>(&self, value: &'v Value) -> Option<&'v Value> {
        (*self).get(value)
    }
}

impl<I> ::std::ops::Index<I> for Value where I: Index {
    type Output = Value;
    fn index(&self, index: I) -> &Self::Output {
        index.get(self).unwrap_or(&Value::Nil)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::str;
    use std::collections::BTreeMap;

    #[test]
    fn escapes_strings() {
        let mut output: Vec<u8> = Vec::new();

        Value::from("<xml> string").write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<string><xml>&nbsp;string</string>\n</value>\n");
    }

    #[test]
    fn escapes_struct_member_names() {
        let mut output: Vec<u8> = Vec::new();
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("x&<x".to_string(), Value::from(true));

        Value::Struct(map).write_as_xml(&mut output).unwrap();
        assert_eq!(str::from_utf8(&output).unwrap(), "<value>\n<struct>\n<member>\n<name>x&<x</name>\n<value>\n<boolean>1</boolean>\n</value>\n</member>\n</struct>\n</value>\n");
    }

    #[test]
    fn access_nested_values() {
        let mut map: BTreeMap<String, Value> = BTreeMap::new();
        map.insert("name".to_string(), Value::from("John Doe"));
        map.insert("age".to_string(), Value::from(37));
        map.insert("children".to_string(), Value::Array(vec![Value::from("Mark"), Value::from("Jennyfer")]));
        let value = Value::Struct(map);

        assert_eq!(value.get("name"), Some(&Value::from("John Doe")));
        assert_eq!(value.get("age"), Some(&Value::from(37)));
        assert_eq!(value.get("birthdate"), None);
        assert_eq!(Value::Nil.get("age"), None);
        assert_eq!(value["name"], Value::from("John Doe"));
        assert_eq!(value["age"], Value::from(37));
        assert_eq!(value["birthdate"], Value::Nil);
        assert_eq!(Value::Nil["age"], Value::Nil);
        assert_eq!(value["children"][0], Value::from("Mark"));
        assert_eq!(value["children"][1], Value::from("Jennyfer"));
        assert_eq!(value["children"][2], Value::Nil);

        assert_eq!(value["age"].as_i32(), Some(37));
        assert_eq!(value["children"][0].as_str(), Some("Mark"));
    }
}
<|endoftext|>


<commit_before>//! Types representing for data which will be retrieved from the driver.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the driver to these types.

use linear_map::LinearMap;
use serde::ser::{Serialize, Serializer};

/// The type which represents the key for maps used throughout the Ardite
/// codebase.
///
/// Functions similarly to an object key in JavaScript.
pub type Key = String;

/// Represents a [JSON pointer][1] to a document property. Examples of a
/// pointer in this context include `/hello/world` or `/a/b/c/d`.
///
/// These pointers are represented as a list of keys.
///
/// [1]: https://duckduckgo.com/?q=json+pointer&atb=v1&ia=about
pub type Pointer = Vec<Key>;

/// Ordered representation of a map of key/value pairs, like a JSON object.
/// Backed by a linear map to maintain order and have high performance for
/// small objects.
// TODO: newtype pattern?
pub type Object = LinearMap<Key, Value>;

/// Ordered array of values, like a JSON array.
// TODO: newtype pattern?
pub type Array = Vec<Value>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
#[derive(PartialEq, Clone, Debug)]
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// An integer numeric value.
  I64(i64),
  /// A floating point numeric value.
  F64(f64),
  /// A list of characters.
  String(String),
  /// A map of key/value pairs.
  Object(Object),
  /// A list of values.
  Array(Array)
}

impl Value {
  /// Gets a value at a specific point. Helpful for retrieving nested values.
  pub fn get(&self, mut pointer: Pointer) -> Option<&Value> {
    match *self {
      Value::Object(ref map) => {
        if pointer.is_empty() {
          Some(self)
        } else if let Some(value) = map.get(&pointer.remove(0)) {
          value.get(pointer)
        } else {
          None
        }
      },
      Value::Array(ref vec) => {
        if pointer.is_empty() {
          Some(self)
        } else if let Some(value) = pointer.remove(0).parse::<usize>().ok().map_or(None, |i| vec.get(i)) {
          value.get(pointer)
        } else {
          None
        }
      },
      _ => if pointer.is_empty() { Some(self) } else { None }
    }
  }

  /// Converts a value into a JSON string for distribution.
  pub fn to_json(&self) -> String {
    match *self {
      Value::Null => "null".to_owned(),
      Value::Boolean(value) => if value { "true".to_owned() } else { "false".to_owned() },
      Value::I64(value) => value.to_string(),
      Value::F64(value) => value.to_string(),
      Value::String(ref value) => "\"".to_owned() + &escape_string_for_json(value) + "\"",
      Value::Object(ref map) => {
        let mut json = "{".to_owned();
        for (key, value) in map {
          json.push_str("\"");
          json.push_str(&escape_string_for_json(key));
          json.push_str("\":");
          json.push_str(&value.to_json());
          json.push_str(",");
        }
        // Remove the last comma.
        json.pop();
        json.push_str("}");
        json
      },
      Value::Array(ref vec) => {
        let mut json = "[".to_owned();
        for item in vec {
          json.push_str(&item.to_json());
          json.push_str(",");
        }
        // Remove the last comma.
        json.pop();
        json.push_str("]");
        json
      }
    }
  }
}

impl Serialize for Value {
  #[inline]
  fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
    match *self {
      Value::Null => serializer.serialize_unit(),
      Value::Boolean(value) => serializer.serialize_bool(value),
      Value::I64(value) => serializer.serialize_i64(value),
      Value::F64(value) => serializer.serialize_f64(value),
      Value::String(ref value) => serializer.serialize_str(&value),
      Value::Array(ref value) => value.serialize(serializer),
      Value::Object(ref value) => value.serialize(serializer)
    }
  }
}

impl<V> From<Option<V>> for Value where V: Into<Value> {
  fn from(option: Option<V>) -> Self {
    match option {
      None => Value::Null,
      Some(value) => value.into()
    }
  }
}

impl From<bool> for Value {
  fn from(boolean: bool) -> Self {
    Value::Boolean(boolean)
  }
}

impl From<i64> for Value {
  fn from(number: i64) -> Self {
    Value::I64(number)
  }
}

impl From<f64> for Value {
  fn from(number: f64) -> Self {
    Value::F64(number)
  }
}

impl From<String> for Value {
  fn from(string: String) -> Self {
    Value::String(string)
  }
}

impl<'a> From<&'a str> for Value {
  fn from(string: &'a str) -> Self {
    Value::from(string.to_owned())
  }
}

/// Takes a string and escapes it for use within a JSON encoded object. Read,
/// inside quotes.
fn escape_string_for_json(string: &str) -> String {
  string.replace("\"", "\\\"").replace("\n", "\\n")
}

/// An iterator of values. Used by drivers to convert their own iterator
/// implementations into a single type.
pub struct ValueIter<'a> {
  iter: Box<Iterator<Item=Value> + 'a>
}

impl<'a> ValueIter<'a> {
  /// Create a new value iterator.
  pub fn new<I>(iter: I) -> Self where I: Iterator<Item=Value> + 'a {
    ValueIter {
      iter: Box::new(iter)
    }
  }
}

impl<'a> Iterator for ValueIter<'a> {
  type Item = Value;

  #[inline]
  fn next(&mut self) -> Option<Value> {
    self.iter.next()
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn test_get_primitive() {
    assert_eq!(value!().get(point![]).cloned(), Some(value!()));
    assert_eq!(value!().get(point!["hello"]).cloned(), None);
    assert_eq!(value!().get(point!["a", "b", "c", "d", "e"]).cloned(), None);
    assert_eq!(value!(true).get(point![]).cloned(), Some(value!(true)));
    assert_eq!(value!(true).get(point!["hello"]).cloned(), None);
    assert_eq!(value!(36).get(point![]).cloned(), Some(value!(36)));
    assert_eq!(value!(36).get(point!["hello"]).cloned(), None);
    assert_eq!(value!("world").get(point![]).cloned(), Some(value!("world")));
    assert_eq!(value!("world").get(point!["hello"]).cloned(), None);
  }

  #[test]
  fn test_get_object() {
    let object = value!({
      "hello" => true,
      "world" => 8,
      "yolo" => "swag",
      "5" => (),
      "moon" => {
        "hello" => "yoyo"
      }
    });
    assert_eq!(object.get(point![]).cloned(), Some(object.clone()));
    assert_eq!(object.get(point!["hello"]).cloned(), Some(value!(true)));
    assert_eq!(object.get(point!["yolo"]).cloned(), Some(value!("swag")));
    assert_eq!(object.get(point!["5"]).cloned(), Some(value!()));
    assert_eq!(object.get(point!["world", "hello"]).cloned(), None);
    assert_eq!(object.get(point!["moon", "hello"]).cloned(), Some(value!("yoyo")));
    assert_eq!(object.get(point!["moon", "nope"]).cloned(), None);
  }

  #[test]
  fn test_get_array() {
    let array = value!([
      false,
      64,
      {
        "hello" => true,
        "world" => false,
        "moon" => {
          "goodbye" => "yoyo"
        }
      },
      [[1, 2, 3], 4, 5 ]
    ]);
    assert_eq!(array.get(point![]).cloned(), Some(array.clone()));
    assert_eq!(array.get(point!["0"]).cloned(), Some(value!(false)));
    assert_eq!(array.get(point!["1"]).cloned(), Some(value!(64)));
    assert_eq!(array.get(point!["2", "hello"]).cloned(), Some(value!(true)));
    assert_eq!(array.get(point!["2", "moon", "goodbye"]).cloned(), Some(value!("yoyo")));
    assert_eq!(array.get(point!["length"]).cloned(), None);
    assert_eq!(array.get(point!["3", "0", "1"]).cloned(), Some(value!(2)));
  }

  #[test]
  fn test_to_json() {
    assert_eq!(&value!().to_json(), "null");
    assert_eq!(&value!(true).to_json(), "true");
    assert_eq!(&value!(false).to_json(), "false");
    assert_eq!(&value!(7).to_json(), "7");
    assert_eq!(&value!(6.667).to_json(), "6.667");
    assert_eq!(&value!("Hello,\n\"world\"!").to_json(), r#""Hello,\n\"world\"!""#);
    assert_eq!(&value!({
      "hello" => "world",
      "foo" => true,
      "null" => (),
      "goodbye" => {
        "moon" => 2
      }
    }).to_json(), r#"{"hello":"world","foo":true,"null":null,"goodbye":{"moon":2}}"#);
    assert_eq!(
      &value!(["world", 3.333, { "hello" => "world" }, (), (), [1, 2, 3], ()]).to_json(),
      r#"["world",3.333,{"hello":"world"},null,null,[1,2,3],null]"#
    );
  }
}
<commit_msg>feat(value): implement deserialize for value<commit_after>//! Types representing for data which will be retrieved from the driver.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the driver to these types.

use linear_map::LinearMap;
use linear_map::serde::LinearMapVisitor;
use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error as DeError, Visitor, SeqVisitor, MapVisitor};
use serde::de::impls::VecVisitor;

/// The type which represents the key for maps used throughout the Ardite
/// codebase.
///
/// Functions similarly to an object key in JavaScript.
pub type Key = String;

/// Represents a [JSON pointer][1] to a document property. Examples of a
/// pointer in this context include `/hello/world` or `/a/b/c/d`.
///
/// These pointers are represented as a list of keys.
///
/// [1]: https://duckduckgo.com/?q=json+pointer&atb=v1&ia=about
pub type Pointer = Vec<Key>;

/// Ordered representation of a map of key/value pairs, like a JSON object.
/// Backed by a linear map to maintain order and have high performance for
/// small objects.
// TODO: newtype pattern?
pub type Object = LinearMap<Key, Value>;

/// Ordered array of values, like a JSON array.
// TODO: newtype pattern?
pub type Array = Vec<Value>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
#[derive(PartialEq, Clone, Debug)]
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// An integer numeric value.
  I64(i64),
  /// A floating point numeric value.
  F64(f64),
  /// A list of characters.
  String(String),
  /// A map of key/value pairs.
  Object(Object),
  /// A list of values.
  Array(Array)
}

impl Value {
  /// Gets a value at a specific point. Helpful for retrieving nested values.
  pub fn get(&self, mut pointer: Pointer) -> Option<&Value> {
    match *self {
      Value::Object(ref map) => {
        if pointer.is_empty() {
          Some(self)
        } else if let Some(value) = map.get(&pointer.remove(0)) {
          value.get(pointer)
        } else {
          None
        }
      },
      Value::Array(ref vec) => {
        if pointer.is_empty() {
          Some(self)
        } else if let Some(value) = pointer.remove(0).parse::<usize>().ok().map_or(None, |i| vec.get(i)) {
          value.get(pointer)
        } else {
          None
        }
      },
      _ => if pointer.is_empty() { Some(self) } else { None }
    }
  }

  /// Converts a value into a JSON string for distribution.
  pub fn to_json(&self) -> String {
    match *self {
      Value::Null => "null".to_owned(),
      Value::Boolean(value) => if value { "true".to_owned() } else { "false".to_owned() },
      Value::I64(value) => value.to_string(),
      Value::F64(value) => value.to_string(),
      Value::String(ref value) => "\"".to_owned() + &escape_string_for_json(value) + "\"",
      Value::Object(ref map) => {
        let mut json = "{".to_owned();
        for (key, value) in map {
          json.push_str("\"");
          json.push_str(&escape_string_for_json(key));
          json.push_str("\":");
          json.push_str(&value.to_json());
          json.push_str(",");
        }
        // Remove the last comma.
        json.pop();
        json.push_str("}");
        json
      },
      Value::Array(ref vec) => {
        let mut json = "[".to_owned();
        for item in vec {
          json.push_str(&item.to_json());
          json.push_str(",");
        }
        // Remove the last comma.
        json.pop();
        json.push_str("]");
        json
      }
    }
  }
}

impl Serialize for Value {
  #[inline]
  fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error> where S: Serializer {
    match *self {
      Value::Null => serializer.serialize_unit(),
      Value::Boolean(value) => serializer.serialize_bool(value),
      Value::I64(value) => serializer.serialize_i64(value),
      Value::F64(value) => serializer.serialize_f64(value),
      Value::String(ref value) => serializer.serialize_str(&value),
      Value::Array(ref value) => value.serialize(serializer),
      Value::Object(ref value) => value.serialize(serializer)
    }
  }
}

impl Deserialize for Value {
  #[inline]
  fn deserialize<D>(deserializer: &mut D) -> Result<Value, D::Error> where D: Deserializer {
    struct ValueVisitor;

    impl Visitor for ValueVisitor {
      type Value = Value;

      #[inline] fn visit_bool<E>(&mut self, value: bool) -> Result<Value, E> { Ok(Value::Boolean(value)) }
      #[inline] fn visit_i64<E>(&mut self, value: i64) -> Result<Value, E> { Ok(Value::I64(value)) }
      #[inline] fn visit_f64<E>(&mut self, value: f64) -> Result<Value, E> { Ok(Value::F64(value)) }
      #[inline] fn visit_str<E>(&mut self, value: &str) -> Result<Value, E> where E: DeError { self.visit_string(value.to_owned()) }
      #[inline] fn visit_string<E>(&mut self, value: String) -> Result<Value, E> { Ok(Value::String(value)) }
      #[inline] fn visit_none<E>(&mut self) -> Result<Value, E> { Ok(Value::Null) }
      #[inline] fn visit_some<D>(&mut self, deserializer: &mut D) -> Result<Value, D::Error> where D: Deserializer { Deserialize::deserialize(deserializer) }
      #[inline] fn visit_unit<E>(&mut self) -> Result<Value, E> { Ok(Value::Null) }
      #[inline] fn visit_seq<V>(&mut self, visitor: V) -> Result<Value, V::Error> where V: SeqVisitor { let values = try!(VecVisitor::new().visit_seq(visitor)); Ok(Value::Array(values)) }
      #[inline] fn visit_map<V>(&mut self, visitor: V) -> Result<Value, V::Error> where V: MapVisitor { let values = try!(LinearMapVisitor::new().visit_map(visitor)); Ok(Value::Object(values)) }
    }

    deserializer.deserialize(ValueVisitor)
  }
}

impl<V> From<Option<V>> for Value where V: Into<Value> {
  fn from(option: Option<V>) -> Self {
    match option {
      None => Value::Null,
      Some(value) => value.into()
    }
  }
}

impl From<bool> for Value {
  fn from(boolean: bool) -> Self {
    Value::Boolean(boolean)
  }
}

impl From<i64> for Value {
  fn from(number: i64) -> Self {
    Value::I64(number)
  }
}

impl From<f64> for Value {
  fn from(number: f64) -> Self {
    Value::F64(number)
  }
}

impl From<String> for Value {
  fn from(string: String) -> Self {
    Value::String(string)
  }
}

impl<'a> From<&'a str> for Value {
  fn from(string: &'a str) -> Self {
    Value::from(string.to_owned())
  }
}

/// Takes a string and escapes it for use within a JSON encoded object. Read,
/// inside quotes.
fn escape_string_for_json(string: &str) -> String {
  string.replace("\"", "\\\"").replace("\n", "\\n")
}

/// An iterator of values. Used by drivers to convert their own iterator
/// implementations into a single type.
pub struct ValueIter<'a> {
  iter: Box<Iterator<Item=Value> + 'a>
}

impl<'a> ValueIter<'a> {
  /// Create a new value iterator.
  pub fn new<I>(iter: I) -> Self where I: Iterator<Item=Value> + 'a {
    ValueIter {
      iter: Box::new(iter)
    }
  }
}

impl<'a> Iterator for ValueIter<'a> {
  type Item = Value;

  #[inline]
  fn next(&mut self) -> Option<Value> {
    self.iter.next()
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn test_get_primitive() {
    assert_eq!(value!().get(point![]).cloned(), Some(value!()));
    assert_eq!(value!().get(point!["hello"]).cloned(), None);
    assert_eq!(value!().get(point!["a", "b", "c", "d", "e"]).cloned(), None);
    assert_eq!(value!(true).get(point![]).cloned(), Some(value!(true)));
    assert_eq!(value!(true).get(point!["hello"]).cloned(), None);
    assert_eq!(value!(36).get(point![]).cloned(), Some(value!(36)));
    assert_eq!(value!(36).get(point!["hello"]).cloned(), None);
    assert_eq!(value!("world").get(point![]).cloned(), Some(value!("world")));
    assert_eq!(value!("world").get(point!["hello"]).cloned(), None);
  }

  #[test]
  fn test_get_object() {
    let object = value!({
      "hello" => true,
      "world" => 8,
      "yolo" => "swag",
      "5" => (),
      "moon" => {
        "hello" => "yoyo"
      }
    });
    assert_eq!(object.get(point![]).cloned(), Some(object.clone()));
    assert_eq!(object.get(point!["hello"]).cloned(), Some(value!(true)));
    assert_eq!(object.get(point!["yolo"]).cloned(), Some(value!("swag")));
    assert_eq!(object.get(point!["5"]).cloned(), Some(value!()));
    assert_eq!(object.get(point!["world", "hello"]).cloned(), None);
    assert_eq!(object.get(point!["moon", "hello"]).cloned(), Some(value!("yoyo")));
    assert_eq!(object.get(point!["moon", "nope"]).cloned(), None);
  }

  #[test]
  fn test_get_array() {
    let array = value!([
      false,
      64,
      {
        "hello" => true,
        "world" => false,
        "moon" => {
          "goodbye" => "yoyo"
        }
      },
      [[1, 2, 3], 4, 5 ]
    ]);
    assert_eq!(array.get(point![]).cloned(), Some(array.clone()));
    assert_eq!(array.get(point!["0"]).cloned(), Some(value!(false)));
    assert_eq!(array.get(point!["1"]).cloned(), Some(value!(64)));
    assert_eq!(array.get(point!["2", "hello"]).cloned(), Some(value!(true)));
    assert_eq!(array.get(point!["2", "moon", "goodbye"]).cloned(), Some(value!("yoyo")));
    assert_eq!(array.get(point!["length"]).cloned(), None);
    assert_eq!(array.get(point!["3", "0", "1"]).cloned(), Some(value!(2)));
  }

  #[test]
  fn test_to_json() {
    assert_eq!(&value!().to_json(), "null");
    assert_eq!(&value!(true).to_json(), "true");
    assert_eq!(&value!(false).to_json(), "false");
    assert_eq!(&value!(7).to_json(), "7");
    assert_eq!(&value!(6.667).to_json(), "6.667");
    assert_eq!(&value!("Hello,\n\"world\"!").to_json(), r#""Hello,\n\"world\"!""#);
    assert_eq!(&value!({
      "hello" => "world",
      "foo" => true,
      "null" => (),
      "goodbye" => {
        "moon" => 2
      }
    }).to_json(), r#"{"hello":"world","foo":true,"null":null,"goodbye":{"moon":2}}"#);
    assert_eq!(
      &value!(["world", 3.333, { "hello" => "world" }, (), (), [1, 2, 3], ()]).to_json(),
      r#"["world",3.333,{"hello":"world"},null,null,[1,2,3],null]"#
    );
  }
}
<|endoftext|>


<commit_before>use libc::{c_char, c_uint, c_int};
use ffi::prelude::LLVMValueRef;
use ffi::{core, LLVMAttribute};
use std::ffi::CString;
use std::{fmt, mem, ptr};
use std::ops::{Deref, Index};
use block::BasicBlock;
use context::{Context, GetContext};
use ty::{FunctionType, Type};
use util::{self, CastFrom};

/// A typed value that can be used as an operand in instructions.
pub struct Value;
native_ref!(&Value = LLVMValueRef);
impl Value {
    /// Create a new constant struct from the values given.
    pub fn new_struct<'a>(context: &'a Context, vals: &[&'a Value], packed: bool) -> &'a Value {
        unsafe { core::LLVMConstStructInContext(context.into(), vals.as_ptr() as *mut LLVMValueRef, vals.len() as c_uint, packed as c_int) }.into()
    }
    /// Create a new constant vector from the values given.
    pub fn new_vector<'a>(vals: &[&'a Value]) -> &'a Value {
        unsafe { core::LLVMConstVector(vals.as_ptr() as *mut LLVMValueRef, vals.len() as c_uint).into() }
    }
    /// Create a new constant C string from the text given.
    pub fn new_string<'a>(context: &'a Context, text: &str, rust_style: bool) -> &'a Value {
        unsafe {
            let ptr = text.as_ptr() as *const c_char;
            let len = text.len() as c_uint;
            core::LLVMConstStringInContext(context.into(), ptr, len, rust_style as c_int).into()
        }
    }
    /// Create a new constant undefined value of the given type.
    pub fn new_undef<'a>(ty: &'a Type) -> &'a Value {
        unsafe { core::LLVMGetUndef(ty.into()).into() }
    }
    /// Returns the name of this value, or `None` if it lacks a name
    pub fn get_name(&self) -> Option<&str> {
        unsafe {
            let c_name = core::LLVMGetValueName(self.into());
            util::to_null_str(c_name as *mut i8)
        }
    }
    /// Sets the name of this value
    pub fn set_name(&self, name: &str) {
        let c_name = CString::new(name).unwrap();
        unsafe {
            core::LLVMSetValueName(self.into(), c_name.as_ptr())
        }
    }
    /// Returns the type of this value
    pub fn get_type(&self) -> &Type {
        unsafe { core::LLVMTypeOf(self.into()) }.into()
    }
}

pub struct GlobalValue;
native_ref!(&GlobalValue = LLVMValueRef);
deref!(GlobalValue, Value);

impl GlobalValue
{
	/// Sets the initial value for this global.
	pub fn set_initializer(&self, value: &Value)
	{
	  unsafe { core::LLVMSetInitializer(self.into(), value.into()) }
	}

	/// Gets the initial value for this global.
	pub fn get_initializer(&self) -> &Value
	{
	  unsafe { core::LLVMGetInitializer(self.into()) }.into()
	}
}

impl CastFrom for GlobalValue
{
  type From = Value;

  fn cast<'a>(val: &'a Value) -> Option<&'a GlobalValue>
  {
    let gv = unsafe { core::LLVMIsAGlobalValue(val.into()) };
    if gv == ptr::null_mut() {
      None
    } else {
      Some(gv.into())
    }
 }
}

/// Comparative operations on values.
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Predicate {
    Equal,
    NotEqual,
    GreaterThan,
    GreaterThanOrEqual,
    LessThan,
    LessThanOrEqual
}
/// A function argument.
pub struct Arg;
native_ref!(&Arg = LLVMValueRef);
impl Deref for Arg {
    type Target = Value;
    fn deref(&self) -> &Value {
        unsafe { mem::transmute(self) }
    }
}
impl Arg {
    /// Add the attribute given to this argument.
    pub fn add_attribute(&self, attr: Attribute) {
        unsafe { core::LLVMAddAttribute(self.into(), attr.into()) }
    }
    /// Add all the attributes given to this argument.
    pub fn add_attributes(&self, attrs: &[Attribute]) {
        let mut sum = LLVMAttribute::empty();
        for attr in attrs {
            let attr:LLVMAttribute = (*attr).into();
            sum = sum | attr;
        }
        unsafe { core::LLVMAddAttribute(self.into(), sum.into()) }
    }
    /// Returns true if this argument has the attribute given.
    pub fn has_attribute(&self, attr: Attribute) -> bool {
        unsafe {
            let other = core::LLVMGetAttribute(self.into());
            other.contains(attr.into())
        }
    }
    /// Returns true if this argument has all the attributes given.
    pub fn has_attributes(&self, attrs: &[Attribute]) -> bool {
        unsafe {
            let other = core::LLVMGetAttribute(self.into());
            for &attr in attrs {
                if !other.contains(attr.into()) {
                    return false;
                }
            }
            return true;
        }
    }
    /// Remove an attribute from this argument.
    pub fn remove_attribute(&self, attr: Attribute) {
        unsafe { core::LLVMRemoveAttribute(self.into(), attr.into()) }
    }
}
/// A function that can be called and contains blocks.
pub struct Function;
native_ref!(&Function = LLVMValueRef);
impl Deref for Function {
    type Target = Value;
    fn deref(&self) -> &Value {
        unsafe { mem::transmute(self) }
    }
}
impl Index<usize> for Function {
    type Output = Arg;
    fn index(&self, index: usize) -> &Arg {
        unsafe {
            if index < core::LLVMCountParams(self.into()) as usize {
                core::LLVMGetParam(self.into(), index as c_uint).into()
            } else {
                panic!("no such index {} on {:?}", index, self.get_type())
            }
        }
    }
}
impl CastFrom for Function {
    type From = Value;
    fn cast<'a>(val: &'a Value) -> Option<&'a Function> {
        let ty = val.get_type();
        let mut is_func = ty.is_function();
        if let Some(elem) = ty.get_element() {
            is_func = is_func || elem.is_function()
        }
        if is_func {
            Some(unsafe { mem::transmute(val) })
        } else {
            None
        }
    }
}
impl Function {
    /// Add a basic block with the name given to the function and return it.
    pub fn append<'a>(&'a self, name: &str) -> &'a BasicBlock {
        util::with_cstr(name, |ptr| unsafe {
            core::LLVMAppendBasicBlockInContext(self.get_context().into(), self.into(), ptr).into()
        })
    }
    /// Returns the entry block of this function or `None` if there is none.
    pub fn get_entry(&self) -> Option<&BasicBlock> {
        unsafe { mem::transmute(core::LLVMGetEntryBasicBlock(self.into())) }
    }
    /// Returns the name of this function.
    pub fn get_name(&self) -> &str {
        unsafe {
            let c_name = core::LLVMGetValueName(self.into());
            util::to_str(c_name as *mut i8)
        }
    }
    /// Returns the function signature representing this function's signature.
    pub fn get_signature(&self) -> &FunctionType {
        unsafe {
            let ty = core::LLVMTypeOf(self.into());
            core::LLVMGetElementType(ty).into()
        }
    }
    /// Add the attribute given to this function.
    pub fn add_attribute(&self, attr: Attribute) {
        unsafe { core::LLVMAddFunctionAttr(self.into(), attr.into()) }
    }
    /// Add all the attributes given to this function.
    pub fn add_attributes(&self, attrs: &[Attribute]) {
        let mut sum = LLVMAttribute::empty();
        for attr in attrs {
            let attr:LLVMAttribute = (*attr).into();
            sum = sum | attr;
        }
        unsafe { core::LLVMAddFunctionAttr(self.into(), sum.into()) }
    }
    /// Returns true if the attribute given is set in this function.
    pub fn has_attribute(&self, attr: Attribute) -> bool {
        unsafe {
            let other = core::LLVMGetFunctionAttr(self.into());
            other.contains(attr.into())
        }
    }
    /// Returns true if all the attributes given is set in this function.
    pub fn has_attributes(&self, attrs: &[Attribute]) -> bool {
        unsafe {
            let other = core::LLVMGetFunctionAttr(self.into());
            for &attr in attrs {
                if !other.contains(attr.into()) {
                    return false;
                }
            }
            return true;
        }
    }
    /// Remove the attribute given from this function.
    pub fn remove_attribute(&self, attr: Attribute) {
        unsafe { core::LLVMRemoveFunctionAttr(self.into(), attr.into()) }
    }
}
impl GetContext for Function {
    fn get_context(&self) -> &Context {
        self.get_type().get_context()
    }
}
/// A way of indicating to LLVM how you want arguments / functions to be handled.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(C)]
pub enum Attribute {
    /// Zero-extended before or after call.
    ZExt =              0b1,
    /// Sign-extended before or after call.
    SExt =              0b10,
    /// Mark the function as not returning.
    NoReturn =          0b100,
    /// Force argument to be passed in register.
    InReg =             0b1000,
    /// Hidden pointer to structure to return.
    StructRet =         0b10000,
    /// Function doesn't unwind stack.
    NoUnwind =          0b100000,
    /// Consider to not alias after call.
    NoAlias =           0b1000000,
    /// Pass structure by value.
    ByVal =             0b10000000,
    /// Nested function static chain.
    Nest =              0b100000000,
    /// Function doesn't access memory.
    ReadNone =          0b1000000000,
    /// Function only reads from memory.
    ReadOnly =          0b10000000000,
    /// Never inline this function.
    NoInline =          0b100000000000,
    /// Always inline this function.
    AlwaysInline =      0b1000000000000,
    /// Optimize this function for size.
    OptimizeForSize =   0b10000000000000,
    /// Stack protection.
    StackProtect =      0b100000000000000,
    /// Stack protection required.
    StackProtectReq =   0b1000000000000000,
    /// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias 0 means unaligned (different from align(1)).
    Alignment =         0b10000000000000000,
    /// Function creates no aliases of pointer.
    NoCapture =         0b100000000000000000,
    /// Disable redzone.
    NoRedZone =         0b1000000000000000000,
    /// Disable implicit float instructions.
    NoImplicitFloat =   0b10000000000000000000,
    /// Naked function.
    Naked =             0b100000000000000000000,
    /// The source language has marked this function as inline.
    InlineHint =        0b1000000000000000000000,
    /// Alignment of stack for function (3 bits) stored as log2 of alignment with +1 bias 0 means unaligned (different from alignstack=(1)).
    StackAlignment =    0b11100000000000000000000000000,
    /// This function returns twice.
    ReturnsTwice =      0b100000000000000000000000000000,
    /// Function must be in unwind table.
    UWTable =           0b1000000000000000000000000000000,
    /// Function is called early/often, so lazy binding isn't effective.
    NonLazyBind =       0b10000000000000000000000000000000
}
impl From<LLVMAttribute> for Attribute {
    fn from(attr: LLVMAttribute) -> Attribute {
        unsafe { mem::transmute(attr) }
    }
}
impl From<Attribute> for LLVMAttribute {
    fn from(attr: Attribute) -> LLVMAttribute {
        unsafe { mem::transmute(attr) }
    }
}
impl GetContext for Value {
    fn get_context(&self) -> &Context {
        self.get_type().get_context()
    }
}
impl_display!(Value, LLVMPrintValueToString);
<commit_msg>Add value iterator.<commit_after>use libc::{c_char, c_uint, c_int};
use ffi::prelude::LLVMValueRef;
use ffi::{core, LLVMAttribute};
use std::ffi::CString;
use std::{fmt, mem, ptr};
use std::ops::{Deref, Index};
use block::BasicBlock;
use context::{Context, GetContext};
use ty::{FunctionType, Type};
use util::{self, CastFrom};

/// A typed value that can be used as an operand in instructions.
pub struct Value;
native_ref!(&Value = LLVMValueRef);
impl Value {
    /// Create a new constant struct from the values given.
    pub fn new_struct<'a>(context: &'a Context, vals: &[&'a Value], packed: bool) -> &'a Value {
        unsafe { core::LLVMConstStructInContext(context.into(), vals.as_ptr() as *mut LLVMValueRef, vals.len() as c_uint, packed as c_int) }.into()
    }
    /// Create a new constant vector from the values given.
    pub fn new_vector<'a>(vals: &[&'a Value]) -> &'a Value {
        unsafe { core::LLVMConstVector(vals.as_ptr() as *mut LLVMValueRef, vals.len() as c_uint).into() }
    }
    /// Create a new constant C string from the text given.
    pub fn new_string<'a>(context: &'a Context, text: &str, rust_style: bool) -> &'a Value {
        unsafe {
            let ptr = text.as_ptr() as *const c_char;
            let len = text.len() as c_uint;
            core::LLVMConstStringInContext(context.into(), ptr, len, rust_style as c_int).into()
        }
    }
    /// Create a new constant undefined value of the given type.
    pub fn new_undef<'a>(ty: &'a Type) -> &'a Value {
        unsafe { core::LLVMGetUndef(ty.into()).into() }
    }
    /// Returns the name of this value, or `None` if it lacks a name
    pub fn get_name(&self) -> Option<&str> {
        unsafe {
            let c_name = core::LLVMGetValueName(self.into());
            util::to_null_str(c_name as *mut i8)
        }
    }
    /// Sets the name of this value
    pub fn set_name(&self, name: &str) {
        let c_name = CString::new(name).unwrap();
        unsafe {
            core::LLVMSetValueName(self.into(), c_name.as_ptr())
        }
    }
    /// Returns the type of this value
    pub fn get_type(&self) -> &Type {
        unsafe { core::LLVMTypeOf(self.into()) }.into()
    }
}

pub struct GlobalValue;
native_ref!(&GlobalValue = LLVMValueRef);
deref!(GlobalValue, Value);

impl GlobalValue
{
	/// Sets the initial value for this global.
	pub fn set_initializer(&self, value: &Value)
	{
	  unsafe { core::LLVMSetInitializer(self.into(), value.into()) }
	}

	/// Gets the initial value for this global.
	pub fn get_initializer(&self) -> &Value
	{
	  unsafe { core::LLVMGetInitializer(self.into()) }.into()
	}
}

impl CastFrom for GlobalValue
{
  type From = Value;

  fn cast<'a>(val: &'a Value) -> Option<&'a GlobalValue>
  {
    let gv = unsafe { core::LLVMIsAGlobalValue(val.into()) };
    if gv == ptr::null_mut() {
      None
    } else {
      Some(gv.into())
    }
 }
}

/// Comparative operations on values.
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum Predicate {
    Equal,
    NotEqual,
    GreaterThan,
    GreaterThanOrEqual,
    LessThan,
    LessThanOrEqual
}
/// A function argument.
pub struct Arg;
native_ref!(&Arg = LLVMValueRef);
impl Deref for Arg {
    type Target = Value;
    fn deref(&self) -> &Value {
        unsafe { mem::transmute(self) }
    }
}
impl Arg {
    /// Add the attribute given to this argument.
    pub fn add_attribute(&self, attr: Attribute) {
        unsafe { core::LLVMAddAttribute(self.into(), attr.into()) }
    }
    /// Add all the attributes given to this argument.
    pub fn add_attributes(&self, attrs: &[Attribute]) {
        let mut sum = LLVMAttribute::empty();
        for attr in attrs {
            let attr:LLVMAttribute = (*attr).into();
            sum = sum | attr;
        }
        unsafe { core::LLVMAddAttribute(self.into(), sum.into()) }
    }
    /// Returns true if this argument has the attribute given.
    pub fn has_attribute(&self, attr: Attribute) -> bool {
        unsafe {
            let other = core::LLVMGetAttribute(self.into());
            other.contains(attr.into())
        }
    }
    /// Returns true if this argument has all the attributes given.
    pub fn has_attributes(&self, attrs: &[Attribute]) -> bool {
        unsafe {
            let other = core::LLVMGetAttribute(self.into());
            for &attr in attrs {
                if !other.contains(attr.into()) {
                    return false;
                }
            }
            return true;
        }
    }
    /// Remove an attribute from this argument.
    pub fn remove_attribute(&self, attr: Attribute) {
        unsafe { core::LLVMRemoveAttribute(self.into(), attr.into()) }
    }
}
/// A function that can be called and contains blocks.
pub struct Function;
native_ref!(&Function = LLVMValueRef);
impl Deref for Function {
    type Target = Value;
    fn deref(&self) -> &Value {
        unsafe { mem::transmute(self) }
    }
}
impl Index<usize> for Function {
    type Output = Arg;
    fn index(&self, index: usize) -> &Arg {
        unsafe {
            if index < core::LLVMCountParams(self.into()) as usize {
                core::LLVMGetParam(self.into(), index as c_uint).into()
            } else {
                panic!("no such index {} on {:?}", index, self.get_type())
            }
        }
    }
}
impl CastFrom for Function {
    type From = Value;
    fn cast<'a>(val: &'a Value) -> Option<&'a Function> {
        let ty = val.get_type();
        let mut is_func = ty.is_function();
        if let Some(elem) = ty.get_element() {
            is_func = is_func || elem.is_function()
        }
        if is_func {
            Some(unsafe { mem::transmute(val) })
        } else {
            None
        }
    }
}
impl Function {
    /// Add a basic block with the name given to the function and return it.
    pub fn append<'a>(&'a self, name: &str) -> &'a BasicBlock {
        util::with_cstr(name, |ptr| unsafe {
            core::LLVMAppendBasicBlockInContext(self.get_context().into(), self.into(), ptr).into()
        })
    }
    /// Returns the entry block of this function or `None` if there is none.
    pub fn get_entry(&self) -> Option<&BasicBlock> {
        unsafe { mem::transmute(core::LLVMGetEntryBasicBlock(self.into())) }
    }
    /// Returns the name of this function.
    pub fn get_name(&self) -> &str {
        unsafe {
            let c_name = core::LLVMGetValueName(self.into());
            util::to_str(c_name as *mut i8)
        }
    }
    /// Returns the function signature representing this function's signature.
    pub fn get_signature(&self) -> &FunctionType {
        unsafe {
            let ty = core::LLVMTypeOf(self.into());
            core::LLVMGetElementType(ty).into()
        }
    }
    /// Add the attribute given to this function.
    pub fn add_attribute(&self, attr: Attribute) {
        unsafe { core::LLVMAddFunctionAttr(self.into(), attr.into()) }
    }
    /// Add all the attributes given to this function.
    pub fn add_attributes(&self, attrs: &[Attribute]) {
        let mut sum = LLVMAttribute::empty();
        for attr in attrs {
            let attr:LLVMAttribute = (*attr).into();
            sum = sum | attr;
        }
        unsafe { core::LLVMAddFunctionAttr(self.into(), sum.into()) }
    }
    /// Returns true if the attribute given is set in this function.
    pub fn has_attribute(&self, attr: Attribute) -> bool {
        unsafe {
            let other = core::LLVMGetFunctionAttr(self.into());
            other.contains(attr.into())
        }
    }
    /// Returns true if all the attributes given is set in this function.
    pub fn has_attributes(&self, attrs: &[Attribute]) -> bool {
        unsafe {
            let other = core::LLVMGetFunctionAttr(self.into());
            for &attr in attrs {
                if !other.contains(attr.into()) {
                    return false;
                }
            }
            return true;
        }
    }
    /// Remove the attribute given from this function.
    pub fn remove_attribute(&self, attr: Attribute) {
        unsafe { core::LLVMRemoveFunctionAttr(self.into(), attr.into()) }
    }
}
impl GetContext for Function {
    fn get_context(&self) -> &Context {
        self.get_type().get_context()
    }
}
/// A way of indicating to LLVM how you want arguments / functions to be handled.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[repr(C)]
pub enum Attribute {
    /// Zero-extended before or after call.
    ZExt =              0b1,
    /// Sign-extended before or after call.
    SExt =              0b10,
    /// Mark the function as not returning.
    NoReturn =          0b100,
    /// Force argument to be passed in register.
    InReg =             0b1000,
    /// Hidden pointer to structure to return.
    StructRet =         0b10000,
    /// Function doesn't unwind stack.
    NoUnwind =          0b100000,
    /// Consider to not alias after call.
    NoAlias =           0b1000000,
    /// Pass structure by value.
    ByVal =             0b10000000,
    /// Nested function static chain.
    Nest =              0b100000000,
    /// Function doesn't access memory.
    ReadNone =          0b1000000000,
    /// Function only reads from memory.
    ReadOnly =          0b10000000000,
    /// Never inline this function.
    NoInline =          0b100000000000,
    /// Always inline this function.
    AlwaysInline =      0b1000000000000,
    /// Optimize this function for size.
    OptimizeForSize =   0b10000000000000,
    /// Stack protection.
    StackProtect =      0b100000000000000,
    /// Stack protection required.
    StackProtectReq =   0b1000000000000000,
    /// Alignment of parameter (5 bits) stored as log2 of alignment with +1 bias 0 means unaligned (different from align(1)).
    Alignment =         0b10000000000000000,
    /// Function creates no aliases of pointer.
    NoCapture =         0b100000000000000000,
    /// Disable redzone.
    NoRedZone =         0b1000000000000000000,
    /// Disable implicit float instructions.
    NoImplicitFloat =   0b10000000000000000000,
    /// Naked function.
    Naked =             0b100000000000000000000,
    /// The source language has marked this function as inline.
    InlineHint =        0b1000000000000000000000,
    /// Alignment of stack for function (3 bits) stored as log2 of alignment with +1 bias 0 means unaligned (different from alignstack=(1)).
    StackAlignment =    0b11100000000000000000000000000,
    /// This function returns twice.
    ReturnsTwice =      0b100000000000000000000000000000,
    /// Function must be in unwind table.
    UWTable =           0b1000000000000000000000000000000,
    /// Function is called early/often, so lazy binding isn't effective.
    NonLazyBind =       0b10000000000000000000000000000000
}
impl From<LLVMAttribute> for Attribute {
    fn from(attr: LLVMAttribute) -> Attribute {
        unsafe { mem::transmute(attr) }
    }
}
impl From<Attribute> for LLVMAttribute {
    fn from(attr: Attribute) -> LLVMAttribute {
        unsafe { mem::transmute(attr) }
    }
}
impl GetContext for Value {
    fn get_context(&self) -> &Context {
        self.get_type().get_context()
    }
}
impl_display!(Value, LLVMPrintValueToString);

pub struct ValueIter<'a> {
  cur : &'a Value,
  step: unsafe extern "C" fn(LLVMValueRef) -> LLVMValueRef,
}

impl<'a> Iterator for ValueIter<'a> {
    type Item = &'a Value;

    fn next(&mut self) -> Option<&'a Value> {
        let old: LLVMValueRef = self.cur.into();
        if !old.is_null() {
            self.cur = unsafe { (self.step)(old) }.into();
            Some(old.into())
        } else {
            None
        }
    }
}

fn iter_functions(module: &::module::Module) -> ValueIter {
	unsafe {
  	ValueIter {
    	cur:  core::LLVMGetFirstFunction(module.into()).into(),
      step: core::LLVMGetNextFunction,
    }
  }
}<|endoftext|>


<commit_before>use crate::io::DecodeError;

pub enum VisitError<E> {
    LazyDecode(DecodeError),
    Custom(E),
}

impl<E: std::fmt::Display> std::fmt::Display for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::fmt::Debug> std::fmt::Debug for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::error::Error> std::error::Error for VisitError<E> {}

pub use wasmbin_derive::WasmbinVisit;
pub trait WasmbinVisit: 'static + Sized {
    fn visit<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        mut f: F,
    ) -> Result<(), VisitError<E>> {
        self.visit_child(&mut f)
    }

    fn visit_mut<'a, T: 'static, E, F: FnMut(&'a mut T) -> Result<(), E>>(
        &'a mut self,
        mut f: F,
    ) -> Result<(), VisitError<E>> {
        self.visit_child_mut(&mut f)
    }

    fn visit_child<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        match std::any::Any::downcast_ref(self) {
            Some(v) => f(v).map_err(VisitError::Custom),
            None => self.visit_children(f),
        }
    }

    fn visit_child_mut<'a, T: 'static, E, F: FnMut(&'a mut T) -> Result<(), E>>(
        &'a mut self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        match std::any::Any::downcast_mut(self) {
            Some(v) => f(unsafe {
                // Working around an apparent bug in NLL: https://github.com/rust-lang/rust/issues/70255
                &mut *(v as *mut _)
            })
            .map_err(VisitError::Custom),
            None => self.visit_children_mut(f),
        }
    }

    fn visit_children<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }

    fn visit_children_mut<'a, T: 'static, E, F: FnMut(&'a mut T) -> Result<(), E>>(
        &'a mut self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }
}
<commit_msg>Add more visitor callback types<commit_after>use crate::io::DecodeError;

pub enum VisitError<E> {
    LazyDecode(DecodeError),
    Custom(E),
}

impl<E: std::fmt::Display> std::fmt::Display for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::fmt::Debug> std::fmt::Debug for VisitError<E> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            VisitError::LazyDecode(err) => err.fmt(f),
            VisitError::Custom(err) => err.fmt(f),
        }
    }
}

impl<E: std::error::Error> std::error::Error for VisitError<E> {}

#[cfg(feature = "nightly")]
pub type NeverError = !;

#[cfg(not(feature = "nightly"))]
pub enum NeverError {}

impl From<VisitError<NeverError>> for DecodeError {
    fn from(err: VisitError<NeverError>) -> Self {
        match err {
            VisitError::Custom(err) => match err {},
            VisitError::LazyDecode(err) => err,
        }
    }
}

pub trait VisitResult {
    type Error;

    fn as_result(self) -> Result<(), Self::Error>;
}

impl VisitResult for () {
    type Error = NeverError;

    fn as_result(self) -> Result<(), Self::Error> {
        Ok(())
    }
}

impl VisitResult for bool {
    type Error = ();

    fn as_result(self) -> Result<(), Self::Error> {
        match self {
            true => Ok(()),
            false => Err(()),
        }
    }
}

impl<E> VisitResult for Result<(), E> {
    type Error = E;

    fn as_result(self) -> Result<(), Self::Error> {
        self
    }
}

pub use wasmbin_derive::WasmbinVisit;
pub trait WasmbinVisit: 'static + Sized {
    fn visit<'a, T: 'static, R: VisitResult, F: FnMut(&'a T) -> R>(
        &'a self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child(&mut move |item| f(item).as_result())
    }

    fn visit_mut<'a, T: 'static, R: VisitResult, F: FnMut(&'a mut T) -> R>(
        &'a mut self,
        mut f: F,
    ) -> Result<(), VisitError<R::Error>> {
        self.visit_child_mut(&mut move |item| f(item).as_result())
    }

    fn visit_child<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        match std::any::Any::downcast_ref(self) {
            Some(v) => f(v).map_err(VisitError::Custom),
            None => self.visit_children(f),
        }
    }

    fn visit_child_mut<'a, T: 'static, E, F: FnMut(&'a mut T) -> Result<(), E>>(
        &'a mut self,
        f: &mut F,
    ) -> Result<(), VisitError<E>> {
        match std::any::Any::downcast_mut(self) {
            Some(v) => f(unsafe {
                // Working around an apparent bug in NLL: https://github.com/rust-lang/rust/issues/70255
                &mut *(v as *mut _)
            })
            .map_err(VisitError::Custom),
            None => self.visit_children_mut(f),
        }
    }

    fn visit_children<'a, T: 'static, E, F: FnMut(&'a T) -> Result<(), E>>(
        &'a self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }

    fn visit_children_mut<'a, T: 'static, E, F: FnMut(&'a mut T) -> Result<(), E>>(
        &'a mut self,
        _f: &mut F,
    ) -> Result<(), VisitError<E>> {
        Ok(())
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate bencher;

extern crate bitwise;

use bencher::Bencher;

use bitwise::word::gcd;

pub fn run_u8_small<F: Fn(u8, u8) -> u8>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u8(0, u8::max_value() / 3,
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

pub fn run_u8_mid<F: Fn(u8, u8) -> u8>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u8(u8::max_value() / 3, u8::max_value() / 3 * 2,
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

pub fn run_u8_large<F: Fn(u8, u8) -> u8>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u8(u8::max_value() / 3 * 2, u8::max_value(),
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

fn u08_small_euclid_recursive(b: &mut Bencher) {
    run_u8_small(b, gcd::euclid::recursive)
}

fn u08_small_euclid_iterative(b: &mut Bencher) {
    run_u8_small(b, gcd::euclid::iterative)
}

fn u08_small_steins_recursive(b: &mut Bencher) {
    run_u8_small(b, gcd::steins::recursive)
}

fn u08_small_steins_iterative(b: &mut Bencher) {
    run_u8_small(b, gcd::steins::iterative)
}

fn u08_small_steins_iterative_xor(b: &mut Bencher) {
    run_u8_small(b, gcd::steins::iterative_xor)
}

benchmark_group!(u08_small_g,
                 u08_small_euclid_recursive,
                 u08_small_euclid_iterative,
                 u08_small_steins_recursive,
                 u08_small_steins_iterative,
                 u08_small_steins_iterative_xor
                 );

fn u08_mid_euclid_recursive(b: &mut Bencher) {
    run_u8_mid(b, gcd::euclid::recursive)
}

fn u08_mid_euclid_iterative(b: &mut Bencher) {
    run_u8_mid(b, gcd::euclid::iterative)
}

fn u08_mid_steins_recursive(b: &mut Bencher) {
    run_u8_mid(b, gcd::steins::recursive)
}

fn u08_mid_steins_iterative(b: &mut Bencher) {
    run_u8_mid(b, gcd::steins::iterative)
}

fn u08_mid_steins_iterative_xor(b: &mut Bencher) {
    run_u8_mid(b, gcd::steins::iterative_xor)
}

benchmark_group!(u08_mid_g,
                 u08_mid_euclid_recursive,
                 u08_mid_euclid_iterative,
                 u08_mid_steins_recursive,
                 u08_mid_steins_iterative,
                 u08_mid_steins_iterative_xor
);

fn u08_large_euclid_recursive(b: &mut Bencher) {
    run_u8_large(b, gcd::euclid::recursive)
}

fn u08_large_euclid_iterative(b: &mut Bencher) {
    run_u8_large(b, gcd::euclid::iterative)
}

fn u08_large_steins_recursive(b: &mut Bencher) {
    run_u8_large(b, gcd::steins::recursive)
}

fn u08_large_steins_iterative(b: &mut Bencher) {
    run_u8_large(b, gcd::steins::iterative)
}

fn u08_large_steins_iterative_xor(b: &mut Bencher) {
    run_u8_large(b, gcd::steins::iterative_xor)
}

benchmark_group!(u08_large_g,
                 u08_large_euclid_recursive,
                 u08_large_euclid_iterative,
                 u08_large_steins_recursive,
                 u08_large_steins_iterative,
                 u08_large_steins_iterative_xor
);

pub fn run_u16_small<F: Fn(u16, u16) -> u16>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u16(0, u16::max_value() / 3,
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

pub fn run_u16_mid<F: Fn(u16, u16) -> u16>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u16(u16::max_value() / 3, u16::max_value() / 3 * 2,
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

pub fn run_u16_large<F: Fn(u16, u16) -> u16>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u16(u16::max_value() / 6 * 5 , u16::max_value(),
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

fn u16_small_euclid_recursive(b: &mut Bencher) {
    run_u16_small(b, gcd::euclid::recursive)
}

fn u16_small_euclid_iterative(b: &mut Bencher) {
    run_u16_small(b, gcd::euclid::iterative)
}

fn u16_small_steins_recursive(b: &mut Bencher) {
    run_u16_small(b, gcd::steins::recursive)
}

fn u16_small_steins_iterative(b: &mut Bencher) {
    run_u16_small(b, gcd::steins::iterative)
}

fn u16_small_steins_iterative_xor(b: &mut Bencher) {
    run_u16_small(b, gcd::steins::iterative_xor)
}

benchmark_group!(u16_small_g,
                 u16_small_euclid_recursive,
                 u16_small_euclid_iterative,
                 u16_small_steins_recursive,
                 u16_small_steins_iterative,
                 u16_small_steins_iterative_xor
                 );

fn u16_mid_euclid_recursive(b: &mut Bencher) {
    run_u16_mid(b, gcd::euclid::recursive)
}

fn u16_mid_euclid_iterative(b: &mut Bencher) {
    run_u16_mid(b, gcd::euclid::iterative)
}

fn u16_mid_steins_recursive(b: &mut Bencher) {
    run_u16_mid(b, gcd::steins::recursive)
}

fn u16_mid_steins_iterative(b: &mut Bencher) {
    run_u16_mid(b, gcd::steins::iterative)
}

fn u16_mid_steins_iterative_xor(b: &mut Bencher) {
    run_u16_mid(b, gcd::steins::iterative_xor)
}

benchmark_group!(u16_mid_g,
                 u16_mid_euclid_recursive,
                 u16_mid_euclid_iterative,
                 u16_mid_steins_recursive,
                 u16_mid_steins_iterative,
                 u16_mid_steins_iterative_xor
);

fn u16_large_euclid_recursive(b: &mut Bencher) {
    run_u16_large(b, gcd::euclid::recursive)
}

fn u16_large_euclid_iterative(b: &mut Bencher) {
    run_u16_large(b, gcd::euclid::iterative)
}

fn u16_large_steins_recursive(b: &mut Bencher) {
    run_u16_large(b, gcd::steins::recursive)
}

fn u16_large_steins_iterative(b: &mut Bencher) {
    run_u16_large(b, gcd::steins::iterative)
}

fn u16_large_steins_iterative_xor(b: &mut Bencher) {
    run_u16_large(b, gcd::steins::iterative_xor)
}

/*
benchmark_group!(u16_large_g,
                 //u16_large_euclid_recursive,
                 //u16_large_euclid_iterative,
                 //u16_large_steins_recursive,
                 //u16_large_steins_iterative,
                 u16_large_steins_iterative_xor
);
*/

benchmark_main!(u08_small_g, u08_mid_g, u08_large_g,
                u16_small_g, u16_mid_g);
<commit_msg>disable expensive benchmarks<commit_after>#[macro_use]
extern crate bencher;

extern crate bitwise;

use bencher::Bencher;

use bitwise::word::gcd;

pub fn run_u8_small<F: Fn(u8, u8) -> u8>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u8(0, u8::max_value() / 3,
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

pub fn run_u8_mid<F: Fn(u8, u8) -> u8>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u8(u8::max_value() / 3, u8::max_value() / 3 * 2,
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

pub fn run_u8_large<F: Fn(u8, u8) -> u8>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u8(u8::max_value() / 3 * 2, u8::max_value(),
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

fn u08_small_euclid_recursive(b: &mut Bencher) {
    run_u8_small(b, gcd::euclid::recursive)
}

fn u08_small_euclid_iterative(b: &mut Bencher) {
    run_u8_small(b, gcd::euclid::iterative)
}

fn u08_small_steins_recursive(b: &mut Bencher) {
    run_u8_small(b, gcd::steins::recursive)
}

fn u08_small_steins_iterative(b: &mut Bencher) {
    run_u8_small(b, gcd::steins::iterative)
}

fn u08_small_steins_iterative_xor(b: &mut Bencher) {
    run_u8_small(b, gcd::steins::iterative_xor)
}

benchmark_group!(u08_small_g,
                 u08_small_euclid_recursive,
                 u08_small_euclid_iterative,
                 u08_small_steins_recursive,
                 u08_small_steins_iterative,
                 u08_small_steins_iterative_xor
                 );

fn u08_mid_euclid_recursive(b: &mut Bencher) {
    run_u8_mid(b, gcd::euclid::recursive)
}

fn u08_mid_euclid_iterative(b: &mut Bencher) {
    run_u8_mid(b, gcd::euclid::iterative)
}

fn u08_mid_steins_recursive(b: &mut Bencher) {
    run_u8_mid(b, gcd::steins::recursive)
}

fn u08_mid_steins_iterative(b: &mut Bencher) {
    run_u8_mid(b, gcd::steins::iterative)
}

fn u08_mid_steins_iterative_xor(b: &mut Bencher) {
    run_u8_mid(b, gcd::steins::iterative_xor)
}

benchmark_group!(u08_mid_g,
                 u08_mid_euclid_recursive,
                 u08_mid_euclid_iterative,
                 u08_mid_steins_recursive,
                 u08_mid_steins_iterative,
                 u08_mid_steins_iterative_xor
);

fn u08_large_euclid_recursive(b: &mut Bencher) {
    run_u8_large(b, gcd::euclid::recursive)
}

fn u08_large_euclid_iterative(b: &mut Bencher) {
    run_u8_large(b, gcd::euclid::iterative)
}

fn u08_large_steins_recursive(b: &mut Bencher) {
    run_u8_large(b, gcd::steins::recursive)
}

fn u08_large_steins_iterative(b: &mut Bencher) {
    run_u8_large(b, gcd::steins::iterative)
}

fn u08_large_steins_iterative_xor(b: &mut Bencher) {
    run_u8_large(b, gcd::steins::iterative_xor)
}

benchmark_group!(u08_large_g,
                 u08_large_euclid_recursive,
                 u08_large_euclid_iterative,
                 u08_large_steins_recursive,
                 u08_large_steins_iterative,
                 u08_large_steins_iterative_xor
);

pub fn run_u16_small<F: Fn(u16, u16) -> u16>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u16(0, u16::max_value() / 3,
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

pub fn run_u16_mid<F: Fn(u16, u16) -> u16>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u16(u16::max_value() / 3, u16::max_value() / 3 * 2,
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

pub fn run_u16_large<F: Fn(u16, u16) -> u16>(b: &mut Bencher, f: F) {
    b.iter(|| gcd::test_util::run_u16(u16::max_value() / 6 * 5 , u16::max_value(),
                                     |x, y| bencher::black_box(f(bencher::black_box(x),
                                                                 bencher::black_box(y)))));
}

fn u16_small_euclid_recursive(b: &mut Bencher) {
    run_u16_small(b, gcd::euclid::recursive)
}

fn u16_small_euclid_iterative(b: &mut Bencher) {
    run_u16_small(b, gcd::euclid::iterative)
}

fn u16_small_steins_recursive(b: &mut Bencher) {
    run_u16_small(b, gcd::steins::recursive)
}

fn u16_small_steins_iterative(b: &mut Bencher) {
    run_u16_small(b, gcd::steins::iterative)
}

fn u16_small_steins_iterative_xor(b: &mut Bencher) {
    run_u16_small(b, gcd::steins::iterative_xor)
}
/*

benchmark_group!(u16_small_g,
                 u16_small_euclid_recursive,
                 u16_small_euclid_iterative,
                 u16_small_steins_recursive,
                 u16_small_steins_iterative,
                 u16_small_steins_iterative_xor
                 );

fn u16_mid_euclid_recursive(b: &mut Bencher) {
    run_u16_mid(b, gcd::euclid::recursive)
}

fn u16_mid_euclid_iterative(b: &mut Bencher) {
    run_u16_mid(b, gcd::euclid::iterative)
}

fn u16_mid_steins_recursive(b: &mut Bencher) {
    run_u16_mid(b, gcd::steins::recursive)
}

fn u16_mid_steins_iterative(b: &mut Bencher) {
    run_u16_mid(b, gcd::steins::iterative)
}

fn u16_mid_steins_iterative_xor(b: &mut Bencher) {
    run_u16_mid(b, gcd::steins::iterative_xor)
}

benchmark_group!(u16_mid_g,
                 u16_mid_euclid_recursive,
                 u16_mid_euclid_iterative,
                 u16_mid_steins_recursive,
                 u16_mid_steins_iterative,
                 u16_mid_steins_iterative_xor
);

fn u16_large_euclid_recursive(b: &mut Bencher) {
    run_u16_large(b, gcd::euclid::recursive)
}

fn u16_large_euclid_iterative(b: &mut Bencher) {
    run_u16_large(b, gcd::euclid::iterative)
}

fn u16_large_steins_recursive(b: &mut Bencher) {
    run_u16_large(b, gcd::steins::recursive)
}

fn u16_large_steins_iterative(b: &mut Bencher) {
    run_u16_large(b, gcd::steins::iterative)
}

fn u16_large_steins_iterative_xor(b: &mut Bencher) {
    run_u16_large(b, gcd::steins::iterative_xor)
}

benchmark_group!(u16_large_g,
                 //u16_large_euclid_recursive,
                 //u16_large_euclid_iterative,
                 //u16_large_steins_recursive,
                 //u16_large_steins_iterative,
                 u16_large_steins_iterative_xor
);
*/

benchmark_main!(u08_small_g, u08_mid_g, u08_large_g,
                u16_small_g, u16_mid_g);
<|endoftext|>


<commit_before>#![feature(test)]

extern crate fft;
extern crate test;

#[bench] fn forward_0004(bencher: &mut test::Bencher) { forward(   4, bencher); }
#[bench] fn forward_0016(bencher: &mut test::Bencher) { forward(  16, bencher); }
#[bench] fn forward_0064(bencher: &mut test::Bencher) { forward(  64, bencher); }
#[bench] fn forward_0256(bencher: &mut test::Bencher) { forward( 256, bencher); }
#[bench] fn forward_1024(bencher: &mut test::Bencher) { forward(1024, bencher); }
#[bench] fn forward_4096(bencher: &mut test::Bencher) { forward(4096, bencher); }

fn forward(size: usize, bencher: &mut test::Bencher) {
    let mut data = vec![fft::c64(42.0, 0.0); size];
    bencher.iter(|| {
        test::black_box(fft::forward(&mut data));
    });
}
<commit_msg>Update the benchmarks<commit_after>#![feature(test)]

extern crate complex;
extern crate fft;
extern crate test;

use complex::c64;
use test::{Bencher, black_box};

#[bench] fn complex_forward_0004(bencher: &mut Bencher) { complex_forward(   4, bencher); }
#[bench] fn complex_forward_0016(bencher: &mut Bencher) { complex_forward(  16, bencher); }
#[bench] fn complex_forward_0064(bencher: &mut Bencher) { complex_forward(  64, bencher); }
#[bench] fn complex_forward_0256(bencher: &mut Bencher) { complex_forward( 256, bencher); }
#[bench] fn complex_forward_1024(bencher: &mut Bencher) { complex_forward(1024, bencher); }
#[bench] fn complex_forward_4096(bencher: &mut Bencher) { complex_forward(4096, bencher); }

fn complex_forward(size: usize, bencher: &mut Bencher) {
    let mut data = vec![c64(42.0, 0.0); size];
    bencher.iter(|| black_box(fft::complex::forward(&mut data)));
}
<|endoftext|>