<commit_before>mod base;
mod backprop;
mod expand;
mod payoff;
mod rollout;
mod statistics;
mod ucb;

use self::backprop::*;
use self::payoff::*;

pub use self::base::*;
pub use self::statistics::*;

use ::rand::Rng;
use ::console_ui;
use ::game;
use ::search_graph::Target;

use std::cell::Cell;
use std::collections::HashSet;
use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub enum SearchError {
    NoRootState,
    Cycle,
    NoTerminalPayoff,
    UnexpandedInCycle,
    Ucb(ucb::UcbError),
}

pub type ActionStatistics = Vec<(game::Action, Statistics)>;

pub type Result = ::std::result::Result<ActionStatistics, SearchError>;

impl fmt::Display for SearchError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SearchError::NoRootState => write!(f, "Root state not found"),
            SearchError::Cycle => write!(f, "Cycle encountered during rollout"),
            SearchError::NoTerminalPayoff => write!(f, "Found terminal game state with no payoff"),
            SearchError::UnexpandedInCycle =>
                write!(f, "Found cycle that included an unexpanded vertex"),
            SearchError::Ucb(ref e) => write!(f, "Error computing UCB score: {}", e),
        }
    }
}

impl Error for SearchError {
    fn description(&self) -> &str {
        match *self {
            SearchError::NoRootState => "no root state",
            SearchError::Cycle => "cycle in rollout",
            SearchError::NoTerminalPayoff => "terminal state with no payoff",
            SearchError::UnexpandedInCycle => "cycle with unexpanded vertex",
            SearchError::Ucb(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            SearchError::Ucb(ref e) => Some(e),
            _ => None,
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub struct SearchSettings {
    pub simulation_count: usize,
}

pub struct SearchState<R> where R: Rng {
    epoch: usize,
    rng: R,
    explore_bias: f64,
}

impl<R> SearchState<R> where R: Rng {
    pub fn new(rng: R, explore_bias: f64) -> Self {
        SearchState {
            epoch: 1,
            rng: rng,
            explore_bias: explore_bias,
        }
    }

    pub fn search<F>(&mut self, graph: &mut Graph, root_state: game::State, mut settings_fn: F)
                     -> Result where F: FnMut(usize)-> SearchSettings {
        match graph.get_node_mut(&root_state) {
            Some(root) => {
                trace!("SearchState::search: beginning epoch {}", self.epoch);
                let settings = settings_fn(self.epoch);
                if let Err(e) = self.iterate_search(root_state.clone(), root, &settings) {
                    return Err(e)
                }
            },
            None => return Err(SearchError::NoRootState),
        }
        self.epoch += 1;
        let mut root_stats = Vec::new();
        for child_edge in graph.get_node(&root_state).unwrap().get_child_list().iter() {
            root_stats.push((child_edge.get_data().action,
                             child_edge.get_data().statistics.get()));
        }
        Ok(root_stats)
    }

    fn iterate_search<'a>(&mut self, mut state: game::State, node: MutNode<'a>,
                          settings: &SearchSettings)
                          -> ::std::result::Result<(), SearchError> {
        match rollout::rollout(node, &mut state, self.explore_bias, self.epoch, &mut self.rng) {
            Ok(Target::Unexpanded(expander)) => {
                let (expanded_node, mut player, payoff) = expand::expand(
                    expander, state.clone(), &mut self.rng, settings.simulation_count);
                // The player returned by expand::expand() is the player who is
                // now active, so we toggle the player to see who made the move
                // that got to the expanded node.
                player.toggle();
                trace!("SearchState::iterate_search: expanded node {} with incoming move by {:?} gets payoff {:?}", expanded_node.get_id(), player, payoff);
                backprop_payoff(expanded_node.to_node(), self.epoch, payoff, player,
                                self.explore_bias, &mut self.rng);
                return Ok(())
            },
            Ok(Target::Expanded(node)) =>
                match payoff(&state) {
                    None => return Err(SearchError::NoTerminalPayoff),
                    Some(p) => {
                        backprop_known_payoff(node, p);
                        return Ok(())
                    },
                },
            Err(rollout::RolloutError::Cycle(_)) => panic!("cycle in rollout"),
            Err(rollout::RolloutError::Ucb(e)) => Err(SearchError::Ucb(e)),
            // Err(e) => panic!("{:?}", e),
            // rollout::Result::Cycle(mut cyclic_edge) => {

            //     match cyclic_edge.get_target() {
            //         ::search_graph::Target::Expanded(child_node) =>
            //             if child_node.get_id() == node_id {
            //                 trace!("cycle back to root");
            //             } else {
            //                 trace!("cycle to intermediate vertex: {}", child_node.get_id());
            //             },
            //         ::search_graph::Target::Unexpanded(_) =>
            //             return Err(SearchError::UnexpandedInCycle),
            //     }
            //     // We "punish" the last edge in the cycle and the vertex it
            //     // comes from by pretending we've visited them without
            //     // having any payoff, thereby diluting their statistics and
            //     // discouraging a visit in the immediate future.
            //     // TODO: This is a hack. Most problematically, it doesn't
            //     // adequately handle the case of all paths looping back to
            //     // root. In that case, we are stuck in a loop incrementing
            //     // the visit count ad infinitum.
            //     self.punish(&cyclic_edge.get_data().statistics);
            //     self.punish(&cyclic_edge.get_source().get_data().statistics);
            // },
            // Err(rollout::RolloutError::Ucb(e)) => Err(SearchError::Ucb(e)),
        }
    }
}

fn punish(stats_cell: &Cell<Statistics>) {
    let mut stats = stats_cell.get();
    stats.visits += 1;
    stats_cell.set(stats);
}
<commit_msg>Use try! because we can.<commit_after>mod base;
mod backprop;
mod expand;
mod payoff;
mod rollout;
mod statistics;
mod ucb;

use self::backprop::*;
use self::payoff::*;

pub use self::base::*;
pub use self::statistics::*;

use ::rand::Rng;
use ::console_ui;
use ::game;
use ::search_graph::Target;

use std::cell::Cell;
use std::collections::HashSet;
use std::error::Error;
use std::fmt;

#[derive(Debug)]
pub enum SearchError {
    NoRootState,
    Cycle,
    NoTerminalPayoff,
    UnexpandedInCycle,
    Ucb(ucb::UcbError),
}

pub type ActionStatistics = Vec<(game::Action, Statistics)>;

pub type Result = ::std::result::Result<ActionStatistics, SearchError>;

impl fmt::Display for SearchError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SearchError::NoRootState => write!(f, "Root state not found"),
            SearchError::Cycle => write!(f, "Cycle encountered during rollout"),
            SearchError::NoTerminalPayoff => write!(f, "Found terminal game state with no payoff"),
            SearchError::UnexpandedInCycle =>
                write!(f, "Found cycle that included an unexpanded vertex"),
            SearchError::Ucb(ref e) => write!(f, "Error computing UCB score: {}", e),
        }
    }
}

impl Error for SearchError {
    fn description(&self) -> &str {
        match *self {
            SearchError::NoRootState => "no root state",
            SearchError::Cycle => "cycle in rollout",
            SearchError::NoTerminalPayoff => "terminal state with no payoff",
            SearchError::UnexpandedInCycle => "cycle with unexpanded vertex",
            SearchError::Ucb(ref e) => e.description(),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            SearchError::Ucb(ref e) => Some(e),
            _ => None,
        }
    }
}

#[derive(Clone, Copy, Debug)]
pub struct SearchSettings {
    pub simulation_count: usize,
}

pub struct SearchState<R> where R: Rng {
    epoch: usize,
    rng: R,
    explore_bias: f64,
}

impl<R> SearchState<R> where R: Rng {
    pub fn new(rng: R, explore_bias: f64) -> Self {
        SearchState {
            epoch: 1,
            rng: rng,
            explore_bias: explore_bias,
        }
    }

    pub fn search<F>(&mut self, graph: &mut Graph, root_state: game::State, mut settings_fn: F)
                     -> Result where F: FnMut(usize)-> SearchSettings {
        match graph.get_node_mut(&root_state) {
            Some(root) => {
                trace!("SearchState::search: beginning epoch {}", self.epoch);
                let settings = settings_fn(self.epoch);
                try!(self.iterate_search(root_state.clone(), root, &settings));
            },
            None => return Err(SearchError::NoRootState),
        }
        self.epoch += 1;
        let mut root_stats = Vec::new();
        for child_edge in graph.get_node(&root_state).unwrap().get_child_list().iter() {
            root_stats.push((child_edge.get_data().action,
                             child_edge.get_data().statistics.get()));
        }
        Ok(root_stats)
    }

    fn iterate_search<'a>(&mut self, mut state: game::State, node: MutNode<'a>,
                          settings: &SearchSettings)
                          -> ::std::result::Result<(), SearchError> {
        match rollout::rollout(node, &mut state, self.explore_bias, self.epoch, &mut self.rng) {
            Ok(Target::Unexpanded(expander)) => {
                let (expanded_node, mut player, payoff) = expand::expand(
                    expander, state.clone(), &mut self.rng, settings.simulation_count);
                // The player returned by expand::expand() is the player who is
                // now active, so we toggle the player to see who made the move
                // that got to the expanded node.
                player.toggle();
                trace!("SearchState::iterate_search: expanded node {} with incoming move by {:?} gets payoff {:?}", expanded_node.get_id(), player, payoff);
                backprop_payoff(expanded_node.to_node(), self.epoch, payoff, player,
                                self.explore_bias, &mut self.rng);
                return Ok(())
            },
            Ok(Target::Expanded(node)) =>
                match payoff(&state) {
                    None => return Err(SearchError::NoTerminalPayoff),
                    Some(p) => {
                        backprop_known_payoff(node, p);
                        return Ok(())
                    },
                },
            Err(rollout::RolloutError::Cycle(_)) => panic!("cycle in rollout"),
            Err(rollout::RolloutError::Ucb(e)) => Err(SearchError::Ucb(e)),
            // Err(e) => panic!("{:?}", e),
            // rollout::Result::Cycle(mut cyclic_edge) => {

            //     match cyclic_edge.get_target() {
            //         ::search_graph::Target::Expanded(child_node) =>
            //             if child_node.get_id() == node_id {
            //                 trace!("cycle back to root");
            //             } else {
            //                 trace!("cycle to intermediate vertex: {}", child_node.get_id());
            //             },
            //         ::search_graph::Target::Unexpanded(_) =>
            //             return Err(SearchError::UnexpandedInCycle),
            //     }
            //     // We "punish" the last edge in the cycle and the vertex it
            //     // comes from by pretending we've visited them without
            //     // having any payoff, thereby diluting their statistics and
            //     // discouraging a visit in the immediate future.
            //     // TODO: This is a hack. Most problematically, it doesn't
            //     // adequately handle the case of all paths looping back to
            //     // root. In that case, we are stuck in a loop incrementing
            //     // the visit count ad infinitum.
            //     self.punish(&cyclic_edge.get_data().statistics);
            //     self.punish(&cyclic_edge.get_source().get_data().statistics);
            // },
            // Err(rollout::RolloutError::Ucb(e)) => Err(SearchError::Ucb(e)),
        }
    }
}

fn punish(stats_cell: &Cell<Statistics>) {
    let mut stats = stats_cell.get();
    stats.visits += 1;
    stats_cell.set(stats);
}
<|endoftext|>


<commit_before>//! This module provides tools for generating meshes for simple shapes like
//! cubes and spheres.
//!
//! It uses an iterator-based interface that begins with a unit shape and
//! manipulates its constituent primitives like points, lines, and polygons.
//! All shapes provide position information and some can additionally generate
//! index, texture, and conjoint point information as well.
//!
//! # Examples
//!
//! Generating position and index data for a scaled sphere mesh:
//!
//! ```
//! use bismuth::mesh::{ConjointPoints, IndexPolygons, Points, Triangulate};
//! use bismuth::mesh::sphere::UVSphere;
//!
//! let sphere = UVSphere::with_unit_radius(16, 16);
//! let positions: Vec<_> = sphere
//!     .conjoint_points() // Get the unique set of points.
//!     .map(|point| point * 10.0) // Scale the points by 10.
//!     .collect();
//! let indeces: Vec<_> = sphere
//!     .index_polygons() // Get indeces into the unique set of points as polygons.
//!     .triangulate() // Decompose the polygons into triangles.
//!     .points() // Decompose the triangles into points (indeces).
//!     .collect();
//! ```

pub mod cube;
mod decompose;
mod generate;
mod primitive;
pub mod sphere;

pub use self::decompose::{Lines, Points, Subdivide, Tetrahedrons, Triangulate};
pub use self::generate::{ConjointPoints, IndexPolygons, Polygons, TexturePolygons};
pub use self::primitive::{Line, MapPoints, Polygon, Rotate, Triangle, Quad};

#[cfg(test)]
mod tests {
    use super::*;
}
<commit_msg>Minor tweak to `mesh` documentation.<commit_after>//! This module provides tools for generating meshes for simple shapes like
//! cubes and spheres.
//!
//! The interface is iterator-based and begins with a unit shape and
//! manipulates its constituent primitives like points, lines, and polygons.
//! All shapes provide position information and some can additionally generate
//! index, texture, and conjoint point information as well.
//!
//! # Examples
//!
//! Generating position and index data for a scaled sphere mesh:
//!
//! ```
//! use bismuth::mesh::{ConjointPoints, IndexPolygons, Points, Triangulate};
//! use bismuth::mesh::sphere::UVSphere;
//!
//! let sphere = UVSphere::with_unit_radius(16, 16);
//! let positions: Vec<_> = sphere
//!     .conjoint_points() // Get the unique set of points.
//!     .map(|point| point * 10.0) // Scale the points by 10.
//!     .collect();
//! let indeces: Vec<_> = sphere
//!     .index_polygons() // Get indeces into the unique set of points as polygons.
//!     .triangulate() // Decompose the polygons into triangles.
//!     .points() // Decompose the triangles into points (indeces).
//!     .collect();
//! ```

pub mod cube;
mod decompose;
mod generate;
mod primitive;
pub mod sphere;

pub use self::decompose::{Lines, Points, Subdivide, Tetrahedrons, Triangulate};
pub use self::generate::{ConjointPoints, IndexPolygons, Polygons, TexturePolygons};
pub use self::primitive::{Line, MapPoints, Polygon, Rotate, Triangle, Quad};

#[cfg(test)]
mod tests {
    use super::*;
}
<|endoftext|>


<commit_before>use eventual::{Async, Future};
use protobuf;

use librespot_protocol as protocol;
use mercury::{MercuryRequest, MercuryMethod};
use util::{SpotifyId, FileId, StrChunksExt};
use session::Session;

pub use librespot_protocol::metadata::AudioFile_Format as FileFormat;

fn countrylist_contains(list: &str, country: &str) -> bool {
    list.chunks(2).any(|cc| cc == country)
}

fn parse_restrictions<'s, I>(restrictions: I, country: &str, catalogue: &str) -> bool
    where I: Iterator<Item = &'s protocol::metadata::Restriction>
{
    restrictions.filter(|r| r.get_catalogue_str().contains(&catalogue.to_owned()))
                .all(|r| {
                    !countrylist_contains(r.get_countries_forbidden(), country) &&
                    (!r.has_countries_allowed() ||
                     countrylist_contains(r.get_countries_allowed(), country))
                })
}

pub trait MetadataTrait : Send + 'static {
    type Message: protobuf::MessageStatic;

    fn base_url() -> &'static str;
    fn parse(msg: &Self::Message, session: &Session) -> Self;
}

#[derive(Debug)]
pub struct Track {
    pub id: SpotifyId,
    pub name: String,
    pub album: SpotifyId,
    pub files: Vec<(FileId, FileFormat)>,
    pub alternatives: Vec<SpotifyId>,
    pub available: bool,
}

#[derive(Debug)]
pub struct Album {
    pub id: SpotifyId,
    pub name: String,
    pub artists: Vec<SpotifyId>,
    pub covers: Vec<FileId>,
}

#[derive(Debug)]
pub struct Artist {
    pub id: SpotifyId,
    pub name: String,
}

pub type MetadataRef<T> = Future<T, ()>;
pub type TrackRef = MetadataRef<Track>;
pub type AlbumRef = MetadataRef<Album>;
pub type ArtistRef = MetadataRef<Artist>;

impl MetadataTrait for Track {
    type Message = protocol::metadata::Track;

    fn base_url() -> &'static str {
        "hm://metadata/3/track"
    }

    fn parse(msg: &Self::Message, session: &Session) -> Self {
        Track {
            id: SpotifyId::from_raw(msg.get_gid()),
            name: msg.get_name().to_owned(),
            album: SpotifyId::from_raw(msg.get_album().get_gid()),
            files: msg.get_file()
                      .iter()
                      .filter(|file| file.has_file_id())
                      .map(|file| {
                          let mut dst = [0u8; 20];
                          dst.clone_from_slice(&file.get_file_id());
                          (FileId(dst), file.get_format())
                      })
                      .collect(),
            alternatives: msg.get_alternative()
                             .iter()
                             .map(|alt| SpotifyId::from_raw(alt.get_gid()))
                             .collect(),
            available: parse_restrictions(msg.get_restriction().iter(),
                                          &session.0.data.read().unwrap().country,
                                          "premium"),
        }
    }
}

impl MetadataTrait for Album {
    type Message = protocol::metadata::Album;

    fn base_url() -> &'static str {
        "hm://metadata/3/album"
    }

    fn parse(msg: &Self::Message, _: &Session) -> Self {
        Album {
            id: SpotifyId::from_raw(msg.get_gid()),
            name: msg.get_name().to_owned(),
            artists: msg.get_artist()
                        .iter()
                        .map(|a| SpotifyId::from_raw(a.get_gid()))
                        .collect(),
            covers: msg.get_cover_group()
                       .get_image()
                       .iter()
                       .filter(|image| image.has_file_id())
                       .map(|image| {
                           let mut dst = [0u8; 20];
                           dst.clone_from_slice(&image.get_file_id());
                           FileId(dst)
                       })
                       .collect(),
        }
    }
}

impl MetadataTrait for Artist {
    type Message = protocol::metadata::Artist;

    fn base_url() -> &'static str {
        "hm://metadata/3/artist"
    }

    fn parse(msg: &Self::Message, _: &Session) -> Self {
        Artist {
            id: SpotifyId::from_raw(msg.get_gid()),
            name: msg.get_name().to_owned(),
        }
    }
}

pub struct MetadataManager;

impl MetadataManager {
    pub fn new() -> MetadataManager {
        MetadataManager
    }

    pub fn get<T: MetadataTrait>(&mut self, session: &Session, id: SpotifyId) -> MetadataRef<T> {
        let session = session.clone();
        session.mercury(MercuryRequest {
                   method: MercuryMethod::GET,
                   uri: format!("{}/{}", T::base_url(), id.to_base16()),
                   content_type: None,
                   payload: Vec::new(),
               })
               .and_then(move |response| {
                   let data = response.payload.first().unwrap();
                   let msg: T::Message = protobuf::parse_from_bytes(data).unwrap();

                   Ok(T::parse(&msg, &session))
               })
    }
}
<commit_msg>Expose some more metadata.<commit_after>use eventual::{Async, Future};
use protobuf;

use librespot_protocol as protocol;
use mercury::{MercuryRequest, MercuryMethod};
use util::{SpotifyId, FileId, StrChunksExt};
use session::Session;

pub use librespot_protocol::metadata::AudioFile_Format as FileFormat;

fn countrylist_contains(list: &str, country: &str) -> bool {
    list.chunks(2).any(|cc| cc == country)
}

fn parse_restrictions<'s, I>(restrictions: I, country: &str, catalogue: &str) -> bool
    where I: IntoIterator<Item = &'s protocol::metadata::Restriction>
{
    restrictions.into_iter()
                .filter(|r| r.get_catalogue_str().contains(&catalogue.to_owned()))
                .all(|r| {
                    !countrylist_contains(r.get_countries_forbidden(), country) &&
                    (!r.has_countries_allowed() ||
                     countrylist_contains(r.get_countries_allowed(), country))
                })
}

pub trait MetadataTrait : Send + 'static {
    type Message: protobuf::MessageStatic;

    fn base_url() -> &'static str;
    fn parse(msg: &Self::Message, session: &Session) -> Self;
}

#[derive(Debug)]
pub struct Track {
    pub id: SpotifyId,
    pub name: String,
    pub album: SpotifyId,
    pub artists: Vec<SpotifyId>,
    pub files: Vec<(FileId, FileFormat)>,
    pub alternatives: Vec<SpotifyId>,
    pub available: bool,
}

#[derive(Debug)]
pub struct Album {
    pub id: SpotifyId,
    pub name: String,
    pub artists: Vec<SpotifyId>,
    pub tracks: Vec<SpotifyId>,
    pub covers: Vec<FileId>,
}

#[derive(Debug)]
pub struct Artist {
    pub id: SpotifyId,
    pub name: String,
    pub top_tracks: Vec<SpotifyId>,
}

pub type MetadataRef<T> = Future<T, ()>;
pub type TrackRef = MetadataRef<Track>;
pub type AlbumRef = MetadataRef<Album>;
pub type ArtistRef = MetadataRef<Artist>;

impl MetadataTrait for Track {
    type Message = protocol::metadata::Track;

    fn base_url() -> &'static str {
        "hm://metadata/3/track"
    }

    fn parse(msg: &Self::Message, session: &Session) -> Self {
        let country = session.0.data.read().unwrap().country.clone();

        let artists = msg.get_artist()
                         .iter()
                         .filter(|artist| artist.has_gid())
                         .map(|artist| SpotifyId::from_raw(artist.get_gid()))
                         .collect::<Vec<_>>();

        let files = msg.get_file()
                       .iter()
                       .filter(|file| file.has_file_id())
                       .map(|file| {
                           let mut dst = [0u8; 20];
                           dst.clone_from_slice(&file.get_file_id());
                           (FileId(dst), file.get_format())
                       })
                       .collect();

        Track {
            id: SpotifyId::from_raw(msg.get_gid()),
            name: msg.get_name().to_owned(),
            album: SpotifyId::from_raw(msg.get_album().get_gid()),
            artists: artists,
            files: files,
            alternatives: msg.get_alternative()
                             .iter()
                             .map(|alt| SpotifyId::from_raw(alt.get_gid()))
                             .collect(),
            available: parse_restrictions(msg.get_restriction(),
                                          &country,
                                          "premium"),
        }
    }
}

impl MetadataTrait for Album {
    type Message = protocol::metadata::Album;

    fn base_url() -> &'static str {
        "hm://metadata/3/album"
    }

    fn parse(msg: &Self::Message, _: &Session) -> Self {
        let artists = msg.get_artist()
                         .iter()
                         .filter(|artist| artist.has_gid())
                         .map(|artist| SpotifyId::from_raw(artist.get_gid()))
                         .collect::<Vec<_>>();

        let tracks = msg.get_disc()
                        .iter()
                        .flat_map(|disc| disc.get_track())
                        .filter(|track| track.has_gid())
                        .map(|track| SpotifyId::from_raw(track.get_gid()))
                        .collect::<Vec<_>>();

        let covers = msg.get_cover_group()
                        .get_image()
                        .iter()
                        .filter(|image| image.has_file_id())
                        .map(|image| {
                            let mut dst = [0u8; 20];
                            dst.clone_from_slice(&image.get_file_id());
                            FileId(dst)
                        })
                        .collect::<Vec<_>>();

        Album {
            id: SpotifyId::from_raw(msg.get_gid()),
            name: msg.get_name().to_owned(),
            artists: artists,
            tracks: tracks,
            covers: covers,
        }
    }
}

impl MetadataTrait for Artist {
    type Message = protocol::metadata::Artist;

    fn base_url() -> &'static str {
        "hm://metadata/3/artist"
    }

    fn parse(msg: &Self::Message, session: &Session) -> Self {
        let country = session.0.data.read().unwrap().country.clone();

        let top_tracks = msg.get_top_track()
                            .iter()
                            .filter(|tt| !tt.has_country() ||
                                         countrylist_contains(tt.get_country(), &country))
                            .next()
                            .unwrap()
                            .get_track()
                            .iter()
                            .filter(|track| track.has_gid())
                            .map(|track| SpotifyId::from_raw(track.get_gid()))
                            .collect::<Vec<_>>();

        Artist {
            id: SpotifyId::from_raw(msg.get_gid()),
            name: msg.get_name().to_owned(),
            top_tracks: top_tracks
        }
    }
}

pub struct MetadataManager;

impl MetadataManager {
    pub fn new() -> MetadataManager {
        MetadataManager
    }

    pub fn get<T: MetadataTrait>(&mut self, session: &Session, id: SpotifyId) -> MetadataRef<T> {
        let session = session.clone();
        session.mercury(MercuryRequest {
                   method: MercuryMethod::GET,
                   uri: format!("{}/{}", T::base_url(), id.to_base16()),
                   content_type: None,
                   payload: Vec::new(),
               })
               .and_then(move |response| {
                   let data = response.payload.first().unwrap();
                   let msg: T::Message = protobuf::parse_from_bytes(data).unwrap();

                   Ok(T::parse(&msg, &session))
               })
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;
use std::io::{stdout, Write};
use std::ops::{AddAssign, SubAssign};
use terminal_size::{terminal_size, Height, Width};

/// Tracks progress of a task.
///
/// There should be not more than a single instance started at a given point in
/// time, it will mangle your terminal output.
pub struct Progress {
    current: usize,
    total: usize,

    caption: String,

    width: Option<u16>,

    started: bool,
}

impl Default for Progress {
    fn default() -> Progress {
        Progress::new("Progress", 0, 100)
    }
}

impl Progress {
    pub fn new<S: Into<String>>(caption: S, start: usize, end: usize) -> Self {
        Progress {
            current: start,
            total: end,
            caption: caption.into(),
            width: None,
            started: false,
        }
    }

    pub fn new_with_width<S>(caption: S, start: usize, end: usize, width: u16) -> Self
    where
        S: Into<String>,
    {
        Progress {
            current: start,
            total: end,
            caption: caption.into(),
            width: Some(width),
            started: false,
        }
    }

    /// Returns the current progress absolute value.
    ///
    /// # Example
    ///
    /// ```
    /// use progress::Progress;
    /// let p = Progress::default();
    /// assert_eq!(0, p.current());
    /// ```
    pub fn current(&self) -> usize {
        self.current
    }

    /// Returns the total value.
    ///
    /// # Example
    ///
    /// ```
    /// use progress::Progress;
    /// let p = Progress::default();
    /// assert_eq!(100, p.total());
    /// ```
    pub fn total(&self) -> usize {
        self.total
    }

    /// Advances the Progress by a certain amount.
    ///
    /// # Examplw
    ///
    /// ```
    /// use progress::Progress;
    /// let mut p = Progress::default();
    /// assert_eq!(0, p.current());
    /// p.forward(10);
    /// assert_eq!(10, p.current());
    /// p += 20;
    /// assert_eq!(30, p.current());
    /// ```
    pub fn forward(&mut self, step: usize) -> &Self {
        *self += step;
        self
    }

    /// Advances the Progress by a certain amount.
    ///
    /// # Examplw
    ///
    /// ```
    /// use progress::Builder;
    /// let mut p = Builder::new().set_start(30).build();
    /// assert_eq!(30, p.current());
    /// p.backward(10);
    /// assert_eq!(20, p.current());
    /// p -= 20;
    /// assert_eq!(0, p.current());
    /// ```
    pub fn backward(&mut self, step: usize) -> &Self {
        *self -= step;
        self
    }

    /// Advances the Progress by exactly one.
    pub fn increment(&mut self) -> &Self {
        self.forward(1)
    }

    /// Does a step backwards at the Progress.
    pub fn decrement(&mut self) -> &Self {
        self.backward(1)
    }

    /// Determines wheter a Progress has finished (reached the total) or not.
    pub fn finished(&self) -> bool {
        self.current >= self.total
    }

    /// Returns the relative value of the Progress.
    pub fn process(&self) -> u8 {
        (self.current * 100 / self.total) as u8
    }

    /// Activates the Progress.
    pub fn start(&mut self) -> &Self {
        self.started = true;
        self
    }

    /// Returns the current caption.
    pub fn caption(&self) -> &String {
        &self.caption
    }
}

impl AddAssign<usize> for Progress {
    fn add_assign(&mut self, step: usize) {
        let new = self.current + step;
        if new > self.total {
            self.current = self.total;
        } else {
            self.current += step;
        }
        print_bar(self);
    }
}

impl SubAssign<usize> for Progress {
    fn sub_assign(&mut self, step: usize) {
        self.current = self.current.saturating_sub(step);
        print_bar(self);
    }
}

fn print_bar(p: &Progress) {
    let p_info = format!(
        "{current} / {total} ({process})",
        current = p.current(),
        total = p.total(),
        process = p.process()
    );
    let caption = p.caption();

    let terminal_width = p.width
        .unwrap_or_else(terminal_size().unwrap_or(((Width(79), Height(0)).0).0)); // terminal_size().unwrap_or((Width(79), Height(0)));

    let bar_width = terminal_width as usize // Width of terminal
        - p_info.len()  // Width of right summary
        - caption.len() // Width of caption
        - 3  // Colon and spaces
        - 2; // vertical bars in the progress meter
    let done_width = (bar_width * p.process() as usize) / 100;
    let todo_width = bar_width - done_width;
    let done_bar = repeat("#").take(done_width).collect::<String>();
    let todo_bar = repeat("-").take(todo_width).collect::<String>();
    let bar = format!("|{}{}|", done_bar, todo_bar);

    print!(
        "{caption}: {bar} {info}\r",
        caption = caption,
        bar = bar,
        info = p_info
    );
    stdout().flush().unwrap();
}
<commit_msg>fix type<commit_after>use std::iter::repeat;
use std::io::{stdout, Write};
use std::ops::{AddAssign, SubAssign};
use terminal_size::{terminal_size, Height, Width};

/// Tracks progress of a task.
///
/// There should be not more than a single instance started at a given point in
/// time, it will mangle your terminal output.
pub struct Progress {
    current: usize,
    total: usize,

    caption: String,

    width: Option<u16>,

    started: bool,
}

impl Default for Progress {
    fn default() -> Progress {
        Progress::new("Progress", 0, 100)
    }
}

impl Progress {
    pub fn new<S: Into<String>>(caption: S, start: usize, end: usize) -> Self {
        Progress {
            current: start,
            total: end,
            caption: caption.into(),
            width: None,
            started: false,
        }
    }

    pub fn new_with_width<S>(caption: S, start: usize, end: usize, width: u16) -> Self
    where
        S: Into<String>,
    {
        Progress {
            current: start,
            total: end,
            caption: caption.into(),
            width: Some(width),
            started: false,
        }
    }

    /// Returns the current progress absolute value.
    ///
    /// # Example
    ///
    /// ```
    /// use progress::Progress;
    /// let p = Progress::default();
    /// assert_eq!(0, p.current());
    /// ```
    pub fn current(&self) -> usize {
        self.current
    }

    /// Returns the total value.
    ///
    /// # Example
    ///
    /// ```
    /// use progress::Progress;
    /// let p = Progress::default();
    /// assert_eq!(100, p.total());
    /// ```
    pub fn total(&self) -> usize {
        self.total
    }

    /// Advances the Progress by a certain amount.
    ///
    /// # Examplw
    ///
    /// ```
    /// use progress::Progress;
    /// let mut p = Progress::default();
    /// assert_eq!(0, p.current());
    /// p.forward(10);
    /// assert_eq!(10, p.current());
    /// p += 20;
    /// assert_eq!(30, p.current());
    /// ```
    pub fn forward(&mut self, step: usize) -> &Self {
        *self += step;
        self
    }

    /// Advances the Progress by a certain amount.
    ///
    /// # Examplw
    ///
    /// ```
    /// use progress::Builder;
    /// let mut p = Builder::new().set_start(30).build();
    /// assert_eq!(30, p.current());
    /// p.backward(10);
    /// assert_eq!(20, p.current());
    /// p -= 20;
    /// assert_eq!(0, p.current());
    /// ```
    pub fn backward(&mut self, step: usize) -> &Self {
        *self -= step;
        self
    }

    /// Advances the Progress by exactly one.
    pub fn increment(&mut self) -> &Self {
        self.forward(1)
    }

    /// Does a step backwards at the Progress.
    pub fn decrement(&mut self) -> &Self {
        self.backward(1)
    }

    /// Determines wheter a Progress has finished (reached the total) or not.
    pub fn finished(&self) -> bool {
        self.current >= self.total
    }

    /// Returns the relative value of the Progress.
    pub fn process(&self) -> u8 {
        (self.current * 100 / self.total) as u8
    }

    /// Activates the Progress.
    pub fn start(&mut self) -> &Self {
        self.started = true;
        self
    }

    /// Returns the current caption.
    pub fn caption(&self) -> &String {
        &self.caption
    }
}

impl AddAssign<usize> for Progress {
    fn add_assign(&mut self, step: usize) {
        let new = self.current + step;
        if new > self.total {
            self.current = self.total;
        } else {
            self.current += step;
        }
        print_bar(self);
    }
}

impl SubAssign<usize> for Progress {
    fn sub_assign(&mut self, step: usize) {
        self.current = self.current.saturating_sub(step);
        print_bar(self);
    }
}

fn print_bar(p: &Progress) {
    let p_info = format!(
        "{current} / {total} ({process})",
        current = p.current(),
        total = p.total(),
        process = p.process()
    );
    let caption = p.caption();

    let terminal_width = p.width
        .unwrap_or_else(|| terminal_size().unwrap_or((Width(79), Height(0))).0 .0); // terminal_size().unwrap_or((Width(79), Height(0)));

    let bar_width = terminal_width as usize // Width of terminal
        - p_info.len()  // Width of right summary
        - caption.len() // Width of caption
        - 3  // Colon and spaces
        - 2; // vertical bars in the progress meter
    let done_width = (bar_width * p.process() as usize) / 100;
    let todo_width = bar_width - done_width;
    let done_bar = repeat("#").take(done_width).collect::<String>();
    let todo_bar = repeat("-").take(todo_width).collect::<String>();
    let bar = format!("|{}{}|", done_bar, todo_bar);

    print!(
        "{caption}: {bar} {info}\r",
        caption = caption,
        bar = bar,
        info = p_info
    );
    stdout().flush().unwrap();
}
<|endoftext|>


<commit_before>use std::ops::{Add, AddAssign, Sub, Div, Mul, Index, IndexMut};

use na;
use num::{Zero, One};

use ::{lerp, find_interval};
use cie;

/// Represents a linear RGB spectrum.
/// TODO Rename this to `RGBSpectrum` and make `Spectrum` a type alias to this so we can also support
/// full spectral rendering.
#[derive(Debug,Copy,PartialEq,Clone,Default)]
pub struct Spectrum {
    pub r: f32,
    pub g: f32,
    pub b: f32,
}

impl Spectrum {
    /// Create an RGB spectrum from its components
    pub fn rgb(r: f32, g: f32, b: f32) -> Spectrum {
        Spectrum { r: r, g: g, b: b }
    }

    /// Create an RGB spectrum where all the components have the same value.
    pub fn grey(v: f32) -> Spectrum {
        Spectrum { r: v, g: v, b: v }
    }

    pub fn white() -> Spectrum {
        Spectrum::rgb(1.0, 1.0, 1.0)
    }

    pub fn black() -> Spectrum {
        Spectrum::rgb(0.0, 0.0, 0.0)
    }

    pub fn red() -> Spectrum {
        Spectrum::rgb(1.0, 0.0, 0.0)
    }

    pub fn green() -> Spectrum {
        Spectrum::rgb(0.0, 1.0, 0.0)
    }

    pub fn blue() -> Spectrum {
        Spectrum::rgb(0.0, 0.0, 1.0)
    }

    /// Convert this linear RGB spectrum to non-linear sRGB and return the result as an array of
    /// bytes.
    pub fn to_srgb(&self) -> [u8; 3] {
        let a = 0.055f32;
        let b = 1f32 / 2.4;
        let mut srgb = [0; 3];
        for i in 0..3 {
            let v = if self[i] <= 0.0031308 {
                12.92 * self[i]
            } else {
                (1.0 + a) * f32::powf(self[i], b) - a
            };
            srgb[i] = na::clamp(v * 255.0, 0.0, 255.0) as u8;
        }
        srgb
    }

    /// Convert a non-linear sRGB value to a linear RGB spectrum.
    pub fn from_srgb(rgb: &[u8; 3]) -> Spectrum {
        fn convert(v: u8) -> f32 {
            let value = v as f32 / 255.0;
            if value <= 0.04045 {
                value / 12.92
            } else {
                ((value + 0.055) * 1.0 / 1.055).powf(2.4)
            }
        }

        Spectrum::rgb(convert(rgb[0]), convert(rgb[1]), convert(rgb[2]))
    }

    /// Convert a linear spectrum in XYZ format to a linear RGB format.
    pub fn from_xyz(xyz: &[f32; 3]) -> Spectrum {
        let r = 3.240479 * xyz[0] - 1.537150 * xyz[1] - 0.498535 * xyz[2];
        let g = -0.969256 * xyz[0] + 1.875991 * xyz[1] + 0.041556 * xyz[2];
        let b = 0.055648 * xyz[0] - 0.204043 * xyz[1] + 1.057311 * xyz[2];
        Spectrum::rgb(r, g, b)
    }

    /// Create a spectrum from a series of (wavelength, value) samples from an SPD (Spectral Power
    /// Distribution).
    pub fn from_sampled(lambda: &[f32], v: &[f32], n: usize) -> Spectrum {
        // TODO sort by wavelength if needed
        let mut xyz = [0.0; 3];
        for i in 0..cie::N_CIE_SAMPLES {
            let val = interpolate_spectrum_samples(lambda, v, n, cie::CIE_LAMBDA[i]);
            xyz[0] += val * cie::CIE_X[i];
            xyz[1] += val * cie::CIE_Y[i];
            xyz[2] += val * cie::CIE_Z[i];
        }
        let scale = (cie::CIE_LAMBDA[cie::N_CIE_SAMPLES - 1] - cie::CIE_LAMBDA[0]) /
                    (cie::CIE_Y_INTEGRAL * cie::N_CIE_SAMPLES as f32);
        xyz[0] *= scale;
        xyz[1] *= scale;
        xyz[2] *= scale;

        Self::from_xyz(&xyz)
    }

    /// Return true if the colour is black i.e (0, 0 ,0).
    pub fn is_black(&self) -> bool {
        self.r == 0.0 && self.g == 0.0 && self.b == 0.0
    }

    /// Return true if any of the components is NaN. Useful for debugging.
    pub fn has_nan(&self) -> bool {
        self.r.is_nan() || self.g.is_nan() || self.b.is_nan()
    }

    /// Return true if any of the components is infinite. Useful for debugging.
    pub fn is_infinite(&self) -> bool {
        self.r.is_infinite() || self.g.is_infinite() || self.b.is_infinite()
    }

    /// Return a spectrum where each component is the square root of the original component.
    pub fn sqrt(&self) -> Spectrum {
        Spectrum::rgb(self.r.sqrt(), self.g.sqrt(), self.b.sqrt())
    }

    /// Return the luminance of the Spectrum
    pub fn y(&self) -> f32 {
        let y_height: [f32; 3] = [0.212671, 0.715160, 0.072169];
        return y_height[0] * self[0] + y_height[1] * self[1] + y_height[2] * self[2];

    }
}

fn interpolate_spectrum_samples(lambda: &[f32], vals: &[f32], n: usize, l: f32) -> f32 {
    for i in 0..n - 1 {
        assert!(lambda[i + 1] > lambda[i]);
    }
    if l <= lambda[0] {
        return vals[0];
    }
    if l >= lambda[n - 1] {
        return vals[n - 1];
    }
    let offset = find_interval(n, |index| lambda[index] <= l);
    assert!(l >= lambda[offset] && l <= lambda[offset + 1]);
    let t = (l - lambda[offset]) / (lambda[offset + 1] - lambda[offset]);
    lerp(t, vals[offset], vals[offset + 1])
}

// Operators

impl Add<Spectrum> for Spectrum {
    type Output = Spectrum;

    fn add(self, rhs: Spectrum) -> Spectrum {
        Spectrum {
            r: self.r + rhs.r,
            g: self.g + rhs.g,
            b: self.b + rhs.b,
        }
    }
}

impl Sub<Spectrum> for Spectrum {
    type Output = Spectrum;

    fn sub(self, rhs: Spectrum) -> Spectrum {
        Spectrum {
            r: self.r - rhs.r,
            g: self.g - rhs.g,
            b: self.b - rhs.b,
        }
    }
}

impl AddAssign<Spectrum> for Spectrum {
    fn add_assign(&mut self, rhs: Spectrum) {
        self.r += rhs.r;
        self.g += rhs.g;
        self.b += rhs.b;
    }
}

impl Mul<Spectrum> for Spectrum {
    type Output = Spectrum;

    fn mul(self, rhs: Spectrum) -> Spectrum {
        Spectrum::rgb(self.r * rhs.r, self.g * rhs.g, self.b * rhs.b)
    }
}

impl Div<Spectrum> for Spectrum {
    type Output = Spectrum;

    fn div(self, rhs: Spectrum) -> Spectrum {
        Spectrum::rgb(self.r / rhs.r, self.g / rhs.g, self.b / rhs.b)
    }
}

impl Add<f32> for Spectrum {
    type Output = Spectrum;

    fn add(self, rhs: f32) -> Spectrum {
        Spectrum {
            r: self.r + rhs,
            g: self.g + rhs,
            b: self.b + rhs,
        }
    }
}

impl Sub<f32> for Spectrum {
    type Output = Spectrum;

    fn sub(self, rhs: f32) -> Spectrum {
        Spectrum {
            r: self.r - rhs,
            g: self.g - rhs,
            b: self.b - rhs,
        }
    }
}

impl Mul<f32> for Spectrum {
    type Output = Spectrum;

    fn mul(self, rhs: f32) -> Spectrum {
        Spectrum::rgb(self.r * rhs, self.g * rhs, self.b * rhs)
    }
}

impl Mul<Spectrum> for f32 {
    type Output = Spectrum;

    fn mul(self, rhs: Spectrum) -> Spectrum {
        Spectrum::rgb(self * rhs.r, self * rhs.g, self * rhs.b)
    }
}

impl Div<f32> for Spectrum {
    type Output = Spectrum;

    fn div(self, rhs: f32) -> Spectrum {
        Spectrum::rgb(self.r / rhs, self.g / rhs, self.b / rhs)
    }
}

impl Index<usize> for Spectrum {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index(&self, i: usize) -> &f32 {
        match i {
            0 => &self.r,
            1 => &self.g,
            2 => &self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}

impl IndexMut<usize> for Spectrum {
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index_mut(&mut self, i: usize) -> &mut f32 {
        match i {
            0 => &mut self.r,
            1 => &mut self.g,
            2 => &mut self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}

impl Zero for Spectrum {
    fn zero() -> Spectrum {
        Spectrum::black()
    }

    fn is_zero(&self) -> bool {
        self.is_black()
    }
}

impl One for Spectrum {
    fn one() -> Spectrum {
        Spectrum::white()
    }
}
<commit_msg>Add Display instance for Spectrum<commit_after>use std::ops::{Add, AddAssign, Sub, Div, Mul, Index, IndexMut};
use std::fmt;

use na;
use num::{Zero, One};

use ::{lerp, find_interval};
use cie;

/// Represents a linear RGB spectrum.
/// TODO Rename this to `RGBSpectrum` and make `Spectrum` a type alias to this so we can also support
/// full spectral rendering.
#[derive(Debug,Copy,PartialEq,Clone,Default)]
pub struct Spectrum {
    pub r: f32,
    pub g: f32,
    pub b: f32,
}

impl Spectrum {
    /// Create an RGB spectrum from its components
    pub fn rgb(r: f32, g: f32, b: f32) -> Spectrum {
        Spectrum { r: r, g: g, b: b }
    }

    /// Create an RGB spectrum where all the components have the same value.
    pub fn grey(v: f32) -> Spectrum {
        Spectrum { r: v, g: v, b: v }
    }

    pub fn white() -> Spectrum {
        Spectrum::rgb(1.0, 1.0, 1.0)
    }

    pub fn black() -> Spectrum {
        Spectrum::rgb(0.0, 0.0, 0.0)
    }

    pub fn red() -> Spectrum {
        Spectrum::rgb(1.0, 0.0, 0.0)
    }

    pub fn green() -> Spectrum {
        Spectrum::rgb(0.0, 1.0, 0.0)
    }

    pub fn blue() -> Spectrum {
        Spectrum::rgb(0.0, 0.0, 1.0)
    }

    /// Convert this linear RGB spectrum to non-linear sRGB and return the result as an array of
    /// bytes.
    pub fn to_srgb(&self) -> [u8; 3] {
        let a = 0.055f32;
        let b = 1f32 / 2.4;
        let mut srgb = [0; 3];
        for i in 0..3 {
            let v = if self[i] <= 0.0031308 {
                12.92 * self[i]
            } else {
                (1.0 + a) * f32::powf(self[i], b) - a
            };
            srgb[i] = na::clamp(v * 255.0, 0.0, 255.0) as u8;
        }
        srgb
    }

    /// Convert a non-linear sRGB value to a linear RGB spectrum.
    pub fn from_srgb(rgb: &[u8; 3]) -> Spectrum {
        fn convert(v: u8) -> f32 {
            let value = v as f32 / 255.0;
            if value <= 0.04045 {
                value / 12.92
            } else {
                ((value + 0.055) * 1.0 / 1.055).powf(2.4)
            }
        }

        Spectrum::rgb(convert(rgb[0]), convert(rgb[1]), convert(rgb[2]))
    }

    /// Convert a linear spectrum in XYZ format to a linear RGB format.
    pub fn from_xyz(xyz: &[f32; 3]) -> Spectrum {
        let r = 3.240479 * xyz[0] - 1.537150 * xyz[1] - 0.498535 * xyz[2];
        let g = -0.969256 * xyz[0] + 1.875991 * xyz[1] + 0.041556 * xyz[2];
        let b = 0.055648 * xyz[0] - 0.204043 * xyz[1] + 1.057311 * xyz[2];
        Spectrum::rgb(r, g, b)
    }

    /// Create a spectrum from a series of (wavelength, value) samples from an SPD (Spectral Power
    /// Distribution).
    pub fn from_sampled(lambda: &[f32], v: &[f32], n: usize) -> Spectrum {
        // TODO sort by wavelength if needed
        let mut xyz = [0.0; 3];
        for i in 0..cie::N_CIE_SAMPLES {
            let val = interpolate_spectrum_samples(lambda, v, n, cie::CIE_LAMBDA[i]);
            xyz[0] += val * cie::CIE_X[i];
            xyz[1] += val * cie::CIE_Y[i];
            xyz[2] += val * cie::CIE_Z[i];
        }
        let scale = (cie::CIE_LAMBDA[cie::N_CIE_SAMPLES - 1] - cie::CIE_LAMBDA[0]) /
                    (cie::CIE_Y_INTEGRAL * cie::N_CIE_SAMPLES as f32);
        xyz[0] *= scale;
        xyz[1] *= scale;
        xyz[2] *= scale;

        Self::from_xyz(&xyz)
    }

    /// Return true if the colour is black i.e (0, 0 ,0).
    pub fn is_black(&self) -> bool {
        self.r == 0.0 && self.g == 0.0 && self.b == 0.0
    }

    /// Return true if any of the components is NaN. Useful for debugging.
    pub fn has_nan(&self) -> bool {
        self.r.is_nan() || self.g.is_nan() || self.b.is_nan()
    }

    /// Return true if any of the components is infinite. Useful for debugging.
    pub fn is_infinite(&self) -> bool {
        self.r.is_infinite() || self.g.is_infinite() || self.b.is_infinite()
    }

    /// Return a spectrum where each component is the square root of the original component.
    pub fn sqrt(&self) -> Spectrum {
        Spectrum::rgb(self.r.sqrt(), self.g.sqrt(), self.b.sqrt())
    }

    /// Return the luminance of the Spectrum
    pub fn y(&self) -> f32 {
        let y_height: [f32; 3] = [0.212671, 0.715160, 0.072169];
        return y_height[0] * self[0] + y_height[1] * self[1] + y_height[2] * self[2];

    }
}

fn interpolate_spectrum_samples(lambda: &[f32], vals: &[f32], n: usize, l: f32) -> f32 {
    for i in 0..n - 1 {
        assert!(lambda[i + 1] > lambda[i]);
    }
    if l <= lambda[0] {
        return vals[0];
    }
    if l >= lambda[n - 1] {
        return vals[n - 1];
    }
    let offset = find_interval(n, |index| lambda[index] <= l);
    assert!(l >= lambda[offset] && l <= lambda[offset + 1]);
    let t = (l - lambda[offset]) / (lambda[offset + 1] - lambda[offset]);
    lerp(t, vals[offset], vals[offset + 1])
}

// Operators

impl Add<Spectrum> for Spectrum {
    type Output = Spectrum;

    fn add(self, rhs: Spectrum) -> Spectrum {
        Spectrum {
            r: self.r + rhs.r,
            g: self.g + rhs.g,
            b: self.b + rhs.b,
        }
    }
}

impl Sub<Spectrum> for Spectrum {
    type Output = Spectrum;

    fn sub(self, rhs: Spectrum) -> Spectrum {
        Spectrum {
            r: self.r - rhs.r,
            g: self.g - rhs.g,
            b: self.b - rhs.b,
        }
    }
}

impl AddAssign<Spectrum> for Spectrum {
    fn add_assign(&mut self, rhs: Spectrum) {
        self.r += rhs.r;
        self.g += rhs.g;
        self.b += rhs.b;
    }
}

impl Mul<Spectrum> for Spectrum {
    type Output = Spectrum;

    fn mul(self, rhs: Spectrum) -> Spectrum {
        Spectrum::rgb(self.r * rhs.r, self.g * rhs.g, self.b * rhs.b)
    }
}

impl Div<Spectrum> for Spectrum {
    type Output = Spectrum;

    fn div(self, rhs: Spectrum) -> Spectrum {
        Spectrum::rgb(self.r / rhs.r, self.g / rhs.g, self.b / rhs.b)
    }
}

impl Add<f32> for Spectrum {
    type Output = Spectrum;

    fn add(self, rhs: f32) -> Spectrum {
        Spectrum {
            r: self.r + rhs,
            g: self.g + rhs,
            b: self.b + rhs,
        }
    }
}

impl Sub<f32> for Spectrum {
    type Output = Spectrum;

    fn sub(self, rhs: f32) -> Spectrum {
        Spectrum {
            r: self.r - rhs,
            g: self.g - rhs,
            b: self.b - rhs,
        }
    }
}

impl Mul<f32> for Spectrum {
    type Output = Spectrum;

    fn mul(self, rhs: f32) -> Spectrum {
        Spectrum::rgb(self.r * rhs, self.g * rhs, self.b * rhs)
    }
}

impl Mul<Spectrum> for f32 {
    type Output = Spectrum;

    fn mul(self, rhs: Spectrum) -> Spectrum {
        Spectrum::rgb(self * rhs.r, self * rhs.g, self * rhs.b)
    }
}

impl Div<f32> for Spectrum {
    type Output = Spectrum;

    fn div(self, rhs: f32) -> Spectrum {
        Spectrum::rgb(self.r / rhs, self.g / rhs, self.b / rhs)
    }
}

impl Index<usize> for Spectrum {
    type Output = f32;
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index(&self, i: usize) -> &f32 {
        match i {
            0 => &self.r,
            1 => &self.g,
            2 => &self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}

impl IndexMut<usize> for Spectrum {
    /// Access the channels by index
    ///
    /// - 0 = r
    /// - 1 = g
    /// - 2 = b
    fn index_mut(&mut self, i: usize) -> &mut f32 {
        match i {
            0 => &mut self.r,
            1 => &mut self.g,
            2 => &mut self.b,
            _ => panic!("Invalid index into color"),
        }
    }
}

impl Zero for Spectrum {
    fn zero() -> Spectrum {
        Spectrum::black()
    }

    fn is_zero(&self) -> bool {
        self.is_black()
    }
}

impl One for Spectrum {
    fn one() -> Spectrum {
        Spectrum::white()
    }
}

impl fmt::Display for Spectrum {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[ {}, {}, {} ]", self.r, self.g, self.b)
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// No-op module to permit compiling token HID support for Android, where
// no results are returned.

#![allow(dead_code)]

use util::OnceCallback;

pub struct PlatformManager {}

impl PlatformManager {
    pub fn new() -> Self {
        Self {}
    }

    pub fn register(
        &mut self,
        timeout: u64,
        challenge: Vec<u8>,
        application: Vec<u8>,
        key_handles: Vec<Vec<u8>>,
        callback: OnceCallback<Vec<u8>>,
    ) {
        // No-op on Android
    }

    pub fn sign(
        &mut self,
        timeout: u64,
        challenge: Vec<u8>,
        application: Vec<u8>,
        key_handles: Vec<Vec<u8>>,
        callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
    ) {
        // No-op on Android
    }

    // This blocks.
    pub fn cancel(&mut self) {
        // No-op on Android
    }
}
<commit_msg>Let stubs fail, instead of running until cancellation<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// No-op module to permit compiling token HID support for Android, where
// no results are returned.

#![allow(dead_code)]

use util::{io_err, OnceCallback};

pub struct PlatformManager {}

impl PlatformManager {
    pub fn new() -> Self {
        Self {}
    }

    pub fn register(
        &mut self,
        timeout: u64,
        challenge: Vec<u8>,
        application: Vec<u8>,
        key_handles: Vec<Vec<u8>>,
        callback: OnceCallback<Vec<u8>>,
    ) {
        // Not implemented.
        callback.call(Err(io_err("not implemented")));
    }

    pub fn sign(
        &mut self,
        timeout: u64,
        challenge: Vec<u8>,
        application: Vec<u8>,
        key_handles: Vec<Vec<u8>>,
        callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
    ) {
        // Not implemented.
        callback.call(Err(io_err("not implemented")));
    }

    pub fn cancel(&mut self) {
        // No-op.
    }
}
<|endoftext|>


<commit_before>pub use libc::dev_t;
pub use libc::stat as FileStat;

use {Errno, Result, NixPath};
use libc::mode_t;
use std::mem;
use std::os::unix::io::RawFd;

mod ffi {
    use libc::{c_char, c_int, mode_t, dev_t};
    pub use libc::{stat, fstat, lstat};

    extern {
        pub fn mknod(pathname: *const c_char, mode: mode_t, dev: dev_t) -> c_int;
        pub fn umask(mask: mode_t) -> mode_t;
    }
}

bitflags!(
    flags SFlag: mode_t {
        const S_IFIFO  = 0o010000,
        const S_IFCHR  = 0o020000,
        const S_IFDIR  = 0o040000,
        const S_IFBLK  = 0o060000,
        const S_IFREG  = 0o100000,
        const S_IFLNK  = 0o120000,
        const S_IFSOCK = 0o140000,
        const S_IFMT   = 0o170000
    }
);

bitflags! {
    flags Mode: mode_t {
        const S_IRWXU = 0o0700,
        const S_IRUSR = 0o0400,
        const S_IWUSR = 0o0200,
        const S_IXUSR = 0o0100,

        const S_IRWXG = 0o0070,
        const S_IRGRP = 0o0040,
        const S_IWGRP = 0o0020,
        const S_IXGRP = 0o0010,

        const S_IRWXO = 0o0007,
        const S_IROTH = 0o0004,
        const S_IWOTH = 0o0002,
        const S_IXOTH = 0o0001,

        const S_ISUID = 0o4000,
        const S_ISGID = 0o2000,
        const S_ISVTX = 0o1000,
    }
}

pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
        }
    }));

    Errno::result(res).map(drop)
}

#[cfg(target_os = "linux")]
const MINORBITS: usize = 20;

#[cfg(target_os = "linux")]
pub fn mkdev(major: u64, minor: u64) -> dev_t {
    (major << MINORBITS) | minor
}

pub fn umask(mode: Mode) -> Mode {
    let prev = unsafe { ffi::umask(mode.bits() as mode_t) };
    Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode")
}

pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::stat(cstr.as_ptr(), &mut dst as *mut FileStat)
        }
    }));

    try!(Errno::result(res));

    Ok(dst)
}

pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::lstat(cstr.as_ptr(), &mut dst as *mut FileStat)
        }
    }));

    try!(Errno::result(res));

    Ok(dst)
}

pub fn fstat(fd: RawFd) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = unsafe { ffi::fstat(fd, &mut dst as *mut FileStat) };

    try!(Errno::result(res));

    Ok(dst)
}
<commit_msg>Use constants from libc<commit_after>pub use libc::dev_t;
pub use libc::stat as FileStat;

use {Errno, Result, NixPath};
use libc::{self, mode_t};
use std::mem;
use std::os::unix::io::RawFd;

mod ffi {
    use libc::{c_char, c_int, mode_t, dev_t};
    pub use libc::{stat, fstat, lstat};

    extern {
        pub fn mknod(pathname: *const c_char, mode: mode_t, dev: dev_t) -> c_int;
        pub fn umask(mask: mode_t) -> mode_t;
    }
}

bitflags!(
    flags SFlag: mode_t {
        const S_IFIFO = libc::S_IFIFO,
        const S_IFCHR = libc::S_IFCHR,
        const S_IFDIR = libc::S_IFDIR,
        const S_IFBLK = libc::S_IFBLK,
        const S_IFREG = libc::S_IFREG,
        const S_IFLNK = libc::S_IFLNK,
        const S_IFSOCK = libc::S_IFSOCK,
        const S_IFMT = libc::S_IFMT,
    }
);

bitflags! {
    flags Mode: mode_t {
        const S_IRWXU = libc::S_IRWXU,
        const S_IRUSR = libc::S_IRUSR,
        const S_IWUSR = libc::S_IWUSR,
        const S_IXUSR = libc::S_IXUSR,

        const S_IRWXG = libc::S_IRWXG,
        const S_IRGRP = libc::S_IRGRP,
        const S_IWGRP = libc::S_IWGRP,
        const S_IXGRP = libc::S_IXGRP,

        const S_IRWXO = libc::S_IRWXO,
        const S_IROTH = libc::S_IROTH,
        const S_IWOTH = libc::S_IWOTH,
        const S_IXOTH = libc::S_IXOTH,

        const S_ISUID = 0o4000,
        const S_ISGID = 0o2000,
        const S_ISVTX = 0o1000,
    }
}

pub fn mknod<P: ?Sized + NixPath>(path: &P, kind: SFlag, perm: Mode, dev: dev_t) -> Result<()> {
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::mknod(cstr.as_ptr(), kind.bits | perm.bits() as mode_t, dev)
        }
    }));

    Errno::result(res).map(drop)
}

#[cfg(target_os = "linux")]
const MINORBITS: usize = 20;

#[cfg(target_os = "linux")]
pub fn mkdev(major: u64, minor: u64) -> dev_t {
    (major << MINORBITS) | minor
}

pub fn umask(mode: Mode) -> Mode {
    let prev = unsafe { ffi::umask(mode.bits() as mode_t) };
    Mode::from_bits(prev).expect("[BUG] umask returned invalid Mode")
}

pub fn stat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::stat(cstr.as_ptr(), &mut dst as *mut FileStat)
        }
    }));

    try!(Errno::result(res));

    Ok(dst)
}

pub fn lstat<P: ?Sized + NixPath>(path: &P) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = try!(path.with_nix_path(|cstr| {
        unsafe {
            ffi::lstat(cstr.as_ptr(), &mut dst as *mut FileStat)
        }
    }));

    try!(Errno::result(res));

    Ok(dst)
}

pub fn fstat(fd: RawFd) -> Result<FileStat> {
    let mut dst = unsafe { mem::uninitialized() };
    let res = unsafe { ffi::fstat(fd, &mut dst as *mut FileStat) };

    try!(Errno::result(res));

    Ok(dst)
}
<|endoftext|>


<commit_before>use std::string::ToString;

#[derive(Debug, Clone, PartialEq, Serialize)]
pub enum FrameRate {
  _24_00,
  _25_00,
  _30_00,
  _50_00,
  _60_00,
}

impl From<FrameRate> for f32 {
  fn from(fr: FrameRate) -> Self {
    match fr {
      FrameRate::_24_00 => 24.0,
      FrameRate::_25_00 => 25.0,
      FrameRate::_30_00 => 30.0,
      FrameRate::_50_00 => 50.0,
      FrameRate::_60_00 => 60.0,
    }
  }
}

#[derive(Debug, Clone, PartialEq, Serialize)]
pub struct Timecode {
  pub hours: u8,
  pub minutes: u8,
  pub seconds: u8,
  pub frame: u8,
  pub drop_frame: bool,
  pub color_frame: bool,
  frame_rate: FrameRate,
}

impl ToString for Timecode {
  fn to_string(&self) -> String {
    let separator = match self.drop_frame {
      true => ';',
      false => ':',
    };

    format!(
      "{:02}:{:02}:{:02}{}{:02}",
      self.hours, self.minutes, self.seconds, separator, self.frame
    )
  }
}

impl From<(u32, FrameRate)> for Timecode {
  fn from((frames, frame_rate): (u32, FrameRate)) -> Self {
    let fps: f32 = frame_rate.clone().into();

    let hours = frames / (60 * 60 * fps as u32);
    let minutes = frames / (60 * fps as u32) - hours * 60;
    let seconds = (frames / fps as u32) - minutes * 60 - hours * 60 * 60;
    let frame = frames
      - seconds * (fps as u32)
      - minutes * 60 * (fps as u32)
      - hours * 60 * 60 * (fps as u32);
    let drop_frame = false;
    let color_frame = false;

    log::trace!("{} {} {} {}", hours, minutes, seconds, frame);

    Timecode {
      hours: hours as u8,
      minutes: minutes as u8,
      seconds: seconds as u8,
      frame: frame as u8,
      drop_frame,
      color_frame,
      frame_rate,
    }
  }
}

impl From<&Timecode> for f64 {
  fn from(timecode: &Timecode) -> Self {
    (timecode.hours as f64) * 3600.0 + (timecode.minutes as f64) * 60.0 + (timecode.seconds as f64)
  }
}

impl Timecode {
  pub fn frame_rate(&self) -> &FrameRate {
    &self.frame_rate
  }

  pub fn parse_smpte_331m(data: &[u8], frame_rate: FrameRate) -> Option<Self> {
    if data.len() != 17 {
      return None;
    }
    match data[0] {
      0x81 => Timecode::parse_smpte_12m(&data[1..], frame_rate),
      _ => None,
    }
  }

  pub fn parse_smpte_12m(data: &[u8], frame_rate: FrameRate) -> Option<Self> {
    if data.len() < 4 {
      return None;
    }

    let mask_tens_2 = 0b0011_0000;
    let mask_tens_3 = 0b0111_0000;

    let frame = Timecode::get_number(data[0], mask_tens_2);
    let seconds = Timecode::get_number(data[1], mask_tens_3);
    let minutes = Timecode::get_number(data[2], mask_tens_3);
    let hours = Timecode::get_number(data[3], mask_tens_2);

    let color_frame = (data[0] & 0b1000_0000) != 0;
    let drop_frame = (data[0] & 0b0100_0000) != 0;

    Some(Timecode {
      hours,
      minutes,
      seconds,
      frame,
      drop_frame,
      color_frame,
      frame_rate,
    })
  }

  // used in STL format (EBU Tech 3264)
  pub fn from_ebu_smpte_time_and_control(data: &[u8; 4], frame_rate: FrameRate) -> Timecode {
    Timecode {
      hours: data[0],
      minutes: data[1],
      seconds: data[2],
      frame: data[3],
      drop_frame: false,
      color_frame: false,
      frame_rate,
    }
  }

  fn get_number(data: u8, mask_tens: u8) -> u8 {
    let mask_unit = 0x0F;

    let tens = (data & mask_tens) >> 4;
    let unit = data & mask_unit;

    (10 * tens) + unit
  }
}

#[test]
fn timecode_from_frame() {
  let timecode = Timecode::from((24 * 60 * 60 * 10, FrameRate::_24_00));
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 * 60, FrameRate::_24_00));
  assert_eq!(timecode.hours, 1);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 * 60 - 1, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 59);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((24 * 60, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 1);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 - 1, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((24, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((23, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((25, FrameRate::_25_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24, FrameRate::_25_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 24);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[10, 0, 0, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 10, 0, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 10);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 0, 10, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 10);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 0, 0, 10], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 10);
}
<commit_msg>add Deserialize trait<commit_after>use std::string::ToString;

#[derive(Debug, Deserialize, Clone, PartialEq, Serialize)]
pub enum FrameRate {
  _24_00,
  _25_00,
  _30_00,
  _50_00,
  _60_00,
}

impl From<FrameRate> for f32 {
  fn from(fr: FrameRate) -> Self {
    match fr {
      FrameRate::_24_00 => 24.0,
      FrameRate::_25_00 => 25.0,
      FrameRate::_30_00 => 30.0,
      FrameRate::_50_00 => 50.0,
      FrameRate::_60_00 => 60.0,
    }
  }
}

#[derive(Debug, Deserialize, Clone, PartialEq, Serialize)]
pub struct Timecode {
  pub hours: u8,
  pub minutes: u8,
  pub seconds: u8,
  pub frame: u8,
  pub drop_frame: bool,
  pub color_frame: bool,
  frame_rate: FrameRate,
}

impl ToString for Timecode {
  fn to_string(&self) -> String {
    let separator = match self.drop_frame {
      true => ';',
      false => ':',
    };

    format!(
      "{:02}:{:02}:{:02}{}{:02}",
      self.hours, self.minutes, self.seconds, separator, self.frame
    )
  }
}

impl From<(u32, FrameRate)> for Timecode {
  fn from((frames, frame_rate): (u32, FrameRate)) -> Self {
    let fps: f32 = frame_rate.clone().into();

    let hours = frames / (60 * 60 * fps as u32);
    let minutes = frames / (60 * fps as u32) - hours * 60;
    let seconds = (frames / fps as u32) - minutes * 60 - hours * 60 * 60;
    let frame = frames
      - seconds * (fps as u32)
      - minutes * 60 * (fps as u32)
      - hours * 60 * 60 * (fps as u32);
    let drop_frame = false;
    let color_frame = false;

    log::trace!("{} {} {} {}", hours, minutes, seconds, frame);

    Timecode {
      hours: hours as u8,
      minutes: minutes as u8,
      seconds: seconds as u8,
      frame: frame as u8,
      drop_frame,
      color_frame,
      frame_rate,
    }
  }
}

impl From<&Timecode> for f64 {
  fn from(timecode: &Timecode) -> Self {
    (timecode.hours as f64) * 3600.0 + (timecode.minutes as f64) * 60.0 + (timecode.seconds as f64)
  }
}

impl Timecode {
  pub fn frame_rate(&self) -> &FrameRate {
    &self.frame_rate
  }

  pub fn parse_smpte_331m(data: &[u8], frame_rate: FrameRate) -> Option<Self> {
    if data.len() != 17 {
      return None;
    }
    match data[0] {
      0x81 => Timecode::parse_smpte_12m(&data[1..], frame_rate),
      _ => None,
    }
  }

  pub fn parse_smpte_12m(data: &[u8], frame_rate: FrameRate) -> Option<Self> {
    if data.len() < 4 {
      return None;
    }

    let mask_tens_2 = 0b0011_0000;
    let mask_tens_3 = 0b0111_0000;

    let frame = Timecode::get_number(data[0], mask_tens_2);
    let seconds = Timecode::get_number(data[1], mask_tens_3);
    let minutes = Timecode::get_number(data[2], mask_tens_3);
    let hours = Timecode::get_number(data[3], mask_tens_2);

    let color_frame = (data[0] & 0b1000_0000) != 0;
    let drop_frame = (data[0] & 0b0100_0000) != 0;

    Some(Timecode {
      hours,
      minutes,
      seconds,
      frame,
      drop_frame,
      color_frame,
      frame_rate,
    })
  }

  // used in STL format (EBU Tech 3264)
  pub fn from_ebu_smpte_time_and_control(data: &[u8; 4], frame_rate: FrameRate) -> Timecode {
    Timecode {
      hours: data[0],
      minutes: data[1],
      seconds: data[2],
      frame: data[3],
      drop_frame: false,
      color_frame: false,
      frame_rate,
    }
  }

  fn get_number(data: u8, mask_tens: u8) -> u8 {
    let mask_unit = 0x0F;

    let tens = (data & mask_tens) >> 4;
    let unit = data & mask_unit;

    (10 * tens) + unit
  }
}

#[test]
fn timecode_from_frame() {
  let timecode = Timecode::from((24 * 60 * 60 * 10, FrameRate::_24_00));
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 * 60, FrameRate::_24_00));
  assert_eq!(timecode.hours, 1);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 * 60 - 1, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 59);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((24 * 60, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 1);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24 * 60 - 1, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 59);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((24, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((23, FrameRate::_24_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 23);

  let timecode = Timecode::from((25, FrameRate::_25_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 1);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from((24, FrameRate::_25_00));
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 24);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[10, 0, 0, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 10);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 10, 0, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 10);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 0, 10, 0], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 10);
  assert_eq!(timecode.frame, 0);

  let timecode = Timecode::from_ebu_smpte_time_and_control(&[0, 0, 0, 10], FrameRate::_25_00);
  assert_eq!(timecode.hours, 0);
  assert_eq!(timecode.minutes, 0);
  assert_eq!(timecode.seconds, 0);
  assert_eq!(timecode.frame, 10);
}
<|endoftext|>


<commit_before>//! # TreeView Sample
//!
//! This sample demonstrates how to create a TreeView with either a ListStore or TreeStore.

extern crate glib;
extern crate gtk;

use gtk::traits::*;
use gtk::signal::Inhibit;

fn append_text_column(tree: &gtk::TreeView) {
    let column = gtk::TreeViewColumn::new().unwrap();
    let cell = gtk::CellRendererText::new().unwrap();

    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    tree.append_column(&column);
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = gtk::Window::new(gtk::WindowType::Toplevel).unwrap();

    window.set_title("TreeView Sample");
    window.set_window_position(gtk::WindowPosition::Center);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    // test Value

    let hello = String::from("Hello world !");
    let mut value = glib::Value::new();

    value.init(glib::Type::String);
    value.set(&hello);
    println!("gvalue.get example : {}", value.get::<String>());

    // left pane

    let left_tree = gtk::TreeView::new().unwrap();
    let column_types = [glib::Type::String];
    let left_store = gtk::ListStore::new(&column_types).unwrap();
    let left_model = left_store.get_model().unwrap();

    left_tree.set_model(&left_model);
    left_tree.set_headers_visible(false);
    append_text_column(&left_tree);

    // print out when a row is selected

    let left_selection = left_tree.get_selection().unwrap();
    let left_model1 = left_model.clone();
    left_selection.connect_changed(move |tree_selection| {
        let mut iter = gtk::TreeIter::new();
        tree_selection.get_selected(&left_model1, &mut iter);
        if let Some(path) = left_model1.get_path(&iter) {
            println!("selected row {}", path.to_string().unwrap());
        }
    });

    for _ in 0..10 {
        let mut iter = gtk::TreeIter::new();
        left_store.append(&mut iter);
        left_store.set_string(&iter, 0, "I'm in a list");

        // select this row as a test

        if let Some(path) = left_model.get_path(&iter) {
            left_selection.select_path(&path);
        }
    }

    // right pane

    let right_tree = gtk::TreeView::new().unwrap();
    let column_types = [glib::Type::String];
    let right_store = gtk::TreeStore::new(&column_types).unwrap();
    let right_model = right_store.get_model().unwrap();

    right_tree.set_model(&right_model);
    right_tree.set_headers_visible(false);
    append_text_column(&right_tree);

    for _ in 0..10 {
        let mut iter = gtk::TreeIter::new();

        right_store.append(&mut iter, None);
        right_store.set_value(&iter, 0, &value);

        let mut child_iter = gtk::TreeIter::new();

        right_store.append(&mut child_iter, Some(&iter));
        right_store.set_string(&child_iter, 0, "I'm a child node");
    }

    // display the panes

    let split_pane = gtk::Box::new(gtk::Orientation::Horizontal, 10).unwrap();

    split_pane.set_size_request(-1, -1);
    split_pane.add(&left_tree);
    split_pane.add(&right_tree);

    window.add(&split_pane);
    window.show_all();
    gtk::main();
}
<commit_msg>Fix TreeIter breakage<commit_after>//! # TreeView Sample
//!
//! This sample demonstrates how to create a TreeView with either a ListStore or TreeStore.

extern crate glib;
extern crate gtk;

use gtk::traits::*;
use gtk::signal::Inhibit;

fn append_text_column(tree: &gtk::TreeView) {
    let column = gtk::TreeViewColumn::new().unwrap();
    let cell = gtk::CellRendererText::new().unwrap();

    column.pack_start(&cell, true);
    column.add_attribute(&cell, "text", 0);
    tree.append_column(&column);
}

fn main() {
    if gtk::init().is_err() {
        println!("Failed to initialize GTK.");
        return;
    }

    let window = gtk::Window::new(gtk::WindowType::Toplevel).unwrap();

    window.set_title("TreeView Sample");
    window.set_window_position(gtk::WindowPosition::Center);

    window.connect_delete_event(|_, _| {
        gtk::main_quit();
        Inhibit(false)
    });

    // test Value

    let hello = String::from("Hello world !");
    let mut value = glib::Value::new();

    value.init(glib::Type::String);
    value.set(&hello);
    println!("gvalue.get example : {}", value.get::<String>());

    // left pane

    let left_tree = gtk::TreeView::new().unwrap();
    let column_types = [glib::Type::String];
    let left_store = gtk::ListStore::new(&column_types).unwrap();
    let left_model = left_store.get_model().unwrap();

    left_tree.set_model(&left_model);
    left_tree.set_headers_visible(false);
    append_text_column(&left_tree);

    // print out when a row is selected

    let left_selection = left_tree.get_selection().unwrap();
    left_selection.connect_changed(|tree_selection| {
        let (left_model, iter) = tree_selection.get_selected().unwrap();
        if let Some(path) = left_model.get_path(&iter) {
            println!("selected row {}", path.to_string().unwrap());
        }
    });

    for _ in 0..10 {
        let iter = left_store.append();
        left_store.set_string(&iter, 0, "I'm in a list");

        // select this row as a test

        if let Some(path) = left_model.get_path(&iter) {
            left_selection.select_path(&path);
        }
    }

    // right pane

    let right_tree = gtk::TreeView::new().unwrap();
    let column_types = [glib::Type::String];
    let right_store = gtk::TreeStore::new(&column_types).unwrap();
    let right_model = right_store.get_model().unwrap();

    right_tree.set_model(&right_model);
    right_tree.set_headers_visible(false);
    append_text_column(&right_tree);

    for i in 0..10 {
        let iter = right_store.append(None);
        right_store.set_value(&iter, 0, &value);

        for _ in 0..i {
            let child_iter = right_store.append(Some(&iter));
            right_store.set_string(&child_iter, 0, "I'm a child node");
        }
    }

    // display the panes

    let split_pane = gtk::Box::new(gtk::Orientation::Horizontal, 10).unwrap();

    split_pane.set_size_request(-1, -1);
    split_pane.add(&left_tree);
    split_pane.add(&right_tree);

    window.add(&split_pane);
    window.show_all();
    gtk::main();
}
<|endoftext|>


<commit_before>use volatile::Into;

#[derive(Copy)]
#[repr(C)]
pub struct Register(u32);

impl Into<Register> for u8 {
    fn convert_into(self) -> Register {
        Register(self as u32)
    }
}
<commit_msg>feat(usart): expose the contents of the DR register<commit_after>use volatile::Into;

#[derive(Copy)]
#[repr(C)]
pub struct Register(u32);

impl Register {
    /// Returns the lower byte of the register
    pub fn u8(&self) -> u8 {
        self.0 as u8
    }
}

impl Into<Register> for u8 {
    fn convert_into(self) -> Register {
        Register(self as u32)
    }
}
<|endoftext|>


<commit_before>pub enum Operator {
    And,
    Or
}

impl Operator {
    pub fn to_sql(&self) -> &str {
        match *self {
            Operator::And => "AND",
            Operator::Or => "OR"
        }
    }
}

trait ToSQL {
    fn to_sql(&self) -> String;
}

struct Where<'a, T: 'a + ?Sized> {
    pub operator: Operator,
    pub clause: &'a [&'a T]
}

impl<'a> ToSQL for &'a str {
    fn to_sql(&self) -> String {
        self.to_string()
    }
}

impl<'a, T: ToSQL> ToSQL for Where<'a, T> {
    fn to_sql(&self) -> String {
        let operator = &format!(" {} ", self.operator.to_sql());
        let mut rv = String::new();
        rv.push('(');
        rv.push_str(&self.clause.into_iter()
                    .map(|x| x.to_sql())
                    .collect::<Vec<_>>()
                    .join(operator));
        rv.push(')');
        rv
    }
}

#[cfg(test)]
mod tests {
    use super::{Operator, ToSQL, Where};

    #[test]
    fn test_operator() {
        let and = Operator::And;
        let or = Operator::Or;

        assert_eq!(and.to_sql(), "AND");
        assert_eq!(or.to_sql(), "OR");
    }

    #[test]
    fn test_alone_where() {
        let foo = Where {
            operator: Operator::And,
            clause: &["foo=bar", "fizz=bazz"]
        };
        assert_eq!(&foo.to_sql(), "(foo=bar AND fizz=bazz")
    }
}
<commit_msg>Fixed some errors<commit_after>pub enum Operator {
    And,
    Or
}

impl Operator {
    pub fn to_sql(&self) -> &str {
        match *self {
            Operator::And => "AND",
            Operator::Or => "OR"
        }
    }
}

trait ToSQL {
    fn to_sql(&self) -> String;
}

struct Where<'a, T: 'a + ?Sized> {
    pub operator: Operator,
    pub clause: &'a [&'a T]
}

impl ToSQL for str {
    fn to_sql(&self) -> String {
        self.to_string()
    }
}

impl<'a, T: ToSQL + ?Sized> ToSQL for Where<'a, T> {
    fn to_sql(&self) -> String {
        let operator = &format!(" {} ", self.operator.to_sql());
        let mut rv = String::new();
        rv.push('(');
        rv.push_str(&self.clause.into_iter()
                    .map(|x| x.to_sql())
                    .collect::<Vec<_>>()
                    .join(operator));
        rv.push(')');
        rv
    }
}

#[cfg(test)]
mod tests {
    use super::{Operator, ToSQL, Where};

    #[test]
    fn test_operator() {
        let and = Operator::And;
        let or = Operator::Or;

        assert_eq!(and.to_sql(), "AND");
        assert_eq!(or.to_sql(), "OR");
    }

    #[test]
    fn test_alone_where() {
        let foo = Where {
            operator: Operator::And,
            clause: &["foo=bar", "fizz=bazz"]
        };
        assert_eq!(foo.to_sql(), "(foo=bar AND fizz=bazz".to_string())
    }
}
<|endoftext|>