<commit_before>// Copyright (c) 2016, 2018 Nikita Pekin and the ferru contributors
// See the README.md file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fs;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};

use config::Config;
use document;
use error::{Error, Result};
use template;
use util;

/// Reads all relevant files in the specified source directory, uses them to
/// generate a static website, and stores the resulting files in the specified
/// destination directory.
pub fn build(config: &Config) -> Result<()> {
    const DEFAULT_SOURCE_PATH: &'static str = "./";
    const DEFAULT_DEST_PATH: &'static str = "./_site/";

    // Get the source path opt.
    let source = config.source_directory.as_ref()
        .map(Path::new)
        .map_or_else(|| PathBuf::from(DEFAULT_SOURCE_PATH), Path::to_path_buf);
    if !source.exists() {
        return Err(Error::path_not_found(&source))
    }

    // Get the destination path opt.
    let dest = config.dest_directory.as_ref()
        .map(Path::new)
        .map_or_else(|| PathBuf::from(DEFAULT_DEST_PATH), Path::to_path_buf);

    debug!("Cleaning destination directory");
    if !dest.exists() {
        println!("Destination directory \"{}\" does not exist, creating.", dest.display());
        fs::create_dir(&dest)?;
    } else {
        println!("Cleaning destination directory \"{}\".", dest.display());
        remove_dir_contents(&dest)?;
    }

    // Load the templates.
    debug!("Loading templates");
    let templates = match template::load_templates_from_disk(&source.join("_templates"), |path| {
        !util::is_hidden(&path) &&
        path.extension().and_then(OsStr::to_str) == Some("tpl")
    }) {
        Ok(v) => v,
        Err(e) => {
            println!("Failed to read templates: {}", e);
            return Err(e);
        }
    };

    // Copy all non-template and non-document content.
    debug!("Copying static files");
    if source != dest {
        let is_static_file = |path: &Path| {
            !util::is_hidden(&path) &&
            path != dest &&
            !path.to_str().map_or(false, |path| path.contains("_posts")) &&
            !path.to_str().map_or(false, |path| path.contains("_templates"))
        };

        try!(util::copy_recursively(&source, &dest, is_static_file))
    }

    debug!("Loading documents from disk");
    let documents: HashMap<PathBuf, document::Document> = try!(document::load_documents_from_disk(&source.join("_posts"), |path| {
        !util::is_hidden(&path)
    }));

    debug!("Rendering documents");
    for (key, document) in documents.into_iter() {
        let new_dest = dest.join(&key);
        try!(document.render_to_file(&new_dest, &templates));
    }

    Ok(())
}

fn remove_dir_contents(path: &Path) -> Result<()> {
    if path.is_dir() {
        for entry in fs::read_dir(path)? {
            let entry = entry?;
            let path = entry.path();
            if path.is_dir() {
                fs::remove_dir_all(path)?;
            } else {
                fs::remove_file(path)?;
            }
        }
    } else {
        warn!("Attempted to remove dir contents for a file path");
    }

    Ok(())
}
<commit_msg>impr: render non-static files to a separate dir<commit_after>// Copyright (c) 2016, 2018 Nikita Pekin and the ferru contributors
// See the README.md file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fs;
use std::collections::HashMap;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};

use config::Config;
use document;
use error::{Error, Result};
use template;
use util;

/// Reads all relevant files in the specified source directory, uses them to
/// generate a static website, and stores the resulting files in the specified
/// destination directory.
pub fn build(config: &Config) -> Result<()> {
    const DEFAULT_SOURCE_PATH: &'static str = "./";
    const DEFAULT_DEST_PATH: &'static str = "./_site/";

    // Get the source path opt.
    let source = config.source_directory.as_ref()
        .map(Path::new)
        .map_or_else(|| PathBuf::from(DEFAULT_SOURCE_PATH), Path::to_path_buf);
    if !source.exists() {
        return Err(Error::path_not_found(&source))
    }

    // Get the destination path opt.
    let dest = config.dest_directory.as_ref()
        .map(Path::new)
        .map_or_else(|| PathBuf::from(DEFAULT_DEST_PATH), Path::to_path_buf);

    debug!("Cleaning destination directory");
    if !dest.exists() {
        println!("Destination directory \"{}\" does not exist, creating.", dest.display());
        fs::create_dir(&dest)?;
    } else {
        println!("Cleaning destination directory \"{}\".", dest.display());
        remove_dir_contents(&dest)?;
    }

    // Load the templates.
    debug!("Loading templates");
    let templates = match template::load_templates_from_disk(&source.join("_templates"), |path| {
        !util::is_hidden(&path) &&
        path.extension().and_then(OsStr::to_str) == Some("tpl")
    }) {
        Ok(v) => v,
        Err(e) => {
            println!("Failed to read templates: {}", e);
            return Err(e);
        }
    };

    // Copy all non-template and non-document content.
    debug!("Copying static files");
    if source != dest {
        let is_static_file = |path: &Path| {
            !util::is_hidden(&path) &&
            path != dest &&
            !path.to_str().map_or(false, |path| path.contains("_posts")) &&
            !path.to_str().map_or(false, |path| path.contains("_templates"))
        };

        try!(util::copy_recursively(&source, &dest, is_static_file))
    }

    debug!("Loading documents from disk");
    let documents: HashMap<PathBuf, document::Document> = try!(document::load_documents_from_disk(&source.join("_posts"), |path| {
        !util::is_hidden(&path)
    }));

    debug!("Rendering documents");
    // Render non-static files to a www/ directory.
    let dest = dest.join("www");
    for (key, document) in documents.into_iter() {
        let new_dest = dest.join(&key);
        try!(document.render_to_file(&new_dest, &templates));
    }

    Ok(())
}

fn remove_dir_contents(path: &Path) -> Result<()> {
    if path.is_dir() {
        for entry in fs::read_dir(path)? {
            let entry = entry?;
            let path = entry.path();
            if path.is_dir() {
                fs::remove_dir_all(path)?;
            } else {
                fs::remove_file(path)?;
            }
        }
    } else {
        warn!("Attempted to remove dir contents for a file path");
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::mem;
use std::ptr;

#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
struct Rawlink<T> {
    p: *mut T
}

impl<T> Rawlink<T> {
    fn none() -> Rawlink<T> {
        Rawlink { p: ptr::null_mut() }
    }

    fn some(n: &mut T) -> Rawlink<T> {
        Rawlink { p: n }
    }

    fn take(&mut self) -> Rawlink<T> {
        mem::replace(self, Rawlink::none())
    }
}

struct Node<T> {
    val: T,
    next: Option<Box<Node<T>>>
}

impl<T> Node<T> {
    /// work around for moved value
    fn into_val_and_next(self) -> (T, Option<Box<Node<T>>>) {
        (self.val, self.next)
    }

    fn len(&self) -> usize {
        self.next.as_ref().map_or(1, |n| 1 + n.len())
    }
}

impl<T: Clone> Clone for Node<T> {
    fn clone(&self) -> Self {
        Node {
            val: self.val.clone(),
            next: self.next.clone()
        }
    }
}

pub struct Queue<T> {
    first: Option<Box<Node<T>>>,
    last: Rawlink<Node<T>>
}

impl<T: Clone> Clone for Queue<T> {
    fn clone(&self) -> Self {
        let mut first = self.first.clone();
        let last = {
            let mut p = first.as_mut();
            while p.as_ref().map_or(false, |n| n.next.is_some()) {
                p = p.unwrap().next.as_mut();
            }
            p.map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
        };
        Queue {
            first: first,
            last: last
        }
    }
}

impl<T> Queue<T> {
    pub fn new() -> Queue<T> {
        Queue { first: None, last: Rawlink::none() }
    }

    pub fn is_empty(&self) -> bool {
        self.first.is_none()
    }

    pub fn enqueue(&mut self, val: T) {
        let ref old_last = self.last.take();
        let mut last = Box::new(Node {
            val: val,
            next: None
        });
        self.last = Rawlink::some(&mut last);
        if self.is_empty() {
            self.first = Some(last)
        } else {
            unsafe {
                (*old_last.p).next = Some(last)
            }
        }
    }

    pub fn dequeue(&mut self) -> Option<T> {
        if self.first.is_none() {
            return None;
        }
        let old_first = self.first.take();
        let (val, first) = old_first.unwrap().into_val_and_next();
        self.first = first;
        if self.first.is_none() {
            self.last = Rawlink::none()
        }
        Some(val)
    }

    pub fn peek(&self) -> Option<&T> {
        self.first.as_ref().map(|n| &(*n).val)
    }

    pub fn peek_mut(&mut self) -> Option<&mut T> {
        self.first.as_mut().map(|n| &mut (*n).val)
    }

    pub fn len(&self) -> usize {
        self.first.as_ref().map_or(0, |n| n.len())
    }
}

pub struct IntoIter<T> {
    queue: Queue<T>
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.queue.dequeue()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let length = self.queue.len();
        (length, Some(length))
    }
}

impl<T> IntoIterator for Queue<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter { queue: self }
    }
}

#[test]
fn test_queue() {
    let mut queue = Queue::<&str>::new();
    assert!(queue.is_empty());
    assert_eq!(queue.len(), 0);

    assert_eq!(queue.peek(), None);

    queue.enqueue("welcome");
    queue.enqueue("to");
    queue.enqueue("china");
    assert!(!queue.is_empty());
    assert_eq!(queue.len(), 3);

    assert_eq!(queue.peek(), Some(&"welcome"));
    queue.peek_mut().map(|val| *val = "go");
    assert_eq!(queue.peek(), Some(&"go"));
}

#[test]
fn test_queue_clone() {
    let mut queue1 = Queue::<&str>::new();
    queue1.enqueue("welcome");
    queue1.enqueue("to");
    queue1.enqueue("china");

    let mut queue2 = queue1.clone();
    queue2.dequeue();
    assert_eq!(queue1.peek(), Some(&"welcome"));
    assert_eq!(queue2.peek(), Some(&"to"));

    queue2.dequeue();
    queue2.dequeue();
    queue2.enqueue("beijing");

    assert_eq!(queue1.peek(), Some(&"welcome"));
    assert_eq!(queue2.peek(), Some(&"beijing"));

}

#[test]
fn test_queue_into_iter() {
    let mut queue = Queue::<&str>::new();
    queue.enqueue("welcome");
    queue.enqueue("to");
    queue.enqueue("china");

    let result = vec!["welcome", "to", "china"];
    for i in queue {
        assert!(result.contains(&i));
    }
}
<commit_msg>implement iter() for Queue<commit_after>use std::mem;
use std::ptr;

#[allow(raw_pointer_derive)]
#[derive(Clone, Copy)]
struct Rawlink<T> {
    p: *mut T
}

impl<T> Rawlink<T> {
    fn none() -> Rawlink<T> {
        Rawlink { p: ptr::null_mut() }
    }

    fn some(n: &mut T) -> Rawlink<T> {
        Rawlink { p: n }
    }

    fn take(&mut self) -> Rawlink<T> {
        mem::replace(self, Rawlink::none())
    }
}

struct Node<T> {
    val: T,
    next: Option<Box<Node<T>>>
}

impl<T> Node<T> {
    /// work around for moved value
    fn into_val_and_next(self) -> (T, Option<Box<Node<T>>>) {
        (self.val, self.next)
    }

    fn len(&self) -> usize {
        self.next.as_ref().map_or(1, |n| 1 + n.len())
    }
}

impl<T: Clone> Clone for Node<T> {
    fn clone(&self) -> Self {
        Node {
            val: self.val.clone(),
            next: self.next.clone()
        }
    }
}

pub struct Queue<T> {
    first: Option<Box<Node<T>>>,
    last: Rawlink<Node<T>>
}

impl<T: Clone> Clone for Queue<T> {
    fn clone(&self) -> Self {
        let mut first = self.first.clone();
        let last = {
            let mut p = first.as_mut();
            while p.as_ref().map_or(false, |n| n.next.is_some()) {
                p = p.unwrap().next.as_mut();
            }
            p.map_or_else(Rawlink::none, |n| Rawlink::some(&mut **n))
        };
        Queue {
            first: first,
            last: last
        }
    }
}

impl<T> Queue<T> {
    pub fn new() -> Queue<T> {
        Queue { first: None, last: Rawlink::none() }
    }

    pub fn is_empty(&self) -> bool {
        self.first.is_none()
    }

    pub fn enqueue(&mut self, val: T) {
        let ref old_last = self.last.take();
        let mut last = Box::new(Node {
            val: val,
            next: None
        });
        self.last = Rawlink::some(&mut last);
        if self.is_empty() {
            self.first = Some(last)
        } else {
            unsafe {
                (*old_last.p).next = Some(last)
            }
        }
    }

    pub fn dequeue(&mut self) -> Option<T> {
        if self.first.is_none() {
            return None;
        }
        let old_first = self.first.take();
        let (val, first) = old_first.unwrap().into_val_and_next();
        self.first = first;
        if self.first.is_none() {
            self.last = Rawlink::none()
        }
        Some(val)
    }

    pub fn peek(&self) -> Option<&T> {
        self.first.as_ref().map(|n| &(*n).val)
    }

    pub fn peek_mut(&mut self) -> Option<&mut T> {
        self.first.as_mut().map(|n| &mut (*n).val)
    }

    pub fn len(&self) -> usize {
        self.first.as_ref().map_or(0, |n| n.len())
    }
}

pub struct IntoIter<T> {
    queue: Queue<T>
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.queue.dequeue()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let length = self.queue.len();
        (length, Some(length))
    }
}

impl<T> IntoIterator for Queue<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter { queue: self }
    }
}

pub struct Iter<'a, T> where T: 'a {
    node: Option<&'a Box<Node<T>>>
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        let ret = self.node.map(|n| &n.val);
        self.node = self.node.map_or(None, |n| n.next.as_ref());
        ret
    }

    // Bad
    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut sz = 0;
        let mut p = self.node;
        while p.is_some() {
            p = p.map_or(None, |n| n.next.as_ref());
            sz += 1;
        }
        (sz, Some(sz))
    }
}

impl<'a, T> ExactSizeIterator for Iter<'a, T> {
    fn len(&self) -> usize {
        self.size_hint().0
    }
}

impl<T> Queue<T> {
    pub fn iter<'a>(&'a self) -> Iter<'a, T> {
        Iter {
            node: self.first.as_ref()
        }
    }
}

#[test]
fn test_queue() {
    let mut queue = Queue::<&str>::new();
    assert!(queue.is_empty());
    assert_eq!(queue.len(), 0);

    assert_eq!(queue.peek(), None);

    queue.enqueue("welcome");
    queue.enqueue("to");
    queue.enqueue("china");
    assert!(!queue.is_empty());
    assert_eq!(queue.len(), 3);

    assert_eq!(queue.peek(), Some(&"welcome"));
    queue.peek_mut().map(|val| *val = "go");
    assert_eq!(queue.peek(), Some(&"go"));
}

#[test]
fn test_queue_clone() {
    let mut queue1 = Queue::<&str>::new();
    queue1.enqueue("welcome");
    queue1.enqueue("to");
    queue1.enqueue("china");

    let mut queue2 = queue1.clone();
    queue2.dequeue();
    assert_eq!(queue1.peek(), Some(&"welcome"));
    assert_eq!(queue2.peek(), Some(&"to"));

    queue2.dequeue();
    queue2.dequeue();
    queue2.enqueue("beijing");

    assert_eq!(queue1.peek(), Some(&"welcome"));
    assert_eq!(queue2.peek(), Some(&"beijing"));

}

#[test]
fn test_queue_into_iter() {
    let mut queue = Queue::<&str>::new();
    queue.enqueue("welcome");
    queue.enqueue("to");
    queue.enqueue("china");

    let result = vec!["welcome", "to", "china"];
    for i in queue {
        assert!(result.contains(&i));
    }
}

#[test]
fn test_queue_iter() {
    let mut queue = Queue::<&str>::new();
    queue.enqueue("welcome");
    queue.enqueue("to");
    queue.enqueue("china");

    let mut rit = vec!["welcome", "to", "china"].into_iter();
    for i in queue.iter() {
        assert_eq!(i, &rit.next().unwrap())
    }

}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use uuid::Uuid;

use graphics::{ Graphics, ImageSize };
use graphics::math::Matrix2d;

use event::GenericEvent;
use ai_behavior::{
    Behavior,
    State,
    Running,
};

use sprite::Sprite;

use animation::{
    Animation,
    AnimationState,
};

/// A scene is used to manage sprite's life and run animation with sprite
pub struct Scene<'a, I: ImageSize> {
    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,
    running: HashMap<&'a Uuid,
        Vec<(Behavior<Animation>, State<Animation, AnimationState>, bool)>>,
}

impl<'a, I: ImageSize> Scene<'a, I> {
    /// Create a new scene
    pub fn new() -> Scene<'a, I> {
        Scene {
            children: Vec::new(),
            children_index: HashMap::new(),
            running: HashMap::new(),
        }
    }

    /// Update animation's state
    pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
        // regenerate the animations and their states
        let running = self.running.clone();
        self.running.clear();

        for (id, animations) in running.into_iter() {
            let mut new_animations = Vec::new();

            for (b, mut a, paused) in animations.into_iter() {
                if paused {
                    new_animations.push((b, a, paused));
                    continue;
                }

                let sprite = self.child_mut(&id).unwrap();
                let (status, _) = a.event(e, &mut |_, dt, animation, s| {
                    let (state, status, remain) = {
                        let start_state;
                        let state = match *s {
                            None => { start_state = animation.to_state(sprite); &start_state },
                            Some(ref state) => state,
                        };
                        state.update(sprite, dt)
                    };
                    *s = state;
                    (status, remain)
                });

                match status {
                    // the behavior is still running, add it for next update
                    Running => {
                        new_animations.push((b, a, paused));
                    },
                    _ => {},
                }
            }

            if new_animations.len() > 0 {
                self.running.insert(id, new_animations);
            }
        }
    }

    /// Render this scene
    pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        for child in self.children.iter() {
            child.draw(t, b);
        }
    }

    /// Register animation with sprite
    pub fn run<'b>(&'b mut self, sprite_id: &'a Uuid, animation: &'b Behavior<Animation>) {
        use std::collections::hash_map::Entry::{ Vacant, Occupied };
        let animations = match self.running.entry(sprite_id) {
            Vacant(entry) => entry.insert(Vec::new()),
            Occupied(entry) => entry.into_mut()
        };
        let state = State::new(animation.clone());
        animations.push((animation.clone(), state, false));
    }

    fn find(&self, sprite_id: &Uuid, animation: &Behavior<Animation>) -> Option<usize> {
        let mut index = None;
        if let Some(animations) = self.running.get(sprite_id) {
            for i in 0..animations.len() {
                let (ref b, _, _) = animations[i];
                if b == animation {
                    index = Some(i);
                    break;
                }
            }
        }
        index
    }

    /// Pause a running animation of the sprite
    pub fn pause(&mut self, sprite_id: &Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, true));
        }
    }

    /// Resume a paused animation of the sprite
    pub fn resume(&mut self, sprite_id: &Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, false));
        }
    }

    /// Toggle an animation of the sprite
    pub fn toggle(&mut self, sprite_id: &Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, paused) = animations.remove(index);
            animations.push((b, s, !paused));
        }
    }

    /// Stop a running animation of the sprite
    pub fn stop(&mut self, sprite_id: &Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            self.running.get_mut(&sprite_id).unwrap().remove(index);
        }
    }

    /// Stop all running animations of the sprite
    pub fn stop_all(&mut self, sprite_id: &Uuid) {
        self.running.remove(&sprite_id);
    }

    /// Get all the running animations in the scene
    pub fn running(&self) -> usize {
        let mut total = 0;
        for (_, animations) in self.running.iter() {
            total += animations.len();
        }
        total
    }

    /// Add sprite to scene
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    fn stop_all_including_children(&mut self, sprite: &Sprite<I>) {
        self.stop_all(&sprite.id());
        for child in sprite.children().iter() {
            self.stop_all_including_children(child);
        }
    }

    /// Remove the child by `id` from the scene's children or grandchild
    /// will stop all the animations run by this child
    pub fn remove_child(&mut self, id: &Uuid) -> Option<Sprite<I>> {
        let removed = if let Some(index) = self.children_index.remove(id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        };

        if removed.is_some() {
            self.stop_all_including_children(removed.as_ref().unwrap());
        }

        removed
    }

    /// Find the child by `id` from the scene's children or grandchild
    pub fn child(&self, id: &Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(id) {
            Some(&self.children[*index])
        } else {
            for child in self.children.iter() {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: &Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(id) {
            Some(&mut self.children[*index])
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }
}
<commit_msg>Removed lifetime on `Scene`<commit_after>use std::collections::HashMap;
use uuid::Uuid;

use graphics::{ Graphics, ImageSize };
use graphics::math::Matrix2d;

use event::GenericEvent;
use ai_behavior::{
    Behavior,
    State,
    Running,
};

use sprite::Sprite;

use animation::{
    Animation,
    AnimationState,
};

/// A scene is used to manage sprite's life and run animation with sprite
pub struct Scene<I: ImageSize> {
    children: Vec<Sprite<I>>,
    children_index: HashMap<Uuid, usize>,
    running: HashMap<Uuid,
        Vec<(Behavior<Animation>, State<Animation, AnimationState>, bool)>>,
}

impl<I: ImageSize> Scene<I> {
    /// Create a new scene
    pub fn new() -> Scene<I> {
        Scene {
            children: Vec::new(),
            children_index: HashMap::new(),
            running: HashMap::new(),
        }
    }

    /// Update animation's state
    pub fn event<E>(&mut self, e: &E) where E: GenericEvent {
        // regenerate the animations and their states
        let running = self.running.clone();
        self.running.clear();

        for (id, animations) in running.into_iter() {
            let mut new_animations = Vec::new();

            for (b, mut a, paused) in animations.into_iter() {
                if paused {
                    new_animations.push((b, a, paused));
                    continue;
                }

                let sprite = self.child_mut(&id).unwrap();
                let (status, _) = a.event(e, &mut |_, dt, animation, s| {
                    let (state, status, remain) = {
                        let start_state;
                        let state = match *s {
                            None => { start_state = animation.to_state(sprite); &start_state },
                            Some(ref state) => state,
                        };
                        state.update(sprite, dt)
                    };
                    *s = state;
                    (status, remain)
                });

                match status {
                    // the behavior is still running, add it for next update
                    Running => {
                        new_animations.push((b, a, paused));
                    },
                    _ => {},
                }
            }

            if new_animations.len() > 0 {
                self.running.insert(id, new_animations);
            }
        }
    }

    /// Render this scene
    pub fn draw<B: Graphics<Texture = I>>(&self, t: Matrix2d, b: &mut B) {
        for child in self.children.iter() {
            child.draw(t, b);
        }
    }

    /// Register animation with sprite
    pub fn run<'b>(&'b mut self, sprite_id: &Uuid, animation: &'b Behavior<Animation>) {
        use std::collections::hash_map::Entry::{ Vacant, Occupied };
        let animations = match self.running.entry(sprite_id.clone()) {
            Vacant(entry) => entry.insert(Vec::new()),
            Occupied(entry) => entry.into_mut()
        };
        let state = State::new(animation.clone());
        animations.push((animation.clone(), state, false));
    }

    fn find(&self, sprite_id: &Uuid, animation: &Behavior<Animation>) -> Option<usize> {
        let mut index = None;
        if let Some(animations) = self.running.get(sprite_id) {
            for i in 0..animations.len() {
                let (ref b, _, _) = animations[i];
                if b == animation {
                    index = Some(i);
                    break;
                }
            }
        }
        index
    }

    /// Pause a running animation of the sprite
    pub fn pause(&mut self, sprite_id: &Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, true));
        }
    }

    /// Resume a paused animation of the sprite
    pub fn resume(&mut self, sprite_id: &Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, _) = animations.remove(index);
            animations.push((b, s, false));
        }
    }

    /// Toggle an animation of the sprite
    pub fn toggle(&mut self, sprite_id: &Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            let animations = self.running.get_mut(&sprite_id).unwrap();
            let (b, s, paused) = animations.remove(index);
            animations.push((b, s, !paused));
        }
    }

    /// Stop a running animation of the sprite
    pub fn stop(&mut self, sprite_id: &Uuid, animation: &Behavior<Animation>) {
        if let Some(index) = self.find(sprite_id, animation) {
            self.running.get_mut(&sprite_id).unwrap().remove(index);
        }
    }

    /// Stop all running animations of the sprite
    pub fn stop_all(&mut self, sprite_id: &Uuid) {
        self.running.remove(&sprite_id);
    }

    /// Get all the running animations in the scene
    pub fn running(&self) -> usize {
        let mut total = 0;
        for (_, animations) in self.running.iter() {
            total += animations.len();
        }
        total
    }

    /// Add sprite to scene
    pub fn add_child(&mut self, sprite: Sprite<I>) -> Uuid {
        let id = sprite.id();
        self.children.push(sprite);
        self.children_index.insert(id.clone(), self.children.len() - 1);
        id
    }

    fn stop_all_including_children(&mut self, sprite: &Sprite<I>) {
        self.stop_all(&sprite.id());
        for child in sprite.children().iter() {
            self.stop_all_including_children(child);
        }
    }

    /// Remove the child by `id` from the scene's children or grandchild
    /// will stop all the animations run by this child
    pub fn remove_child(&mut self, id: &Uuid) -> Option<Sprite<I>> {
        let removed = if let Some(index) = self.children_index.remove(id) {
            let removed = self.children.remove(index);
            // Removing a element of vector will alter the index,
            // update the mapping from uuid to index.
            for i in index..self.children.len() {
                let uuid = self.children[i].id();
                self.children_index.insert(uuid, i);
            }
            Some(removed)
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.remove_child(id.clone()) {
                    return Some(c);
                }
            }
            None
        };

        if removed.is_some() {
            self.stop_all_including_children(removed.as_ref().unwrap());
        }

        removed
    }

    /// Find the child by `id` from the scene's children or grandchild
    pub fn child(&self, id: &Uuid) -> Option<&Sprite<I>> {
        if let Some(index) = self.children_index.get(id) {
            Some(&self.children[*index])
        } else {
            for child in self.children.iter() {
                if let Some(c) = child.child(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }

    /// Find the child by `id` from this sprite's children or grandchild, mutability
    pub fn child_mut(&mut self, id: &Uuid) -> Option<&mut Sprite<I>> {
        if let Some(index) = self.children_index.get(id) {
            Some(&mut self.children[*index])
        } else {
            for child in self.children.iter_mut() {
                if let Some(c) = child.child_mut(id.clone()) {
                    return Some(c);
                }
            }
            None
        }
    }
}
<|endoftext|>


<commit_before>extern crate firebase;

use firebase::Firebase;

#[test]
fn builds_auth_url() {
    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    assert_eq!(f.get_url(), "http://db.rifebass.com/?auth=deadbeaf");
}

#[test]
fn extends_auth_url() {
    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama/SpacePilot3000").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn double_extends_url() {
    let f = Firebase::authed("http://db.rifebass.com", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama.json").ok().unwrap();
    let f = f.at("SpacePilot3000").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn handle_slashes() {
    let f = Firebase::authed("http://db.rifebass.com", "deadbeaf").ok().unwrap();
    let f = f.at("futurama.json").ok().unwrap();
    let f = f.at("SpacePilot3000.json").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());

    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama/").ok().unwrap();
    let f = f.at("/SpacePilot3000/").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn handle_json_suffix() {
    let f = Firebase::new("http://db.rifebass.com").ok().unwrap();
    let f = f.at("0.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("1.json").ok().unwrap().at("8.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("8.json").ok().unwrap()
             .at("8.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("1.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("7.json").ok().unwrap().at("2.json").ok().unwrap()
             .at("5.json").ok().unwrap().at("3.json").ok().unwrap();
    let url_now = "http://db.rifebass.com//0/1/1/8/9/9/9/8/8/1/9/9/9/1/1/9/7/2/5/3.json";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn test_ops() {
    let f = Firebase::new("http://db.fe/").ok().expect("url err");
    let f = f.at("lol").ok().expect("extend err");
    let req = f.end_at(13).limit_to_first(4).equal_to(8).shallow(false);
    let a = "http://db.fe//lol.json?limitToFirst=4&endAt=13&equalTo=8&shallow=false";
    assert_eq!(a, req.get_url());
}

#[test]
fn test_auth_ops() {
    let f = Firebase::authed("db.fe/", "key").ok().unwrap().at("lol").ok().unwrap();
    let req = f.order_by("pts").limit_to_last(5).start_at(8);
    let a = "db.fe/lol.json?auth=key&orderBy=pts&limitToLast=5&startAt=8";
    assert_eq!(a, req.get_url());
}
<commit_msg>All tests pass but one, need to test new way of specifying query params<commit_after>extern crate firebase;
extern crate url;

use firebase::Firebase;
use url::Url;

#[test]
fn builds_auth_url() {
    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    assert_eq!(f.get_url(), "http://db.rifebass.com/?auth=deadbeaf");
}

#[test]
fn extends_auth_url() {
    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama/SpacePilot3000").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn double_extends_url() {
    let f = Firebase::authed("http://db.rifebass.com", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama.json").ok().unwrap();
    let f = f.at("SpacePilot3000").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn handle_slashes() {
    let f = Firebase::authed("http://db.rifebass.com", "deadbeaf").ok().unwrap();
    let f = f.at("futurama.json").ok().unwrap();
    let f = f.at("SpacePilot3000.json").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());

    let f = Firebase::authed("http://db.rifebass.com/", "deadbeaf").ok().unwrap();
    let f = f.at("/futurama/").ok().unwrap();
    let f = f.at("/SpacePilot3000/").ok().unwrap();
    let url_now = "http://db.rifebass.com//futurama/SpacePilot3000.json?auth=deadbeaf";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn handle_json_suffix() {
    let f = Firebase::new("http://db.rifebass.com").ok().unwrap();
    let f = f.at("0.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("1.json").ok().unwrap().at("8.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("8.json").ok().unwrap()
             .at("8.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("9.json").ok().unwrap().at("1.json").ok().unwrap()
             .at("1.json").ok().unwrap().at("9.json").ok().unwrap()
             .at("7.json").ok().unwrap().at("2.json").ok().unwrap()
             .at("5.json").ok().unwrap().at("3.json").ok().unwrap();
    let url_now = "http://db.rifebass.com//0/1/1/8/9/9/9/8/8/1/9/9/9/1/1/9/7/2/5/3.json";
    assert_eq!(url_now, f.get_url());
}

#[test]
fn test_ops() {
    let f = Firebase::new("http://db.fe/").ok().expect("url err");
    let f = f.at("lol").ok().expect("extend err");
    let req = f.end_at(13).limit_to_first(4).equal_to(8).shallow(false);
    let correct = Url::parse("http://db.fe//lol.json?limitToFirst=4&endAt=13&equalTo=8&shallow=false").ok().unwrap();
    let generated = Url::parse(&req.get_url()).ok().unwrap();

    let corr_pairs = correct.query_pairs().unwrap();
    let gen_pairs  = generated.query_pairs().unwrap();

    assert_eq!(corr_pairs.len(), gen_pairs.len());

    for pair in corr_pairs.iter() {
        assert!(gen_pairs.contains(pair));
    }
}

#[test]
fn test_auth_ops() {
    let f = Firebase::authed("db.fe/", "key").ok().unwrap().at("lol").ok().unwrap();
    let req = f.order_by("pts").limit_to_last(5).start_at(8);
    let a = "db.fe/lol.json?auth=key&orderBy=pts&limitToLast=5&startAt=8";
    assert_eq!(a, req.get_url());
}
<|endoftext|>


<commit_before>/// extern test-lib for zwreec
/// to test the whole zwreec library
/// for the future: real twee and z-code test-data

extern crate zwreec;

#[test]
fn file_test() {
    assert_eq!("hello from file", zwreec::utils::file::temp_hello());
}

#[test]
fn frontend_test() {
    assert_eq!("hello from frontend", zwreec::frontend::temp_hello());
}

#[test]
fn backend_test() {
    assert_eq!("hello from backend", zwreec::backend::temp_hello());
}
<commit_msg>Remove old assert statement from frontend test<commit_after>/// extern test-lib for zwreec
/// to test the whole zwreec library
/// for the future: real twee and z-code test-data

extern crate zwreec;

#[test]
fn file_test() {
    assert_eq!("hello from file", zwreec::utils::file::temp_hello());
}

#[test]
fn frontend_test() {
}

#[test]
fn backend_test() {
    assert_eq!("hello from backend", zwreec::backend::temp_hello());
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate simple_bitfield;

simple_bitfield! {
    #[derive(Copy, Clone)]
    /// documentation comments also work!
    struct FooBar(u32); // newtype name, underlying type
    // getter name, setter name: msb (included), lsb
    foo1, set_foo1: 0, 0;
    u8;
    foo2, set_foo2: 31, 31;
    foo3, set_foo3: 3, 0;
    u16, foo4, set_foo4: 31, 28;
    // getter name, setter name: msb of first element (included), lsb of first element; count
    foo5, set_foo5: 0, 0, 32;
    u32;
    foo6, set_foo6: 5, 3, 3;
    getter_only, _: 3, 1;
    _, setter_only: 4, 2;
    getter_only_array, _: 5, 3, 3;
    _, setter_only_array: 6, 4, 3;
    all_bits, set_all_bits: 31, 0;
    single_bit, set_single_bit: 3;
}

#[test]
fn test_single_bit() {
    let mut fb = FooBar(0);

    fb.set_foo1(1);
    assert_eq!(0x1, fb.0);
    assert_eq!(0x1, fb.foo1());
    assert_eq!(0x0, fb.foo2());
    assert_eq!(false, fb.single_bit());

    fb.set_foo2(1);
    assert_eq!(0x80000001, fb.0);
    assert_eq!(0x1, fb.foo1());
    assert_eq!(0x1, fb.foo2());
    assert_eq!(false, fb.single_bit());

    fb.set_foo1(0);
    assert_eq!(0x80000000, fb.0);
    assert_eq!(0x0, fb.foo1());
    assert_eq!(0x1, fb.foo2());
    assert_eq!(false, fb.single_bit());

    fb.set_single_bit(true);
    assert_eq!(0x80000008, fb.0);
    assert_eq!(0x0, fb.foo1());
    assert_eq!(0x1, fb.foo2());
    assert_eq!(true, fb.single_bit());
}

#[test]
fn test_single_bit_plus_garbage() {
    let mut fb = FooBar(0);

    fb.set_foo1(0b10);
    assert_eq!(0x0, fb.0);
    assert_eq!(0x0, fb.foo1());
    assert_eq!(0x0, fb.foo2());

    fb.set_foo1(0b11);
    assert_eq!(0x1, fb.0);
    assert_eq!(0x1, fb.foo1());
    assert_eq!(0x0, fb.foo2());

}

#[test]
fn test_multiple_bit() {
    let mut fb = FooBar(0);

    fb.set_foo3(0x0F);
    assert_eq!(0xF, fb.0);
    assert_eq!(0xF, fb.foo3());
    assert_eq!(0x0, fb.foo4());

    fb.set_foo4(0x0F);
    assert_eq!(0xF000000F, fb.0);
    assert_eq!(0xF, fb.foo3());
    assert_eq!(0xF, fb.foo4());

    fb.set_foo3(0);
    assert_eq!(0xF0000000, fb.0);
    assert_eq!(0x0, fb.foo3());
    assert_eq!(0xF, fb.foo4());

    fb.set_foo3(0xA);
    assert_eq!(0xF000000A, fb.0);
    assert_eq!(0xA, fb.foo3());
    assert_eq!(0xF, fb.foo4());
}

#[test]
fn test_getter_setter_only() {
    let mut fb = FooBar(0);
    fb.setter_only(0x7);
    assert_eq!(0x1C, fb.0);
    assert_eq!(0x6, fb.getter_only());
}

#[test]
fn test_array_field1() {
    let mut fb = FooBar(0);

    fb.set_foo5(0, 1);
    assert_eq!(0x1, fb.0);
    assert_eq!(1, fb.foo5(0));

    fb.set_foo5(0, 0);
    assert_eq!(0x0, fb.0);
    assert_eq!(0, fb.foo5(0));

    fb.set_foo5(0, 1);
    fb.set_foo5(6, 1);
    fb.set_foo5(31, 1);
    assert_eq!(0x80000041, fb.0);
    assert_eq!(1, fb.foo5(0));
    assert_eq!(1, fb.foo5(6));
    assert_eq!(1, fb.foo5(31));
    assert_eq!(0, fb.foo5(1));
    assert_eq!(0, fb.foo5(5));
    assert_eq!(0, fb.foo5(7));
    assert_eq!(0, fb.foo5(30));
}

#[test]
fn test_array_field2() {
    let mut fb = FooBar(0);

    fb.set_foo6(0, 1);
    assert_eq!(0x8, fb.0);
    assert_eq!(1, fb.foo6(0));
    assert_eq!(0, fb.foo6(1));
    assert_eq!(0, fb.foo6(2));

    fb.set_foo6(0, 7);
    assert_eq!(0x38, fb.0);
    assert_eq!(7, fb.foo6(0));
    assert_eq!(0, fb.foo6(1));
    assert_eq!(0, fb.foo6(2));

    fb.set_foo6(2, 7);
    assert_eq!(0xE38, fb.0);
    assert_eq!(7, fb.foo6(0));
    assert_eq!(0, fb.foo6(1));
    assert_eq!(7, fb.foo6(2));

    fb.set_foo6(0, 0);
    assert_eq!(0xE00, fb.0);
    assert_eq!(0, fb.foo6(0));
    assert_eq!(0, fb.foo6(1));
    assert_eq!(7, fb.foo6(2));
}

#[test]
fn test_field_type() {
    let fb = FooBar(0);
    let _: u32 = fb.foo1();
    let _: u8 = fb.foo2();
    let _: u8 = fb.foo3();
    let _: u16 = fb.foo4();
    let _: u8 = fb.foo5(0);
    let _: u32 = fb.foo6(0);
}

#[test]
fn test_all_bits() {
    let mut fb = FooBar(0);

    assert_eq!(0, fb.all_bits());

    fb.set_all_bits(!0u32);
    assert_eq!(!0u32, fb.0);
    assert_eq!(!0u32, fb.all_bits());

    fb.0 = 0x80000001;
    assert_eq!(0x80000001, fb.all_bits());
}

#[test]
fn test_is_copy() {
    let a = FooBar(0);
    let _b = a;
    let _c = a;
}

simple_bitfield! {
    struct ArrayBitfield([u8]);
    foo1, set_foo1: 0, 0;
    foo2, set_foo2: 7, 0;
    foo3, set_foo3: 8, 1;
    foo4, set_foo4: 19, 4;
}

#[test]
fn test_arraybitfield() {
    let mut ab = ArrayBitfield([0; 3]);

    assert_eq!(0, ab.foo1());
    assert_eq!(0, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(1);
    assert_eq!([1, 0, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(1, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(0);
    ab.set_foo2(0xFF);
    assert_eq!([0xFF, 0, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(0xFF, ab.foo2());
    assert_eq!(0x7F, ab.foo3());
    assert_eq!(0x0F, ab.foo4());

    ab.set_foo2(0);
    ab.set_foo3(0xFF);
    assert_eq!([0xFE, 0x1, 0], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0xFE, ab.foo2());
    assert_eq!(0xFF, ab.foo3());
    assert_eq!(0x1F, ab.foo4());

    ab.set_foo3(0);
    ab.set_foo4(0xFFFF);
    assert_eq!([0xF0, 0xFF, 0x0F], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0xF0, ab.foo2());
    assert_eq!(0xF8, ab.foo3());
    assert_eq!(0xFFFF, ab.foo4());
}

simple_bitfield! {
    struct ArrayBitfield2([u16]);
    foo1, set_foo1: 0, 0;
    foo2, set_foo2: 7, 0;
    foo3, set_foo3: 8, 1;
    foo4, set_foo4: 20, 4;
}

#[test]
fn test_arraybitfield2() {
    let mut ab = ArrayBitfield2([0; 2]);

    assert_eq!(0, ab.foo1());
    assert_eq!(0, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(1);
    assert_eq!([1, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(1, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(0);
    ab.set_foo2(0xFF);
    assert_eq!([0xFF, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(0xFF, ab.foo2());
    assert_eq!(0x7F, ab.foo3());
    assert_eq!(0x0F, ab.foo4());

    ab.set_foo2(0);
    ab.set_foo3(0xFF);
    assert_eq!([0x1FE, 0x0], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0xFE, ab.foo2());
    assert_eq!(0xFF, ab.foo3());
    assert_eq!(0x1F, ab.foo4());

    ab.set_foo3(0);
    ab.set_foo4(0xFFFF);
    assert_eq!([0xFFF0, 0xF], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0xF0, ab.foo2());
    assert_eq!(0xF8, ab.foo3());
    assert_eq!(0xFFFF, ab.foo4());
}

simple_bitfield! {
    struct ArrayBitfieldMsb0(MSB0 [u8]);
    foo1, set_foo1: 0, 0;
    foo2, set_foo2: 7, 0;
    foo3, set_foo3: 8, 1;
    foo4, set_foo4: 19, 4;
}

#[test]
fn test_arraybitfield_msb0() {
    let mut ab = ArrayBitfieldMsb0([0; 3]);

    assert_eq!(0, ab.foo1());
    assert_eq!(0, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(1);
    assert_eq!([0b1000_0000, 0, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(0b1000_0000, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(0);
    ab.set_foo2(0xFF);
    assert_eq!([0b1111_1111, 0, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(0b1111_1111, ab.foo2());
    assert_eq!(0b1111_1110, ab.foo3());
    assert_eq!(0b1111_0000_0000_0000, ab.foo4());

    ab.set_foo2(0);
    ab.set_foo3(0xFF);
    assert_eq!([0b01111111, 0b10000000, 0], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0b01111111, ab.foo2());
    assert_eq!(0xFF, ab.foo3());
    assert_eq!(0b1111_1000_0000_0000, ab.foo4());

    ab.set_foo3(0);
    ab.set_foo4(0xFFFF);
    assert_eq!([0x0F, 0xFF, 0xF0], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0x0F, ab.foo2());
    assert_eq!(0b0001_1111, ab.foo3());
    assert_eq!(0xFFFF, ab.foo4());
}
<commit_msg>Remove outdated comments in tests<commit_after>#[macro_use]
extern crate simple_bitfield;

simple_bitfield! {
    #[derive(Copy, Clone)]
    /// documentation comments also work!
    struct FooBar(u32);
    foo1, set_foo1: 0, 0;
    u8;
    foo2, set_foo2: 31, 31;
    foo3, set_foo3: 3, 0;
    u16, foo4, set_foo4: 31, 28;
    foo5, set_foo5: 0, 0, 32;
    u32;
    foo6, set_foo6: 5, 3, 3;
    getter_only, _: 3, 1;
    _, setter_only: 4, 2;
    getter_only_array, _: 5, 3, 3;
    _, setter_only_array: 6, 4, 3;
    all_bits, set_all_bits: 31, 0;
    single_bit, set_single_bit: 3;
}

#[test]
fn test_single_bit() {
    let mut fb = FooBar(0);

    fb.set_foo1(1);
    assert_eq!(0x1, fb.0);
    assert_eq!(0x1, fb.foo1());
    assert_eq!(0x0, fb.foo2());
    assert_eq!(false, fb.single_bit());

    fb.set_foo2(1);
    assert_eq!(0x80000001, fb.0);
    assert_eq!(0x1, fb.foo1());
    assert_eq!(0x1, fb.foo2());
    assert_eq!(false, fb.single_bit());

    fb.set_foo1(0);
    assert_eq!(0x80000000, fb.0);
    assert_eq!(0x0, fb.foo1());
    assert_eq!(0x1, fb.foo2());
    assert_eq!(false, fb.single_bit());

    fb.set_single_bit(true);
    assert_eq!(0x80000008, fb.0);
    assert_eq!(0x0, fb.foo1());
    assert_eq!(0x1, fb.foo2());
    assert_eq!(true, fb.single_bit());
}

#[test]
fn test_single_bit_plus_garbage() {
    let mut fb = FooBar(0);

    fb.set_foo1(0b10);
    assert_eq!(0x0, fb.0);
    assert_eq!(0x0, fb.foo1());
    assert_eq!(0x0, fb.foo2());

    fb.set_foo1(0b11);
    assert_eq!(0x1, fb.0);
    assert_eq!(0x1, fb.foo1());
    assert_eq!(0x0, fb.foo2());

}

#[test]
fn test_multiple_bit() {
    let mut fb = FooBar(0);

    fb.set_foo3(0x0F);
    assert_eq!(0xF, fb.0);
    assert_eq!(0xF, fb.foo3());
    assert_eq!(0x0, fb.foo4());

    fb.set_foo4(0x0F);
    assert_eq!(0xF000000F, fb.0);
    assert_eq!(0xF, fb.foo3());
    assert_eq!(0xF, fb.foo4());

    fb.set_foo3(0);
    assert_eq!(0xF0000000, fb.0);
    assert_eq!(0x0, fb.foo3());
    assert_eq!(0xF, fb.foo4());

    fb.set_foo3(0xA);
    assert_eq!(0xF000000A, fb.0);
    assert_eq!(0xA, fb.foo3());
    assert_eq!(0xF, fb.foo4());
}

#[test]
fn test_getter_setter_only() {
    let mut fb = FooBar(0);
    fb.setter_only(0x7);
    assert_eq!(0x1C, fb.0);
    assert_eq!(0x6, fb.getter_only());
}

#[test]
fn test_array_field1() {
    let mut fb = FooBar(0);

    fb.set_foo5(0, 1);
    assert_eq!(0x1, fb.0);
    assert_eq!(1, fb.foo5(0));

    fb.set_foo5(0, 0);
    assert_eq!(0x0, fb.0);
    assert_eq!(0, fb.foo5(0));

    fb.set_foo5(0, 1);
    fb.set_foo5(6, 1);
    fb.set_foo5(31, 1);
    assert_eq!(0x80000041, fb.0);
    assert_eq!(1, fb.foo5(0));
    assert_eq!(1, fb.foo5(6));
    assert_eq!(1, fb.foo5(31));
    assert_eq!(0, fb.foo5(1));
    assert_eq!(0, fb.foo5(5));
    assert_eq!(0, fb.foo5(7));
    assert_eq!(0, fb.foo5(30));
}

#[test]
fn test_array_field2() {
    let mut fb = FooBar(0);

    fb.set_foo6(0, 1);
    assert_eq!(0x8, fb.0);
    assert_eq!(1, fb.foo6(0));
    assert_eq!(0, fb.foo6(1));
    assert_eq!(0, fb.foo6(2));

    fb.set_foo6(0, 7);
    assert_eq!(0x38, fb.0);
    assert_eq!(7, fb.foo6(0));
    assert_eq!(0, fb.foo6(1));
    assert_eq!(0, fb.foo6(2));

    fb.set_foo6(2, 7);
    assert_eq!(0xE38, fb.0);
    assert_eq!(7, fb.foo6(0));
    assert_eq!(0, fb.foo6(1));
    assert_eq!(7, fb.foo6(2));

    fb.set_foo6(0, 0);
    assert_eq!(0xE00, fb.0);
    assert_eq!(0, fb.foo6(0));
    assert_eq!(0, fb.foo6(1));
    assert_eq!(7, fb.foo6(2));
}

#[test]
fn test_field_type() {
    let fb = FooBar(0);
    let _: u32 = fb.foo1();
    let _: u8 = fb.foo2();
    let _: u8 = fb.foo3();
    let _: u16 = fb.foo4();
    let _: u8 = fb.foo5(0);
    let _: u32 = fb.foo6(0);
}

#[test]
fn test_all_bits() {
    let mut fb = FooBar(0);

    assert_eq!(0, fb.all_bits());

    fb.set_all_bits(!0u32);
    assert_eq!(!0u32, fb.0);
    assert_eq!(!0u32, fb.all_bits());

    fb.0 = 0x80000001;
    assert_eq!(0x80000001, fb.all_bits());
}

#[test]
fn test_is_copy() {
    let a = FooBar(0);
    let _b = a;
    let _c = a;
}

simple_bitfield! {
    struct ArrayBitfield([u8]);
    foo1, set_foo1: 0, 0;
    foo2, set_foo2: 7, 0;
    foo3, set_foo3: 8, 1;
    foo4, set_foo4: 19, 4;
}

#[test]
fn test_arraybitfield() {
    let mut ab = ArrayBitfield([0; 3]);

    assert_eq!(0, ab.foo1());
    assert_eq!(0, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(1);
    assert_eq!([1, 0, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(1, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(0);
    ab.set_foo2(0xFF);
    assert_eq!([0xFF, 0, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(0xFF, ab.foo2());
    assert_eq!(0x7F, ab.foo3());
    assert_eq!(0x0F, ab.foo4());

    ab.set_foo2(0);
    ab.set_foo3(0xFF);
    assert_eq!([0xFE, 0x1, 0], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0xFE, ab.foo2());
    assert_eq!(0xFF, ab.foo3());
    assert_eq!(0x1F, ab.foo4());

    ab.set_foo3(0);
    ab.set_foo4(0xFFFF);
    assert_eq!([0xF0, 0xFF, 0x0F], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0xF0, ab.foo2());
    assert_eq!(0xF8, ab.foo3());
    assert_eq!(0xFFFF, ab.foo4());
}

simple_bitfield! {
    struct ArrayBitfield2([u16]);
    foo1, set_foo1: 0, 0;
    foo2, set_foo2: 7, 0;
    foo3, set_foo3: 8, 1;
    foo4, set_foo4: 20, 4;
}

#[test]
fn test_arraybitfield2() {
    let mut ab = ArrayBitfield2([0; 2]);

    assert_eq!(0, ab.foo1());
    assert_eq!(0, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(1);
    assert_eq!([1, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(1, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(0);
    ab.set_foo2(0xFF);
    assert_eq!([0xFF, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(0xFF, ab.foo2());
    assert_eq!(0x7F, ab.foo3());
    assert_eq!(0x0F, ab.foo4());

    ab.set_foo2(0);
    ab.set_foo3(0xFF);
    assert_eq!([0x1FE, 0x0], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0xFE, ab.foo2());
    assert_eq!(0xFF, ab.foo3());
    assert_eq!(0x1F, ab.foo4());

    ab.set_foo3(0);
    ab.set_foo4(0xFFFF);
    assert_eq!([0xFFF0, 0xF], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0xF0, ab.foo2());
    assert_eq!(0xF8, ab.foo3());
    assert_eq!(0xFFFF, ab.foo4());
}

simple_bitfield! {
    struct ArrayBitfieldMsb0(MSB0 [u8]);
    foo1, set_foo1: 0, 0;
    foo2, set_foo2: 7, 0;
    foo3, set_foo3: 8, 1;
    foo4, set_foo4: 19, 4;
}

#[test]
fn test_arraybitfield_msb0() {
    let mut ab = ArrayBitfieldMsb0([0; 3]);

    assert_eq!(0, ab.foo1());
    assert_eq!(0, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(1);
    assert_eq!([0b1000_0000, 0, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(0b1000_0000, ab.foo2());
    assert_eq!(0, ab.foo3());
    assert_eq!(0, ab.foo4());

    ab.set_foo1(0);
    ab.set_foo2(0xFF);
    assert_eq!([0b1111_1111, 0, 0], ab.0);
    assert_eq!(1, ab.foo1());
    assert_eq!(0b1111_1111, ab.foo2());
    assert_eq!(0b1111_1110, ab.foo3());
    assert_eq!(0b1111_0000_0000_0000, ab.foo4());

    ab.set_foo2(0);
    ab.set_foo3(0xFF);
    assert_eq!([0b01111111, 0b10000000, 0], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0b01111111, ab.foo2());
    assert_eq!(0xFF, ab.foo3());
    assert_eq!(0b1111_1000_0000_0000, ab.foo4());

    ab.set_foo3(0);
    ab.set_foo4(0xFFFF);
    assert_eq!([0x0F, 0xFF, 0xF0], ab.0);
    assert_eq!(0, ab.foo1());
    assert_eq!(0x0F, ab.foo2());
    assert_eq!(0b0001_1111, ab.foo3());
    assert_eq!(0xFFFF, ab.foo4());
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

use std::fmt;
use std::mem;
use std::slice;
use num;
use approx;
use angle::{Deg, Angle, FromAngle, IntoAngle, Turns, Rad};
use angle;
use channel::{PosFreeChannel, FreeChannelScalar, AngularChannel, AngularChannelScalar,
              ChannelFormatCast, ChannelCast, ColorChannel};
use color::{Color, PolarColor, FromTuple, Lerp, Bounded, Flatten};
use convert::{GetChroma, GetHue, FromColor};
use lab::Lab;

pub struct LchabTag;

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Lchab<T, A = Deg<T>> {
    pub L: PosFreeChannel<T>,
    pub chroma: PosFreeChannel<T>,
    pub hue: AngularChannel<A>,
}

impl<T, A> Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    pub fn from_channels(L: T, chroma: T, hue: A) -> Self {
        Lchab {
            L: PosFreeChannel::new(L),
            chroma: PosFreeChannel::new(chroma),
            hue: AngularChannel::new(hue),
        }
    }

    impl_color_color_cast_angular!(Lchab {L, chroma, hue},
        chan_traits={FreeChannelScalar});

    pub fn L(&self) -> T {
        self.L.0.clone()
    }
    pub fn chroma(&self) -> T {
        self.chroma.0.clone()
    }
    pub fn hue(&self) -> A {
        self.hue.0.clone()
    }
    pub fn L_mut(&mut self) -> &mut T {
        &mut self.L.0
    }
    pub fn chroma_mut(&mut self) -> &mut T {
        &mut self.chroma.0
    }
    pub fn hue_mut(&mut self) -> &mut A {
        &mut self.hue.0
    }
    pub fn set_L(&mut self, val: T) {
        self.L.0 = val;
    }
    pub fn set_chroma(&mut self, val: T) {
        self.chroma.0 = val;
    }
    pub fn set_hue(&mut self, val: A) {
        self.hue.0 = val;
    }
}

impl<T, A> Color for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    type Tag = LchabTag;
    type ChannelsTuple = (T, T, A);

    fn num_channels() -> u32 {
        3
    }
    fn to_tuple(self) -> Self::ChannelsTuple {
        (self.L.0, self.chroma.0, self.hue.0)
    }
}

impl<T, A> PolarColor for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    type Angular = A;
    type Cartesian = T;
}

impl<T, A> FromTuple for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    fn from_tuple(values: Self::ChannelsTuple) -> Self {
        Lchab::from_channels(values.0, values.1, values.2)
    }
}

impl<T, A> Lerp for Lchab<T, A>
    where T: FreeChannelScalar + Lerp,
          A: AngularChannelScalar + Lerp
{
    type Position = A::Position;

    impl_color_lerp_angular!(Lchab<T> {hue, L, chroma});
}

impl<T, A> Bounded for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    impl_color_bounded!(Lchab {L, chroma, hue});
}

impl<T, A> Flatten for Lchab<T, A>
    where T: FreeChannelScalar + num::Float,
          A: AngularChannelScalar + Angle<Scalar = T> + FromAngle<Turns<T>>
{
    type ScalarFormat = T;

    impl_color_as_slice!(T);
    impl_color_from_slice_angular!(Lchab<T, A> {hue:AngularChannel - 0,
        chroma:PosFreeChannel - 1, L:PosFreeChannel - 2});
}

impl<T, A> approx::ApproxEq for Lchab<T, A>
    where T: FreeChannelScalar + approx::ApproxEq<Epsilon = A::Epsilon>,
          A: AngularChannelScalar + approx::ApproxEq,
          A::Epsilon: Clone + num::Float
{
    impl_approx_eq!({L, chroma, hue});
}

impl<T, A> Default for Lchab<T, A>
    where T: FreeChannelScalar + num::Zero,
          A: AngularChannelScalar + num::Zero
{
    impl_color_default!(Lchab {hue: AngularChannel,
        L: PosFreeChannel, chroma: PosFreeChannel});
}

impl<T, A> fmt::Display for Lchab<T, A>
    where T: FreeChannelScalar + fmt::Display,
          A: AngularChannelScalar + fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Lch(ab)({}, {}, {})", self.L, self.chroma, self.hue)
    }
}

impl<T, A> GetChroma for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    type ChromaType = T;
    fn get_chroma(&self) -> T {
        return self.chroma();
    }
}

impl<T, A> GetHue for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    impl_color_get_hue_angular!(Lchab);
}

impl<T, A> FromColor<Lab<T>> for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar + FromAngle<Rad<T>> + Angle
{
    fn from_color(from: &Lab<T>) -> Self {
        let L = from.L();
        let chroma = (from.a() * from.a() + from.b() * from.b()).sqrt();
        let hue = A::from_angle(Rad::atan2(from.b(), from.a()));

        Lchab::from_channels(L, chroma, <A as Angle>::normalize(hue))
    }
}

impl<T, A> FromColor<Lchab<T, A>> for Lab<T>
    where T: FreeChannelScalar,
          A: AngularChannelScalar + Angle<Scalar = T>
{
    fn from_color(from: &Lchab<T, A>) -> Self {
        let L = from.L();
        let a = from.chroma() * from.hue().cos();
        let b = from.chroma() * from.hue().sin();

        Lab::from_channels(L, a, b)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use lab::Lab;
    use angle::*;
    use convert::FromColor;

    #[test]
    fn test_from_lab() {
        let c1 = Lab::from_channels(50.0, 30.0, 30.0);
        let t1 = Lchab::from_color(&c1);
        assert_relative_eq!(t1, Lchab::from_channels(50.0, 42.4264, Deg(45.0000)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t1), c1, epsilon=1e-4);

        let c2 = Lab::from_channels(0.0, 0.0, 0.0);
        let t2 = Lchab::from_color(&c2);
        assert_relative_eq!(t2, Lchab::from_channels(0.0, 0.0, Rad(0.0)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t2), c2, epsilon=1e-4);

        let c3 = Lab::from_channels(0.0, 55.0, 95.0);
        let t3 = Lchab::from_color(&c3);
        assert_relative_eq!(t3, Lchab::from_channels(0.0, 109.7725, Deg(59.9314)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t3), c3, epsilon=1e-4);

        let c4 = Lab::from_channels(67.2, -80.0, 80.0);
        let t4 = Lchab::from_color(&c4);
        assert_relative_eq!(t4, Lchab::from_channels(67.2, 113.1371, Deg(135.0)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t4), c4, epsilon=1e-4);

        let c5 = Lab::from_channels(45.0, 100.0, 0.0);
        let t5 = Lchab::from_color(&c5);
        assert_relative_eq!(t5, Lchab::from_channels(45.0, 100.0, Deg(0.0)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t5), c5, epsilon=1e-4);

        let c6 = Lab::from_channels(82.0, 72.5, -67.3);
        let t6 = Lchab::from_color(&c6);
        assert_relative_eq!(t6, Lchab::from_channels(82.0, 98.9219, Deg(317.1302)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t6), c6, epsilon=1e-4);
    }

    #[test]
    fn test_to_lab() {
        let c1 = Lchab::from_channels(75.0, 80.0, Deg(330.0));
        let t1 = Lab::from_color(&c1);
        assert_relative_eq!(t1, Lab::from_channels(75.0, 69.2820, -40.00), epsilon=1e-4);
        assert_relative_eq!(Lchab::from_color(&t1), c1, epsilon=1e-4);

        let c2 = Lchab::from_channels(55.5, 60.0, Deg(0.0));
        let t2 = Lab::from_color(&c2);
        assert_relative_eq!(t2, Lab::from_channels(55.5, 60.0, 0.0), epsilon=1e-4);
        assert_relative_eq!(Lchab::from_color(&t2), c2, epsilon=1e-4);

        let c3 = Lchab::from_channels(88.8, 52.0, Deg(1.5));
        let t3 = Lab::from_color(&c3);
        assert_relative_eq!(t3, Lab::from_channels(88.8, 51.9822, 1.3612), epsilon=1e-4);
        assert_relative_eq!(Lchab::from_color(&t3), c3, epsilon=1e-4);

        let c4 = Lchab::from_channels(62.0, 79.0, Deg(225.0));
        let t4 = Lab::from_color(&c4);
        assert_relative_eq!(t4, Lab::from_channels(62.0, -55.8614, -55.8614), epsilon=1e-4);
        assert_relative_eq!(Lchab::from_color(&t4), c4, epsilon=1e-4);
    }
}
<commit_msg>Added general functionality tests for Lch(ab).<commit_after>#![allow(non_snake_case)]

use std::fmt;
use std::mem;
use std::slice;
use num;
use approx;
use angle::{Deg, Angle, FromAngle, IntoAngle, Turns, Rad};
use angle;
use channel::{PosFreeChannel, FreeChannelScalar, AngularChannel, AngularChannelScalar,
              ChannelFormatCast, ChannelCast, ColorChannel};
use color::{Color, PolarColor, FromTuple, Lerp, Bounded, Flatten};
use convert::{GetChroma, GetHue, FromColor};
use lab::Lab;

pub struct LchabTag;

#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct Lchab<T, A = Deg<T>> {
    pub L: PosFreeChannel<T>,
    pub chroma: PosFreeChannel<T>,
    pub hue: AngularChannel<A>,
}

impl<T, A> Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    pub fn from_channels(L: T, chroma: T, hue: A) -> Self {
        Lchab {
            L: PosFreeChannel::new(L),
            chroma: PosFreeChannel::new(chroma),
            hue: AngularChannel::new(hue),
        }
    }

    impl_color_color_cast_angular!(Lchab {L, chroma, hue},
        chan_traits={FreeChannelScalar});

    pub fn L(&self) -> T {
        self.L.0.clone()
    }
    pub fn chroma(&self) -> T {
        self.chroma.0.clone()
    }
    pub fn hue(&self) -> A {
        self.hue.0.clone()
    }
    pub fn L_mut(&mut self) -> &mut T {
        &mut self.L.0
    }
    pub fn chroma_mut(&mut self) -> &mut T {
        &mut self.chroma.0
    }
    pub fn hue_mut(&mut self) -> &mut A {
        &mut self.hue.0
    }
    pub fn set_L(&mut self, val: T) {
        self.L.0 = val;
    }
    pub fn set_chroma(&mut self, val: T) {
        self.chroma.0 = val;
    }
    pub fn set_hue(&mut self, val: A) {
        self.hue.0 = val;
    }
}

impl<T, A> Color for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    type Tag = LchabTag;
    type ChannelsTuple = (T, T, A);

    fn num_channels() -> u32 {
        3
    }
    fn to_tuple(self) -> Self::ChannelsTuple {
        (self.L.0, self.chroma.0, self.hue.0)
    }
}

impl<T, A> PolarColor for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    type Angular = A;
    type Cartesian = T;
}

impl<T, A> FromTuple for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    fn from_tuple(values: Self::ChannelsTuple) -> Self {
        Lchab::from_channels(values.0, values.1, values.2)
    }
}

impl<T, A> Lerp for Lchab<T, A>
    where T: FreeChannelScalar + Lerp,
          A: AngularChannelScalar + Lerp
{
    type Position = A::Position;

    impl_color_lerp_angular!(Lchab<T> {hue, L, chroma});
}

impl<T, A> Bounded for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    impl_color_bounded!(Lchab {L, chroma, hue});
}

impl<T, A> Flatten for Lchab<T, A>
    where T: FreeChannelScalar + num::Float,
          A: AngularChannelScalar + Angle<Scalar = T> + FromAngle<Turns<T>>
{
    type ScalarFormat = T;

    impl_color_as_slice!(T);

    fn from_slice(vals: &[T]) -> Self {
        Lchab::from_channels(vals[0].clone(),
                             vals[1].clone(),
                             A::from_angle(angle::Turns(vals[2].clone())))
    }
}

impl<T, A> approx::ApproxEq for Lchab<T, A>
    where T: FreeChannelScalar + approx::ApproxEq<Epsilon = A::Epsilon>,
          A: AngularChannelScalar + approx::ApproxEq,
          A::Epsilon: Clone + num::Float
{
    impl_approx_eq!({L, chroma, hue});
}

impl<T, A> Default for Lchab<T, A>
    where T: FreeChannelScalar + num::Zero,
          A: AngularChannelScalar + num::Zero
{
    impl_color_default!(Lchab {hue: AngularChannel,
        L: PosFreeChannel, chroma: PosFreeChannel});
}

impl<T, A> fmt::Display for Lchab<T, A>
    where T: FreeChannelScalar + fmt::Display,
          A: AngularChannelScalar + fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Lch(ab)({}, {}, {})", self.L, self.chroma, self.hue)
    }
}

impl<T, A> GetChroma for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    type ChromaType = T;
    fn get_chroma(&self) -> T {
        return self.chroma();
    }
}

impl<T, A> GetHue for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar
{
    impl_color_get_hue_angular!(Lchab);
}

impl<T, A> FromColor<Lab<T>> for Lchab<T, A>
    where T: FreeChannelScalar,
          A: AngularChannelScalar + FromAngle<Rad<T>> + Angle
{
    fn from_color(from: &Lab<T>) -> Self {
        let L = from.L();
        let chroma = (from.a() * from.a() + from.b() * from.b()).sqrt();
        let hue = A::from_angle(Rad::atan2(from.b(), from.a()));

        Lchab::from_channels(L, chroma, <A as Angle>::normalize(hue))
    }
}

impl<T, A> FromColor<Lchab<T, A>> for Lab<T>
    where T: FreeChannelScalar,
          A: AngularChannelScalar + Angle<Scalar = T>
{
    fn from_color(from: &Lchab<T, A>) -> Self {
        let L = from.L();
        let a = from.chroma() * from.hue().cos();
        let b = from.chroma() * from.hue().sin();

        Lab::from_channels(L, a, b)
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use lab::Lab;
    use angle::*;
    use convert::*;
    use color::*;

    #[test]
    fn test_construct() {
        let c1 = Lchab::from_channels(55.3, 12.9, Deg(90.0));
        assert_relative_eq!(c1.L(), 55.3);
        assert_relative_eq!(c1.chroma(), 12.9);
        assert_relative_eq!(c1.hue(), Deg(90.0));
        assert_eq!(c1.to_tuple(), (55.3, 12.9, Deg(90.0)));
        assert_relative_eq!(Lchab::from_tuple(c1.to_tuple()), c1);

        let c2 = Lchab::from_channels(92.0, 55.0, Turns(0.5));
        assert_relative_eq!(c2.L(), 92.0);
        assert_relative_eq!(c2.chroma(), 55.0);
        assert_relative_eq!(c2.hue(), Turns(0.5));
        assert_eq!(c2.to_tuple(), (92.0, 55.0, Turns(0.5)));
        assert_relative_eq!(Lchab::from_tuple(c2.to_tuple()), c2);
    }

    #[test]
    fn test_lerp() {
        let c1 = Lchab::from_channels(25.0, 90.0, Deg(300.0));
        let c2 = Lchab::from_channels(75.0, 50.0, Deg(50.0));
        assert_relative_eq!(c1.lerp(&c2, 0.0), c1);
        assert_relative_eq!(c1.lerp(&c2, 1.0), c2);
        assert_relative_eq!(c1.lerp(&c2, 0.5), Lchab::from_channels(50.0, 70.0, Deg(355.0)));
        assert_relative_eq!(c1.lerp(&c2, 0.25), Lchab::from_channels(37.5, 80.0, Deg(327.5)));

        let c3 = Lchab::from_channels(0.0, 20.0, Deg(60.0));
        let c4 = Lchab::from_channels(60.0, 80.0, Deg(140.0));
        assert_relative_eq!(c3.lerp(&c4, 0.0), c3);
        assert_relative_eq!(c3.lerp(&c4, 1.0), c4);
        assert_relative_eq!(c3.lerp(&c4, 0.5), Lchab::from_channels(30.0, 50.0, Deg(100.0)));
        assert_relative_eq!(c3.lerp(&c4, 0.75), Lchab::from_channels(45.0, 65.0, Deg(120.0)));
    }

    #[test]
    fn test_normalize() {
        let c1 = Lchab::from_channels(105.0, 32.0, Deg(300.0));
        assert!(c1.is_normalized());
        assert_relative_eq!(c1.normalize(), c1);

        let c2 = Lchab::from_channels(-3.0, 1.0, Deg(220.0));
        assert!(!c2.is_normalized());
        assert_relative_eq!(c2.normalize(), Lchab::from_channels(0.0, 1.0, Deg(220.0)));

        let c3 = Lchab::from_channels(50.0, -50.0, Turns(2.3));
        assert!(!c3.is_normalized());
        assert_relative_eq!(c3.normalize(), Lchab::from_channels(50.0, 0.0, Turns(0.3)));

        let c4 = Lchab::from_channels(110.0, 150.0, Deg(-50.0));
        assert!(!c4.is_normalized());
        assert_relative_eq!(c4.normalize(), Lchab::from_channels(110.0, 150.0, Deg(310.0)));
    }

    #[test]
    fn test_flatten() {
        let c1 = Lchab::from_channels(85.0, 11.11, Turns(0.5));
        assert_eq!(c1.as_slice(), &[85.0, 11.11, 0.5]);
        assert_relative_eq!(Lchab::from_slice(c1.as_slice()), c1);

        let c2 = Lchab::from_channels(55.55, 33.33, Deg(90.00));
        assert_eq!(c2.as_slice(), &[55.55, 33.33, 90.00]);
    }

    #[test]
    fn test_get_chroma() {
        let c1 = Lchab::from_channels(44.44, 55.55, Deg(66.66));
        assert_eq!(c1.get_chroma(), 55.55);
    }

    #[test]
    fn test_get_hue() {
        let c1 = Lchab::from_channels(20.0, 50.0, Deg(180.0));
        assert_eq!(c1.get_hue::<Deg<_>>(), Deg(180.0));
        assert_eq!(c1.get_hue::<Turns<_>>(), Turns(0.5));
    }

    #[test]
    fn test_from_lab() {
        let c1 = Lab::from_channels(50.0, 30.0, 30.0);
        let t1 = Lchab::from_color(&c1);
        assert_relative_eq!(t1, Lchab::from_channels(50.0, 42.4264, Deg(45.0000)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t1), c1, epsilon=1e-4);

        let c2 = Lab::from_channels(0.0, 0.0, 0.0);
        let t2 = Lchab::from_color(&c2);
        assert_relative_eq!(t2, Lchab::from_channels(0.0, 0.0, Rad(0.0)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t2), c2, epsilon=1e-4);

        let c3 = Lab::from_channels(0.0, 55.0, 95.0);
        let t3 = Lchab::from_color(&c3);
        assert_relative_eq!(t3, Lchab::from_channels(0.0, 109.7725, Deg(59.9314)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t3), c3, epsilon=1e-4);

        let c4 = Lab::from_channels(67.2, -80.0, 80.0);
        let t4 = Lchab::from_color(&c4);
        assert_relative_eq!(t4, Lchab::from_channels(67.2, 113.1371, Deg(135.0)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t4), c4, epsilon=1e-4);

        let c5 = Lab::from_channels(45.0, 100.0, 0.0);
        let t5 = Lchab::from_color(&c5);
        assert_relative_eq!(t5, Lchab::from_channels(45.0, 100.0, Deg(0.0)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t5), c5, epsilon=1e-4);

        let c6 = Lab::from_channels(82.0, 72.5, -67.3);
        let t6 = Lchab::from_color(&c6);
        assert_relative_eq!(t6, Lchab::from_channels(82.0, 98.9219, Deg(317.1302)), epsilon=1e-4);
        assert_relative_eq!(Lab::from_color(&t6), c6, epsilon=1e-4);
    }

    #[test]
    fn test_to_lab() {
        let c1 = Lchab::from_channels(75.0, 80.0, Deg(330.0));
        let t1 = Lab::from_color(&c1);
        assert_relative_eq!(t1, Lab::from_channels(75.0, 69.2820, -40.00), epsilon=1e-4);
        assert_relative_eq!(Lchab::from_color(&t1), c1, epsilon=1e-4);

        let c2 = Lchab::from_channels(55.5, 60.0, Deg(0.0));
        let t2 = Lab::from_color(&c2);
        assert_relative_eq!(t2, Lab::from_channels(55.5, 60.0, 0.0), epsilon=1e-4);
        assert_relative_eq!(Lchab::from_color(&t2), c2, epsilon=1e-4);

        let c3 = Lchab::from_channels(88.8, 52.0, Deg(1.5));
        let t3 = Lab::from_color(&c3);
        assert_relative_eq!(t3, Lab::from_channels(88.8, 51.9822, 1.3612), epsilon=1e-4);
        assert_relative_eq!(Lchab::from_color(&t3), c3, epsilon=1e-4);

        let c4 = Lchab::from_channels(62.0, 79.0, Deg(225.0));
        let t4 = Lab::from_color(&c4);
        assert_relative_eq!(t4, Lab::from_channels(62.0, -55.8614, -55.8614), epsilon=1e-4);
        assert_relative_eq!(Lchab::from_color(&t4), c4, epsilon=1e-4);
    }

    #[test]
    fn test_color_cast() {
        let c1 = Lchab::from_channels(0.5f32, 42.0f32, Deg(120.0f32));
        assert_relative_eq!(c1.color_cast(), c1);
        assert_relative_eq!(c1.color_cast::<f32,Rad<f32>>().color_cast(), c1);
        assert_relative_eq!(c1.color_cast(), Lchab::from_channels(0.5, 42.0, Deg(120.0)));
        assert_relative_eq!(c1.color_cast(), Lchab::from_channels(0.5, 42.0, Turns(1.0 / 3.0)));
    }
}
<|endoftext|>


<commit_before>#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        let result = 2 + 2;
        assert_eq!(result, 4);
    }
}
<commit_msg>Sketch of Rust shaper.<commit_after>use std::collections::HashMap;

struct Participant{
    id: String,
    // TODO https://stackoverflow.com/a/39147207/90123
    properties: HashMap<String, String>,
    cookie: u64
}

struct Government {
    majority: Vec<String>,
    minority: Vec<String>,
    arrive: Participant,
    acclimate: Option<String>,
}

struct Shape {
    quorum: Vec<String>,
    government: Government,
}

struct Arrival {
    id: String,
    cookie: u64,
}

struct Shaper {
    parliament_size: u32,
    leader: bool,
    arrivals: Vec<String>,
    arriving: Vec<Arrival>,
    decided: bool,
}

impl Shaper {
    pub fn new (parliament_size: u32) -> Shaper {
        Shaper {
            parliament_size: parliament_size,
            leader: false,
            decided: false,
            arrivals: vec![],
            arriving: vec![],
        }
    }
    fn arrival (&mut self) -> Option<Shape> {
        if self.arriving.len() > 0 {
            let arrival = &self.arriving[0];
            return Some(Shape {
                quorum: vec![],
                government: Government {
                    majority: vec![],
                    minority: vec![],
                    arrive: Participant {
                        id: arrival.id.to_string(),
                        properties: HashMap::new(),
                        cookie: 0,
                    },
                    acclimate: None
                }
            })
        }
        return None;
    }
    pub fn emabark (&mut self, arrival: Arrival) {
        for existing in &self.arriving {
            if existing.id == arrival.id {
                return
            }
        }
        self.arriving.push(arrival);
    }
    pub fn arrived (&mut self, id: &String) {
        self.arrivals.push(id.to_string());
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        use crate::Shaper;
        let mut shaper = Shaper::new(3);
        assert!(! shaper.leader);
    }
}
<|endoftext|>


<commit_before><commit_msg>style: Remove unused DeclarationBlock::get_at_importance.<commit_after><|endoftext|>


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

//! Demote a package from a specified channel.
//!
//! # Examples
//!
//! ```bash
//! $ hab pkg demote acme/redis/2.0.7/2112010203120101 stable
//! ```
//! This will demote the acme package specified from the stable channel, removing it.
//!
//! Notes:
//!    The package should already have been uploaded to Builder.
//!    If the specified channel does not exist, this will fail.
//!

use crate::api_client::Client;
use crate::common::ui::{Status, UIWriter, UI};
use crate::hcore::{package::PackageIdent, ChannelIdent};

use crate::error::{Error, Result};
use crate::{PRODUCT, VERSION};

/// Demote a package from the specified channel.
///
/// # Failures
///
/// * Fails if it cannot find the specified package in Builder.
/// * Fails if the channel specified does not exist.
/// * Fails if "unstable" is the channel specified.
pub fn start(
    ui: &mut UI,
    bldr_url: &str,
    ident: &PackageIdent,
    channel: &ChannelIdent,
    token: &str,
) -> Result<()> {
    let api_client = Client::new(bldr_url, PRODUCT, VERSION, None)?;

    ui.begin(format!("Demoting {} from {}", ident, channel))?;

    if channel == &ChannelIdent::unstable() {
        return Err(Error::CannotRemoveFromChannel((
            format!("{}", ident),
            channel.to_string(),
        )));
    }

    match api_client.demote_package(ident, channel, token) {
        Ok(_) => (),
        Err(e) => {
            println!("Failed to demote '{}': {:?}", ident, e);
            return Err(Error::from(e));
        }
    }

    ui.status(Status::Demoted, ident)?;

    Ok(())
}
<commit_msg>Use to_string instead of a trivial format!<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Demote a package from a specified channel.
//!
//! # Examples
//!
//! ```bash
//! $ hab pkg demote acme/redis/2.0.7/2112010203120101 stable
//! ```
//! This will demote the acme package specified from the stable channel, removing it.
//!
//! Notes:
//!    The package should already have been uploaded to Builder.
//!    If the specified channel does not exist, this will fail.
//!

use crate::api_client::Client;
use crate::common::ui::{Status, UIWriter, UI};
use crate::hcore::{package::PackageIdent, ChannelIdent};

use crate::error::{Error, Result};
use crate::{PRODUCT, VERSION};

/// Demote a package from the specified channel.
///
/// # Failures
///
/// * Fails if it cannot find the specified package in Builder.
/// * Fails if the channel specified does not exist.
/// * Fails if "unstable" is the channel specified.
pub fn start(
    ui: &mut UI,
    bldr_url: &str,
    ident: &PackageIdent,
    channel: &ChannelIdent,
    token: &str,
) -> Result<()> {
    let api_client = Client::new(bldr_url, PRODUCT, VERSION, None)?;

    ui.begin(format!("Demoting {} from {}", ident, channel))?;

    if channel == &ChannelIdent::unstable() {
        return Err(Error::CannotRemoveFromChannel((
            ident.to_string(),
            channel.to_string(),
        )));
    }

    match api_client.demote_package(ident, channel, token) {
        Ok(_) => (),
        Err(e) => {
            println!("Failed to demote '{}': {:?}", ident, e);
            return Err(Error::from(e));
        }
    }

    ui.status(Status::Demoted, ident)?;

    Ok(())
}
<|endoftext|>