<commit_before>pub extern crate conrod;

pub use self::conrod::{backend, color, cursor, event, graph, image, input, position, scroll, text,
                       theme, utils, widget};
pub use self::conrod::{Bordering, Borderable, Color, Colorable, Dimensions, FontSize, Labelable,
                       Point, Positionable, Range, Rect, Scalar, Sizeable, Theme, UiCell, Widget};
pub use self::conrod::event::Input;

/// Simplify inclusion of common traits with a `nannou::ui::prelude` module.
pub mod prelude {
    // Traits.
    pub use super::{Borderable, Colorable, Labelable, Positionable, Sizeable, Widget};
    // Types.
    pub use super::{Bordering, Dimensions, FontSize, Input, Point, Range, Rect, Scalar, Theme, Ui,
                    UiCell};
    // Modules.
    pub use super::{color, image, position, text, widget};
}

use App;
use frame::Frame;
use glium::{self, glutin};
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::{mpsc, Mutex};
use std::ops::Deref;
use window::{self, Window};

/// Owned by the `App`, the `Arrangement` handles the mapping between `Ui`s and their associated
/// windows.
pub(crate) struct Arrangement {
    pub(super) windows: RefCell<HashMap<window::Id, Vec<Handle>>>,
}

/// A handle to the `Ui` owned by the `App`.
pub(crate) struct Handle {
    /// A channel used for automatically submitting `Input` to the associated `Ui`.
    pub(crate) input_tx: Option<mpsc::SyncSender<Input>>,
}

/// A handle to the `Ui` for a specific window.
pub struct Ui {
    /// The `Id` of the window upon which this `Ui` is instantiated.
    window_id: window::Id,
    ui: conrod::Ui,
    input_rx: Option<mpsc::Receiver<Input>>,
    renderer: Mutex<conrod::backend::glium::Renderer>,
    pub image_map: conrod::image::Map<glium::texture::Texture2d>,
}

/// A type used for building a new `Ui`.
pub struct Builder<'a> {
    app: &'a App,
    window_id: window::Id,
    dimensions: Option<[Scalar; 2]>,
    theme: Option<Theme>,
    automatically_handle_input: bool,
    pending_input_limit: usize,
    default_font_path: Option<PathBuf>,
}

/// A map from `image::Id`s to their associatd `Texture2d`.
pub type Texture2dMap = conrod::image::Map<glium::texture::Texture2d>;

impl conrod::backend::winit::WinitWindow for Window {
    fn get_inner_size(&self) -> Option<(u32, u32)> {
        Some(self.inner_size_pixels())
    }
    fn hidpi_factor(&self) -> f32 {
        self.hidpi_factor()
    }
}

impl Arrangement {
    /// Initialise a new UI **Arrangement** (used by the App).
    pub(crate) fn new() -> Self {
        let windows = RefCell::new(HashMap::new());
        Arrangement { windows }
    }
}

impl<'a> Builder<'a> {
    /// Begin building a new `Ui`.
    pub(super) fn new(app: &'a App, window_id: window::Id) -> Self {
        Builder {
            app,
            window_id,
            dimensions: None,
            theme: None,
            automatically_handle_input: true,
            pending_input_limit: Ui::DEFAULT_PENDING_INPUT_LIMIT,
            default_font_path: None,
        }
    }

    /// Build the `Ui` with the given dimensions.
    ///
    /// By default, the `Ui` will have  the dimensions of the specified window.
    pub fn with_dimensions(mut self, dimensions: [Scalar; 2]) -> Self {
        self.dimensions = Some(dimensions);
        self
    }

    /// Build the `Ui` with the given theme.
    ///
    /// By default, nannou uses conrod's default theme.
    pub fn with_theme(mut self, theme: Theme) -> Self {
        self.theme = Some(theme);
        self
    }

    /// Whether or not the `App` should automatically submit input to the `Ui`.
    ///
    /// When enabled, events that can be interpreted as UI `Input` will be passed to the `Ui` via
    /// the `conrod::Ui::handle_input` method.
    ///
    /// Note that `Input`s are not immediately submitted to the `Ui` when received by the `App`.
    /// Instead, they are enqueued for the `Ui` to be processed next time `Ui::set_widgets` is
    /// called. The max number of pending `Input`s before they become ignored can be specified via
    /// the `pending_input_limit` method.
    ///
    /// By default this is `true`. Users should set this to `false` if they wish to manually filter
    /// and submit events (e.g. if something is occluding the `Ui` and the user wishes to filter
    /// occluded input).
    pub fn automatically_handle_input(mut self, b: bool) -> Self {
        self.automatically_handle_input = b;
        self
    }

    /// Specify the max number of pending `Input`s that can be enqueued for processing by the `Ui`
    /// before `Input`s start being ignored.
    ///
    /// By default this is `Ui::DEFAULT_PENDING_INPUT_LIMIT`.
    ///
    /// This has no affect if `automatically_handle_input` is set to `false`.
    pub fn pending_input_limit(mut self, limit: usize) -> Self {
        self.pending_input_limit = limit;
        self
    }

    /// Specify the path to the default font.
    ///
    /// By default this is "fonts/NotoSans/NotoSans-Regular.ttf".
    ///
    /// Fonts can also be specified manually after `Ui` creation using the `fonts_mut` method.
    pub fn default_font_path(mut self, path: PathBuf) -> Self {
        self.default_font_path = Some(path);
        self
    }

    /// Build a `Ui` with the specified parameters.
    ///
    /// Returns `None` if the window at the given `Id` is closed or if the inner `Renderer` returns
    /// an error upon creation.
    pub fn build(self) -> Option<Ui> {
        let Builder {
            app,
            window_id,
            dimensions,
            theme,
            pending_input_limit,
            automatically_handle_input,
            default_font_path,
        } = self;
        let dimensions = match dimensions {
            None => match app.window(window_id) {
                None => return None,
                Some(window) => {
                    let (win_w, win_h) = window.inner_size_points();
                    [win_w as Scalar, win_h as Scalar]
                },
            },
            Some(dimensions) => dimensions,
        };
        let theme = theme.unwrap_or_else(Theme::default);
        let ui = conrod::UiBuilder::new(dimensions).theme(theme).build();

        let (input_rx, handle) = if automatically_handle_input {
            let (input_tx, input_rx) = mpsc::sync_channel(pending_input_limit);
            let input_tx = Some(input_tx);
            let input_rx = Some(input_rx);
            let handle = Handle { input_tx };
            (input_rx, handle)
        } else {
            let input_tx = None;
            let input_rx = None;
            let handle = Handle { input_tx };
            (input_rx, handle)
        };

        // Insert the handle into the app's UI arrangement.
        app.ui.windows.borrow_mut()
            .entry(window_id)
            .or_insert(Vec::new())
            .push(handle);

        // Initialise the renderer which draws conrod::render::Primitives to the frame..
        let renderer = match app.windows.borrow().get(&window_id) {
            None => return None,
            Some(window) => match conrod::backend::glium::Renderer::new(&window.display) {
                Ok(renderer) => Mutex::new(renderer),
                Err(_) => return None,
            },
        };

        // Initialise the image map.
        let image_map = image::Map::new();

        // Initialise the `Ui`.
        let mut ui = Ui { window_id, ui, input_rx, renderer, image_map };

        // If the default font is in the assets/fonts directory, load it into the UI font map.
        let default_font_path = default_font_path
            .or_else(|| app.assets_path().ok().map(|p| p.join(Ui::DEFAULT_FONT_PATH)));

        // If there is some font path to use for the default font, attempt to load it.
        if let Some(font_path) = default_font_path {
            ui.fonts_mut().insert_from_file(font_path).ok();
        }

        Some(ui)
    }
}

impl Deref for Ui {
    type Target = conrod::Ui;
    fn deref(&self) -> &Self::Target {
        &self.ui
    }
}

impl Ui {
    /// The default maximum number of `Input`s that a `Ui` will store in its pending `Input` queue
    /// before `Input`s start being ignored.
    pub const DEFAULT_PENDING_INPUT_LIMIT: usize = 1024;
    /// The path to the default font for the `Ui`.
    pub const DEFAULT_FONT_PATH: &'static str = "fonts/NotoSans/NotoSans-Regular.ttf";

    /// Generate a new, unique `widget::Id` into a Placeholder node within the widget graph. This
    /// should only be called once for each unique widget needed to avoid unnecessary bloat within
    /// the `Ui`'s internal widget graph.
    ///
    /// When using this method, be sure to store the returned `widget::Id` somewhere so that it can
    /// be re-used on next update.
    ///
    /// **Panics** if adding another node would exceed the maximum capacity for node indices.
    pub fn generate_widget_id(&mut self) -> widget::Id {
        self.widget_id_generator().next()
    }

    /// Produces the type that may be used to generate new unique `widget::Id`s.
    pub fn widget_id_generator(&mut self) -> widget::id::Generator {
        self.ui.widget_id_generator()
    }

    /// Handle a raw UI input event and update the **Ui** state accordingly.
    ///
    /// This method *drives* the **Ui** forward and interprets input into higher-level events (like
    /// clicks and drags) for widgets.
    ///
    /// Note: By default, this will be called automatically by the nannou `App`, so most of the
    /// time you should not need to call this (otherwise received inputs may double up). This
    /// method is particularly useful in the case that automatic input handling has been disabled,
    /// as this can be used to manually submit inputs.
    pub fn handle_input(&mut self, input: Input) {
        self.ui.handle_event(input)
    }

    /// Processes all pending input.
    ///
    /// This is automatically called at the beginning of the `set_widgets` method, so the user
    /// should never need to call this manually, however the method is exposed for flexibility
    /// just in case.
    ///
    /// This has no effect if automatic input handling is disabled.
    pub fn handle_pending_input(&mut self) {
        let Ui { ref mut ui, ref input_rx, .. } = *self;
        if let Some(ref rx) = *input_rx {
            for input in rx.try_iter() {
                ui.handle_event(input);
            }
        }
    }

    /// Returns a context upon which UI widgets can be instantiated.
    ///
    /// The **UiCell** simply acts as a wrapper around the **Ui** for the period over which widgets
    /// are instantiated. Once the **UiCell** is dropped, it does some cleanup and sorting that is
    /// required after widget instantiation.
    pub fn set_widgets(&mut self) -> UiCell {
        // Process any pending inputs first.
        self.handle_pending_input();
        self.ui.set_widgets()
    }

    /// Mutable access to the `Ui`'s font map.
    ///
    /// This allows for adding and removing fonts to the UI.
    pub fn fonts_mut(&mut self) -> &mut text::font::Map {
        &mut self.ui.fonts
    }

    /// Mutable access to the `Ui`'s `Theme`.
    ///
    /// This allows for making changes to the active theme.
    pub fn theme_mut(&mut self) -> &mut Theme {
        &mut self.ui.theme
    }

    /// The first of the `Primitives` yielded by `Ui::draw` will always be a `Rectangle` the size
    /// of the window in which the Ui is instantiated.
    ///
    /// This method sets the colour with which this `Rectangle` is drawn (the default being
    /// `color::TRANSPARENT`).
    pub fn clear_with(&mut self, color: Color) {
        self.ui.clear_with(color)
    }

    /// Draws the current state of the `Ui` to the given `Frame`.
    ///
    /// The `Ui` will automatically draw to its associated window within the given `Frame`.
    ///
    /// If you require more control over where the `Ui` is drawn within the `Frame`, the `draw`
    /// method offers more flexibility.
    ///
    /// This has no effect if the window originally associated with the `Ui` no longer exists.
    pub fn draw_to_frame(&self, app: &App, frame: &Frame)
        -> Result<(), conrod::backend::glium::DrawError>
    {
        let Ui { ref ui, ref renderer, ref image_map, window_id, .. } = *self;
        if let Some(window) = app.window(window_id) {
            if let Some(mut window_frame) = frame.window(window_id) {
                if let Ok(mut renderer) = renderer.lock() {
                    let primitives = ui.draw();
                    renderer.fill(&window.display, primitives, &image_map);
                    window_frame.clear_color(0.0, 0.0, 0.0, 1.0);
                    renderer.draw(&window.display, &mut window_frame.frame.frame, image_map)?;
                }
            }
        }
        Ok(())
    }
}

/// Convert the given window event to a UI Input.
///
/// Returns `None` if there's no associated UI Input for the given event.
pub fn glutin_window_event_to_input(event: glutin::WindowEvent, window: &Window) -> Option<Input> {
    conrod::backend::winit::convert_window_event(event, window)
}
<commit_msg>Allow for specifying text glyph cache dimensions when building Ui<commit_after>pub extern crate conrod;

pub use self::conrod::{backend, color, cursor, event, graph, image, input, position, scroll, text,
                       theme, utils, widget};
pub use self::conrod::{Bordering, Borderable, Color, Colorable, Dimensions, FontSize, Labelable,
                       Point, Positionable, Range, Rect, Scalar, Sizeable, Theme, UiCell, Widget};
pub use self::conrod::event::Input;

/// Simplify inclusion of common traits with a `nannou::ui::prelude` module.
pub mod prelude {
    // Traits.
    pub use super::{Borderable, Colorable, Labelable, Positionable, Sizeable, Widget};
    // Types.
    pub use super::{Bordering, Dimensions, FontSize, Input, Point, Range, Rect, Scalar, Theme, Ui,
                    UiCell};
    // Modules.
    pub use super::{color, image, position, text, widget};
}

use App;
use frame::Frame;
use glium::{self, glutin};
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::PathBuf;
use std::sync::{mpsc, Mutex};
use std::ops::Deref;
use window::{self, Window};

/// Owned by the `App`, the `Arrangement` handles the mapping between `Ui`s and their associated
/// windows.
pub(crate) struct Arrangement {
    pub(super) windows: RefCell<HashMap<window::Id, Vec<Handle>>>,
}

/// A handle to the `Ui` owned by the `App`.
pub(crate) struct Handle {
    /// A channel used for automatically submitting `Input` to the associated `Ui`.
    pub(crate) input_tx: Option<mpsc::SyncSender<Input>>,
}

/// A handle to the `Ui` for a specific window.
pub struct Ui {
    /// The `Id` of the window upon which this `Ui` is instantiated.
    window_id: window::Id,
    ui: conrod::Ui,
    input_rx: Option<mpsc::Receiver<Input>>,
    renderer: Mutex<conrod::backend::glium::Renderer>,
    pub image_map: conrod::image::Map<glium::texture::Texture2d>,
}

/// A type used for building a new `Ui`.
pub struct Builder<'a> {
    app: &'a App,
    window_id: window::Id,
    dimensions: Option<[Scalar; 2]>,
    theme: Option<Theme>,
    automatically_handle_input: bool,
    pending_input_limit: usize,
    default_font_path: Option<PathBuf>,
    glyph_cache_dimensions: Option<(u32, u32)>,
}

/// A map from `image::Id`s to their associatd `Texture2d`.
pub type Texture2dMap = conrod::image::Map<glium::texture::Texture2d>;

impl conrod::backend::winit::WinitWindow for Window {
    fn get_inner_size(&self) -> Option<(u32, u32)> {
        Some(self.inner_size_pixels())
    }
    fn hidpi_factor(&self) -> f32 {
        self.hidpi_factor()
    }
}

impl Arrangement {
    /// Initialise a new UI **Arrangement** (used by the App).
    pub(crate) fn new() -> Self {
        let windows = RefCell::new(HashMap::new());
        Arrangement { windows }
    }
}

impl<'a> Builder<'a> {
    /// Begin building a new `Ui`.
    pub(super) fn new(app: &'a App, window_id: window::Id) -> Self {
        Builder {
            app,
            window_id,
            dimensions: None,
            theme: None,
            automatically_handle_input: true,
            pending_input_limit: Ui::DEFAULT_PENDING_INPUT_LIMIT,
            default_font_path: None,
            glyph_cache_dimensions: None,
        }
    }

    /// Build the `Ui` with the given dimensions.
    ///
    /// By default, the `Ui` will have  the dimensions of the specified window.
    pub fn with_dimensions(mut self, dimensions: [Scalar; 2]) -> Self {
        self.dimensions = Some(dimensions);
        self
    }

    /// Build the `Ui` with the given theme.
    ///
    /// By default, nannou uses conrod's default theme.
    pub fn with_theme(mut self, theme: Theme) -> Self {
        self.theme = Some(theme);
        self
    }

    /// Whether or not the `App` should automatically submit input to the `Ui`.
    ///
    /// When enabled, events that can be interpreted as UI `Input` will be passed to the `Ui` via
    /// the `conrod::Ui::handle_input` method.
    ///
    /// Note that `Input`s are not immediately submitted to the `Ui` when received by the `App`.
    /// Instead, they are enqueued for the `Ui` to be processed next time `Ui::set_widgets` is
    /// called. The max number of pending `Input`s before they become ignored can be specified via
    /// the `pending_input_limit` method.
    ///
    /// By default this is `true`. Users should set this to `false` if they wish to manually filter
    /// and submit events (e.g. if something is occluding the `Ui` and the user wishes to filter
    /// occluded input).
    pub fn automatically_handle_input(mut self, b: bool) -> Self {
        self.automatically_handle_input = b;
        self
    }

    /// Specify the max number of pending `Input`s that can be enqueued for processing by the `Ui`
    /// before `Input`s start being ignored.
    ///
    /// By default this is `Ui::DEFAULT_PENDING_INPUT_LIMIT`.
    ///
    /// This has no affect if `automatically_handle_input` is set to `false`.
    pub fn pending_input_limit(mut self, limit: usize) -> Self {
        self.pending_input_limit = limit;
        self
    }

    /// Specify the path to the default font.
    ///
    /// By default this is "fonts/NotoSans/NotoSans-Regular.ttf".
    ///
    /// Fonts can also be specified manually after `Ui` creation using the `fonts_mut` method.
    pub fn default_font_path(mut self, path: PathBuf) -> Self {
        self.default_font_path = Some(path);
        self
    }

    /// Specify the dimensions of the texture used to cache glyphs on the GPU.
    ///
    /// By default this is equal to the framebuffer dimensions of the associated window at the time
    /// of building the `UI`.
    ///
    /// If you notice any glitching of UI text, this may be due to exceeding the bounds of the
    /// texture used to cache glyphs. Try using this to specify a larger glyph cache size to fix
    /// this.
    pub fn with_glyph_cache_dimensions(mut self, width: u32, height: u32) -> Self {
        self.glyph_cache_dimensions = Some((width, height));
        self
    }

    /// Build a `Ui` with the specified parameters.
    ///
    /// Returns `None` if the window at the given `Id` is closed or if the inner `Renderer` returns
    /// an error upon creation.
    pub fn build(self) -> Option<Ui> {
        let Builder {
            app,
            window_id,
            dimensions,
            theme,
            pending_input_limit,
            automatically_handle_input,
            default_font_path,
            glyph_cache_dimensions,
        } = self;
        let dimensions = match dimensions {
            None => match app.window(window_id) {
                None => return None,
                Some(window) => {
                    let (win_w, win_h) = window.inner_size_points();
                    [win_w as Scalar, win_h as Scalar]
                },
            },
            Some(dimensions) => dimensions,
        };
        let theme = theme.unwrap_or_else(Theme::default);
        let ui = conrod::UiBuilder::new(dimensions).theme(theme).build();

        let (input_rx, handle) = if automatically_handle_input {
            let (input_tx, input_rx) = mpsc::sync_channel(pending_input_limit);
            let input_tx = Some(input_tx);
            let input_rx = Some(input_rx);
            let handle = Handle { input_tx };
            (input_rx, handle)
        } else {
            let input_tx = None;
            let input_rx = None;
            let handle = Handle { input_tx };
            (input_rx, handle)
        };

        // Insert the handle into the app's UI arrangement.
        app.ui.windows.borrow_mut()
            .entry(window_id)
            .or_insert(Vec::new())
            .push(handle);

        // Initialise the renderer which draws conrod::render::Primitives to the frame..
        let renderer = match app.windows.borrow().get(&window_id) {
            None => return None,
            Some(window) => {
                let renderer = match glyph_cache_dimensions {
                    Some((w, h)) => {
                        conrod::backend::glium::Renderer::with_glyph_cache_dimensions(&window.display, w, h)
                    },
                    None => {
                        conrod::backend::glium::Renderer::new(&window.display)
                    },
                };
                match renderer {
                    Ok(renderer) => Mutex::new(renderer),
                    Err(_) => return None,
                }
            },
        };

        // Initialise the image map.
        let image_map = image::Map::new();

        // Initialise the `Ui`.
        let mut ui = Ui { window_id, ui, input_rx, renderer, image_map };

        // If the default font is in the assets/fonts directory, load it into the UI font map.
        let default_font_path = default_font_path
            .or_else(|| app.assets_path().ok().map(|p| p.join(Ui::DEFAULT_FONT_PATH)));

        // If there is some font path to use for the default font, attempt to load it.
        if let Some(font_path) = default_font_path {
            ui.fonts_mut().insert_from_file(font_path).ok();
        }

        Some(ui)
    }
}

impl Deref for Ui {
    type Target = conrod::Ui;
    fn deref(&self) -> &Self::Target {
        &self.ui
    }
}

impl Ui {
    /// The default maximum number of `Input`s that a `Ui` will store in its pending `Input` queue
    /// before `Input`s start being ignored.
    pub const DEFAULT_PENDING_INPUT_LIMIT: usize = 1024;
    /// The path to the default font for the `Ui`.
    pub const DEFAULT_FONT_PATH: &'static str = "fonts/NotoSans/NotoSans-Regular.ttf";

    /// Generate a new, unique `widget::Id` into a Placeholder node within the widget graph. This
    /// should only be called once for each unique widget needed to avoid unnecessary bloat within
    /// the `Ui`'s internal widget graph.
    ///
    /// When using this method, be sure to store the returned `widget::Id` somewhere so that it can
    /// be re-used on next update.
    ///
    /// **Panics** if adding another node would exceed the maximum capacity for node indices.
    pub fn generate_widget_id(&mut self) -> widget::Id {
        self.widget_id_generator().next()
    }

    /// Produces the type that may be used to generate new unique `widget::Id`s.
    pub fn widget_id_generator(&mut self) -> widget::id::Generator {
        self.ui.widget_id_generator()
    }

    /// Handle a raw UI input event and update the **Ui** state accordingly.
    ///
    /// This method *drives* the **Ui** forward and interprets input into higher-level events (like
    /// clicks and drags) for widgets.
    ///
    /// Note: By default, this will be called automatically by the nannou `App`, so most of the
    /// time you should not need to call this (otherwise received inputs may double up). This
    /// method is particularly useful in the case that automatic input handling has been disabled,
    /// as this can be used to manually submit inputs.
    pub fn handle_input(&mut self, input: Input) {
        self.ui.handle_event(input)
    }

    /// Processes all pending input.
    ///
    /// This is automatically called at the beginning of the `set_widgets` method, so the user
    /// should never need to call this manually, however the method is exposed for flexibility
    /// just in case.
    ///
    /// This has no effect if automatic input handling is disabled.
    pub fn handle_pending_input(&mut self) {
        let Ui { ref mut ui, ref input_rx, .. } = *self;
        if let Some(ref rx) = *input_rx {
            for input in rx.try_iter() {
                ui.handle_event(input);
            }
        }
    }

    /// Returns a context upon which UI widgets can be instantiated.
    ///
    /// The **UiCell** simply acts as a wrapper around the **Ui** for the period over which widgets
    /// are instantiated. Once the **UiCell** is dropped, it does some cleanup and sorting that is
    /// required after widget instantiation.
    pub fn set_widgets(&mut self) -> UiCell {
        // Process any pending inputs first.
        self.handle_pending_input();
        self.ui.set_widgets()
    }

    /// Mutable access to the `Ui`'s font map.
    ///
    /// This allows for adding and removing fonts to the UI.
    pub fn fonts_mut(&mut self) -> &mut text::font::Map {
        &mut self.ui.fonts
    }

    /// Mutable access to the `Ui`'s `Theme`.
    ///
    /// This allows for making changes to the active theme.
    pub fn theme_mut(&mut self) -> &mut Theme {
        &mut self.ui.theme
    }

    /// The first of the `Primitives` yielded by `Ui::draw` will always be a `Rectangle` the size
    /// of the window in which the Ui is instantiated.
    ///
    /// This method sets the colour with which this `Rectangle` is drawn (the default being
    /// `color::TRANSPARENT`).
    pub fn clear_with(&mut self, color: Color) {
        self.ui.clear_with(color)
    }

    /// Draws the current state of the `Ui` to the given `Frame`.
    ///
    /// The `Ui` will automatically draw to its associated window within the given `Frame`.
    ///
    /// If you require more control over where the `Ui` is drawn within the `Frame`, the `draw`
    /// method offers more flexibility.
    ///
    /// This has no effect if the window originally associated with the `Ui` no longer exists.
    pub fn draw_to_frame(&self, app: &App, frame: &Frame)
        -> Result<(), conrod::backend::glium::DrawError>
    {
        let Ui { ref ui, ref renderer, ref image_map, window_id, .. } = *self;
        if let Some(window) = app.window(window_id) {
            if let Some(mut window_frame) = frame.window(window_id) {
                if let Ok(mut renderer) = renderer.lock() {
                    let primitives = ui.draw();
                    renderer.fill(&window.display, primitives, &image_map);
                    window_frame.clear_color(0.0, 0.0, 0.0, 1.0);
                    renderer.draw(&window.display, &mut window_frame.frame.frame, image_map)?;
                }
            }
        }
        Ok(())
    }
}

/// Convert the given window event to a UI Input.
///
/// Returns `None` if there's no associated UI Input for the given event.
pub fn glutin_window_event_to_input(event: glutin::WindowEvent, window: &Window) -> Option<Input> {
    conrod::backend::winit::convert_window_event(event, window)
}
<|endoftext|>


<commit_before>use find_folder;
use conrod::{
    Button, Canvas, Colorable, Frameable, Positionable, Labelable, Sizeable, Theme,
    Ui, UiCell, Text, Widget, color
};
use piston_window::{G2d, Glyphs, Graphics, PistonWindow};

use game::{Rustris, GameState};
use stats::GameStats;
use settings::*;
use tetromino::Piece;

pub type Backend = (<G2d<'static> as Graphics>::Texture, Glyphs);
pub type UI = Ui<Backend>;
pub type UICell<'a> = UiCell<'a, Backend>;

pub fn create_ui(window: &PistonWindow) -> UI {
    let assets = find_folder::Search::KidsThenParents(3, 5)
        .for_folder("assets").unwrap();
    let font_path = assets.join("fonts/NotoSans/NotoSans-Regular.ttf");
    let theme = Theme::default();
    let glyph_cache = Glyphs::new(&font_path, window.factory.clone());
    UI::new(glyph_cache.unwrap(), theme)
}

pub fn set_ui(ref mut ui: UICell, game: &mut Rustris) {
    Canvas::new().flow_right(&[
        (LEFT_COLUMN, Canvas::new().color(color::DARK_CHARCOAL).pad(20.0)),
        (MIDDLE_COLUMN, Canvas::new().color(color::TRANSPARENT).length(300.0)),
        (RIGHT_COLUMN, Canvas::new().color(color::DARK_CHARCOAL).pad(20.0)),
    ]).set(MASTER, ui);
    set_scoreboard(ui, game.get_game_stats());
    set_next_piece(ui, game.get_next_piece());

    if game.is_paused() {
        set_pause_menu(ui, game);
    } else if game.is_game_over() {
        set_game_over_menu(ui, game);
    }

}

fn set_pause_menu(ui: &mut UICell, game: &mut Rustris) {
    Canvas::new()
      .w_h(WINDOW_WIDTH as f64, WINDOW_HEIGHT as f64)
      .floating(true)
      .middle_of(MASTER)
      .rgba(0.0, 0.0, 0.0, 0.3)
      .set(PAUSE_OVERLAY, ui);

    Canvas::new().flow_down(&[
        (RESUME_CANVAS, Canvas::new()),
        (QUIT_CANVAS, Canvas::new())
    ]).label("Paused")
      .label_color(color::WHITE)
      .w_h(200.0, 200.0)
      .frame(1.0)
      .frame_color(color::WHITE)
      .pad(1.0)
      .middle_of(PAUSE_OVERLAY)
      .set(PAUSE_MENU, ui);

    Button::new()
        .label("Resume")
        .label_color(color::WHITE)
        .color(color::CHARCOAL)
        .middle_of(RESUME_CANVAS)
        .w_h(150.0, 30.0)
        .react(|| {
            game.set_game_state(GameState::Playing);
        })
        .set(RESUME_BUTTON, ui);

    Button::new()
        .label("Quit")
        .label_color(color::WHITE)
        .color(color::CHARCOAL)
        .middle_of(QUIT_CANVAS)
        .w_h(150.0, 30.0)
        .react(|| {})
        .set(QUIT_BUTTON, ui);
}

fn set_game_over_menu(ui: &mut UICell, game: &mut Rustris) {
    Canvas::new()
      .w_h(WINDOW_WIDTH as f64, WINDOW_HEIGHT as f64)
      .floating(true)
      .middle_of(MASTER)
      .rgba(0.0, 0.0, 0.0, 0.3)
      .set(GAME_OVER_OVERLAY, ui);

    Canvas::new().flow_down(&[
        (FINAL_SCORE_CANVAS, Canvas::new()),
        (RESTART_CANVAS, Canvas::new())
    ]).label("Game Over")
      .label_color(color::WHITE)
      .w_h(200.0, 200.0)
      .frame(1.0)
      .frame_color(color::WHITE)
      .pad(1.0)
      .middle_of(GAME_OVER_OVERLAY)
      .set(GAME_OVER_MENU, ui);

    {
        let stats = game.get_game_stats();
        Text::new(
            &format!("Final Score: {}", stats.get_score().to_string()))
            .color(color::WHITE)
            .middle_of(FINAL_SCORE_CANVAS)
            .set(FINAL_SCORE_TEXT, ui);
    }

    Button::new()
        .label("New Game?")
        .label_color(color::WHITE)
        .color(color::CHARCOAL)
        .middle_of(RESTART_CANVAS)
        .w_h(150.0, 30.0)
        .react(|| {
            game.reset();
        })
        .set(NEW_GAME_BUTTON, ui);
}

fn set_scoreboard(ui: &mut UICell, stats: &GameStats) {
    Canvas::new().flow_down(&[
        (SCORE_CANVAS, Canvas::new().label("Score").label_color(color::WHITE)),
        (LEVEL_CANVAS, Canvas::new().label("Level").label_color(color::WHITE)),
        (LINES_CANVAS, Canvas::new().label("Lines").label_color(color::WHITE))
    ]).w_h(150.0, 250.0)
      .frame(1.0)
      .frame_color(color::WHITE)
      .pad(1.0)
      .mid_bottom_of(LEFT_COLUMN)
      .set(SCOREBOARD, ui);

    Text::new(&stats.get_score().to_string())
        .color(color::WHITE)
        .middle_of(SCORE_CANVAS)
        .set(SCORE, ui);
    Text::new(&stats.get_level().to_string())
        .color(color::WHITE)
        .middle_of(LEVEL_CANVAS)
        .set(LEVEL, ui);
    Text::new(&stats.get_lines().to_string())
        .color(color::WHITE)
        .middle_of(LINES_CANVAS)
        .set(LINES, ui);
}

fn set_next_piece(ui: &mut UICell, next_piece: &Piece) {
    Canvas::new()
        .label("Next Piece")
        .label_color(color::WHITE)
        .w_h(150.0, 150.0)
        .mid_top_of(RIGHT_COLUMN)
        .set(NEXT_PIECE, ui);
}

widget_ids! {
    // Canvas IDs
    MASTER,
    LEFT_COLUMN,
    MIDDLE_COLUMN,
    RIGHT_COLUMN,

    // Scoreboard IDs
    SCOREBOARD,
    SCORE_CANVAS,
    LEVEL_CANVAS,
    LINES_CANVAS,
    SCORE,
    LEVEL,
    LINES,

    // Pause Menu
    PAUSE_OVERLAY,
    PAUSE_MENU,
    RESUME_CANVAS,
    RESUME_BUTTON,
    QUIT_CANVAS,
    QUIT_BUTTON,

    // Game Over Menu
    GAME_OVER_OVERLAY,
    GAME_OVER_MENU,
    NEW_GAME_BUTTON,
    RESTART_CANVAS,
    FINAL_SCORE_CANVAS,
    FINAL_SCORE_TEXT,

    // Next Piece IDs
    NEXT_PIECE
}
<commit_msg>add a frame to the next piece block<commit_after>use find_folder;
use conrod::{
    Button, Canvas, Colorable, Frameable, Positionable, Labelable, Sizeable, Theme,
    Ui, UiCell, Text, Widget, color
};
use piston_window::{G2d, Glyphs, Graphics, PistonWindow};

use game::{Rustris, GameState};
use stats::GameStats;
use settings::*;
use tetromino::Piece;

pub type Backend = (<G2d<'static> as Graphics>::Texture, Glyphs);
pub type UI = Ui<Backend>;
pub type UICell<'a> = UiCell<'a, Backend>;

pub fn create_ui(window: &PistonWindow) -> UI {
    let assets = find_folder::Search::KidsThenParents(3, 5)
        .for_folder("assets").unwrap();
    let font_path = assets.join("fonts/NotoSans/NotoSans-Regular.ttf");
    let theme = Theme::default();
    let glyph_cache = Glyphs::new(&font_path, window.factory.clone());
    UI::new(glyph_cache.unwrap(), theme)
}

pub fn set_ui(ref mut ui: UICell, game: &mut Rustris) {
    Canvas::new().flow_right(&[
        (LEFT_COLUMN, Canvas::new().color(color::DARK_CHARCOAL).pad(20.0)),
        (MIDDLE_COLUMN, Canvas::new().color(color::TRANSPARENT).length(300.0)),
        (RIGHT_COLUMN, Canvas::new().color(color::DARK_CHARCOAL).pad(20.0)),
    ]).set(MASTER, ui);
    set_scoreboard(ui, game.get_game_stats());
    set_next_piece(ui, game.get_next_piece());

    if game.is_paused() {
        set_pause_menu(ui, game);
    } else if game.is_game_over() {
        set_game_over_menu(ui, game);
    }

}

fn set_pause_menu(ui: &mut UICell, game: &mut Rustris) {
    Canvas::new()
      .w_h(WINDOW_WIDTH as f64, WINDOW_HEIGHT as f64)
      .floating(true)
      .middle_of(MASTER)
      .rgba(0.0, 0.0, 0.0, 0.3)
      .set(PAUSE_OVERLAY, ui);

    Canvas::new().flow_down(&[
        (RESUME_CANVAS, Canvas::new()),
        (QUIT_CANVAS, Canvas::new())
    ]).label("Paused")
      .label_color(color::WHITE)
      .w_h(200.0, 200.0)
      .frame(1.0)
      .frame_color(color::WHITE)
      .pad(1.0)
      .middle_of(PAUSE_OVERLAY)
      .set(PAUSE_MENU, ui);

    Button::new()
        .label("Resume")
        .label_color(color::WHITE)
        .color(color::CHARCOAL)
        .middle_of(RESUME_CANVAS)
        .w_h(150.0, 30.0)
        .react(|| {
            game.set_game_state(GameState::Playing);
        })
        .set(RESUME_BUTTON, ui);

    Button::new()
        .label("Quit")
        .label_color(color::WHITE)
        .color(color::CHARCOAL)
        .middle_of(QUIT_CANVAS)
        .w_h(150.0, 30.0)
        .react(|| {})
        .set(QUIT_BUTTON, ui);
}

fn set_game_over_menu(ui: &mut UICell, game: &mut Rustris) {
    Canvas::new()
      .w_h(WINDOW_WIDTH as f64, WINDOW_HEIGHT as f64)
      .floating(true)
      .middle_of(MASTER)
      .rgba(0.0, 0.0, 0.0, 0.3)
      .set(GAME_OVER_OVERLAY, ui);

    Canvas::new().flow_down(&[
        (FINAL_SCORE_CANVAS, Canvas::new()),
        (RESTART_CANVAS, Canvas::new())
    ]).label("Game Over")
      .label_color(color::WHITE)
      .w_h(200.0, 200.0)
      .frame(1.0)
      .frame_color(color::WHITE)
      .pad(1.0)
      .middle_of(GAME_OVER_OVERLAY)
      .set(GAME_OVER_MENU, ui);

    {
        let stats = game.get_game_stats();
        Text::new(
            &format!("Final Score: {}", stats.get_score().to_string()))
            .color(color::WHITE)
            .middle_of(FINAL_SCORE_CANVAS)
            .set(FINAL_SCORE_TEXT, ui);
    }

    Button::new()
        .label("New Game?")
        .label_color(color::WHITE)
        .color(color::CHARCOAL)
        .middle_of(RESTART_CANVAS)
        .w_h(150.0, 30.0)
        .react(|| {
            game.reset();
        })
        .set(NEW_GAME_BUTTON, ui);
}

fn set_scoreboard(ui: &mut UICell, stats: &GameStats) {
    Canvas::new().flow_down(&[
        (SCORE_CANVAS, Canvas::new().label("Score").label_color(color::WHITE)),
        (LEVEL_CANVAS, Canvas::new().label("Level").label_color(color::WHITE)),
        (LINES_CANVAS, Canvas::new().label("Lines").label_color(color::WHITE))
    ]).w_h(150.0, 250.0)
      .frame(1.0)
      .frame_color(color::WHITE)
      .pad(1.0)
      .mid_bottom_of(LEFT_COLUMN)
      .set(SCOREBOARD, ui);

    Text::new(&stats.get_score().to_string())
        .color(color::WHITE)
        .middle_of(SCORE_CANVAS)
        .set(SCORE, ui);
    Text::new(&stats.get_level().to_string())
        .color(color::WHITE)
        .middle_of(LEVEL_CANVAS)
        .set(LEVEL, ui);
    Text::new(&stats.get_lines().to_string())
        .color(color::WHITE)
        .middle_of(LINES_CANVAS)
        .set(LINES, ui);
}

fn set_next_piece(ui: &mut UICell, next_piece: &Piece) {
    Canvas::new()
        .label("Next Piece")
        .label_color(color::WHITE)
        .w_h(150.0, 150.0)
        .frame(1.0)
        .frame_color(color::WHITE)
        .pad(1.0)
        .mid_top_of(RIGHT_COLUMN)
        .set(NEXT_PIECE, ui);
}

widget_ids! {
    // Canvas IDs
    MASTER,
    LEFT_COLUMN,
    MIDDLE_COLUMN,
    RIGHT_COLUMN,

    // Scoreboard IDs
    SCOREBOARD,
    SCORE_CANVAS,
    LEVEL_CANVAS,
    LINES_CANVAS,
    SCORE,
    LEVEL,
    LINES,

    // Pause Menu
    PAUSE_OVERLAY,
    PAUSE_MENU,
    RESUME_CANVAS,
    RESUME_BUTTON,
    QUIT_CANVAS,
    QUIT_BUTTON,

    // Game Over Menu
    GAME_OVER_OVERLAY,
    GAME_OVER_MENU,
    NEW_GAME_BUTTON,
    RESTART_CANVAS,
    FINAL_SCORE_CANVAS,
    FINAL_SCORE_TEXT,

    // Next Piece IDs
    NEXT_PIECE
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap};
use std::fmt::Display;
use std::hash::{Hash, Hasher};
use std::mem;
use std::rc::Rc;

use serde::{Serialize, Serializer};

use crate::core::interning::InternedString;
use crate::core::{Dependency, PackageId, SourceId};
use semver::Version;

use crate::util::CargoResult;

/// Subset of a `Manifest`. Contains only the most important information about
/// a package.
///
/// Summaries are cloned, and should not be mutated after creation
#[derive(Debug, Clone)]
pub struct Summary {
    inner: Rc<Inner>,
}

#[derive(Debug, Clone)]
struct Inner {
    package_id: PackageId,
    dependencies: Vec<Dependency>,
    features: FeatureMap,
    checksum: Option<String>,
    links: Option<InternedString>,
    namespaced_features: bool,
}

impl Summary {
    pub fn new<K>(
        pkg_id: PackageId,
        dependencies: Vec<Dependency>,
        features: &BTreeMap<K, Vec<impl AsRef<str>>>,
        links: Option<impl Into<InternedString>>,
        namespaced_features: bool,
    ) -> CargoResult<Summary>
    where
        K: Borrow<str> + Ord + Display,
    {
        for dep in dependencies.iter() {
            let feature = dep.name_in_toml();
            if !namespaced_features && features.get(&*feature).is_some() {
                failure::bail!(
                    "Features and dependencies cannot have the \
                     same name: `{}`",
                    feature
                )
            }
            if dep.is_optional() && !dep.is_transitive() {
                failure::bail!(
                    "Dev-dependencies are not allowed to be optional: `{}`",
                    feature
                )
            }
        }
        let feature_map = build_feature_map(features, &dependencies, namespaced_features)?;
        Ok(Summary {
            inner: Rc::new(Inner {
                package_id: pkg_id,
                dependencies,
                features: feature_map,
                checksum: None,
                links: links.map(|l| l.into()),
                namespaced_features,
            }),
        })
    }

    pub fn package_id(&self) -> PackageId {
        self.inner.package_id
    }
    pub fn name(&self) -> InternedString {
        self.package_id().name()
    }
    pub fn version(&self) -> &Version {
        self.package_id().version()
    }
    pub fn source_id(&self) -> SourceId {
        self.package_id().source_id()
    }
    pub fn dependencies(&self) -> &[Dependency] {
        &self.inner.dependencies
    }
    pub fn features(&self) -> &FeatureMap {
        &self.inner.features
    }
    pub fn checksum(&self) -> Option<&str> {
        self.inner.checksum.as_ref().map(|s| &s[..])
    }
    pub fn links(&self) -> Option<InternedString> {
        self.inner.links
    }
    pub fn namespaced_features(&self) -> bool {
        self.inner.namespaced_features
    }

    pub fn override_id(mut self, id: PackageId) -> Summary {
        Rc::make_mut(&mut self.inner).package_id = id;
        self
    }

    pub fn set_checksum(&mut self, cksum: String) {
        Rc::make_mut(&mut self.inner).checksum = Some(cksum);
    }

    pub fn map_dependencies<F>(mut self, f: F) -> Summary
    where
        F: FnMut(Dependency) -> Dependency,
    {
        {
            let slot = &mut Rc::make_mut(&mut self.inner).dependencies;
            let deps = mem::replace(slot, Vec::new());
            *slot = deps.into_iter().map(f).collect();
        }
        self
    }

    pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Summary {
        let me = if self.package_id().source_id() == to_replace {
            let new_id = self.package_id().with_source_id(replace_with);
            self.override_id(new_id)
        } else {
            self
        };
        me.map_dependencies(|dep| dep.map_source(to_replace, replace_with))
    }
}

impl PartialEq for Summary {
    fn eq(&self, other: &Summary) -> bool {
        self.inner.package_id == other.inner.package_id
    }
}

impl Eq for Summary {}

impl Hash for Summary {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.inner.package_id.hash(state);
    }
}

// Checks features for errors, bailing out a CargoResult:Err if invalid,
// and creates FeatureValues for each feature.
fn build_feature_map<K>(
    features: &BTreeMap<K, Vec<impl AsRef<str>>>,
    dependencies: &[Dependency],
    namespaced: bool,
) -> CargoResult<FeatureMap>
where
    K: Borrow<str> + Ord + Display,
{
    use self::FeatureValue::*;
    let mut dep_map = HashMap::new();
    for dep in dependencies.iter() {
        dep_map
            .entry(dep.name_in_toml())
            .or_insert_with(Vec::new)
            .push(dep);
    }

    let mut map = BTreeMap::new();
    for (feature, list) in features.iter() {
        // If namespaced features is active and the key is the same as that of an
        // optional dependency, that dependency must be included in the values.
        // Thus, if a `feature` is found that has the same name as a dependency, we
        // (a) bail out if the dependency is non-optional, and (b) we track if the
        // feature requirements include the dependency `crate:feature` in the list.
        // This is done with the `dependency_found` variable, which can only be
        // false if features are namespaced and the current feature key is the same
        // as the name of an optional dependency. If so, it gets set to true during
        // iteration over the list if the dependency is found in the list.
        let mut dependency_found = if namespaced {
            match dep_map.get(feature.borrow()) {
                Some(dep_data) => {
                    if !dep_data.iter().any(|d| d.is_optional()) {
                        failure::bail!(
                            "Feature `{}` includes the dependency of the same name, but this is \
                             left implicit in the features included by this feature.\n\
                             Additionally, the dependency must be marked as optional to be \
                             included in the feature definition.\n\
                             Consider adding `crate:{}` to this feature's requirements \
                             and marking the dependency as `optional = true`",
                            feature,
                            feature
                        )
                    } else {
                        false
                    }
                }
                None => true,
            }
        } else {
            true
        };

        let mut values = vec![];
        for dep in list {
            let val = FeatureValue::build(
                InternedString::new(dep.as_ref()),
                |fs| features.contains_key(fs.as_str()),
                namespaced,
            );

            // Find data for the referenced dependency...
            let dep_data = {
                match val {
                    Feature(ref dep_name) | Crate(ref dep_name) | CrateFeature(ref dep_name, _) => {
                        dep_map.get(dep_name.as_str())
                    }
                }
            };
            let is_optional_dep = dep_data
                .iter()
                .flat_map(|d| d.iter())
                .any(|d| d.is_optional());
            if let FeatureValue::Crate(ref dep_name) = val {
                // If we have a dependency value, check if this is the dependency named
                // the same as the feature that we were looking for.
                if !dependency_found && feature.borrow() == dep_name.as_str() {
                    dependency_found = true;
                }
            }

            match (&val, dep_data.is_some(), is_optional_dep) {
                // The value is a feature. If features are namespaced, this just means
                // it's not prefixed with `crate:`, so we have to check whether the
                // feature actually exist. If the feature is not defined *and* an optional
                // dependency of the same name exists, the feature is defined implicitly
                // here by adding it to the feature map, pointing to the dependency.
                // If features are not namespaced, it's been validated as a feature already
                // while instantiating the `FeatureValue` in `FeatureValue::build()`, so
                // we don't have to do so here.
                (&Feature(feat), _, true) => {
                    if namespaced && !features.contains_key(&*feat) {
                        map.insert(feat, vec![FeatureValue::Crate(feat)]);
                    }
                }
                // If features are namespaced and the value is not defined as a feature
                // and there is no optional dependency of the same name, error out.
                // If features are not namespaced, there must be an existing feature
                // here (checked by `FeatureValue::build()`), so it will always be defined.
                (&Feature(feat), dep_exists, false) => {
                    if namespaced && !features.contains_key(&*feat) {
                        if dep_exists {
                            failure::bail!(
                                "Feature `{}` includes `{}` which is not defined as a feature.\n\
                                 A non-optional dependency of the same name is defined; consider \
                                 adding `optional = true` to its definition",
                                feature,
                                feat
                            )
                        } else {
                            failure::bail!(
                                "Feature `{}` includes `{}` which is not defined as a feature",
                                feature,
                                feat
                            )
                        }
                    }
                }
                // The value is a dependency. If features are namespaced, it is explicitly
                // tagged as such (`crate:value`). If features are not namespaced, any value
                // not recognized as a feature is pegged as a `Crate`. Here we handle the case
                // where the dependency exists but is non-optional. It branches on namespaced
                // just to provide the correct string for the crate dependency in the error.
                (&Crate(ref dep), true, false) => {
                    if namespaced {
                        failure::bail!(
                            "Feature `{}` includes `crate:{}` which is not an \
                             optional dependency.\nConsider adding \
                             `optional = true` to the dependency",
                            feature,
                            dep
                        )
                    } else {
                        failure::bail!(
                            "Feature `{}` depends on `{}` which is not an \
                             optional dependency.\nConsider adding \
                             `optional = true` to the dependency",
                            feature,
                            dep
                        )
                    }
                }
                // If namespaced, the value was tagged as a dependency; if not namespaced,
                // this could be anything not defined as a feature. This handles the case
                // where no such dependency is actually defined; again, the branch on
                // namespaced here is just to provide the correct string in the error.
                (&Crate(ref dep), false, _) => {
                    if namespaced {
                        failure::bail!(
                            "Feature `{}` includes `crate:{}` which is not a known \
                             dependency",
                            feature,
                            dep
                        )
                    } else {
                        failure::bail!(
                            "Feature `{}` includes `{}` which is neither a dependency nor \
                             another feature",
                            feature,
                            dep
                        )
                    }
                }
                (&Crate(_), true, true) => {}
                // If the value is a feature for one of the dependencies, bail out if no such
                // dependency is actually defined in the manifest.
                (&CrateFeature(ref dep, _), false, _) => failure::bail!(
                    "Feature `{}` requires a feature of `{}` which is not a \
                     dependency",
                    feature,
                    dep
                ),
                (&CrateFeature(_, _), true, _) => {}
            }
            values.push(val);
        }

        if !dependency_found {
            // If we have not found the dependency of the same-named feature, we should
            // bail here.
            failure::bail!(
                "Feature `{}` includes the optional dependency of the \
                 same name, but this is left implicit in the features \
                 included by this feature.\nConsider adding \
                 `crate:{}` to this feature's requirements.",
                feature,
                feature
            )
        }

        map.insert(InternedString::new(feature.borrow()), values);
    }
    Ok(map)
}

/// FeatureValue represents the types of dependencies a feature can have:
///
/// * Another feature
/// * An optional dependency
/// * A feature in a dependency
///
/// The selection between these 3 things happens as part of the construction of the FeatureValue.
#[derive(Clone, Debug)]
pub enum FeatureValue {
    Feature(InternedString),
    Crate(InternedString),
    CrateFeature(InternedString, InternedString),
}

impl FeatureValue {
    fn build<T>(feature: InternedString, is_feature: T, namespaced: bool) -> FeatureValue
    where
        T: Fn(InternedString) -> bool,
    {
        match (feature.find('/'), namespaced) {
            (Some(pos), _) => {
                let (dep, dep_feat) = feature.split_at(pos);
                let dep_feat = &dep_feat[1..];
                FeatureValue::CrateFeature(InternedString::new(dep), InternedString::new(dep_feat))
            }
            (None, true) if feature.starts_with("crate:") => {
                FeatureValue::Crate(InternedString::new(&feature[6..]))
            }
            (None, true) => FeatureValue::Feature(feature),
            (None, false) if is_feature(feature) => FeatureValue::Feature(feature),
            (None, false) => FeatureValue::Crate(feature),
        }
    }

    pub fn new(feature: InternedString, s: &Summary) -> FeatureValue {
        Self::build(
            feature,
            |fs| s.features().contains_key(&fs),
            s.namespaced_features(),
        )
    }

    pub fn to_string(&self, s: &Summary) -> String {
        use self::FeatureValue::*;
        match *self {
            Feature(ref f) => f.to_string(),
            Crate(ref c) => {
                if s.namespaced_features() {
                    format!("crate:{}", &c)
                } else {
                    c.to_string()
                }
            }
            CrateFeature(ref c, ref f) => [c.as_ref(), f.as_ref()].join("/"),
        }
    }
}

impl Serialize for FeatureValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        use self::FeatureValue::*;
        match *self {
            Feature(ref f) => serializer.serialize_str(f),
            Crate(ref c) => serializer.serialize_str(c),
            CrateFeature(ref c, ref f) => {
                serializer.serialize_str(&[c.as_ref(), f.as_ref()].join("/"))
            }
        }
    }
}

pub type FeatureMap = BTreeMap<InternedString, Vec<FeatureValue>>;
<commit_msg>Auto merge of #7326 - Eh2406:map_dependencies, r=ehuss<commit_after>use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap};
use std::fmt::Display;
use std::hash::{Hash, Hasher};
use std::mem;
use std::rc::Rc;

use serde::{Serialize, Serializer};

use crate::core::interning::InternedString;
use crate::core::{Dependency, PackageId, SourceId};
use semver::Version;

use crate::util::CargoResult;

/// Subset of a `Manifest`. Contains only the most important information about
/// a package.
///
/// Summaries are cloned, and should not be mutated after creation
#[derive(Debug, Clone)]
pub struct Summary {
    inner: Rc<Inner>,
}

#[derive(Debug, Clone)]
struct Inner {
    package_id: PackageId,
    dependencies: Vec<Dependency>,
    features: Rc<FeatureMap>,
    checksum: Option<String>,
    links: Option<InternedString>,
    namespaced_features: bool,
}

impl Summary {
    pub fn new<K>(
        pkg_id: PackageId,
        dependencies: Vec<Dependency>,
        features: &BTreeMap<K, Vec<impl AsRef<str>>>,
        links: Option<impl Into<InternedString>>,
        namespaced_features: bool,
    ) -> CargoResult<Summary>
    where
        K: Borrow<str> + Ord + Display,
    {
        for dep in dependencies.iter() {
            let feature = dep.name_in_toml();
            if !namespaced_features && features.get(&*feature).is_some() {
                failure::bail!(
                    "Features and dependencies cannot have the \
                     same name: `{}`",
                    feature
                )
            }
            if dep.is_optional() && !dep.is_transitive() {
                failure::bail!(
                    "Dev-dependencies are not allowed to be optional: `{}`",
                    feature
                )
            }
        }
        let feature_map = build_feature_map(features, &dependencies, namespaced_features)?;
        Ok(Summary {
            inner: Rc::new(Inner {
                package_id: pkg_id,
                dependencies,
                features: Rc::new(feature_map),
                checksum: None,
                links: links.map(|l| l.into()),
                namespaced_features,
            }),
        })
    }

    pub fn package_id(&self) -> PackageId {
        self.inner.package_id
    }
    pub fn name(&self) -> InternedString {
        self.package_id().name()
    }
    pub fn version(&self) -> &Version {
        self.package_id().version()
    }
    pub fn source_id(&self) -> SourceId {
        self.package_id().source_id()
    }
    pub fn dependencies(&self) -> &[Dependency] {
        &self.inner.dependencies
    }
    pub fn features(&self) -> &FeatureMap {
        &self.inner.features
    }
    pub fn checksum(&self) -> Option<&str> {
        self.inner.checksum.as_ref().map(|s| &s[..])
    }
    pub fn links(&self) -> Option<InternedString> {
        self.inner.links
    }
    pub fn namespaced_features(&self) -> bool {
        self.inner.namespaced_features
    }

    pub fn override_id(mut self, id: PackageId) -> Summary {
        Rc::make_mut(&mut self.inner).package_id = id;
        self
    }

    pub fn set_checksum(&mut self, cksum: String) {
        Rc::make_mut(&mut self.inner).checksum = Some(cksum);
    }

    pub fn map_dependencies<F>(mut self, f: F) -> Summary
    where
        F: FnMut(Dependency) -> Dependency,
    {
        {
            let slot = &mut Rc::make_mut(&mut self.inner).dependencies;
            let deps = mem::replace(slot, Vec::new());
            *slot = deps.into_iter().map(f).collect();
        }
        self
    }

    pub fn map_source(self, to_replace: SourceId, replace_with: SourceId) -> Summary {
        let me = if self.package_id().source_id() == to_replace {
            let new_id = self.package_id().with_source_id(replace_with);
            self.override_id(new_id)
        } else {
            self
        };
        me.map_dependencies(|dep| dep.map_source(to_replace, replace_with))
    }
}

impl PartialEq for Summary {
    fn eq(&self, other: &Summary) -> bool {
        self.inner.package_id == other.inner.package_id
    }
}

impl Eq for Summary {}

impl Hash for Summary {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.inner.package_id.hash(state);
    }
}

// Checks features for errors, bailing out a CargoResult:Err if invalid,
// and creates FeatureValues for each feature.
fn build_feature_map<K>(
    features: &BTreeMap<K, Vec<impl AsRef<str>>>,
    dependencies: &[Dependency],
    namespaced: bool,
) -> CargoResult<FeatureMap>
where
    K: Borrow<str> + Ord + Display,
{
    use self::FeatureValue::*;
    let mut dep_map = HashMap::new();
    for dep in dependencies.iter() {
        dep_map
            .entry(dep.name_in_toml())
            .or_insert_with(Vec::new)
            .push(dep);
    }

    let mut map = BTreeMap::new();
    for (feature, list) in features.iter() {
        // If namespaced features is active and the key is the same as that of an
        // optional dependency, that dependency must be included in the values.
        // Thus, if a `feature` is found that has the same name as a dependency, we
        // (a) bail out if the dependency is non-optional, and (b) we track if the
        // feature requirements include the dependency `crate:feature` in the list.
        // This is done with the `dependency_found` variable, which can only be
        // false if features are namespaced and the current feature key is the same
        // as the name of an optional dependency. If so, it gets set to true during
        // iteration over the list if the dependency is found in the list.
        let mut dependency_found = if namespaced {
            match dep_map.get(feature.borrow()) {
                Some(dep_data) => {
                    if !dep_data.iter().any(|d| d.is_optional()) {
                        failure::bail!(
                            "Feature `{}` includes the dependency of the same name, but this is \
                             left implicit in the features included by this feature.\n\
                             Additionally, the dependency must be marked as optional to be \
                             included in the feature definition.\n\
                             Consider adding `crate:{}` to this feature's requirements \
                             and marking the dependency as `optional = true`",
                            feature,
                            feature
                        )
                    } else {
                        false
                    }
                }
                None => true,
            }
        } else {
            true
        };

        let mut values = vec![];
        for dep in list {
            let val = FeatureValue::build(
                InternedString::new(dep.as_ref()),
                |fs| features.contains_key(fs.as_str()),
                namespaced,
            );

            // Find data for the referenced dependency...
            let dep_data = {
                match val {
                    Feature(ref dep_name) | Crate(ref dep_name) | CrateFeature(ref dep_name, _) => {
                        dep_map.get(dep_name.as_str())
                    }
                }
            };
            let is_optional_dep = dep_data
                .iter()
                .flat_map(|d| d.iter())
                .any(|d| d.is_optional());
            if let FeatureValue::Crate(ref dep_name) = val {
                // If we have a dependency value, check if this is the dependency named
                // the same as the feature that we were looking for.
                if !dependency_found && feature.borrow() == dep_name.as_str() {
                    dependency_found = true;
                }
            }

            match (&val, dep_data.is_some(), is_optional_dep) {
                // The value is a feature. If features are namespaced, this just means
                // it's not prefixed with `crate:`, so we have to check whether the
                // feature actually exist. If the feature is not defined *and* an optional
                // dependency of the same name exists, the feature is defined implicitly
                // here by adding it to the feature map, pointing to the dependency.
                // If features are not namespaced, it's been validated as a feature already
                // while instantiating the `FeatureValue` in `FeatureValue::build()`, so
                // we don't have to do so here.
                (&Feature(feat), _, true) => {
                    if namespaced && !features.contains_key(&*feat) {
                        map.insert(feat, vec![FeatureValue::Crate(feat)]);
                    }
                }
                // If features are namespaced and the value is not defined as a feature
                // and there is no optional dependency of the same name, error out.
                // If features are not namespaced, there must be an existing feature
                // here (checked by `FeatureValue::build()`), so it will always be defined.
                (&Feature(feat), dep_exists, false) => {
                    if namespaced && !features.contains_key(&*feat) {
                        if dep_exists {
                            failure::bail!(
                                "Feature `{}` includes `{}` which is not defined as a feature.\n\
                                 A non-optional dependency of the same name is defined; consider \
                                 adding `optional = true` to its definition",
                                feature,
                                feat
                            )
                        } else {
                            failure::bail!(
                                "Feature `{}` includes `{}` which is not defined as a feature",
                                feature,
                                feat
                            )
                        }
                    }
                }
                // The value is a dependency. If features are namespaced, it is explicitly
                // tagged as such (`crate:value`). If features are not namespaced, any value
                // not recognized as a feature is pegged as a `Crate`. Here we handle the case
                // where the dependency exists but is non-optional. It branches on namespaced
                // just to provide the correct string for the crate dependency in the error.
                (&Crate(ref dep), true, false) => {
                    if namespaced {
                        failure::bail!(
                            "Feature `{}` includes `crate:{}` which is not an \
                             optional dependency.\nConsider adding \
                             `optional = true` to the dependency",
                            feature,
                            dep
                        )
                    } else {
                        failure::bail!(
                            "Feature `{}` depends on `{}` which is not an \
                             optional dependency.\nConsider adding \
                             `optional = true` to the dependency",
                            feature,
                            dep
                        )
                    }
                }
                // If namespaced, the value was tagged as a dependency; if not namespaced,
                // this could be anything not defined as a feature. This handles the case
                // where no such dependency is actually defined; again, the branch on
                // namespaced here is just to provide the correct string in the error.
                (&Crate(ref dep), false, _) => {
                    if namespaced {
                        failure::bail!(
                            "Feature `{}` includes `crate:{}` which is not a known \
                             dependency",
                            feature,
                            dep
                        )
                    } else {
                        failure::bail!(
                            "Feature `{}` includes `{}` which is neither a dependency nor \
                             another feature",
                            feature,
                            dep
                        )
                    }
                }
                (&Crate(_), true, true) => {}
                // If the value is a feature for one of the dependencies, bail out if no such
                // dependency is actually defined in the manifest.
                (&CrateFeature(ref dep, _), false, _) => failure::bail!(
                    "Feature `{}` requires a feature of `{}` which is not a \
                     dependency",
                    feature,
                    dep
                ),
                (&CrateFeature(_, _), true, _) => {}
            }
            values.push(val);
        }

        if !dependency_found {
            // If we have not found the dependency of the same-named feature, we should
            // bail here.
            failure::bail!(
                "Feature `{}` includes the optional dependency of the \
                 same name, but this is left implicit in the features \
                 included by this feature.\nConsider adding \
                 `crate:{}` to this feature's requirements.",
                feature,
                feature
            )
        }

        map.insert(InternedString::new(feature.borrow()), values);
    }
    Ok(map)
}

/// FeatureValue represents the types of dependencies a feature can have:
///
/// * Another feature
/// * An optional dependency
/// * A feature in a dependency
///
/// The selection between these 3 things happens as part of the construction of the FeatureValue.
#[derive(Clone, Debug)]
pub enum FeatureValue {
    Feature(InternedString),
    Crate(InternedString),
    CrateFeature(InternedString, InternedString),
}

impl FeatureValue {
    fn build<T>(feature: InternedString, is_feature: T, namespaced: bool) -> FeatureValue
    where
        T: Fn(InternedString) -> bool,
    {
        match (feature.find('/'), namespaced) {
            (Some(pos), _) => {
                let (dep, dep_feat) = feature.split_at(pos);
                let dep_feat = &dep_feat[1..];
                FeatureValue::CrateFeature(InternedString::new(dep), InternedString::new(dep_feat))
            }
            (None, true) if feature.starts_with("crate:") => {
                FeatureValue::Crate(InternedString::new(&feature[6..]))
            }
            (None, true) => FeatureValue::Feature(feature),
            (None, false) if is_feature(feature) => FeatureValue::Feature(feature),
            (None, false) => FeatureValue::Crate(feature),
        }
    }

    pub fn new(feature: InternedString, s: &Summary) -> FeatureValue {
        Self::build(
            feature,
            |fs| s.features().contains_key(&fs),
            s.namespaced_features(),
        )
    }

    pub fn to_string(&self, s: &Summary) -> String {
        use self::FeatureValue::*;
        match *self {
            Feature(ref f) => f.to_string(),
            Crate(ref c) => {
                if s.namespaced_features() {
                    format!("crate:{}", &c)
                } else {
                    c.to_string()
                }
            }
            CrateFeature(ref c, ref f) => [c.as_ref(), f.as_ref()].join("/"),
        }
    }
}

impl Serialize for FeatureValue {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        use self::FeatureValue::*;
        match *self {
            Feature(ref f) => serializer.serialize_str(f),
            Crate(ref c) => serializer.serialize_str(c),
            CrateFeature(ref c, ref f) => {
                serializer.serialize_str(&[c.as_ref(), f.as_ref()].join("/"))
            }
        }
    }
}

pub type FeatureMap = BTreeMap<InternedString, Vec<FeatureValue>>;
<|endoftext|>


<commit_before>use crate::syscall::io::{Io, Pio, Mmio, ReadOnly};

bitflags! {
    /// Interrupt enable flags
    struct IntEnFlags: u8 {
        const RECEIVED = 1;
        const SENT = 1 << 1;
        const ERRORED = 1 << 2;
        const STATUS_CHANGE = 1 << 3;
        // 4 to 7 are unused
    }
}

bitflags! {
    /// Line status flags
    struct LineStsFlags: u8 {
        const INPUT_FULL = 1;
        // 1 to 4 unknown
        const OUTPUT_EMPTY = 1 << 5;
        // 6 and 7 unknown
    }
}

#[allow(dead_code)]
pub struct SerialPort<T: Io<Value = u8>> {
    /// Data register, read to receive, write to send
    data: T,
    /// Interrupt enable
    int_en: T,
    /// FIFO control
    fifo_ctrl: T,
    /// Line control
    line_ctrl: T,
    /// Modem control
    modem_ctrl: T,
    /// Line status
    line_sts: ReadOnly<T>,
    /// Modem status
    modem_sts: ReadOnly<T>,
}

impl SerialPort<Pio<u8>> {
    pub const fn new(base: u16) -> SerialPort<Pio<u8>> {
        SerialPort {
            data: Pio::new(base),
            int_en: Pio::new(base + 1),
            fifo_ctrl: Pio::new(base + 2),
            line_ctrl: Pio::new(base + 3),
            modem_ctrl: Pio::new(base + 4),
            line_sts: ReadOnly::new(Pio::new(base + 5)),
            modem_sts: ReadOnly::new(Pio::new(base + 6))
        }
    }
}

impl SerialPort<Mmio<u8>> {
    pub fn new(_base: usize) -> SerialPort<Mmio<u8>> {
        SerialPort {
            data: Mmio::new(),
            int_en: Mmio::new(),
            fifo_ctrl: Mmio::new(),
            line_ctrl: Mmio::new(),
            modem_ctrl: Mmio::new(),
            line_sts: ReadOnly::new(Mmio::new()),
            modem_sts: ReadOnly::new(Mmio::new())
        }
    }
}

impl<T: Io<Value = u8>> SerialPort<T> {
    pub fn init(&mut self) {
        //TODO: Cleanup
        self.int_en.write(0x00);
        self.line_ctrl.write(0x80);
        self.data.write(0x01);
        self.int_en.write(0x00);
        self.line_ctrl.write(0x03);
        self.fifo_ctrl.write(0xC7);
        self.modem_ctrl.write(0x0B);
        self.int_en.write(0x01);
    }

    fn line_sts(&self) -> LineStsFlags {
        LineStsFlags::from_bits_truncate(self.line_sts.read())
    }

    pub fn receive(&mut self) -> Option<u8> {
        if self.line_sts().contains(LineStsFlags::INPUT_FULL) {
            Some(self.data.read())
        } else {
            None
        }
    }

    pub fn send(&mut self, data: u8) {
        while ! self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY) {}
        self.data.write(data);
    }

    pub fn write(&mut self, buf: &[u8]) {
        for &b in buf {
            match b {
                8 | 0x7F => {
                    self.send(8);
                    self.send(b' ');
                    self.send(8);
                },
                _ => {
                    self.send(b);
                }
            }
        }
    }
}
<commit_msg>Support SerialPort<Mmio<u32>><commit_after>use core::convert::TryInto;

use crate::syscall::io::{Io, Pio, Mmio, ReadOnly};

bitflags! {
    /// Interrupt enable flags
    struct IntEnFlags: u8 {
        const RECEIVED = 1;
        const SENT = 1 << 1;
        const ERRORED = 1 << 2;
        const STATUS_CHANGE = 1 << 3;
        // 4 to 7 are unused
    }
}

bitflags! {
    /// Line status flags
    struct LineStsFlags: u8 {
        const INPUT_FULL = 1;
        // 1 to 4 unknown
        const OUTPUT_EMPTY = 1 << 5;
        // 6 and 7 unknown
    }
}

#[allow(dead_code)]
#[repr(packed)]
pub struct SerialPort<T: Io> {
    /// Data register, read to receive, write to send
    data: T,
    /// Interrupt enable
    int_en: T,
    /// FIFO control
    fifo_ctrl: T,
    /// Line control
    line_ctrl: T,
    /// Modem control
    modem_ctrl: T,
    /// Line status
    line_sts: ReadOnly<T>,
    /// Modem status
    modem_sts: ReadOnly<T>,
}

impl SerialPort<Pio<u8>> {
    pub const fn new(base: u16) -> SerialPort<Pio<u8>> {
        SerialPort {
            data: Pio::new(base),
            int_en: Pio::new(base + 1),
            fifo_ctrl: Pio::new(base + 2),
            line_ctrl: Pio::new(base + 3),
            modem_ctrl: Pio::new(base + 4),
            line_sts: ReadOnly::new(Pio::new(base + 5)),
            modem_sts: ReadOnly::new(Pio::new(base + 6))
        }
    }
}

impl SerialPort<Mmio<u32>> {
    pub unsafe fn new(base: usize) -> &'static mut SerialPort<Mmio<u32>> {
        &mut *(base as *mut Self)
    }
}

impl<T: Io> SerialPort<T>
    where T::Value: From<u8> + TryInto<u8>
{
    pub fn init(&mut self) {
        //TODO: Cleanup
        self.int_en.write(0x00.into());
        self.line_ctrl.write(0x80.into());
        self.data.write(0x01.into());
        self.int_en.write(0x00.into());
        self.line_ctrl.write(0x03.into());
        self.fifo_ctrl.write(0xC7.into());
        self.modem_ctrl.write(0x0B.into());
        self.int_en.write(0x01.into());
    }

    fn line_sts(&self) -> LineStsFlags {
        LineStsFlags::from_bits_truncate(
            (self.line_sts.read() & 0xFF.into()).try_into().unwrap_or(0)
        )
    }

    pub fn receive(&mut self) -> Option<u8> {
        if self.line_sts().contains(LineStsFlags::INPUT_FULL) {
            Some(
                (self.data.read() & 0xFF.into()).try_into().unwrap_or(0)
            )
        } else {
            None
        }
    }

    pub fn send(&mut self, data: u8) {
        while ! self.line_sts().contains(LineStsFlags::OUTPUT_EMPTY) {}
        self.data.write(data.into());
    }

    pub fn write(&mut self, buf: &[u8]) {
        for &b in buf {
            match b {
                8 | 0x7F => {
                    self.send(8);
                    self.send(b' ');
                    self.send(8);
                },
                b'\n' => {
                    self.send(b'\r');
                    self.send(b'\n');
                },
                _ => {
                    self.send(b);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Saw wave signal generator.
//!
//! The saw wave can be considered a "basic waveform", since it has a pretty simple relationship
//! between the harmonics and the fundamental (in this case, it contains all harmonics (odd *and*
//! even) with a falloff of -6dB/octave).
//!
//! In the time domain, the conventional saw wave has the zeroth sample starting at -1.00, and
//! consecutive samples ramp upward until it hits 1.00, then sharply drops to -1.00 and starts over.
//! The rate at which the samples ramp up depend on the frequency of the saw wave. To get an
//! "inverse saw wave" (one that starts at 1.00 and ramps downward until -1.00), you can simply make
//! a conventional saw wave with the desired frequency and amplitude and negate the signal.
//!
//! In the frequency domain, the saw wave is a combination of an infinite number of sine waves,
//! starting with the "fundamental frequency" (the lowest frequency, which is the `frequency`
//! field in the struct) and including every (even and odd) harmonic above the fundamental.
//! Each harmonic x has an amplitude of 1/x times the fundamental frequency. For example, if the
//! fundamental frequency has an amplitude of 1.00, the second harmonic would have an amplitude of
//! 0.50, the third harmonic would have an amplitude of 0.33, the fourth harmonic would have an
//! amplitude of 0.25, etc.
//!
//! In digital synthesis, this pattern of adding of sine waves together only happens from the
//! fundamental frequency up to the Nyquist frequency (half the sampling frequency) - Otherwise,
//! you will create aliasing. NOTE that this implementation generates a saw wave directly in the
//! time domain, which does not take into account the Nyquist frequency and does not band-limit
//! higher frequencies, so this implementation *might* include aliasing distortion. (???)

use dsp::traits::Signal;

/// Saw wave generator struct.
pub struct Saw {
    sample_rate: f64,
    frequency: f64,
    amplitude: f64,
    // TODO: Rename to "phase" to reduce confusion; rename "current_output" below to "output"
    output: f64,
}

impl Saw {
    /// Creates a new Saw wave signal generator.
    pub fn new(sample_rate: f64, frequency: f64, amplitude: f64) -> Saw {
        Saw { sample_rate, frequency, amplitude, output: 0.0}
    }
}

impl Signal for Saw {
    fn evaluate(&mut self) -> (f64) {
        let mut current_output = self.output;

        self.output += self.frequency / self.sample_rate as f64;
        if self.output >= 1.0 {
            self.output -= 1.0;
        }

        current_output *= self.amplitude;
        current_output
    }
}<commit_msg>Make Saw generator parametric by default<commit_after>//! Saw wave signal generator.
//!
//! The saw wave can be considered a "basic waveform", since it has a pretty simple relationship
//! between the harmonics and the fundamental (in this case, it contains all harmonics (odd *and*
//! even) with a falloff of -6dB/octave).
//!
//! In the time domain, the conventional saw wave has the zeroth sample starting at -1.00, and
//! consecutive samples ramp upward until it hits 1.00, then sharply drops to -1.00 and starts over.
//! The rate at which the samples ramp up depend on the frequency of the saw wave. To get an
//! "inverse saw wave" (one that starts at 1.00 and ramps downward until -1.00), you can simply make
//! a conventional saw wave with the desired frequency and amplitude and negate the signal.
//!
//! In the frequency domain, the saw wave is a combination of an infinite number of sine waves,
//! starting with the "fundamental frequency" (the lowest frequency, which is the `frequency`
//! field in the struct) and including every (even and odd) harmonic above the fundamental.
//! Each harmonic x has an amplitude of 1/x times the fundamental frequency. For example, if the
//! fundamental frequency has an amplitude of 1.00, the second harmonic would have an amplitude of
//! 0.50, the third harmonic would have an amplitude of 0.33, the fourth harmonic would have an
//! amplitude of 0.25, etc.
//!
//! In digital synthesis, this pattern of adding of sine waves together only happens from the
//! fundamental frequency up to the Nyquist frequency (half the sampling frequency) - Otherwise,
//! you will create aliasing. NOTE that this implementation generates a saw wave directly in the
//! time domain, which does not take into account the Nyquist frequency and does not band-limit
//! higher frequencies, so this implementation *might* include aliasing distortion. (???)

use dsp::traits::Signal;

/// Saw wave generator struct.
pub struct Saw<A, F, O> where
    A: Signal,
    F: Signal,
    O: Signal,
{
    sample_rate: f64,  // Sample rate (for audio playback, etc) - Should be the same throughout the whole project
    amplitude: A,      // Amplitude of the Sine wave
    frequency: F,      // Frequency of the Sine wave
    offset: O,         // DC offset of the Sine wave    (+/- y axis)
    phase: f64,        // Phase offset of the Sine wave (+/- x axis, as a percent of the whole period)
}

impl<A, F, O> Saw<A, F, O> where
    A: Signal,
    F: Signal,
    O: Signal,
{
    /// Creates a new Saw wave signal generator.
    pub fn new(amplitude: A, frequency: F, offset: O) -> Saw<A, F, O> {
        Saw {
            sample_rate: 44100.0,
            amplitude,
            frequency,
            offset,
            phase: 0.0,
        }
    }
}

impl<A, F, O> Signal for Saw<A, F, O> where
    A: Signal,
    F: Signal,
    O: Signal,
{
    fn evaluate(&mut self) -> (f64) {
        let amplitude = self.amplitude.evaluate();
        let frequency = self.frequency.evaluate();
        let offset = self.offset.evaluate();

        let mut output = self.phase * 2.0 - 1.0;
        let last_phase = self.phase;
        self.phase = (self.phase + frequency / self.sample_rate).fract();

        output *= amplitude;
        output += offset;

        //println!("{}", output);

        output
    }
}<|endoftext|>


<commit_before>
//! All entities of a gerrit instance
//!
//! The entities are documented on gerrit site on
//! <https://gerrit-documentation.storage.googleapis.com/Documentation/2.12.3/rest-api-changes.html#json-entities>.
//!
//! **NOTICE**: Only current needed entities are here reflected.

use std::collections::HashMap;
use std::fmt;
use std::fmt::Display;

#[derive(RustcDecodable, Debug)]
pub struct AccountInfo {
    pub _account_id: u64,
    pub name: Option<String>,
    pub email: Option<String>,
    pub secondary_emails: Option<Vec<String>>,
    pub username: Option<String>,
    pub _more_accounts: Option<String>,
}

impl Display for AccountInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(x) = self.name.clone() {
            try!(write!(f, "{}", x));
        } else {
            try!(write!(f, "uid:{}", self._account_id));
        };

        if let Some(x) = self.email.clone() {
            try!(write!(f, "{}", x));
        };

        Ok(())
    }
}

#[derive(RustcDecodable, Debug)]
pub struct ActionInfo {
    pub method: Option<String>,
    pub label: Option<String>,
    pub title: Option<String>,
    pub enabled: Option<String>,
}

#[derive(RustcDecodable, Debug)]
pub enum ChangeStatus {
    NEW,
    MERGED,
    ABANDONED,
    DRAFT,
}

impl Display for ChangeStatus {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            ChangeStatus::NEW => "NEW",
            ChangeStatus::MERGED => "MERGED",
            ChangeStatus::ABANDONED => "ABANDONED",
            ChangeStatus::DRAFT => "DRAFT",
        };
        write!(f, "{}", s)
    }
}

#[derive(RustcDecodable, Debug)]
pub struct LabelInfo {
    pub optional: Option<bool>,
}

#[derive(RustcDecodable, Debug)]
pub struct ChangeMessageInfo {
    pub id: String,
    pub author: Option<AccountInfo>,
    pub date: String,
    pub message: String,
    pub tag: Option<String>,
    pub _revision_number: Option<u16>,
}

#[allow(non_camel_case_types)]
#[derive(RustcDecodable, Debug)]
pub enum RevisionInfoKind {
    REWORK,
    TRIVIAL_REBASE,
    MERGE_FIRST_PARENT_UPDATE,
    NO_CODE_CHANGE,
    NO_CHANGE,
}

#[derive(RustcDecodable, Debug)]
pub struct FetchInfo {
    pub url: String,
    pub reference: String,
    pub commands: Option<String>,
}

#[derive(RustcDecodable, Debug)]
pub struct RevisionInfo {
    pub draft: bool,
    pub kind: RevisionInfoKind,
    pub _number: u16,
    pub created: String,
    pub uploader: AccountInfo,
    pub reference: String,
    pub fetch: HashMap<String, FetchInfo>,
    /* TODO: Some fileds ommited */
}

#[derive(RustcDecodable, Debug)]
pub struct ProblemInfo {
    pub message: String,
    pub status: Option<String>,
    pub outcome: Option<String>,
}

#[derive(RustcDecodable, Debug)]
pub struct ChangeInfo {
    pub id: String,
    pub project: String,
    pub branch: String,
    pub topic: Option<String>,
    pub change_id: String,
    pub subject: String,
    pub status: ChangeStatus,
    pub created: String,
    pub updated: String,
    pub submitted: Option<String>,
    pub starred: Option<bool>,
    pub stars: Option<Vec<String>>,
    pub reviewed: Option<bool>,
    pub submit_type: Option<String>,
    pub mergeable: Option<bool>,
    pub insertions: u16,
    pub deletions: u16,
    pub _number: u16,
    pub owner: AccountInfo,
    pub action: Option<Vec<ActionInfo>>,
    pub labels: Option<HashMap<String, LabelInfo>>,
    pub permitted_labels: Option<HashMap<String, LabelInfo>>,
    pub removeable_reviewers: Option<Vec<AccountInfo>>,
    pub reviewers: Option<String>,
    pub messages: Option<HashMap<String, ChangeMessageInfo>>,
    pub current_revision: Option<HashMap<String, RevisionInfo>>,
    pub revision: Option<HashMap<String, RevisionInfo>>,
    pub _more_changes: Option<bool>,
    pub problems: Option<Vec<ProblemInfo>>,
}

/// **TODO**: This is subject to change! Its to unflexible.
impl Display for ChangeInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "* {project:.<41.41} {branch:.<20.20} {subject:.>30.30}", project=self.project, branch=self.branch, subject=self.subject));
        try!(writeln!(f, "| {changeid:41.41} {number:<31.10} {created:>19.19}", changeid=self.change_id, number=self._number, created=self.created));
        try!(writeln!(f, "| {topic:73.41} {updated:19.19}", topic=self.topic.clone().unwrap_or("N/A".to_string()), updated=self.updated));
        write!(f, "` {status}, {owner}", owner=self.owner, status=self.status)
    }
}

#[derive(RustcDecodable, Debug)]
pub enum ProjectState {
    ACTIVE,
    READONLY,
    HIDDEN,
}

#[derive(RustcDecodable, Debug, Clone)]
pub enum ProjectTypes {
    ALL,
    CODE,
    PERMISSIONS,
}

#[derive(RustcDecodable, Debug)]
pub struct WebLinkInfo {
    pub name: String,
    pub url: String,
    pub image_url: String,
}

#[derive(RustcDecodable, Debug)]
pub struct ProjectInfo {
    pub name: Option<String>,
    pub id: String,
    pub parent: Option<String>,
    pub description: Option<String>,
    pub state: Option<ProjectState>,
    pub branches: Option<HashMap<String, String>>,
    pub web_links: Option<Vec<WebLinkInfo>>,
}
<commit_msg>entities: add comment about enum variant style<commit_after>
//! All entities of a gerrit instance
//!
//! The entities are documented on gerrit site on
//! <https://gerrit-documentation.storage.googleapis.com/Documentation/2.12.3/rest-api-changes.html#json-entities>.
//!
//! **NOTICE**: Only current needed entities are here reflected.

use std::collections::HashMap;
use std::fmt;
use std::fmt::Display;

#[derive(RustcDecodable, Debug)]
pub struct AccountInfo {
    pub _account_id: u64,
    pub name: Option<String>,
    pub email: Option<String>,
    pub secondary_emails: Option<Vec<String>>,
    pub username: Option<String>,
    pub _more_accounts: Option<String>,
}

impl Display for AccountInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let Some(x) = self.name.clone() {
            try!(write!(f, "{}", x));
        } else {
            try!(write!(f, "uid:{}", self._account_id));
        };

        if let Some(x) = self.email.clone() {
            try!(write!(f, "{}", x));
        };

        Ok(())
    }
}

#[derive(RustcDecodable, Debug)]
pub struct ActionInfo {
    pub method: Option<String>,
    pub label: Option<String>,
    pub title: Option<String>,
    pub enabled: Option<String>,
}

// the enum variants must be in upper case letters, the server will send them in this style
#[derive(RustcDecodable, Debug)]
pub enum ChangeStatus {
    NEW,
    MERGED,
    ABANDONED,
    DRAFT,
}

impl Display for ChangeStatus {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            ChangeStatus::NEW => "NEW",
            ChangeStatus::MERGED => "MERGED",
            ChangeStatus::ABANDONED => "ABANDONED",
            ChangeStatus::DRAFT => "DRAFT",
        };
        write!(f, "{}", s)
    }
}

#[derive(RustcDecodable, Debug)]
pub struct LabelInfo {
    pub optional: Option<bool>,
}

#[derive(RustcDecodable, Debug)]
pub struct ChangeMessageInfo {
    pub id: String,
    pub author: Option<AccountInfo>,
    pub date: String,
    pub message: String,
    pub tag: Option<String>,
    pub _revision_number: Option<u16>,
}

#[allow(non_camel_case_types)]
#[derive(RustcDecodable, Debug)]
pub enum RevisionInfoKind {
    REWORK,
    TRIVIAL_REBASE,
    MERGE_FIRST_PARENT_UPDATE,
    NO_CODE_CHANGE,
    NO_CHANGE,
}

#[derive(RustcDecodable, Debug)]
pub struct FetchInfo {
    pub url: String,
    pub reference: String,
    pub commands: Option<String>,
}

#[derive(RustcDecodable, Debug)]
pub struct RevisionInfo {
    pub draft: bool,
    pub kind: RevisionInfoKind,
    pub _number: u16,
    pub created: String,
    pub uploader: AccountInfo,
    pub reference: String,
    pub fetch: HashMap<String, FetchInfo>,
    /* TODO: Some fileds ommited */
}

#[derive(RustcDecodable, Debug)]
pub struct ProblemInfo {
    pub message: String,
    pub status: Option<String>,
    pub outcome: Option<String>,
}

#[derive(RustcDecodable, Debug)]
pub struct ChangeInfo {
    pub id: String,
    pub project: String,
    pub branch: String,
    pub topic: Option<String>,
    pub change_id: String,
    pub subject: String,
    pub status: ChangeStatus,
    pub created: String,
    pub updated: String,
    pub submitted: Option<String>,
    pub starred: Option<bool>,
    pub stars: Option<Vec<String>>,
    pub reviewed: Option<bool>,
    pub submit_type: Option<String>,
    pub mergeable: Option<bool>,
    pub insertions: u16,
    pub deletions: u16,
    pub _number: u16,
    pub owner: AccountInfo,
    pub action: Option<Vec<ActionInfo>>,
    pub labels: Option<HashMap<String, LabelInfo>>,
    pub permitted_labels: Option<HashMap<String, LabelInfo>>,
    pub removeable_reviewers: Option<Vec<AccountInfo>>,
    pub reviewers: Option<String>,
    pub messages: Option<HashMap<String, ChangeMessageInfo>>,
    pub current_revision: Option<HashMap<String, RevisionInfo>>,
    pub revision: Option<HashMap<String, RevisionInfo>>,
    pub _more_changes: Option<bool>,
    pub problems: Option<Vec<ProblemInfo>>,
}

/// **TODO**: This is subject to change! Its to unflexible.
impl Display for ChangeInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "* {project:.<41.41} {branch:.<20.20} {subject:.>30.30}", project=self.project, branch=self.branch, subject=self.subject));
        try!(writeln!(f, "| {changeid:41.41} {number:<31.10} {created:>19.19}", changeid=self.change_id, number=self._number, created=self.created));
        try!(writeln!(f, "| {topic:73.41} {updated:19.19}", topic=self.topic.clone().unwrap_or("N/A".to_string()), updated=self.updated));
        write!(f, "` {status}, {owner}", owner=self.owner, status=self.status)
    }
}

#[derive(RustcDecodable, Debug)]
pub enum ProjectState {
    ACTIVE,
    READONLY,
    HIDDEN,
}

#[derive(RustcDecodable, Debug, Clone)]
pub enum ProjectTypes {
    ALL,
    CODE,
    PERMISSIONS,
}

#[derive(RustcDecodable, Debug)]
pub struct WebLinkInfo {
    pub name: String,
    pub url: String,
    pub image_url: String,
}

#[derive(RustcDecodable, Debug)]
pub struct ProjectInfo {
    pub name: Option<String>,
    pub id: String,
    pub parent: Option<String>,
    pub description: Option<String>,
    pub state: Option<ProjectState>,
    pub branches: Option<HashMap<String, String>>,
    pub web_links: Option<Vec<WebLinkInfo>>,
}
<|endoftext|>