<commit_before>//! This module implements a simple asset loader and cache.
//!
//! While ggez offers functions to load raw game assets such as
//! music files, images, etc, it provides no facilities for managing
//! them.  Ideally you want to load all the assets you need at once,
//! hold on to them for a time (the course of a level for instance),
//! and then potentially ditch the ones you don't need.
//! This module offers cache-like functionality to do exactly this.
//!
//! It will return an `Rc` containing the item loaded, so multiple
//! items can safely access (read-only) instances of the same asset.
//! (In the same thread, at least.)
//!
//! What it does NOT do is allow you to free individual assets from
//! the cache.  This is on purpose.  If you want fine-grained manual
//! memory management you know where to get it.  This is more a memory
//! pool like thing where you allocate a bunch of objects, keep them
//! around for however long you need them (while the game is loaded,
//! while a particular scene is loaded, etc), and then free them all.
//!
//! If you want to make a stack of asset managers, where one
//! has access to the assets higher up in the stack...
//! Just build one and clone it.  All the Rc's in it will get
//! cloned along with it, providing exactly the behavior you
//! want except better.  :D
//!
//! Though whether or not asset handles from the old one will be valid
//! with the new one... hmmm.  That might not be a big problem since we
//! can just request new asset handles from the new cache and they'll already
//! be there, so that might be the way to go?

// TODO: This is not thread safe; should we offer one that it?
// TODO: Check out calx-resource:
// https://github.com/rsaarelm/calx/blob/master/calx-resource/src/lib.rs
// It has a) nifty macros to build these automatically,
// and b) an asset type that will serialize to a key, and then
// deserialize the key to that asset.  Very neat!  But also
// a bit labyrenthine.
// It DOES also make thread-safety work through thread_local!().

use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::fmt::Debug;
use std::path::Path;
use std::rc::Rc;
use ggez;
use ggez::{Context, GameError, GameResult};
use ggez::graphics;

pub trait Loadable<K, E> {
    fn load(_key: &K) -> Result<Self, E> where Self: Sized;
}

pub trait StateLoadable<K, E, S> {
    fn load_state(_key: &K, &mut S) -> Result<Self, E> where Self: Sized;
}

#[derive(Debug, Clone)]
pub struct AssetCache<K, V>
    where K: Ord + Clone + Debug
{
    contents: BTreeMap<K, Rc<V>>,
}

impl<K, V> AssetCache<K, V>
    where K: Ord + Clone + Debug
{
    /// Creates a new `AssetCache` that loads assets
    /// when necessary with the given loader function.
    pub fn new() -> Self {
        let map = BTreeMap::new();
        AssetCache { contents: map }
    }

    /// Gets the given asset, loading it if necessary.
    // Oh my goodness getting the E type param to the
    // right place was amazingly difficult.
    pub fn get<E>(&mut self, key: &K) -> Result<Rc<V>, E>
        where V: Loadable<K, E>
    {
        if let Some(v) = self.contents.get(key) {
            return Ok(v.clone());
        };

        let v = V::load(key)?;
        let v_rc = Rc::new(v);
        self.contents.insert(key.clone(), v_rc.clone());
        Ok(v_rc)
    }

    pub fn get_mut<E, S>(&mut self, key: &K) -> Result<&mut Rc<V>, E>
        where V: Loadable<K, E>
    {
        // entry.or_insert_with() isn't quite powerful
        // enough 'cause it doesn't propegate results.  ;_;
        let entry = self.contents.entry(key.clone());
        match entry {
            Entry::Vacant(e) => {
                let v = V::load(key)?;
                let v_rc = Rc::new(v);
                Ok(e.insert(v_rc))
            }
            Entry::Occupied(e) => Ok(e.into_mut()),
        }
    }

    /// Gets the given asset, loading it if necessary.
    pub fn get_state<E, S>(&mut self, key: &K, state: &mut S) -> Result<Rc<V>, E>
        where V: StateLoadable<K, E, S>
    {
        if let Some(v) = self.contents.get(key) {
            return Ok(v.clone());
        };

        let v = V::load_state(key, state)?;
        let v_rc = Rc::new(v);
        self.contents.insert(key.clone(), v_rc.clone());
        Ok(v_rc)
    }

    pub fn get_state_mut<E, S>(&mut self, key: &K, state: &mut S) -> Result<&mut Rc<V>, E>
        where V: StateLoadable<K, E, S>
    {
        // entry.or_insert_with() isn't quite powerful
        // enough 'cause it doesn't propegate results.  ;_;
        let entry = self.contents.entry(key.clone());
        match entry {
            Entry::Vacant(e) => {
                let v = V::load_state(key, state)?;
                let v_rc = Rc::new(v);
                Ok(e.insert(v_rc))
            }
            Entry::Occupied(e) => Ok(e.into_mut()),
        }
    }

    /// Removes all assets from the cache
    /// and frees any excess memory it uses.
    pub fn clear(&mut self) {
        let map = BTreeMap::new();
        self.contents = map;
    }

    /// Returns true if the given asset is loaded.
    pub fn loaded(&self, key: &K) -> bool {
        self.contents.contains_key(key)
    }

    /// Takes a slice containing a list of keys,
    /// and loads all the keys so that their objects
    /// are immediately accessible.
    pub fn preload<E>(&mut self, keys: &[K])
        where V: Loadable<K, E>
    {
        for k in keys {
            let _ = self.get(k);
        }
    }

    /// Preloads objects that require a state to load.
    pub fn preload_state<E, S>(&mut self, keys: &[K], state: &mut S)
        where V: StateLoadable<K, E, S>
    {
        for k in keys {
            let _ = self.get_state(k, state);
        }
    }

    /// Gets an object but only if it already exists in the
    /// wossname.
    /// Returns an error if it is not.
    pub fn get_preload(&mut self, key: &K) -> GameResult<Rc<V>> {
        if let Some(val) = self.contents.get(key) {
            Ok(val.clone())
        } else {
            let errmsg = format!("Tried to get asset {:?} but it was not preloaded!", key);
            let err = GameError::ResourceNotFound(errmsg, vec![]);
            Err(err)

        }
    }

    pub fn get_preload_mut(&mut self, key: &K) -> GameResult<&mut Rc<V>> {
        if let Some(val) = self.contents.get_mut(key) {
            Ok(val)
        } else {
            let errmsg = format!("Tried to get asset {:?} but it was not preloaded!", key);
            let err = GameError::ResourceNotFound(errmsg, vec![]);
            Err(err)

        }
    }
}

impl<K: AsRef<Path>> StateLoadable<K, GameError, ggez::Context> for ggez::graphics::Image {
    fn load_state(key: &K, ctx: &mut Context) -> GameResult<Self> {
        graphics::Image::new(ctx, key)
    }
}

/// An opaque asset handle that can be used for O(1) fetches
/// of assets.
// TODO: Add a UUID or something to this....
#[derive(Debug, Copy, Clone)]
pub struct AssetHandle(usize);

// We COULD use a generic interning crate such as symtern or symbol-map to
// implement the Handle -> Asset map here.  It might be useful.
// But it wouldn't get us all the way because we'd still need to maintain
// the Key -> Handle association ourselves.
#[derive(Debug, Clone)]
pub struct AssetCache2<K, V>
    where K: Ord + Clone + Debug
{
    handles: Vec<Rc<V>>,
    keys: BTreeMap<K, AssetHandle>,
    next_handle: usize,
}

impl<K, V> AssetCache2<K, V>
    where K: Ord + Clone + Debug
{
    /// Creates a new `AssetCache` that loads assets
    /// when necessary with the given loader function.
    pub fn new() -> Self {
        AssetCache2 {
            handles: Vec::new(),
            keys: BTreeMap::new(),
            next_handle: 0,
        }
    }

    fn new_handle(&mut self) -> AssetHandle {
        let i = self.next_handle;
        self.next_handle += 1;
        AssetHandle(i)
    }

    // Inserts the given asset into the handles vec at the given
    // location, and inserts the key into the key->handle mapping.
    // Performs asserts that will panic if something
    // gets out of sync (which should be impossible).
    fn bind_handle(&mut self, key: K, h: AssetHandle, value: Rc<V>) {
        let AssetHandle(i) = h;
        assert!(i == self.handles.len());
        self.handles.push(value);

        assert!(!self.keys.contains_key(&key));
        self.keys.insert(key, h);
    }

    // Adds a new item to the cache, returns an Rc reference to it
    // and an AssetHandle.
    fn add_item(&mut self, key: K, value: V) -> (AssetHandle, Rc<V>) {
        let handle = self.new_handle();
        let rc = Rc::new(value);
        self.bind_handle(key, handle, rc.clone());
        (handle, rc)
    }

    /// Retrieves an asset via its handle.
    /// This is always safe (and fast) because for a handle
    /// to be valid its object *must* exist in the cache.
    pub fn get(&self, handle: AssetHandle) -> Rc<V> {
        let AssetHandle(i) = handle;
        assert!(i < self.handles.len());
        self.handles[i].clone()
    }

    /// Not sure this is even right, but...
    pub fn get_mut<'a>(&'a mut self, handle: AssetHandle) -> Option<&'a mut V> {
        let AssetHandle(i) = handle;
        assert!(i < self.handles.len());
        use std::rc::Rc;
        Rc::get_mut(&mut self.handles[i])
    }

    // fn add_item_mut(&mut self, key: K, value: &mut V) -> (AssetHandle, Rc<&mut V>) {
    //     let handle = self.new_handle();
    //     let entry = self.entry(key.clone());
    //     match entry {
    //         Entry::Vacant(e) => {
    //             let v = V::load(key)?;
    //             let v_rc = Rc::new(v);
    //             Ok(e.insert(v_rc));
    //             Ok(self.add_item(key.clone(), v));
    //         }
    //         Entry::Occupied(e) => Ok(e.into_mut()),
    //     }

    // }

    /// Gets the given asset, loading it if necessary.
    /// Returns an Rc to the value, plus an AssetHandle
    /// which can be used to retrieve it quickly.
    // Oh my goodness getting the E type param to the
    // right place was amazingly difficult.
    pub fn get_key<E>(&mut self, key: &K) -> Result<(AssetHandle, Rc<V>), E>
        where V: Loadable<K, E>
    {
        if let Some(handle) = self.keys.get(key) {
            return Ok((*handle, self.get(*handle)));
        };

        let v = V::load(key)?;
        let res = self.add_item(key.clone(), v);
        Ok(res)
    }

    // pub fn get_mut<E, S>(&mut self, key: &K) -> Result<&mut Rc<V>, E>
    //     where V: Loadable<K, E>
    // {
    //     // entry.or_insert_with() isn't quite powerful
    //     // enough 'cause it doesn't propegate Results.  ;_;
    //     let entry = self.contents.entry(key.clone());
    //     match entry {
    //         Entry::Vacant(e) => {
    //             let v = V::load(key)?;
    //             let v_rc = Rc::new(v);
    //             Ok(e.insert(v_rc));
    //             Ok(self.add_item(key.clone(), v));
    //         }
    //         Entry::Occupied(e) => Ok(e.into_mut()),
    //     }
    // }

    /// Gets the given asset, loading it with a state object if necessary.
    pub fn get_key_state<E, S>(&mut self, key: &K, state: &mut S) -> Result<(AssetHandle, Rc<V>), E>
        where V: StateLoadable<K, E, S>
    {
        if let Some(handle) = self.keys.get(key) {
            return Ok((*handle, self.get(*handle)));
        };

        let v = V::load_state(key, state)?;
        let res = self.add_item(key.clone(), v);
        Ok(res)
    }

    // /// Removes all assets from the cache
    // /// and frees any excess memory it uses.
    // /// This is now unsafe because it introduces the possibility
    // /// of dangling handles!  We can have a stack of bindings, kinda,
    // /// to manage this.  (Or just create/delete new state objects.)
    // pub fn clear(&mut self) {
    //     let map = BTreeMap::new();
    //     self.contents = map;
    // }

    /// Returns true if the given asset is loaded.
    pub fn loaded(&self, key: &K) -> bool {
        self.keys.contains_key(key)
    }

    /// Takes a slice containing a list of keys,
    /// and loads all the keys so that their objects
    /// are immediately accessible.
    pub fn preload<E>(&mut self, keys: &[K])
        where V: Loadable<K, E>
    {
        for k in keys {
            let _ = self.get_key(k);
        }
    }

    /// Preloads objects that require a state to load.
    pub fn preload_state<E, S>(&mut self, keys: &[K], state: &mut S)
        where V: StateLoadable<K, E, S>
    {
        for k in keys {
            let _ = self.get_key_state(k, state);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    impl<'a> Loadable<&'a str, ()> for String {
        fn load(key: &&str) -> Result<String, ()> {
            Ok(key.to_string())
        }
    }

    // It would be nice to get rid of the double references here somehow,
    // but then AssetCache ends up with a type of <str, String>
    // and `str` is not sized so it always has to involve a reference.
    #[test]
    fn test_assetcache() {
        let mut a = AssetCache::<&str, String>::new();
        assert!(!a.loaded(&"foo"));
        let s1 = a.get(&"foo").unwrap();
        assert_eq!(*s1, "foo");
        assert!(a.loaded(&"foo"));
    }

    impl<'a> StateLoadable<&'a str, (), i32> for String {
        fn load_state(key: &&str, state: &mut i32) -> Result<String, ()> {
            *state += 1;
            Ok(key.to_string())
        }
    }

    #[test]
    fn test_stateful_assetcache() {
        let mut a = AssetCache::<&str, String>::new();
        let s = &mut 10;
        assert!(!a.loaded(&"foo"));
        let s1 = a.get_state(&"foo", s).unwrap();
        assert_eq!(*s1, "foo");
        assert_eq!(*s, 11);
        assert!(a.loaded(&"foo"));
    }

    #[test]
    fn test_assetcache2() {
        let mut a = AssetCache2::<&str, String>::new();
        let h;
        {
            assert!(!a.loaded(&"foo"));
            let (handle, s1) = a.get_key(&"foo").unwrap();
            h = handle;
            assert!(a.loaded(&"foo"));
            assert_eq!(*s1, "foo");
            let gotten_with_handle = a.get(handle);
            assert_eq!(*s1, *gotten_with_handle);
        }
    }

    #[test]
    fn test_stateful_assetcache2() {
        let mut a = AssetCache2::<&str, String>::new();
        {
            let s = &mut 10;
            assert!(!a.loaded(&"foo"));
            let (handle, s1) = a.get_key_state(&"foo", s).unwrap();
            assert_eq!(*s1, "foo");
            assert_eq!(*s, 11);
            assert!(a.loaded(&"foo"));

            let gotten_with_handle = a.get(handle);
            assert_eq!(*s1, *gotten_with_handle);
            assert_eq!(*s, 11);

        }

    }

    #[test]
    fn test_mut_assetcache2() {
        let mut a = AssetCache2::<&str, String>::new();
        assert!(!a.loaded(&"foo"));
        let (h, _) = a.get_key(&"foo").unwrap();

        {
            let mut_value = a.get_mut(h);
            assert!(mut_value.is_some());
            let m = mut_value.unwrap();
            assert_eq!("foo", *m);
            *m += "Foobaz";
            assert_eq!("fooFoobaz", *m);
        }
        // Now get it again and ensure it's mutated.
        {
            let mut_value = a.get_mut(h);
            assert!(mut_value.is_some());
            let m = mut_value.unwrap();
            assert_eq!("fooFoobaz", *m);
        }

    }
}
<commit_msg>Ripped out old asset manager.<commit_after>//! This module implements a simple asset loader and cache.
//!
//! While ggez offers functions to load raw game assets such as
//! music files, images, etc, it provides no facilities for managing
//! them.  Ideally you want to load all the assets you need at once,
//! hold on to them for a time (the course of a level for instance),
//! and then potentially ditch the ones you don't need.
//! This module offers cache-like functionality to do exactly this.
//!
//! It will return an `Rc` containing the item loaded, so multiple
//! items can safely access (read-only) instances of the same asset.
//! (In the same thread, at least.)
//!
//! What it does NOT do is allow you to free individual assets from
//! the cache.  This is on purpose.  If you want fine-grained manual
//! memory management you know where to get it.  This is more a memory
//! pool like thing where you allocate a bunch of objects, keep them
//! around for however long you need them (while the game is loaded,
//! while a particular scene is loaded, etc), and then free them all.
//!
//! If you want to make a stack of asset managers, where one
//! has access to the assets higher up in the stack...
//! Just build one and clone it.  All the Rc's in it will get
//! cloned along with it, providing exactly the behavior you
//! want except better.  :D
//!
//! Though whether or not asset handles from the old one will be valid
//! with the new one... hmmm.  That might not be a big problem since we
//! can just request new asset handles from the new cache and they'll already
//! be there, so that might be the way to go?

// TODO: This is not thread safe; should we offer one that it?
// TODO: Check out calx-resource:
// https://github.com/rsaarelm/calx/blob/master/calx-resource/src/lib.rs
// It has a) nifty macros to build these automatically,
// and b) an asset type that will serialize to a key, and then
// deserialize the key to that asset.  Very neat!  But also
// a bit labyrenthine.
// It DOES also make thread-safety work through thread_local!().

use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::fmt::Debug;
use std::path::Path;
use std::rc::Rc;
use ggez;
use ggez::{Context, GameError, GameResult};
use ggez::graphics;

pub trait Loadable<K, E> {
    fn load(_key: &K) -> Result<Self, E> where Self: Sized;
}

pub trait StateLoadable<K, E, S> {
    fn load_state(_key: &K, &mut S) -> Result<Self, E> where Self: Sized;
}

/// An opaque asset handle that can be used for O(1) fetches
/// of assets.
// TODO: Add a UUID or something to this....
#[derive(Debug, Copy, Clone)]
pub struct AssetHandle(usize);

// We COULD use a generic interning crate such as symtern or symbol-map to
// implement the Handle -> Asset map here.  It might be useful.
// But it wouldn't get us all the way because we'd still need to maintain
// the Key -> Handle association ourselves.
#[derive(Debug, Clone)]
pub struct AssetCache<K, V>
    where K: Ord + Clone + Debug
{
    handles: Vec<Rc<V>>,
    keys: BTreeMap<K, AssetHandle>,
    next_handle: usize,
}

impl<K, V> AssetCache<K, V>
    where K: Ord + Clone + Debug
{
    /// Creates a new `AssetCache` that loads assets
    /// when necessary with the given loader function.
    pub fn new() -> Self {
        AssetCache {
            handles: Vec::new(),
            keys: BTreeMap::new(),
            next_handle: 0,
        }
    }

    fn new_handle(&mut self) -> AssetHandle {
        let i = self.next_handle;
        self.next_handle += 1;
        AssetHandle(i)
    }

    // Inserts the given asset into the handles vec at the given
    // location, and inserts the key into the key->handle mapping.
    // Performs asserts that will panic if something
    // gets out of sync (which should be impossible).
    fn bind_handle(&mut self, key: K, h: AssetHandle, value: Rc<V>) {
        let AssetHandle(i) = h;
        assert!(i == self.handles.len());
        self.handles.push(value);

        assert!(!self.keys.contains_key(&key));
        self.keys.insert(key, h);
    }

    // Adds a new item to the cache, returns an Rc reference to it
    // and an AssetHandle.
    fn add_item(&mut self, key: K, value: V) -> (AssetHandle, Rc<V>) {
        let handle = self.new_handle();
        let rc = Rc::new(value);
        self.bind_handle(key, handle, rc.clone());
        (handle, rc)
    }

    /// Retrieves an asset via its handle.
    /// This is always safe (and fast) because for a handle
    /// to be valid its object *must* exist in the cache.
    pub fn get(&self, handle: AssetHandle) -> Rc<V> {
        let AssetHandle(i) = handle;
        assert!(i < self.handles.len());
        self.handles[i].clone()
    }

    /// Not sure this is even right, but...
    pub fn get_mut<'a>(&'a mut self, handle: AssetHandle) -> Option<&'a mut V> {
        let AssetHandle(i) = handle;
        assert!(i < self.handles.len());
        use std::rc::Rc;
        Rc::get_mut(&mut self.handles[i])
    }

    // fn add_item_mut(&mut self, key: K, value: &mut V) -> (AssetHandle, Rc<&mut V>) {
    //     let handle = self.new_handle();
    //     let entry = self.entry(key.clone());
    //     match entry {
    //         Entry::Vacant(e) => {
    //             let v = V::load(key)?;
    //             let v_rc = Rc::new(v);
    //             Ok(e.insert(v_rc));
    //             Ok(self.add_item(key.clone(), v));
    //         }
    //         Entry::Occupied(e) => Ok(e.into_mut()),
    //     }

    // }

    /// Gets the given asset, loading it if necessary.
    /// Returns an Rc to the value, plus an AssetHandle
    /// which can be used to retrieve it quickly.
    // Oh my goodness getting the E type param to the
    // right place was amazingly difficult.
    pub fn get_key<E>(&mut self, key: &K) -> Result<(AssetHandle, Rc<V>), E>
        where V: Loadable<K, E>
    {
        if let Some(handle) = self.keys.get(key) {
            return Ok((*handle, self.get(*handle)));
        };

        let v = V::load(key)?;
        let res = self.add_item(key.clone(), v);
        Ok(res)
    }

    // pub fn get_mut<E, S>(&mut self, key: &K) -> Result<&mut Rc<V>, E>
    //     where V: Loadable<K, E>
    // {
    //     // entry.or_insert_with() isn't quite powerful
    //     // enough 'cause it doesn't propegate Results.  ;_;
    //     let entry = self.contents.entry(key.clone());
    //     match entry {
    //         Entry::Vacant(e) => {
    //             let v = V::load(key)?;
    //             let v_rc = Rc::new(v);
    //             Ok(e.insert(v_rc));
    //             Ok(self.add_item(key.clone(), v));
    //         }
    //         Entry::Occupied(e) => Ok(e.into_mut()),
    //     }
    // }

    /// Gets the given asset, loading it with a state object if necessary.
    pub fn get_key_state<E, S>(&mut self, key: &K, state: &mut S) -> Result<(AssetHandle, Rc<V>), E>
        where V: StateLoadable<K, E, S>
    {
        if let Some(handle) = self.keys.get(key) {
            return Ok((*handle, self.get(*handle)));
        };

        let v = V::load_state(key, state)?;
        let res = self.add_item(key.clone(), v);
        Ok(res)
    }

    // /// Removes all assets from the cache
    // /// and frees any excess memory it uses.
    // /// This is now unsafe because it introduces the possibility
    // /// of dangling handles!  We can have a stack of bindings, kinda,
    // /// to manage this.  (Or just create/delete new state objects.)
    // pub fn clear(&mut self) {
    //     let map = BTreeMap::new();
    //     self.contents = map;
    // }

    /// Returns true if the given asset is loaded.
    pub fn loaded(&self, key: &K) -> bool {
        self.keys.contains_key(key)
    }

    /// Takes a slice containing a list of keys,
    /// and loads all the keys so that their objects
    /// are immediately accessible.
    pub fn preload<E>(&mut self, keys: &[K])
        where V: Loadable<K, E>
    {
        for k in keys {
            let _ = self.get_key(k);
        }
    }

    /// Preloads objects that require a state to load.
    pub fn preload_state<E, S>(&mut self, keys: &[K], state: &mut S)
        where V: StateLoadable<K, E, S>
    {
        for k in keys {
            let _ = self.get_key_state(k, state);
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    impl<'a> Loadable<&'a str, ()> for String {
        fn load(key: &&str) -> Result<String, ()> {
            Ok(key.to_string())
        }
    }

    impl<'a> StateLoadable<&'a str, (), i32> for String {
        fn load_state(key: &&str, state: &mut i32) -> Result<String, ()> {
            *state += 1;
            Ok(key.to_string())
        }
    }

    #[test]
    fn test_assetcache() {
        let mut a = AssetCache::<&str, String>::new();
        let h;
        {
            assert!(!a.loaded(&"foo"));
            let (handle, s1) = a.get_key(&"foo").unwrap();
            h = handle;
            assert!(a.loaded(&"foo"));
            assert_eq!(*s1, "foo");
            let gotten_with_handle = a.get(handle);
            assert_eq!(*s1, *gotten_with_handle);
        }
    }

    #[test]
    fn test_stateful_assetcache() {
        let mut a = AssetCache::<&str, String>::new();
        {
            let s = &mut 10;
            assert!(!a.loaded(&"foo"));
            let (handle, s1) = a.get_key_state(&"foo", s).unwrap();
            assert_eq!(*s1, "foo");
            assert_eq!(*s, 11);
            assert!(a.loaded(&"foo"));

            let gotten_with_handle = a.get(handle);
            assert_eq!(*s1, *gotten_with_handle);
            assert_eq!(*s, 11);

        }

    }

    #[test]
    fn test_mut_assetcache() {
        let mut a = AssetCache::<&str, String>::new();
        assert!(!a.loaded(&"foo"));
        let (h, _) = a.get_key(&"foo").unwrap();

        {
            let mut_value = a.get_mut(h);
            assert!(mut_value.is_some());
            let m = mut_value.unwrap();
            assert_eq!("foo", *m);
            *m += "Foobaz";
            assert_eq!("fooFoobaz", *m);
        }
        // Now get it again and ensure it's mutated.
        {
            let mut_value = a.get_mut(h);
            assert!(mut_value.is_some());
            let m = mut_value.unwrap();
            assert_eq!("fooFoobaz", *m);
        }

    }
}
<|endoftext|>


<commit_before>use alto::{self, SourceTrait};
use std::fs::File;
use std::path::Path;
use vorbis::Decoder;

/// The audio object you can use to interact with the soundtrack.
pub struct Audio<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  /// Length of the track.
  len: f32,
  /// OpenAL source.
  source: &'c mut alto::StreamingSource<'a, 'b>
}

impl<'a, 'b, 'c> Audio<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub fn len(&self) -> f32 {
    self.len
  }

  pub fn cursor(&mut self) -> f32 {
    let source = &mut self.source;

    let c = source.sec_offset().unwrap();

    // loop the device if we hit the end of the demo
    if c > self.len {
      let _ = source.rewind();
      0.
    } else {
      c
    }
  }

  pub fn set_cursor(&mut self, t: f32) {
    assert!(t >= 0. && t <= 1.);
    let _ = self.source.set_sec_offset(t * self.len);
  }

  pub fn toggle(&mut self) -> bool {
    let source = &mut self.source;

    if source.state().unwrap() == alto::SourceState::Playing {
      // pause the OpenAL source
      let _ = source.pause();
      false
    } else {
      // unpause the OpenAL source
      let _ = source.play();
      true
    }
  }

  pub fn open<P, A, F>(track_path: P, f: F) -> A where P: AsRef<Path>, F: FnOnce(Audio) -> A {
    deb!("initializing OpenAL");

    let alto = alto::Alto::load_default().unwrap();
    let al_device = alto.open(None).unwrap();
    let al_ctx = al_device.new_context(None).unwrap();

    // create the required objects to play the soundtrack
    let mut al_buffer = al_ctx.new_buffer().unwrap();
    let mut al_source = al_ctx.new_streaming_source().unwrap();

    info!("loading soundtrack {:?}", track_path.as_ref());

    // FIXME: stream the file instead?
    // load PCM data from the file
    let vorbis_decoder = Decoder::new(File::open(track_path).unwrap()).unwrap();
    let mut pcm_buffer = Vec::new();

    for packet in vorbis_decoder.into_packets().map(Result::unwrap) {
      pcm_buffer.extend(packet.data);
    }

    // fill the OpenAL buffers with the PCM data
    let _ = al_buffer.set_data::<alto::Stereo<_>, _>(&pcm_buffer[..], 44100);

    // compute the length of soundtrack
    let len = (al_buffer.size().unwrap() * 8 / (al_buffer.channels().unwrap() * al_buffer.bits().unwrap())) as f32 / al_buffer.frequency().unwrap() as f32;

    let _ = al_source.queue_buffer(al_buffer);

    let audio = Audio { len: len, source: &mut al_source };

    f(audio)
  }

}
<commit_msg>Added Audio::{play,pause}.<commit_after>use alto::{self, SourceTrait};
use std::fs::File;
use std::path::Path;
use vorbis::Decoder;

/// The audio object you can use to interact with the soundtrack.
pub struct Audio<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  /// Length of the track.
  len: f32,
  /// OpenAL source.
  source: &'c mut alto::StreamingSource<'a, 'b>
}

impl<'a, 'b, 'c> Audio<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub fn len(&self) -> f32 {
    self.len
  }

  pub fn cursor(&mut self) -> f32 {
    let source = &mut self.source;

    let c = source.sec_offset().unwrap();

    // loop the device if we hit the end of the demo
    if c > self.len {
      let _ = source.rewind();
      0.
    } else {
      c
    }
  }

  pub fn set_cursor(&mut self, t: f32) {
    assert!(t >= 0. && t <= 1.);
    let _ = self.source.set_sec_offset(t * self.len);
  }

  pub fn play(&mut self) {
    let _ = self.source.play();
  }

  pub fn pause(&mut self) {
    let _ = self.source.pause();
  }

  pub fn toggle(&mut self) -> bool {
    let source = &mut self.source;

    if source.state().unwrap() == alto::SourceState::Playing {
      // pause the OpenAL source
      let _ = source.pause();
      false
    } else {
      // unpause the OpenAL source
      let _ = source.play();
      true
    }
  }

  pub fn open<P, A, F>(track_path: P, f: F) -> A where P: AsRef<Path>, F: FnOnce(Audio) -> A {
    deb!("initializing OpenAL");

    let alto = alto::Alto::load_default().unwrap();
    let al_device = alto.open(None).unwrap();
    let al_ctx = al_device.new_context(None).unwrap();

    // create the required objects to play the soundtrack
    let mut al_buffer = al_ctx.new_buffer().unwrap();
    let mut al_source = al_ctx.new_streaming_source().unwrap();

    info!("loading soundtrack {:?}", track_path.as_ref());

    // FIXME: stream the file instead?
    // load PCM data from the file
    let vorbis_decoder = Decoder::new(File::open(track_path).unwrap()).unwrap();
    let mut pcm_buffer = Vec::new();

    for packet in vorbis_decoder.into_packets().map(Result::unwrap) {
      pcm_buffer.extend(packet.data);
    }

    // fill the OpenAL buffers with the PCM data
    let _ = al_buffer.set_data::<alto::Stereo<_>, _>(&pcm_buffer[..], 44100);

    // compute the length of soundtrack
    let len = (al_buffer.size().unwrap() * 8 / (al_buffer.channels().unwrap() * al_buffer.bits().unwrap())) as f32 / al_buffer.frequency().unwrap() as f32;

    let _ = al_source.queue_buffer(al_buffer);

    let audio = Audio { len: len, source: &mut al_source };

    f(audio)
  }

}
<|endoftext|>


<commit_before>//!RGB types, spaces and standards.

use alpha::Alpha;
use float::Float;
use core::any::Any;

use {Component, Yxy};
use white_point::WhitePoint;

use encoding::{Linear, TransferFn};

pub use self::rgb::{Rgb, Rgba};

//mod linear;
mod rgb;

///Nonlinear sRGB.
pub type Srgb<T = f32> = Rgb<::encoding::Srgb, T>;
///Nonlinear sRGB with an alpha component.
pub type Srgba<T = f32> = Rgba<::encoding::Srgb, T>;

///Linear sRGB.
pub type LinSrgb<T = f32> = Rgb<Linear<::encoding::Srgb>, T>;
///Linear sRGB with an alpha component.
pub type LinSrgba<T = f32> = Rgba<Linear<::encoding::Srgb>, T>;

/// Gamma 2.2 encoded sRGB.
pub type GammaSrgb<T = f32> = Rgb<::encoding::Gamma<::encoding::Srgb>, T>;
/// Gamma 2.2 encoded sRGB with an alpha component.
pub type GammaSrgba<T = f32> = Rgba<::encoding::Gamma<::encoding::Srgb>, T>;

///An RGB space and a transfer function.
pub trait RgbStandard {
    ///The RGB color space.
    type Space: RgbSpace;

    ///The transfer function for the color components.
    type TransferFn: TransferFn;
}

impl<S: RgbSpace, T: TransferFn> RgbStandard for (S, T) {
    type Space = S;
    type TransferFn = T;
}

impl<P: Primaries, W: WhitePoint, T: TransferFn> RgbStandard for (P, W, T) {
    type Space = (P, W);
    type TransferFn = T;
}

///A set of primaries and a white point.
pub trait RgbSpace {
    ///The primaries of the RGB color space.
    type Primaries: Primaries;

    ///The white point of the RGB color space.
    type WhitePoint: WhitePoint;
}

impl<P: Primaries, W: WhitePoint> RgbSpace for (P, W) {
    type Primaries = P;
    type WhitePoint = W;
}

///Represents the red, green and blue primaries of an RGB space.
pub trait Primaries: Any {
    ///Primary red.
    fn red<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
    ///Primary green.
    fn green<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
    ///Primary blue.
    fn blue<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
}

impl<T, U> From<LinSrgb<T>> for Srgb<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(lin_srgb: LinSrgb<T>) -> Self {
        let non_lin = Srgb::<T>::from_linear(lin_srgb);
        non_lin.into_format()
    }
}

impl<T, U> From<Srgb<T>> for LinSrgb<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(srgb: Srgb<T>) -> Self {
        srgb.into_linear()
            .into_format()
    }
}

impl<T, U> From<LinSrgb<T>> for Srgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(lin_srgb: LinSrgb<T>) -> Self {
        let color = lin_srgb.into();
        let alpha = U::max_intensity();
        Alpha { color, alpha }
    }
}

impl<T, U> From<LinSrgba<T>> for Srgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(lin_srgba: LinSrgba<T>) -> Self {
        let (r, g, b, a) = lin_srgba.into();
        let color = LinSrgb::new(r, g, b).into();
        let alpha = a.convert();
        Alpha { color, alpha }
    }
}

impl<T, U> From<Srgb<T>> for LinSrgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(srgb: Srgb<T>) -> Self {
        let color = srgb.into();
        let alpha = U::max_intensity();
        Alpha { color, alpha }
    }
}

impl<T, U> From<Srgba<T>> for LinSrgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(srgba: Srgba<T>) -> Self {
        let (r, g, b, a) = srgba.into();
        let color = Srgb::new(r, g, b).into();
        let alpha = a.convert();
        Alpha { color, alpha }
    }
}
<commit_msg>Refactor conversions in terms of `{into/from}_{linear/format}`<commit_after>//!RGB types, spaces and standards.

use float::Float;
use core::any::Any;

use {Component, Yxy};
use white_point::WhitePoint;

use encoding::{Linear, TransferFn};

pub use self::rgb::{Rgb, Rgba};

//mod linear;
mod rgb;

///Nonlinear sRGB.
pub type Srgb<T = f32> = Rgb<::encoding::Srgb, T>;
///Nonlinear sRGB with an alpha component.
pub type Srgba<T = f32> = Rgba<::encoding::Srgb, T>;

///Linear sRGB.
pub type LinSrgb<T = f32> = Rgb<Linear<::encoding::Srgb>, T>;
///Linear sRGB with an alpha component.
pub type LinSrgba<T = f32> = Rgba<Linear<::encoding::Srgb>, T>;

/// Gamma 2.2 encoded sRGB.
pub type GammaSrgb<T = f32> = Rgb<::encoding::Gamma<::encoding::Srgb>, T>;
/// Gamma 2.2 encoded sRGB with an alpha component.
pub type GammaSrgba<T = f32> = Rgba<::encoding::Gamma<::encoding::Srgb>, T>;

///An RGB space and a transfer function.
pub trait RgbStandard {
    ///The RGB color space.
    type Space: RgbSpace;

    ///The transfer function for the color components.
    type TransferFn: TransferFn;
}

impl<S: RgbSpace, T: TransferFn> RgbStandard for (S, T) {
    type Space = S;
    type TransferFn = T;
}

impl<P: Primaries, W: WhitePoint, T: TransferFn> RgbStandard for (P, W, T) {
    type Space = (P, W);
    type TransferFn = T;
}

///A set of primaries and a white point.
pub trait RgbSpace {
    ///The primaries of the RGB color space.
    type Primaries: Primaries;

    ///The white point of the RGB color space.
    type WhitePoint: WhitePoint;
}

impl<P: Primaries, W: WhitePoint> RgbSpace for (P, W) {
    type Primaries = P;
    type WhitePoint = W;
}

///Represents the red, green and blue primaries of an RGB space.
pub trait Primaries: Any {
    ///Primary red.
    fn red<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
    ///Primary green.
    fn green<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
    ///Primary blue.
    fn blue<Wp: WhitePoint, T: Component + Float>() -> Yxy<Wp, T>;
}

impl<T, U> From<LinSrgb<T>> for Srgb<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(lin_srgb: LinSrgb<T>) -> Self {
        let non_lin = Srgb::<T>::from_linear(lin_srgb);
        non_lin.into_format()
    }
}

impl<T, U> From<Srgb<T>> for LinSrgb<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(srgb: Srgb<T>) -> Self {
        srgb.into_linear()
            .into_format()
    }
}

impl<T, U> From<LinSrgb<T>> for Srgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(lin_srgb: LinSrgb<T>) -> Self {
        let non_lin = Srgb::<T>::from_linear(lin_srgb);
        let new_fmt = Srgb::<U>::from_format(non_lin);
        new_fmt.into()
    }
}

impl<T, U> From<LinSrgba<T>> for Srgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(lin_srgba: LinSrgba<T>) -> Self {
        let non_lin = Srgba::<T>::from_linear(lin_srgba);
        non_lin.into_format()
    }
}

impl<T, U> From<Srgb<T>> for LinSrgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(srgb: Srgb<T>) -> Self {
        srgb.into_linear()
            .into_format()
            .into()
    }
}

impl<T, U> From<Srgba<T>> for LinSrgba<U>
where
    T: Component + Float,
    U: Component,
{
    fn from(srgba: Srgba<T>) -> Self {
        srgba.into_linear()
            .into_format()
    }
}
<|endoftext|>


<commit_before>use std::cast;
use std::mem::size_of;
use std::raw::Slice;

mod buffer;
mod schema;

struct BTree<'a, K> {
	segment: u64,
	manager: &'a mut buffer::BufferManager,
	tree: LazyBranchNode,
}

impl<'a, K: TotalOrd> BTree<'a, K> {
	fn new<'b>(segment_id: u64, dummy: K, manager: &'b mut buffer::BufferManager) -> BTree<'b, K> {
		let lbn = LazyBranchNode::new(1);
		BTree { segment: segment_id, manager: manager, tree: lbn}
	}

	//fn locate_page

	fn insert(&mut self, key: K, value: schema::TID) {
		let node: BranchPage<K> = self.tree.load(self.manager);
	}

	fn erase(&mut self, key: K) {
	}

	fn lookup(self, key: K) -> Option<schema::TID> {
		None
	}
}

/* a placeholder for the actual page */
struct LazyBranchNode {
	page_id: u64,
}

// TODO implement Drop to unfix page
impl LazyBranchNode {
	fn new(page_id: u64) -> LazyBranchNode {
		LazyBranchNode {page_id: page_id}
	}

	fn load<K>(&self, manager: &mut buffer::BufferManager) -> BranchPage<K> {
		let pagelock = manager.fix_page(self.page_id).unwrap();
		let page = pagelock.read();
		let bp: BranchPage<K> = BranchPage::new(page.get_data());
		bp
	}
}

enum Node<'a, K> {
	Inner(BranchPage<'a, K>),
	Leaf(LeafPage<'a, K>),
}

struct LeafEntry<K> {
	key: K,
	tid: schema::TID,
}

struct BranchEntry<K> {
	key: K,
	page_id: u64,
}

struct LeafPage<'a, K> {
	capacity: uint,
	entries: &'a [LeafEntry<K>],
}

impl<'a, K> LeafPage<'a, K> {
	fn new(page: &[u8]) -> LeafPage<'a, K> {
		let entry_size = size_of::<LeafEntry<K>>();
		//let mut r: &[LeafEntry<K>] = unsafe { cast::transmute(page) };
		//unsafe { r.set_len(buffer::PAGE_SIZE / entry_size) };
		let r = unsafe {
			cast::transmute(
				Slice::<LeafEntry<K>> {
					data: page.as_ptr() as *() as *LeafEntry<K>,
					len: page.len() / entry_size,
				}
			)
		};
		LeafPage { entries: r, capacity: r.len() }
	}

	fn insert(&mut self, key: K, tid: schema::TID) -> Option<()> {
		if self.capacity == 0 {
			return None
		}

		// find place to insert
		for i in range(0, self.entries.len()) {
			//let e = self.entries[i];
			println!("Entry {:?}", self.entries[i]);
		}
		Some(())
	}
}

struct BranchPage<'a, K> {
	entries: &'a [BranchEntry<K>],
}

impl<'a, K> BranchPage<'a, K> {
	fn new(page: &[u8]) -> BranchPage<'a, K> {
		let entry_size = size_of::<BranchEntry<K>>();
		let r = unsafe {
			cast::transmute(
				Slice::<BranchEntry<K>> {
					data: page.as_ptr() as *() as *BranchEntry<K>,
					len: page.len() / entry_size,
				}
			)
		};
		BranchPage { entries: r }
	}
}

#[test]
fn simple_insert() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let mut bt = BTree::new(23, 42, &mut manager);
	bt.insert(42, schema::TID::new(0, 0));
	assert!(false);
}

#[test]
fn create_leaf_page() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let pagelock = manager.fix_page(0).unwrap();
	let page = pagelock.read();
	let lp: LeafPage<u64> = LeafPage::new(page.get_data());
	println!("lp len: {}", lp.entries.len());
	assert!(false);
}
<commit_msg>Added beginning of insertion stuff<commit_after>use std::cast;
use std::mem::size_of;
use std::raw::Slice;

mod buffer;
mod schema;

struct BTree<'a, K> {
	segment: u64,
	manager: &'a mut buffer::BufferManager,
	tree: LazyBranchNode,
}

impl<'a, K: TotalOrd> BTree<'a, K> {
	fn new<'b>(segment_id: u64, dummy: K, manager: &'b mut buffer::BufferManager) -> BTree<'b, K> {
		BTree {
			segment: segment_id,
			manager: manager,
			tree: LazyBranchNode::new(1),
		}
	}

	//fn locate_page

	fn insert(&mut self, key: K, value: schema::TID) {
		let node: BranchPage<K> = self.tree.load(self.manager);

		//for i in range(0, node.entries.len()) {
		//	println!("i {:?}", node.entries[i]);
		//}
		node.insert_value(key, value);
	}

	fn erase(&mut self, key: K) {
	}

	fn lookup(self, key: K) -> Option<schema::TID> {
		None
	}
}

/* a placeholder for the actual page */
struct LazyBranchNode {
	page_id: u64,
}

// TODO implement Drop to unfix page
impl LazyBranchNode {
	fn new(page_id: u64) -> LazyBranchNode {
		LazyBranchNode {page_id: page_id}
	}

	fn load<K>(&self, manager: &mut buffer::BufferManager) -> BranchPage<K> {
		let pagelock = manager.fix_page(self.page_id).unwrap();
		let page = pagelock.read();
		let bp: BranchPage<K> = BranchPage::new(page.get_data());
		bp
	}
}

enum Node<'a, K> {
	Inner(BranchPage<'a, K>),
	Leaf(LeafPage<'a, K>),
}

struct LeafEntry<K> {
	key: K,
	tid: schema::TID,
}

struct BranchEntry<K> {
	key: K,
	page_id: u64,
}

struct LeafPage<'a, K> {
	capacity: uint,
	entries: &'a [LeafEntry<K>],
}

impl<'a, K> LeafPage<'a, K> {
	fn new(page: &[u8]) -> LeafPage<'a, K> {
		let entry_size = size_of::<LeafEntry<K>>();
		//let mut r: &[LeafEntry<K>] = unsafe { cast::transmute(page) };
		//unsafe { r.set_len(buffer::PAGE_SIZE / entry_size) };
		let r = unsafe {
			cast::transmute(
				Slice::<LeafEntry<K>> {
					data: page.as_ptr() as *() as *LeafEntry<K>,
					len: page.len() / entry_size,
				}
			)
		};
		// TODO: calculate capacity
		LeafPage { entries: r, capacity: r.len() }
	}

	fn insert(&mut self, key: K, tid: schema::TID) -> Option<()> {
		if self.capacity == 0 {
			return None
		}

		// find place to insert
		for i in range(0, self.entries.len()) {
			//let e = self.entries[i];
			println!("Entry {:?}", self.entries[i]);
		}
		Some(())
	}
}

struct BranchPage<'a, K> {
	capacity: uint,
	entries: &'a [BranchEntry<K>],
}

impl<'a, K> BranchPage<'a, K> {
	fn new(page: &[u8]) -> BranchPage<'a, K> {
		let entry_size = size_of::<BranchEntry<K>>();
		let r: &[BranchEntry<K>] = unsafe {
			cast::transmute(
				Slice::<BranchEntry<K>> {
					data: page.as_ptr() as *() as *BranchEntry<K>,
					len: page.len() / entry_size,
				}
			)
		};

		/* find slots that are used */
		let mut capacity = r.len();
		for i in range(0, r.len()) {
			if r[i].page_id != 0 {
				capacity -= 1;
			}
		}

		println!("BranchPage computed capacity: {}", capacity);

		BranchPage {
			entries: r,
			capacity: capacity
		}
	}

	/* might return a new branch node if this one was split */
	fn insert_value(&self, key: K, value: schema::TID) -> Option<LazyBranchNode> {
		let mut place = 0;
		// locate the place where to insert
		for i in range(0, self.entries.len()) {
			if self.entries[i].page_id == 0 {
				continue
			}
			println!("Entry i {:?}, key {:?}", self.entries[i], self.entries[i].key);
			// TODO find place
		}
		let go_to_page = self.entries[place].page_id;
		if go_to_page == 0 {
			// TODO: create page
		}

		// currently not caring about splitting branch pages
		None
	}

	//fn insert_page
}

#[test]
fn simple_insert() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let mut bt = BTree::new(23, 42, &mut manager);
	bt.insert(42, schema::TID::new(0, 0));
	assert!(false);
}

#[test]
fn create_leaf_page() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let pagelock = manager.fix_page(0).unwrap();
	let page = pagelock.read();
	let lp: LeafPage<u64> = LeafPage::new(page.get_data());
	println!("lp len: {}", lp.entries.len());
	assert!(false);
}
<|endoftext|>


<commit_before>use core::fmt::{self, Debug};
use core::ops::Deref;

#[cfg(feature = "alloc")]
use alloc::borrow::ToOwned;

#[cfg(any(feature = "std", feature = "alloc"))]
use crate::ByteBuf;

use serde::de::{Deserialize, Deserializer, Error, Visitor};
use serde::ser::{Serialize, Serializer};

/// Wrapper around `&[u8]` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::Bytes;
///
/// fn print_encoded_cache() -> bincode::Result<()> {
///     let mut cache = HashMap::new();
///     cache.insert(3, Bytes::new(b"three"));
///     cache.insert(2, Bytes::new(b"two"));
///     cache.insert(1, Bytes::new(b"one"));
///
///     bincode::serialize_into(&mut io::stdout(), &cache)
/// }
/// #
/// # fn main() {
/// #     print_encoded_cache().unwrap();
/// # }
/// ```
#[derive(Eq, Hash, PartialEq, PartialOrd, Ord)]
#[repr(C)]
pub struct Bytes {
    bytes: [u8],
}

impl Bytes {
    /// Wrap an existing `&[u8]`.
    pub fn new(bytes: &[u8]) -> &Self {
        unsafe { &*(bytes as *const [u8] as *const Bytes) }
    }
}

impl Debug for Bytes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.bytes, f)
    }
}

impl Deref for Bytes {
    type Target = [u8];

    fn deref(&self) -> &[u8] {
        &self.bytes
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl ToOwned for Bytes {
    type Owned = ByteBuf;

    fn to_owned(&self) -> Self::Owned {
        ByteBuf::from(&self.bytes)
    }
}

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

struct BytesVisitor;

impl<'de> Visitor<'de> for BytesVisitor {
    type Value = &'de Bytes;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a borrowed byte array")
    }

    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v))
    }

    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v.as_bytes()))
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for &'a Bytes {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(BytesVisitor)
    }
}
<commit_msg>Implement DerefMut for Bytes<commit_after>use core::fmt::{self, Debug};
use core::ops::{Deref, DerefMut};

#[cfg(feature = "alloc")]
use alloc::borrow::ToOwned;

#[cfg(any(feature = "std", feature = "alloc"))]
use crate::ByteBuf;

use serde::de::{Deserialize, Deserializer, Error, Visitor};
use serde::ser::{Serialize, Serializer};

/// Wrapper around `&[u8]` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::Bytes;
///
/// fn print_encoded_cache() -> bincode::Result<()> {
///     let mut cache = HashMap::new();
///     cache.insert(3, Bytes::new(b"three"));
///     cache.insert(2, Bytes::new(b"two"));
///     cache.insert(1, Bytes::new(b"one"));
///
///     bincode::serialize_into(&mut io::stdout(), &cache)
/// }
/// #
/// # fn main() {
/// #     print_encoded_cache().unwrap();
/// # }
/// ```
#[derive(Eq, Hash, PartialEq, PartialOrd, Ord)]
#[repr(C)]
pub struct Bytes {
    bytes: [u8],
}

impl Bytes {
    /// Wrap an existing `&[u8]`.
    pub fn new(bytes: &[u8]) -> &Self {
        unsafe { &*(bytes as *const [u8] as *const Bytes) }
    }
}

impl Debug for Bytes {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.bytes, f)
    }
}

impl Deref for Bytes {
    type Target = [u8];

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

impl DerefMut for Bytes {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.bytes
    }
}

#[cfg(any(feature = "std", feature = "alloc"))]
impl ToOwned for Bytes {
    type Owned = ByteBuf;

    fn to_owned(&self) -> Self::Owned {
        ByteBuf::from(&self.bytes)
    }
}

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

struct BytesVisitor;

impl<'de> Visitor<'de> for BytesVisitor {
    type Value = &'de Bytes;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("a borrowed byte array")
    }

    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v))
    }

    fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
    where
        E: Error,
    {
        Ok(Bytes::new(v.as_bytes()))
    }
}

impl<'a, 'de: 'a> Deserialize<'de> for &'a Bytes {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_bytes(BytesVisitor)
    }
}
<|endoftext|>


<commit_before>use quote::Ident;

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Rule {
    pub name: Ident,
    pub ty:   RuleType,
    pub body: Body
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RuleType {
    Normal,
    Silent,
    Atomic,
    NonAtomic
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Body {
    Normal(Expr),
    Infix(Expr, Vec<(Rule, bool)>)
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Expr {
    Char(String),
    Str(String),
    Insens(String),
    Range(String, String),
    Ident(Ident),
    Seq(Vec<Expr>),
    Choice(Vec<Expr>),
    RepZero(Box<Expr>),
    RepOne(Box<Expr>),
    Opt(Box<Expr>),
    PosLhd(Box<Expr>),
    NegLhd(Box<Expr>),
    Push(Box<Expr>)
}

pub fn map_rules<F>(rules: Vec<Rule>, mut f: F) -> Vec<Rule> where F: FnMut(Rule) -> Rule {
    rules.into_iter().map(move |rule| {
        match rule {
            Rule { body: Body::Normal(_), .. } => f(rule),
            Rule { name, ty, body: Body::Infix(expr, rules) } => {
                let rule = Rule {
                    name: name,
                    ty:   ty,
                    body: Body::Infix(expr, rules.into_iter().map(|pair| {
                        let (rule, assoc) = pair;

                        (f(rule), assoc)
                    }).collect())
                };

                f(rule)
            }
        }
    }).collect()
}

pub fn map_expr<F>(expr: Expr, f: &mut F) -> Expr where F: FnMut(Expr) -> Expr {
    match expr {
        Expr::Char(_)       => f(expr),
        Expr::Str(_)        => f(expr),
        Expr::Insens(_)     => f(expr),
        Expr::Range(..)     => f(expr),
        Expr::Ident(_)      => f(expr),
        Expr::Seq(exprs)    => {
            let mapped = exprs.into_iter().map(|expr| f(expr)).collect();
            f(Expr::Seq(mapped))
        },
        Expr::Choice(exprs) => {
            let mapped = exprs.into_iter().map(|expr| f(expr)).collect();
            f(Expr::Choice(mapped))
        },
        Expr::RepZero(expr) => {
            let mapped = Box::new(f(*expr));
            f(Expr::RepZero(mapped))
        },
        Expr::RepOne(expr)  => {
            let mapped = Box::new(f(*expr));
            f(Expr::RepOne(mapped))
        },
        Expr::Opt(expr)     => {
            let mapped = Box::new(f(*expr));
            f(Expr::Opt(mapped))
        },
        Expr::PosLhd(expr)  => {
            let mapped = Box::new(f(*expr));
            f(Expr::PosLhd(mapped))
        },
        Expr::NegLhd(expr)  => {
            let mapped = Box::new(f(*expr));
            f(Expr::NegLhd(mapped))
        },
        Expr::Push(expr)    => {
            let mapped = Box::new(f(*expr));
            f(Expr::Push(mapped))
        }
    }
}

pub fn map_all_exprs<F>(rules: Vec<Rule>, mut f: F) -> Vec<Rule> where F: FnMut(Expr) -> Expr {
    fn map_rec<F>(rules: Vec<Rule>, f: &mut F) -> Vec<Rule> where F: FnMut(Expr) -> Expr {
        rules.into_iter().map(move |rule| {
            match rule {
                Rule { name, ty, body: Body::Normal(expr), .. } => {
                    Rule {
                        name: name,
                        ty:   ty,
                        body: Body::Normal(map_expr(expr, f))
                    }
                }
                Rule { name, ty, body: Body::Infix(expr, rules) } => {
                    let assocs: Vec<bool> = rules.iter().map(|pair| pair.1).collect();
                    let rules = map_rec(rules.into_iter().map(|pair| pair.0).collect(), f);

                    Rule {
                        name: name,
                        ty:   ty,
                        body: Body::Infix(f(expr), rules.into_iter().zip(assocs).collect())
                    }
                }
            }
        }).collect()
    }

    map_rec(rules, &mut f)
}
<commit_msg>Fixed pattern.<commit_after>use quote::Ident;

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Rule {
    pub name: Ident,
    pub ty:   RuleType,
    pub body: Body
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum RuleType {
    Normal,
    Silent,
    Atomic,
    NonAtomic
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Body {
    Normal(Expr),
    Infix(Expr, Vec<(Rule, bool)>)
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Expr {
    Char(String),
    Str(String),
    Insens(String),
    Range(String, String),
    Ident(Ident),
    Seq(Vec<Expr>),
    Choice(Vec<Expr>),
    RepZero(Box<Expr>),
    RepOne(Box<Expr>),
    Opt(Box<Expr>),
    PosLhd(Box<Expr>),
    NegLhd(Box<Expr>),
    Push(Box<Expr>)
}

pub fn map_rules<F>(rules: Vec<Rule>, mut f: F) -> Vec<Rule> where F: FnMut(Rule) -> Rule {
    rules.into_iter().map(move |rule| {
        match rule {
            Rule { body: Body::Normal(_), .. } => f(rule),
            Rule { name, ty, body: Body::Infix(expr, rules) } => {
                let rule = Rule {
                    name: name,
                    ty:   ty,
                    body: Body::Infix(expr, rules.into_iter().map(|pair| {
                        let (rule, assoc) = pair;

                        (f(rule), assoc)
                    }).collect())
                };

                f(rule)
            }
        }
    }).collect()
}

pub fn map_expr<F>(expr: Expr, f: &mut F) -> Expr where F: FnMut(Expr) -> Expr {
    match expr {
        Expr::Char(_)       => f(expr),
        Expr::Str(_)        => f(expr),
        Expr::Insens(_)     => f(expr),
        Expr::Range(..)     => f(expr),
        Expr::Ident(_)      => f(expr),
        Expr::Seq(exprs)    => {
            let mapped = exprs.into_iter().map(|expr| f(expr)).collect();
            f(Expr::Seq(mapped))
        },
        Expr::Choice(exprs) => {
            let mapped = exprs.into_iter().map(|expr| f(expr)).collect();
            f(Expr::Choice(mapped))
        },
        Expr::RepZero(expr) => {
            let mapped = Box::new(f(*expr));
            f(Expr::RepZero(mapped))
        },
        Expr::RepOne(expr)  => {
            let mapped = Box::new(f(*expr));
            f(Expr::RepOne(mapped))
        },
        Expr::Opt(expr)     => {
            let mapped = Box::new(f(*expr));
            f(Expr::Opt(mapped))
        },
        Expr::PosLhd(expr)  => {
            let mapped = Box::new(f(*expr));
            f(Expr::PosLhd(mapped))
        },
        Expr::NegLhd(expr)  => {
            let mapped = Box::new(f(*expr));
            f(Expr::NegLhd(mapped))
        },
        Expr::Push(expr)    => {
            let mapped = Box::new(f(*expr));
            f(Expr::Push(mapped))
        }
    }
}

pub fn map_all_exprs<F>(rules: Vec<Rule>, mut f: F) -> Vec<Rule> where F: FnMut(Expr) -> Expr {
    fn map_rec<F>(rules: Vec<Rule>, f: &mut F) -> Vec<Rule> where F: FnMut(Expr) -> Expr {
        rules.into_iter().map(move |rule| {
            match rule {
                Rule { name, ty, body: Body::Normal(expr) } => {
                    Rule {
                        name: name,
                        ty:   ty,
                        body: Body::Normal(map_expr(expr, f))
                    }
                }
                Rule { name, ty, body: Body::Infix(expr, rules) } => {
                    let assocs: Vec<bool> = rules.iter().map(|pair| pair.1).collect();
                    let rules = map_rec(rules.into_iter().map(|pair| pair.0).collect(), f);

                    Rule {
                        name: name,
                        ty:   ty,
                        body: Body::Infix(f(expr), rules.into_iter().zip(assocs).collect())
                    }
                }
            }
        }).collect()
    }

    map_rec(rules, &mut f)
}
<|endoftext|>


<commit_before>//! Provides a linear chain to cascade `AudioDevice`s together.

use types::{AudioDevice, Sample, Time};
pub use tick::Tick;

pub struct DeviceChain {
    devices: Vec<AudioNode>,
    time: Time
}

impl DeviceChain {
    pub fn from<D>(device: D) -> DeviceChain where D: 'static+AudioDevice {
        DeviceChain { devices: vec![AudioNode::new(device)], time: 0 }
    }

    pub fn into<D>(mut self, device: D) -> DeviceChain where D: 'static+AudioDevice {
        if self.devices[self.devices.len()-1].outputs.len() != device.num_inputs() {
            panic!("DeviceChain: number of outputs must match number of inputs");
        }
        self.devices.push(AudioNode::new(device));
        self
    }
}

impl Tick for DeviceChain {
    fn tick(&mut self) {
        self.devices[0].tick(self.time, &[0.0;0]);
        for i in 1..self.devices.len() {
            let inputs = self.devices[i-1].outputs.clone();
            self.devices[i].tick(self.time, &inputs);
        }
        self.time += 1;
    }
}

struct AudioNode {
    device: Box<AudioDevice>,
    outputs: Vec<Sample>
}

impl AudioNode {
    fn new<D>(device: D) -> AudioNode where D: 'static+AudioDevice {
        let n = device.num_outputs();
        AudioNode {
            device: Box::new(device),
            outputs: vec![0.0; n]
        }
    }

    fn tick(&mut self, t: Time, inputs: &[Sample]) {
        self.device.tick(t, inputs, &mut self.outputs);
    }
}
<commit_msg>New method for fetching the output of an audio chain<commit_after>//! Provides a linear chain to cascade `AudioDevice`s together.

use types::{AudioDevice, Sample, Time};
pub use tick::Tick;

pub struct DeviceChain {
    devices: Vec<AudioNode>,
    time: Time
}

impl DeviceChain {
    pub fn from<D>(device: D) -> DeviceChain where D: 'static+AudioDevice {
        DeviceChain { devices: vec![AudioNode::new(device)], time: 0 }
    }

    pub fn into<D>(mut self, device: D) -> DeviceChain where D: 'static+AudioDevice {
        if self.devices[self.devices.len()-1].outputs.len() != device.num_inputs() {
            panic!("DeviceChain: number of outputs must match number of inputs");
        }
        self.devices.push(AudioNode::new(device));
        self
    }

    pub fn get_output(&self) -> Vec<Sample> {
        self.devices[self.devices.len()-1].outputs.clone()
    }
}

impl Tick for DeviceChain {
    fn tick(&mut self) {
        self.devices[0].tick(self.time, &[0.0;0]);
        for i in 1..self.devices.len() {
            let inputs = self.devices[i-1].outputs.clone();
            self.devices[i].tick(self.time, &inputs);
        }
        self.time += 1;
    }
}

struct AudioNode {
    device: Box<AudioDevice>,
    outputs: Vec<Sample>
}

impl AudioNode {
    fn new<D>(device: D) -> AudioNode where D: 'static+AudioDevice {
        let n = device.num_outputs();
        AudioNode {
            device: Box::new(device),
            outputs: vec![0.0; n]
        }
    }

    fn tick(&mut self, t: Time, inputs: &[Sample]) {
        self.device.tick(t, inputs, &mut self.outputs);
    }
}
<|endoftext|>


<commit_before>extern crate ocl;
#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
#[allow(non_snake_case)]
pub mod ffi;
use std::mem;
pub use ffi::clfftSetupData;

macro_rules! clfft_try {
    ( $result_expr: expr) => {
        let result = $result_expr;
        if result != ffi::clfftStatus::CLFFT_SUCCESS {
            let error_code: i32 = unsafe { mem::transmute(result) };
            return ocl::Error::err(format!("FOREIGN_CLFFT_ERROR {}\nSee http://clmathlibraries.github.io/clFFT/clFFT_8h.html#a74e303bed132064cfa22c1cce96d2bce for further information", error_code));
        }
    }
}

macro_rules! clfft_panic {
    ( $result_expr: expr) => {
        let result = $result_expr;
        if result != ffi::clfftStatus::CLFFT_SUCCESS {
            panic!("Unexpeced error in foreign library: {:?}", result);
        }
    }
}

/// Initialize the internal FFT resources such as FFT implementation caches kernels, programs, and buffers.
pub fn init_lib() -> ffi::clfftSetupData {
    let mut major: ocl::ffi::cl_uint = 0;
    let mut minor: ocl::ffi::cl_uint = 0;
    let mut patch: ocl::ffi::cl_uint = 0;
    clfft_panic!( unsafe { ffi::clfftGetVersion(&mut major, &mut minor, &mut patch) } );
    let data = ffi::clfftSetupData {
        major: major,
        minor: minor,
        patch: patch,
        debugFlags: 0,
    };

    clfft_panic!(unsafe { ffi::clfftSetup(&data) });
    data
}

/// Release all internal resources acquired during `init_lib`.
pub fn drop_lib() {
    unsafe { ffi::clfftTeardown() };
}

fn translate_to_fft_dim(dims: ocl::SpatialDims) -> ffi::clfftDim {
    match dims.dim_count() {
        1 => ffi::clfftDim::CLFFT_1D,
        2 => ffi::clfftDim::CLFFT_2D,
        3 => ffi::clfftDim::CLFFT_3D,
        n => panic!("Number of dimensions must be 1, 2 or 3, but it is {}", n)
    }
}

pub struct FftPlan {
    handle: ffi::clfftPlanHandle
}

/// Specify the expected precision of each FFT.
pub enum Precision {
    Single,
    Double,
    SingleFast,
    DoubleFast
}

fn translate_precision(precision: Precision) -> ffi::clfftPrecision {
    match precision {
        Precision::Single => ffi::clfftPrecision::CLFFT_SINGLE,
        Precision::Double => ffi::clfftPrecision::CLFFT_DOUBLE,
        Precision::SingleFast => ffi::clfftPrecision::CLFFT_SINGLE_FAST,
        Precision::DoubleFast => ffi::clfftPrecision::CLFFT_DOUBLE_FAST
    }
}

fn translate_precision_back(precision: ffi::clfftPrecision) -> Precision {
    match precision {
        ffi::clfftPrecision::CLFFT_SINGLE => Precision::Single,
        ffi::clfftPrecision::CLFFT_DOUBLE => Precision::Double,
        ffi::clfftPrecision::CLFFT_SINGLE_FAST => Precision::SingleFast,
        ffi::clfftPrecision::CLFFT_DOUBLE_FAST => Precision::DoubleFast,
        ffi::clfftPrecision::ENDPRECISION => panic!("ENDPRECISION should never be returned")
    }
}

/// Specify the expected layouts of the buffers.
pub enum Layout {
    ComplexInterleaved,
    ComplexPlanar,
    HermitianInterleaved,
    HermitianPlanar,
    Real
}

fn translate_layout(layout: Layout) -> ffi::clfftLayout {
    match layout {
        Layout::ComplexInterleaved => ffi::clfftLayout::CLFFT_COMPLEX_INTERLEAVED,
        Layout::ComplexPlanar => ffi::clfftLayout::CLFFT_COMPLEX_PLANAR,
        Layout::HermitianInterleaved => ffi::clfftLayout::CLFFT_HERMITIAN_INTERLEAVED,
        Layout::HermitianPlanar => ffi::clfftLayout::CLFFT_HERMITIAN_PLANAR,
        Layout::Real => ffi::clfftLayout::CLFFT_REAL
    }
}

fn translate_layout_back(layout: ffi::clfftLayout) -> Layout {
    match layout {
        ffi::clfftLayout::CLFFT_COMPLEX_INTERLEAVED => Layout::ComplexInterleaved,
        ffi::clfftLayout::CLFFT_COMPLEX_PLANAR => Layout::ComplexPlanar,
        ffi::clfftLayout::CLFFT_HERMITIAN_INTERLEAVED => Layout::HermitianInterleaved,
        ffi::clfftLayout::CLFFT_HERMITIAN_PLANAR => Layout::HermitianPlanar,
        ffi::clfftLayout::CLFFT_REAL => Layout::Real,
        ffi::clfftLayout::ENDLAYOUT => panic!("ENDLAYOUT should never be returned")
    }
}

/// Specify the expected direction of each FFT, time or the frequency domains
pub enum Direction {
    Forward,
    Backward
}

fn translate_direction(direction: Direction) -> ffi::clfftDirection {
    match direction {
        Direction::Forward => ffi::clfftDirection::CLFFT_FORWARD,
        Direction::Backward => ffi::clfftDirection::CLFFT_BACKWARD
    }
}

fn translate_direction_back(direction: ffi::clfftDirection) -> Direction {
    match direction {
        ffi::clfftDirection::CLFFT_FORWARD => Direction::Forward,
        ffi::clfftDirection::CLFFT_BACKWARD => Direction::Backward,
        ffi::clfftDirection::ENDDIRECTION => panic!("ENDDIRECTION should never be returned")
    }
}

/// pecify wheter the input buffers are overwritten with results
pub enum Location {
    Inplace,
    OutOfPlace
}

fn translate_location(location: Location) -> ffi::clfftResultLocation {
    match location {
        Location::Inplace => ffi::clfftResultLocation::CLFFT_INPLACE,
        Location::OutOfPlace => ffi::clfftResultLocation::CLFFT_OUTOFPLACE
    }
}

fn translate_location_back(location: ffi::clfftResultLocation) -> Location {
    match location {
        ffi::clfftResultLocation::CLFFT_INPLACE => Location::Inplace,
        ffi::clfftResultLocation::CLFFT_OUTOFPLACE => Location::OutOfPlace,
        ffi::clfftResultLocation::ENDPLACE => panic!("ENDPLACE should never be returned")
    }
}

impl FftPlan {
    /// Create a plan object initialized entirely with default values.
    ///
    /// A plan is a repository of state for calculating FFT's.  Allows the runtime to pre-calculate kernels, programs
    /// and buffers and associate them with buffers of specified dimensions.
    pub fn default<D: Into<ocl::SpatialDims>>(pro_que: &ocl::ProQue, dims: D)
        -> ocl::Result<FftPlan> {
        let context = unsafe { pro_que.context().core_as_ref().as_ptr() };
        let dims = dims.into();
        let dim = translate_to_fft_dim(dims);
        let lengths = try!(dims.to_lens());
        let mut plan: ffi::clfftPlanHandle = 0;
        clfft_try!( unsafe { ffi::clfftCreateDefaultPlan(&mut plan, context, dim, &lengths as *const usize) } );
        Ok(FftPlan {  handle: plan })
    }

    /// Returns the native clFFT plan handle.
    pub fn plan_handle(&self) -> ffi::clfftPlanHandle {
        self.handle
    }

    /// Set the floating point precision of the FFT data
    pub fn set_precision(&mut self, precision: Precision) -> ocl::Result<()> {
        let precision = translate_precision(precision);
        clfft_try!(unsafe { ffi::clfftSetPlanPrecision(self.handle, precision) });
        Ok(())
    }

    pub fn get_precision(&self) -> ocl::Result<Precision> {
        let mut precision = ffi::clfftPrecision::CLFFT_SINGLE;
        clfft_try!(unsafe { ffi::clfftGetPlanPrecision(self.handle, &mut precision) });
        Ok(translate_precision_back(precision))
    }

    /// Set the expected layout of the input and output buffers
    pub fn set_layout(&mut self, input_layout: Layout, output_layout: Layout) -> ocl::Result<()> {
        let input_layout = translate_layout(input_layout);
        let output_layout = translate_layout(output_layout);
        clfft_try!(unsafe { ffi::clfftSetLayout(self.handle, input_layout, output_layout) });
        Ok(())
    }

    pub fn get_layout(&self) -> ocl::Result<(Layout, Layout)> {
        let mut input_layout = ffi::clfftLayout::CLFFT_COMPLEX_INTERLEAVED;
        let mut output_layout = ffi::clfftLayout::CLFFT_COMPLEX_INTERLEAVED;
        clfft_try!(unsafe { ffi::clfftGetLayout(self.handle, &mut input_layout, &mut output_layout) });
        Ok((translate_layout_back(input_layout), translate_layout_back(output_layout)))
    }

    /// Set whether the input buffers are to be overwritten with results
    pub fn set_result_location(&mut self, location: Location) -> ocl::Result<()> {
        let location = translate_location(location);
        clfft_try!(unsafe { ffi::clfftSetResultLocation(self.handle, location) });
        Ok(())
    }

    pub fn get_result_location(&self) -> ocl::Result<Location> {
        let mut location = ffi::clfftResultLocation::CLFFT_INPLACE;
        clfft_try!(unsafe { ffi::clfftGetResultLocation(self.handle, &mut location) });
        Ok(translate_location_back(location))
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ocl::{ProQue};
    use ocl::builders::ProgramBuilder;

    #[test]
    pub fn fft_test() {
        init_lib();
        let prog_bldr = ProgramBuilder::new();
        let ocl_pq = ProQue::builder()
            .prog_bldr(prog_bldr)
            .build()
            .expect("Building ProQue");
        FftPlan::default(&ocl_pq, [1000]);
        drop_lib();
    }
}<commit_msg>Making sure that plans are destroyed while they are still in construction<commit_after>extern crate ocl;
#[allow(non_camel_case_types)]
#[allow(non_upper_case_globals)]
#[allow(non_snake_case)]
pub mod ffi;
use std::mem;
pub use ffi::clfftSetupData;

macro_rules! clfft_try {
    ( $result_expr: expr) => {
        let result = $result_expr;
        if result != ffi::clfftStatus::CLFFT_SUCCESS {
            let error_code: i32 = unsafe { mem::transmute(result) };
            return ocl::Error::err(format!("FOREIGN_CLFFT_ERROR {}\nSee http://clmathlibraries.github.io/clFFT/clFFT_8h.html#a74e303bed132064cfa22c1cce96d2bce for further information", error_code));
        }
    }
}

macro_rules! clfft_panic {
    ( $result_expr: expr) => {
        let result = $result_expr;
        if result != ffi::clfftStatus::CLFFT_SUCCESS {
            panic!("Unexpeced error in foreign library: {:?}", result);
        }
    }
}

/// Initialize the internal FFT resources such as FFT implementation caches kernels, programs, and buffers.
pub fn init_lib() -> ffi::clfftSetupData {
    let mut major: ocl::ffi::cl_uint = 0;
    let mut minor: ocl::ffi::cl_uint = 0;
    let mut patch: ocl::ffi::cl_uint = 0;
    clfft_panic!( unsafe { ffi::clfftGetVersion(&mut major, &mut minor, &mut patch) } );
    let data = ffi::clfftSetupData {
        major: major,
        minor: minor,
        patch: patch,
        debugFlags: 0,
    };

    clfft_panic!(unsafe { ffi::clfftSetup(&data) });
    data
}

/// Release all internal resources acquired during `init_lib`.
pub fn drop_lib() {
    unsafe { ffi::clfftTeardown() };
}

fn translate_to_fft_dim(dims: ocl::SpatialDims) -> ffi::clfftDim {
    match dims.dim_count() {
        1 => ffi::clfftDim::CLFFT_1D,
        2 => ffi::clfftDim::CLFFT_2D,
        3 => ffi::clfftDim::CLFFT_3D,
        n => panic!("Number of dimensions must be 1, 2 or 3, but it is {}", n)
    }
}

pub struct FftPlanBuilder {
    handle: ffi::clfftPlanHandle
}

/// Specify the expected precision of each FFT.
pub enum Precision {
    Single,
    Double,
    SingleFast,
    DoubleFast
}

fn translate_precision(precision: Precision) -> ffi::clfftPrecision {
    match precision {
        Precision::Single => ffi::clfftPrecision::CLFFT_SINGLE,
        Precision::Double => ffi::clfftPrecision::CLFFT_DOUBLE,
        Precision::SingleFast => ffi::clfftPrecision::CLFFT_SINGLE_FAST,
        Precision::DoubleFast => ffi::clfftPrecision::CLFFT_DOUBLE_FAST
    }
}

fn translate_precision_back(precision: ffi::clfftPrecision) -> Precision {
    match precision {
        ffi::clfftPrecision::CLFFT_SINGLE => Precision::Single,
        ffi::clfftPrecision::CLFFT_DOUBLE => Precision::Double,
        ffi::clfftPrecision::CLFFT_SINGLE_FAST => Precision::SingleFast,
        ffi::clfftPrecision::CLFFT_DOUBLE_FAST => Precision::DoubleFast,
        ffi::clfftPrecision::ENDPRECISION => panic!("ENDPRECISION should never be returned")
    }
}

/// Specify the expected layouts of the buffers.
pub enum Layout {
    ComplexInterleaved,
    ComplexPlanar,
    HermitianInterleaved,
    HermitianPlanar,
    Real
}

fn translate_layout(layout: Layout) -> ffi::clfftLayout {
    match layout {
        Layout::ComplexInterleaved => ffi::clfftLayout::CLFFT_COMPLEX_INTERLEAVED,
        Layout::ComplexPlanar => ffi::clfftLayout::CLFFT_COMPLEX_PLANAR,
        Layout::HermitianInterleaved => ffi::clfftLayout::CLFFT_HERMITIAN_INTERLEAVED,
        Layout::HermitianPlanar => ffi::clfftLayout::CLFFT_HERMITIAN_PLANAR,
        Layout::Real => ffi::clfftLayout::CLFFT_REAL
    }
}

fn translate_layout_back(layout: ffi::clfftLayout) -> Layout {
    match layout {
        ffi::clfftLayout::CLFFT_COMPLEX_INTERLEAVED => Layout::ComplexInterleaved,
        ffi::clfftLayout::CLFFT_COMPLEX_PLANAR => Layout::ComplexPlanar,
        ffi::clfftLayout::CLFFT_HERMITIAN_INTERLEAVED => Layout::HermitianInterleaved,
        ffi::clfftLayout::CLFFT_HERMITIAN_PLANAR => Layout::HermitianPlanar,
        ffi::clfftLayout::CLFFT_REAL => Layout::Real,
        ffi::clfftLayout::ENDLAYOUT => panic!("ENDLAYOUT should never be returned")
    }
}

/// Specify the expected direction of each FFT, time or the frequency domains
pub enum Direction {
    Forward,
    Backward
}

fn translate_direction(direction: Direction) -> ffi::clfftDirection {
    match direction {
        Direction::Forward => ffi::clfftDirection::CLFFT_FORWARD,
        Direction::Backward => ffi::clfftDirection::CLFFT_BACKWARD
    }
}

fn translate_direction_back(direction: ffi::clfftDirection) -> Direction {
    match direction {
        ffi::clfftDirection::CLFFT_FORWARD => Direction::Forward,
        ffi::clfftDirection::CLFFT_BACKWARD => Direction::Backward,
        ffi::clfftDirection::ENDDIRECTION => panic!("ENDDIRECTION should never be returned")
    }
}

/// pecify wheter the input buffers are overwritten with results
pub enum Location {
    Inplace,
    OutOfPlace
}

fn translate_location(location: Location) -> ffi::clfftResultLocation {
    match location {
        Location::Inplace => ffi::clfftResultLocation::CLFFT_INPLACE,
        Location::OutOfPlace => ffi::clfftResultLocation::CLFFT_OUTOFPLACE
    }
}

fn translate_location_back(location: ffi::clfftResultLocation) -> Location {
    match location {
        ffi::clfftResultLocation::CLFFT_INPLACE => Location::Inplace,
        ffi::clfftResultLocation::CLFFT_OUTOFPLACE => Location::OutOfPlace,
        ffi::clfftResultLocation::ENDPLACE => panic!("ENDPLACE should never be returned")
    }
}

impl FftPlanBuilder {
    /// Create a plan object initialized entirely with default values.
    ///
    /// A plan is a repository of state for calculating FFT's.  Allows the runtime to pre-calculate kernels, programs
    /// and buffers and associate them with buffers of specified dimensions.
    pub fn default<D: Into<ocl::SpatialDims>>(pro_que: &ocl::ProQue, dims: D)
        -> ocl::Result<FftPlanBuilder> {
        let context = unsafe { pro_que.context().core_as_ref().as_ptr() };
        let dims = dims.into();
        let dim = translate_to_fft_dim(dims);
        let lengths = try!(dims.to_lens());
        let mut plan: ffi::clfftPlanHandle = 0;
        clfft_try!( unsafe { ffi::clfftCreateDefaultPlan(&mut plan, context, dim, &lengths as *const usize) } );
        Ok(FftPlanBuilder {  handle: plan })
    }

    /// Returns the native clFFT plan handle.
    pub fn plan_handle(&self) -> ffi::clfftPlanHandle {
        self.handle
    }

    /// Set the floating point precision of the FFT data
    pub fn set_precision(&mut self, precision: Precision) -> ocl::Result<()> {
        let precision = translate_precision(precision);
        clfft_try!(unsafe { ffi::clfftSetPlanPrecision(self.handle, precision) });
        Ok(())
    }

    pub fn get_precision(&self) -> ocl::Result<Precision> {
        let mut precision = ffi::clfftPrecision::CLFFT_SINGLE;
        clfft_try!(unsafe { ffi::clfftGetPlanPrecision(self.handle, &mut precision) });
        Ok(translate_precision_back(precision))
    }

    /// Set the expected layout of the input and output buffers
    pub fn set_layout(&mut self, input_layout: Layout, output_layout: Layout) -> ocl::Result<()> {
        let input_layout = translate_layout(input_layout);
        let output_layout = translate_layout(output_layout);
        clfft_try!(unsafe { ffi::clfftSetLayout(self.handle, input_layout, output_layout) });
        Ok(())
    }

    pub fn get_layout(&self) -> ocl::Result<(Layout, Layout)> {
        let mut input_layout = ffi::clfftLayout::CLFFT_COMPLEX_INTERLEAVED;
        let mut output_layout = ffi::clfftLayout::CLFFT_COMPLEX_INTERLEAVED;
        clfft_try!(unsafe { ffi::clfftGetLayout(self.handle, &mut input_layout, &mut output_layout) });
        Ok((translate_layout_back(input_layout), translate_layout_back(output_layout)))
    }

    /// Set whether the input buffers are to be overwritten with results
    pub fn set_result_location(&mut self, location: Location) -> ocl::Result<()> {
        let location = translate_location(location);
        clfft_try!(unsafe { ffi::clfftSetResultLocation(self.handle, location) });
        Ok(())
    }

    pub fn get_result_location(&self) -> ocl::Result<Location> {
        let mut location = ffi::clfftResultLocation::CLFFT_INPLACE;
        clfft_try!(unsafe { ffi::clfftGetResultLocation(self.handle, &mut location) });
        Ok(translate_location_back(location))
    }
}

impl std::ops::Drop for FftPlanBuilder {
    fn drop(&mut self) {
        if self.handle != 0 {
            unsafe { ffi::clfftDestroyPlan(&mut self.handle) };
            self.handle = 0;
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ocl::{ProQue};
    use ocl::builders::ProgramBuilder;

    #[test]
    pub fn fft_test() {
        init_lib();
        let prog_bldr = ProgramBuilder::new();
        let ocl_pq = ProQue::builder()
            .prog_bldr(prog_bldr)
            .build()
            .expect("Building ProQue");
        FftPlan::default(&ocl_pq, [1000]);
        drop_lib();
    }
}<|endoftext|>


<commit_before>use std::str;

const DATA: &'static str = include_str!("../data/input_5.txt");

pub fn main() -> Vec<String> {
    let s1 = nice_count(DATA);
    let s2 = nicer_count(DATA);
    vec![s1.to_string(), s2.to_string()]
}

fn nice(s: &str) -> bool {
    let has_three_vowels = |s: &str| s.chars().filter(|c| "aeiou".contains(*c)).count() >= 3;
    let has_doubles = |s: &str| s.as_bytes().windows(2).any(|w| w[0] == w[1]);
    let has_bad_pairs = |s: &str| {
        s.as_bytes()
         .windows(2)
         .any(|w| ["ab", "cd", "pq", "xy"].contains(&(unsafe { str::from_utf8_unchecked(w) })))
    };
    has_three_vowels(s) && has_doubles(s) && !has_bad_pairs(s)
}

fn nice_count(input: &str) -> usize {
    input.lines()
         .filter(|line| nice(line))
         .count()
}

fn nicer(s: &str) -> bool {
    let has_double_pairs = |s: &str| {
        let bs = s.as_bytes();
        (0..bs.len() - 3)
            .any(|n| bs[n + 2..].windows(2).any(|w| w[0] == bs[n] && w[1] == bs[n + 1]))
    };
    let has_sandwich = |s: &str| s.as_bytes().windows(3).any(|w| w[0] == w[2]);
    has_double_pairs(s) && has_sandwich(s)
}

fn nicer_count(input: &str) -> usize {
    input.lines()
         .filter(|line| nicer(line))
         .count()
}

#[cfg(test)]
mod test {
    use super::{nice_count, nicer_count};

    #[test]
    fn test_nice_string() {
        assert_eq!(nice_count("ugknbfddgicrmopn"), 1);
        assert_eq!(nice_count("aaa"), 1);
        assert_eq!(nice_count("jchzalrnumimnmhp"), 0);
        assert_eq!(nice_count("haegwjzuvuyypxyu"), 0);
        assert_eq!(nice_count("dvszwmarrgswjxmb"), 0);
    }

    #[test]
    fn test_nicer_string() {
        assert_eq!(nicer_count("qjhvhtzxzqqjkmpb"), 1);
        assert_eq!(nicer_count("xxyxx"), 1);
        assert_eq!(nicer_count("uurcxstgmygtbstg"), 0);
        assert_eq!(nicer_count("eodomkazucvgmuy"), 0);
    }
}
<commit_msg>day 5: use pattern matching instead of contains<commit_after>use std::str;

const DATA: &'static str = include_str!("../data/input_5.txt");

pub fn main() -> Vec<String> {
    let s1 = nice_count(DATA);
    let s2 = nicer_count(DATA);
    vec![s1.to_string(), s2.to_string()]
}

fn nice(s: &str) -> bool {
    let has_three_vowels = |s: &str| {
        s.chars()
         .filter(|&c| {
             match c {
                 'a' | 'e' | 'i' | 'o' | 'u' => true,
                 _ => false,
             }
         })
         .count() >= 3
    };
    let has_doubles = |s: &str| {
        s.as_bytes()
         .windows(2)
         .any(|w| w[0] == w[1])
    };
    let has_bad_pairs = |s: &str| {
        s.as_bytes()
         .windows(2)
         .any(|w| {
             match unsafe { str::from_utf8_unchecked(w) } {
                 "ab" | "cd" | "pq" | "xy" => true,
                 _ => false,
             }
         })
    };
    has_three_vowels(s) && has_doubles(s) && !has_bad_pairs(s)
}

fn nice_count(input: &str) -> usize {
    input.lines()
         .filter(|line| nice(line))
         .count()
}

fn nicer(s: &str) -> bool {
    let has_double_pairs = |s: &str| {
        let bs = s.as_bytes();
        (0..bs.len() - 3).any(|n| {
            bs[n + 2..]
                .windows(2)
                .any(|w| w[0] == bs[n] && w[1] == bs[n + 1])
        })
    };
    let has_sandwich = |s: &str| {
        s.as_bytes()
         .windows(3)
         .any(|w| w[0] == w[2])
    };
    has_double_pairs(s) && has_sandwich(s)
}

fn nicer_count(input: &str) -> usize {
    input.lines()
         .filter(|line| nicer(line))
         .count()
}

#[cfg(test)]
mod test {
    use super::{nice_count, nicer_count};

    #[test]
    fn test_nice_string() {
        assert_eq!(nice_count("ugknbfddgicrmopn"), 1);
        assert_eq!(nice_count("aaa"), 1);
        assert_eq!(nice_count("jchzalrnumimnmhp"), 0);
        assert_eq!(nice_count("haegwjzuvuyypxyu"), 0);
        assert_eq!(nice_count("dvszwmarrgswjxmb"), 0);
    }

    #[test]
    fn test_nicer_string() {
        assert_eq!(nicer_count("qjhvhtzxzqqjkmpb"), 1);
        assert_eq!(nicer_count("xxyxx"), 1);
        assert_eq!(nicer_count("uurcxstgmygtbstg"), 0);
        assert_eq!(nicer_count("eodomkazucvgmuy"), 0);
    }
}
<|endoftext|>


<commit_before>use std::str::FromStr;
use std::collections::HashMap;

#[derive(PartialEq, Eq, Hash, Clone)]
struct Wire(pub String);

#[derive(PartialEq, Eq, Hash, Clone)]
enum Source {
    Pattern(u16),
    Wire(Wire),
}

impl FromStr for Source {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Source, Self::Err> {
        match s {
            s if s.is_empty() => Err("empty identifier"),
            s if (|s: &str| s.chars().all(|c| c.is_digit(10)))(s) => {
                s.parse::<u16>().map_err(|_| "parse error").map(Source::Pattern)
            }
            s if (|s: &str| s.chars().all(|c| c.is_alphabetic()))(s) => {
                return Ok(Source::Wire(Wire(s.to_owned())))
            }
            _ => Err("unknown identifier format"),
        }
    }
}

#[derive(PartialEq, Eq, Hash, Clone)]
enum Gate {
    Pass {
        src: Source,
        out: Source,
    },
    Not {
        src: Source,
        out: Source,
    },
    And {
        a: Source,
        b: Source,
        out: Source,
    },
    Or {
        a: Source,
        b: Source,
        out: Source,
    },
    LShift {
        src: Source,
        shift: u16,
        out: Source,
    },
    RShift {
        src: Source,
        shift: u16,
        out: Source,
    },
}

impl FromStr for Gate {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Gate, Self::Err> {
        match &s.split_whitespace().collect::<Vec<_>>()[..] {
            [a, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| {
                     o.parse::<Source>()
                      .map(|o| Gate::Pass { src: a, out: o })
                 })
            }
            ["NOT", a, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| {
                     o.parse::<Source>()
                      .map(|o| Gate::Not { src: a, out: o })
                 })
            }
            [a, "AND", b, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| {
                     b.parse::<Source>()
                      .and_then(|b| {
                          o.parse::<Source>()
                           .map(|o| {
                               Gate::And {
                                   a: a,
                                   b: b,
                                   out: o,
                               }
                           })
                      })
                 })
            }
            [a, "OR", b, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| {
                     b.parse::<Source>()
                      .and_then(|b| {
                          o.parse::<Source>()
                           .map(|o| {
                               Gate::Or {
                                   a: a,
                                   b: b,
                                   out: o,
                               }
                           })
                      })
                 })
            }
            [a, "LSHIFT", n, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| {
                     n.parse::<u16>()
                      .map_err(|_| "parse error")
                      .and_then(|n| {
                          o.parse::<Source>()
                           .map(|o| {
                               Gate::LShift {
                                   src: a,
                                   shift: n,
                                   out: o,
                               }
                           })
                      })
                 })
            }
            [a, "RSHIFT", n, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| {
                     n.parse::<u16>()
                      .map_err(|_| "parse error")
                      .and_then(|n| {
                          o.parse::<Source>()
                           .map(|o| {
                               Gate::RShift {
                                   src: a,
                                   shift: n,
                                   out: o,
                               }
                           })
                      })
                 })
            }
            _ => Err("bad input"),
        }
    }
}

impl Gate {
    fn out(&self) -> Source {
        match *self {
            Gate::Pass{ ref out, ..} => out,
            Gate::Not{ ref out, ..} => out,
            Gate::And{ ref out, ..} => out,
            Gate::Or{ ref out, ..} => out,
            Gate::LShift{ ref out, ..} => out,
            Gate::RShift{ ref out, ..} => out,
        }
        .clone()
    }

    fn eval(&self, c: &mut Circuit) -> Option<u16> {
        match *self {
            Gate::Pass{ ref src, .. } => c.eval(src),
            Gate::Not{ ref src, .. } => c.eval(src).map(|v| !v),
            Gate::And{ ref a, ref b, .. } => {
                match (c.eval(a), c.eval(b)) {
                    (None, _) => None,
                    (_, None) => None,
                    (Some(lhs), Some(rhs)) => Some(lhs & rhs),
                }
            }
            Gate::Or{ ref a, ref b, .. } => {
                match (c.eval(a), c.eval(b)) {
                    (None, _) => None,
                    (_, None) => None,
                    (Some(lhs), Some(rhs)) => Some(lhs | rhs),
                }
            }
            Gate::LShift{ ref src, shift, .. } => c.eval(src).map(|v| v << shift),
            Gate::RShift{ ref src, shift, .. } => c.eval(src).map(|v| v >> shift),
        }
    }
}

struct Circuit {
    gates: HashMap<Source, Gate>,
    cache: HashMap<Source, u16>,
}

impl Circuit {
    fn from_str(input: &str) -> Circuit {
        let mut circuit = HashMap::new();
        let cache = HashMap::new();

        for line in input.lines() {
            let gate = Gate::from_str(line).unwrap();
            circuit.insert(gate.out(), gate);
        }
        Circuit {
            gates: circuit,
            cache: cache,
        }
    }

    fn eval(&mut self, wire: &Source) -> Option<u16> {
        match *wire {
            Source::Pattern(p) => Some(p),
            ref s @ Source::Wire(_) => {
                if self.cache.contains_key(s) {
                    self.cache.get(s).cloned()
                } else {
                    let v = self.gates.get(s).cloned().and_then(|g| g.eval(self));
                    self.cache.insert(s.clone(), v.unwrap());
                    v
                }
            }
        }
    }

    fn force(&mut self, s: &Source, v: u16) {
        self.cache.clear();
        self.cache.insert(s.clone(), v);
    }
}

fn run_circuit(input: &str, target: &str) -> u16 {
    let mut c = Circuit::from_str(input);
    c.eval(&Source::Wire(Wire(target.to_owned()))).unwrap()
}

fn part2(input: &str, target: &str, force: &str, v: u16) -> u16 {
    let mut c = Circuit::from_str(input);
    c.force(&Source::Wire(Wire(force.to_owned())), v);
    c.eval(&Source::Wire(Wire(target.to_owned()))).unwrap()
}

#[cfg(test)]
mod test {
    use super::{Circuit, Source, Wire};

    #[test]
    fn test_circuit() {
        let cs = ["123 -> x",
                  "456 -> y",
                  "x AND y -> d",
                  "x OR y -> e",
                  "x LSHIFT 2 -> f",
                  "y RSHIFT 2 -> g",
                  "NOT x -> h",
                  "NOT y -> i"]
                     .join("\n");
        let mut c = Circuit::from_str(&cs);
        assert_eq!(c.eval(&Source::Wire(Wire("d".to_owned()))), Some(72));
        assert_eq!(c.eval(&Source::Wire(Wire("e".to_owned()))), Some(507));
        assert_eq!(c.eval(&Source::Wire(Wire("f".to_owned()))), Some(492));
        assert_eq!(c.eval(&Source::Wire(Wire("g".to_owned()))), Some(114));
        assert_eq!(c.eval(&Source::Wire(Wire("h".to_owned()))), Some(65412));
        assert_eq!(c.eval(&Source::Wire(Wire("i".to_owned()))), Some(65079));
        assert_eq!(c.eval(&Source::Wire(Wire("x".to_owned()))), Some(123));
        assert_eq!(c.eval(&Source::Wire(Wire("y".to_owned()))), Some(456));
    }
}

const DATA: &'static str = include_str!("../data/input_7.txt");

pub fn main() -> Vec<String> {
    let s1 = run_circuit(DATA, "a");
    let s2 = part2(DATA, "a", "b", 956);
    vec![s1.to_string(), s2.to_string()]
}
<commit_msg>day07: more cleanup + remove unwrap calls<commit_after>use std::str::FromStr;
use std::collections::HashMap;

#[derive(PartialEq, Eq, Hash, Clone)]
enum Source {
    Pattern(u16),
    Wire(String),
}

impl FromStr for Source {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Source, Self::Err> {
        match s {
            s if s.is_empty() => Err("empty identifier"),
            s if (|s: &str| s.chars().all(|c| c.is_digit(10)))(s) => {
                s.parse::<u16>().map_err(|_| "parse error").map(Source::Pattern)
            }
            s if (|s: &str| s.chars().all(|c| c.is_alphabetic()))(s) => {
                Ok(Source::Wire(s.to_owned()))
            }
            _ => Err("unknown identifier format"),
        }
    }
}

#[derive(PartialEq, Eq, Hash, Clone)]
enum Gate {
    Pass {
        src: Source,
        out: Source,
    },
    Not {
        src: Source,
        out: Source,
    },
    And {
        a: Source,
        b: Source,
        out: Source,
    },
    Or {
        a: Source,
        b: Source,
        out: Source,
    },
    LShift {
        src: Source,
        shift: u16,
        out: Source,
    },
    RShift {
        src: Source,
        shift: u16,
        out: Source,
    },
}

impl FromStr for Gate {
    type Err = &'static str;
    fn from_str(s: &str) -> Result<Gate, Self::Err> {
        match &s.split_whitespace().collect::<Vec<_>>()[..] {
            [a, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| o.parse::<Source>().map(|o| Gate::Pass { src: a, out: o }))
            }
            ["NOT", a, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| o.parse::<Source>().map(|o| Gate::Not { src: a, out: o }))
            }
            [a, "AND", b, "->", o] => {
                a.parse::<Source>().and_then(|a| {
                    b.parse::<Source>().and_then(|b| {
                        o.parse::<Source>().map(|o| {
                            Gate::And {
                                a: a,
                                b: b,
                                out: o,
                            }
                        })
                    })
                })
            }
            [a, "OR", b, "->", o] => {
                a.parse::<Source>().and_then(|a| {
                    b.parse::<Source>().and_then(|b| {
                        o.parse::<Source>().map(|o| {
                            Gate::Or {
                                a: a,
                                b: b,
                                out: o,
                            }
                        })
                    })
                })
            }
            [a, "LSHIFT", n, "->", o] => {
                a.parse::<Source>().and_then(|a| {
                    n.parse::<u16>().map_err(|_| "parse error").and_then(|n| {
                        o.parse::<Source>().map(|o| {
                            Gate::LShift {
                                src: a,
                                shift: n,
                                out: o,
                            }
                        })
                    })
                })
            }
            [a, "RSHIFT", n, "->", o] => {
                a.parse::<Source>().and_then(|a| {
                    n.parse::<u16>().map_err(|_| "parse error").and_then(|n| {
                        o.parse::<Source>().map(|o| {
                            Gate::RShift {
                                src: a,
                                shift: n,
                                out: o,
                            }
                        })
                    })
                })
            }
            _ => Err("bad input"),
        }
    }
}

impl Gate {
    fn out(&self) -> Source {
        match *self {
            Gate::Pass{ ref out, ..} => out,
            Gate::Not{ ref out, ..} => out,
            Gate::And{ ref out, ..} => out,
            Gate::Or{ ref out, ..} => out,
            Gate::LShift{ ref out, ..} => out,
            Gate::RShift{ ref out, ..} => out,
        }
        .clone()
    }

    fn eval(&self, c: &mut Circuit) -> Option<u16> {
        match *self {
            Gate::Pass{ ref src, .. } => c.eval(src),
            Gate::Not{ ref src, .. } => c.eval(src).map(|v| !v),
            Gate::And{ ref a, ref b, .. } => {
                match (c.eval(a), c.eval(b)) {
                    (None, _) => None,
                    (_, None) => None,
                    (Some(lhs), Some(rhs)) => Some(lhs & rhs),
                }
            }
            Gate::Or{ ref a, ref b, .. } => {
                match (c.eval(a), c.eval(b)) {
                    (None, _) => None,
                    (_, None) => None,
                    (Some(lhs), Some(rhs)) => Some(lhs | rhs),
                }
            }
            Gate::LShift{ ref src, shift, .. } => c.eval(src).map(|v| v << shift),
            Gate::RShift{ ref src, shift, .. } => c.eval(src).map(|v| v >> shift),
        }
    }
}

struct Circuit {
    gates: HashMap<Source, Gate>,
    cache: HashMap<Source, u16>,
}

impl FromStr for Circuit {
    type Err = &'static str;

    fn from_str(input: &str) -> Result<Circuit, Self::Err> {
        let mut circuit = HashMap::new();
        let cache = HashMap::new();

        for line in input.lines() {
            if let Ok(gate) = Gate::from_str(line) {
                circuit.insert(gate.out(), gate);
            } else {
                return Err("gate parse error");
            }
        }
        Ok(Circuit {
            gates: circuit,
            cache: cache,
        })
    }
}

impl Circuit {
    fn eval(&mut self, wire: &Source) -> Option<u16> {
        match *wire {
            Source::Pattern(p) => Some(p),
            ref s @ Source::Wire(_) => {
                if self.cache.contains_key(s) {
                    self.cache.get(s).cloned()
                } else {
                    if let Some(v) = self.gates.get(s).cloned().and_then(|g| g.eval(self)) {
                        self.cache.insert(s.clone(), v);
                        Some(v)
                    } else {
                        None
                    }
                }
            }
        }
    }

    fn force(&mut self, s: &Source, v: u16) {
        self.cache.clear();
        self.cache.insert(s.clone(), v);
    }
}

fn run_circuit(input: &str, target: &str) -> Option<u16> {
    if let Ok(mut c) = Circuit::from_str(input) {
        c.eval(&Source::Wire(target.to_owned()))
    } else {
        None
    }
}

fn part2(input: &str, target: &str, force: &str, v: u16) -> Option<u16> {
    if let Ok(mut c) = Circuit::from_str(input) {
        c.force(&Source::Wire(force.to_owned()), v);
        c.eval(&Source::Wire(target.to_owned()))
    } else {
        None
    }
}

#[cfg(test)]
mod test {
    use std::str::FromStr;
    use super::{Circuit, Source};

    #[test]
    fn test_circuit() {
        let cs = ["123 -> x",
                  "456 -> y",
                  "x AND y -> d",
                  "x OR y -> e",
                  "x LSHIFT 2 -> f",
                  "y RSHIFT 2 -> g",
                  "NOT x -> h",
                  "NOT y -> i"]
                     .join("\n");
        let mut c = Circuit::from_str(&cs).unwrap();
        assert_eq!(c.eval(&Source::Wire("d".to_owned())), Some(72));
        assert_eq!(c.eval(&Source::Wire("e".to_owned())), Some(507));
        assert_eq!(c.eval(&Source::Wire("f".to_owned())), Some(492));
        assert_eq!(c.eval(&Source::Wire("g".to_owned())), Some(114));
        assert_eq!(c.eval(&Source::Wire("h".to_owned())), Some(65412));
        assert_eq!(c.eval(&Source::Wire("i".to_owned())), Some(65079));
        assert_eq!(c.eval(&Source::Wire("x".to_owned())), Some(123));
        assert_eq!(c.eval(&Source::Wire("y".to_owned())), Some(456));
    }
}

const DATA: &'static str = include_str!("../data/input_7.txt");

pub fn main() -> Vec<String> {
    let s1 = run_circuit(DATA, "a").unwrap();
    let s2 = part2(DATA, "a", "b", 956).unwrap();
    vec![s1.to_string(), s2.to_string()]
}
<|endoftext|>