<commit_before>pub mod nintendo_gallery {
    pub const GREAT_SEA: &'static str = "figureA";
    pub const WINDFALL_ISLAND: &'static str = "figureB";
    pub const OUTSET_ISLAND: &'static str = "figureC";
    pub const FORSAKEN_FORTRESS: &'static str = "figureD";
    pub const SECRET_CAVERN: &'static str = "figureE";
    pub const DRAGON_ROOST_ISLAND: &'static str = "figureF";
    pub const FOREST_HAVEN: &'static str = "figureG";
    pub const MAIN_ROOM: &'static str = "Pfigure";
}

pub mod savage_labyrinth {
    pub const ENTRANCE: &'static str = "Cave09";
    pub const ROOM11: &'static str = "Cave10";
    pub const ROOM32: &'static str = "Cave11";
    pub const END: &'static str = "Cave06";
}

pub mod dev {
    pub const INVISIBLE_ISLAND: &'static str = "A_nami";
    pub const E3_FOREST: &'static str = "A_R00";
    pub const AMOS_T: &'static str = "Amos_T";
    pub const WIND_TEMPLE: &'static str = "Cave08";
    pub const OUTSET_ISLAND: &'static str = "DmSpot0";
    pub const E3_BOATING_COURSE: &'static str = "E3ROOP";
    pub const ISLAND_WITH_HOUSE: &'static str = "Ebesso";
    pub const PIG_CHAMBER: &'static str = "H_test";
    pub const FIRE_CAVERN_WITH_SWITCHES: &'static str = "ITest61";
    pub const ICE_RING_ISLE_CAVERN: &'static str = "ITest62";
    pub const FIRE_MOUNTAIN_CAVERN: &'static str = "I_SubAN";
    pub const BASIC_ACTIONS: &'static str = "I_TestM";
    pub const ROPE_ROOM: &'static str = "I_TestR";
    pub const BRIDGE_ROOM: &'static str = "KATA_HB";
    pub const LARGE_EMPTY_ROOM: &'static str = "KATA_RM";
    pub const FIRE_MOUNTAIN: &'static str = "kazan";
    pub const K_TEST2: &'static str = "K_Test2";
    pub const K_TEST3: &'static str = "K_Test3";
    pub const K_TEST4: &'static str = "K_Test4";
    pub const K_TEST5: &'static str = "K_Test5";
    pub const K_TEST6: &'static str = "K_Test6";
    pub const K_TEST8: &'static str = "K_Test8";
    pub const K_TEST9: &'static str = "K_Test9";
    pub const K_TESTA: &'static str = "K_Testa";
    pub const K_TESTB: &'static str = "K_Testb";
    pub const K_TESTC: &'static str = "K_Testc";
    pub const K_TESTD: &'static str = "K_Testd";
    pub const K_TESTE: &'static str = "K_Teste";
    pub const CAMERA_TEST: &'static str = "morocam";
    pub const SMOKE_TEST_ROOM: &'static str = "Msmoke";
    pub const HEADSTONE_ISLAND: &'static str = "Mukao";
    pub const EARLY_PIRATE_SHIP: &'static str = "Obshop";
    pub const DEV_ENDING: &'static str = "ENDumi";
    pub const ORCAS_ROOM: &'static str = "Ojhous2";
    pub const GHOST_SHIP_1: &'static str = "PShip2";
    pub const GHOST_SHIP_2: &'static str = "PShip3";
    pub const GHOST_SHIP_3: &'static str = "SubD45";
    pub const SHIP_CONTROL_TEST: &'static str = "sea_E";
    pub const STONE_WATCHER_ISLAND_CAVERN: &'static str = "SubD44";
    pub const BOMB_ISLAND_CAVERN: &'static str = "SubD51";
    pub const DECORATIVE_PEDESTALS: &'static str = "TEST";
    pub const DARK_CAVERN_WITH_SWITCHES: &'static str = "TF_05";
    pub const GROTTO_WITH_DARKNUTS: &'static str = "TF_07";
    pub const TINGLES_ROOM: &'static str = "tincle";
    pub const BASIC_ISLAND: &'static str = "VrTest";
}

pub mod great_fairy {
    pub const NORTH: &'static str = "Fairy01";
    pub const EAST: &'static str = "Fairy02";
    pub const WEST: &'static str = "Fairy03";
    pub const FOREST_OF_FAIRIES: &'static str = "Fairy04";
    pub const THORNED: &'static str = "Fairy05";
    pub const SOUTH: &'static str = "Fairy06";
}

pub mod ganons_tower {
    pub const ENTRANCE: &'static str = "GanonA";
    pub const ROOM_TOWARDS_GOHMA: &'static str = "GanonB";
    pub const ROOM_TOWARDS_MOLGERA: &'static str = "GanonC";
    pub const ROOM_TOWARDS_KALLE_DEMOS: &'static str = "GanonD";
    pub const ROOM_TOWARDS_JALHALLA: &'static str = "GanonE";
    pub const PHANTOM_GANONS_MAZE: &'static str = "GanonJ";
    pub const PUPPET_GANON: &'static str = "GanonK";
    pub const STAIRCASE_TOWARDS_PUPPET_GANON: &'static str = "GanonL";
    pub const MAIN_ROOM: &'static str = "GanonM";
    pub const STAIRCASE_TO_MAIN_ROOM: &'static str = "GanonN";
    pub const TOWER: &'static str = "GTower";
    pub const GOHMA: &'static str = "Xboss0";
    pub const KALLE_DEMOS: &'static str = "Xboss1";
    pub const JALHALLA: &'static str = "Xboss2";
    pub const MOLGERA: &'static str = "Xboss3";
}

pub mod hyrule {
    pub const CASTLE: &'static str = "Hyroom";
    pub const FIELD: &'static str = "Hyrule";
    pub const MASTER_SWORD_CHAMBER: &'static str = "kenroom";
}

pub mod cavern {
    pub const BOMB_ISLAND: &'static str = "Cave01";
    pub const STAR_ISLAND: &'static str = "Cave02";
    pub const CLIFF_PLATEAU_ISLES: &'static str = "Cave03";
    pub const ROCK_SPIRE_ISLE: &'static str = "Cave04";
    pub const HORSESHOE_ISLAND: &'static str = "Cave05";
    pub const PAWPRINT_ISLE_WIZZROBE: &'static str = "Cave07";
    pub const SHARK_ISLAND: &'static str = "ITest63";
    pub const ICE_RING_ISLE: &'static str = "MiniHyo";
    pub const FIRE_MOUNTAIN: &'static str = "MiniKaz";
    pub const NEEDLE_ROCK_ISLE: &'static str = "SubD42";
    pub const ANGULAR_ISLES: &'static str = "SubD43";
    pub const BOATING_COURSE: &'static str = "SubD71";
    pub const STONE_WATCHER_ISLAND: &'static str = "TF_01";
    pub const OVERLOOK_ISLAND: &'static str = "TF_02";
    pub const BIRDS_PEAK_ROCK: &'static str = "TF_03";
    pub const CABANA: &'static str = "TF_04";
    pub const DRAGON_ROOST_ISLAND: &'static str = "TF_06";
    pub const PAWPRINT_ISLE_CHUCHU: &'static str = "TyuTyu";
    pub const DIAMOND_STEPPE_ISLAND: &'static str = "WarpD";
}

pub mod windfall {
    pub const GAME_ROOM: &'static str = "Kaisen";
    pub const SCHOOL_OF_JOY: &'static str = "Nitiyou";
    pub const BOMB_SHOP: &'static str = "Obombh";
    pub const LENZOS_HOUSE: &'static str = "Ocmera";
    pub const CAFE_BAR: &'static str = "Opub";
    pub const HOUSE_OF_WEALTH: &'static str = "Orichh";
    pub const CHU_JELLY_JUICE_SHOP: &'static str = "Pdrgsh";
    pub const JAIL: &'static str = "Pnezumi";
}

pub mod earth_temple {
    pub const ENTRANCE: &'static str = "Edaichi";
    pub const TEMPLE: &'static str = "M_Dai";
    pub const BOSS: &'static str = "M_DaiB";
    pub const MINI_BOSS: &'static str = "M_DaiMB";
}

pub mod wind_temple {
    pub const ENTRANCE: &'static str = "Ekaze";
    pub const TEMPLE: &'static str = "kaze";
    pub const BOSS: &'static str = "kazeB";
    pub const MINI_BOSS: &'static str = "kazeMB";
}

pub mod forbidden_woods {
    pub const BOSS: &'static str = "kinBOSS";
    pub const DUNGEON: &'static str = "kindan";
    pub const MINI_BOSS: &'static str = "kinMB";
}

pub mod outset {
    pub const LINKS_HOUSE: &'static str = "LinkRM";
    pub const UNDER_LINKS_HOUSE: &'static str = "LinkUG";
    pub const FOREST_OF_FAIRIES: &'static str = "A_mori";
    pub const ORCAS_ROOM: &'static str = "Ojhous";
    pub const MESAS_HOUSE: &'static str = "Omasao";
    pub const ABE_AND_ROSES_HOUSE: &'static str = "Onobuta";
    pub const JABUNS_ROOM: &'static str = "Pjavdou";
}

pub mod forsaken_fortress {
    pub const GANONDORFS_ROOM: &'static str = "M2ganon";
    pub const FF1_TOWER: &'static str = "Mjtower";
    pub const FF2_TOWER: &'static str = "M2tower";
    pub const FF1_INTERIOR: &'static str = "majroom";
    pub const FF2_INTERIOR: &'static str = "ma2room";
    pub const FF3_INTERIOR: &'static str = "ma3room";
    pub const FF1: &'static str = "MajyuE";
}

pub mod dragon_roost_cavern {
    pub const DUNGEON: &'static str = "M_NewD2";
    pub const BOSS: &'static str = "M_DragB";
    pub const MINI_BOSS: &'static str = "M_Dra09";
}

pub mod dragon_roost_island {
    pub const POND: &'static str = "Adanmae";
    pub const KOMALIS_ROOM: &'static str = "Comori";
    pub const POSTAL_SERVICE: &'static str = "Atorizk";
}

pub mod forest_haven {
    pub const POTION_ROOM: &'static str = "Ocrogh";
    pub const FOREST_HAVEN: &'static str = "Omori";
    pub const MAKARS_HIDING_PLACE: &'static str = "Otkura";
}

pub mod sea {
    pub const SEA: &'static str = "sea";
    pub const TETRAS_SHIP_INSIDE: &'static str = "Asoko";
    pub const TETRAS_SHIP_OUTSIDE: &'static str = "A_umikz";
    pub const SUBMARINE_FIVE_STAR_ISLES: &'static str = "Abship";
    pub const CABANA: &'static str = "Abesso";
    pub const BOATING_COURSE: &'static str = "Ocean";
    pub const GHOST_SHIP: &'static str = "PShip";
    pub const ISLET_OF_STEEL: &'static str = "ShipD";
}

pub mod other {
    pub const NAME_SELECT: &'static str = "Name";
    pub const ENDING: &'static str = "ENDING";
    pub const TITLE_SCREEN: &'static str = "sea_T";
}

pub mod tower_of_the_gods {
    pub const DUNGEON: &'static str = "Siren";
    pub const BOSS: &'static str = "SirenB";
    pub const MINI_BOSS: &'static str = "SirenMB";
    pub const OUTSIDE: &'static str = "ADMumi";
}
<commit_msg>Fix constant for Beedle's Shop Ship<commit_after>pub mod nintendo_gallery {
    pub const GREAT_SEA: &'static str = "figureA";
    pub const WINDFALL_ISLAND: &'static str = "figureB";
    pub const OUTSET_ISLAND: &'static str = "figureC";
    pub const FORSAKEN_FORTRESS: &'static str = "figureD";
    pub const SECRET_CAVERN: &'static str = "figureE";
    pub const DRAGON_ROOST_ISLAND: &'static str = "figureF";
    pub const FOREST_HAVEN: &'static str = "figureG";
    pub const MAIN_ROOM: &'static str = "Pfigure";
}

pub mod savage_labyrinth {
    pub const ENTRANCE: &'static str = "Cave09";
    pub const ROOM11: &'static str = "Cave10";
    pub const ROOM32: &'static str = "Cave11";
    pub const END: &'static str = "Cave06";
}

pub mod dev {
    pub const INVISIBLE_ISLAND: &'static str = "A_nami";
    pub const E3_FOREST: &'static str = "A_R00";
    pub const AMOS_T: &'static str = "Amos_T";
    pub const WIND_TEMPLE: &'static str = "Cave08";
    pub const OUTSET_ISLAND: &'static str = "DmSpot0";
    pub const E3_BOATING_COURSE: &'static str = "E3ROOP";
    pub const ISLAND_WITH_HOUSE: &'static str = "Ebesso";
    pub const PIG_CHAMBER: &'static str = "H_test";
    pub const FIRE_CAVERN_WITH_SWITCHES: &'static str = "ITest61";
    pub const ICE_RING_ISLE_CAVERN: &'static str = "ITest62";
    pub const FIRE_MOUNTAIN_CAVERN: &'static str = "I_SubAN";
    pub const BASIC_ACTIONS: &'static str = "I_TestM";
    pub const ROPE_ROOM: &'static str = "I_TestR";
    pub const BRIDGE_ROOM: &'static str = "KATA_HB";
    pub const LARGE_EMPTY_ROOM: &'static str = "KATA_RM";
    pub const FIRE_MOUNTAIN: &'static str = "kazan";
    pub const K_TEST2: &'static str = "K_Test2";
    pub const K_TEST3: &'static str = "K_Test3";
    pub const K_TEST4: &'static str = "K_Test4";
    pub const K_TEST5: &'static str = "K_Test5";
    pub const K_TEST6: &'static str = "K_Test6";
    pub const K_TEST8: &'static str = "K_Test8";
    pub const K_TEST9: &'static str = "K_Test9";
    pub const K_TESTA: &'static str = "K_Testa";
    pub const K_TESTB: &'static str = "K_Testb";
    pub const K_TESTC: &'static str = "K_Testc";
    pub const K_TESTD: &'static str = "K_Testd";
    pub const K_TESTE: &'static str = "K_Teste";
    pub const CAMERA_TEST: &'static str = "morocam";
    pub const SMOKE_TEST_ROOM: &'static str = "Msmoke";
    pub const HEADSTONE_ISLAND: &'static str = "Mukao";
    pub const DEV_ENDING: &'static str = "ENDumi";
    pub const ORCAS_ROOM: &'static str = "Ojhous2";
    pub const GHOST_SHIP_1: &'static str = "PShip2";
    pub const GHOST_SHIP_2: &'static str = "PShip3";
    pub const GHOST_SHIP_3: &'static str = "SubD45";
    pub const SHIP_CONTROL_TEST: &'static str = "sea_E";
    pub const STONE_WATCHER_ISLAND_CAVERN: &'static str = "SubD44";
    pub const BOMB_ISLAND_CAVERN: &'static str = "SubD51";
    pub const DECORATIVE_PEDESTALS: &'static str = "TEST";
    pub const DARK_CAVERN_WITH_SWITCHES: &'static str = "TF_05";
    pub const GROTTO_WITH_DARKNUTS: &'static str = "TF_07";
    pub const TINGLES_ROOM: &'static str = "tincle";
    pub const BASIC_ISLAND: &'static str = "VrTest";
}

pub mod great_fairy {
    pub const NORTH: &'static str = "Fairy01";
    pub const EAST: &'static str = "Fairy02";
    pub const WEST: &'static str = "Fairy03";
    pub const FOREST_OF_FAIRIES: &'static str = "Fairy04";
    pub const THORNED: &'static str = "Fairy05";
    pub const SOUTH: &'static str = "Fairy06";
}

pub mod ganons_tower {
    pub const ENTRANCE: &'static str = "GanonA";
    pub const ROOM_TOWARDS_GOHMA: &'static str = "GanonB";
    pub const ROOM_TOWARDS_MOLGERA: &'static str = "GanonC";
    pub const ROOM_TOWARDS_KALLE_DEMOS: &'static str = "GanonD";
    pub const ROOM_TOWARDS_JALHALLA: &'static str = "GanonE";
    pub const PHANTOM_GANONS_MAZE: &'static str = "GanonJ";
    pub const PUPPET_GANON: &'static str = "GanonK";
    pub const STAIRCASE_TOWARDS_PUPPET_GANON: &'static str = "GanonL";
    pub const MAIN_ROOM: &'static str = "GanonM";
    pub const STAIRCASE_TO_MAIN_ROOM: &'static str = "GanonN";
    pub const TOWER: &'static str = "GTower";
    pub const GOHMA: &'static str = "Xboss0";
    pub const KALLE_DEMOS: &'static str = "Xboss1";
    pub const JALHALLA: &'static str = "Xboss2";
    pub const MOLGERA: &'static str = "Xboss3";
}

pub mod hyrule {
    pub const CASTLE: &'static str = "Hyroom";
    pub const FIELD: &'static str = "Hyrule";
    pub const MASTER_SWORD_CHAMBER: &'static str = "kenroom";
}

pub mod cavern {
    pub const BOMB_ISLAND: &'static str = "Cave01";
    pub const STAR_ISLAND: &'static str = "Cave02";
    pub const CLIFF_PLATEAU_ISLES: &'static str = "Cave03";
    pub const ROCK_SPIRE_ISLE: &'static str = "Cave04";
    pub const HORSESHOE_ISLAND: &'static str = "Cave05";
    pub const PAWPRINT_ISLE_WIZZROBE: &'static str = "Cave07";
    pub const SHARK_ISLAND: &'static str = "ITest63";
    pub const ICE_RING_ISLE: &'static str = "MiniHyo";
    pub const FIRE_MOUNTAIN: &'static str = "MiniKaz";
    pub const NEEDLE_ROCK_ISLE: &'static str = "SubD42";
    pub const ANGULAR_ISLES: &'static str = "SubD43";
    pub const BOATING_COURSE: &'static str = "SubD71";
    pub const STONE_WATCHER_ISLAND: &'static str = "TF_01";
    pub const OVERLOOK_ISLAND: &'static str = "TF_02";
    pub const BIRDS_PEAK_ROCK: &'static str = "TF_03";
    pub const CABANA: &'static str = "TF_04";
    pub const DRAGON_ROOST_ISLAND: &'static str = "TF_06";
    pub const PAWPRINT_ISLE_CHUCHU: &'static str = "TyuTyu";
    pub const DIAMOND_STEPPE_ISLAND: &'static str = "WarpD";
}

pub mod windfall {
    pub const GAME_ROOM: &'static str = "Kaisen";
    pub const SCHOOL_OF_JOY: &'static str = "Nitiyou";
    pub const BOMB_SHOP: &'static str = "Obombh";
    pub const LENZOS_HOUSE: &'static str = "Ocmera";
    pub const CAFE_BAR: &'static str = "Opub";
    pub const HOUSE_OF_WEALTH: &'static str = "Orichh";
    pub const CHU_JELLY_JUICE_SHOP: &'static str = "Pdrgsh";
    pub const JAIL: &'static str = "Pnezumi";
}

pub mod earth_temple {
    pub const ENTRANCE: &'static str = "Edaichi";
    pub const TEMPLE: &'static str = "M_Dai";
    pub const BOSS: &'static str = "M_DaiB";
    pub const MINI_BOSS: &'static str = "M_DaiMB";
}

pub mod wind_temple {
    pub const ENTRANCE: &'static str = "Ekaze";
    pub const TEMPLE: &'static str = "kaze";
    pub const BOSS: &'static str = "kazeB";
    pub const MINI_BOSS: &'static str = "kazeMB";
}

pub mod forbidden_woods {
    pub const BOSS: &'static str = "kinBOSS";
    pub const DUNGEON: &'static str = "kindan";
    pub const MINI_BOSS: &'static str = "kinMB";
}

pub mod outset {
    pub const LINKS_HOUSE: &'static str = "LinkRM";
    pub const UNDER_LINKS_HOUSE: &'static str = "LinkUG";
    pub const FOREST_OF_FAIRIES: &'static str = "A_mori";
    pub const ORCAS_ROOM: &'static str = "Ojhous";
    pub const MESAS_HOUSE: &'static str = "Omasao";
    pub const ABE_AND_ROSES_HOUSE: &'static str = "Onobuta";
    pub const JABUNS_ROOM: &'static str = "Pjavdou";
}

pub mod forsaken_fortress {
    pub const GANONDORFS_ROOM: &'static str = "M2ganon";
    pub const FF1_TOWER: &'static str = "Mjtower";
    pub const FF2_TOWER: &'static str = "M2tower";
    pub const FF1_INTERIOR: &'static str = "majroom";
    pub const FF2_INTERIOR: &'static str = "ma2room";
    pub const FF3_INTERIOR: &'static str = "ma3room";
    pub const FF1: &'static str = "MajyuE";
}

pub mod dragon_roost_cavern {
    pub const DUNGEON: &'static str = "M_NewD2";
    pub const BOSS: &'static str = "M_DragB";
    pub const MINI_BOSS: &'static str = "M_Dra09";
}

pub mod dragon_roost_island {
    pub const POND: &'static str = "Adanmae";
    pub const KOMALIS_ROOM: &'static str = "Comori";
    pub const POSTAL_SERVICE: &'static str = "Atorizk";
}

pub mod forest_haven {
    pub const POTION_ROOM: &'static str = "Ocrogh";
    pub const FOREST_HAVEN: &'static str = "Omori";
    pub const MAKARS_HIDING_PLACE: &'static str = "Otkura";
}

pub mod sea {
    pub const SEA: &'static str = "sea";
    pub const TETRAS_SHIP_INSIDE: &'static str = "Asoko";
    pub const TETRAS_SHIP_OUTSIDE: &'static str = "A_umikz";
    pub const SUBMARINE_FIVE_STAR_ISLES: &'static str = "Abship";
    pub const CABANA: &'static str = "Abesso";
    pub const BOATING_COURSE: &'static str = "Ocean";
    pub const GHOST_SHIP: &'static str = "PShip";
    pub const ISLET_OF_STEEL: &'static str = "ShipD";
    pub const BEEDLES_SHOP_SHIP: &'static str = "Obshop";
}

pub mod other {
    pub const NAME_SELECT: &'static str = "Name";
    pub const ENDING: &'static str = "ENDING";
    pub const TITLE_SCREEN: &'static str = "sea_T";
}

pub mod tower_of_the_gods {
    pub const DUNGEON: &'static str = "Siren";
    pub const BOSS: &'static str = "SirenB";
    pub const MINI_BOSS: &'static str = "SirenMB";
    pub const OUTSIDE: &'static str = "ADMumi";
}
<|endoftext|>


<commit_before>
use canvas::CanvasId;
use color::{Color, Colorable};
use elmesque::Element;
use frame::Frameable;
use graphics::character::CharacterCache;
use label::{FontSize, Labelable};
use mouse::Mouse;
use position::{Depth, Dimensions, HorizontalAlign, Point, Position, Positionable, VerticalAlign};
use theme::Theme;
use ui::{GlyphCache, UserInput};
use widget::{self, Widget};

/// A pressable button widget whose reaction is triggered upon release.
pub struct Button<'a, F> {
    pos: Position,
    dim: Dimensions,
    maybe_h_align: Option<HorizontalAlign>,
    maybe_v_align: Option<VerticalAlign>,
    depth: Depth,
    maybe_label: Option<&'a str>,
    maybe_react: Option<F>,
    style: Style,
    enabled: bool,
    maybe_canvas_id: Option<CanvasId>,
}

/// Styling for the Button, necessary for constructing its renderable Element.
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Style {
    pub maybe_color: Option<Color>,
    pub maybe_frame: Option<f64>,
    pub maybe_frame_color: Option<Color>,
    pub maybe_label_color: Option<Color>,
    pub maybe_label_font_size: Option<u32>,
}

/// Represents the state of the Button widget.
#[derive(Clone, Debug, PartialEq)]
pub struct State {
    maybe_label: Option<String>,
    interaction: Interaction,
}

/// Represents an interaction with the Button widget.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Interaction {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Alter the widget color depending on the state.
    fn color(&self, color: Color) -> Color {
        match self.interaction {
            Interaction::Normal => color,
            Interaction::Highlighted => color.highlighted(),
            Interaction::Clicked => color.clicked(),
        }
    }
}

/// Check the current state of the button.
fn get_new_interaction(is_over: bool, prev: Interaction, mouse: Mouse) -> Interaction {
    use mouse::ButtonState::{Down, Up};
    use self::Interaction::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

impl<'a, F> Button<'a, F> {

    /// Create a button context to be built upon.
    pub fn new() -> Button<'a, F> {
        Button {
            dim: [64.0, 64.0],
            pos: Position::default(),
            maybe_h_align: None,
            maybe_v_align: None,
            depth: 0.0,
            maybe_react: None,
            maybe_label: None,
            style: Style::new(),
            enabled: true,
            maybe_canvas_id: None,
        }
    }

    /// Set the reaction for the Button. The reaction will be triggered upon release of the button.
    pub fn react(mut self, reaction: F) -> Self {
        self.maybe_react = Some(reaction);
        self
    }

    /// If true, will allow user inputs.  If false, will disallow user inputs.
    pub fn enabled(mut self, flag: bool) -> Self {
        self.enabled = flag;
        self
    }

    /// Set which Canvas to attach the Widget to. Note that you can also attach a widget to a
    /// Canvas by using the canvas placement `Positionable` methods.
    pub fn canvas(mut self, id: CanvasId) -> Self {
        self.maybe_canvas_id = Some(id);
        self
    }

}

impl<'a, F> Widget for Button<'a, F>
    where
        F: FnMut()
{
    type State = State;
    type Style = Style;
    fn unique_kind(&self) -> &'static str { "Button" }
    fn init_state(&self) -> State {
        State { maybe_label: None, interaction: Interaction::Normal }
    }
    fn style(&self) -> Style { self.style.clone() }
    fn canvas_id(&self) -> Option<CanvasId> { self.maybe_canvas_id }

    /// Update the state of the Button.
    fn update<'b, C>(mut self,
                     prev_state: &widget::State<State>,
                     xy: Point,
                     dim: Dimensions,
                     input: UserInput<'b>,
                     _style: &Style,
                     _theme: &Theme,
                     _glyph_cache: &GlyphCache<C>) -> Option<State>
        where
            C: CharacterCache,
    {
        use utils::is_over_rect;
        let widget::State { ref state, .. } = *prev_state;
        let maybe_mouse = input.maybe_mouse.map(|mouse| mouse.relative_to(xy));

        // Check whether or not a new interaction has occurred.
        let new_interaction = match (self.enabled, maybe_mouse) {
            (false, _) | (true, None) => Interaction::Normal,
            (true, Some(mouse)) => {
                let is_over = is_over_rect([0.0, 0.0], mouse.xy, dim);
                get_new_interaction(is_over, state.interaction, mouse)
            },
        };

        // If the mouse was released over button, react.
        if let (Interaction::Clicked, Interaction::Highlighted) =
            (state.interaction, new_interaction) {
            if let Some(ref mut react) = self.maybe_react { react() }
        }

        // A function for constructing a new state.
        let new_state = || {
            State {
                maybe_label: self.maybe_label.as_ref().map(|label| label.to_string()),
                interaction: new_interaction,
            }
        };

        // Check whether or not the state has changed since the previous update.
        let state_has_changed = state.interaction != new_interaction
            || state.maybe_label.as_ref().map(|string| &string[..]) != self.maybe_label;

        // Construct the new state if there was a change.
        if state_has_changed { Some(new_state()) } else { None }
    }

    /// Construct an Element from the given Button State.
    fn draw<C>(new_state: &widget::State<State>,
               style: &Style,
               theme: &Theme,
               _glyph_cache: &GlyphCache<C>) -> Element
        where
            C: CharacterCache,
    {
        use elmesque::form::{collage, rect, text};
        let widget::State { ref state, dim, xy, .. } = *new_state;

        // Retrieve the styling for the Element..
        let color = state.color(style.color(theme));
        let frame = style.frame(theme);
        let frame_color = style.frame_color(theme);

        // Construct the frame and inner rectangle forms.
        let frame_form = rect(dim[0], dim[1]).filled(frame_color);
        let (inner_w, inner_h) = (dim[0] - frame * 2.0, dim[1] - frame * 2.0);
        let pressable_form = rect(inner_w, inner_h).filled(color);

        // Construct the label's Form.
        let maybe_label_form = state.maybe_label.as_ref().map(|label_text| {
            use elmesque::text::Text;
            let label_color = style.label_color(theme);
            let size = style.label_font_size(theme);
            text(Text::from_string(label_text.to_string()).color(label_color).height(size as f64))
                .shift(xy[0].floor(), xy[1].floor())
        });

        // Construct the button's Form.
        let form_chain = Some(frame_form).into_iter()
            .chain(Some(pressable_form))
            .map(|form| form.shift(xy[0], xy[1]))
            .chain(maybe_label_form);

        // Turn the form into a renderable Element.
        collage(dim[0] as i32, dim[1] as i32, form_chain.collect())
    }

}

impl Style {

    /// Construct the default Style.
    pub fn new() -> Style {
        Style {
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }

    /// Get the Color for an Element.
    pub fn color(&self, theme: &Theme) -> Color {
        self.maybe_color.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_color.unwrap_or(theme.shape_color)
        })).unwrap_or(theme.shape_color)
    }

    /// Get the frame for an Element.
    pub fn frame(&self, theme: &Theme) -> f64 {
        self.maybe_frame.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_frame.unwrap_or(theme.frame_width)
        })).unwrap_or(theme.frame_width)
    }

    /// Get the frame Color for an Element.
    pub fn frame_color(&self, theme: &Theme) -> Color {
        self.maybe_frame_color.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_frame_color.unwrap_or(theme.frame_color)
        })).unwrap_or(theme.frame_color)
    }

    /// Get the label Color for an Element.
    pub fn label_color(&self, theme: &Theme) -> Color {
        self.maybe_label_color.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_label_color.unwrap_or(theme.label_color)
        })).unwrap_or(theme.label_color)
    }

    /// Get the label font size for an Element.
    pub fn label_font_size(&self, theme: &Theme) -> FontSize {
        self.maybe_label_font_size.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_label_font_size.unwrap_or(theme.font_size_medium)
        })).unwrap_or(theme.font_size_medium)
    }

}

impl<'a, F> Colorable for Button<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.style.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for Button<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.style.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.style.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, F> Labelable<'a> for Button<'a, F> {
    fn label(mut self, text: &'a str) -> Self {
        self.maybe_label = Some(text);
        self
    }

    fn label_color(mut self, color: Color) -> Self {
        self.style.maybe_label_color = Some(color);
        self
    }

    fn label_font_size(mut self, size: FontSize) -> Self {
        self.style.maybe_label_font_size = Some(size);
        self
    }
}

impl<'a, F> Positionable for Button<'a, F> {
    fn position(mut self, pos: Position) -> Self {
        self.pos = pos;
        self
    }
    fn get_position(&self) -> Position { self.pos }
    #[inline]
    fn horizontal_align(self, h_align: HorizontalAlign) -> Self {
        Button { maybe_h_align: Some(h_align), ..self }
    }
    #[inline]
    fn vertical_align(self, v_align: VerticalAlign) -> Self {
        Button { maybe_v_align: Some(v_align), ..self }
    }
    fn get_horizontal_align(&self, theme: &Theme) -> HorizontalAlign {
        self.maybe_h_align.unwrap_or(theme.align.horizontal)
    }
    fn get_vertical_align(&self, theme: &Theme) -> VerticalAlign {
        self.maybe_v_align.unwrap_or(theme.align.vertical)
    }
    fn depth(mut self, depth: Depth) -> Self {
        self.depth = depth;
        self
    }
    fn get_depth(&self) -> Depth { self.depth }
}

impl<'a, F> ::position::Sizeable for Button<'a, F> {
    #[inline]
    fn width(self, w: f64) -> Self {
        let h = self.dim[1];
        Button { dim: [w, h], ..self }
    }
    #[inline]
    fn height(self, h: f64) -> Self {
        let w = self.dim[0];
        Button { dim: [w, h], ..self }
    }
    fn get_width<C: CharacterCache>(&self, _theme: &Theme, _: &GlyphCache<C>) -> f64 { self.dim[0] }
    fn get_height(&self, _theme: &Theme) -> f64 { self.dim[1] }
}

<commit_msg>Moved button dimensions into its style for easier customisation<commit_after>
use canvas::CanvasId;
use color::{Color, Colorable};
use elmesque::Element;
use frame::Frameable;
use graphics::character::CharacterCache;
use graphics::math::Scalar;
use label::{FontSize, Labelable};
use mouse::Mouse;
use position::{Depth, Dimensions, HorizontalAlign, Point, Position, Positionable, VerticalAlign};
use theme::Theme;
use ui::{GlyphCache, UserInput};
use widget::{self, Widget};

/// A pressable button widget whose reaction is triggered upon release.
pub struct Button<'a, F> {
    pos: Position,
    maybe_h_align: Option<HorizontalAlign>,
    maybe_v_align: Option<VerticalAlign>,
    depth: Depth,
    maybe_label: Option<&'a str>,
    maybe_react: Option<F>,
    style: Style,
    enabled: bool,
    maybe_canvas_id: Option<CanvasId>,
}

/// Styling for the Button, necessary for constructing its renderable Element.
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Style {
    pub maybe_width: Option<Scalar>,
    pub maybe_height: Option<Scalar>,
    pub maybe_color: Option<Color>,
    pub maybe_frame: Option<f64>,
    pub maybe_frame_color: Option<Color>,
    pub maybe_label_color: Option<Color>,
    pub maybe_label_font_size: Option<u32>,
}

/// Represents the state of the Button widget.
#[derive(Clone, Debug, PartialEq)]
pub struct State {
    maybe_label: Option<String>,
    interaction: Interaction,
}

/// Represents an interaction with the Button widget.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Interaction {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Alter the widget color depending on the state.
    fn color(&self, color: Color) -> Color {
        match self.interaction {
            Interaction::Normal => color,
            Interaction::Highlighted => color.highlighted(),
            Interaction::Clicked => color.clicked(),
        }
    }
}

/// Check the current state of the button.
fn get_new_interaction(is_over: bool, prev: Interaction, mouse: Mouse) -> Interaction {
    use mouse::ButtonState::{Down, Up};
    use self::Interaction::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

impl<'a, F> Button<'a, F> {

    /// Create a button context to be built upon.
    pub fn new() -> Button<'a, F> {
        Button {
            pos: Position::default(),
            maybe_h_align: None,
            maybe_v_align: None,
            depth: 0.0,
            maybe_react: None,
            maybe_label: None,
            style: Style::new(),
            enabled: true,
            maybe_canvas_id: None,
        }
    }

    /// Set the reaction for the Button. The reaction will be triggered upon release of the button.
    pub fn react(mut self, reaction: F) -> Self {
        self.maybe_react = Some(reaction);
        self
    }

    /// If true, will allow user inputs.  If false, will disallow user inputs.
    pub fn enabled(mut self, flag: bool) -> Self {
        self.enabled = flag;
        self
    }

    /// Set which Canvas to attach the Widget to. Note that you can also attach a widget to a
    /// Canvas by using the canvas placement `Positionable` methods.
    pub fn canvas(mut self, id: CanvasId) -> Self {
        self.maybe_canvas_id = Some(id);
        self
    }

}

impl<'a, F> Widget for Button<'a, F>
    where
        F: FnMut()
{
    type State = State;
    type Style = Style;
    fn unique_kind(&self) -> &'static str { "Button" }
    fn init_state(&self) -> State {
        State { maybe_label: None, interaction: Interaction::Normal }
    }
    fn style(&self) -> Style { self.style.clone() }
    fn canvas_id(&self) -> Option<CanvasId> { self.maybe_canvas_id }

    /// Update the state of the Button.
    fn update<'b, C>(mut self,
                     prev_state: &widget::State<State>,
                     xy: Point,
                     dim: Dimensions,
                     input: UserInput<'b>,
                     _style: &Style,
                     _theme: &Theme,
                     _glyph_cache: &GlyphCache<C>) -> Option<State>
        where
            C: CharacterCache,
    {
        use utils::is_over_rect;
        let widget::State { ref state, .. } = *prev_state;
        let maybe_mouse = input.maybe_mouse.map(|mouse| mouse.relative_to(xy));

        // Check whether or not a new interaction has occurred.
        let new_interaction = match (self.enabled, maybe_mouse) {
            (false, _) | (true, None) => Interaction::Normal,
            (true, Some(mouse)) => {
                let is_over = is_over_rect([0.0, 0.0], mouse.xy, dim);
                get_new_interaction(is_over, state.interaction, mouse)
            },
        };

        // If the mouse was released over button, react.
        if let (Interaction::Clicked, Interaction::Highlighted) =
            (state.interaction, new_interaction) {
            if let Some(ref mut react) = self.maybe_react { react() }
        }

        // A function for constructing a new state.
        let new_state = || {
            State {
                maybe_label: self.maybe_label.as_ref().map(|label| label.to_string()),
                interaction: new_interaction,
            }
        };

        // Check whether or not the state has changed since the previous update.
        let state_has_changed = state.interaction != new_interaction
            || state.maybe_label.as_ref().map(|string| &string[..]) != self.maybe_label;

        // Construct the new state if there was a change.
        if state_has_changed { Some(new_state()) } else { None }
    }

    /// Construct an Element from the given Button State.
    fn draw<C>(new_state: &widget::State<State>,
               style: &Style,
               theme: &Theme,
               _glyph_cache: &GlyphCache<C>) -> Element
        where
            C: CharacterCache,
    {
        use elmesque::form::{collage, rect, text};
        let widget::State { ref state, dim, xy, .. } = *new_state;

        // Retrieve the styling for the Element..
        let color = state.color(style.color(theme));
        let frame = style.frame(theme);
        let frame_color = style.frame_color(theme);

        // Construct the frame and inner rectangle forms.
        let frame_form = rect(dim[0], dim[1]).filled(frame_color);
        let (inner_w, inner_h) = (dim[0] - frame * 2.0, dim[1] - frame * 2.0);
        let pressable_form = rect(inner_w, inner_h).filled(color);

        // Construct the label's Form.
        let maybe_label_form = state.maybe_label.as_ref().map(|label_text| {
            use elmesque::text::Text;
            let label_color = style.label_color(theme);
            let size = style.label_font_size(theme);
            text(Text::from_string(label_text.to_string()).color(label_color).height(size as f64))
                .shift(xy[0].floor(), xy[1].floor())
        });

        // Construct the button's Form.
        let form_chain = Some(frame_form).into_iter()
            .chain(Some(pressable_form))
            .map(|form| form.shift(xy[0], xy[1]))
            .chain(maybe_label_form);

        // Turn the form into a renderable Element.
        collage(dim[0] as i32, dim[1] as i32, form_chain.collect())
    }

}

impl Style {

    /// Construct the default Style.
    pub fn new() -> Style {
        Style {
            maybe_width: None,
            maybe_height: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }

    /// Get the width of the Widget.
    pub fn width(&self, theme: &Theme) -> Scalar {
        const DEFAULT_WIDTH: Scalar = 64.0;
        self.maybe_width.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_width.unwrap_or(DEFAULT_WIDTH)
        })).unwrap_or(DEFAULT_WIDTH)
    }

    /// Get the height of the Widget.
    pub fn height(&self, theme: &Theme) -> Scalar {
        const DEFAULT_HEIGHT: Scalar = 64.0;
        self.maybe_height.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_height.unwrap_or(DEFAULT_HEIGHT)
        })).unwrap_or(DEFAULT_HEIGHT)
    }

    /// Get the Color for an Element.
    pub fn color(&self, theme: &Theme) -> Color {
        self.maybe_color.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_color.unwrap_or(theme.shape_color)
        })).unwrap_or(theme.shape_color)
    }

    /// Get the frame for an Element.
    pub fn frame(&self, theme: &Theme) -> f64 {
        self.maybe_frame.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_frame.unwrap_or(theme.frame_width)
        })).unwrap_or(theme.frame_width)
    }

    /// Get the frame Color for an Element.
    pub fn frame_color(&self, theme: &Theme) -> Color {
        self.maybe_frame_color.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_frame_color.unwrap_or(theme.frame_color)
        })).unwrap_or(theme.frame_color)
    }

    /// Get the label Color for an Element.
    pub fn label_color(&self, theme: &Theme) -> Color {
        self.maybe_label_color.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_label_color.unwrap_or(theme.label_color)
        })).unwrap_or(theme.label_color)
    }

    /// Get the label font size for an Element.
    pub fn label_font_size(&self, theme: &Theme) -> FontSize {
        self.maybe_label_font_size.or(theme.maybe_button.as_ref().map(|style| {
            style.maybe_label_font_size.unwrap_or(theme.font_size_medium)
        })).unwrap_or(theme.font_size_medium)
    }

}

impl<'a, F> Colorable for Button<'a, F> {
    fn color(mut self, color: Color) -> Self {
        self.style.maybe_color = Some(color);
        self
    }
}

impl<'a, F> Frameable for Button<'a, F> {
    fn frame(mut self, width: f64) -> Self {
        self.style.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.style.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, F> Labelable<'a> for Button<'a, F> {
    fn label(mut self, text: &'a str) -> Self {
        self.maybe_label = Some(text);
        self
    }

    fn label_color(mut self, color: Color) -> Self {
        self.style.maybe_label_color = Some(color);
        self
    }

    fn label_font_size(mut self, size: FontSize) -> Self {
        self.style.maybe_label_font_size = Some(size);
        self
    }
}

impl<'a, F> Positionable for Button<'a, F> {
    fn position(mut self, pos: Position) -> Self {
        self.pos = pos;
        self
    }
    fn get_position(&self) -> Position { self.pos }
    #[inline]
    fn horizontal_align(self, h_align: HorizontalAlign) -> Self {
        Button { maybe_h_align: Some(h_align), ..self }
    }
    #[inline]
    fn vertical_align(self, v_align: VerticalAlign) -> Self {
        Button { maybe_v_align: Some(v_align), ..self }
    }
    fn get_horizontal_align(&self, theme: &Theme) -> HorizontalAlign {
        self.maybe_h_align.unwrap_or(theme.align.horizontal)
    }
    fn get_vertical_align(&self, theme: &Theme) -> VerticalAlign {
        self.maybe_v_align.unwrap_or(theme.align.vertical)
    }
    fn depth(mut self, depth: Depth) -> Self {
        self.depth = depth;
        self
    }
    fn get_depth(&self) -> Depth { self.depth }
}

impl<'a, F> ::position::Sizeable for Button<'a, F> {
    #[inline]
    fn width(mut self, w: f64) -> Self {
        self.style.maybe_width = Some(w);
        self
    }
    #[inline]
    fn height(mut self, h: f64) -> Self {
        self.style.maybe_height = Some(h);
        self
    }
    fn get_width<C: CharacterCache>(&self, theme: &Theme, _: &GlyphCache<C>) -> f64 {
        self.style.width(theme)
    }
    fn get_height(&self, theme: &Theme) -> f64 {
        self.style.height(theme)
    }
}

<|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/. */

use dom::baseaudiocontext::BaseAudioContext;
use dom::bindings::codegen::Bindings::AudioNodeBinding::{AudioNodeMethods, AudioNodeOptions};
use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation};
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::root::{Dom, DomRoot};
use dom::audioparam::AudioParam;
use dom::eventtarget::EventTarget;
use dom_struct::dom_struct;
use servo_media::audio::graph::NodeId;
use servo_media::audio::node::{AudioNodeMessage, AudioNodeInit};
use std::cell::Cell;

// 32 is the minimum required by the spec for createBuffer() and the deprecated
// createScriptProcessor() and matches what is used by Blink and Gecko.
// The limit protects against large memory allocations.
pub const MAX_CHANNEL_COUNT: u32 = 32;

#[dom_struct]
pub struct AudioNode {
    eventtarget: EventTarget,
    #[ignore_malloc_size_of = "servo_media"]
    node_id: NodeId,
    context: Dom<BaseAudioContext>,
    number_of_inputs: u32,
    number_of_outputs: u32,
    channel_count: Cell<u32>,
    channel_count_mode: Cell<ChannelCountMode>,
    channel_interpretation: Cell<ChannelInterpretation>,
}

impl AudioNode {
    pub fn new_inherited(
        node_type: AudioNodeInit,
        node_id: Option<NodeId>,
        context: &BaseAudioContext,
        options: &AudioNodeOptions,
        number_of_inputs: u32,
        number_of_outputs: u32,
    ) -> AudioNode {
        let node_id =
            node_id.unwrap_or_else(|| context.audio_context_impl().create_node(node_type));
        AudioNode {
            eventtarget: EventTarget::new_inherited(),
            node_id,
            context: Dom::from_ref(context),
            number_of_inputs,
            number_of_outputs,
            channel_count: Cell::new(options.channelCount.unwrap_or(2)),
            channel_count_mode: Cell::new(options.channelCountMode.unwrap_or_default()),
            channel_interpretation: Cell::new(options.channelInterpretation.unwrap_or_default()),
        }
    }

    pub fn message(&self, message: AudioNodeMessage) {
        self.context
            .audio_context_impl()
            .message_node(self.node_id, message);
    }

    pub fn node_id(&self) -> NodeId {
        self.node_id
    }
}

impl AudioNodeMethods for AudioNode {
    // https://webaudio.github.io/web-audio-api/#dom-audionode-connect
    fn Connect(
        &self,
        destination: &AudioNode,
        output: u32,
        input: u32,
    ) -> Fallible<DomRoot<AudioNode>> {
        if self.context != destination.context {
            return Err(Error::InvalidAccess);
        }

        if output >= self.NumberOfOutputs() || input >= destination.NumberOfInputs() {
            return Err(Error::IndexSize);
        }

        self.context.audio_context_impl().connect_ports(
            self.node_id().output(output),
            destination.node_id().input(input),
        );

        Ok(DomRoot::from_ref(destination))
    }

    fn Connect_(&self, _: &AudioParam, _: u32) -> Fallible<()> {
        // TODO
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
    fn Disconnect(&self) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_all_from(self.node_id());
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-output
    fn Disconnect_(&self, out: u32) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_output(self.node_id().output(out));
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode
    fn Disconnect__(&self, to: &AudioNode) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_between(self.node_id(), to.node_id());
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output
    fn Disconnect___(&self, to: &AudioNode, out: u32) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_output_between(self.node_id().output(out), to.node_id());
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output-input
    fn Disconnect____(&self, to: &AudioNode, out: u32, inp: u32) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_output_between_to(self.node_id().output(out), to.node_id().input(inp));
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
    fn Disconnect_____(&self, _: &AudioParam) -> ErrorResult {
        // TODO
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
    fn Disconnect______(&self, _: &AudioParam, _: u32) -> ErrorResult {
        // TODO
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-context
    fn Context(&self) -> DomRoot<BaseAudioContext> {
        DomRoot::from_ref(&self.context)
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-numberofinputs
    fn NumberOfInputs(&self) -> u32 {
        self.number_of_inputs
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-numberofoutputs
    fn NumberOfOutputs(&self) -> u32 {
        self.number_of_outputs
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-channelcount
    fn ChannelCount(&self) -> u32 {
        self.channel_count.get()
    }

    fn SetChannelCount(&self, value: u32) -> ErrorResult {
        if value == 0 || value > MAX_CHANNEL_COUNT {
            return Err(Error::NotSupported);
        }
        self.channel_count.set(value);
        Ok(())
    }

    fn ChannelCountMode(&self) -> ChannelCountMode {
        self.channel_count_mode.get()
    }

    fn SetChannelCountMode(&self, value: ChannelCountMode) -> ErrorResult {
        self.channel_count_mode.set(value);
        Ok(())
    }

    fn ChannelInterpretation(&self) -> ChannelInterpretation {
        self.channel_interpretation.get()
    }

    fn SetChannelInterpretation(&self, value: ChannelInterpretation) {
        self.channel_interpretation.set(value);
    }
}
<commit_msg>Clarify that servo-media deals with duplicated connections<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/. */

use dom::baseaudiocontext::BaseAudioContext;
use dom::bindings::codegen::Bindings::AudioNodeBinding::{AudioNodeMethods, AudioNodeOptions};
use dom::bindings::codegen::Bindings::AudioNodeBinding::{ChannelCountMode, ChannelInterpretation};
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::root::{Dom, DomRoot};
use dom::audioparam::AudioParam;
use dom::eventtarget::EventTarget;
use dom_struct::dom_struct;
use servo_media::audio::graph::NodeId;
use servo_media::audio::node::{AudioNodeMessage, AudioNodeInit};
use std::cell::Cell;

// 32 is the minimum required by the spec for createBuffer() and the deprecated
// createScriptProcessor() and matches what is used by Blink and Gecko.
// The limit protects against large memory allocations.
pub const MAX_CHANNEL_COUNT: u32 = 32;

#[dom_struct]
pub struct AudioNode {
    eventtarget: EventTarget,
    #[ignore_malloc_size_of = "servo_media"]
    node_id: NodeId,
    context: Dom<BaseAudioContext>,
    number_of_inputs: u32,
    number_of_outputs: u32,
    channel_count: Cell<u32>,
    channel_count_mode: Cell<ChannelCountMode>,
    channel_interpretation: Cell<ChannelInterpretation>,
}

impl AudioNode {
    pub fn new_inherited(
        node_type: AudioNodeInit,
        node_id: Option<NodeId>,
        context: &BaseAudioContext,
        options: &AudioNodeOptions,
        number_of_inputs: u32,
        number_of_outputs: u32,
    ) -> AudioNode {
        let node_id =
            node_id.unwrap_or_else(|| context.audio_context_impl().create_node(node_type));
        AudioNode {
            eventtarget: EventTarget::new_inherited(),
            node_id,
            context: Dom::from_ref(context),
            number_of_inputs,
            number_of_outputs,
            channel_count: Cell::new(options.channelCount.unwrap_or(2)),
            channel_count_mode: Cell::new(options.channelCountMode.unwrap_or_default()),
            channel_interpretation: Cell::new(options.channelInterpretation.unwrap_or_default()),
        }
    }

    pub fn message(&self, message: AudioNodeMessage) {
        self.context
            .audio_context_impl()
            .message_node(self.node_id, message);
    }

    pub fn node_id(&self) -> NodeId {
        self.node_id
    }
}

impl AudioNodeMethods for AudioNode {
    // https://webaudio.github.io/web-audio-api/#dom-audionode-connect
    fn Connect(
        &self,
        destination: &AudioNode,
        output: u32,
        input: u32,
    ) -> Fallible<DomRoot<AudioNode>> {
        if self.context != destination.context {
            return Err(Error::InvalidAccess);
        }

        if output >= self.NumberOfOutputs() || input >= destination.NumberOfInputs() {
            return Err(Error::IndexSize);
        }

        // servo-media takes care of ignoring duplicated connections.

        self.context.audio_context_impl().connect_ports(
            self.node_id().output(output),
            destination.node_id().input(input),
        );

        Ok(DomRoot::from_ref(destination))
    }

    fn Connect_(&self, _: &AudioParam, _: u32) -> Fallible<()> {
        // TODO
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
    fn Disconnect(&self) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_all_from(self.node_id());
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-output
    fn Disconnect_(&self, out: u32) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_output(self.node_id().output(out));
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode
    fn Disconnect__(&self, to: &AudioNode) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_between(self.node_id(), to.node_id());
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output
    fn Disconnect___(&self, to: &AudioNode, out: u32) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_output_between(self.node_id().output(out), to.node_id());
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect-destinationnode-output-input
    fn Disconnect____(&self, to: &AudioNode, out: u32, inp: u32) -> ErrorResult {
        self.context
            .audio_context_impl()
            .disconnect_output_between_to(self.node_id().output(out), to.node_id().input(inp));
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
    fn Disconnect_____(&self, _: &AudioParam) -> ErrorResult {
        // TODO
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-disconnect
    fn Disconnect______(&self, _: &AudioParam, _: u32) -> ErrorResult {
        // TODO
        Ok(())
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-context
    fn Context(&self) -> DomRoot<BaseAudioContext> {
        DomRoot::from_ref(&self.context)
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-numberofinputs
    fn NumberOfInputs(&self) -> u32 {
        self.number_of_inputs
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-numberofoutputs
    fn NumberOfOutputs(&self) -> u32 {
        self.number_of_outputs
    }

    // https://webaudio.github.io/web-audio-api/#dom-audionode-channelcount
    fn ChannelCount(&self) -> u32 {
        self.channel_count.get()
    }

    fn SetChannelCount(&self, value: u32) -> ErrorResult {
        if value == 0 || value > MAX_CHANNEL_COUNT {
            return Err(Error::NotSupported);
        }
        self.channel_count.set(value);
        Ok(())
    }

    fn ChannelCountMode(&self) -> ChannelCountMode {
        self.channel_count_mode.get()
    }

    fn SetChannelCountMode(&self, value: ChannelCountMode) -> ErrorResult {
        self.channel_count_mode.set(value);
        Ok(())
    }

    fn ChannelInterpretation(&self) -> ChannelInterpretation {
        self.channel_interpretation.get()
    }

    fn SetChannelInterpretation(&self, value: ChannelInterpretation) {
        self.channel_interpretation.set(value);
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::marker;

use crate::reflect::runtime_types::RuntimeTypeEnumOrUnknown;
use crate::reflect::EnumDescriptor;
use crate::reflect::EnumValueDescriptor;
use crate::reflect::ProtobufValue;

/// Trait implemented by all protobuf enum types.
pub trait ProtobufEnum: Eq + Sized + Copy + 'static + ProtobufValue + fmt::Debug + Default {
    /// Get enum `i32` value.
    fn value(&self) -> i32;

    /// Try to create an enum from `i32` value.
    /// Return `None` if value is unknown.
    fn from_i32(v: i32) -> Option<Self>;

    /// Get all enum values for enum type.
    fn values() -> &'static [Self];

    /// Get enum value descriptor.
    fn descriptor(&self) -> EnumValueDescriptor {
        self.enum_descriptor()
            .get_value_by_number(self.value())
            .unwrap()
    }

    /// Get enum descriptor.
    fn enum_descriptor(&self) -> EnumDescriptor {
        Self::enum_descriptor_static()
    }

    /// Get enum descriptor by type.
    fn enum_descriptor_static() -> EnumDescriptor {
        panic!();
    }
}

/// Protobuf enums with possibly unknown values are preserved in this struct.
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
#[repr(transparent)]
// TODO: specify <E: ProtobufEnum> when it no longer prevents using const fns
pub struct ProtobufEnumOrUnknown<E> {
    value: i32,
    _marker: marker::PhantomData<E>,
}

// TODO: move into <E: ProtobufEnum> when no longer:
//  trait bounds other than `Sized` on const fn parameters are unstable
impl<E> ProtobufEnumOrUnknown<E> {
    /// Construct from any `i32` value.
    ///
    /// Note passed value is not required to be a valid enum value.
    pub const fn from_i32(value: i32) -> ProtobufEnumOrUnknown<E> {
        ProtobufEnumOrUnknown {
            value,
            _marker: marker::PhantomData,
        }
    }
}

impl<E: ProtobufEnum> ProtobufEnumOrUnknown<E> {
    /// Construct from typed enum
    pub fn new(e: E) -> ProtobufEnumOrUnknown<E> {
        ProtobufEnumOrUnknown::from_i32(e.value())
    }

    /// Get contained `i32` value of enum
    pub fn value(&self) -> i32 {
        self.value
    }

    /// Get `i32` value as typed enum. Return `None` is value is unknown.
    pub fn enum_value(&self) -> Result<E, i32> {
        E::from_i32(self.value).ok_or(self.value)
    }

    /// Get contained enum, panic if value is unknown.
    pub fn unwrap(&self) -> E {
        self.enum_value().unwrap()
    }

    /// Get `i32` value as typed enum.
    /// Return default enum value (first value) if value is unknown.
    pub fn enum_value_or_default(&self) -> E {
        self.enum_value().unwrap_or_default()
    }

    /// Get `i32` value as typed enum.
    /// Return given enum value if value is unknown.
    pub fn enum_value_or(&self, map_unknown: E) -> E {
        self.enum_value().unwrap_or(map_unknown)
    }

    /// Get enum descriptor by type.
    pub fn enum_descriptor_static() -> EnumDescriptor {
        E::enum_descriptor_static()
    }
}

impl<E: ProtobufEnum> From<E> for ProtobufEnumOrUnknown<E> {
    fn from(e: E) -> Self {
        ProtobufEnumOrUnknown::new(e)
    }
}

impl<E: ProtobufEnum> Default for ProtobufEnumOrUnknown<E> {
    fn default() -> ProtobufEnumOrUnknown<E> {
        ProtobufEnumOrUnknown::new(E::default())
    }
}

impl<E: ProtobufEnum> fmt::Debug for ProtobufEnumOrUnknown<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.enum_value() {
            Ok(e) => fmt::Debug::fmt(&e, f),
            Err(e) => fmt::Debug::fmt(&e, f),
        }
    }
}

impl<E: ProtobufEnum + ProtobufValue> ProtobufValue for ProtobufEnumOrUnknown<E> {
    type RuntimeType = RuntimeTypeEnumOrUnknown<E>;
}

#[cfg(feature = "with-serde")]
impl<E: serde::Serialize + ProtobufEnum> serde::Serialize for ProtobufEnumOrUnknown<E> {
    fn serialize<S>(
        &self,
        serializer: S,
    ) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error>
    where
        S: serde::Serializer,
    {
        // TODO: serialize number when unknown
        self.enum_value_or_default().serialize(serializer)
    }
}

#[cfg(feature = "with-serde")]
impl<'de, E: serde::Deserialize<'de> + ProtobufEnum> serde::Deserialize<'de>
    for ProtobufEnumOrUnknown<E>
{
    fn deserialize<D>(deserializer: D) -> Result<Self, <D as serde::Deserializer<'de>>::Error>
    where
        D: serde::Deserializer<'de>,
    {
        Ok(ProtobufEnumOrUnknown::new(E::deserialize(deserializer)?))
    }
}
<commit_msg>ProtobufEnum does not need to extend ProtobufValue<commit_after>use std::fmt;
use std::marker;

use crate::reflect::runtime_types::RuntimeTypeEnumOrUnknown;
use crate::reflect::EnumDescriptor;
use crate::reflect::EnumValueDescriptor;
use crate::reflect::ProtobufValue;

/// Trait implemented by all protobuf enum types.
pub trait ProtobufEnum: Eq + Sized + Copy + 'static + fmt::Debug + Default + Sync + Send {
    /// Get enum `i32` value.
    fn value(&self) -> i32;

    /// Try to create an enum from `i32` value.
    /// Return `None` if value is unknown.
    fn from_i32(v: i32) -> Option<Self>;

    /// Get all enum values for enum type.
    fn values() -> &'static [Self];

    /// Get enum value descriptor.
    fn descriptor(&self) -> EnumValueDescriptor {
        self.enum_descriptor()
            .get_value_by_number(self.value())
            .unwrap()
    }

    /// Get enum descriptor.
    fn enum_descriptor(&self) -> EnumDescriptor {
        Self::enum_descriptor_static()
    }

    /// Get enum descriptor by type.
    fn enum_descriptor_static() -> EnumDescriptor {
        panic!();
    }
}

/// Protobuf enums with possibly unknown values are preserved in this struct.
#[derive(Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
#[repr(transparent)]
// TODO: specify <E: ProtobufEnum> when it no longer prevents using const fns
pub struct ProtobufEnumOrUnknown<E> {
    value: i32,
    _marker: marker::PhantomData<E>,
}

// TODO: move into <E: ProtobufEnum> when no longer:
//  trait bounds other than `Sized` on const fn parameters are unstable
impl<E> ProtobufEnumOrUnknown<E> {
    /// Construct from any `i32` value.
    ///
    /// Note passed value is not required to be a valid enum value.
    pub const fn from_i32(value: i32) -> ProtobufEnumOrUnknown<E> {
        ProtobufEnumOrUnknown {
            value,
            _marker: marker::PhantomData,
        }
    }
}

impl<E: ProtobufEnum> ProtobufEnumOrUnknown<E> {
    /// Construct from typed enum
    pub fn new(e: E) -> ProtobufEnumOrUnknown<E> {
        ProtobufEnumOrUnknown::from_i32(e.value())
    }

    /// Get contained `i32` value of enum
    pub fn value(&self) -> i32 {
        self.value
    }

    /// Get `i32` value as typed enum. Return `None` is value is unknown.
    pub fn enum_value(&self) -> Result<E, i32> {
        E::from_i32(self.value).ok_or(self.value)
    }

    /// Get contained enum, panic if value is unknown.
    pub fn unwrap(&self) -> E {
        self.enum_value().unwrap()
    }

    /// Get `i32` value as typed enum.
    /// Return default enum value (first value) if value is unknown.
    pub fn enum_value_or_default(&self) -> E {
        self.enum_value().unwrap_or_default()
    }

    /// Get `i32` value as typed enum.
    /// Return given enum value if value is unknown.
    pub fn enum_value_or(&self, map_unknown: E) -> E {
        self.enum_value().unwrap_or(map_unknown)
    }

    /// Get enum descriptor by type.
    pub fn enum_descriptor_static() -> EnumDescriptor {
        E::enum_descriptor_static()
    }
}

impl<E: ProtobufEnum> From<E> for ProtobufEnumOrUnknown<E> {
    fn from(e: E) -> Self {
        ProtobufEnumOrUnknown::new(e)
    }
}

impl<E: ProtobufEnum> Default for ProtobufEnumOrUnknown<E> {
    fn default() -> ProtobufEnumOrUnknown<E> {
        ProtobufEnumOrUnknown::new(E::default())
    }
}

impl<E: ProtobufEnum> fmt::Debug for ProtobufEnumOrUnknown<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.enum_value() {
            Ok(e) => fmt::Debug::fmt(&e, f),
            Err(e) => fmt::Debug::fmt(&e, f),
        }
    }
}

impl<E: ProtobufEnum + ProtobufValue> ProtobufValue for ProtobufEnumOrUnknown<E> {
    type RuntimeType = RuntimeTypeEnumOrUnknown<E>;
}

#[cfg(feature = "with-serde")]
impl<E: serde::Serialize + ProtobufEnum> serde::Serialize for ProtobufEnumOrUnknown<E> {
    fn serialize<S>(
        &self,
        serializer: S,
    ) -> Result<<S as serde::Serializer>::Ok, <S as serde::Serializer>::Error>
    where
        S: serde::Serializer,
    {
        // TODO: serialize number when unknown
        self.enum_value_or_default().serialize(serializer)
    }
}

#[cfg(feature = "with-serde")]
impl<'de, E: serde::Deserialize<'de> + ProtobufEnum> serde::Deserialize<'de>
    for ProtobufEnumOrUnknown<E>
{
    fn deserialize<D>(deserializer: D) -> Result<Self, <D as serde::Deserializer<'de>>::Error>
    where
        D: serde::Deserializer<'de>,
    {
        Ok(ProtobufEnumOrUnknown::new(E::deserialize(deserializer)?))
    }
}
<|endoftext|>


<commit_before>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

// Looking for `pkg::install`? That's in the `common` crate. You're welcome :)

pub mod binlink {
    use std::fs;
    use std::path::Path;
    use std::os::unix;

    use ansi_term::Colour::{Blue, Green, Yellow};
    use hcore::package::{PackageIdent, PackageInstall};

    use error::{Error, Result};
    use exec::find_command_in_pkg;

    pub fn start(ident: &PackageIdent,
                 binary: &str,
                 dest_path: &Path,
                 fs_root_path: &Path)
                 -> Result<()> {
        let dst_path = fs_root_path.join(try!(dest_path.strip_prefix("/")));
        let dst = dst_path.join(&binary);
        println!("{}",
                 Yellow.bold().paint(format!("» Symlinking {} from {} into {}",
                                             &binary,
                                             &ident,
                                             dst_path.display())));
        let pkg_install = try!(PackageInstall::load(&ident, Some(fs_root_path)));
        let src = match try!(find_command_in_pkg(binary, &pkg_install, fs_root_path)) {
            Some(c) => c,
            None => {
                return Err(Error::CommandNotFoundInPkg((pkg_install.ident().to_string(),
                                                        binary.to_string())))
            }
        };
        if !dst_path.is_dir() {
            println!("{} parent directory {}",
                     Green.paint("Ω Creating"),
                     dst_path.display());
            try!(fs::create_dir_all(&dst_path))
        }
        match fs::read_link(&dst) {
            Ok(path) => {
                if path != src {
                    try!(fs::remove_file(&dst));
                    try!(unix::fs::symlink(&src, &dst));
                }
            }
            Err(_) => try!(unix::fs::symlink(&src, &dst)),
        }
        println!("{}",
                 Blue.paint(format!("★ Binary {} from {} symlinked to {}",
                                    &binary,
                                    &pkg_install.ident(),
                                    &dst.display())));
        Ok(())
    }
}

pub mod build {
    use std::ffi::OsString;

    use error::Result;
    use command::studio;

    pub fn start(plan_context: &str,
                 root: Option<&str>,
                 src: Option<&str>,
                 keys: Option<&str>,
                 reuse: bool)
                 -> Result<()> {
        let mut args: Vec<OsString> = Vec::new();
        if let Some(root) = root {
            args.push("-r".into());
            args.push(root.into());
        }
        if let Some(src) = src {
            args.push("-s".into());
            args.push(src.into());
        }
        if let Some(keys) = keys {
            args.push("-k".into());
            args.push(keys.into());
        }
        args.push("build".into());
        if cfg!(target_os = "linux") && reuse {
            args.push("-R".into());
        }
        args.push(plan_context.into());
        studio::start(args)
    }
}

pub mod exec {
    use std::env;
    use std::ffi::OsString;

    use hcore::package::{PackageIdent, PackageInstall};
    use hcore::fs::find_command;

    use error::{Error, Result};
    use exec;

    pub fn start(ident: &PackageIdent, command: &str, args: Vec<OsString>) -> Result<()> {
        let pkg_install = try!(PackageInstall::load(&ident, None));
        let env_path = try!(pkg_install.runtime_path());
        info!("Setting: PATH='{}'", &env_path);
        env::set_var("PATH", env_path);
        let command = match find_command(command) {
            Some(path) => path,
            None => return Err(Error::ExecCommandNotFound(command.to_string())),
        };
        let mut display_args = command.to_string_lossy().into_owned();
        for arg in &args {
            display_args.push(' ');
            display_args.push_str(arg.to_string_lossy().as_ref());
        }
        info!("Running: {}", display_args);
        exec::exec_command(command, args)
    }
}

pub mod path {
    use std::path::Path;

    use hcore::package::{PackageIdent, PackageInstall};

    use error::Result;

    pub fn start(ident: &PackageIdent, fs_root_path: &Path) -> Result<()> {
        let pkg_install = try!(PackageInstall::load(ident, Some(fs_root_path)));
        println!("{}", pkg_install.installed_path().display());
        Ok(())
    }
}
<commit_msg>[hab/mac] Ensure that `-R` is passed to `hab studio` on `pkg build`.<commit_after>// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

// Looking for `pkg::install`? That's in the `common` crate. You're welcome :)

pub mod binlink {
    use std::fs;
    use std::path::Path;
    use std::os::unix;

    use ansi_term::Colour::{Blue, Green, Yellow};
    use hcore::package::{PackageIdent, PackageInstall};

    use error::{Error, Result};
    use exec::find_command_in_pkg;

    pub fn start(ident: &PackageIdent,
                 binary: &str,
                 dest_path: &Path,
                 fs_root_path: &Path)
                 -> Result<()> {
        let dst_path = fs_root_path.join(try!(dest_path.strip_prefix("/")));
        let dst = dst_path.join(&binary);
        println!("{}",
                 Yellow.bold().paint(format!("» Symlinking {} from {} into {}",
                                             &binary,
                                             &ident,
                                             dst_path.display())));
        let pkg_install = try!(PackageInstall::load(&ident, Some(fs_root_path)));
        let src = match try!(find_command_in_pkg(binary, &pkg_install, fs_root_path)) {
            Some(c) => c,
            None => {
                return Err(Error::CommandNotFoundInPkg((pkg_install.ident().to_string(),
                                                        binary.to_string())))
            }
        };
        if !dst_path.is_dir() {
            println!("{} parent directory {}",
                     Green.paint("Ω Creating"),
                     dst_path.display());
            try!(fs::create_dir_all(&dst_path))
        }
        match fs::read_link(&dst) {
            Ok(path) => {
                if path != src {
                    try!(fs::remove_file(&dst));
                    try!(unix::fs::symlink(&src, &dst));
                }
            }
            Err(_) => try!(unix::fs::symlink(&src, &dst)),
        }
        println!("{}",
                 Blue.paint(format!("★ Binary {} from {} symlinked to {}",
                                    &binary,
                                    &pkg_install.ident(),
                                    &dst.display())));
        Ok(())
    }
}

pub mod build {
    use std::ffi::OsString;

    use error::Result;
    use command::studio;

    pub fn start(plan_context: &str,
                 root: Option<&str>,
                 src: Option<&str>,
                 keys: Option<&str>,
                 reuse: bool)
                 -> Result<()> {
        let mut args: Vec<OsString> = Vec::new();
        if let Some(root) = root {
            args.push("-r".into());
            args.push(root.into());
        }
        if let Some(src) = src {
            args.push("-s".into());
            args.push(src.into());
        }
        if let Some(keys) = keys {
            args.push("-k".into());
            args.push(keys.into());
        }
        args.push("build".into());
        if cfg!(not(target_os = "linux")) || reuse {
            args.push("-R".into());
        }
        args.push(plan_context.into());
        studio::start(args)
    }
}

pub mod exec {
    use std::env;
    use std::ffi::OsString;

    use hcore::package::{PackageIdent, PackageInstall};
    use hcore::fs::find_command;

    use error::{Error, Result};
    use exec;

    pub fn start(ident: &PackageIdent, command: &str, args: Vec<OsString>) -> Result<()> {
        let pkg_install = try!(PackageInstall::load(&ident, None));
        let env_path = try!(pkg_install.runtime_path());
        info!("Setting: PATH='{}'", &env_path);
        env::set_var("PATH", env_path);
        let command = match find_command(command) {
            Some(path) => path,
            None => return Err(Error::ExecCommandNotFound(command.to_string())),
        };
        let mut display_args = command.to_string_lossy().into_owned();
        for arg in &args {
            display_args.push(' ');
            display_args.push_str(arg.to_string_lossy().as_ref());
        }
        info!("Running: {}", display_args);
        exec::exec_command(command, args)
    }
}

pub mod path {
    use std::path::Path;

    use hcore::package::{PackageIdent, PackageInstall};

    use error::Result;

    pub fn start(ident: &PackageIdent, fs_root_path: &Path) -> Result<()> {
        let pkg_install = try!(PackageInstall::load(ident, Some(fs_root_path)));
        println!("{}", pkg_install.installed_path().display());
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Contains Value and ValueRef structs and its conversion traits.

use std::convert::From;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

impl Value {
    /// Returns true if the `Value` is a Null. Returns false otherwise.
    pub fn is_nil(&self) -> bool {
        if let Value::Nil = *self {
            true
        } else {
            false
        }
    }

    /// If the `Value` is a Boolean, returns the associated bool.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some(true), Value::Boolean(true).as_bool());
    /// assert_eq!(None, Value::Nil.as_bool());
    /// ```
    pub fn as_bool(&self) -> Option<bool> {
        if let Value::Boolean(val) = *self {
            Some(val)
        } else {
            None
        }
    }

    /// If the `Value` is an integer, return or cast it to a i64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42i64), Value::Integer(Integer::I64(42)).as_i64());
    /// assert_eq!(Some(42i64), Value::Integer(Integer::U64(42)).as_i64());
    ///
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_i64());
    /// ```
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Integer(Integer::I64(n)) => Some(n),
            Value::Integer(Integer::U64(n)) if n <= i64::max_value() as u64 => Some(n as i64),
            _ => None,
        }
    }

    /// If the `Value` is an integer, return or cast it to a u64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42u64), Value::Integer(Integer::I64(42)).as_u64());
    /// assert_eq!(Some(42u64), Value::Integer(Integer::U64(42)).as_u64());
    ///
    /// assert_eq!(None, Value::Integer(Integer::I64(-42)).as_u64());
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_u64());
    /// ```
    pub fn as_u64(&self) -> Option<u64> {
        match *self {
            Value::Integer(Integer::I64(n)) if 0 <= n => Some(n as u64),
            Value::Integer(Integer::U64(n)) => Some(n),
            _ => None,
        }
    }

    /// If the `Value` is a number, return or cast it to a f64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42.0), Value::Integer(Integer::I64(42)).as_f64());
    /// assert_eq!(Some(42.0), Value::Integer(Integer::U64(42)).as_f64());
    /// assert_eq!(Some(42.0), Value::Float(Float::F32(42.0f32)).as_f64());
    /// assert_eq!(Some(42.0), Value::Float(Float::F64(42.0f64)).as_f64());
    ///
    /// assert_eq!(Some(2147483647.0), Value::Integer(Integer::I64(i32::max_value() as i64)).as_f64());
    ///
    /// assert_eq!(None, Value::Nil.as_f64());
    ///
    /// assert_eq!(None, Value::Integer(Integer::I64(i32::max_value() as i64 + 1)).as_f64());
    /// ```
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::Integer(Integer::I64(n)) if (i32::min_value() as i64 <= n) && (n <= i32::max_value() as i64) => {
                Some(From::from(n as i32))
            }
            Value::Integer(Integer::U64(n)) if n <= u32::max_value() as u64 => {
                Some(From::from(n as u32))
            }
            Value::Float(Float::F32(n)) => Some(From::from(n)),
            Value::Float(Float::F64(n)) => Some(n),
            _ => None,
        }
    }
}

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

impl From<u8> for Value {
    fn from(v: u8) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u16> for Value {
    fn from(v: u16) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u32> for Value {
    fn from(v: u32) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u64> for Value {
    fn from(v: u64) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<usize> for Value {
    fn from(v: usize) -> Value {
        Value::Integer(Integer::U64(v as u64))
    }
}

impl From<i8> for Value {
    fn from(v: i8) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i16> for Value {
    fn from(v: i16) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i32> for Value {
    fn from(v: i32) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

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

impl From<isize> for Value {
    fn from(v: isize) -> Value {
        Value::Integer(Integer::I64(v as i64))
    }
}

impl From<f32> for Value {
    fn from(v: f32) -> Value {
        Value::Float(Float::F32(v))
    }
}

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

/// Implements human-readable value formatting.
impl ::std::fmt::Display for Value {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Integer(Integer::U64(val)) => write!(f, "{}", val),
            Value::Integer(Integer::I64(val)) => write!(f, "{}", val),
            Value::Float(Float::F32(val)) => write!(f, "{}", val),
            Value::Float(Float::F64(val)) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "\"{}\"", val),
            Value::Binary(ref val) => write!(f, "{:?}", val),
            Value::Array(ref vec) => {
                // TODO: This can be slower than naive implementation. Need benchmarks for more
                // information.
                let res = vec.iter()
                    .map(|val| format!("{}", val))
                    .collect::<Vec<String>>()
                    .join(", ");

                write!(f, "[{}]", res)
            }
            Value::Map(ref vec) => {
                try!(write!(f, "{{"));

                match vec.iter().take(1).next() {
                    Some(&(ref k, ref v)) => {
                        try!(write!(f, "{}: {}", k, v));
                    }
                    None => {
                        try!(write!(f, ""));
                    }
                }

                for &(ref k, ref v) in vec.iter().skip(1) {
                    try!(write!(f, ", {}: {}", k, v));
                }

                write!(f, "}}")
            }
            Value::Ext(ty, ref data) => {
                write!(f, "[{}, {:?}]", ty, data)
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(Vec<ValueRef<'a>>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_owned()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<commit_msg>feat: odd conversion to a str for value<commit_after>//! Contains Value and ValueRef structs and its conversion traits.

use std::convert::From;

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

impl Value {
    /// Returns true if the `Value` is a Null. Returns false otherwise.
    pub fn is_nil(&self) -> bool {
        if let Value::Nil = *self {
            true
        } else {
            false
        }
    }

    /// If the `Value` is a Boolean, returns the associated bool.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some(true), Value::Boolean(true).as_bool());
    /// assert_eq!(None, Value::Nil.as_bool());
    /// ```
    pub fn as_bool(&self) -> Option<bool> {
        if let Value::Boolean(val) = *self {
            Some(val)
        } else {
            None
        }
    }

    /// If the `Value` is an integer, return or cast it to a i64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42i64), Value::Integer(Integer::I64(42)).as_i64());
    /// assert_eq!(Some(42i64), Value::Integer(Integer::U64(42)).as_i64());
    ///
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_i64());
    /// ```
    pub fn as_i64(&self) -> Option<i64> {
        match *self {
            Value::Integer(Integer::I64(n)) => Some(n),
            Value::Integer(Integer::U64(n)) if n <= i64::max_value() as u64 => Some(n as i64),
            _ => None,
        }
    }

    /// If the `Value` is an integer, return or cast it to a u64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42u64), Value::Integer(Integer::I64(42)).as_u64());
    /// assert_eq!(Some(42u64), Value::Integer(Integer::U64(42)).as_u64());
    ///
    /// assert_eq!(None, Value::Integer(Integer::I64(-42)).as_u64());
    /// assert_eq!(None, Value::Float(Float::F64(42.0)).as_u64());
    /// ```
    pub fn as_u64(&self) -> Option<u64> {
        match *self {
            Value::Integer(Integer::I64(n)) if 0 <= n => Some(n as u64),
            Value::Integer(Integer::U64(n)) => Some(n),
            _ => None,
        }
    }

    /// If the `Value` is a number, return or cast it to a f64.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    /// use rmp::value::{Float, Integer};
    ///
    /// assert_eq!(Some(42.0), Value::Integer(Integer::I64(42)).as_f64());
    /// assert_eq!(Some(42.0), Value::Integer(Integer::U64(42)).as_f64());
    /// assert_eq!(Some(42.0), Value::Float(Float::F32(42.0f32)).as_f64());
    /// assert_eq!(Some(42.0), Value::Float(Float::F64(42.0f64)).as_f64());
    ///
    /// assert_eq!(Some(2147483647.0), Value::Integer(Integer::I64(i32::max_value() as i64)).as_f64());
    ///
    /// assert_eq!(None, Value::Nil.as_f64());
    ///
    /// assert_eq!(None, Value::Integer(Integer::I64(i32::max_value() as i64 + 1)).as_f64());
    /// ```
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            Value::Integer(Integer::I64(n)) if (i32::min_value() as i64 <= n) && (n <= i32::max_value() as i64) => {
                Some(From::from(n as i32))
            }
            Value::Integer(Integer::U64(n)) if n <= u32::max_value() as u64 => {
                Some(From::from(n as u32))
            }
            Value::Float(Float::F32(n)) => Some(From::from(n)),
            Value::Float(Float::F64(n)) => Some(n),
            _ => None,
        }
    }

    /// If the `Value` is a String, returns the associated str.
    /// Returns None otherwise.
    ///
    /// # Examples
    ///
    /// ```
    /// use rmp::Value;
    ///
    /// assert_eq!(Some("le message"), Value::String("le message".into()).as_str());
    /// assert_eq!(None, Value::Boolean(true).as_str());
    /// ```
    pub fn as_str(&self) -> Option<&str> {
        if let Value::String(ref val) = *self {
            Some(val)
        } else {
            None
        }
    }
}

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

impl From<u8> for Value {
    fn from(v: u8) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u16> for Value {
    fn from(v: u16) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u32> for Value {
    fn from(v: u32) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<u64> for Value {
    fn from(v: u64) -> Value {
        Value::Integer(Integer::U64(From::from(v)))
    }
}

impl From<usize> for Value {
    fn from(v: usize) -> Value {
        Value::Integer(Integer::U64(v as u64))
    }
}

impl From<i8> for Value {
    fn from(v: i8) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i16> for Value {
    fn from(v: i16) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

impl From<i32> for Value {
    fn from(v: i32) -> Value {
        Value::Integer(Integer::I64(From::from(v)))
    }
}

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

impl From<isize> for Value {
    fn from(v: isize) -> Value {
        Value::Integer(Integer::I64(v as i64))
    }
}

impl From<f32> for Value {
    fn from(v: f32) -> Value {
        Value::Float(Float::F32(v))
    }
}

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

/// Implements human-readable value formatting.
impl ::std::fmt::Display for Value {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Value::Nil => write!(f, "nil"),
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Integer(Integer::U64(val)) => write!(f, "{}", val),
            Value::Integer(Integer::I64(val)) => write!(f, "{}", val),
            Value::Float(Float::F32(val)) => write!(f, "{}", val),
            Value::Float(Float::F64(val)) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "\"{}\"", val),
            Value::Binary(ref val) => write!(f, "{:?}", val),
            Value::Array(ref vec) => {
                // TODO: This can be slower than naive implementation. Need benchmarks for more
                // information.
                let res = vec.iter()
                    .map(|val| format!("{}", val))
                    .collect::<Vec<String>>()
                    .join(", ");

                write!(f, "[{}]", res)
            }
            Value::Map(ref vec) => {
                try!(write!(f, "{{"));

                match vec.iter().take(1).next() {
                    Some(&(ref k, ref v)) => {
                        try!(write!(f, "{}: {}", k, v));
                    }
                    None => {
                        try!(write!(f, ""));
                    }
                }

                for &(ref k, ref v) in vec.iter().skip(1) {
                    try!(write!(f, ", {}: {}", k, v));
                }

                write!(f, "}}")
            }
            Value::Ext(ty, ref data) => {
                write!(f, "[{}, {:?}]", ty, data)
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(Vec<ValueRef<'a>>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_owned()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<|endoftext|>


<commit_before><commit_msg>Fix typo: `s/Attemps/Attempts/`<commit_after><|endoftext|>