<commit_before>//! Commands from the user to manipulate the tree

use super::{try_lock_tree, try_lock_action};
use super::{Action, ActionErr, Container, ContainerType, Direction, Handle, Layout, TreeError};
use super::Tree;

use uuid::Uuid;
use rustwlc::{Point, ResizeEdge, WlcView, WlcOutput, ViewType};
use rustc_serialize::json::{Json, ToJson};

pub type CommandResult = Result<(), TreeError>;

/* These commands are exported to take nothing and return nothing,
 * since they are the commands actually registered and usable over
 * the IPC/Lua thread.
 */

pub fn remove_active() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Some(container) = tree.0.get_active_container_mut() {
            match *container {
                Container::View { ref handle, .. } => {
                    handle.close();
                    // Thanks borrowck
                    // Views shouldn't be removed from tree, that's handled by
                    // view_destroyed callback
                    return
                },
                _ => {}
            }
        }
        tree.0.remove_active();
    }
}

pub fn toggle_float() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.toggle_float().ok();
    }
}

pub fn toggle_float_focus() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Err(err) = tree.toggle_floating_focus() {
            warn!("Could not float focus: {:#?}", err);
        }
    }
}

pub fn tile_switch() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Some(id) = tree.active_id() {
            tree.toggle_cardinal_tiling(id).unwrap_or_else(|err| {
                warn!("Could not toggle cardinal tiling: {:#?}", err);
            });
        }
    }
}

pub fn split_vertical() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Vertical).ok();
    }
}

pub fn split_horizontal() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Horizontal).ok();
    }
}

pub fn focus_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Left)
            .unwrap_or_else(|_| {
                warn!("Could not focus left");
            });
    }
}

pub fn focus_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Right)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            });
    }
}

pub fn focus_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Up)
            .unwrap_or_else(|_| {
                warn!("Could not focus up");
            });
    }
}

pub fn focus_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Down)
            .unwrap_or_else(|_| {
                warn!("Could not focus down");
            });
    }
}

pub fn move_active_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Left)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn move_active_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Right)
            .unwrap_or_else(|_| {
                error!("Could not focus right");
            })
    }
}

pub fn move_active_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Up)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn move_active_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Down)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn tree_as_json() -> Json {
    if let Ok(tree) = try_lock_tree() {
        tree.0.to_json()
    } else {
        Json::Null
    }
}

/// Returns a copy of the action behind the lock.
pub fn performing_action() -> Option<Action> {
    if let Ok(action) = try_lock_action() {
        *action
    } else {
        error!("Could not lock action mutex!");
        None
    }
}

/// Sets the value behind the lock to the provided value.
///
/// Note that this method blocks until the lock is released
///
/// None means an action is done being performed.
pub fn set_performing_action(val: Option<Action>) {
    if let Ok(mut action) = try_lock_action() {
        *action = val;
    } else {
        error!("Action mutex was poisoned");
        panic!("Action mutex was poisoned");
    }
}

/* These commands are the interface that the rest of Way Cooler has to the
 * tree. Any action done, whether through a callback, or from the IPC/Lua thread
 * it will have to go through one of these methods.
 */

impl Tree {
    /// Gets the uuid of the active container, if there is an active container
    pub fn active_id(&self) -> Option<Uuid> {
        self.0.active_container
            .map(|active_ix| self.0.tree[active_ix].get_id())
    }

    pub fn lookup_view(&self, view: WlcView) -> Option<Uuid> {
        self.0.lookup_view(view).map(|c| c.get_id())
    }

    pub fn toggle_float(&mut self) -> CommandResult {
        if let Some(uuid) = self.active_id() {
            let is_floating: Result<bool, _> = self.0.lookup(uuid)
                .and_then(|container| Ok(container.floating()));
            try!(match is_floating {
                Ok(true) => self.ground_container(uuid),
                Ok(false) => self.float_container(uuid),
                Err(err) => return Err(err)
            });
        }
        Ok(())
    }

    pub fn toggle_cardinal_tiling(&mut self, id: Uuid) -> CommandResult {
        self.0.toggle_cardinal_tiling(id)
            .and_then(|_| self.layout_active_of(ContainerType::Workspace))
    }

    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        self.0.toggle_floating_focus()
    }

    pub fn move_active(&mut self, maybe_uuid: Option<Uuid>, direction: Direction) -> CommandResult {
        let uuid = try!(maybe_uuid
                        .or_else(|| self.0.get_active_container()
                                 .and_then(|container| Some(container.get_id())))
                        .ok_or(TreeError::NoActiveContainer));
        try!(self.0.move_container(uuid, direction));
        // NOTE Make this not layout the active, but actually the node index's workspace.
        try!(self.layout_active_of(ContainerType::Output));
        Ok(())
    }

    /// Attempts to drag the window around the screen.
    pub fn try_drag_active(&mut self, point: Point) -> CommandResult {
        if let Some(mut action) = performing_action() {
            let old_point = action.grab;
            let active_ix = try!(self.0.active_container
                                .ok_or(TreeError::NoActiveContainer));
            try!(self.0.drag_floating(active_ix, point, old_point));
            action.grab = point;
            set_performing_action(Some(action));
            Ok(())
        } else {
            Err(TreeError::PerformingAction(false))
        }
    }

    /// Adds an Output to the tree. Never fails
    pub fn add_output(&mut self, output: WlcOutput) -> CommandResult {
        self.0.add_output(output);
        Ok(())
    }

    /// Adds a Workspace to the tree. Never fails
    pub fn switch_to_workspace(&mut self, name: &str) -> CommandResult {
        self.0.switch_to_workspace(name);
        Ok(())
    }

    /// Tiles the active container of some container type. Never fails
    pub fn layout_active_of(&mut self, c_type: ContainerType) -> CommandResult {
        self.0.layout_active_of(c_type);
        Ok(())
    }

    /// Attempts to set the node behind the id to be floating
    pub fn float_container(&mut self, id: Uuid) -> CommandResult {
        self.0.float_container(id)
    }

    /// Attempts to set the node behind the id to be not floating
    pub fn ground_container(&mut self, id: Uuid) -> CommandResult {
        self.0.ground_container(id)
    }

    /// Adds a view to the workspace of the active container
    pub fn add_view(&mut self, view: WlcView) -> CommandResult {
        let tree = &mut self.0;
        let output = view.get_output();
        if tree.get_active_container().is_none() {
            return Err(TreeError::NoActiveContainer)
        }
        view.set_mask(output.get_mask());
        if view.get_type() != ViewType::empty() {
            try!(tree.add_floating_view(view));
        } else {
            try!(tree.add_view(view));
            tree.normalize_view(view);
        }
        tree.layout_active_of(ContainerType::Workspace);
        Ok(())
    }

    /// Attempts to remove a view from the tree. If it is not in the tree it fails.
    ///
    /// This will close the handle behind the view.
    pub fn remove_view(&mut self, view: WlcView) -> CommandResult {
        let result;
        match self.0.remove_view(&view) {
            Err(err)  => {
                result = Err(err)
            },
            Ok(Container::View { handle, id, .. }) => {
                trace!("Removed container {:?}", id);
                handle.close();
                trace!("Close wlc view {:?}", handle);
                result = Ok(())
            },
            _ => unreachable!()
        }
        let root_ix = self.0.tree.root_ix();
        self.0.layout(root_ix);
        result
    }

    /// Attempts to remove a container based on UUID. Fails if the container
    /// cannot be removed or if the container does not exist.
    ///
    /// This WILL close the view, and should never be called from the
    /// `view_destroyed` callback, as it's possible the view from that callback is invalid.
    pub fn remove_view_by_id(&mut self, id: Uuid) -> CommandResult {
        match try!(self.0.lookup(id)).get_handle() {
            Some(Handle::View(view)) => return self.remove_view(view),
            Some(Handle::Output(_)) | None => {
                Err(TreeError::UuidNotAssociatedWith(ContainerType::View))
            }
        }
    }

    /// Sets the view to be the new active container.
    /// Will fail if the container is floating.
    pub fn set_active_view(&mut self, view: WlcView) -> CommandResult {
        try!(self.0.set_active_view(view.clone()));
        view.focus();
        Ok(())
    }

    #[allow(dead_code)]
    /// Sets the active container to be the container at the UUID
    /// Fails if the container is not a container or view, or if the
    /// container does not exist
    ///
    /// Can also not set floating containers to be active.
    pub fn set_active_container_by_id(&mut self, id: Uuid) -> CommandResult {
        self.0.set_active_container(id)
    }

    /// Focuses on the container. If the container is not floating and is a
    /// Container or a View, then it is also made the active container.
    pub fn focus(&mut self, id: Uuid) -> CommandResult {
        self.set_active_container_by_id(id)
            .or_else(|_| {
                self.0.focus_on(id)
            })
    }

    /// Destroy the tree
    pub fn destroy_tree(&mut self) -> CommandResult {
        self.0.destroy_tree();
        Ok(())
    }

    pub fn move_focus(&mut self, dir: Direction) -> CommandResult {
        try!(self.0.move_focus(dir));
        Ok(())
    }

    /// Moves the active container to a workspace
    pub fn send_active_to_workspace(&mut self, workspace_name: &str) -> CommandResult {
        self.0.send_active_to_workspace(workspace_name);
        Ok(())
    }

    /// Resizes the container, as if it was dragged at the edge to a certain point
    /// on the screen.
    pub fn resize_container(&mut self, id: Uuid, edge: ResizeEdge, pointer: Point) -> CommandResult {
        match try_lock_action() {
            Ok(mut lock) => {
                if let Some(ref mut action) = *lock {
                    if try!(self.0.lookup(id)).floating() {
                        self.0.resize_floating(id, edge, pointer, action)
                    } else {
                        self.0.resize_tiled(id, edge, pointer, action)
                    }
                } else {
                    Err(TreeError::Action(ActionErr::ActionNotInProgress))
                }
            },
            _ => Err(TreeError::Action(ActionErr::ActionLocked))
        }
    }

    pub fn send_to_workspace(&mut self, id: Uuid, workspace_name: &str) -> CommandResult {
        self.0.send_to_workspace(id, workspace_name);
        Ok(())
    }

}
<commit_msg>Added container_in_active_workspace command<commit_after>//! Commands from the user to manipulate the tree

use super::{try_lock_tree, try_lock_action};
use super::{Action, ActionErr, Container, ContainerType, Direction, Handle, Layout, TreeError};
use super::Tree;

use uuid::Uuid;
use rustwlc::{Point, ResizeEdge, WlcView, WlcOutput, ViewType};
use rustc_serialize::json::{Json, ToJson};

pub type CommandResult = Result<(), TreeError>;

/* These commands are exported to take nothing and return nothing,
 * since they are the commands actually registered and usable over
 * the IPC/Lua thread.
 */

pub fn remove_active() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Some(container) = tree.0.get_active_container_mut() {
            match *container {
                Container::View { ref handle, .. } => {
                    handle.close();
                    // Thanks borrowck
                    // Views shouldn't be removed from tree, that's handled by
                    // view_destroyed callback
                    return
                },
                _ => {}
            }
        }
        tree.0.remove_active();
    }
}

pub fn toggle_float() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.toggle_float().ok();
    }
}

pub fn toggle_float_focus() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Err(err) = tree.toggle_floating_focus() {
            warn!("Could not float focus: {:#?}", err);
        }
    }
}

pub fn tile_switch() {
    if let Ok(mut tree) = try_lock_tree() {
        if let Some(id) = tree.active_id() {
            tree.toggle_cardinal_tiling(id).unwrap_or_else(|err| {
                warn!("Could not toggle cardinal tiling: {:#?}", err);
            });
        }
    }
}

pub fn split_vertical() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Vertical).ok();
    }
}

pub fn split_horizontal() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Horizontal).ok();
    }
}

pub fn focus_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Left)
            .unwrap_or_else(|_| {
                warn!("Could not focus left");
            });
    }
}

pub fn focus_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Right)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            });
    }
}

pub fn focus_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Up)
            .unwrap_or_else(|_| {
                warn!("Could not focus up");
            });
    }
}

pub fn focus_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Down)
            .unwrap_or_else(|_| {
                warn!("Could not focus down");
            });
    }
}

pub fn move_active_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Left)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn move_active_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Right)
            .unwrap_or_else(|_| {
                error!("Could not focus right");
            })
    }
}

pub fn move_active_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Up)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn move_active_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_active(None, Direction::Down)
            .unwrap_or_else(|_| {
                warn!("Could not focus right");
            })
    }
}

pub fn tree_as_json() -> Json {
    if let Ok(tree) = try_lock_tree() {
        tree.0.to_json()
    } else {
        Json::Null
    }
}

/// Returns a copy of the action behind the lock.
pub fn performing_action() -> Option<Action> {
    if let Ok(action) = try_lock_action() {
        *action
    } else {
        error!("Could not lock action mutex!");
        None
    }
}

/// Sets the value behind the lock to the provided value.
///
/// Note that this method blocks until the lock is released
///
/// None means an action is done being performed.
pub fn set_performing_action(val: Option<Action>) {
    if let Ok(mut action) = try_lock_action() {
        *action = val;
    } else {
        error!("Action mutex was poisoned");
        panic!("Action mutex was poisoned");
    }
}

/* These commands are the interface that the rest of Way Cooler has to the
 * tree. Any action done, whether through a callback, or from the IPC/Lua thread
 * it will have to go through one of these methods.
 */

impl Tree {
    /// Gets the uuid of the active container, if there is an active container
    pub fn active_id(&self) -> Option<Uuid> {
        self.0.active_container
            .map(|active_ix| self.0.tree[active_ix].get_id())
    }

    pub fn lookup_view(&self, view: WlcView) -> Option<Uuid> {
        self.0.lookup_view(view).map(|c| c.get_id())
    }

    /// Determines if the container is in the currently active workspace.
    pub fn container_in_active_workspace(&self, id: Uuid) -> Result<bool, TreeError> {
        let view = match try!(self.0.lookup(id)).get_handle() {
            Some(Handle::View(view)) => view,
            _ => return Err(TreeError::UuidNotAssociatedWith(ContainerType::View))
        };
        if let Some(active_workspace) = self.0.active_ix_of(ContainerType::Workspace) {
            Ok(self.0.tree.descendant_with_handle(active_workspace, &view).is_some())
        } else {
            Ok(false)
        }
    }

    pub fn toggle_float(&mut self) -> CommandResult {
        if let Some(uuid) = self.active_id() {
            let is_floating: Result<bool, _> = self.0.lookup(uuid)
                .and_then(|container| Ok(container.floating()));
            try!(match is_floating {
                Ok(true) => self.ground_container(uuid),
                Ok(false) => self.float_container(uuid),
                Err(err) => return Err(err)
            });
        }
        Ok(())
    }

    pub fn toggle_cardinal_tiling(&mut self, id: Uuid) -> CommandResult {
        self.0.toggle_cardinal_tiling(id)
            .and_then(|_| self.layout_active_of(ContainerType::Workspace))
    }

    pub fn toggle_floating_focus(&mut self) -> CommandResult {
        self.0.toggle_floating_focus()
    }

    pub fn move_active(&mut self, maybe_uuid: Option<Uuid>, direction: Direction) -> CommandResult {
        let uuid = try!(maybe_uuid
                        .or_else(|| self.0.get_active_container()
                                 .and_then(|container| Some(container.get_id())))
                        .ok_or(TreeError::NoActiveContainer));
        try!(self.0.move_container(uuid, direction));
        // NOTE Make this not layout the active, but actually the node index's workspace.
        try!(self.layout_active_of(ContainerType::Output));
        Ok(())
    }

    /// Attempts to drag the window around the screen.
    pub fn try_drag_active(&mut self, point: Point) -> CommandResult {
        if let Some(mut action) = performing_action() {
            let old_point = action.grab;
            let active_ix = try!(self.0.active_container
                                .ok_or(TreeError::NoActiveContainer));
            try!(self.0.drag_floating(active_ix, point, old_point));
            action.grab = point;
            set_performing_action(Some(action));
            Ok(())
        } else {
            Err(TreeError::PerformingAction(false))
        }
    }

    /// Adds an Output to the tree. Never fails
    pub fn add_output(&mut self, output: WlcOutput) -> CommandResult {
        self.0.add_output(output);
        Ok(())
    }

    /// Adds a Workspace to the tree. Never fails
    pub fn switch_to_workspace(&mut self, name: &str) -> CommandResult {
        self.0.switch_to_workspace(name);
        Ok(())
    }

    /// Tiles the active container of some container type. Never fails
    pub fn layout_active_of(&mut self, c_type: ContainerType) -> CommandResult {
        self.0.layout_active_of(c_type);
        Ok(())
    }

    /// Attempts to set the node behind the id to be floating
    pub fn float_container(&mut self, id: Uuid) -> CommandResult {
        self.0.float_container(id)
    }

    /// Attempts to set the node behind the id to be not floating
    pub fn ground_container(&mut self, id: Uuid) -> CommandResult {
        self.0.ground_container(id)
    }

    /// Adds a view to the workspace of the active container
    pub fn add_view(&mut self, view: WlcView) -> CommandResult {
        let tree = &mut self.0;
        let output = view.get_output();
        if tree.get_active_container().is_none() {
            return Err(TreeError::NoActiveContainer)
        }
        view.set_mask(output.get_mask());
        if view.get_type() != ViewType::empty() {
            try!(tree.add_floating_view(view));
        } else {
            try!(tree.add_view(view));
            tree.normalize_view(view);
        }
        tree.layout_active_of(ContainerType::Workspace);
        Ok(())
    }

    /// Attempts to remove a view from the tree. If it is not in the tree it fails.
    ///
    /// This will close the handle behind the view.
    pub fn remove_view(&mut self, view: WlcView) -> CommandResult {
        let result;
        match self.0.remove_view(&view) {
            Err(err)  => {
                result = Err(err)
            },
            Ok(Container::View { handle, id, .. }) => {
                trace!("Removed container {:?}", id);
                handle.close();
                trace!("Close wlc view {:?}", handle);
                result = Ok(())
            },
            _ => unreachable!()
        }
        let root_ix = self.0.tree.root_ix();
        self.0.layout(root_ix);
        result
    }

    /// Attempts to remove a container based on UUID. Fails if the container
    /// cannot be removed or if the container does not exist.
    ///
    /// This WILL close the view, and should never be called from the
    /// `view_destroyed` callback, as it's possible the view from that callback is invalid.
    pub fn remove_view_by_id(&mut self, id: Uuid) -> CommandResult {
        match try!(self.0.lookup(id)).get_handle() {
            Some(Handle::View(view)) => return self.remove_view(view),
            Some(Handle::Output(_)) | None => {
                Err(TreeError::UuidNotAssociatedWith(ContainerType::View))
            }
        }
    }

    /// Sets the view to be the new active container.
    /// Will fail if the container is floating.
    pub fn set_active_view(&mut self, view: WlcView) -> CommandResult {
        try!(self.0.set_active_view(view.clone()));
        view.focus();
        Ok(())
    }

    #[allow(dead_code)]
    /// Sets the active container to be the container at the UUID
    /// Fails if the container is not a container or view, or if the
    /// container does not exist
    ///
    /// Can also not set floating containers to be active.
    pub fn set_active_container_by_id(&mut self, id: Uuid) -> CommandResult {
        self.0.set_active_container(id)
    }

    /// Focuses on the container. If the container is not floating and is a
    /// Container or a View, then it is also made the active container.
    pub fn focus(&mut self, id: Uuid) -> CommandResult {
        self.set_active_container_by_id(id)
            .or_else(|_| {
                self.0.focus_on(id)
            })
    }

    /// Destroy the tree
    pub fn destroy_tree(&mut self) -> CommandResult {
        self.0.destroy_tree();
        Ok(())
    }

    pub fn move_focus(&mut self, dir: Direction) -> CommandResult {
        try!(self.0.move_focus(dir));
        Ok(())
    }

    /// Moves the active container to a workspace
    pub fn send_active_to_workspace(&mut self, workspace_name: &str) -> CommandResult {
        self.0.send_active_to_workspace(workspace_name);
        Ok(())
    }

    /// Resizes the container, as if it was dragged at the edge to a certain point
    /// on the screen.
    pub fn resize_container(&mut self, id: Uuid, edge: ResizeEdge, pointer: Point) -> CommandResult {
        match try_lock_action() {
            Ok(mut lock) => {
                if let Some(ref mut action) = *lock {
                    if try!(self.0.lookup(id)).floating() {
                        self.0.resize_floating(id, edge, pointer, action)
                    } else {
                        self.0.resize_tiled(id, edge, pointer, action)
                    }
                } else {
                    Err(TreeError::Action(ActionErr::ActionNotInProgress))
                }
            },
            _ => Err(TreeError::Action(ActionErr::ActionLocked))
        }
    }

    pub fn send_to_workspace(&mut self, id: Uuid, workspace_name: &str) -> CommandResult {
        self.0.send_to_workspace(id, workspace_name);
        Ok(())
    }

}
<|endoftext|>


<commit_before>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

**Deprecated** iteration traits and common implementations.

*/

#[allow(missing_doc)];

use cmp::{Eq, Ord};
use kinds::Copy;
use option::{None, Option, Some};
use vec;

/// A function used to initialize the elements of a sequence
pub type InitOp<'self,T> = &'self fn(uint) -> T;

pub trait BaseIter<A> {
    fn each(&self, blk: &fn(v: &A) -> bool) -> bool;
    fn size_hint(&self) -> Option<uint>;
}

pub trait ReverseIter<A>: BaseIter<A> {
    fn each_reverse(&self, blk: &fn(&A) -> bool) -> bool;
}

pub trait ExtendedIter<A> {
    fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool;
    fn all(&self, blk: &fn(&A) -> bool) -> bool;
    fn any(&self, blk: &fn(&A) -> bool) -> bool;
    fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B;
    fn position(&self, f: &fn(&A) -> bool) -> Option<uint>;
    fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B];
    fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B];
}

pub trait EqIter<A:Eq> {
    fn contains(&self, x: &A) -> bool;
    fn count(&self, x: &A) -> uint;
}

pub trait CopyableIter<A:Copy> {
    fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A];
    fn to_vec(&self) -> ~[A];
    fn find(&self, p: &fn(&A) -> bool) -> Option<A>;
}

// A trait for sequences that can be built by imperatively pushing elements
// onto them.
pub trait Buildable<A> {
    /**
     * Builds a buildable sequence by calling a provided function with
     * an argument function that pushes an element onto the back of
     * the sequence.
     * This version takes an initial size for the sequence.
     *
     * # Arguments
     *
     * * size - A hint for an initial size of the sequence
     * * builder - A function that will construct the sequence. It receives
     *             as an argument a function that will push an element
     *             onto the sequence being constructed.
     */
     fn build_sized(size: uint, builder: &fn(push: &fn(A))) -> Self;
}

#[inline(always)]
pub fn _eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
    let mut i = 0;
    for this.each |a| {
        if !blk(i, a) {
            return false;
        }
        i += 1;
    }
    return true;
}

pub fn eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
    _eachi(this, blk)
}

#[inline(always)]
pub fn all<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
    for this.each |a| {
        if !blk(a) {
            return false;
        }
    }
    return true;
}

#[inline(always)]
pub fn any<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
    for this.each |a| {
        if blk(a) {
            return true;
        }
    }
    return false;
}

#[inline(always)]
pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(this: &IA,
                                            prd: &fn(&A) -> bool)
                                         -> ~[A] {
    do vec::build_sized_opt(this.size_hint()) |push| {
        for this.each |a| {
            if prd(a) { push(*a); }
        }
    }
}

#[inline(always)]
pub fn map_to_vec<A,B,IA:BaseIter<A>>(this: &IA, op: &fn(&A) -> B) -> ~[B] {
    do vec::build_sized_opt(this.size_hint()) |push| {
        for this.each |a| {
            push(op(a));
        }
    }
}

#[inline(always)]
pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(this: &IA,
                                                          op: &fn(&A) -> IB)
                                                       -> ~[B] {
    do vec::build |push| {
        for this.each |a| {
            for op(a).each |&b| {
                push(b);
            }
        }
    }
}

#[inline(always)]
pub fn foldl<A,B,IA:BaseIter<A>>(this: &IA, b0: B, blk: &fn(&B, &A) -> B)
                              -> B {
    let mut b = b0;
    for this.each |a| {
        b = blk(&b, a);
    }
    b
}

#[inline(always)]
pub fn to_vec<A:Copy,IA:BaseIter<A>>(this: &IA) -> ~[A] {
    map_to_vec(this, |&x| x)
}

#[inline(always)]
pub fn contains<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> bool {
    for this.each |a| {
        if *a == *x { return true; }
    }
    return false;
}

#[inline(always)]
pub fn count<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> uint {
    do foldl(this, 0) |count, value| {
        if *value == *x {
            *count + 1
        } else {
            *count
        }
    }
}

#[inline(always)]
pub fn position<A,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
                               -> Option<uint> {
    let mut i = 0;
    for this.each |a| {
        if f(a) { return Some(i); }
        i += 1;
    }
    return None;
}

// note: 'rposition' would only make sense to provide with a bidirectional
// iter interface, such as would provide "reach" in addition to "each". As is,
// it would have to be implemented with foldr, which is too inefficient.

#[inline(always)]
pub fn min<A:Copy + Ord,IA:BaseIter<A>>(this: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(this, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ < *b => {
             *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!("min called on empty iterator")
    }
}

#[inline(always)]
pub fn max<A:Copy + Ord,IA:BaseIter<A>>(this: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(this, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ > *b => {
              *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!("max called on empty iterator")
    }
}

#[inline(always)]
pub fn find<A:Copy,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
                                -> Option<A> {
    for this.each |i| {
        if f(i) { return Some(*i) }
    }
    return None;
}

// Some functions for just building

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 *
 * # Arguments
 *
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub fn build<A,B: Buildable<A>>(builder: &fn(push: &fn(A))) -> B {
    Buildable::build_sized(4, builder)
}

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of the sequence.
 * This version takes an initial size for the sequence.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the sequence
 *          to reserve.
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub fn build_sized_opt<A,B: Buildable<A>>(size: Option<uint>,
                                          builder: &fn(push: &fn(A))) -> B {
    Buildable::build_sized(size.get_or_default(4), builder)
}

// Functions that combine iteration and building

/// Applies a function to each element of an iterable and returns the results
/// in a sequence built via `BU`.  See also `map_to_vec`.
#[inline(always)]
pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: &fn(&T) -> U)
    -> BU {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each() |elem| {
            push(f(elem));
        }
    }
}

/**
 * Creates and initializes a generic sequence from a function.
 *
 * Creates a generic sequence of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
#[inline(always)]
pub fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes a generic sequence with some elements.
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
#[inline(always)]
pub fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint, t: T) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0;
        while i < n_elts { push(t); i += 1; }
    }
}

/// Appends two generic sequences.
#[inline(always)]
pub fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(lhs: &IT, rhs: &IT)
                                                  -> BT {
    let size_opt = lhs.size_hint().chain_ref(
        |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
    do build_sized_opt(size_opt) |push| {
        for lhs.each |x| { push(*x); }
        for rhs.each |x| { push(*x); }
    }
}

/// Copies a generic sequence, possibly converting it to a different
/// type of sequence.
#[inline(always)]
pub fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(v: &IT) -> BT {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each |x| { push(*x); }
    }
}
<commit_msg>old_iter: rm the min/max free functions<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

**Deprecated** iteration traits and common implementations.

*/

#[allow(missing_doc)];

use cmp::{Eq, Ord};
use kinds::Copy;
use option::{None, Option, Some};
use vec;

/// A function used to initialize the elements of a sequence
pub type InitOp<'self,T> = &'self fn(uint) -> T;

pub trait BaseIter<A> {
    fn each(&self, blk: &fn(v: &A) -> bool) -> bool;
    fn size_hint(&self) -> Option<uint>;
}

pub trait ReverseIter<A>: BaseIter<A> {
    fn each_reverse(&self, blk: &fn(&A) -> bool) -> bool;
}

pub trait ExtendedIter<A> {
    fn eachi(&self, blk: &fn(uint, v: &A) -> bool) -> bool;
    fn all(&self, blk: &fn(&A) -> bool) -> bool;
    fn any(&self, blk: &fn(&A) -> bool) -> bool;
    fn foldl<B>(&self, b0: B, blk: &fn(&B, &A) -> B) -> B;
    fn position(&self, f: &fn(&A) -> bool) -> Option<uint>;
    fn map_to_vec<B>(&self, op: &fn(&A) -> B) -> ~[B];
    fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: &fn(&A) -> IB) -> ~[B];
}

pub trait EqIter<A:Eq> {
    fn contains(&self, x: &A) -> bool;
    fn count(&self, x: &A) -> uint;
}

pub trait CopyableIter<A:Copy> {
    fn filter_to_vec(&self, pred: &fn(&A) -> bool) -> ~[A];
    fn to_vec(&self) -> ~[A];
    fn find(&self, p: &fn(&A) -> bool) -> Option<A>;
}

// A trait for sequences that can be built by imperatively pushing elements
// onto them.
pub trait Buildable<A> {
    /**
     * Builds a buildable sequence by calling a provided function with
     * an argument function that pushes an element onto the back of
     * the sequence.
     * This version takes an initial size for the sequence.
     *
     * # Arguments
     *
     * * size - A hint for an initial size of the sequence
     * * builder - A function that will construct the sequence. It receives
     *             as an argument a function that will push an element
     *             onto the sequence being constructed.
     */
     fn build_sized(size: uint, builder: &fn(push: &fn(A))) -> Self;
}

#[inline(always)]
pub fn _eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
    let mut i = 0;
    for this.each |a| {
        if !blk(i, a) {
            return false;
        }
        i += 1;
    }
    return true;
}

pub fn eachi<A,IA:BaseIter<A>>(this: &IA, blk: &fn(uint, &A) -> bool) -> bool {
    _eachi(this, blk)
}

#[inline(always)]
pub fn all<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
    for this.each |a| {
        if !blk(a) {
            return false;
        }
    }
    return true;
}

#[inline(always)]
pub fn any<A,IA:BaseIter<A>>(this: &IA, blk: &fn(&A) -> bool) -> bool {
    for this.each |a| {
        if blk(a) {
            return true;
        }
    }
    return false;
}

#[inline(always)]
pub fn filter_to_vec<A:Copy,IA:BaseIter<A>>(this: &IA,
                                            prd: &fn(&A) -> bool)
                                         -> ~[A] {
    do vec::build_sized_opt(this.size_hint()) |push| {
        for this.each |a| {
            if prd(a) { push(*a); }
        }
    }
}

#[inline(always)]
pub fn map_to_vec<A,B,IA:BaseIter<A>>(this: &IA, op: &fn(&A) -> B) -> ~[B] {
    do vec::build_sized_opt(this.size_hint()) |push| {
        for this.each |a| {
            push(op(a));
        }
    }
}

#[inline(always)]
pub fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(this: &IA,
                                                          op: &fn(&A) -> IB)
                                                       -> ~[B] {
    do vec::build |push| {
        for this.each |a| {
            for op(a).each |&b| {
                push(b);
            }
        }
    }
}

#[inline(always)]
pub fn foldl<A,B,IA:BaseIter<A>>(this: &IA, b0: B, blk: &fn(&B, &A) -> B)
                              -> B {
    let mut b = b0;
    for this.each |a| {
        b = blk(&b, a);
    }
    b
}

#[inline(always)]
pub fn to_vec<A:Copy,IA:BaseIter<A>>(this: &IA) -> ~[A] {
    map_to_vec(this, |&x| x)
}

#[inline(always)]
pub fn contains<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> bool {
    for this.each |a| {
        if *a == *x { return true; }
    }
    return false;
}

#[inline(always)]
pub fn count<A:Eq,IA:BaseIter<A>>(this: &IA, x: &A) -> uint {
    do foldl(this, 0) |count, value| {
        if *value == *x {
            *count + 1
        } else {
            *count
        }
    }
}

#[inline(always)]
pub fn position<A,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
                               -> Option<uint> {
    let mut i = 0;
    for this.each |a| {
        if f(a) { return Some(i); }
        i += 1;
    }
    return None;
}

#[inline(always)]
pub fn find<A:Copy,IA:BaseIter<A>>(this: &IA, f: &fn(&A) -> bool)
                                -> Option<A> {
    for this.each |i| {
        if f(i) { return Some(*i) }
    }
    return None;
}

// Some functions for just building

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 *
 * # Arguments
 *
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub fn build<A,B: Buildable<A>>(builder: &fn(push: &fn(A))) -> B {
    Buildable::build_sized(4, builder)
}

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of the sequence.
 * This version takes an initial size for the sequence.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the sequence
 *          to reserve.
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub fn build_sized_opt<A,B: Buildable<A>>(size: Option<uint>,
                                          builder: &fn(push: &fn(A))) -> B {
    Buildable::build_sized(size.get_or_default(4), builder)
}

// Functions that combine iteration and building

/// Applies a function to each element of an iterable and returns the results
/// in a sequence built via `BU`.  See also `map_to_vec`.
#[inline(always)]
pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: &fn(&T) -> U)
    -> BU {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each() |elem| {
            push(f(elem));
        }
    }
}

/**
 * Creates and initializes a generic sequence from a function.
 *
 * Creates a generic sequence of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
#[inline(always)]
pub fn from_fn<T,BT: Buildable<T>>(n_elts: uint, op: InitOp<T>) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes a generic sequence with some elements.
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
#[inline(always)]
pub fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint, t: T) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0;
        while i < n_elts { push(t); i += 1; }
    }
}

/// Appends two generic sequences.
#[inline(always)]
pub fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(lhs: &IT, rhs: &IT)
                                                  -> BT {
    let size_opt = lhs.size_hint().chain_ref(
        |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
    do build_sized_opt(size_opt) |push| {
        for lhs.each |x| { push(*x); }
        for rhs.each |x| { push(*x); }
    }
}

/// Copies a generic sequence, possibly converting it to a different
/// type of sequence.
#[inline(always)]
pub fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(v: &IT) -> BT {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each |x| { push(*x); }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "string_cache_namespace",
            reason = "This may move as string-cache becomes less Web-specific.")]

use atom::Atom;

/// An atom that is meant to represent a namespace in the HTML / XML sense.
/// Whether a given string represents a namespace is contextual, so this is
/// a transparent wrapper that will not catch all mistakes.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct Namespace(pub Atom);

/// A name with a namespace.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct QualName {
    pub ns: Namespace,
    pub local: Atom,
}

impl QualName {
    #[inline]
    pub fn new(ns: Namespace, local: Atom) -> QualName {
        QualName {
            ns: ns,
            local: local,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Namespace, QualName};

    #[test]
    fn ns_macro() {
        assert_eq!(ns!(""),     Namespace(atom!("")));

        assert_eq!(ns!(html),   Namespace(atom!("http://www.w3.org/1999/xhtml")));
        assert_eq!(ns!(xml),    Namespace(atom!("http://www.w3.org/XML/1998/namespace")));
        assert_eq!(ns!(xmlns),  Namespace(atom!("http://www.w3.org/2000/xmlns/")));
        assert_eq!(ns!(xlink),  Namespace(atom!("http://www.w3.org/1999/xlink")));
        assert_eq!(ns!(svg),    Namespace(atom!("http://www.w3.org/2000/svg")));
        assert_eq!(ns!(mathml), Namespace(atom!("http://www.w3.org/1998/Math/MathML")));

        assert_eq!(ns!(HtMl),   Namespace(atom!("http://www.w3.org/1999/xhtml")));
        assert_eq!(ns!(xMl),    Namespace(atom!("http://www.w3.org/XML/1998/namespace")));
        assert_eq!(ns!(XmLnS),  Namespace(atom!("http://www.w3.org/2000/xmlns/")));
        assert_eq!(ns!(xLiNk),  Namespace(atom!("http://www.w3.org/1999/xlink")));
        assert_eq!(ns!(SvG),    Namespace(atom!("http://www.w3.org/2000/svg")));
        assert_eq!(ns!(mAtHmL), Namespace(atom!("http://www.w3.org/1998/Math/MathML")));
    }

    #[test]
    fn qualname() {
        assert_eq!(QualName::new(ns!(""), atom!("")),
            QualName { ns: ns!(""), local: atom!("") });
        assert_eq!(QualName::new(ns!(XML), atom!(base)),
            QualName { ns: ns!(XML), local: atom!(base) });
    }

    #[test]
    fn qualname_macro() {
        assert_eq!(qualname!("", ""), QualName { ns: ns!(""), local: atom!("") });
        assert_eq!(qualname!(XML, base), QualName { ns: ns!(XML), local: atom!(base) });
    }
}
<commit_msg>Upgrade to rustc 1.1.0-nightly (90cc83015 2015-04-22) (built 2015-04-23)<commit_after>// Copyright 2014 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! **Note:** This may move as string-cache becomes less Web-specific.

use atom::Atom;

/// An atom that is meant to represent a namespace in the HTML / XML sense.
/// Whether a given string represents a namespace is contextual, so this is
/// a transparent wrapper that will not catch all mistakes.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct Namespace(pub Atom);

/// A name with a namespace.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Clone)]
pub struct QualName {
    pub ns: Namespace,
    pub local: Atom,
}

impl QualName {
    #[inline]
    pub fn new(ns: Namespace, local: Atom) -> QualName {
        QualName {
            ns: ns,
            local: local,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{Namespace, QualName};

    #[test]
    fn ns_macro() {
        assert_eq!(ns!(""),     Namespace(atom!("")));

        assert_eq!(ns!(html),   Namespace(atom!("http://www.w3.org/1999/xhtml")));
        assert_eq!(ns!(xml),    Namespace(atom!("http://www.w3.org/XML/1998/namespace")));
        assert_eq!(ns!(xmlns),  Namespace(atom!("http://www.w3.org/2000/xmlns/")));
        assert_eq!(ns!(xlink),  Namespace(atom!("http://www.w3.org/1999/xlink")));
        assert_eq!(ns!(svg),    Namespace(atom!("http://www.w3.org/2000/svg")));
        assert_eq!(ns!(mathml), Namespace(atom!("http://www.w3.org/1998/Math/MathML")));

        assert_eq!(ns!(HtMl),   Namespace(atom!("http://www.w3.org/1999/xhtml")));
        assert_eq!(ns!(xMl),    Namespace(atom!("http://www.w3.org/XML/1998/namespace")));
        assert_eq!(ns!(XmLnS),  Namespace(atom!("http://www.w3.org/2000/xmlns/")));
        assert_eq!(ns!(xLiNk),  Namespace(atom!("http://www.w3.org/1999/xlink")));
        assert_eq!(ns!(SvG),    Namespace(atom!("http://www.w3.org/2000/svg")));
        assert_eq!(ns!(mAtHmL), Namespace(atom!("http://www.w3.org/1998/Math/MathML")));
    }

    #[test]
    fn qualname() {
        assert_eq!(QualName::new(ns!(""), atom!("")),
            QualName { ns: ns!(""), local: atom!("") });
        assert_eq!(QualName::new(ns!(XML), atom!(base)),
            QualName { ns: ns!(XML), local: atom!(base) });
    }

    #[test]
    fn qualname_macro() {
        assert_eq!(qualname!("", ""), QualName { ns: ns!(""), local: atom!("") });
        assert_eq!(qualname!(XML, base), QualName { ns: ns!(XML), local: atom!(base) });
    }
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use messaging::{UpdateMessage, UpdateMessageSender};

use super::Mixer;
use super::AudioFilter;

pub struct SoftMixer {
  volume: Arc<AtomicUsize>,
  tx: Option<UpdateMessageSender>
}

impl SoftMixer {
    pub fn new() -> SoftMixer {
        SoftMixer {
            volume: Arc::new(AtomicUsize::new(0xFFFF)),
            tx: None
        }
    }
}

impl Mixer for SoftMixer {
    fn init(&mut self, tx: UpdateMessageSender) {
        self.tx = Some(tx);
    }
    fn start(&self) {
    }
    fn stop(&self) {
    }
    fn volume(&self) -> u16 {
        self.volume.load(Ordering::Relaxed) as u16
    }
    fn set_volume(&self, volume: u16) {
        self.volume.store(volume as usize, Ordering::Relaxed);
        let tx = self.tx.as_ref().expect("SoftMixer not initialized");
        tx.send(UpdateMessage).unwrap();
    }
    fn get_audio_filter(&self) -> Option<Box<AudioFilter + Send>> {
        Some(Box::new(SoftVolumeApplier { volume: self.volume.clone() }))
    }
}

struct SoftVolumeApplier {
  volume: Arc<AtomicUsize>
}

impl AudioFilter for SoftVolumeApplier {
    fn modify_stream(&self, data: &mut [i16]) {
        let volume = self.volume.load(Ordering::Relaxed) as u16;
        if volume != 0xFFFF {
            let factor = volume as i32 / 0xFFFF;
            for x in data.iter_mut() {
                *x = (*x as i32 * factor) as i16;
            }
        }
    }
}<commit_msg>SoftVolumeMixer: move factor in again, otherwise i32 division always results in 0<commit_after>use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};

use messaging::{UpdateMessage, UpdateMessageSender};

use super::Mixer;
use super::AudioFilter;

pub struct SoftMixer {
  volume: Arc<AtomicUsize>,
  tx: Option<UpdateMessageSender>
}

impl SoftMixer {
    pub fn new() -> SoftMixer {
        SoftMixer {
            volume: Arc::new(AtomicUsize::new(0xFFFF)),
            tx: None
        }
    }
}

impl Mixer for SoftMixer {
    fn init(&mut self, tx: UpdateMessageSender) {
        self.tx = Some(tx);
    }
    fn start(&self) {
    }
    fn stop(&self) {
    }
    fn volume(&self) -> u16 {
        self.volume.load(Ordering::Relaxed) as u16
    }
    fn set_volume(&self, volume: u16) {
        self.volume.store(volume as usize, Ordering::Relaxed);
        let tx = self.tx.as_ref().expect("SoftMixer not initialized");
        tx.send(UpdateMessage).unwrap();
    }
    fn get_audio_filter(&self) -> Option<Box<AudioFilter + Send>> {
        Some(Box::new(SoftVolumeApplier { volume: self.volume.clone() }))
    }
}

struct SoftVolumeApplier {
  volume: Arc<AtomicUsize>
}

impl AudioFilter for SoftVolumeApplier {
    fn modify_stream(&self, data: &mut [i16]) {
        let volume = self.volume.load(Ordering::Relaxed) as u16;
        if volume != 0xFFFF {
            for x in data.iter_mut() {
                *x = (*x as i32 * volume as i32 / 0xFFFF) as i16;
            }
        }
    }
}<|endoftext|>


<commit_before>use nes::system::{System, SystemState};
use nes::bus::BusKind;

#[derive(Default)]
pub struct InputState {
    read_counter: u32,
    read_shifter: u8,
    input_buffer: u8,
    pub input: u8,
}

pub trait InputDevice {
    fn to_byte(&self) -> u8;
}

pub struct Controller {
    pub a: bool,
    pub b: bool,
    pub select: bool,
    pub start: bool,
    pub up: bool,
    pub down: bool,
    pub left: bool,
    pub right: bool,
}

impl Controller {
    pub fn new() -> Controller {
        Controller {
            a: false,
            b: false,
            select: false,
            start: false,
            up: false,
            down: false,
            left: false,
            right: false,
        }
    }
}

impl InputDevice for Controller {
    fn to_byte(&self) -> u8 {
        let mut value = 0;
        if self.a { value |= 0x01; }
        if self.b { value |= 0x02; }
        if self.select { value |= 0x04; }
        if self.start { value |= 0x08; }
        if self.up { value |= 0x10; }
        if self.down { value |= 0x20; }
        if self.left { value |= 0x40; }
        if self.right { value |= 0x80; }

        value
    }
}

pub struct Input;

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

    pub fn peek(&self, device: BusKind, system: &System, state: &SystemState, addr: u16)-> u8 {
        match addr {
            0x4016 => {
                if state.input.read_counter == 0 {
                    0x41
                } else {
                    let value = (state.input.read_shifter & 1) | 0x40;
                    value
                }
            },
            0x4017 => {
                0x40
            },
            _ => unimplemented!()
        }
    }

    pub fn read(&self, device: BusKind, system: &System, state: &mut SystemState, addr: u16) -> u8 {
        match addr {
            0x4016 => {
                if state.input.read_counter == 0 {
                    0x41
                } else {
                    let value = (state.input.read_shifter & 1) | 0x40;
                    state.input.read_shifter >>= 1;
                    state.input.read_counter -= 1;
                    value
                }
            },
            0x4017 => {
                0x40
            },
            _ => unimplemented!()
        }
    }

    pub fn write(&self, device: BusKind, system: &System, state: &mut SystemState, addr: u16, value: u8) {
        match addr {
            0x4016 => {
                if value & 0x01 == 1 {
                    state.input.input_buffer = state.input.input;
                    system.debug.log_for(state, 100);
                } else {
                    state.input.read_shifter = state.input.input_buffer;
                    state.input.read_counter = 8;
                }
            },
            _ => unimplemented!()
        }
    }
}

<commit_msg>Turn off input logging<commit_after>use nes::system::{System, SystemState};
use nes::bus::BusKind;

#[derive(Default)]
pub struct InputState {
    read_counter: u32,
    read_shifter: u8,
    input_buffer: u8,
    pub input: u8,
}

pub trait InputDevice {
    fn to_byte(&self) -> u8;
}

pub struct Controller {
    pub a: bool,
    pub b: bool,
    pub select: bool,
    pub start: bool,
    pub up: bool,
    pub down: bool,
    pub left: bool,
    pub right: bool,
}

impl Controller {
    pub fn new() -> Controller {
        Controller {
            a: false,
            b: false,
            select: false,
            start: false,
            up: false,
            down: false,
            left: false,
            right: false,
        }
    }
}

impl InputDevice for Controller {
    fn to_byte(&self) -> u8 {
        let mut value = 0;
        if self.a { value |= 0x01; }
        if self.b { value |= 0x02; }
        if self.select { value |= 0x04; }
        if self.start { value |= 0x08; }
        if self.up { value |= 0x10; }
        if self.down { value |= 0x20; }
        if self.left { value |= 0x40; }
        if self.right { value |= 0x80; }

        value
    }
}

pub struct Input;

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

    pub fn peek(&self, device: BusKind, system: &System, state: &SystemState, addr: u16)-> u8 {
        match addr {
            0x4016 => {
                if state.input.read_counter == 0 {
                    0x41
                } else {
                    let value = (state.input.read_shifter & 1) | 0x40;
                    value
                }
            },
            0x4017 => {
                0x40
            },
            _ => unimplemented!()
        }
    }

    pub fn read(&self, device: BusKind, system: &System, state: &mut SystemState, addr: u16) -> u8 {
        match addr {
            0x4016 => {
                if state.input.read_counter == 0 {
                    0x41
                } else {
                    let value = (state.input.read_shifter & 1) | 0x40;
                    state.input.read_shifter >>= 1;
                    state.input.read_counter -= 1;
                    value
                }
            },
            0x4017 => {
                0x40
            },
            _ => unimplemented!()
        }
    }

    pub fn write(&self, device: BusKind, system: &System, state: &mut SystemState, addr: u16, value: u8) {
        match addr {
            0x4016 => {
                if value & 0x01 == 1 {
                    state.input.input_buffer = state.input.input;
                } else {
                    state.input.read_shifter = state.input.input_buffer;
                    state.input.read_counter = 8;
                }
            },
            _ => unimplemented!()
        }
    }
}

<|endoftext|>


<commit_before>//! Various source mapping utilities

use std::borrow::Cow;
use std::path::{Path, PathBuf};
use std::{fmt, io};

use index::{ByteIndex, ByteOffset, ColumnIndex, LineIndex, LineOffset, RawIndex, RawOffset};
use span::ByteSpan;

#[derive(Clone, Debug)]
pub enum FileName {
    /// A real file on disk
    Real(PathBuf),
    /// A synthetic file, eg. from the REPL
    Virtual(Cow<'static, str>),
}

impl From<PathBuf> for FileName {
    fn from(name: PathBuf) -> FileName {
        FileName::real(name)
    }
}

impl<'a> From<&'a Path> for FileName {
    fn from(name: &Path) -> FileName {
        FileName::real(name)
    }
}

impl From<String> for FileName {
    fn from(name: String) -> FileName {
        FileName::virtual_(name)
    }
}

impl From<&'static str> for FileName {
    fn from(name: &'static str) -> FileName {
        FileName::virtual_(name)
    }
}

impl FileName {
    pub fn real<T: Into<PathBuf>>(name: T) -> FileName {
        FileName::Real(name.into())
    }

    pub fn virtual_<T: Into<Cow<'static, str>>>(name: T) -> FileName {
        FileName::Virtual(name.into())
    }
}

impl fmt::Display for FileName {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FileName::Real(ref path) => write!(fmt, "{}", path.display()),
            FileName::Virtual(ref name) => write!(fmt, "<{}>", name),
        }
    }
}

#[derive(Debug, Fail, PartialEq)]
pub enum LineIndexError {
    #[fail(display = "Line out of bounds - given: {:?}, max: {:?}", given, max)]
    OutOfBounds { given: LineIndex, max: LineIndex },
}

#[derive(Debug, Fail, PartialEq)]
pub enum ByteIndexError {
    #[fail(display = "Byte index out of bounds - given: {}, span: {}", given, span)]
    OutOfBounds { given: ByteIndex, span: ByteSpan },
    #[fail(display = "Byte index points within a character boundary - given: {}", given)]
    InvalidCharBoundary { given: ByteIndex },
}

#[derive(Debug, Fail, PartialEq)]
pub enum LocationError {
    #[fail(display = "Line out of bounds - given: {:?}, max: {:?}", given, max)]
    LineOutOfBounds { given: LineIndex, max: LineIndex },
    #[fail(display = "Column out of bounds - given: {:?}, max: {:?}", given, max)]
    ColumnOutOfBounds {
        given: ColumnIndex,
        max: ColumnIndex,
    },
}

#[derive(Debug, Fail, PartialEq)]
pub enum SpanError {
    #[fail(display = "Span out of bounds - given: {}, span: {}", given, span)]
    OutOfBounds { given: ByteSpan, span: ByteSpan },
}

#[derive(Debug)]
/// Some source code
pub struct FileMap {
    /// The name of the file that the source came from
    name: FileName,
    /// The complete source code
    src: String,
    /// The span of the source in the `CodeMap`
    span: ByteSpan,
    /// Offsets to the line beginnings in the source
    lines: Vec<ByteOffset>,
}

impl FileMap {
    /// Construct a new, standalone filemap.
    ///
    /// This can be useful for tests that consist of a single source file. Production code should however
    /// use `CodeMap::add_filemap` or `CodeMap::add_filemap_from_disk` instead.
    pub fn new(name: FileName, src: String) -> FileMap {
        FileMap::with_index(name, src, ByteIndex(1))
    }

    pub(crate) fn with_index(name: FileName, src: String, start: ByteIndex) -> FileMap {
        use std::iter;

        let span = ByteSpan::from_offset(start, ByteOffset::from_str(&src));
        let lines = {
            let newline_off = ByteOffset::from_char_utf8('\n');
            let offsets = src.match_indices('\n')
                .map(|(i, _)| ByteOffset(i as RawOffset) + newline_off);

            iter::once(ByteOffset(0)).chain(offsets).collect()
        };

        FileMap {
            name,
            src,
            span,
            lines,
        }
    }

    /// Read some source code from a file, loading it into a filemap
    pub(crate) fn from_disk<P: Into<PathBuf>>(name: P, start: ByteIndex) -> io::Result<FileMap> {
        use std::fs::File;
        use std::io::Read;

        let name = name.into();
        let mut file = File::open(&name)?;
        let mut src = String::new();
        file.read_to_string(&mut src)?;

        Ok(FileMap::with_index(FileName::Real(name), src, start))
    }

    /// The name of the file that the source came from
    pub fn name(&self) -> &FileName {
        &self.name
    }

    /// The underlying source code
    pub fn src(&self) -> &str {
        &self.src
    }

    /// The span of the source in the `CodeMap`
    pub fn span(&self) -> ByteSpan {
        self.span
    }

    pub fn offset(
        &self,
        line: LineIndex,
        column: ColumnIndex,
    ) -> Result<ByteOffset, LocationError> {
        self.byte_index(line, column)
            .map(|index| index - self.span.start())
    }

    pub fn byte_index(
        &self,
        line: LineIndex,
        column: ColumnIndex,
    ) -> Result<ByteIndex, LocationError> {
        self.line_span(line)
            .map_err(
                |LineIndexError::OutOfBounds { given, max }| LocationError::LineOutOfBounds {
                    given,
                    max,
                },
            )
            .and_then(|span| {
                let distance = ColumnIndex(span.end().0 - span.start().0);
                if column > distance {
                    Err(LocationError::ColumnOutOfBounds {
                        given: column,
                        max: distance,
                    })
                } else {
                    Ok(span.start() + ByteOffset::from(column.0 as i64))
                }
            })
    }

    /// Returns the byte offset to the start of `line`
    pub fn line_offset(&self, index: LineIndex) -> Result<ByteOffset, LineIndexError> {
        self.lines
            .get(index.to_usize())
            .cloned()
            .ok_or_else(|| LineIndexError::OutOfBounds {
                given: index,
                max: LineIndex(self.lines.len() as RawIndex - 1),
            })
    }

    /// Returns the byte index of the start of `line`
    pub fn line_byte_index(&self, index: LineIndex) -> Result<ByteIndex, LineIndexError> {
        self.line_offset(index)
            .map(|offset| self.span.start() + offset)
    }

    /// Returns the byte offset to the start of `line`
    pub fn line_span(&self, line: LineIndex) -> Result<ByteSpan, LineIndexError> {
        let start = self.span.start() + self.line_offset(line)?;
        let end = match self.line_offset(line + LineOffset(1)) {
            Ok(offset_hi) => self.span.start() + offset_hi,
            Err(_) => self.span.end(),
        };

        Ok(ByteSpan::new(end, start))
    }

    /// Returns the line and column location of `byte`
    pub fn location(&self, index: ByteIndex) -> Result<(LineIndex, ColumnIndex), ByteIndexError> {
        let line_index = self.find_line(index)?;
        let line_span = self.line_span(line_index).unwrap(); // line_index should be valid!
        let line_slice = self.src_slice(line_span).unwrap(); // line_span should be valid!
        let byte_col = index - line_span.start();
        let column_index =
            ColumnIndex(line_slice[..byte_col.to_usize()].chars().count() as RawIndex);

        Ok((line_index, column_index))
    }

    /// Returns the line index that the byte index points to
    pub fn find_line(&self, index: ByteIndex) -> Result<LineIndex, ByteIndexError> {
        if index < self.span.start() || index > self.span.end() {
            Err(ByteIndexError::OutOfBounds {
                given: index,
                span: self.span,
            })
        } else {
            let offset = index - self.span.start();

            if self.src.is_char_boundary(offset.to_usize()) {
                match self.lines.binary_search(&offset) {
                    Ok(i) => Ok(LineIndex(i as RawIndex)),
                    Err(i) => Ok(LineIndex(i as RawIndex - 1)),
                }
            } else {
                Err(ByteIndexError::InvalidCharBoundary {
                    given: self.span.start(),
                })
            }
        }
    }

    /// Get the corresponding source string for a span
    ///
    /// Returns `Err` if the span is outside the bounds of the file
    pub fn src_slice(&self, span: ByteSpan) -> Result<&str, SpanError> {
        if self.span.contains(span) {
            let start = (span.start() - self.span.start()).to_usize();
            let end = (span.end() - self.span.start()).to_usize();

            // TODO: check char boundaries
            Ok(&self.src[start..end])
        } else {
            Err(SpanError::OutOfBounds {
                given: span,
                span: self.span,
            })
        }
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use {CodeMap, FileMap, FileName};

    use super::*;

    struct TestData {
        filemap: Arc<FileMap>,
        lines: &'static [&'static str],
    }

    impl TestData {
        fn new() -> TestData {
            let mut codemap = CodeMap::new();
            let lines = &["hello!\n", "howdy\n", "\n", "hi萤\n", "bloop\n"];
            let filemap = codemap.add_filemap(FileName::Virtual("test".into()), lines.concat());

            TestData { filemap, lines }
        }

        fn byte_offsets(&self) -> Vec<ByteOffset> {
            let mut offset = ByteOffset(0);
            let mut byte_offsets = Vec::new();

            for line in self.lines {
                byte_offsets.push(offset);
                offset += ByteOffset::from_str(line);
                byte_offsets.push(offset + -ByteOffset::from_char_utf8('\n'));
            }

            // bump us past the end
            byte_offsets.push(offset);

            byte_offsets
        }

        fn byte_indices(&self) -> Vec<ByteIndex> {
            let mut offsets = vec![ByteIndex::none()];
            offsets.extend(self.byte_offsets().iter().map(|&off| ByteIndex(1) + off));
            let out_of_bounds = *offsets.last().unwrap() + ByteOffset(1);
            offsets.push(out_of_bounds);
            offsets
        }

        fn line_indices(&self) -> Vec<LineIndex> {
            (0..self.lines.len() + 2)
                .map(|i| LineIndex(i as RawIndex))
                .collect()
        }
    }

    #[test]
    fn offset() {
        let test_data = TestData::new();
        assert!(
            test_data
                .filemap
                .offset(
                    (test_data.lines.len() as u32 - 1).into(),
                    (test_data.lines.last().unwrap().len() as u32).into()
                )
                .is_ok()
        );
        assert!(
            test_data
                .filemap
                .offset(
                    (test_data.lines.len() as u32 - 1).into(),
                    (test_data.lines.last().unwrap().len() as u32 + 1).into()
                )
                .is_err()
        );
    }

    #[test]
    fn line_offset() {
        let test_data = TestData::new();
        let offsets: Vec<_> = test_data
            .line_indices()
            .iter()
            .map(|&i| test_data.filemap.line_offset(i))
            .collect();

        assert_eq!(
            offsets,
            vec![
                Ok(ByteOffset(0)),
                Ok(ByteOffset(7)),
                Ok(ByteOffset(13)),
                Ok(ByteOffset(14)),
                Ok(ByteOffset(20)),
                Ok(ByteOffset(26)),
                Err(LineIndexError::OutOfBounds {
                    given: LineIndex(6),
                    max: LineIndex(5),
                }),
            ],
        );
    }

    #[test]
    fn line_byte_index() {
        let test_data = TestData::new();
        let offsets: Vec<_> = test_data
            .line_indices()
            .iter()
            .map(|&i| test_data.filemap.line_byte_index(i))
            .collect();

        assert_eq!(
            offsets,
            vec![
                Ok(test_data.filemap.span().start() + ByteOffset(0)),
                Ok(test_data.filemap.span().start() + ByteOffset(7)),
                Ok(test_data.filemap.span().start() + ByteOffset(13)),
                Ok(test_data.filemap.span().start() + ByteOffset(14)),
                Ok(test_data.filemap.span().start() + ByteOffset(20)),
                Ok(test_data.filemap.span().start() + ByteOffset(26)),
                Err(LineIndexError::OutOfBounds {
                    given: LineIndex(6),
                    max: LineIndex(5),
                }),
            ],
        );
    }

    // #[test]
    // fn line_span() {
    //     let filemap = filemap();
    //     let start = filemap.span().start();

    //     assert_eq!(filemap.line_byte_index(Li(0)), Some(start + BOff(0)));
    //     assert_eq!(filemap.line_byte_index(Li(1)), Some(start + BOff(7)));
    //     assert_eq!(filemap.line_byte_index(Li(2)), Some(start + BOff(13)));
    //     assert_eq!(filemap.line_byte_index(Li(3)), Some(start + BOff(14)));
    //     assert_eq!(filemap.line_byte_index(Li(4)), Some(start + BOff(20)));
    //     assert_eq!(filemap.line_byte_index(Li(5)), Some(start + BOff(26)));
    //     assert_eq!(filemap.line_byte_index(Li(6)), None);
    // }

    #[test]
    fn location() {
        let test_data = TestData::new();
        let lines: Vec<_> = test_data
            .byte_indices()
            .iter()
            .map(|&index| test_data.filemap.location(index))
            .collect();

        assert_eq!(
            lines,
            vec![
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(0),
                    span: test_data.filemap.span(),
                }),
                Ok((LineIndex(0), ColumnIndex(0))),
                Ok((LineIndex(0), ColumnIndex(6))),
                Ok((LineIndex(1), ColumnIndex(0))),
                Ok((LineIndex(1), ColumnIndex(5))),
                Ok((LineIndex(2), ColumnIndex(0))),
                Ok((LineIndex(2), ColumnIndex(0))),
                Ok((LineIndex(3), ColumnIndex(0))),
                Ok((LineIndex(3), ColumnIndex(3))),
                Ok((LineIndex(4), ColumnIndex(0))),
                Ok((LineIndex(4), ColumnIndex(5))),
                Ok((LineIndex(5), ColumnIndex(0))),
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(28),
                    span: test_data.filemap.span(),
                }),
            ],
        );
    }

    #[test]
    fn find_line() {
        let test_data = TestData::new();
        let lines: Vec<_> = test_data
            .byte_indices()
            .iter()
            .map(|&index| test_data.filemap.find_line(index))
            .collect();

        assert_eq!(
            lines,
            vec![
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(0),
                    span: test_data.filemap.span(),
                }),
                Ok(LineIndex(0)),
                Ok(LineIndex(0)),
                Ok(LineIndex(1)),
                Ok(LineIndex(1)),
                Ok(LineIndex(2)),
                Ok(LineIndex(2)),
                Ok(LineIndex(3)),
                Ok(LineIndex(3)),
                Ok(LineIndex(4)),
                Ok(LineIndex(4)),
                Ok(LineIndex(5)),
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(28),
                    span: test_data.filemap.span(),
                }),
            ],
        );
    }
}
<commit_msg>feat: Implement comparison traits on FileName<commit_after>//! Various source mapping utilities

use std::borrow::Cow;
use std::path::{Path, PathBuf};
use std::{fmt, io};

use index::{ByteIndex, ByteOffset, ColumnIndex, LineIndex, LineOffset, RawIndex, RawOffset};
use span::ByteSpan;

#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum FileName {
    /// A real file on disk
    Real(PathBuf),
    /// A synthetic file, eg. from the REPL
    Virtual(Cow<'static, str>),
}

impl From<PathBuf> for FileName {
    fn from(name: PathBuf) -> FileName {
        FileName::real(name)
    }
}

impl<'a> From<&'a Path> for FileName {
    fn from(name: &Path) -> FileName {
        FileName::real(name)
    }
}

impl From<String> for FileName {
    fn from(name: String) -> FileName {
        FileName::virtual_(name)
    }
}

impl From<&'static str> for FileName {
    fn from(name: &'static str) -> FileName {
        FileName::virtual_(name)
    }
}

impl FileName {
    pub fn real<T: Into<PathBuf>>(name: T) -> FileName {
        FileName::Real(name.into())
    }

    pub fn virtual_<T: Into<Cow<'static, str>>>(name: T) -> FileName {
        FileName::Virtual(name.into())
    }
}

impl fmt::Display for FileName {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FileName::Real(ref path) => write!(fmt, "{}", path.display()),
            FileName::Virtual(ref name) => write!(fmt, "<{}>", name),
        }
    }
}

#[derive(Debug, Fail, PartialEq)]
pub enum LineIndexError {
    #[fail(display = "Line out of bounds - given: {:?}, max: {:?}", given, max)]
    OutOfBounds { given: LineIndex, max: LineIndex },
}

#[derive(Debug, Fail, PartialEq)]
pub enum ByteIndexError {
    #[fail(display = "Byte index out of bounds - given: {}, span: {}", given, span)]
    OutOfBounds { given: ByteIndex, span: ByteSpan },
    #[fail(display = "Byte index points within a character boundary - given: {}", given)]
    InvalidCharBoundary { given: ByteIndex },
}

#[derive(Debug, Fail, PartialEq)]
pub enum LocationError {
    #[fail(display = "Line out of bounds - given: {:?}, max: {:?}", given, max)]
    LineOutOfBounds { given: LineIndex, max: LineIndex },
    #[fail(display = "Column out of bounds - given: {:?}, max: {:?}", given, max)]
    ColumnOutOfBounds {
        given: ColumnIndex,
        max: ColumnIndex,
    },
}

#[derive(Debug, Fail, PartialEq)]
pub enum SpanError {
    #[fail(display = "Span out of bounds - given: {}, span: {}", given, span)]
    OutOfBounds { given: ByteSpan, span: ByteSpan },
}

#[derive(Debug)]
/// Some source code
pub struct FileMap {
    /// The name of the file that the source came from
    name: FileName,
    /// The complete source code
    src: String,
    /// The span of the source in the `CodeMap`
    span: ByteSpan,
    /// Offsets to the line beginnings in the source
    lines: Vec<ByteOffset>,
}

impl FileMap {
    /// Construct a new, standalone filemap.
    ///
    /// This can be useful for tests that consist of a single source file. Production code should however
    /// use `CodeMap::add_filemap` or `CodeMap::add_filemap_from_disk` instead.
    pub fn new(name: FileName, src: String) -> FileMap {
        FileMap::with_index(name, src, ByteIndex(1))
    }

    pub(crate) fn with_index(name: FileName, src: String, start: ByteIndex) -> FileMap {
        use std::iter;

        let span = ByteSpan::from_offset(start, ByteOffset::from_str(&src));
        let lines = {
            let newline_off = ByteOffset::from_char_utf8('\n');
            let offsets = src.match_indices('\n')
                .map(|(i, _)| ByteOffset(i as RawOffset) + newline_off);

            iter::once(ByteOffset(0)).chain(offsets).collect()
        };

        FileMap {
            name,
            src,
            span,
            lines,
        }
    }

    /// Read some source code from a file, loading it into a filemap
    pub(crate) fn from_disk<P: Into<PathBuf>>(name: P, start: ByteIndex) -> io::Result<FileMap> {
        use std::fs::File;
        use std::io::Read;

        let name = name.into();
        let mut file = File::open(&name)?;
        let mut src = String::new();
        file.read_to_string(&mut src)?;

        Ok(FileMap::with_index(FileName::Real(name), src, start))
    }

    /// The name of the file that the source came from
    pub fn name(&self) -> &FileName {
        &self.name
    }

    /// The underlying source code
    pub fn src(&self) -> &str {
        &self.src
    }

    /// The span of the source in the `CodeMap`
    pub fn span(&self) -> ByteSpan {
        self.span
    }

    pub fn offset(
        &self,
        line: LineIndex,
        column: ColumnIndex,
    ) -> Result<ByteOffset, LocationError> {
        self.byte_index(line, column)
            .map(|index| index - self.span.start())
    }

    pub fn byte_index(
        &self,
        line: LineIndex,
        column: ColumnIndex,
    ) -> Result<ByteIndex, LocationError> {
        self.line_span(line)
            .map_err(
                |LineIndexError::OutOfBounds { given, max }| LocationError::LineOutOfBounds {
                    given,
                    max,
                },
            )
            .and_then(|span| {
                let distance = ColumnIndex(span.end().0 - span.start().0);
                if column > distance {
                    Err(LocationError::ColumnOutOfBounds {
                        given: column,
                        max: distance,
                    })
                } else {
                    Ok(span.start() + ByteOffset::from(column.0 as i64))
                }
            })
    }

    /// Returns the byte offset to the start of `line`
    pub fn line_offset(&self, index: LineIndex) -> Result<ByteOffset, LineIndexError> {
        self.lines
            .get(index.to_usize())
            .cloned()
            .ok_or_else(|| LineIndexError::OutOfBounds {
                given: index,
                max: LineIndex(self.lines.len() as RawIndex - 1),
            })
    }

    /// Returns the byte index of the start of `line`
    pub fn line_byte_index(&self, index: LineIndex) -> Result<ByteIndex, LineIndexError> {
        self.line_offset(index)
            .map(|offset| self.span.start() + offset)
    }

    /// Returns the byte offset to the start of `line`
    pub fn line_span(&self, line: LineIndex) -> Result<ByteSpan, LineIndexError> {
        let start = self.span.start() + self.line_offset(line)?;
        let end = match self.line_offset(line + LineOffset(1)) {
            Ok(offset_hi) => self.span.start() + offset_hi,
            Err(_) => self.span.end(),
        };

        Ok(ByteSpan::new(end, start))
    }

    /// Returns the line and column location of `byte`
    pub fn location(&self, index: ByteIndex) -> Result<(LineIndex, ColumnIndex), ByteIndexError> {
        let line_index = self.find_line(index)?;
        let line_span = self.line_span(line_index).unwrap(); // line_index should be valid!
        let line_slice = self.src_slice(line_span).unwrap(); // line_span should be valid!
        let byte_col = index - line_span.start();
        let column_index =
            ColumnIndex(line_slice[..byte_col.to_usize()].chars().count() as RawIndex);

        Ok((line_index, column_index))
    }

    /// Returns the line index that the byte index points to
    pub fn find_line(&self, index: ByteIndex) -> Result<LineIndex, ByteIndexError> {
        if index < self.span.start() || index > self.span.end() {
            Err(ByteIndexError::OutOfBounds {
                given: index,
                span: self.span,
            })
        } else {
            let offset = index - self.span.start();

            if self.src.is_char_boundary(offset.to_usize()) {
                match self.lines.binary_search(&offset) {
                    Ok(i) => Ok(LineIndex(i as RawIndex)),
                    Err(i) => Ok(LineIndex(i as RawIndex - 1)),
                }
            } else {
                Err(ByteIndexError::InvalidCharBoundary {
                    given: self.span.start(),
                })
            }
        }
    }

    /// Get the corresponding source string for a span
    ///
    /// Returns `Err` if the span is outside the bounds of the file
    pub fn src_slice(&self, span: ByteSpan) -> Result<&str, SpanError> {
        if self.span.contains(span) {
            let start = (span.start() - self.span.start()).to_usize();
            let end = (span.end() - self.span.start()).to_usize();

            // TODO: check char boundaries
            Ok(&self.src[start..end])
        } else {
            Err(SpanError::OutOfBounds {
                given: span,
                span: self.span,
            })
        }
    }
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use {CodeMap, FileMap, FileName};

    use super::*;

    struct TestData {
        filemap: Arc<FileMap>,
        lines: &'static [&'static str],
    }

    impl TestData {
        fn new() -> TestData {
            let mut codemap = CodeMap::new();
            let lines = &["hello!\n", "howdy\n", "\n", "hi萤\n", "bloop\n"];
            let filemap = codemap.add_filemap(FileName::Virtual("test".into()), lines.concat());

            TestData { filemap, lines }
        }

        fn byte_offsets(&self) -> Vec<ByteOffset> {
            let mut offset = ByteOffset(0);
            let mut byte_offsets = Vec::new();

            for line in self.lines {
                byte_offsets.push(offset);
                offset += ByteOffset::from_str(line);
                byte_offsets.push(offset + -ByteOffset::from_char_utf8('\n'));
            }

            // bump us past the end
            byte_offsets.push(offset);

            byte_offsets
        }

        fn byte_indices(&self) -> Vec<ByteIndex> {
            let mut offsets = vec![ByteIndex::none()];
            offsets.extend(self.byte_offsets().iter().map(|&off| ByteIndex(1) + off));
            let out_of_bounds = *offsets.last().unwrap() + ByteOffset(1);
            offsets.push(out_of_bounds);
            offsets
        }

        fn line_indices(&self) -> Vec<LineIndex> {
            (0..self.lines.len() + 2)
                .map(|i| LineIndex(i as RawIndex))
                .collect()
        }
    }

    #[test]
    fn offset() {
        let test_data = TestData::new();
        assert!(
            test_data
                .filemap
                .offset(
                    (test_data.lines.len() as u32 - 1).into(),
                    (test_data.lines.last().unwrap().len() as u32).into()
                )
                .is_ok()
        );
        assert!(
            test_data
                .filemap
                .offset(
                    (test_data.lines.len() as u32 - 1).into(),
                    (test_data.lines.last().unwrap().len() as u32 + 1).into()
                )
                .is_err()
        );
    }

    #[test]
    fn line_offset() {
        let test_data = TestData::new();
        let offsets: Vec<_> = test_data
            .line_indices()
            .iter()
            .map(|&i| test_data.filemap.line_offset(i))
            .collect();

        assert_eq!(
            offsets,
            vec![
                Ok(ByteOffset(0)),
                Ok(ByteOffset(7)),
                Ok(ByteOffset(13)),
                Ok(ByteOffset(14)),
                Ok(ByteOffset(20)),
                Ok(ByteOffset(26)),
                Err(LineIndexError::OutOfBounds {
                    given: LineIndex(6),
                    max: LineIndex(5),
                }),
            ],
        );
    }

    #[test]
    fn line_byte_index() {
        let test_data = TestData::new();
        let offsets: Vec<_> = test_data
            .line_indices()
            .iter()
            .map(|&i| test_data.filemap.line_byte_index(i))
            .collect();

        assert_eq!(
            offsets,
            vec![
                Ok(test_data.filemap.span().start() + ByteOffset(0)),
                Ok(test_data.filemap.span().start() + ByteOffset(7)),
                Ok(test_data.filemap.span().start() + ByteOffset(13)),
                Ok(test_data.filemap.span().start() + ByteOffset(14)),
                Ok(test_data.filemap.span().start() + ByteOffset(20)),
                Ok(test_data.filemap.span().start() + ByteOffset(26)),
                Err(LineIndexError::OutOfBounds {
                    given: LineIndex(6),
                    max: LineIndex(5),
                }),
            ],
        );
    }

    // #[test]
    // fn line_span() {
    //     let filemap = filemap();
    //     let start = filemap.span().start();

    //     assert_eq!(filemap.line_byte_index(Li(0)), Some(start + BOff(0)));
    //     assert_eq!(filemap.line_byte_index(Li(1)), Some(start + BOff(7)));
    //     assert_eq!(filemap.line_byte_index(Li(2)), Some(start + BOff(13)));
    //     assert_eq!(filemap.line_byte_index(Li(3)), Some(start + BOff(14)));
    //     assert_eq!(filemap.line_byte_index(Li(4)), Some(start + BOff(20)));
    //     assert_eq!(filemap.line_byte_index(Li(5)), Some(start + BOff(26)));
    //     assert_eq!(filemap.line_byte_index(Li(6)), None);
    // }

    #[test]
    fn location() {
        let test_data = TestData::new();
        let lines: Vec<_> = test_data
            .byte_indices()
            .iter()
            .map(|&index| test_data.filemap.location(index))
            .collect();

        assert_eq!(
            lines,
            vec![
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(0),
                    span: test_data.filemap.span(),
                }),
                Ok((LineIndex(0), ColumnIndex(0))),
                Ok((LineIndex(0), ColumnIndex(6))),
                Ok((LineIndex(1), ColumnIndex(0))),
                Ok((LineIndex(1), ColumnIndex(5))),
                Ok((LineIndex(2), ColumnIndex(0))),
                Ok((LineIndex(2), ColumnIndex(0))),
                Ok((LineIndex(3), ColumnIndex(0))),
                Ok((LineIndex(3), ColumnIndex(3))),
                Ok((LineIndex(4), ColumnIndex(0))),
                Ok((LineIndex(4), ColumnIndex(5))),
                Ok((LineIndex(5), ColumnIndex(0))),
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(28),
                    span: test_data.filemap.span(),
                }),
            ],
        );
    }

    #[test]
    fn find_line() {
        let test_data = TestData::new();
        let lines: Vec<_> = test_data
            .byte_indices()
            .iter()
            .map(|&index| test_data.filemap.find_line(index))
            .collect();

        assert_eq!(
            lines,
            vec![
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(0),
                    span: test_data.filemap.span(),
                }),
                Ok(LineIndex(0)),
                Ok(LineIndex(0)),
                Ok(LineIndex(1)),
                Ok(LineIndex(1)),
                Ok(LineIndex(2)),
                Ok(LineIndex(2)),
                Ok(LineIndex(3)),
                Ok(LineIndex(3)),
                Ok(LineIndex(4)),
                Ok(LineIndex(4)),
                Ok(LineIndex(5)),
                Err(ByteIndexError::OutOfBounds {
                    given: ByteIndex(28),
                    span: test_data.filemap.span(),
                }),
            ],
        );
    }
}
<|endoftext|>


<commit_before>use crate::printing;

pub fn next() {
    printing::heading("Follow feeds so that I'm aware of industry changes.");

    printing::subheading("Open the top recent items in each feed");

    printing::subheading("Programming");
    printing::list(vec!["https://www.reddit.com/r/programming/top/?t=month"]);

    printing::subheading("Unix");
    printing::list(vec![
        "https://brew.sh/blog",
        "https://www.reddit.com/r/commandline/top/?t=month",
    ]);

    printing::subheading("Vim");
    printing::list(vec![
        "https://www.vim.org/news/news.php",
        "https://www.reddit.com/r/vim/top/?t=month",
    ]);

    printing::subheading("Git");
    printing::list(vec!["https://www.reddit.com/r/git/top/?t=month"]);

    printing::subheading("Rust");
    printing::list(vec![
        "https://blog.rust-lang.org",
        "https://www.reddit.com/r/rust/top/?t=month",
    ]);

    printing::subheading("JavaScript");
    printing::list(vec!["https://www.reddit.com/r/javascript/top/?t=month"]);

    printing::pause();
}
<commit_msg>Add more core technologies used at work to feeds<commit_after>use crate::printing;

pub fn next() {
    printing::heading("Follow feeds so that I'm aware of industry changes.");

    printing::subheading("Open the top recent items in each feed");

    printing::subheading("Programming");
    printing::list(vec!["https://www.reddit.com/r/programming/top/?t=month"]);

    printing::subheading("Unix");
    printing::list(vec![
        "https://brew.sh/blog",
        "https://www.reddit.com/r/commandline/top/?t=month",
    ]);

    printing::subheading("Vim");
    printing::list(vec![
        "https://www.vim.org/news/news.php",
        "https://www.reddit.com/r/vim/top/?t=month",
    ]);

    printing::subheading("Git");
    printing::list(vec!["https://www.reddit.com/r/git/top/?t=month"]);

    printing::subheading("Rust");
    printing::list(vec![
        "https://blog.rust-lang.org",
        "https://www.reddit.com/r/rust/top/?t=month",
    ]);

    printing::subheading("JavaScript");
    printing::list(vec!["https://www.reddit.com/r/javascript/top/?t=month"]);
    printing::list(vec!["https://nodejs.org/en/blog/"]);
    printing::list(vec!["https://www.reddit.com/r/node/top/?t=month"]);
    printing::list(vec!["https://reactjs.org/blog/all.html"]);
    printing::list(vec!["https://nextjs.org/blog"]);

    printing::pause();
}
<|endoftext|>


<commit_before>pub mod average_segments;
pub mod best_segments;
pub mod best_split_times;
pub mod none;
pub mod worst_segments;

pub use self::average_segments::AverageSegments;
pub use self::best_segments::BestSegments;
pub use self::best_split_times::BestSplitTimes;
pub use self::none::None;
pub use self::worst_segments::WorstSegments;

use std::fmt::Debug;
use {Attempt, Segment};

pub trait ComparisonGenerator: Debug + ComparisonGeneratorClone {
    fn name(&self) -> &str;
    fn generate(&mut self, segments: &mut [Segment], attempts: &[Attempt]);
}

pub trait ComparisonGeneratorClone {
    fn clone_box(&self) -> Box<ComparisonGenerator>;
}

impl<T> ComparisonGeneratorClone for T
    where T: 'static + ComparisonGenerator + Clone
{
    fn clone_box(&self) -> Box<ComparisonGenerator> {
        Box::new(self.clone())
    }
}

impl Clone for Box<ComparisonGenerator> {
    fn clone(&self) -> Self {
        self.clone_box()
    }
}

pub fn default_generators() -> Vec<Box<ComparisonGenerator>> {
    vec![Box::new(BestSegments),
         Box::new(BestSplitTimes),
         Box::new(AverageSegments),
         Box::new(WorstSegments),
         Box::new(None)]
}
<commit_msg>Force Comparison Generators to be Send + Sync<commit_after>pub mod average_segments;
pub mod best_segments;
pub mod best_split_times;
pub mod none;
pub mod worst_segments;

pub use self::average_segments::AverageSegments;
pub use self::best_segments::BestSegments;
pub use self::best_split_times::BestSplitTimes;
pub use self::none::None;
pub use self::worst_segments::WorstSegments;

use std::fmt::Debug;
use {Attempt, Segment};

pub trait ComparisonGenerator: Debug + Sync + Send + ComparisonGeneratorClone {
    fn name(&self) -> &str;
    fn generate(&mut self, segments: &mut [Segment], attempts: &[Attempt]);
}

pub trait ComparisonGeneratorClone {
    fn clone_box(&self) -> Box<ComparisonGenerator>;
}

impl<T> ComparisonGeneratorClone for T
    where T: 'static + ComparisonGenerator + Clone
{
    fn clone_box(&self) -> Box<ComparisonGenerator> {
        Box::new(self.clone())
    }
}

impl Clone for Box<ComparisonGenerator> {
    fn clone(&self) -> Self {
        self.clone_box()
    }
}

pub fn default_generators() -> Vec<Box<ComparisonGenerator>> {
    vec![Box::new(BestSegments),
         Box::new(BestSplitTimes),
         Box::new(AverageSegments),
         Box::new(WorstSegments),
         Box::new(None)]
}
<|endoftext|>