<commit_before>mod data;

use std::collections::HashMap;
use std::path::Path;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Types {
    pub(crate) ext_by_type: HashMap<String, Vec<String>>,
    type_by_ext: HashMap<String, String>,
}

impl Types {
    pub fn new() -> Result<Types, ()> {
        let mut by_type = HashMap::new();
        let mut by_ext = HashMap::new();
        for (mime_type, exts) in data::MIME_TYPES.iter() {
            by_type.insert(mime_type.to_string(), exts.iter().map(|ext| ext.to_string()).collect());

            for ext in exts.iter() {
                by_ext.insert(ext.to_string(), mime_type.to_string());
            }
        }

        Ok(Types {
            ext_by_type: by_type,
            type_by_ext: by_ext,
        })
    }

    pub fn get_extension<'a>(&'a self, name: &str) -> Option<&'a [String]> {
        self.ext_by_type.get(name).map(|v| &v[..])
    }

    pub fn get_mime_type<'a>(&'a self, ext: &str) -> Option<&'a str> {
        self.type_by_ext.get(ext).map(|v| &v[..])
    }

    pub fn mime_for_path<'a>(&'a self, path: &Path) -> &'a str {
        path.extension()
            .and_then(|s| s.to_str())
            .and_then(|ext| self.get_mime_type(ext))
            .unwrap_or_else(|| "text/plain")
    }
}

#[cfg(test)]
mod test {
    use crate::Types;
    use serde::Deserialize;
    use std::collections::HashMap;
    use std::path::Path;

    static JSON: &str = include_str!("../data/mime.json");

    #[test]
    fn test_against_json_data() {
        let mut deserializer = serde_json::Deserializer::from_str(JSON);
        let deserialized: HashMap<String, Vec<String>> =
            Deserialize::deserialize(&mut deserializer).unwrap();

        let t = Types::new().ok().expect("Types didn't load");
        assert_eq!(t.ext_by_type, deserialized);
    }

    #[test]
    fn test_by_ext() {
        let t = Types::new().ok().expect("Types didn't load");
        assert_eq!(t.get_extension("text/css").unwrap(), ["css".to_string()]);
    }

    #[test]
    fn test_by_type() {
        let t = Types::new().ok().expect("Types didn't load");
        assert_eq!(t.get_mime_type("css"), Some("text/css"));
    }

    #[test]
    fn test_by_path() {
        let t = Types::new().ok().expect("Types didn't load");

        test_path(&t, "foo", "text/plain");
        test_path(&t, "/path/to/foo", "text/plain");
        test_path(&t, "foo.css", "text/css");
        test_path(&t, "/path/to/foo.css", "text/css");
        test_path(&t, "foo.html.css", "text/css");
        test_path(&t, "/path/to/foo.html.css", "text/css");
        test_path(&t, "/path/to.html/foo.css", "text/css");
    }

    fn test_path(types: &Types, path: &str, expected: &str) {
        assert_eq!(types.mime_for_path(Path::new(path)), expected);
    }
}
<commit_msg>Convert to API `&'static str`<commit_after>mod data;

use std::collections::HashMap;
use std::path::Path;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Types {
    pub(crate) ext_by_type: HashMap<&'static str, Vec<&'static str>>,
    type_by_ext: HashMap<&'static str, &'static str>,
}

impl Types {
    pub fn new() -> Result<Types, ()> {
        let mut by_type = HashMap::new();
        let mut by_ext = HashMap::new();
        for (mime_type, exts) in data::MIME_TYPES {
            by_type.insert(*mime_type, exts.iter().map(|ext| *ext).collect());

            for ext in exts.iter() {
                by_ext.insert(*ext, *mime_type);
            }
        }

        Ok(Types {
            ext_by_type: by_type,
            type_by_ext: by_ext,
        })
    }

    pub fn get_extension(&self, name: &str) -> Option<&[&str]> {
        self.ext_by_type.get(name).map(|v| &v[..])
    }

    pub fn get_mime_type(&self, ext: &str) -> Option<&str> {
        self.type_by_ext.get(ext).map(|mime_type| *mime_type)
    }

    pub fn mime_for_path(&self, path: &Path) -> &str {
        path.extension()
            .and_then(|s| s.to_str())
            .and_then(|ext| self.get_mime_type(ext))
            .unwrap_or_else(|| "text/plain")
    }
}

#[cfg(test)]
mod test {
    use crate::Types;
    use serde::Deserialize;
    use std::collections::BTreeMap;
    use std::path::Path;

    static JSON: &str = include_str!("../data/mime.json");

    #[test]
    fn test_against_json_data() {
        let mut deserializer = serde_json::Deserializer::from_str(JSON);
        let deserialized: BTreeMap<String, Vec<String>> =
            Deserialize::deserialize(&mut deserializer).unwrap();

        let t = Types::new().ok().expect("Types didn't load");
        for (mime_type, exts) in deserialized {
            let bundled_exts = t.get_extension(&mime_type).unwrap();
            assert_eq!(bundled_exts, exts);
        }
    }

    #[test]
    fn test_by_ext() {
        let t = Types::new().ok().expect("Types didn't load");
        assert_eq!(t.get_extension("text/css").unwrap(), ["css".to_string()]);
    }

    #[test]
    fn test_by_type() {
        let t = Types::new().ok().expect("Types didn't load");
        assert_eq!(t.get_mime_type("css"), Some("text/css"));
    }

    #[test]
    fn test_by_path() {
        let t = Types::new().ok().expect("Types didn't load");

        test_path(&t, "foo", "text/plain");
        test_path(&t, "/path/to/foo", "text/plain");
        test_path(&t, "foo.css", "text/css");
        test_path(&t, "/path/to/foo.css", "text/css");
        test_path(&t, "foo.html.css", "text/css");
        test_path(&t, "/path/to/foo.html.css", "text/css");
        test_path(&t, "/path/to.html/foo.css", "text/css");
    }

    fn test_path(types: &Types, path: &str, expected: &str) {
        assert_eq!(types.mime_for_path(Path::new(path)), expected);
    }
}
<|endoftext|>


<commit_before><commit_msg>remove lib.rs<commit_after><|endoftext|>


<commit_before>extern crate tokio_core;
extern crate hyper;
extern crate futures;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate quick_error;

use futures::{Future, Stream};
use futures::future::Either;
use hyper::client::{self, HttpConnector};
use tokio_core::reactor::Handle;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Url(error: hyper::error::ParseError) {
            description(error.description())
            display("Unable to parse URL: {}", error)
            from()
            cause(error)
        }
        Hyper(error: hyper::Error) {
            description(error.description())
            display("Unable to perform HTTP request: {}", error)
            from()
            cause(error)
        }
        Serde(error: serde_json::Error) {
            description(error.description())
            display("Unable to deserialize JSON: {}", error)
            from()
            cause(error)
        }
        BadRequest(what: String) {
            description("The InfluxDB server responded with an error")
            display("The InfluxDB server responded with an error: {}", what)
        }
    }
}

type Result<T> = ::std::result::Result<T, Error>;

pub struct AsyncDb {
    name: String,
    query_endpoint: hyper::Url,
    write_endpoint: hyper::Url,
    client: hyper::Client<HttpConnector>,
}

impl AsyncDb {
    pub fn new(handle: Handle, base_url: &str, name: &str) -> Result<Self> {
        let base_url = hyper::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = hyper::Client::configure().keep_alive(false).build(&handle);

        Ok(AsyncDb {
            name: name.into(),
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
            client: client,
        })
    }

    pub fn add_data(&self, data: &str) -> AddData {
        let mut request = client::Request::new(hyper::Method::Post, self.write_endpoint.clone());
        request.set_body(data.to_owned());

        let response =
            self.client.request(request)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .map(|_| ());

        AddData(Box::new(response))
    }

    pub fn query(&self, query: &str) -> Query {
        let mut query_endpoint = self.query_endpoint.clone();
        query_endpoint.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);

        let response =
            self.client.get(query_endpoint)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .and_then(response_to_json);

        Query(Box::new(response))
    }
}

fn check_response_code(resp: client::Response) -> Box<Future<Item = client::Response, Error = Error>> {
    let f = if resp.status().is_success() {
        Either::A(futures::future::ok(resp))
    } else {
        let e = response_to_json::<InfluxServerError>(resp)
            .and_then(|message| Err(Error::BadRequest(message.error)));
        Either::B(e)
    };

    Box::new(f)
}

fn response_to_json<T>(resp: client::Response) -> Box<Future<Item = T, Error = Error>>
    where T: serde::Deserialize + 'static,
{
    let f =
        resp.body()
        .map_err(Error::Hyper)
        .fold(Vec::new(), |mut acc, chunk| {
            // TODO: Is it the best idea to just build up a big `Vec`?
            // TODO: Is there some way of reusing the vector allocation?
            acc.extend_from_slice(&*chunk);
            futures::future::ok::<_, Error>(acc)
        })
        .and_then(|body| serde_json::from_slice(&body).map_err(Error::Serde));

    Box::new(f)
}

#[must_use = "futures do nothing unless polled"]
pub struct AddData(Box<Future<Item = (), Error = Error>>);

impl Future for AddData {
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct Query(Box<Future<Item = QueryResponse, Error = Error>>);

impl Future for Query {
    type Item = QueryResponse;
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[derive(Debug, Deserialize)]
pub struct QueryResponse {
    pub results: Vec<QueryResult>,
}

#[derive(Debug, Deserialize)]
pub struct QueryResult {
    #[serde(default)]
    pub series: Vec<Series>,
    pub statement_id: usize, // TODO: correct integer type?
}

#[derive(Debug, Deserialize)]
pub struct Series {
    pub name: String,
    pub columns: Vec<String>, // TODO: `time` is always added?
    pub values: Vec<Vec<serde_json::Value>>, // TODO: matches with columns?
    // TODO: Don't expose serde types publically
}

#[derive(Debug, Deserialize)]
pub struct InfluxServerError {
    pub error: String,
}
<commit_msg>statement_id should indeed be usize<commit_after>extern crate tokio_core;
extern crate hyper;
extern crate futures;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate quick_error;

use futures::{Future, Stream};
use futures::future::Either;
use hyper::client::{self, HttpConnector};
use tokio_core::reactor::Handle;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Url(error: hyper::error::ParseError) {
            description(error.description())
            display("Unable to parse URL: {}", error)
            from()
            cause(error)
        }
        Hyper(error: hyper::Error) {
            description(error.description())
            display("Unable to perform HTTP request: {}", error)
            from()
            cause(error)
        }
        Serde(error: serde_json::Error) {
            description(error.description())
            display("Unable to deserialize JSON: {}", error)
            from()
            cause(error)
        }
        BadRequest(what: String) {
            description("The InfluxDB server responded with an error")
            display("The InfluxDB server responded with an error: {}", what)
        }
    }
}

type Result<T> = ::std::result::Result<T, Error>;

pub struct AsyncDb {
    name: String,
    query_endpoint: hyper::Url,
    write_endpoint: hyper::Url,
    client: hyper::Client<HttpConnector>,
}

impl AsyncDb {
    pub fn new(handle: Handle, base_url: &str, name: &str) -> Result<Self> {
        let base_url = hyper::Url::parse(base_url)?;
        let query_endpoint = base_url.join("/query")?;
        let mut write_endpoint = base_url.join("/write")?;
        write_endpoint.query_pairs_mut()
            .append_pair("db", &name);

        let client = hyper::Client::configure().keep_alive(false).build(&handle);

        Ok(AsyncDb {
            name: name.into(),
            query_endpoint: query_endpoint,
            write_endpoint: write_endpoint,
            client: client,
        })
    }

    pub fn add_data(&self, data: &str) -> AddData {
        let mut request = client::Request::new(hyper::Method::Post, self.write_endpoint.clone());
        request.set_body(data.to_owned());

        let response =
            self.client.request(request)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .map(|_| ());

        AddData(Box::new(response))
    }

    pub fn query(&self, query: &str) -> Query {
        let mut query_endpoint = self.query_endpoint.clone();
        query_endpoint.query_pairs_mut()
            .append_pair("db", &self.name)
            .append_pair("q", query);

        let response =
            self.client.get(query_endpoint)
            .map_err(Error::Hyper)
            .and_then(check_response_code)
            .and_then(response_to_json);

        Query(Box::new(response))
    }
}

fn check_response_code(resp: client::Response) -> Box<Future<Item = client::Response, Error = Error>> {
    let f = if resp.status().is_success() {
        Either::A(futures::future::ok(resp))
    } else {
        let e = response_to_json::<InfluxServerError>(resp)
            .and_then(|message| Err(Error::BadRequest(message.error)));
        Either::B(e)
    };

    Box::new(f)
}

fn response_to_json<T>(resp: client::Response) -> Box<Future<Item = T, Error = Error>>
    where T: serde::Deserialize + 'static,
{
    let f =
        resp.body()
        .map_err(Error::Hyper)
        .fold(Vec::new(), |mut acc, chunk| {
            // TODO: Is it the best idea to just build up a big `Vec`?
            // TODO: Is there some way of reusing the vector allocation?
            acc.extend_from_slice(&*chunk);
            futures::future::ok::<_, Error>(acc)
        })
        .and_then(|body| serde_json::from_slice(&body).map_err(Error::Serde));

    Box::new(f)
}

#[must_use = "futures do nothing unless polled"]
pub struct AddData(Box<Future<Item = (), Error = Error>>);

impl Future for AddData {
    type Item = ();
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[must_use = "futures do nothing unless polled"]
pub struct Query(Box<Future<Item = QueryResponse, Error = Error>>);

impl Future for Query {
    type Item = QueryResponse;
    type Error = Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.0.poll()
    }
}

#[derive(Debug, Deserialize)]
pub struct QueryResponse {
    pub results: Vec<QueryResult>,
}

#[derive(Debug, Deserialize)]
pub struct QueryResult {
    #[serde(default)]
    pub series: Vec<Series>,
    pub statement_id: usize,
}

#[derive(Debug, Deserialize)]
pub struct Series {
    pub name: String,
    pub columns: Vec<String>, // TODO: `time` is always added?
    pub values: Vec<Vec<serde_json::Value>>, // TODO: matches with columns?
    // TODO: Don't expose serde types publically
}

#[derive(Debug, Deserialize)]
pub struct InfluxServerError {
    pub error: String,
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate crypto;

#[macro_use] mod macros;

mod bytes;
mod error;
mod header;
mod read;
mod signature;

use std::fs;

pub use error::Error;

#[derive(Debug)]
pub enum FileType {
    KeePass1,
    KeePass2PreRelease,
    KeePass2
}

pub fn read(path: &str, passphrase: &str) -> Result<String, Error> {
    let mut file = match fs::File::open(path) {
        Ok(f) => f,
        Err(e) => return Err(Error::Io(e))
    };

    let header = match signature::read_file_type(&mut file)
        .and_then(|file_type| header::read_header(file_type, &mut file)) {
        Ok(h) => h,
        Err(e) => return Err(e)
    };

    header.master_key(passphrase)
        .and_then(|key| read::read(&key, &header.encryption_iv(), &header.stream_start_bytes(), &mut file))
}
<commit_msg>Better path handling<commit_after>extern crate byteorder;
extern crate crypto;

#[macro_use] mod macros;

mod bytes;
mod error;
mod header;
mod read;
mod signature;

use std::fs::File;
use std::path::Path;

pub use error::Error;

#[derive(Debug)]
pub enum FileType {
    KeePass1,
    KeePass2PreRelease,
    KeePass2
}

pub fn read<P: AsRef<Path>>(path: P, passphrase: &str) -> Result<String, Error> {
    let mut file = match File::open(path) {
        Ok(f) => f,
        Err(e) => return Err(Error::Io(e))
    };

    let header = match signature::read_file_type(&mut file)
        .and_then(|file_type| header::read_header(file_type, &mut file)) {
        Ok(h) => h,
        Err(e) => return Err(e)
    };

    header.master_key(passphrase)
        .and_then(|key| read::read(&key, &header.encryption_iv(), &header.stream_start_bytes(), &mut file))
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;
use std::ops::{
    Deref,
    DerefMut,
};
use std::slice;
use std::convert::From;

/// Make sure the non-nullable pointer optimization does not occur!
enum Flag<T> {
    Alive(T),
    Dropped,
    _Unused,
}

/// Trait for fixed size arrays.
pub unsafe trait Array {
    #[doc(hidden)]
    type Item;
    #[doc(hidden)]
    unsafe fn new() -> Self;
    #[doc(hidden)]
    fn as_ptr(&self) -> *const Self::Item;
    #[doc(hidden)]
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    #[doc(hidden)]
    fn capacity() -> usize;
}

macro_rules! fix_array_impl {
    ($len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            unsafe fn new() -> [T; $len] { mem::uninitialized() }
            #[inline]
            fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
            fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
            #[inline]
            fn capacity() -> usize { $len }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    () => ();
    ($len:expr, $($more:expr,)*) => (
        fix_array_impl!($len);
        fix_array_impl_recursive!($($more,)*);
    );
}

fix_array_impl_recursive!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
                          16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
                          32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,);

/// A vector with a fixed capacity.
///
/// The **ArrayVec** is a vector backed by a fixed size array and keeps track of
/// the number of initialized elements.
///
/// The vector is a contiguous value that you can store directly on the stack
/// if needed.
///
/// It offers a simple API of *.push()* and *.pop()* but also dereferences to a slice, so
/// that the full slice API is available.
///
/// The vector also implements a by value iterator.
pub struct ArrayVec<A: Array> {
    len: u8,
    xs: Flag<A>,
}

impl<A: Array> Drop for ArrayVec<A> {
    fn drop(&mut self) {
        // clear all elements, then inhibit drop of inner array
        while let Some(_) = self.pop() { }
        unsafe {
            ptr::write(&mut self.xs, Flag::Dropped);
        }
    }
}

impl<A: Array> ArrayVec<A> {
    /// Create a new empty **ArrayVec**.
    ///
    /// Capacity is inferred from the type parameter.
    ///
    /// ## Examples
    ///
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 16]>::new();
    /// array.push(1);
    /// array.push(2);
    /// assert_eq!(&array[..], &[1, 2]);
    /// assert_eq!(array.capacity(), 16);
    /// ```
    pub fn new() -> ArrayVec<A> {
        unsafe {
            ArrayVec { xs: Flag::Alive(Array::new()), len: 0 }
        }
    }

    #[inline]
    fn array(&self) -> &A {
        match self.xs {
            Flag::Alive(ref xs) => xs,
            _ => unreachable!(),
            //_ => std::intrinsics::unreachable(),
        }
    }

    #[inline]
    fn array_mut(&mut self) -> &mut A {
        // FIXME: Optimize this, we know it's always Some.
        match self.xs {
            Flag::Alive(ref mut xs) => xs,
            _ => unreachable!(),
            //_ => std::intrinsics::unreachable(),
        }
    }

    /// Return the length of the **ArrayVec**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::from([1, 2, 3]);
    /// array.pop();
    /// assert_eq!(array.len(), 2);
    /// ```
    #[inline]
    pub fn len(&self) -> usize { self.len as usize }

    /// Return the capacity of the **ArrayVec**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let array = ArrayVec::from([1, 2, 3]);
    /// assert_eq!(array.capacity(), 3);
    /// ```
    #[inline]
    pub fn capacity(&self) -> usize { A::capacity() }

    /// Push **elt** to the end of the vector.
    ///
    /// Return **None** if the push succeeds, or and return **Some(** *elt* **)**
    /// if the vector is full.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 2]>::new();
    ///
    /// array.push(1);
    /// array.push(2);
    /// let overflow = array.push(3);
    ///
    /// assert_eq!(&array[..], &[1, 2]);
    /// assert_eq!(overflow, Some(3));
    /// ```
    pub fn push(&mut self, elt: A::Item) -> Option<A::Item> {
        if self.len() < A::capacity() {
            unsafe {
                let len = self.len();
                ptr::write(self.get_unchecked_mut(len), elt);
            }
            self.len += 1;
            None
        } else {
            Some(elt)
        }
    }

    /// Remove the last element in the vector.
    ///
    /// Return **Some(** *element* **)** if the vector is non-empty, else **None**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 2]>::new();
    ///
    /// array.push(1);
    ///
    /// assert_eq!(array.pop(), Some(1));
    /// assert_eq!(array.pop(), None);
    /// ```
    pub fn pop(&mut self) -> Option<A::Item> {
        if self.len == 0 {
            return None
        }
        unsafe {
            self.len -= 1;
            let len = self.len();
            Some(ptr::read(self.get_unchecked_mut(len)))
        }
    }
}

impl<A: Array> Deref for ArrayVec<A> {
    type Target = [A::Item];
    #[inline]
    fn deref(&self) -> &[A::Item] {
        unsafe {
            slice::from_raw_parts(self.array().as_ptr(), self.len())
        }
    }
}

impl<A: Array> DerefMut for ArrayVec<A> {
    #[inline]
    fn deref_mut(&mut self) -> &mut [A::Item] {
        let len = self.len();
        unsafe {
            slice::from_raw_parts_mut(self.array_mut().as_mut_ptr(), len)
        }
    }
}

/// Create an **ArrayVec** from an array.
///
/// ## Examples
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::from([1, 2, 3]);
/// assert_eq!(array.len(), 3);
/// assert_eq!(array.capacity(), 3);
/// ```
impl<A: Array> From<A> for ArrayVec<A> {
    fn from(array: A) -> Self {
        ArrayVec { xs: Flag::Alive(array), len: A::capacity() as u8 }
    }
}

/// Iterate the **ArrayVec** with references to each element.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let array = ArrayVec::from([1, 2, 3]);
///
/// for elt in &array {
///     // ...
/// }
/// ```
impl<'a, A: Array> IntoIterator for &'a ArrayVec<A> {
    type Item = &'a A::Item;
    type IntoIter = slice::Iter<'a, A::Item>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

/// Iterate the **ArrayVec** with each element by value.
///
/// The vector is consumed by this operation.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// for elt in ArrayVec::from([1, 2, 3]) {
///     // ...
/// }
/// ```
impl<A: Array> IntoIterator for ArrayVec<A> {
    type Item = A::Item;
    type IntoIter = IntoIter<A>;
    fn into_iter(self) -> IntoIter<A> {
        IntoIter { index: 0, v: self, }
    }
}

/// By-value iterator for ArrayVec.
pub struct IntoIter<A: Array> {
    index: u8,
    v: ArrayVec<A>,
}

impl<A: Array> Iterator for IntoIter<A> {
    type Item = A::Item;

    fn next(&mut self) -> Option<A::Item> {
        if self.index == self.v.len {
            None
        } else {
            unsafe {
                let ptr = self.v.get_unchecked_mut(self.index as usize);
                let elt = ptr::read(ptr);
                self.index += 1;
                Some(elt)
            }
        }
    }
}

impl<A: Array> Drop for IntoIter<A> {
    fn drop(&mut self) {
        // exhaust iterator and clear the vector
        while let Some(_) = self.next() { }
        self.v.len = 0;
    }
}

#[test]
fn test_simple() {
    use std::ops::Add;

    let mut vec: ArrayVec<[Vec<i32>; 3]> = ArrayVec::new();

    vec.push(vec![1,2,3,4]);
    vec.push(vec![3]);
    vec.push(vec![-1, 90, -2]);

    for elt in &vec {
        println!("{:?}", elt);
    }

    let sum = vec.iter().map(|x| x.iter().fold(0, Add::add)).fold(0, Add::add);
    assert_eq!(sum, 13 + 87);
    let sum_len = vec.into_iter().map(|x| x.len()).fold(0, Add::add);
    assert_eq!(sum_len, 8);
}

#[test]
fn test_drop() {
    use std::rc::Rc;
    use std::cell::Cell;

    let flag = Rc::new(Cell::new(0));

    struct Foo(Rc<Cell<i32>>);

    impl Drop for Foo {
        fn drop(&mut self) {
            let n = self.0.get();
            self.0.set(n + 1);
        }
    }

    {
        let mut array = ArrayVec::<[Foo; 128]>::new();
        array.push(Foo(flag.clone()));
        array.push(Foo(flag.clone()));
    }
    assert_eq!(flag.get(), 2);

    // test something with the nullable pointer optimization
    flag.set(0);

    {
        let mut array = ArrayVec::<[_; 3]>::new();
        array.push(vec![Foo(flag.clone())]);
        array.push(vec![Foo(flag.clone()), Foo(flag.clone())]);
        array.push(vec![]);
        array.push(vec![Foo(flag.clone())]);
        assert_eq!(flag.get(), 1);
        drop(array.pop());
        assert_eq!(flag.get(), 1);
        drop(array.pop());
        assert_eq!(flag.get(), 3);
    }

    assert_eq!(flag.get(), 4);
}
<commit_msg>Add comment to Array::new<commit_after>use std::mem;
use std::ptr;
use std::ops::{
    Deref,
    DerefMut,
};
use std::slice;
use std::convert::From;

/// Make sure the non-nullable pointer optimization does not occur!
enum Flag<T> {
    Alive(T),
    Dropped,
    _Unused,
}

/// Trait for fixed size arrays.
pub unsafe trait Array {
    #[doc(hidden)]
    type Item;
    #[doc(hidden)]
    unsafe fn new() -> Self;
    #[doc(hidden)]
    fn as_ptr(&self) -> *const Self::Item;
    #[doc(hidden)]
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
    #[doc(hidden)]
    fn capacity() -> usize;
}

macro_rules! fix_array_impl {
    ($len:expr ) => (
        unsafe impl<T> Array for [T; $len] {
            type Item = T;
            /// Note: Returnin an uninitialized value here only works
            /// if we can be sure the data is never used. The nullable pointer
            /// inside enum optimization conflicts with this this for example,
            /// so we need to be extra careful. See `Flag` enum.
            unsafe fn new() -> [T; $len] { mem::uninitialized() }
            #[inline]
            fn as_ptr(&self) -> *const T { self as *const _ as *const _ }
            fn as_mut_ptr(&mut self) -> *mut T { self as *mut _ as *mut _}
            #[inline]
            fn capacity() -> usize { $len }
        }
    )
}

macro_rules! fix_array_impl_recursive {
    () => ();
    ($len:expr, $($more:expr,)*) => (
        fix_array_impl!($len);
        fix_array_impl_recursive!($($more,)*);
    );
}

fix_array_impl_recursive!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
                          16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
                          32, 40, 48, 56, 64, 72, 96, 128, 160, 192, 224,);

/// A vector with a fixed capacity.
///
/// The **ArrayVec** is a vector backed by a fixed size array and keeps track of
/// the number of initialized elements.
///
/// The vector is a contiguous value that you can store directly on the stack
/// if needed.
///
/// It offers a simple API of *.push()* and *.pop()* but also dereferences to a slice, so
/// that the full slice API is available.
///
/// The vector also implements a by value iterator.
pub struct ArrayVec<A: Array> {
    len: u8,
    xs: Flag<A>,
}

impl<A: Array> Drop for ArrayVec<A> {
    fn drop(&mut self) {
        // clear all elements, then inhibit drop of inner array
        while let Some(_) = self.pop() { }
        unsafe {
            ptr::write(&mut self.xs, Flag::Dropped);
        }
    }
}

impl<A: Array> ArrayVec<A> {
    /// Create a new empty **ArrayVec**.
    ///
    /// Capacity is inferred from the type parameter.
    ///
    /// ## Examples
    ///
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 16]>::new();
    /// array.push(1);
    /// array.push(2);
    /// assert_eq!(&array[..], &[1, 2]);
    /// assert_eq!(array.capacity(), 16);
    /// ```
    pub fn new() -> ArrayVec<A> {
        unsafe {
            ArrayVec { xs: Flag::Alive(Array::new()), len: 0 }
        }
    }

    #[inline]
    fn array(&self) -> &A {
        match self.xs {
            Flag::Alive(ref xs) => xs,
            _ => unreachable!(),
            //_ => std::intrinsics::unreachable(),
        }
    }

    #[inline]
    fn array_mut(&mut self) -> &mut A {
        // FIXME: Optimize this, we know it's always Some.
        match self.xs {
            Flag::Alive(ref mut xs) => xs,
            _ => unreachable!(),
            //_ => std::intrinsics::unreachable(),
        }
    }

    /// Return the length of the **ArrayVec**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::from([1, 2, 3]);
    /// array.pop();
    /// assert_eq!(array.len(), 2);
    /// ```
    #[inline]
    pub fn len(&self) -> usize { self.len as usize }

    /// Return the capacity of the **ArrayVec**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let array = ArrayVec::from([1, 2, 3]);
    /// assert_eq!(array.capacity(), 3);
    /// ```
    #[inline]
    pub fn capacity(&self) -> usize { A::capacity() }

    /// Push **elt** to the end of the vector.
    ///
    /// Return **None** if the push succeeds, or and return **Some(** *elt* **)**
    /// if the vector is full.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 2]>::new();
    ///
    /// array.push(1);
    /// array.push(2);
    /// let overflow = array.push(3);
    ///
    /// assert_eq!(&array[..], &[1, 2]);
    /// assert_eq!(overflow, Some(3));
    /// ```
    pub fn push(&mut self, elt: A::Item) -> Option<A::Item> {
        if self.len() < A::capacity() {
            unsafe {
                let len = self.len();
                ptr::write(self.get_unchecked_mut(len), elt);
            }
            self.len += 1;
            None
        } else {
            Some(elt)
        }
    }

    /// Remove the last element in the vector.
    ///
    /// Return **Some(** *element* **)** if the vector is non-empty, else **None**.
    ///
    /// ## Examples
    /// ```
    /// use arrayvec::ArrayVec;
    ///
    /// let mut array = ArrayVec::<[_; 2]>::new();
    ///
    /// array.push(1);
    ///
    /// assert_eq!(array.pop(), Some(1));
    /// assert_eq!(array.pop(), None);
    /// ```
    pub fn pop(&mut self) -> Option<A::Item> {
        if self.len == 0 {
            return None
        }
        unsafe {
            self.len -= 1;
            let len = self.len();
            Some(ptr::read(self.get_unchecked_mut(len)))
        }
    }
}

impl<A: Array> Deref for ArrayVec<A> {
    type Target = [A::Item];
    #[inline]
    fn deref(&self) -> &[A::Item] {
        unsafe {
            slice::from_raw_parts(self.array().as_ptr(), self.len())
        }
    }
}

impl<A: Array> DerefMut for ArrayVec<A> {
    #[inline]
    fn deref_mut(&mut self) -> &mut [A::Item] {
        let len = self.len();
        unsafe {
            slice::from_raw_parts_mut(self.array_mut().as_mut_ptr(), len)
        }
    }
}

/// Create an **ArrayVec** from an array.
///
/// ## Examples
/// ```
/// use arrayvec::ArrayVec;
///
/// let mut array = ArrayVec::from([1, 2, 3]);
/// assert_eq!(array.len(), 3);
/// assert_eq!(array.capacity(), 3);
/// ```
impl<A: Array> From<A> for ArrayVec<A> {
    fn from(array: A) -> Self {
        ArrayVec { xs: Flag::Alive(array), len: A::capacity() as u8 }
    }
}

/// Iterate the **ArrayVec** with references to each element.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// let array = ArrayVec::from([1, 2, 3]);
///
/// for elt in &array {
///     // ...
/// }
/// ```
impl<'a, A: Array> IntoIterator for &'a ArrayVec<A> {
    type Item = &'a A::Item;
    type IntoIter = slice::Iter<'a, A::Item>;
    fn into_iter(self) -> Self::IntoIter { self.iter() }
}

/// Iterate the **ArrayVec** with each element by value.
///
/// The vector is consumed by this operation.
///
/// ## Examples
///
/// ```
/// use arrayvec::ArrayVec;
///
/// for elt in ArrayVec::from([1, 2, 3]) {
///     // ...
/// }
/// ```
impl<A: Array> IntoIterator for ArrayVec<A> {
    type Item = A::Item;
    type IntoIter = IntoIter<A>;
    fn into_iter(self) -> IntoIter<A> {
        IntoIter { index: 0, v: self, }
    }
}

/// By-value iterator for ArrayVec.
pub struct IntoIter<A: Array> {
    index: u8,
    v: ArrayVec<A>,
}

impl<A: Array> Iterator for IntoIter<A> {
    type Item = A::Item;

    fn next(&mut self) -> Option<A::Item> {
        if self.index == self.v.len {
            None
        } else {
            unsafe {
                let ptr = self.v.get_unchecked_mut(self.index as usize);
                let elt = ptr::read(ptr);
                self.index += 1;
                Some(elt)
            }
        }
    }
}

impl<A: Array> Drop for IntoIter<A> {
    fn drop(&mut self) {
        // exhaust iterator and clear the vector
        while let Some(_) = self.next() { }
        self.v.len = 0;
    }
}

#[test]
fn test_simple() {
    use std::ops::Add;

    let mut vec: ArrayVec<[Vec<i32>; 3]> = ArrayVec::new();

    vec.push(vec![1,2,3,4]);
    vec.push(vec![3]);
    vec.push(vec![-1, 90, -2]);

    for elt in &vec {
        println!("{:?}", elt);
    }

    let sum = vec.iter().map(|x| x.iter().fold(0, Add::add)).fold(0, Add::add);
    assert_eq!(sum, 13 + 87);
    let sum_len = vec.into_iter().map(|x| x.len()).fold(0, Add::add);
    assert_eq!(sum_len, 8);
}

#[test]
fn test_drop() {
    use std::rc::Rc;
    use std::cell::Cell;

    let flag = Rc::new(Cell::new(0));

    struct Foo(Rc<Cell<i32>>);

    impl Drop for Foo {
        fn drop(&mut self) {
            let n = self.0.get();
            self.0.set(n + 1);
        }
    }

    {
        let mut array = ArrayVec::<[Foo; 128]>::new();
        array.push(Foo(flag.clone()));
        array.push(Foo(flag.clone()));
    }
    assert_eq!(flag.get(), 2);

    // test something with the nullable pointer optimization
    flag.set(0);

    {
        let mut array = ArrayVec::<[_; 3]>::new();
        array.push(vec![Foo(flag.clone())]);
        array.push(vec![Foo(flag.clone()), Foo(flag.clone())]);
        array.push(vec![]);
        array.push(vec![Foo(flag.clone())]);
        assert_eq!(flag.get(), 1);
        drop(array.pop());
        assert_eq!(flag.get(), 1);
        drop(array.pop());
        assert_eq!(flag.get(), 3);
    }

    assert_eq!(flag.get(), 4);
}
<|endoftext|>


<commit_before>use serial::{Serial, SerialCallback};
use timer::Timer;
use keypad::Keypad;
use gpu::GPU;
use sound::Sound;
use gbmode::{GbMode, GbSpeed};
use std::path;

const WRAM_SIZE: usize = 0x8000;
const ZRAM_SIZE: usize = 0x7F;

#[derive(PartialEq)]
enum DMAType {
    NoDMA,
    GDMA,
    HDMA,
}

pub struct MMU<'a> {
    wram: [u8; WRAM_SIZE],
    zram: [u8; ZRAM_SIZE],
    hdma: [u8; 4],
    pub inte: u8,
    pub intf: u8,
    pub serial: Serial<'a>,
    pub timer: Timer,
    pub keypad: Keypad,
    pub gpu: GPU,
    pub sound: Option<Sound>,
    hdma_status: DMAType,
    hdma_src: u16,
    hdma_dst: u16,
    hdma_len: u8,
    wrambank: usize,
    mbc: Box<::mbc::MBC+'static>,
    gbmode: GbMode,
    gbspeed: GbSpeed,
    speed_switch_req: bool,
}

impl<'a> MMU<'a> {
    pub fn new(romname: &str, serial_callback: Option<SerialCallback<'a>>) -> ::StrResult<MMU<'a>> {
        let mmu_mbc = try!(::mbc::get_mbc(path::PathBuf::from(romname)));
        let serial = match serial_callback {
            Some(cb) => Serial::new_with_callback(cb),
            None => Serial::new(),
        };
        let mut res = MMU {
            wram: [0; WRAM_SIZE],
            zram: [0; ZRAM_SIZE],
            hdma: [0; 4],
            wrambank: 1,
            inte: 0,
            intf: 0,
            serial: serial,
            timer: Timer::new(),
            keypad: Keypad::new(),
            gpu: GPU::new(),
            sound: None,
            mbc: mmu_mbc,
            gbmode: GbMode::Classic,
            gbspeed: GbSpeed::Single,
            speed_switch_req: false,
            hdma_src: 0,
            hdma_dst: 0,
            hdma_status: DMAType::NoDMA,
            hdma_len: 0xFF,
        };
        if res.rb(0x0143) == 0xC0 {
            return Err("This game does not work in Classic mode");
        }
        res.set_initial();
        Ok(res)
    }

    pub fn new_cgb(romname: &str, serial_callback: Option<SerialCallback<'a>>) -> ::StrResult<MMU<'a>> {
        let mmu_mbc = try!(::mbc::get_mbc(path::PathBuf::from(romname)));
        let serial = match serial_callback {
            Some(cb) => Serial::new_with_callback(cb),
            None => Serial::new(),
        };
        let mut res = MMU {
            wram: [0; WRAM_SIZE],
            zram: [0; ZRAM_SIZE],
            wrambank: 1,
            hdma: [0; 4],
            inte: 0,
            intf: 0,
            serial: serial,
            timer: Timer::new(),
            keypad: Keypad::new(),
            gpu: GPU::new_cgb(),
            sound: None,
            mbc: mmu_mbc,
            gbmode: GbMode::Color,
            gbspeed: GbSpeed::Single,
            speed_switch_req: false,
            hdma_src: 0,
            hdma_dst: 0,
            hdma_status: DMAType::NoDMA,
            hdma_len: 0xFF,
        };
        res.determine_mode();
        res.set_initial();
        Ok(res)
    }

    fn set_initial(&mut self) {
        self.wb(0xFF05, 0);
        self.wb(0xFF06, 0);
        self.wb(0xFF07, 0);
        self.wb(0xFF40, 0x91);
        self.wb(0xFF42, 0);
        self.wb(0xFF43, 0);
        self.wb(0xFF45, 0);
        self.wb(0xFF47, 0xFC);
        self.wb(0xFF48, 0xFF);
        self.wb(0xFF49, 0xFF);
        self.wb(0xFF4A, 0);
        self.wb(0xFF4B, 0);
    }

    fn determine_mode(&mut self) {
        let mode = match self.rb(0x0143) & 0x80 {
            0x80 => GbMode::Color,
            _ => GbMode::ColorAsClassic,
        };
        self.gbmode = mode;
        self.gpu.gbmode = mode;
    }

    pub fn do_cycle(&mut self, cputicks: u32) -> u32 {
        let cpudivider = match self.gbspeed {
            GbSpeed::Single => 1,
            GbSpeed::Double => 2,
        };
        let ticks = cputicks / cpudivider;
        let gputicks = ticks + self.perform_vramdma();

        self.timer.do_cycle(ticks);
        self.intf |= self.timer.interrupt;
        self.timer.interrupt = 0;

        self.intf |= self.keypad.interrupt;
        self.keypad.interrupt = 0;

        self.gpu.do_cycle(gputicks);
        self.intf |= self.gpu.interrupt;
        self.gpu.interrupt = 0;

        self.sound.as_mut().map_or((), |s| s.do_cycle(gputicks));

        return gputicks;
    }

    pub fn rb(&mut self, address: u16) -> u8 {
        match address {
            0x0000 ... 0x7FFF => self.mbc.readrom(address),
            0x8000 ... 0x9FFF => self.gpu.rb(address),
            0xA000 ... 0xBFFF => self.mbc.readram(address),
            0xC000 ... 0xCFFF | 0xE000 ... 0xEFFF => self.wram[address as usize & 0x0FFF],
            0xD000 ... 0xDFFF | 0xF000 ... 0xFDFF => self.wram[(self.wrambank * 0x1000) | address as usize & 0x0FFF],
            0xFE00 ... 0xFE9F => self.gpu.rb(address),
            0xFF00 => self.keypad.rb(),
            0xFF01 ... 0xFF02 => self.serial.rb(address),
            0xFF04 ... 0xFF07 => self.timer.rb(address),
            0xFF0F => self.intf,
            0xFF10 ... 0xFF3F => self.sound.as_mut().map_or(0, |s| s.rb(address)),
            0xFF4D => (if self.gbspeed == GbSpeed::Double { 0x80 } else { 0 }) | (if self.speed_switch_req { 1 } else { 0 }),
            0xFF40 ... 0xFF4F => self.gpu.rb(address),
            0xFF51 ... 0xFF55 => self.hdma_read(address),
            0xFF68 ... 0xFF6B => self.gpu.rb(address),
            0xFF70 => self.wrambank as u8,
            0xFF80 ... 0xFFFE => self.zram[address as usize & 0x007F],
            0xFFFF => self.inte,
            _ => 0,
        }
    }

    pub fn rw(&mut self, address: u16) -> u16 {
        (self.rb(address) as u16) | ((self.rb(address + 1) as u16) << 8)
    }

    pub fn wb(&mut self, address: u16, value: u8) {
        match address {
            0x0000 ... 0x7FFF => self.mbc.writerom(address, value),
            0x8000 ... 0x9FFF => self.gpu.wb(address, value),
            0xA000 ... 0xBFFF => self.mbc.writeram(address, value),
            0xC000 ... 0xCFFF | 0xE000 ... 0xEFFF => self.wram[address as usize & 0x0FFF] = value,
            0xD000 ... 0xDFFF | 0xF000 ... 0xFDFF => self.wram[(self.wrambank * 0x1000) | (address as usize & 0x0FFF)] = value,
            0xFE00 ... 0xFE9F => self.gpu.wb(address, value),
            0xFF00 => self.keypad.wb(value),
            0xFF01 ... 0xFF02 => self.serial.wb(address, value),
            0xFF04 ... 0xFF07 => self.timer.wb(address, value),
            0xFF10 ... 0xFF3F => self.sound.as_mut().map_or((), |s| s.wb(address, value)),
            0xFF46 => self.oamdma(value),
            0xFF4D => if value & 0x1 == 0x1 { self.speed_switch_req = true; },
            0xFF40 ... 0xFF4F => self.gpu.wb(address, value),
            0xFF51 ... 0xFF55 => self.hdma_write(address, value),
            0xFF68 ... 0xFF6B => self.gpu.wb(address, value),
            0xFF0F => self.intf = value,
            0xFF70 => { self.wrambank = match value & 0x7 { 0 => 1, n => n as usize }; },
            0xFF80 ... 0xFFFE => self.zram[address as usize & 0x007F] = value,
            0xFFFF => self.inte = value,
            _ => {},
        };
    }

    pub fn ww(&mut self, address: u16, value: u16) {
        self.wb(address, (value & 0xFF) as u8);
        self.wb(address + 1, (value >> 8) as u8);
    }

    pub fn switch_speed(&mut self) {
        if self.speed_switch_req {
            if self.gbspeed == GbSpeed::Double {
                self.gbspeed = GbSpeed::Single;
            } else {
                self.gbspeed = GbSpeed::Double;
            }
        }
        self.speed_switch_req = false;
    }

    fn oamdma(&mut self, value: u8) {
        let base = (value as u16) << 8;
        for i in (0u16 .. 0xA0) {
            let b = self.rb(base + i);
            self.wb(0xFE00 + i, b);
        }
    }

    fn hdma_read(&self, a: u16) -> u8 {
        match a {
            0xFF51 ... 0xFF54 => { self.hdma[(a - 0xFF51) as usize] },
            0xFF55 => self.hdma_len | if self.hdma_status == DMAType::NoDMA { 0x80 } else { 0 },
            _ => panic!("The address {:04X} should not be handled by hdma_read", a),
        }
    }

    fn hdma_write(&mut self, a: u16, v: u8) {
        match a {
            0xFF51 => self.hdma[0] = v,
            0xFF52 => self.hdma[1] = v & 0xF0,
            0xFF53 => self.hdma[2] = v & 0x1F,
            0xFF54 => self.hdma[3] = v & 0xF0,
            0xFF55 => {
                if self.hdma_status == DMAType::HDMA {
                    if v & 0x80 == 0 { self.hdma_status = DMAType::NoDMA; };
                    return;
                }
                let src = ((self.hdma[0] as u16) << 8) | (self.hdma[1] as u16);
                let dst = ((self.hdma[2] as u16) << 8) | (self.hdma[3] as u16) | 0x8000;
                if !(src <= 0x7FF0 || (src >= 0xA000 && src <= 0xDFF0)) { panic!("HDMA transfer with illegal start address {:04X}", src); }

                self.hdma_src = src;
                self.hdma_dst = dst;
                self.hdma_len = v & 0x7F;

                self.hdma_status =
                    if v & 0x80 == 0x80 { DMAType::HDMA }
                    else { DMAType::GDMA };
            },
            _ => panic!("The address {:04X} should not be handled by hdma_write", a),
        };
    }

    fn perform_vramdma(&mut self) -> u32 {
        match self.hdma_status {
            DMAType::NoDMA => 0,
            DMAType::GDMA => self.perform_gdma(),
            DMAType::HDMA => self.perform_hdma(),
        }
    }

    fn perform_hdma(&mut self) -> u32 {
        if self.gpu.may_hdma() == false {
            return 0;
        }

        self.perform_vramdma_row();
        if self.hdma_len == 0x7F { self.hdma_status = DMAType::NoDMA; }

        return 8;
    }

    fn perform_gdma(&mut self) -> u32 {
        let len = self.hdma_len as u32 + 1;
        for _i in (0 .. len) {
            self.perform_vramdma_row();
        }

        self.hdma_status = DMAType::NoDMA;
        return len * 8;
    }

    fn perform_vramdma_row(&mut self) {
        let mmu_src = self.hdma_src;
        for j in (0u16 .. 0x10) {
            let b: u8 = self.rb(mmu_src + j);
            self.gpu.wb(self.hdma_dst + j, b);
        }
        self.hdma_src += 0x10;
        self.hdma_dst += 0x10;

        if self.hdma_len == 0 {
            self.hdma_len = 0x7F;
        }
        else {
            self.hdma_len -= 1;
        }
    }
}
<commit_msg>Add initialization of sound registers<commit_after>use serial::{Serial, SerialCallback};
use timer::Timer;
use keypad::Keypad;
use gpu::GPU;
use sound::Sound;
use gbmode::{GbMode, GbSpeed};
use std::path;

const WRAM_SIZE: usize = 0x8000;
const ZRAM_SIZE: usize = 0x7F;

#[derive(PartialEq)]
enum DMAType {
    NoDMA,
    GDMA,
    HDMA,
}

pub struct MMU<'a> {
    wram: [u8; WRAM_SIZE],
    zram: [u8; ZRAM_SIZE],
    hdma: [u8; 4],
    pub inte: u8,
    pub intf: u8,
    pub serial: Serial<'a>,
    pub timer: Timer,
    pub keypad: Keypad,
    pub gpu: GPU,
    pub sound: Option<Sound>,
    hdma_status: DMAType,
    hdma_src: u16,
    hdma_dst: u16,
    hdma_len: u8,
    wrambank: usize,
    mbc: Box<::mbc::MBC+'static>,
    gbmode: GbMode,
    gbspeed: GbSpeed,
    speed_switch_req: bool,
}

impl<'a> MMU<'a> {
    pub fn new(romname: &str, serial_callback: Option<SerialCallback<'a>>) -> ::StrResult<MMU<'a>> {
        let mmu_mbc = try!(::mbc::get_mbc(path::PathBuf::from(romname)));
        let serial = match serial_callback {
            Some(cb) => Serial::new_with_callback(cb),
            None => Serial::new(),
        };
        let mut res = MMU {
            wram: [0; WRAM_SIZE],
            zram: [0; ZRAM_SIZE],
            hdma: [0; 4],
            wrambank: 1,
            inte: 0,
            intf: 0,
            serial: serial,
            timer: Timer::new(),
            keypad: Keypad::new(),
            gpu: GPU::new(),
            sound: None,
            mbc: mmu_mbc,
            gbmode: GbMode::Classic,
            gbspeed: GbSpeed::Single,
            speed_switch_req: false,
            hdma_src: 0,
            hdma_dst: 0,
            hdma_status: DMAType::NoDMA,
            hdma_len: 0xFF,
        };
        if res.rb(0x0143) == 0xC0 {
            return Err("This game does not work in Classic mode");
        }
        res.set_initial();
        Ok(res)
    }

    pub fn new_cgb(romname: &str, serial_callback: Option<SerialCallback<'a>>) -> ::StrResult<MMU<'a>> {
        let mmu_mbc = try!(::mbc::get_mbc(path::PathBuf::from(romname)));
        let serial = match serial_callback {
            Some(cb) => Serial::new_with_callback(cb),
            None => Serial::new(),
        };
        let mut res = MMU {
            wram: [0; WRAM_SIZE],
            zram: [0; ZRAM_SIZE],
            wrambank: 1,
            hdma: [0; 4],
            inte: 0,
            intf: 0,
            serial: serial,
            timer: Timer::new(),
            keypad: Keypad::new(),
            gpu: GPU::new_cgb(),
            sound: None,
            mbc: mmu_mbc,
            gbmode: GbMode::Color,
            gbspeed: GbSpeed::Single,
            speed_switch_req: false,
            hdma_src: 0,
            hdma_dst: 0,
            hdma_status: DMAType::NoDMA,
            hdma_len: 0xFF,
        };
        res.determine_mode();
        res.set_initial();
        Ok(res)
    }

    fn set_initial(&mut self) {
        self.wb(0xFF05, 0);
        self.wb(0xFF06, 0);
        self.wb(0xFF07, 0);
        self.wb(0xFF10, 0x80);
        self.wb(0xFF11, 0xBF);
        self.wb(0xFF12, 0xF3);
        self.wb(0xFF14, 0xBF);
        self.wb(0xFF16, 0x3F);
        self.wb(0xFF16, 0x3F);
        self.wb(0xFF17, 0);
        self.wb(0xFF19, 0xBF);
        self.wb(0xFF1A, 0x7F);
        self.wb(0xFF1B, 0xFF);
        self.wb(0xFF1C, 0x9F);
        self.wb(0xFF1E, 0xFF);
        self.wb(0xFF20, 0xFF);
        self.wb(0xFF21, 0);
        self.wb(0xFF22, 0);
        self.wb(0xFF23, 0xBF);
        self.wb(0xFF24, 0x77);
        self.wb(0xFF25, 0xF3);
        self.wb(0xFF26, 0xF1);
        self.wb(0xFF40, 0x91);
        self.wb(0xFF42, 0);
        self.wb(0xFF43, 0);
        self.wb(0xFF45, 0);
        self.wb(0xFF47, 0xFC);
        self.wb(0xFF48, 0xFF);
        self.wb(0xFF49, 0xFF);
        self.wb(0xFF4A, 0);
        self.wb(0xFF4B, 0);
    }

    fn determine_mode(&mut self) {
        let mode = match self.rb(0x0143) & 0x80 {
            0x80 => GbMode::Color,
            _ => GbMode::ColorAsClassic,
        };
        self.gbmode = mode;
        self.gpu.gbmode = mode;
    }

    pub fn do_cycle(&mut self, cputicks: u32) -> u32 {
        let cpudivider = match self.gbspeed {
            GbSpeed::Single => 1,
            GbSpeed::Double => 2,
        };
        let ticks = cputicks / cpudivider;
        let gputicks = ticks + self.perform_vramdma();

        self.timer.do_cycle(ticks);
        self.intf |= self.timer.interrupt;
        self.timer.interrupt = 0;

        self.intf |= self.keypad.interrupt;
        self.keypad.interrupt = 0;

        self.gpu.do_cycle(gputicks);
        self.intf |= self.gpu.interrupt;
        self.gpu.interrupt = 0;

        self.sound.as_mut().map_or((), |s| s.do_cycle(gputicks));

        return gputicks;
    }

    pub fn rb(&mut self, address: u16) -> u8 {
        match address {
            0x0000 ... 0x7FFF => self.mbc.readrom(address),
            0x8000 ... 0x9FFF => self.gpu.rb(address),
            0xA000 ... 0xBFFF => self.mbc.readram(address),
            0xC000 ... 0xCFFF | 0xE000 ... 0xEFFF => self.wram[address as usize & 0x0FFF],
            0xD000 ... 0xDFFF | 0xF000 ... 0xFDFF => self.wram[(self.wrambank * 0x1000) | address as usize & 0x0FFF],
            0xFE00 ... 0xFE9F => self.gpu.rb(address),
            0xFF00 => self.keypad.rb(),
            0xFF01 ... 0xFF02 => self.serial.rb(address),
            0xFF04 ... 0xFF07 => self.timer.rb(address),
            0xFF0F => self.intf,
            0xFF10 ... 0xFF3F => self.sound.as_mut().map_or(0, |s| s.rb(address)),
            0xFF4D => (if self.gbspeed == GbSpeed::Double { 0x80 } else { 0 }) | (if self.speed_switch_req { 1 } else { 0 }),
            0xFF40 ... 0xFF4F => self.gpu.rb(address),
            0xFF51 ... 0xFF55 => self.hdma_read(address),
            0xFF68 ... 0xFF6B => self.gpu.rb(address),
            0xFF70 => self.wrambank as u8,
            0xFF80 ... 0xFFFE => self.zram[address as usize & 0x007F],
            0xFFFF => self.inte,
            _ => 0,
        }
    }

    pub fn rw(&mut self, address: u16) -> u16 {
        (self.rb(address) as u16) | ((self.rb(address + 1) as u16) << 8)
    }

    pub fn wb(&mut self, address: u16, value: u8) {
        match address {
            0x0000 ... 0x7FFF => self.mbc.writerom(address, value),
            0x8000 ... 0x9FFF => self.gpu.wb(address, value),
            0xA000 ... 0xBFFF => self.mbc.writeram(address, value),
            0xC000 ... 0xCFFF | 0xE000 ... 0xEFFF => self.wram[address as usize & 0x0FFF] = value,
            0xD000 ... 0xDFFF | 0xF000 ... 0xFDFF => self.wram[(self.wrambank * 0x1000) | (address as usize & 0x0FFF)] = value,
            0xFE00 ... 0xFE9F => self.gpu.wb(address, value),
            0xFF00 => self.keypad.wb(value),
            0xFF01 ... 0xFF02 => self.serial.wb(address, value),
            0xFF04 ... 0xFF07 => self.timer.wb(address, value),
            0xFF10 ... 0xFF3F => self.sound.as_mut().map_or((), |s| s.wb(address, value)),
            0xFF46 => self.oamdma(value),
            0xFF4D => if value & 0x1 == 0x1 { self.speed_switch_req = true; },
            0xFF40 ... 0xFF4F => self.gpu.wb(address, value),
            0xFF51 ... 0xFF55 => self.hdma_write(address, value),
            0xFF68 ... 0xFF6B => self.gpu.wb(address, value),
            0xFF0F => self.intf = value,
            0xFF70 => { self.wrambank = match value & 0x7 { 0 => 1, n => n as usize }; },
            0xFF80 ... 0xFFFE => self.zram[address as usize & 0x007F] = value,
            0xFFFF => self.inte = value,
            _ => {},
        };
    }

    pub fn ww(&mut self, address: u16, value: u16) {
        self.wb(address, (value & 0xFF) as u8);
        self.wb(address + 1, (value >> 8) as u8);
    }

    pub fn switch_speed(&mut self) {
        if self.speed_switch_req {
            if self.gbspeed == GbSpeed::Double {
                self.gbspeed = GbSpeed::Single;
            } else {
                self.gbspeed = GbSpeed::Double;
            }
        }
        self.speed_switch_req = false;
    }

    fn oamdma(&mut self, value: u8) {
        let base = (value as u16) << 8;
        for i in (0u16 .. 0xA0) {
            let b = self.rb(base + i);
            self.wb(0xFE00 + i, b);
        }
    }

    fn hdma_read(&self, a: u16) -> u8 {
        match a {
            0xFF51 ... 0xFF54 => { self.hdma[(a - 0xFF51) as usize] },
            0xFF55 => self.hdma_len | if self.hdma_status == DMAType::NoDMA { 0x80 } else { 0 },
            _ => panic!("The address {:04X} should not be handled by hdma_read", a),
        }
    }

    fn hdma_write(&mut self, a: u16, v: u8) {
        match a {
            0xFF51 => self.hdma[0] = v,
            0xFF52 => self.hdma[1] = v & 0xF0,
            0xFF53 => self.hdma[2] = v & 0x1F,
            0xFF54 => self.hdma[3] = v & 0xF0,
            0xFF55 => {
                if self.hdma_status == DMAType::HDMA {
                    if v & 0x80 == 0 { self.hdma_status = DMAType::NoDMA; };
                    return;
                }
                let src = ((self.hdma[0] as u16) << 8) | (self.hdma[1] as u16);
                let dst = ((self.hdma[2] as u16) << 8) | (self.hdma[3] as u16) | 0x8000;
                if !(src <= 0x7FF0 || (src >= 0xA000 && src <= 0xDFF0)) { panic!("HDMA transfer with illegal start address {:04X}", src); }

                self.hdma_src = src;
                self.hdma_dst = dst;
                self.hdma_len = v & 0x7F;

                self.hdma_status =
                    if v & 0x80 == 0x80 { DMAType::HDMA }
                    else { DMAType::GDMA };
            },
            _ => panic!("The address {:04X} should not be handled by hdma_write", a),
        };
    }

    fn perform_vramdma(&mut self) -> u32 {
        match self.hdma_status {
            DMAType::NoDMA => 0,
            DMAType::GDMA => self.perform_gdma(),
            DMAType::HDMA => self.perform_hdma(),
        }
    }

    fn perform_hdma(&mut self) -> u32 {
        if self.gpu.may_hdma() == false {
            return 0;
        }

        self.perform_vramdma_row();
        if self.hdma_len == 0x7F { self.hdma_status = DMAType::NoDMA; }

        return 8;
    }

    fn perform_gdma(&mut self) -> u32 {
        let len = self.hdma_len as u32 + 1;
        for _i in (0 .. len) {
            self.perform_vramdma_row();
        }

        self.hdma_status = DMAType::NoDMA;
        return len * 8;
    }

    fn perform_vramdma_row(&mut self) {
        let mmu_src = self.hdma_src;
        for j in (0u16 .. 0x10) {
            let b: u8 = self.rb(mmu_src + j);
            self.gpu.wb(self.hdma_dst + j, b);
        }
        self.hdma_src += 0x10;
        self.hdma_dst += 0x10;

        if self.hdma_len == 0 {
            self.hdma_len = 0x7F;
        }
        else {
            self.hdma_len -= 1;
        }
    }
}
<|endoftext|>


<commit_before>use error::Error;

mod cmath {
    extern {
        pub fn lgamma(z: f64) -> f64;
    }
}

/// The natural logarithm of the gamma function [1].
///
/// [1]: https://www.encyclopediaofmath.org/index.php/Gamma-function
fn ln_gamma(z: f64) -> f64 {
    unsafe { cmath::lgamma(z) }
}

/// The complete beta function [1].
///
/// Computed using the equation [2] via the natural log-gamma function.
///
/// [1]: https://www.encyclopediaofmath.org/index.php/Beta-function
/// [2]: http://dlmf.nist.gov/8.17#E3
fn beta(a: f64, b: f64) -> f64 {
    (ln_gamma(a) + ln_gamma(b) - ln_gamma(a + b)).exp()
}

/// The regularized incomplete beta function [1].
///
/// We compute the incomplete beta function by using the modified Lentz's
/// algorithm [2] to evaluate its continued fraction representation [3].
/// Depending on the arguments, we use the symmetry relation [4] to guarantee a
/// bound that implies rapid convergence.
///
/// [1]: https://www.encyclopediaofmath.org/index.php/Incomplete_beta-function
/// [2]: "Numerical Recipes in C", 2nd Ed., p. 171
/// [3]: http://dlmf.nist.gov/8.17#E22
/// [4]: http://dlmf.nist.gov/8.17#E4
pub fn inc_beta(x: f64, a: f64, b: f64) -> Result<f64, Error> {
    if x < 0.0 { return Err(Error::Undefined); }
    if 1.0 < x { return Err(Error::Undefined); }

    let bound = (a + 1.0) / (a + b + 2.0);
    let ib = if x < bound {
        // The continued fraction will converge rapidly with the given args.

        // Leading coefficient of [3].
        let coeff = (x.powf(a) * (1.0 - x).powf(b))
            / (a * beta(a, b));

        coeff * inc_beta_cf(x, a, b)?
    } else {
        // Apply the identity `I_x(a, b) = 1 - I_{1-x}(b, a)` from [4].
        1.0 - inc_beta(1.0 - x, b, a)?
    };

    Ok(ib)
}

const INC_BETA_CF_APPX_ZERO: f64 = 1e-30;
const INC_BETA_CONVERGENCE_LIMIT: f64 = 1e-15;
const INC_BETA_MAX_ITER: usize = 1000;

/// This continued fraction part of the equation [1], evaluated using the
/// modified Lentz's algorithm.
///
/// [1]: http://dlmf.nist.gov/8.17#E22
fn inc_beta_cf(x: f64, a: f64, b: f64) -> Result<f64, Error> {
    let mut f = INC_BETA_CF_APPX_ZERO;
    let mut c = f;
    let mut d = 0.0;

    for i in 1..INC_BETA_MAX_ITER {
        let next = inc_beta_cf_step(x, a, b, i, f, c, d);
        let (_, _, _, del) = next;

        if (del - 1.0).abs() < INC_BETA_CONVERGENCE_LIMIT {
            return Ok(f);
        }

        f = next.0;
        c = next.1;
        d = next.2;
    }

    Err(Error::Diverged)
}

/// Compute the next partial evaluation of the continued fraction, given the last.
fn inc_beta_cf_step(x: f64, a: f64, b: f64, i: usize, f0: f64, c0: f64, d0: f64) -> (f64, f64, f64, f64) {
    // The `i`th numerator of the continued fraction. This is given by the
    // sequence `(1, d_1, d_2, ...)`, with `d_i` as defined in [1].
    //
    // [1]: http://dlmf.nist.gov/8.17#E23
    let cf_num = if i == 1 {
        1.0
    } else {
        cf_d(i - 1, x, a, b)
    };

    let mut d = 1.0 + cf_num * d0;
    if d.abs() < INC_BETA_CF_APPX_ZERO {
        d = INC_BETA_CF_APPX_ZERO;
    }
    d = d.recip();

    let mut c = 1.0 + cf_num / c0;
    if c.abs() < INC_BETA_CF_APPX_ZERO {
        c = INC_BETA_CF_APPX_ZERO;
    }

    let del = c * d;
    let f = f0 * del;

    (f, c, d, del)
}

/// The sequence `d_i` given in [1] to define the terms of the continued
/// fraction. Note that it depends on `x`, `a`, and `b`.
///
/// [1]: http://dlmf.nist.gov/8.17#E23
fn cf_d(i: usize, x: f64, a: f64, b: f64) -> f64 {
    if i % 2 == 0 {
        let m = (i / 2) as f64;
        cf_d_even(m, x, a, b)
    } else {
        let m = ((i - 1) / 2) as f64;
        cf_d_odd(m, x, a, b)
    }
}

/// Even terms `d_i` with `i = 2m`.
fn cf_d_even(m: f64, x: f64, a: f64, b: f64) -> f64 {
    let num = m * (b - m) * x;
    let den = (a + 2.0 * m - 1.0) * (a + 2.0 * m);
    num / den
}

/// Odd terms `d_i` with `i = 2m + 1`.
fn cf_d_odd(m: f64, x: f64, a: f64, b: f64) -> f64 {
    let num = (a + m) * (a + b + m) * x;
    let den = (a + 2.0 * m) * (a + 2.0 * m + 1.0);
    -num / den
}
<commit_msg>Check domain of all incomplete beta parameters<commit_after>use error::Error;

mod cmath {
    extern {
        pub fn lgamma(z: f64) -> f64;
    }
}

/// The natural logarithm of the gamma function [1].
///
/// [1]: https://www.encyclopediaofmath.org/index.php/Gamma-function
fn ln_gamma(z: f64) -> f64 {
    unsafe { cmath::lgamma(z) }
}

/// The complete beta function [1].
///
/// Computed using the equation [2] via the natural log-gamma function.
///
/// [1]: https://www.encyclopediaofmath.org/index.php/Beta-function
/// [2]: http://dlmf.nist.gov/8.17#E3
fn beta(a: f64, b: f64) -> f64 {
    (ln_gamma(a) + ln_gamma(b) - ln_gamma(a + b)).exp()
}

/// The regularized incomplete beta function [1].
///
/// We compute the incomplete beta function by using the modified Lentz's
/// algorithm [2] to evaluate its continued fraction representation [3].
/// Depending on the arguments, we use the symmetry relation [4] to guarantee a
/// bound that implies rapid convergence.
///
/// [1]: https://www.encyclopediaofmath.org/index.php/Incomplete_beta-function
/// [2]: "Numerical Recipes in C", 2nd Ed., p. 171
/// [3]: http://dlmf.nist.gov/8.17#E22
/// [4]: http://dlmf.nist.gov/8.17#E4
pub fn inc_beta(x: f64, a: f64, b: f64) -> Result<f64, Error> {
    if x < 0.0 { return Err(Error::Undefined); }
    if 1.0 < x { return Err(Error::Undefined); }
    if a <= 0.0 { return Err(Error::Undefined); }
    if b <= 0.0 { return Err(Error::Undefined); }

    let bound = (a + 1.0) / (a + b + 2.0);
    let ib = if x < bound {
        // The continued fraction will converge rapidly with the given args.

        // Leading coefficient of [3].
        let coeff = (x.powf(a) * (1.0 - x).powf(b))
            / (a * beta(a, b));

        coeff * inc_beta_cf(x, a, b)?
    } else {
        // Apply the identity `I_x(a, b) = 1 - I_{1-x}(b, a)` from [4].
        1.0 - inc_beta(1.0 - x, b, a)?
    };

    Ok(ib)
}

const INC_BETA_CF_APPX_ZERO: f64 = 1e-30;
const INC_BETA_CONVERGENCE_LIMIT: f64 = 1e-15;
const INC_BETA_MAX_ITER: usize = 1000;

/// This continued fraction part of the equation [1], evaluated using the
/// modified Lentz's algorithm.
///
/// [1]: http://dlmf.nist.gov/8.17#E22
fn inc_beta_cf(x: f64, a: f64, b: f64) -> Result<f64, Error> {
    let mut f = INC_BETA_CF_APPX_ZERO;
    let mut c = f;
    let mut d = 0.0;

    for i in 1..INC_BETA_MAX_ITER {
        let next = inc_beta_cf_step(x, a, b, i, f, c, d);
        let (_, _, _, del) = next;

        if (del - 1.0).abs() < INC_BETA_CONVERGENCE_LIMIT {
            return Ok(f);
        }

        f = next.0;
        c = next.1;
        d = next.2;
    }

    Err(Error::Diverged)
}

/// Compute the next partial evaluation of the continued fraction, given the last.
fn inc_beta_cf_step(x: f64, a: f64, b: f64, i: usize, f0: f64, c0: f64, d0: f64) -> (f64, f64, f64, f64) {
    // The `i`th numerator of the continued fraction. This is given by the
    // sequence `(1, d_1, d_2, ...)`, with `d_i` as defined in [1].
    //
    // [1]: http://dlmf.nist.gov/8.17#E23
    let cf_num = if i == 1 {
        1.0
    } else {
        cf_d(i - 1, x, a, b)
    };

    let mut d = 1.0 + cf_num * d0;
    if d.abs() < INC_BETA_CF_APPX_ZERO {
        d = INC_BETA_CF_APPX_ZERO;
    }
    d = d.recip();

    let mut c = 1.0 + cf_num / c0;
    if c.abs() < INC_BETA_CF_APPX_ZERO {
        c = INC_BETA_CF_APPX_ZERO;
    }

    let del = c * d;
    let f = f0 * del;

    (f, c, d, del)
}

/// The sequence `d_i` given in [1] to define the terms of the continued
/// fraction. Note that it depends on `x`, `a`, and `b`.
///
/// [1]: http://dlmf.nist.gov/8.17#E23
fn cf_d(i: usize, x: f64, a: f64, b: f64) -> f64 {
    if i % 2 == 0 {
        let m = (i / 2) as f64;
        cf_d_even(m, x, a, b)
    } else {
        let m = ((i - 1) / 2) as f64;
        cf_d_odd(m, x, a, b)
    }
}

/// Even terms `d_i` with `i = 2m`.
fn cf_d_even(m: f64, x: f64, a: f64, b: f64) -> f64 {
    let num = m * (b - m) * x;
    let den = (a + 2.0 * m - 1.0) * (a + 2.0 * m);
    num / den
}

/// Odd terms `d_i` with `i = 2m + 1`.
fn cf_d_odd(m: f64, x: f64, a: f64, b: f64) -> f64 {
    let num = (a + m) * (a + b + m) * x;
    let den = (a + 2.0 * m) * (a + 2.0 * m + 1.0);
    -num / den
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate gluon_codegen;
extern crate gluon;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate gluon_vm;

use gluon::base::types::ArcType;
use gluon::vm::api::{self, VmType};
use gluon::vm::{self, thread::ThreadInternal, ExternModule};
use gluon::{import, new_vm, Compiler, Thread};

#[derive(Getable, Debug, Serialize, Deserialize)]
enum TupleEnum {
    Variant,
    OtherVariant,
    One(u32),
    LotsOfTupleThings(i32, String, f64),
}

impl VmType for TupleEnum {
    type Type = TupleEnum;

    fn make_type(vm: &Thread) -> ArcType {
        vm.global_env()
            .get_env()
            .find_type_info("types.TupleEnum")
            .unwrap()
            .into_owned()
            .into_type()
    }
}

fn load_tuple_enum_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        tuple_enum_to_str => primitive!(1 tuple_enum_to_str),
    };

    ExternModule::new(vm, module)
}

fn tuple_enum_to_str(val: TupleEnum) -> String {
    format!("{:?}", val)
}

#[derive(Getable, Debug, Serialize, Deserialize)]
enum StructEnum {
    OneField { field: i32 },
    TwoFields { name: String, val: f64 },
}

impl VmType for StructEnum {
    type Type = StructEnum;

    fn make_type(vm: &Thread) -> ArcType {
        vm.global_env()
            .get_env()
            .find_type_info("types.StructEnum")
            .unwrap()
            .into_owned()
            .into_type()
    }
}

fn load_struct_enum_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        struct_enum_to_str => primitive!(1 struct_enum_to_str),
    };

    ExternModule::new(vm, module)
}

fn struct_enum_to_str(val: StructEnum) -> String {
    format!("{:?}", val)
}

#[derive(Getable, Debug, Serialize, Deserialize)]
enum GenericEnum<'a, T>
where
    T: 'static + Into<String>,
{
    Val(T),
    Lifetime(&'a str),
}

impl<'a, T> VmType for GenericEnum<'a, T>
where
    T: 'static + Into<String>,
{
    type Type = GenericEnum<'static, T>;

    fn make_type(vm: &Thread) -> ArcType {
        vm.global_env()
            .get_env()
            .find_type_info("types.GenericEnum")
            .unwrap()
            .into_owned()
            .into_type()
    }
}

fn load_generic_enum_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        generic_enum_to_str => primitive!(1 generic_enum_to_str),
    };

    ExternModule::new(vm, module)
}

fn generic_enum_to_str(val: GenericEnum<String>) -> String {
    format!("{:?}", val)
}

#[test]
fn enum_tuple_variants() {
    let vm = new_vm();
    let mut compiler = Compiler::new();

    let src = api::typ::make_source::<TupleEnum>(&vm).unwrap();
    compiler.load_script(&vm, "types", &src).unwrap();
    import::add_extern_module(&vm, "functions", load_tuple_enum_mod);

    let script = r#"
        let { TupleEnum } = import! types
        let { tuple_enum_to_str } = import! functions
        let { assert } = import! std.test

        assert (tuple_enum_to_str Variant == "Variant")
        assert (tuple_enum_to_str OtherVariant == "OtherVariant")
        assert (tuple_enum_to_str (One 1) == "One(1)")
        assert (tuple_enum_to_str (LotsOfTupleThings 42 "Text" 0.0) == "LotsOfTupleThings(42, \"Text\", 0.0)")
    "#;

    if let Err(why) = compiler.run_expr::<()>(&vm, "test", script) {
        panic!("{}", why);
    }
}

#[test]
fn enum_struct_variants() {
    let vm = new_vm();
    let mut compiler = Compiler::new();

    let src = api::typ::make_source::<StructEnum>(&vm).unwrap();
    compiler.load_script(&vm, "types", &src).unwrap();
    import::add_extern_module(&vm, "functions", load_struct_enum_mod);

    let script = r#"
        let { StructEnum } = import! types
        let { struct_enum_to_str } = import! functions
        let { assert } = import! std.test

        assert (struct_enum_to_str (OneField 1337) == "OneField { field: 1337 }")
        assert (struct_enum_to_str (TwoFields "Pi" 3.14) == "TwoFields { name: \"Pi\", val: 3.14 }")
    "#;

    if let Err(why) = compiler.run_expr::<()>(&vm, "test", script) {
        panic!("{}", why);
    }
}

// TODO: needs safe interface for Getable::from_value() when used with references
#[test]
#[ignore]
fn enum_generic_variants() {
    let vm = new_vm();
    let mut compiler = Compiler::new();

    // make_source does not work with &str
    let src = r#"
        type GenericEnum = | Val String | Lifetime String
        { GenericEnum }
    "#;

    compiler.load_script(&vm, "types", src).unwrap();
    import::add_extern_module(&vm, "functions", load_generic_enum_mod);

    let script = r#"
        let { GenericEnum } = import! types
        let { generic_enum_to_str } = import! functions
        let { assert } = import! std.test

        assert (generic_enum_to_str (Lifetime "'vm") == "Lifetime(\"'vm\")")
        assert (generic_enum_to_str (Val "str") == "Val(\"str\")")
    "#;

    if let Err(why) = compiler.run_expr::<()>(&vm, "test", script) {
        panic!("{}", why);
    }
}

#[derive(Getable, Debug, Serialize, Deserialize)]
struct Struct {
    string: String,
    int: i32,
    tuple: (f64, f64),
}

impl VmType for Struct {
    type Type = Struct;

    fn make_type(vm: &Thread) -> ArcType {
        vm.global_env()
            .get_env()
            .find_type_info("types.Struct")
            .unwrap()
            .into_owned()
            .into_type()
    }
}

fn load_struct_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        struct_to_str => primitive!(1 struct_to_str),
    };

    ExternModule::new(vm, module)
}

fn struct_to_str(val: Struct) -> String {
    format!("{:?}", val)
}

#[test]
fn struct_derive() {
    let vm = new_vm();
    let mut compiler = Compiler::new();

    let src = api::typ::make_source::<Struct>(&vm).unwrap();
    compiler.load_script(&vm, "types", &src).unwrap();
    import::add_extern_module(&vm, "functions", load_struct_mod);

    let script = r#"
        let { Struct } = import! types
        let { struct_to_str } = import! functions
        let { assert } = import! std.test

        assert (struct_to_str { string = "test", int = 55, tuple = (0.0, 1.0) } == "Struct { string: \"test\", int: 55, tuple: (0.0, 1.0) }")
    "#;

    if let Err(why) = compiler.run_expr::<()>(&vm, "test", script) {
        panic!("{}", why);
    }
}
<commit_msg>Reorder tests to make them more readable<commit_after>#[macro_use]
extern crate gluon_codegen;
extern crate gluon;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate gluon_vm;

use gluon::base::types::ArcType;
use gluon::vm::api::{self, VmType};
use gluon::vm::{self, thread::ThreadInternal, ExternModule};
use gluon::{import, new_vm, Compiler, Thread};

#[derive(Getable, Debug, Serialize, Deserialize)]
enum TupleEnum {
    Variant,
    OtherVariant,
    One(u32),
    LotsOfTupleThings(i32, String, f64),
}

impl VmType for TupleEnum {
    type Type = TupleEnum;

    fn make_type(vm: &Thread) -> ArcType {
        vm.global_env()
            .get_env()
            .find_type_info("types.TupleEnum")
            .unwrap()
            .into_owned()
            .into_type()
    }
}

fn load_tuple_enum_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        tuple_enum_to_str => primitive!(1 tuple_enum_to_str),
    };

    ExternModule::new(vm, module)
}

fn tuple_enum_to_str(val: TupleEnum) -> String {
    format!("{:?}", val)
}

#[test]
fn enum_tuple_variants() {
    let vm = new_vm();
    let mut compiler = Compiler::new();

    let src = api::typ::make_source::<TupleEnum>(&vm).unwrap();
    compiler.load_script(&vm, "types", &src).unwrap();
    import::add_extern_module(&vm, "functions", load_tuple_enum_mod);

    let script = r#"
        let { TupleEnum } = import! types
        let { tuple_enum_to_str } = import! functions
        let { assert } = import! std.test

        assert (tuple_enum_to_str Variant == "Variant")
        assert (tuple_enum_to_str OtherVariant == "OtherVariant")
        assert (tuple_enum_to_str (One 1) == "One(1)")
        assert (tuple_enum_to_str (LotsOfTupleThings 42 "Text" 0.0) == "LotsOfTupleThings(42, \"Text\", 0.0)")
    "#;

    if let Err(why) = compiler.run_expr::<()>(&vm, "test", script) {
        panic!("{}", why);
    }
}

#[derive(Getable, Debug, Serialize, Deserialize)]
enum StructEnum {
    OneField { field: i32 },
    TwoFields { name: String, val: f64 },
}

impl VmType for StructEnum {
    type Type = StructEnum;

    fn make_type(vm: &Thread) -> ArcType {
        vm.global_env()
            .get_env()
            .find_type_info("types.StructEnum")
            .unwrap()
            .into_owned()
            .into_type()
    }
}

fn load_struct_enum_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        struct_enum_to_str => primitive!(1 struct_enum_to_str),
    };

    ExternModule::new(vm, module)
}

fn struct_enum_to_str(val: StructEnum) -> String {
    format!("{:?}", val)
}

#[test]
fn enum_struct_variants() {
    let vm = new_vm();
    let mut compiler = Compiler::new();

    let src = api::typ::make_source::<StructEnum>(&vm).unwrap();
    compiler.load_script(&vm, "types", &src).unwrap();
    import::add_extern_module(&vm, "functions", load_struct_enum_mod);

    let script = r#"
        let { StructEnum } = import! types
        let { struct_enum_to_str } = import! functions
        let { assert } = import! std.test

        assert (struct_enum_to_str (OneField 1337) == "OneField { field: 1337 }")
        assert (struct_enum_to_str (TwoFields "Pi" 3.14) == "TwoFields { name: \"Pi\", val: 3.14 }")
    "#;

    if let Err(why) = compiler.run_expr::<()>(&vm, "test", script) {
        panic!("{}", why);
    }
}

#[derive(Getable, Debug, Serialize, Deserialize)]
enum GenericEnum<'a, T>
where
    T: 'static + Into<String>,
{
    Val(T),
    Lifetime(&'a str),
}

impl<'a, T> VmType for GenericEnum<'a, T>
where
    T: 'static + Into<String>,
{
    type Type = GenericEnum<'static, T>;

    fn make_type(vm: &Thread) -> ArcType {
        vm.global_env()
            .get_env()
            .find_type_info("types.GenericEnum")
            .unwrap()
            .into_owned()
            .into_type()
    }
}

fn load_generic_enum_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        generic_enum_to_str => primitive!(1 generic_enum_to_str),
    };

    ExternModule::new(vm, module)
}

fn generic_enum_to_str(val: GenericEnum<String>) -> String {
    format!("{:?}", val)
}

// TODO: needs safe interface for Getable::from_value() when used with references
#[test]
#[ignore]
fn enum_generic_variants() {
    let vm = new_vm();
    let mut compiler = Compiler::new();

    // make_source does not work with &str
    let src = r#"
        type GenericEnum = | Val String | Lifetime String
        { GenericEnum }
    "#;

    compiler.load_script(&vm, "types", src).unwrap();
    import::add_extern_module(&vm, "functions", load_generic_enum_mod);

    let script = r#"
        let { GenericEnum } = import! types
        let { generic_enum_to_str } = import! functions
        let { assert } = import! std.test

        assert (generic_enum_to_str (Lifetime "'vm") == "Lifetime(\"'vm\")")
        assert (generic_enum_to_str (Val "str") == "Val(\"str\")")
    "#;

    if let Err(why) = compiler.run_expr::<()>(&vm, "test", script) {
        panic!("{}", why);
    }
}

#[derive(Getable, Debug, Serialize, Deserialize)]
struct Struct {
    string: String,
    int: i32,
    tuple: (f64, f64),
}

impl VmType for Struct {
    type Type = Struct;

    fn make_type(vm: &Thread) -> ArcType {
        vm.global_env()
            .get_env()
            .find_type_info("types.Struct")
            .unwrap()
            .into_owned()
            .into_type()
    }
}

fn load_struct_mod(vm: &Thread) -> vm::Result<ExternModule> {
    let module = record! {
        struct_to_str => primitive!(1 struct_to_str),
    };

    ExternModule::new(vm, module)
}

fn struct_to_str(val: Struct) -> String {
    format!("{:?}", val)
}

#[test]
fn struct_derive() {
    let vm = new_vm();
    let mut compiler = Compiler::new();

    let src = api::typ::make_source::<Struct>(&vm).unwrap();
    compiler.load_script(&vm, "types", &src).unwrap();
    import::add_extern_module(&vm, "functions", load_struct_mod);

    let script = r#"
        let { Struct } = import! types
        let { struct_to_str } = import! functions
        let { assert } = import! std.test

        assert (struct_to_str { string = "test", int = 55, tuple = (0.0, 1.0) } == "Struct { string: \"test\", int: 55, tuple: (0.0, 1.0) }")
    "#;

    if let Err(why) = compiler.run_expr::<()>(&vm, "test", script) {
        panic!("{}", why);
    }
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::Deref;

use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor};
use serde::de::value::BorrowedStrDeserializer;

use error::Error;

/// Represents any valid JSON value as a series of raw bytes.
///
/// This type can be used to defer parsing parts of a payload until later,
/// or to embed it verbatim into another JSON payload.
///
/// When serializing, a value of this type will retain its original formatting
/// and will not be minified or pretty-printed.
///
/// When deserializing, this type can not be used with the `#[serde(flatten)]` attribute,
/// as it relies on the original input buffer.
#[repr(C)]
pub struct RawSlice {
    borrowed: str,
}

///
pub struct RawValue {
    owned: Box<RawSlice>,
}

impl RawSlice {
    fn from_inner(borrowed: &str) -> &Self {
        unsafe { mem::transmute::<&str, &RawSlice>(borrowed) }
    }
}

impl RawValue {
    fn from_inner(owned: Box<str>) -> Self {
        RawValue {
            owned: unsafe { mem::transmute::<Box<str>, Box<RawSlice>>(owned) },
        }
    }
}

impl Clone for RawValue {
    fn clone(&self) -> Self {
        self.owned.to_owned()
    }
}

impl Deref for RawValue {
    type Target = RawSlice;

    fn deref(&self) -> &Self::Target {
        &self.owned
    }
}

impl Borrow<RawSlice> for RawValue {
    fn borrow(&self) -> &RawSlice {
        &self.owned
    }
}

impl ToOwned for RawSlice {
    type Owned = RawValue;

    fn to_owned(&self) -> Self::Owned {
        RawValue::from_inner(self.borrowed.to_owned().into_boxed_str())
    }
}

impl Debug for RawSlice {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_tuple("RawSlice")
            .field(&format_args!("{}", &self.borrowed))
            .finish()
    }
}

impl Debug for RawValue {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_tuple("RawValue")
            .field(&format_args!("{}", &self.owned.borrowed))
            .finish()
    }
}

impl RawSlice {
    ///
    pub fn as_ref(&self) -> &str {
        &self.borrowed
    }
}

impl Display for RawSlice {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.borrowed)
    }
}

impl Display for RawValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&**self, f)
    }
}

pub const TOKEN: &'static str = "$serde_json::private::RawValue";

impl Serialize for RawSlice {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut s = serializer.serialize_struct(TOKEN, 1)?;
        s.serialize_field(TOKEN, &self.borrowed)?;
        s.end()
    }
}

impl Serialize for RawValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        (**self).serialize(serializer)
    }
}

impl<'de: 'a, 'a> Deserialize<'de> for &'a RawSlice {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct RawSliceVisitor;

        impl<'de> Visitor<'de> for RawSliceVisitor {
            type Value = &'de RawSlice;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(RawSliceFromString)
            }
        }

        deserializer.deserialize_newtype_struct(TOKEN, RawSliceVisitor)
    }
}

impl<'de> Deserialize<'de> for RawValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct RawValueVisitor;

        impl<'de> Visitor<'de> for RawValueVisitor {
            type Value = RawValue;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(RawValueFromString)
            }
        }

        deserializer.deserialize_newtype_struct(TOKEN, RawValueVisitor)
    }
}

struct RawKey;

impl<'de> Deserialize<'de> for RawKey {
    fn deserialize<D>(deserializer: D) -> Result<RawKey, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct FieldVisitor;

        impl<'de> Visitor<'de> for FieldVisitor {
            type Value = ();

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("raw value")
            }

            fn visit_str<E>(self, s: &str) -> Result<(), E>
            where
                E: de::Error,
            {
                if s == TOKEN {
                    Ok(())
                } else {
                    Err(de::Error::custom("unexpected raw value"))
                }
            }
        }

        deserializer.deserialize_identifier(FieldVisitor)?;
        Ok(RawKey)
    }
}

pub struct RawSliceFromString;

impl<'de> DeserializeSeed<'de> for RawSliceFromString {
    type Value = &'de RawSlice;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for RawSliceFromString {
    type Value = &'de RawSlice;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawSlice::from_inner(s))
    }
}

pub struct RawValueFromString;

impl<'de> DeserializeSeed<'de> for RawValueFromString {
    type Value = RawValue;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for RawValueFromString {
    type Value = RawValue;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        self.visit_string(s.to_owned())
    }

    fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue::from_inner(s.into_boxed_str()))
    }
}

struct RawKeyDeserializer;

impl<'de> Deserializer<'de> for RawKeyDeserializer {
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_borrowed_str(TOKEN)
    }

    forward_to_deserialize_any! {
        bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq
        bytes byte_buf map struct option unit newtype_struct ignored_any
        unit_struct tuple_struct tuple enum identifier
    }
}

pub struct OwnedRawDeserializer {
    pub raw_value: Option<String>,
}

impl<'de> MapAccess<'de> for OwnedRawDeserializer {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(self.raw_value.take().unwrap().into_deserializer())
    }
}

pub struct BorrowedRawDeserializer<'de> {
    pub raw_value: Option<&'de str>,
}

impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap()))
    }
}
<commit_msg>Document RawSlice<commit_after>use std::borrow::Borrow;
use std::fmt::{self, Debug, Display};
use std::mem;
use std::ops::Deref;

use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{self, Deserialize, Deserializer, DeserializeSeed, IntoDeserializer, MapAccess, Unexpected, Visitor};
use serde::de::value::BorrowedStrDeserializer;

use error::Error;

/// Reference to a range of bytes encompassing a single valid JSON value in the
/// input data.
///
/// A `RawSlice` can be used to defer parsing parts of a payload until later,
/// or to avoid parsing it at all in the case that part of the payload just
/// needs to be transferred verbatim into a different output object.
///
/// When serializing, a value of this type will retain its original formatting
/// and will not be minified or pretty-printed.
///
/// # Example
///
/// ```
/// #[macro_use]
/// extern crate serde_derive;
/// extern crate serde_json;
///
/// use serde_json::{Result, value::RawSlice};
///
/// #[derive(Deserialize)]
/// struct Input<'a> {
///     code: u32,
///     #[serde(borrow)]
///     payload: &'a RawSlice,
/// }
///
/// #[derive(Serialize)]
/// struct Output<'a> {
///     info: (u32, &'a RawSlice),
/// }
///
/// // Efficiently rearrange JSON input containing separate "code" and "payload"
/// // keys into a single "info" key holding an array of code and payload.
/// //
/// // This could be done equivalently using serde_json::Value as the type for
/// // payload, but &RawSlice will perform netter because it does not require
/// // memory allocation. The correct range of bytes is borrowed from the input
/// // data and pasted verbatim into the output.
/// fn rearrange(input: &str) -> Result<String> {
///     let input: Input = serde_json::from_str(input)?;
///
///     let output = Output {
///         info: (input.code, input.payload),
///     };
///
///     serde_json::to_string(&output)
/// }
///
/// fn main() -> Result<()> {
///     let out = rearrange(r#" {"code": 200, "payload": {}} "#)?;
///
///     assert_eq!(out, r#"{"info":[200,{}]}"#);
///
///     Ok(())
/// }
/// ```
///
/// # Note
///
/// `RawSlice` is only available if serde\_json is built with the `"raw_value"`
/// feature.
///
/// ```toml
/// [dependencies]
/// serde_json = { version = "1.0", features = ["raw_value"] }
/// ```
#[repr(C)]
pub struct RawSlice {
    borrowed: str,
}

///
pub struct RawValue {
    owned: Box<RawSlice>,
}

impl RawSlice {
    fn from_inner(borrowed: &str) -> &Self {
        unsafe { mem::transmute::<&str, &RawSlice>(borrowed) }
    }
}

impl RawValue {
    fn from_inner(owned: Box<str>) -> Self {
        RawValue {
            owned: unsafe { mem::transmute::<Box<str>, Box<RawSlice>>(owned) },
        }
    }
}

impl Clone for RawValue {
    fn clone(&self) -> Self {
        self.owned.to_owned()
    }
}

impl Deref for RawValue {
    type Target = RawSlice;

    fn deref(&self) -> &Self::Target {
        &self.owned
    }
}

impl Borrow<RawSlice> for RawValue {
    fn borrow(&self) -> &RawSlice {
        &self.owned
    }
}

impl ToOwned for RawSlice {
    type Owned = RawValue;

    fn to_owned(&self) -> Self::Owned {
        RawValue::from_inner(self.borrowed.to_owned().into_boxed_str())
    }
}

impl Debug for RawSlice {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_tuple("RawSlice")
            .field(&format_args!("{}", &self.borrowed))
            .finish()
    }
}

impl Debug for RawValue {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_tuple("RawValue")
            .field(&format_args!("{}", &self.owned.borrowed))
            .finish()
    }
}

impl RawSlice {
    /// Access the JSON text underlying a raw value.
    ///
    /// # Example
    ///
    /// ```
    /// #[macro_use]
    /// extern crate serde_derive;
    /// extern crate serde_json;
    ///
    /// use serde_json::{Result, value::RawSlice};
    ///
    /// #[derive(Deserialize)]
    /// struct Response<'a> {
    ///     code: u32,
    ///     #[serde(borrow)]
    ///     payload: &'a RawSlice,
    /// }
    ///
    /// fn process(input: &str) -> Result<()> {
    ///     let response: Response = serde_json::from_str(input)?;
    ///
    ///     let payload = response.payload.as_ref();
    ///     if payload.starts_with('{') {
    ///         // handle a payload which is a JSON map
    ///     } else {
    ///         // handle any other type
    ///     }
    ///
    ///     Ok(())
    /// }
    ///
    /// fn main() -> Result<()> {
    ///     process(r#" {"code": 200, "payload": {}} "#)?;
    ///     Ok(())
    /// }
    /// ```
    pub fn as_ref(&self) -> &str {
        &self.borrowed
    }
}

impl Display for RawSlice {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.borrowed)
    }
}

impl Display for RawValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&**self, f)
    }
}

pub const TOKEN: &'static str = "$serde_json::private::RawValue";

impl Serialize for RawSlice {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut s = serializer.serialize_struct(TOKEN, 1)?;
        s.serialize_field(TOKEN, &self.borrowed)?;
        s.end()
    }
}

impl Serialize for RawValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        (**self).serialize(serializer)
    }
}

impl<'de: 'a, 'a> Deserialize<'de> for &'a RawSlice {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct RawSliceVisitor;

        impl<'de> Visitor<'de> for RawSliceVisitor {
            type Value = &'de RawSlice;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(RawSliceFromString)
            }
        }

        deserializer.deserialize_newtype_struct(TOKEN, RawSliceVisitor)
    }
}

impl<'de> Deserialize<'de> for RawValue {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct RawValueVisitor;

        impl<'de> Visitor<'de> for RawValueVisitor {
            type Value = RawValue;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "any valid JSON value")
            }

            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: MapAccess<'de>,
            {
                let value = visitor.next_key::<RawKey>()?;
                if value.is_none() {
                    return Err(de::Error::invalid_type(Unexpected::Map, &self));
                }
                visitor.next_value_seed(RawValueFromString)
            }
        }

        deserializer.deserialize_newtype_struct(TOKEN, RawValueVisitor)
    }
}

struct RawKey;

impl<'de> Deserialize<'de> for RawKey {
    fn deserialize<D>(deserializer: D) -> Result<RawKey, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct FieldVisitor;

        impl<'de> Visitor<'de> for FieldVisitor {
            type Value = ();

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("raw value")
            }

            fn visit_str<E>(self, s: &str) -> Result<(), E>
            where
                E: de::Error,
            {
                if s == TOKEN {
                    Ok(())
                } else {
                    Err(de::Error::custom("unexpected raw value"))
                }
            }
        }

        deserializer.deserialize_identifier(FieldVisitor)?;
        Ok(RawKey)
    }
}

pub struct RawSliceFromString;

impl<'de> DeserializeSeed<'de> for RawSliceFromString {
    type Value = &'de RawSlice;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for RawSliceFromString {
    type Value = &'de RawSlice;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_borrowed_str<E>(self, s: &'de str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawSlice::from_inner(s))
    }
}

pub struct RawValueFromString;

impl<'de> DeserializeSeed<'de> for RawValueFromString {
    type Value = RawValue;

    fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_str(self)
    }
}

impl<'de> Visitor<'de> for RawValueFromString {
    type Value = RawValue;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("raw value")
    }

    fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        self.visit_string(s.to_owned())
    }

    fn visit_string<E>(self, s: String) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        Ok(RawValue::from_inner(s.into_boxed_str()))
    }
}

struct RawKeyDeserializer;

impl<'de> Deserializer<'de> for RawKeyDeserializer {
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_borrowed_str(TOKEN)
    }

    forward_to_deserialize_any! {
        bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq
        bytes byte_buf map struct option unit newtype_struct ignored_any
        unit_struct tuple_struct tuple enum identifier
    }
}

pub struct OwnedRawDeserializer {
    pub raw_value: Option<String>,
}

impl<'de> MapAccess<'de> for OwnedRawDeserializer {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(self.raw_value.take().unwrap().into_deserializer())
    }
}

pub struct BorrowedRawDeserializer<'de> {
    pub raw_value: Option<&'de str>,
}

impl<'de> MapAccess<'de> for BorrowedRawDeserializer<'de> {
    type Error = Error;

    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
    where
        K: de::DeserializeSeed<'de>,
    {
        if self.raw_value.is_none() {
            return Ok(None);
        }
        seed.deserialize(RawKeyDeserializer).map(Some)
    }

    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
    where
        V: de::DeserializeSeed<'de>,
    {
        seed.deserialize(BorrowedStrDeserializer::new(self.raw_value.take().unwrap()))
    }
}
<|endoftext|>