<commit_before>//! Layout handling

// remove
#![allow(unused)]

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::VIEW_MAXIMIZED;
use std::rc::{Rc, Weak};
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;
use std::cell::RefCell;

pub type Node = Rc<RefCell<Container>>;

#[derive(Debug, Clone)]
pub enum Handle {
    View(WlcView),
    Output(WlcOutput)
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A Container, houses views and other containers
    Container,
    /// A view (window)
    View
}

/// Layout mode for a container
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Layout {
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

#[derive(Clone)]
pub struct Container {
    handle: Option<Handle>,
    parent: Option<Weak<RefCell<Container>>>,
    children: Vec<Node>,
    container_type: ContainerType,
    layout: Option<Layout>,
    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

/// Like i3, everything (workspaces, containers, views) are containable.
impl Container {

    /// Makes the root container. There should be only one of these
    /// Does not ensure that this is the only root container
    pub fn new_root() -> Node {
        trace!("Root created");
        Rc::new(RefCell::new(Container {
            handle: None,
            parent: None,
            children: vec!(),
            container_type: ContainerType::Root,
            layout: None,
            visible: false,
            is_focused: false,
            is_floating: false
        }))
    }

    /// Makes a new output. These can only be children of the root node. They
    /// contain information about which monitor (output) its children are being
    /// displayed on.
    pub fn new_output(root: &mut Node, wlc_output: WlcOutput) -> Node {
        if ! root.borrow().is_root() {
            panic!("Output containers can only be children of the root, not {:?}", root.borrow().get_type());
        }

        let size = wlc_output.get_resolution();
        let output = Rc::new(RefCell::new(Container {
            handle: Some(Handle::Output(wlc_output.clone())),
            parent: Some(Rc::downgrade(&root)),
            children: vec!(),
            container_type: ContainerType::Output,
            layout: None,
            visible: false,
            is_focused: false,
            is_floating: false
        }));
        // NOTE Should automatically add a new workspace here, there are edge
        // cases to worry about though so leaving that out for now
        root.borrow_mut().add_child(output.clone());
        output
    }

    /// Makes a new workspace container. These can only be attached to output
    /// containers. They will inherit the output of the parent container.
    pub fn new_workspace(parent_: &mut Node) -> Node {
        let parent = parent_.borrow();
        if parent.get_type() != ContainerType::Output {
            panic!("Workspaces can only be children of an output container, not {:?}", parent.get_type());
        }
        let workspace: Node =
            Rc::new(RefCell::new(Container {
                handle: Some(parent.get_handle().expect("Workspace could not get handle from output parent")),
                parent: Some(Rc::downgrade(&parent_)),
                children: vec!(),
                container_type: ContainerType::Workspace,
                layout: Some(Layout::Horizontal),
                visible: false,
                is_focused: false,
                is_floating: false,
                }));
        drop(parent);
        parent_.borrow_mut().add_child(workspace.clone());
        trace!("Workspace created");
        workspace
    }

    /// Makes a new container. These hold views and other containers.
    /// Container hold information about specific parts of the tree in some
    /// workspace and the layout of the views within.
    pub fn new_container(parent_: &mut Node, mut layout: Layout) -> Node {
        let mut parent = parent_.borrow_mut();
        if ! (parent.get_type() == ContainerType::Container
            || parent.get_type() == ContainerType::Workspace) {
            panic!("Container can only be child of container or workspace, not {:?}", parent.get_type());
        }
        let output = parent.get_handle().expect("Container could not get handle from parent");
        // NOTE Make sure we do all of the Container specific init stuff
        let container = Rc::new(RefCell::new(Container {
            handle: Some(output),
            parent: Some(Rc::downgrade(&parent_)),
            children: vec!(),
            container_type: ContainerType::Container,
            layout: Some(layout),
            visible: false,
            is_focused: false,
            is_floating: false,
        }));
        if parent.get_type() == ContainerType::Workspace {
            let mut workspace = parent;
            if let Some(layout) = workspace.get_layout() {
                container.borrow_mut().set_layout(layout);
            }
            workspace.add_child(container.clone());
        } else {
            // Need to add the "parent" as the child of the container we just made.
            drop(parent);
            let child_ = parent_.clone();
            let child = child_.borrow();
            let parent_of_child = child.get_parent().expect("Parent container has no parent");
            let child_clone = Rc::make_mut(&mut child_.clone()).clone().into_inner();
            // Need to remove the child from their parent
            parent_of_child.borrow_mut().remove_child(&child_clone.clone());
            // Add the container we just made as a child, replacing the one we removed
            parent_of_child.borrow_mut().add_child(container.clone());
            // The new container is now a child of the old child's parent
            container.borrow_mut().add_child(child_.clone());
        }
        trace!("Container created");
        container
    }

    /// Makes a new view. A view holds either a Wayland or an X Wayland window.
    pub fn new_view(parent_: &mut Node, wlc_view: WlcView) -> Node {
        let parent = parent_.borrow();
        if parent.is_root() {
            panic!("View cannot be a direct child of root, not {:?}", parent.get_type());
        }
        let view = Rc::new(RefCell::new(Container {
            handle: Some(Handle::View(wlc_view.clone())),
            parent: Some(Rc::downgrade(&parent_)),
            children: vec!(),
            container_type: ContainerType::View,
            layout: None,
            visible: false,
            is_focused: false,
            is_floating: false
        }));
        if parent.get_type() == ContainerType::Workspace {
            // Case of focused workspace, just create a child of it
            drop(parent);
            let mut parent = parent_.borrow_mut();
            parent.add_child(view.clone());
        } else {
            // Regular case, create as sibling of current container
            parent.add_sibling(view.clone());
        }
        trace!("View created");
        view
    }

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    pub fn get_parent(&self) -> Option<Node> {
        if self.is_root() {
            None
        } else {
            if let Some(parent) = self.parent.clone() {
                parent.upgrade()
            } else {
                None
            }
        }
    }

    pub fn add_child(&mut self, container: Node) -> Result<(), &'static str> {
        if self.get_type() == ContainerType::Workspace
            && container.borrow().get_type() == ContainerType::Workspace {
            return Err("Only containers can be children of a workspace");
        } else if self.get_type() == ContainerType::View {
            return Err("Cannot add child to a view");
        }
        // NOTE check to make sure we are not adding a duplicate
        self.children.push(container);
        Ok(())
    }

    pub fn add_sibling(&self, container: Node) -> Result<(), &'static str> {
        if self.is_root() {
            return Err("Root has no sibling, cannot add sibling to root");
        }
        let parent = self.get_parent().expect("Could not get parent, was removed from tree");
        trace!("Borrowing container {:?} (parent of {:?}) as mutable", parent, self);
        parent.borrow_mut().add_child(container);
        Ok(())
    }

    /// Removes this container and all of its children.
    /// You MUST call this function while `borrow`ing, a mutable borrow will
    /// cause it to panic at run time
    pub fn remove_container(&self) -> Result<(), &'static str> {
        if self.is_root() {
            return Err("Cannot remove root container");
        } else if self.get_type() == ContainerType::Workspace  {
            return Err("Cannot remove workspace container");
        }
        if let Some(parent) = self.get_parent() {
            // NOTE Add check here to ensure we can borrow mutably once that
            // feature stabilizes
            trace!("Borrowing container {:?} (parent of {:?}) as mutable", parent, self);
            parent.borrow_mut().remove_child(self);
        }
        Ok(())
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    pub fn get_children(&self) -> Option<&[Node]> {
        if self.get_type() == ContainerType::View {
            None
        }
        else {
            Some(self.children.as_slice())
        }
    }

    /// Gets the type of the container
    pub fn get_type(&self) -> ContainerType {
        self.container_type
    }

    /// Gets the handle of the container. This could either be an output (a
    /// monitor), or a view (a Wayland or X Wayland Window)
    pub fn get_handle(&self) -> Option<Handle> {
        self.handle.clone()
    }

    /// Gets the layout of the container, if there is one.
    pub fn get_layout(&self) -> Option<Layout> {
        self.layout
    }

    /// Returns true if this container is focused.
    pub fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes the child at the specified index
    pub fn remove_child_at(&mut self, index: usize) -> Result<Node, &'static str> {
        // NOTE Add check here to ensure we can borrow once that
        // feature stabilizes
        if self.children[index].borrow().get_type() == ContainerType::Workspace {
            return Err("Cannot remove workspace")
        }
        Ok(self.children.remove(index))
    }

    /// Removes the given child from this container's children.
    /// If the child is not present, then an error is returned
    pub fn remove_child(&mut self, node: &Container) -> Result<Node, &'static str> {
        for (index, child) in self.children.clone().iter().enumerate() {
            // NOTE Add check here to ensure we can borrow once that
            // feature stabilizes
            if *child.borrow() == *node {
                if child.borrow().get_type() == ContainerType::Workspace {
                    return Err("Can not remove workspace");
                }
                return Ok(self.children.remove(index));
            }
        }
        return Err("Could not find child in container");//format!("Could not find child {:?} in {:?}", node, self));
    }

    /// Sets this container (and everything in it) to given visibility
    pub fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Sets the layout of the container.
    pub fn set_layout(&mut self, layout: Layout) {
        self.layout = Some(layout)
    }

    /// Gets the visibility of the container
    pub fn get_visibility(&self) -> bool {
        self.visible
    }

    /// Gets the X and Y dimensions of the container. Width is the first
    /// value, height is the second.
    pub fn get_dimensions(&self) -> Option<(u32, u32)> {
        if let Some(ref handle) = self.handle {
            match handle {
                &Handle::Output(ref output) => {
                    let size = output.get_resolution();
                    Some((size.w, size.h))
                }
                &Handle::View(ref view) => {
                    let ref size = view.get_geometry().expect("View did not have a geometry").size;
                    Some((size.w, size.h))
                }
            }
        } else {
            None
        }
    }

    /// Gets the position of this container on the screen.
    pub fn get_position(&self) -> Option<(i32, i32)> {
        if let Some(ref handle) = self.handle {
            match handle {
                &Handle::Output(ref output) => None,
                &Handle::View(ref view) => {
                    let ref origin = view.get_geometry().expect("View did not have a geometry").origin;
                    Some((origin.x, origin.y))
                }
            }
        } else {
            None
        }
    }

    /// Returns true if this container is a parent of the child
    pub fn is_parent_of(&self, child: Node) -> bool {
        if self.is_root() {
            true
        } else {
            while ! child.borrow().is_root() {
                let parent = child.borrow().get_parent().expect("Could not get parent, was removed from tree");
                if child == parent {
                    return true
                }
            }
            return false;
        }
    }

    /// Returns true if this container is a child is an decedent of the parent
    pub fn is_child_of(&self, parent: Node) -> bool {
        parent.borrow().is_parent_of(Rc::new(RefCell::new(self.clone())))
    }

    pub fn is_root(&self) -> bool {
        self.get_type() == ContainerType::Root
    }

    /// Finds a parent container with the given type, if there is any
    pub fn get_parent_by_type(&self, container_type: ContainerType) -> Option<Node> {
        let mut container = self.get_parent();
        loop {
            if let Some(parent) = container {
                if parent.borrow().get_type() == container_type {
                    return Some(parent);
                }
                container = parent.borrow().get_parent();
            } else {
                return None;
            }
        }
    }
}

impl PartialEq for Container {
    fn eq(&self, other: &Container) -> bool {
        self.get_type() == other.get_type()
    }
}

impl Eq for Container { }

impl Debug for Container {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        f.debug_struct("Containable")
            .field("type", &self.get_type())
            //.field("parent", &self.get_parent())
            .field("children", &self.get_children())
            .field("focused", &self.is_focused())
            .finish()
    }
}
<commit_msg>Container equality now checks if the handles are the same if the types are also the same (though if the handles are not present, then only the type is check to be the same<commit_after>//! Layout handling

// remove
#![allow(unused)]

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::VIEW_MAXIMIZED;
use std::rc::{Rc, Weak};
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;
use std::cell::RefCell;

pub type Node = Rc<RefCell<Container>>;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Handle {
    View(WlcView),
    Output(WlcOutput)
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A Container, houses views and other containers
    Container,
    /// A view (window)
    View
}

/// Layout mode for a container
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Layout {
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

#[derive(Clone)]
pub struct Container {
    handle: Option<Handle>,
    parent: Option<Weak<RefCell<Container>>>,
    children: Vec<Node>,
    container_type: ContainerType,
    layout: Option<Layout>,
    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

/// Like i3, everything (workspaces, containers, views) are containable.
impl Container {

    /// Makes the root container. There should be only one of these
    /// Does not ensure that this is the only root container
    pub fn new_root() -> Node {
        trace!("Root created");
        Rc::new(RefCell::new(Container {
            handle: None,
            parent: None,
            children: vec!(),
            container_type: ContainerType::Root,
            layout: None,
            visible: false,
            is_focused: false,
            is_floating: false
        }))
    }

    /// Makes a new output. These can only be children of the root node. They
    /// contain information about which monitor (output) its children are being
    /// displayed on.
    pub fn new_output(root: &mut Node, wlc_output: WlcOutput) -> Node {
        if ! root.borrow().is_root() {
            panic!("Output containers can only be children of the root, not {:?}", root.borrow().get_type());
        }

        let size = wlc_output.get_resolution();
        let output = Rc::new(RefCell::new(Container {
            handle: Some(Handle::Output(wlc_output.clone())),
            parent: Some(Rc::downgrade(&root)),
            children: vec!(),
            container_type: ContainerType::Output,
            layout: None,
            visible: false,
            is_focused: false,
            is_floating: false
        }));
        // NOTE Should automatically add a new workspace here, there are edge
        // cases to worry about though so leaving that out for now
        root.borrow_mut().add_child(output.clone());
        output
    }

    /// Makes a new workspace container. These can only be attached to output
    /// containers. They will inherit the output of the parent container.
    pub fn new_workspace(parent_: &mut Node) -> Node {
        let parent = parent_.borrow();
        if parent.get_type() != ContainerType::Output {
            panic!("Workspaces can only be children of an output container, not {:?}", parent.get_type());
        }
        let workspace: Node =
            Rc::new(RefCell::new(Container {
                handle: Some(parent.get_handle().expect("Workspace could not get handle from output parent")),
                parent: Some(Rc::downgrade(&parent_)),
                children: vec!(),
                container_type: ContainerType::Workspace,
                layout: Some(Layout::Horizontal),
                visible: false,
                is_focused: false,
                is_floating: false,
                }));
        drop(parent);
        parent_.borrow_mut().add_child(workspace.clone());
        trace!("Workspace created");
        workspace
    }

    /// Makes a new container. These hold views and other containers.
    /// Container hold information about specific parts of the tree in some
    /// workspace and the layout of the views within.
    pub fn new_container(parent_: &mut Node, mut layout: Layout) -> Node {
        let mut parent = parent_.borrow_mut();
        if ! (parent.get_type() == ContainerType::Container
            || parent.get_type() == ContainerType::Workspace) {
            panic!("Container can only be child of container or workspace, not {:?}", parent.get_type());
        }
        let output = parent.get_handle().expect("Container could not get handle from parent");
        // NOTE Make sure we do all of the Container specific init stuff
        let container = Rc::new(RefCell::new(Container {
            handle: Some(output),
            parent: Some(Rc::downgrade(&parent_)),
            children: vec!(),
            container_type: ContainerType::Container,
            layout: Some(layout),
            visible: false,
            is_focused: false,
            is_floating: false,
        }));
        if parent.get_type() == ContainerType::Workspace {
            let mut workspace = parent;
            if let Some(layout) = workspace.get_layout() {
                container.borrow_mut().set_layout(layout);
            }
            workspace.add_child(container.clone());
        } else {
            // Need to add the "parent" as the child of the container we just made.
            drop(parent);
            let child_ = parent_.clone();
            let child = child_.borrow();
            let parent_of_child = child.get_parent().expect("Parent container has no parent");
            let child_clone = Rc::make_mut(&mut child_.clone()).clone().into_inner();
            // Need to remove the child from their parent
            parent_of_child.borrow_mut().remove_child(&child_clone.clone());
            // Add the container we just made as a child, replacing the one we removed
            parent_of_child.borrow_mut().add_child(container.clone());
            // The new container is now a child of the old child's parent
            container.borrow_mut().add_child(child_.clone());
        }
        trace!("Container created");
        container
    }

    /// Makes a new view. A view holds either a Wayland or an X Wayland window.
    pub fn new_view(parent_: &mut Node, wlc_view: WlcView) -> Node {
        let parent = parent_.borrow();
        if parent.is_root() {
            panic!("View cannot be a direct child of root, not {:?}", parent.get_type());
        }
        let view = Rc::new(RefCell::new(Container {
            handle: Some(Handle::View(wlc_view.clone())),
            parent: Some(Rc::downgrade(&parent_)),
            children: vec!(),
            container_type: ContainerType::View,
            layout: None,
            visible: false,
            is_focused: false,
            is_floating: false
        }));
        if parent.get_type() == ContainerType::Workspace {
            // Case of focused workspace, just create a child of it
            drop(parent);
            let mut parent = parent_.borrow_mut();
            parent.add_child(view.clone());
        } else {
            // Regular case, create as sibling of current container
            parent.add_sibling(view.clone());
        }
        trace!("View created");
        view
    }

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    pub fn get_parent(&self) -> Option<Node> {
        if self.is_root() {
            None
        } else {
            if let Some(parent) = self.parent.clone() {
                parent.upgrade()
            } else {
                None
            }
        }
    }

    pub fn add_child(&mut self, container: Node) -> Result<(), &'static str> {
        if self.get_type() == ContainerType::Workspace
            && container.borrow().get_type() == ContainerType::Workspace {
            return Err("Only containers can be children of a workspace");
        } else if self.get_type() == ContainerType::View {
            return Err("Cannot add child to a view");
        }
        // NOTE check to make sure we are not adding a duplicate
        self.children.push(container);
        Ok(())
    }

    pub fn add_sibling(&self, container: Node) -> Result<(), &'static str> {
        if self.is_root() {
            return Err("Root has no sibling, cannot add sibling to root");
        }
        let parent = self.get_parent().expect("Could not get parent, was removed from tree");
        trace!("Borrowing container {:?} (parent of {:?}) as mutable", parent, self);
        parent.borrow_mut().add_child(container);
        Ok(())
    }

    /// Removes this container and all of its children.
    /// You MUST call this function while `borrow`ing, a mutable borrow will
    /// cause it to panic at run time
    pub fn remove_container(&self) -> Result<(), &'static str> {
        if self.is_root() {
            return Err("Cannot remove root container");
        } else if self.get_type() == ContainerType::Workspace  {
            return Err("Cannot remove workspace container");
        }
        if let Some(parent) = self.get_parent() {
            // NOTE Add check here to ensure we can borrow mutably once that
            // feature stabilizes
            trace!("Borrowing container {:?} (parent of {:?}) as mutable", parent, self);
            parent.borrow_mut().remove_child(self);
        }
        Ok(())
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    pub fn get_children(&self) -> Option<&[Node]> {
        if self.get_type() == ContainerType::View {
            None
        }
        else {
            Some(self.children.as_slice())
        }
    }

    /// Gets the type of the container
    pub fn get_type(&self) -> ContainerType {
        self.container_type
    }

    /// Gets the handle of the container. This could either be an output (a
    /// monitor), or a view (a Wayland or X Wayland Window)
    pub fn get_handle(&self) -> Option<Handle> {
        self.handle.clone()
    }

    /// Gets the layout of the container, if there is one.
    pub fn get_layout(&self) -> Option<Layout> {
        self.layout
    }

    /// Returns true if this container is focused.
    pub fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes the child at the specified index
    pub fn remove_child_at(&mut self, index: usize) -> Result<Node, &'static str> {
        // NOTE Add check here to ensure we can borrow once that
        // feature stabilizes
        if self.children[index].borrow().get_type() == ContainerType::Workspace {
            return Err("Cannot remove workspace")
        }
        Ok(self.children.remove(index))
    }

    /// Removes the given child from this container's children.
    /// If the child is not present, then an error is returned
    pub fn remove_child(&mut self, node: &Container) -> Result<Node, &'static str> {
        for (index, child) in self.children.clone().iter().enumerate() {
            // NOTE Add check here to ensure we can borrow once that
            // feature stabilizes
            if *child.borrow() == *node {
                if child.borrow().get_type() == ContainerType::Workspace {
                    return Err("Can not remove workspace");
                }
                return Ok(self.children.remove(index));
            }
        }
        return Err("Could not find child in container");//format!("Could not find child {:?} in {:?}", node, self));
    }

    /// Sets this container (and everything in it) to given visibility
    pub fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Sets the layout of the container.
    pub fn set_layout(&mut self, layout: Layout) {
        self.layout = Some(layout)
    }

    /// Gets the visibility of the container
    pub fn get_visibility(&self) -> bool {
        self.visible
    }

    /// Gets the X and Y dimensions of the container. Width is the first
    /// value, height is the second.
    pub fn get_dimensions(&self) -> Option<(u32, u32)> {
        if let Some(ref handle) = self.handle {
            match handle {
                &Handle::Output(ref output) => {
                    let size = output.get_resolution();
                    Some((size.w, size.h))
                }
                &Handle::View(ref view) => {
                    let ref size = view.get_geometry().expect("View did not have a geometry").size;
                    Some((size.w, size.h))
                }
            }
        } else {
            None
        }
    }

    /// Gets the position of this container on the screen.
    pub fn get_position(&self) -> Option<(i32, i32)> {
        if let Some(ref handle) = self.handle {
            match handle {
                &Handle::Output(ref output) => None,
                &Handle::View(ref view) => {
                    let ref origin = view.get_geometry().expect("View did not have a geometry").origin;
                    Some((origin.x, origin.y))
                }
            }
        } else {
            None
        }
    }

    /// Returns true if this container is a parent of the child
    pub fn is_parent_of(&self, child: Node) -> bool {
        if self.is_root() {
            true
        } else {
            while ! child.borrow().is_root() {
                let parent = child.borrow().get_parent().expect("Could not get parent, was removed from tree");
                if child == parent {
                    return true
                }
            }
            return false;
        }
    }

    /// Returns true if this container is a child is an decedent of the parent
    pub fn is_child_of(&self, parent: Node) -> bool {
        parent.borrow().is_parent_of(Rc::new(RefCell::new(self.clone())))
    }

    pub fn is_root(&self) -> bool {
        self.get_type() == ContainerType::Root
    }

    /// Finds a parent container with the given type, if there is any
    pub fn get_parent_by_type(&self, container_type: ContainerType) -> Option<Node> {
        let mut container = self.get_parent();
        loop {
            if let Some(parent) = container {
                if parent.borrow().get_type() == container_type {
                    return Some(parent);
                }
                container = parent.borrow().get_parent();
            } else {
                return None;
            }
        }
    }
}

impl PartialEq for Container {
    fn eq(&self, other: &Container) -> bool {
        if self.get_type() == other.get_type() {
            if let Some(self_handle) = self.get_handle() {
                if let Some(other_handle) = other.get_handle() {
                    if self_handle == other_handle {
                        return true
                    }
                }
            } else {
                return true
            }
        }
        return false
    }
}

impl Eq for Container { }

impl Debug for Container {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        f.debug_struct("Containable")
            .field("type", &self.get_type())
            //.field("parent", &self.get_parent())
            .field("children", &self.get_children())
            .field("focused", &self.is_focused())
            .finish()
    }
}
<|endoftext|>


<commit_before>#![stable(feature = "futures_api", since = "1.36.0")]

//! Asynchronous values.

#[cfg(not(bootstrap))]
use crate::{
    ops::{Generator, GeneratorState},
    pin::Pin,
    ptr::NonNull,
    task::{Context, Poll},
};

mod future;
#[stable(feature = "futures_api", since = "1.36.0")]
pub use self::future::Future;

/// This type is needed because:
///
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
///    a raw pointer.
/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
///    non-Send/Sync as well, and we don't want that.
///
/// It also simplifies the HIR lowering of `.await`.
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[derive(Debug, Copy, Clone)]
pub struct ResumeTy(NonNull<Context<'static>>);

#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Send for ResumeTy {}

#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Sync for ResumeTy {}

/// Wrap a generator in a future.
///
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
// This is `const` to avoid extra errors after we recover from `const async fn`
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
where
    T: Generator<ResumeTy, Yield = ()>,
{
    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);

    // We rely on the fact that async/await futures are immovable in order to create
    // self-referential borrows in the underlying generator.
    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}

    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
        type Output = T::Return;
        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
            // Safety: Safe because we're !Unpin + !Drop mapping to a ?Unpin value
            let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };

            // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
            // `.await` lowering will safely cast that back to a `&mut Context`.
            match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
                GeneratorState::Yielded(()) => Poll::Pending,
                GeneratorState::Complete(x) => Poll::Ready(x),
            }
        }
    }

    GenFuture(gen)
}

#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub unsafe fn poll_with_context<F>(f: Pin<&mut F>, mut cx: ResumeTy) -> Poll<F::Output>
where
    F: Future,
{
    F::poll(f, cx.0.as_mut())
}
<commit_msg>Clarify comment<commit_after>#![stable(feature = "futures_api", since = "1.36.0")]

//! Asynchronous values.

#[cfg(not(bootstrap))]
use crate::{
    ops::{Generator, GeneratorState},
    pin::Pin,
    ptr::NonNull,
    task::{Context, Poll},
};

mod future;
#[stable(feature = "futures_api", since = "1.36.0")]
pub use self::future::Future;

/// This type is needed because:
///
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
///    a raw pointer.
/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
///    non-Send/Sync as well, and we don't want that.
///
/// It also simplifies the HIR lowering of `.await`.
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[derive(Debug, Copy, Clone)]
pub struct ResumeTy(NonNull<Context<'static>>);

#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Send for ResumeTy {}

#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
unsafe impl Sync for ResumeTy {}

/// Wrap a generator in a future.
///
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
// This is `const` to avoid extra errors after we recover from `const async fn`
#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
where
    T: Generator<ResumeTy, Yield = ()>,
{
    struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);

    // We rely on the fact that async/await futures are immovable in order to create
    // self-referential borrows in the underlying generator.
    impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}

    impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
        type Output = T::Return;
        fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
            // Safety: Safe because we're !Unpin + !Drop, and this is just a field projection.
            let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };

            // Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
            // `.await` lowering will safely cast that back to a `&mut Context`.
            match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
                GeneratorState::Yielded(()) => Poll::Pending,
                GeneratorState::Complete(x) => Poll::Ready(x),
            }
        }
    }

    GenFuture(gen)
}

#[doc(hidden)]
#[unstable(feature = "gen_future", issue = "50547")]
#[cfg(not(bootstrap))]
#[inline]
pub unsafe fn poll_with_context<F>(f: Pin<&mut F>, mut cx: ResumeTy) -> Poll<F::Output>
where
    F: Future,
{
    F::poll(f, cx.0.as_mut())
}
<|endoftext|>


<commit_before>// ignore-tidy-linelength
// compile-flags: -Z mir-emit-retag -Z mir-opt-level=0 -Z span_free_formats

#![allow(unused)]

struct Test(i32);

impl Test {
    // Make sure we run the pass on a method, not just on bare functions.
    fn foo<'x>(&self, x: &'x mut i32) -> &'x mut i32 { x }
    fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 { x }
}

fn main() {
    let mut x = 0;
    {
        let v = Test(0).foo(&mut x); // just making sure we do not panic when there is a tuple struct ctor
        let w = { v }; // assignment
        let w = w; // reborrow
        // escape-to-raw (mut)
        let _w = w as *mut _;
    }

    // Also test closures
    let c: fn(&i32) -> &i32 = |x: &i32| -> &i32 { let _y = x; x };
    let _w = c(&x);

    // need to call `foo_shr` or it doesn't even get generated
    Test(0).foo_shr(&0);

    // escape-to-raw (shr)
    let _w = _w as *const _;
}

// END RUST SOURCE
// START rustc.{{impl}}-foo.EraseRegions.after.mir
//     bb0: {
//         Retag([fn entry] _1);
//         Retag([fn entry] _2);
//         ...
//         _0 = &mut (*_3);
//         Retag(_0);
//         ...
//         return;
//     }
// END rustc.{{impl}}-foo.EraseRegions.after.mir
// START rustc.{{impl}}-foo_shr.EraseRegions.after.mir
//     bb0: {
//         Retag([fn entry] _1);
//         Retag([fn entry] _2);
//         ...
//         _0 = _2;
//         Retag(_0);
//         ...
//         return;
//     }
// END rustc.{{impl}}-foo_shr.EraseRegions.after.mir
// START rustc.main.EraseRegions.after.mir
// fn main() -> () {
//     ...
//     bb0: {
//         ...
//         _3 = const Test::foo(move _4, move _6) -> bb1;
//     }
//
//     bb1: {
//         Retag(_3);
//         ...
//         _9 = move _3;
//         Retag(_9);
//         _8 = &mut (*_9);
//         Retag(_8);
//         StorageDead(_9);
//         StorageLive(_10);
//         _10 = move _8;
//         Retag(_10);
//         ...
//         _13 = &mut (*_10);
//         Retag(_13);
//         _12 = move _13 as *mut i32 (Misc);
//         Retag([raw] _12);
//         ...
//         _16 = move _17(move _18) -> bb2;
//     }
//
//     bb2: {
//         Retag(_16);
//         ...
//         _20 = const Test::foo_shr(move _21, move _23) -> bb3;
//     }
//
//     bb3: {
//         ...
//         return;
//     }
//
//     ...
// }
// END rustc.main.EraseRegions.after.mir
// START rustc.main-{{closure}}.EraseRegions.after.mir
// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(20), local_id: 72 }], _2: &i32) -> &i32 {
//     ...
//     bb0: {
//         Retag([fn entry] _1);
//         Retag([fn entry] _2);
//         StorageLive(_3);
//         _3 = _2;
//         Retag(_3);
//         _0 = _2;
//         Retag(_0);
//         StorageDead(_3);
//         return;
//     }
// }
// END rustc.main-{{closure}}.EraseRegions.after.mir
<commit_msg>test Retag in drop shim<commit_after>// ignore-tidy-linelength
// compile-flags: -Z mir-emit-retag -Z mir-opt-level=0 -Z span_free_formats

#![allow(unused)]

struct Test(i32);

impl Test {
    // Make sure we run the pass on a method, not just on bare functions.
    fn foo<'x>(&self, x: &'x mut i32) -> &'x mut i32 { x }
    fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 { x }
}

impl Drop for Test {
    fn drop(&mut self) {}
}

fn main() {
    let mut x = 0;
    {
        let v = Test(0).foo(&mut x); // just making sure we do not panic when there is a tuple struct ctor
        let w = { v }; // assignment
        let w = w; // reborrow
        // escape-to-raw (mut)
        let _w = w as *mut _;
    }

    // Also test closures
    let c: fn(&i32) -> &i32 = |x: &i32| -> &i32 { let _y = x; x };
    let _w = c(&x);

    // need to call `foo_shr` or it doesn't even get generated
    Test(0).foo_shr(&0);

    // escape-to-raw (shr)
    let _w = _w as *const _;
}

// END RUST SOURCE
// START rustc.{{impl}}-foo.EraseRegions.after.mir
//     bb0: {
//         Retag([fn entry] _1);
//         Retag([fn entry] _2);
//         ...
//         _0 = &mut (*_3);
//         Retag(_0);
//         ...
//         return;
//     }
// END rustc.{{impl}}-foo.EraseRegions.after.mir
// START rustc.{{impl}}-foo_shr.EraseRegions.after.mir
//     bb0: {
//         Retag([fn entry] _1);
//         Retag([fn entry] _2);
//         ...
//         _0 = _2;
//         Retag(_0);
//         ...
//         return;
//     }
// END rustc.{{impl}}-foo_shr.EraseRegions.after.mir
// START rustc.main.EraseRegions.after.mir
// fn main() -> () {
//     ...
//     bb0: {
//         ...
//         _3 = const Test::foo(move _4, move _6) -> [return: bb2, unwind: bb3];
//     }
//
//     ...
//
//     bb2: {
//         Retag(_3);
//         ...
//         _9 = move _3;
//         Retag(_9);
//         _8 = &mut (*_9);
//         Retag(_8);
//         StorageDead(_9);
//         StorageLive(_10);
//         _10 = move _8;
//         Retag(_10);
//         ...
//         _13 = &mut (*_10);
//         Retag(_13);
//         _12 = move _13 as *mut i32 (Misc);
//         Retag([raw] _12);
//         ...
//         _16 = move _17(move _18) -> bb5;
//     }
//
//     bb5: {
//         Retag(_16);
//         ...
//         _20 = const Test::foo_shr(move _21, move _23) -> [return: bb6, unwind: bb7];
//     }
//
//     ...
// }
// END rustc.main.EraseRegions.after.mir
// START rustc.main-{{closure}}.EraseRegions.after.mir
// fn main::{{closure}}#0(_1: &[closure@HirId { owner: DefIndex(22), local_id: 72 }], _2: &i32) -> &i32 {
//     ...
//     bb0: {
//         Retag([fn entry] _1);
//         Retag([fn entry] _2);
//         StorageLive(_3);
//         _3 = _2;
//         Retag(_3);
//         _0 = _2;
//         Retag(_0);
//         StorageDead(_3);
//         return;
//     }
// }
// END rustc.main-{{closure}}.EraseRegions.after.mir
// START rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir
// fn  std::ptr::real_drop_in_place(_1: &mut Test) -> () {
//     ...
//     bb0: {
//         Retag([raw] _1);
//         _2 = &mut (*_1);
//         _3 = const <Test as std::ops::Drop>::drop(move _2) -> bb1;
//     }
//
//     bb1: {
//         return;
//     }
// }
// END rustc.ptr-real_drop_in_place.Test.SimplifyCfg-make_shim.after.mir
<|endoftext|>


<commit_before>use std::vec::Vec;

use hyper::Client;
use hyper::header::Connection;

use std::io::Read;
use std::default::Default;

use tendril::StrTendril;

use html5ever::tokenizer::{Tokenizer, TokenizerOpts};

pub fn get_rows(url: &str) -> Vec<String> {
    let mut tok = Tokenizer::new(collector::RowCollector::new(), TokenizerOpts {
        .. Default::default()
    });
    tok.feed(get_html(url));
    tok.end();
    tok.unwrap().rows
}

fn get_html(url: &str) -> StrTendril {
    let mut res = Client::new().get(url)
        .header(Connection::close()).send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    let input = StrTendril::try_from_byte_slice(body.as_bytes()).unwrap();
    input.try_reinterpret().unwrap()
}

mod collector {
    use std::vec::Vec;
    use std::str::FromStr;

    use html5ever::tokenizer::{TokenSink, Token, Tag};
    use html5ever::tokenizer::{TagToken, StartTag, EndTag};

    static TARGET_TAG: &'static str = "p";
    static TARGET_ATTR: &'static str = "data-pid";

    pub struct RowCollector {
        pub rows: Vec<String>
    }

    impl RowCollector {
        pub fn new() -> Self {
            RowCollector {
                rows: Vec::new(),
            }
        }

        fn get_url(&self, tag: Tag) -> Option<String> {
            if match tag.kind {
                StartTag => true,
                EndTag => false
            } && tag.name.as_ref() == TARGET_TAG {
                for attr in tag.attrs.iter() {
                    if attr.name.local.as_ref() == TARGET_ATTR {
                        return Some(String::from_str(attr.value.as_ref()).unwrap());
                    }
                }
            }

            return None;
        }

        fn is_tag_token(&self, token: &Token) -> bool {
            match *token {
                TagToken(_) => true,
                _ => false
            }
        }

        fn get_tag_token(&self, token: Token) -> Tag {
            match token {
                TagToken(tag) => tag,
                _ => panic!()
            }
        }
    }

    impl TokenSink for RowCollector {
        fn process_token(&mut self, token: Token) {
            if self.is_tag_token(&token) {
                let url = self.get_url(self.get_tag_token(token));
                if url.is_some() {
                    self.rows.push(url.unwrap());
                }
            }
        }
    }
}
<commit_msg>style change<commit_after>use std::vec::Vec;
use std::io::Read;
use std::default::Default;

use hyper::Client;
use hyper::header::Connection;

use tendril::StrTendril;

use html5ever::tokenizer::{Tokenizer, TokenizerOpts};

pub fn get_rows(url: &str) -> Vec<String> {
    let mut tok = Tokenizer::new(collector::RowCollector::new(), TokenizerOpts {
        .. Default::default()
    });
    tok.feed(get_html(url));
    tok.end();
    tok.unwrap().rows
}

fn get_html(url: &str) -> StrTendril {
    let mut res = Client::new().get(url)
        .header(Connection::close()).send().unwrap();
    let mut body = String::new();
    res.read_to_string(&mut body).unwrap();
    let input = StrTendril::try_from_byte_slice(body.as_bytes()).unwrap();
    input.try_reinterpret().unwrap()
}

mod collector {
    use std::vec::Vec;
    use std::str::FromStr;

    use html5ever::tokenizer::{TokenSink, Token, Tag};
    use html5ever::tokenizer::{TagToken, StartTag, EndTag};

    static TARGET_TAG: &'static str = "p";
    static TARGET_ATTR: &'static str = "data-pid";

    pub struct RowCollector {
        pub rows: Vec<String>
    }

    impl RowCollector {
        pub fn new() -> Self {
            RowCollector {
                rows: Vec::new(),
            }
        }

        fn get_url(&self, tag: Tag) -> Option<String> {
            if match tag.kind {
                StartTag => true,
                EndTag => false
            } && tag.name.as_ref() == TARGET_TAG {
                for attr in tag.attrs.iter() {
                    if attr.name.local.as_ref() == TARGET_ATTR {
                        return Some(String::from_str(attr.value.as_ref()).unwrap());
                    }
                }
            }

            return None;
        }

        fn is_tag_token(&self, token: &Token) -> bool {
            match *token {
                TagToken(_) => true,
                _ => false
            }
        }

        fn get_tag_token(&self, token: Token) -> Tag {
            match token {
                TagToken(tag) => tag,
                _ => panic!()
            }
        }
    }

    impl TokenSink for RowCollector {
        fn process_token(&mut self, token: Token) {
            if self.is_tag_token(&token) {
                let url = self.get_url(self.get_tag_token(token));
                if url.is_some() {
                    self.rows.push(url.unwrap());
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::hash_map::Entry;

pub struct SimpleWordModel(HashMap<String, u32>);
pub struct Prediction {
    word: String,
    score: u32,
}

impl SimpleWordModel {
    pub fn from_str(input: &str) -> SimpleWordModel {
        let model_hm: HashMap<String, u32> = HashMap::new();
        let mut model = SimpleWordModel(model_hm);
        let v_input = input.split(' ').collect();
        count_words(&mut model, &v_input);

        model
    }

    pub fn from_vec(input: &Vec<&str>) -> SimpleWordModel {
        let model_hm: HashMap<String, u32> = HashMap::new();
        let mut model = SimpleWordModel(model_hm);

        count_words(&mut model, input);

        model
    }

    pub fn new() -> SimpleWordModel {
        let model_hm: HashMap<String, u32> = HashMap::new();

        SimpleWordModel(model_hm)
    }

    pub fn train_str(&mut self, input: &str) {
        let v_input = input.split(' ').collect();
        count_words(self, &v_input);
    }

    pub fn suggest(&self, letters: &str) -> Vec<Prediction> {
        let mut predictions: Vec<Prediction> = Vec::new();
        let &SimpleWordModel(ref model_hm) = self;

        for (key, value) in model_hm {
            if key.starts_with(letters) {
                predictions.push(Prediction {word: key.clone(), score: *value});
            }
        }

        predictions
    }
}

fn count_words(model: &mut SimpleWordModel, input: &Vec<&str>) {
    let &mut SimpleWordModel(ref mut model_hm) = model;
    for word in input {
        let string_word = String::from_str(*word);
        let entry = model_hm.entry(string_word);
        match entry {
            Entry::Vacant(vacant_entry) => {
                vacant_entry.insert(1);
            },
            Entry::Occupied(mut occ_entry) => {
                let c = occ_entry.get_mut();
                *c += 1;
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use models::SimpleWordModel;

    #[test]
    fn test_from_str() {
        let model = SimpleWordModel::from_str("world domination is my profession hello hello");

        let SimpleWordModel(hash_map) = model;

        assert_eq!(1, *hash_map.get("world").unwrap());
        assert_eq!(2, *hash_map.get("hello").unwrap());
    }

    #[test]
    fn test_from_vec() {
        let model = SimpleWordModel::from_vec(&vec!["rabbit", "rabbit", "hare"]);

        let SimpleWordModel(hash_map) = model;

        assert_eq!(1, *hash_map.get("hare").unwrap());
        assert_eq!(2, *hash_map.get("rabbit").unwrap());
    }

    #[test]
    fn test_train() {
        let mut model = SimpleWordModel::new();

        model.train_str("hello hello hello there there");

        let SimpleWordModel(hash_map) = model;
        assert_eq!(3, *hash_map.get("hello").unwrap());
        assert_eq!(2, *hash_map.get("there").unwrap());
    }

}
<commit_msg>Added predictor.<commit_after>use std::cmp::{Ord,PartialOrd,Ordering};
use std::collections::HashMap;
use std::collections::hash_map::Entry;

// SimpleWordModel uses a HashMap representation to train on word
// frequency. It is fast for looking up words and incrementing their
// count but since HashMap does not keep track of order, searching the
// keys of a hashmap takes a long time. After the model is trained it
// must be converted to a SimpleWordPredictor which stores the words
// in lexical order and has an index of first letters.

#[derive(Debug)]
pub struct SimpleWordModel(HashMap<String, u32>);

#[derive(Debug)]
pub struct SimpleWordPredictor {
    entries: Vec<SimpleWordEntry>,
    ixs: HashMap<char, u32>,

}
#[derive(Debug)]
pub struct SimpleWordEntry {
    word: String,
    score: u32,
}

impl Eq for SimpleWordEntry { }

impl PartialEq for SimpleWordEntry {
    fn eq(&self, other: &Self) -> bool {
        self.word.eq(&other.word)
    }
}

impl PartialOrd for SimpleWordEntry {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.word.partial_cmp(&other.word)
    }
}

impl Ord for SimpleWordEntry {
    fn cmp(&self, other: &Self) -> Ordering {
        self.word.cmp(&other.word)
    }
}

impl SimpleWordModel {
    pub fn from_str(input: &str) -> SimpleWordModel {
        let model_hm: HashMap<String, u32> = HashMap::new();
        let mut model = SimpleWordModel(model_hm);
        let v_input = input.split(' ').collect();
        count_words(&mut model, &v_input);

        model
    }

    pub fn from_vec(input: &Vec<&str>) -> SimpleWordModel {
        let model_hm: HashMap<String, u32> = HashMap::new();
        let mut model = SimpleWordModel(model_hm);

        count_words(&mut model, input);

        model
    }

    pub fn new() -> SimpleWordModel {
        let model_hm: HashMap<String, u32> = HashMap::new();

        SimpleWordModel(model_hm)
    }

    pub fn train_str(&mut self, input: &str) {
        let v_input = input.split(' ').collect();
        count_words(self, &v_input);
    }

    pub fn train_vec(&mut self, input: Vec<&str>) {
        count_words(self, &input);
    }

    pub fn finalize(self) -> SimpleWordPredictor {
        let SimpleWordModel(hm) = self;
        let size = hm.len();
        let mut entries = Vec::with_capacity(size);

        for (key, value) in hm {
            entries.push(SimpleWordEntry {word: key, score: value});
        }

        entries.sort();

        let ixs = generate_ixs(&entries);
        println!("{:?}", entries);
        println!("{:?}", ixs);
        SimpleWordPredictor {entries: entries, ixs: ixs}
    }
}

fn generate_ixs(entries: &Vec<SimpleWordEntry>) -> HashMap<char, u32>{
    let mut ixs: HashMap<char, u32> = HashMap::new();

    // There will be no newlines in the input. This is a placeholder
    // until the first time the loop runs.
    let mut last_c = '\n';
    let mut ix = 0;

    for entry in entries {
        let c = entry.word.char_at(0);
        if c != last_c {
            ixs.insert(c, ix);
            last_c = c;
        }
        ix += 1;
    }

    ixs
}

fn count_words(model: &mut SimpleWordModel, input: &Vec<&str>) {
    let &mut SimpleWordModel(ref mut model_hm) = model;
    for word in input {
        let string_word = String::from_str(*word);
        let entry = model_hm.entry(string_word);
        match entry {
            Entry::Vacant(vacant_entry) => {
                vacant_entry.insert(1);
            },
            Entry::Occupied(mut occ_entry) => {
                let c = occ_entry.get_mut();
                *c += 1;
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use models::SimpleWordModel;

    #[test]
    fn test_from_str() {
        let model = SimpleWordModel::from_str("world domination is my profession hello hello");

        let SimpleWordModel(hash_map) = model;

        assert_eq!(1, *hash_map.get("world").unwrap());
        assert_eq!(2, *hash_map.get("hello").unwrap());
    }

    #[test]
    fn test_from_vec() {
        let model = SimpleWordModel::from_vec(&vec!["rabbit", "rabbit", "hare"]);

        let SimpleWordModel(hash_map) = model;

        assert_eq!(1, *hash_map.get("hare").unwrap());
        assert_eq!(2, *hash_map.get("rabbit").unwrap());
    }

    #[test]
    fn test_train_str() {
        let mut model = SimpleWordModel::new();

        model.train_str("hello hello hello there there");

        let SimpleWordModel(hash_map) = model;
        assert_eq!(3, *hash_map.get("hello").unwrap());
        assert_eq!(2, *hash_map.get("there").unwrap());
    }

    #[test]
    fn test_train_vec() {
        let mut model = SimpleWordModel::new();

        model.train_vec(vec!["hello", "hello", "hello", "what",
                             "is", "this"]);

        let SimpleWordModel(hash_map) = model;
        assert_eq!(3, *hash_map.get("hello").unwrap());
        assert_eq!(1, *hash_map.get("what").unwrap());
    }

    #[test]
    fn test_finalize() {
        let mut model = SimpleWordModel::new();

        model.train_str(concat!["anybody can become angry that is easy but to be ",
                                "angry with the right person and to the right degree ",
                                "and at the right time and for the right purpose ",
                                "and in the right way that is not within everybody's ",
                                "power and is not easy"]);

        let predictor = model.finalize();

        assert_eq!(predictor.entries[0].word, "and");
        assert_eq!(predictor.entries[0].score, 5);
    }

}
<|endoftext|>


<commit_before>use runtime::Runtime;
use error::ImagErrorBase;

pub struct ModuleError {
    base: ImagErrorBase,
    module_name: String,
}

impl ModuleError {

    pub fn short<T: Module>(module : &T, short : String) -> ModuleError {
        ModuleError::new(module, short, "".to_string())
    }

    pub fn new<T: Module>(module : &T, short : String, long : String) -> ModuleError {
        ModuleError {
            base: ImagErrorBase {
                shortdesc: short,
                longdesc: long,
            },
            module_name: module.name(),
        }
    }

}

pub trait Module {

    fn new() -> Self;
    fn load(&self, &rt : Runtime) -> Self;
    fn name(&self) -> String;

    fn execute(&self, &rt : Runtime) -> Option<ModuleError>;

}
<commit_msg>Add: impl ImagError for ModuleError<commit_after>use runtime::Runtime;
use error::ImagError;
use error::ImagErrorBase;

pub struct ModuleError {
    base: ImagErrorBase,
    module_name: String,
}

impl ModuleError {

    pub fn short<T: Module>(module : &T, short : String) -> ModuleError {
        ModuleError::new(module, short, "".to_string())
    }

    pub fn new<T: Module>(module : &T, short : String, long : String) -> ModuleError {
        ModuleError {
            base: ImagErrorBase {
                shortdesc: short,
                longdesc: long,
            },
            module_name: module.name(),
        }
    }

}

impl<'a> ImagError<'a> for ModuleError {
    fn print(&self, rt: &Runtime) {
        if self.base.longdesc.is_empty() {
            let s = format!("{}: {}\n\n{}\n\n",
                            self.module_name,
                            self.base.shortdesc,
                            self.base.longdesc);
            rt.print(&s)
        } else {
            let s = format!("{}: {}\n",
                            self.module_name,
                            self.base.shortdesc);
            rt.print(&s)
        }
    }

    fn print_short(&self, rt : &Runtime) {
        let s = format!("{}: {}\n", self.module_name, self.base.shortdesc);
        rt.print(&s)
    }

    fn print_long(&self, rt : &Runtime) {
        let s = format!("{}: {}\n\n{}\n\n",
                        self.module_name,
                        self.base.shortdesc,
                        self.base.longdesc);
        rt.print(&s)
    }
}

pub trait Module {

    fn new() -> Self;
    fn load(&self, &rt : Runtime) -> Self;
    fn name(&self) -> String;

    fn execute(&self, &rt : Runtime) -> Option<ModuleError>;

}
<|endoftext|>


<commit_before>pub const SYS_DEBUG: usize = 0;

// Linux compatible
pub const SYS_BRK: usize = 45;
pub const SYS_CHDIR: usize = 12;
pub const SYS_CLOSE: usize = 6;
pub const SYS_CLONE: usize = 120;
pub const CLONE_VM: usize = 0x100;
pub const CLONE_FS: usize = 0x200;
pub const CLONE_FILES: usize = 0x400;
pub const SYS_CLOCK_GETTIME: usize = 265;
pub const CLOCK_REALTIME: usize = 0;
pub const CLOCK_MONOTONIC: usize = 1;
pub const SYS_DUP: usize = 41;
pub const SYS_EXECVE: usize = 11;
pub const SYS_EXIT: usize = 1;
pub const SYS_FPATH: usize = 3001;
pub const SYS_FSTAT: usize = 28;
pub const SYS_FSYNC: usize = 118;
pub const SYS_FTRUNCATE: usize = 93;
pub const SYS_LINK: usize = 9;
pub const SYS_LSEEK: usize = 19;
pub const SEEK_SET: usize = 0;
pub const SEEK_CUR: usize = 1;
pub const SEEK_END: usize = 2;
pub const SYS_NANOSLEEP: usize = 162;
pub const SYS_OPEN: usize = 5;
pub const O_RDONLY: usize = 0;
pub const O_WRONLY: usize = 1;
pub const O_RDWR: usize = 2;
pub const O_NONBLOCK: usize = 4;
pub const O_APPEND: usize = 8;
pub const O_SHLOCK: usize = 0x10;
pub const O_EXLOCK: usize = 0x20;
pub const O_ASYNC: usize = 0x40;
pub const O_FSYNC: usize = 0x80;
pub const O_CREAT: usize = 0x200;
pub const O_TRUNC: usize = 0x400;
pub const O_EXCL: usize = 0x800;
pub const SYS_READ: usize = 3;
pub const SYS_UNLINK: usize = 10;
pub const SYS_WRITE: usize = 4;
pub const SYS_YIELD: usize = 158;

// Rust Memory
pub const SYS_ALLOC: usize = 1000;
pub const SYS_REALLOC: usize = 1001;
pub const SYS_REALLOC_INPLACE: usize = 1002;
pub const SYS_UNALLOC: usize = 1003;

// Structures

#[repr(packed)]
pub struct TimeSpec {
    pub tv_sec: i64,
    pub tv_nsec: i32,
}
<commit_msg>Added SYS_MKDIR const<commit_after>pub const SYS_DEBUG: usize = 0;

// Linux compatible
pub const SYS_BRK: usize = 45;
pub const SYS_CHDIR: usize = 12;
pub const SYS_CLOSE: usize = 6;
pub const SYS_CLONE: usize = 120;
pub const CLONE_VM: usize = 0x100;
pub const CLONE_FS: usize = 0x200;
pub const CLONE_FILES: usize = 0x400;
pub const SYS_CLOCK_GETTIME: usize = 265;
pub const CLOCK_REALTIME: usize = 0;
pub const CLOCK_MONOTONIC: usize = 1;
pub const SYS_DUP: usize = 41;
pub const SYS_EXECVE: usize = 11;
pub const SYS_EXIT: usize = 1;
pub const SYS_FPATH: usize = 3001;
pub const SYS_FSTAT: usize = 28;
pub const SYS_FSYNC: usize = 118;
pub const SYS_FTRUNCATE: usize = 93;
pub const SYS_LINK: usize = 9;
pub const SYS_LSEEK: usize = 19;
pub const SEEK_SET: usize = 0;
pub const SEEK_CUR: usize = 1;
pub const SEEK_END: usize = 2;
pub const SYS_MKDIR: usize = 39;
pub const SYS_NANOSLEEP: usize = 162;
pub const SYS_OPEN: usize = 5;
pub const O_RDONLY: usize = 0;
pub const O_WRONLY: usize = 1;
pub const O_RDWR: usize = 2;
pub const O_NONBLOCK: usize = 4;
pub const O_APPEND: usize = 8;
pub const O_SHLOCK: usize = 0x10;
pub const O_EXLOCK: usize = 0x20;
pub const O_ASYNC: usize = 0x40;
pub const O_FSYNC: usize = 0x80;
pub const O_CREAT: usize = 0x200;
pub const O_TRUNC: usize = 0x400;
pub const O_EXCL: usize = 0x800;
pub const SYS_READ: usize = 3;
pub const SYS_UNLINK: usize = 10;
pub const SYS_WRITE: usize = 4;
pub const SYS_YIELD: usize = 158;

// Rust Memory
pub const SYS_ALLOC: usize = 1000;
pub const SYS_REALLOC: usize = 1001;
pub const SYS_REALLOC_INPLACE: usize = 1002;
pub const SYS_UNALLOC: usize = 1003;

// Structures

#[repr(packed)]
pub struct TimeSpec {
    pub tv_sec: i64,
    pub tv_nsec: i32,
}
<|endoftext|>


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

use std::{self, str};

use util::xeval::EvalContext;
use super::Result;

/// `bytes_to_int_without_context` converts a byte arrays to an i64
/// in best effort, but without context.
/// TODO: handle overflow.
pub fn bytes_to_int_without_context(bytes: &[u8]) -> Result<i64> {
    // trim
    let mut trimed = bytes.iter().skip_while(|&&b| b == b' ' || b == b'\t');
    let mut negative = false;
    let mut r = 0i64;
    if let Some(&c) = trimed.next() {
        if c == b'-' {
            negative = true;
        } else if c >= b'0' && c <= b'9' {
            r = c as i64 - b'0' as i64;
        } else if c != b'+' {
            return Ok(0);
        }

        r = trimed.take_while(|&&c| c >= b'0' && c <= b'9')
            .fold(r, |l, &r| l * 10 + (r - b'0') as i64);
        if negative {
            r = -r;
        }
    }
    Ok(r)
}

/// `bytes_to_int` converts a byte arrays to an i64 in best effort.
/// TODO: handle overflow.
pub fn bytes_to_int(ctx: &EvalContext, bytes: &[u8]) -> Result<i64> {
    let s = try!(str::from_utf8(bytes)).trim();
    let vs = get_valid_int_prefix(s);
    try!(handle_truncate(ctx, s.len() > vs.len()));

    bytes_to_int_without_context(vs.as_bytes())
}

fn bytes_to_f64_without_context(bytes: &[u8]) -> Result<f64> {
    let f = match std::str::from_utf8(bytes) {
        Ok(s) => {
            match s.trim().parse::<f64>() {
                Ok(f) => f,
                Err(e) => {
                    error!("failed to parse float from {}: {}", s, e);
                    0.0
                }
            }
        }
        Err(e) => {
            error!("failed to convert bytes to str: {:?}", e);
            0.0
        }
    };
    Ok(f)
}

/// `bytes_to_f64` converts a byte array to a float64 in best effort.
pub fn bytes_to_f64(ctx: &EvalContext, bytes: &[u8]) -> Result<f64> {
    let s = try!(str::from_utf8(bytes)).trim();
    let vs = get_valid_float_prefix(s);
    try!(handle_truncate(ctx, s.len() > vs.len()));

    bytes_to_f64_without_context(vs.as_bytes())
}

#[inline]
fn handle_truncate(ctx: &EvalContext, is_truncated: bool) -> Result<()> {
    if is_truncated && !(ctx.ignore_truncate || ctx.truncate_as_warning) {
        Err(box_err!("[1265] Data Truncated"))
    } else {
        Ok(())
    }
}

// TODO: port `floatStrToIntStr`.
fn get_valid_int_prefix(s: &str) -> &str {
    get_valid_float_prefix(s)
}

fn get_valid_float_prefix(s: &str) -> &str {
    let mut saw_dot = false;
    let mut saw_digit = false;
    let mut valid_len = 0;
    let mut e_idx = 0;
    for (i, c) in s.chars().enumerate() {
        if c == '+' || c == '-' {
            if i != 0 && i != e_idx + 1 {
                // "1e+1" is valid.
                break;
            }
        } else if c == '.' {
            if saw_dot || e_idx > 0 {
                // "1.1." or "1e1.1"
                break;
            }
            saw_dot = true;
            if saw_digit {
                // "123." is valid.
                valid_len = i + 1;
            }
        } else if c == 'e' || c == 'E' {
            if !saw_digit {
                // "+.e"
                break;
            }
            if e_idx != 0 {
                // "1e5e"
                break;
            }
            e_idx = i
        } else if c < '0' || c > '9' {
            break;
        } else {
            saw_digit = true;
            valid_len = i + 1;
        }
    }

    if valid_len == 0 { "0" } else { &s[..valid_len] }
}

#[cfg(test)]
mod test {
    use std::f64::EPSILON;
    use chrono::FixedOffset;
    use util::xeval::EvalContext;

    #[test]
    fn test_bytes_to_i64() {
        let tests: Vec<(&'static [u8], i64)> = vec![
            (b"0", 0),
            (b" 23a", 23),
            (b"\t 23a", 23),
            (b"\r23a", 0),
            (b"1", 1),
            (b"2.1", 2),
            (b"23e10", 23),
            (b"ab", 0),
            (b"4a", 4),
            (b"+1024", 1024),
            (b"-231", -231),
            (b"", 0),
        ];

        for (bs, n) in tests {
            let t = super::bytes_to_int_without_context(bs).unwrap();
            if t != n {
                panic!("expect convert {:?} to {}, but got {}", bs, n, t);
            }
        }
    }

    #[test]
    fn test_bytes_to_f64() {
        let tests: Vec<(&'static [u8], f64)> = vec![
            (b"", 0.0),
            (b" 23", 23.0),
            (b"-1", -1.0),
            (b"1.11", 1.11),
            (b"1.11.00", 0.0),
            (b"xx", 0.0),
            (b"0x00", 0.0),
            (b"11.xx", 0.0),
            (b"xx.11", 0.0),
        ];

        for (v, f) in tests {
            let ff = super::bytes_to_f64_without_context(v).unwrap();
            if (ff - f).abs() > EPSILON {
                panic!("{:?} should be decode to {}, but got {}", v, f, ff);
            }
        }
    }

    #[test]
    fn test_handle_truncate() {
        let ctxs = vec![EvalContext {
                            tz: FixedOffset::east(0),
                            ignore_truncate: true,
                            truncate_as_warning: true,
                        },
                        EvalContext {
                            tz: FixedOffset::east(0),
                            ignore_truncate: true,
                            truncate_as_warning: false,
                        },
                        EvalContext {
                            tz: FixedOffset::east(0),
                            ignore_truncate: false,
                            truncate_as_warning: true,
                        },
                        EvalContext {
                            tz: FixedOffset::east(0),
                            ignore_truncate: false,
                            truncate_as_warning: false,
                        }];

        for ctx in &ctxs {
            assert!(super::handle_truncate(ctx, false).is_ok());
        }

        assert!(super::handle_truncate(&ctxs[0], true).is_ok());
        assert!(super::handle_truncate(&ctxs[1], true).is_ok());
        assert!(super::handle_truncate(&ctxs[2], true).is_ok());
        assert!(super::handle_truncate(&ctxs[3], true).is_err());
    }

    #[test]
    fn test_get_valid_float_prefix() {
        let cases = vec![("-100", "-100"),
                         ("1abc", "1"),
                         ("-1-1", "-1"),
                         ("+1+1", "+1"),
                         ("123..34", "123."),
                         ("123.23E-10", "123.23E-10"),
                         ("1.1e1.3", "1.1e1"),
                         ("11e1.3", "11e1"),
                         ("1.1e-13a", "1.1e-13"),
                         ("1.", "1."),
                         (".1", ".1"),
                         ("", "0"),
                         ("123e+", "123"),
                         ("123.e", "123.")];

        for (i, o) in cases {
            assert_eq!(super::get_valid_float_prefix(i), o);
        }
    }
}
<commit_msg>util/codec: keep large integer precision and roughly check overflow (#1437)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{self, str, i64};
use std::borrow::Cow;

use util::xeval::EvalContext;
use super::Result;

/// `bytes_to_int_without_context` converts a byte arrays to an i64
/// in best effort, but without context.
/// Note that it does NOT handle overflow.
pub fn bytes_to_int_without_context(bytes: &[u8]) -> Result<i64> {
    // trim
    let mut trimed = bytes.iter().skip_while(|&&b| b == b' ' || b == b'\t');
    let mut negative = false;
    let mut r = 0i64;
    if let Some(&c) = trimed.next() {
        if c == b'-' {
            negative = true;
        } else if c >= b'0' && c <= b'9' {
            r = c as i64 - b'0' as i64;
        } else if c != b'+' {
            return Ok(0);
        }

        r = trimed.take_while(|&&c| c >= b'0' && c <= b'9')
            .fold(r, |l, &r| l * 10 + (r - b'0') as i64);
        if negative {
            r = -r;
        }
    }
    Ok(r)
}

/// `bytes_to_int` converts a byte arrays to an i64 in best effort.
/// TODO: handle overflow properly.
pub fn bytes_to_int(ctx: &EvalContext, bytes: &[u8]) -> Result<i64> {
    let s = try!(str::from_utf8(bytes)).trim();
    let vs = try!(get_valid_int_prefix(ctx, s));

    bytes_to_int_without_context(vs.as_bytes())
}

fn bytes_to_f64_without_context(bytes: &[u8]) -> Result<f64> {
    let f = match std::str::from_utf8(bytes) {
        Ok(s) => {
            match s.trim().parse::<f64>() {
                Ok(f) => f,
                Err(e) => {
                    error!("failed to parse float from {}: {}", s, e);
                    0.0
                }
            }
        }
        Err(e) => {
            error!("failed to convert bytes to str: {:?}", e);
            0.0
        }
    };
    Ok(f)
}

/// `bytes_to_f64` converts a byte array to a float64 in best effort.
pub fn bytes_to_f64(ctx: &EvalContext, bytes: &[u8]) -> Result<f64> {
    let s = try!(str::from_utf8(bytes)).trim();
    let vs = try!(get_valid_float_prefix(ctx, s));

    bytes_to_f64_without_context(vs.as_bytes())
}

#[inline]
fn handle_truncate(ctx: &EvalContext, is_truncated: bool) -> Result<()> {
    if is_truncated && !(ctx.ignore_truncate || ctx.truncate_as_warning) {
        Err(box_err!("[1265] Data Truncated"))
    } else {
        Ok(())
    }
}

fn get_valid_int_prefix<'a>(ctx: &EvalContext, s: &'a str) -> Result<Cow<'a, str>> {
    let vs = try!(get_valid_float_prefix(ctx, s));
    float_str_to_int_string(vs)
}

fn get_valid_float_prefix<'a>(ctx: &EvalContext, s: &'a str) -> Result<&'a str> {
    let mut saw_dot = false;
    let mut saw_digit = false;
    let mut valid_len = 0;
    let mut e_idx = 0;
    for (i, c) in s.chars().enumerate() {
        if c == '+' || c == '-' {
            if i != 0 && i != e_idx + 1 {
                // "1e+1" is valid.
                break;
            }
        } else if c == '.' {
            if saw_dot || e_idx > 0 {
                // "1.1." or "1e1.1"
                break;
            }
            saw_dot = true;
            if saw_digit {
                // "123." is valid.
                valid_len = i + 1;
            }
        } else if c == 'e' || c == 'E' {
            if !saw_digit {
                // "+.e"
                break;
            }
            if e_idx != 0 {
                // "1e5e"
                break;
            }
            e_idx = i
        } else if c < '0' || c > '9' {
            break;
        } else {
            saw_digit = true;
            valid_len = i + 1;
        }
    }

    try!(handle_truncate(ctx, valid_len < s.len()));
    if valid_len == 0 {
        Ok("0")
    } else {
        Ok(&s[..valid_len])
    }
}

/// It converts a valid float string into valid integer string which can be
/// parsed by `i64::from_str`, we can't parse float first then convert it to string
/// because precision will be lost.
fn float_str_to_int_string<'a, 'b: 'a>(valid_float: &'b str) -> Result<Cow<'a, str>> {
    let mut dot_idx = None;
    let mut e_idx = None;
    let mut int_cnt: i64 = 0;
    let mut digits_cnt: i64 = 0;

    for (i, c) in valid_float.chars().enumerate() {
        match c {
            '.' => dot_idx = Some(i),
            'e' | 'E' => e_idx = Some(i),
            '0'...'9' => {
                if e_idx.is_none() {
                    if dot_idx.is_none() {
                        int_cnt += 1;
                    }
                    digits_cnt += 1;
                }
            }
            _ => (),
        }
    }

    if dot_idx.is_none() && e_idx.is_none() {
        return Ok(Cow::Borrowed(valid_float));
    }

    if e_idx.is_none() {
        if int_cnt == 0 {
            return Ok(Cow::Borrowed("0"));
        }
        return Ok(Cow::Borrowed(&valid_float[..dot_idx.unwrap()]));
    }

    let exp = box_try!((&valid_float[e_idx.unwrap() + 1..]).parse::<i64>());
    if exp > 0 && int_cnt > (i64::MAX - exp) {
        // (exp + inc_cnt) overflows MaxInt64.
        // TODO: refactor errors
        return Err(box_err!("[1264] Data Out of Range"));
    }
    if int_cnt + exp <= 0 {
        return Ok(Cow::Borrowed("0"));
    }

    let mut valid_int = String::from(&valid_float[..e_idx.unwrap()]);
    if dot_idx.is_some() {
        valid_int.remove(dot_idx.unwrap());
    }

    let extra_zero_count = exp + int_cnt - digits_cnt;
    if extra_zero_count > MAX_ZERO_COUNT {
        // Return overflow to avoid allocating too much memory.
        // TODO: refactor errors
        return Err(box_err!("[1264] Data Out of Range"));
    }

    if extra_zero_count >= 0 {
        valid_int.extend((0..extra_zero_count).map(|_| '0'));
    } else {
        let len = valid_int.len();
        if extra_zero_count >= len as i64 {
            return Ok(Cow::Borrowed("0"));
        }
        valid_int.truncate((len as i64 + extra_zero_count) as usize);
    }

    Ok(Cow::Owned(valid_int))
}

const MAX_ZERO_COUNT: i64 = 20;

#[cfg(test)]
mod test {
    use std::f64::EPSILON;

    use chrono::FixedOffset;

    use util::xeval::EvalContext;

    #[test]
    fn test_bytes_to_i64() {
        let tests: Vec<(&'static [u8], i64)> = vec![
            (b"0", 0),
            (b" 23a", 23),
            (b"\t 23a", 23),
            (b"\r23a", 0),
            (b"1", 1),
            (b"2.1", 2),
            (b"23e10", 23),
            (b"ab", 0),
            (b"4a", 4),
            (b"+1024", 1024),
            (b"-231", -231),
            (b"", 0),
        ];

        for (bs, n) in tests {
            let t = super::bytes_to_int_without_context(bs).unwrap();
            if t != n {
                panic!("expect convert {:?} to {}, but got {}", bs, n, t);
            }
        }
    }

    #[test]
    fn test_bytes_to_f64() {
        let tests: Vec<(&'static [u8], f64)> = vec![
            (b"", 0.0),
            (b" 23", 23.0),
            (b"-1", -1.0),
            (b"1.11", 1.11),
            (b"1.11.00", 0.0),
            (b"xx", 0.0),
            (b"0x00", 0.0),
            (b"11.xx", 0.0),
            (b"xx.11", 0.0),
        ];

        for (v, f) in tests {
            let ff = super::bytes_to_f64_without_context(v).unwrap();
            if (ff - f).abs() > EPSILON {
                panic!("{:?} should be decode to {}, but got {}", v, f, ff);
            }
        }
    }

    #[test]
    fn test_handle_truncate() {
        let ctxs = vec![EvalContext {
                            tz: FixedOffset::east(0),
                            ignore_truncate: true,
                            truncate_as_warning: true,
                        },
                        EvalContext {
                            tz: FixedOffset::east(0),
                            ignore_truncate: true,
                            truncate_as_warning: false,
                        },
                        EvalContext {
                            tz: FixedOffset::east(0),
                            ignore_truncate: false,
                            truncate_as_warning: true,
                        },
                        EvalContext {
                            tz: FixedOffset::east(0),
                            ignore_truncate: false,
                            truncate_as_warning: false,
                        }];

        for ctx in &ctxs {
            assert!(super::handle_truncate(ctx, false).is_ok());
        }

        assert!(super::handle_truncate(&ctxs[0], true).is_ok());
        assert!(super::handle_truncate(&ctxs[1], true).is_ok());
        assert!(super::handle_truncate(&ctxs[2], true).is_ok());
        assert!(super::handle_truncate(&ctxs[3], true).is_err());
    }

    #[test]
    fn test_get_valid_float_prefix() {
        let cases = vec![("-100", "-100"),
                         ("1abc", "1"),
                         ("-1-1", "-1"),
                         ("+1+1", "+1"),
                         ("123..34", "123."),
                         ("123.23E-10", "123.23E-10"),
                         ("1.1e1.3", "1.1e1"),
                         ("11e1.3", "11e1"),
                         ("1.1e-13a", "1.1e-13"),
                         ("1.", "1."),
                         (".1", ".1"),
                         ("", "0"),
                         ("123e+", "123"),
                         ("123.e", "123.")];

        let ctx = EvalContext {
            tz: FixedOffset::east(0),
            ignore_truncate: true,
            truncate_as_warning: false,
        };
        for (i, o) in cases {
            assert_eq!(super::get_valid_float_prefix(&ctx, i).unwrap(), o);
        }
    }

    #[test]
    fn test_invalid_get_valid_int_prefix() {
        let cases = vec!["1e21", "1e9223372036854775807"];

        for i in cases {
            let o = super::float_str_to_int_string(i);
            assert!(o.is_err());
        }
    }

    #[test]
    fn test_valid_get_valid_int_prefix() {
        let cases = vec![(".1", "0"),
                         (".0", "0"),
                         ("123", "123"),
                         ("123e1", "1230"),
                         ("123.1e2", "12310"),
                         ("123.45e5", "12345000"),
                         ("123.45678e5", "12345678"),
                         ("123.456789e5", "12345678"),
                         ("-123.45678e5", "-12345678"),
                         ("+123.45678e5", "+12345678")];

        for (i, e) in cases {
            let o = super::float_str_to_int_string(i);
            assert_eq!(o.unwrap(), *e);
        }
    }
}
<|endoftext|>


<commit_before>use crate::clause_types::*;
use crate::instructions::*;
use crate::machine::machine_indices::*;

#[derive(Debug)]
pub struct CodeRepo {
    pub(super) code: Code,
}

impl CodeRepo {
    #[inline]
    pub(super)
    fn new() -> Self {
        CodeRepo {
            code: Code::new(),
        }
    }

    #[inline]
    pub(super)
    fn lookup_local_instr<'a>(
        &'a self,
        p: LocalCodePtr,
    ) -> RefOrOwned<'a, Line> {
        match p {
            LocalCodePtr::Halt => {
                unreachable!()
            }
            LocalCodePtr::DirEntry(p) => {
                RefOrOwned::Borrowed(&self.code[p as usize])
            }
            LocalCodePtr::IndexingBuf(p, o, i) => {
                match &self.code[p] {
                    &Line::IndexingCode(ref indexing_lines) => {
                        match &indexing_lines[o] {
                            &IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
                                RefOrOwned::Owned(Line::IndexedChoice(indexed_choice_instrs[i]))
                            }
                            _ => {
                                unreachable!()
                            }
                        }
                    }
                    _ => {
                        unreachable!()
                    }
                }
            }
        }
    }

    pub(super)
    fn lookup_instr<'a>(
        &'a self,
        last_call: bool,
        p: &CodePtr,
    ) -> Option<RefOrOwned<'a, Line>> {
        match p {
            &CodePtr::Local(local) => {
                return Some(self.lookup_local_instr(local));
            }
            &CodePtr::REPL(..) => {
                None
            }
            &CodePtr::BuiltInClause(ref built_in, _) => {
                let call_clause = call_clause!(
                    ClauseType::BuiltIn(built_in.clone()),
                    built_in.arity(),
                    0,
                    last_call
                );

                Some(RefOrOwned::Owned(call_clause))
            }
            &CodePtr::CallN(arity, _, last_call) => {
                let call_clause = call_clause!(
                    ClauseType::CallN,
                    arity,
                    0,
                    last_call
                );

                Some(RefOrOwned::Owned(call_clause))
            }
            &CodePtr::VerifyAttrInterrupt(p) => {
                Some(RefOrOwned::Borrowed(&self.code[p]))
            }
/*
            &CodePtr::DynamicTransaction(..) => {
                None
            }
*/
        }
    }
}
<commit_msg>treat LocalCodePtr::Halt received at lookup_local_instr as an interrupt (#823)<commit_after>use crate::clause_types::*;
use crate::instructions::*;
use crate::machine::machine_indices::*;

#[derive(Debug)]
pub struct CodeRepo {
    pub(super) code: Code,
}

impl CodeRepo {
    #[inline]
    pub(super)
    fn new() -> Self {
        CodeRepo {
            code: Code::new(),
        }
    }

    #[inline]
    pub(super)
    fn lookup_local_instr<'a>(
        &'a self,
        p: LocalCodePtr,
    ) -> RefOrOwned<'a, Line> {
        match p {
            LocalCodePtr::Halt => {
                // exit with the interrupt exit code.
                std::process::exit(1);
            }
            LocalCodePtr::DirEntry(p) => {
                RefOrOwned::Borrowed(&self.code[p as usize])
            }
            LocalCodePtr::IndexingBuf(p, o, i) => {
                match &self.code[p] {
                    &Line::IndexingCode(ref indexing_lines) => {
                        match &indexing_lines[o] {
                            &IndexingLine::IndexedChoice(ref indexed_choice_instrs) => {
                                RefOrOwned::Owned(Line::IndexedChoice(indexed_choice_instrs[i]))
                            }
                            _ => {
                                unreachable!()
                            }
                        }
                    }
                    _ => {
                        unreachable!()
                    }
                }
            }
        }
    }

    pub(super)
    fn lookup_instr<'a>(
        &'a self,
        last_call: bool,
        p: &CodePtr,
    ) -> Option<RefOrOwned<'a, Line>> {
        match p {
            &CodePtr::Local(local) => {
                return Some(self.lookup_local_instr(local));
            }
            &CodePtr::REPL(..) => {
                None
            }
            &CodePtr::BuiltInClause(ref built_in, _) => {
                let call_clause = call_clause!(
                    ClauseType::BuiltIn(built_in.clone()),
                    built_in.arity(),
                    0,
                    last_call
                );

                Some(RefOrOwned::Owned(call_clause))
            }
            &CodePtr::CallN(arity, _, last_call) => {
                let call_clause = call_clause!(
                    ClauseType::CallN,
                    arity,
                    0,
                    last_call
                );

                Some(RefOrOwned::Owned(call_clause))
            }
            &CodePtr::VerifyAttrInterrupt(p) => {
                Some(RefOrOwned::Borrowed(&self.code[p]))
            }
/*
            &CodePtr::DynamicTransaction(..) => {
                None
            }
*/
        }
    }
}
<|endoftext|>


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

use dom::bindings::codegen::Bindings::FormDataBinding;
use dom::bindings::codegen::InheritTypes::FileCast;
use dom::bindings::codegen::UnionTypes::FileOrString::{FileOrString, eFile, eString};
use dom::bindings::error::{Fallible};
use dom::bindings::global::{GlobalRef, Window};
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::blob::Blob;
use dom::file::File;
use dom::htmlformelement::HTMLFormElement;
use dom::window::Window;
use servo_util::str::DOMString;
use std::cell::RefCell;
use std::collections::hashmap::HashMap;

#[deriving(Encodable, Clone)]
pub enum FormDatum {
    StringData(DOMString),
    FileData(JS<File>)
}

#[deriving(Encodable)]
pub struct FormData {
    data: Traceable<RefCell<HashMap<DOMString, Vec<FormDatum>>>>,
    reflector_: Reflector,
    window: JS<Window>,
    form: Option<JS<HTMLFormElement>>
}

impl FormData {
    pub fn new_inherited(form: Option<JSRef<HTMLFormElement>>, window: &JSRef<Window>) -> FormData {
        FormData {
            data: Traceable::new(RefCell::new(HashMap::new())),
            reflector_: Reflector::new(),
            window: JS::from_rooted(window),
            form: form.map(|f| JS::from_rooted(&f)),
        }
    }

    pub fn new(form: Option<JSRef<HTMLFormElement>>, window: &JSRef<Window>) -> Temporary<FormData> {
        reflect_dom_object(box FormData::new_inherited(form, window),
                           &Window(*window), FormDataBinding::Wrap)
    }

    pub fn Constructor(global: &GlobalRef, form: Option<JSRef<HTMLFormElement>>) -> Fallible<Temporary<FormData>> {
        Ok(FormData::new(form, global.as_window()))
    }
}

pub trait FormDataMethods {
    fn Append(&self, name: DOMString, value: &JSRef<Blob>, filename: Option<DOMString>);
    fn Append_(&self, name: DOMString, value: DOMString);
    fn Delete(&self, name: DOMString);
    fn Get(&self, name: DOMString) -> Option<FileOrString>;
    fn Has(&self, name: DOMString) -> bool;
    fn Set(&self, name: DOMString, value: &JSRef<Blob>, filename: Option<DOMString>);
    fn Set_(&self, name: DOMString, value: DOMString);
}

impl<'a> FormDataMethods for JSRef<'a, FormData> {
    fn Append(&self, name: DOMString, value: &JSRef<Blob>, filename: Option<DOMString>) {
        let file = FileData(JS::from_rooted(&self.get_file_from_blob(value, filename)));
        self.data.deref().borrow_mut().insert_or_update_with(name.clone(), vec!(file.clone()),
                                        |_k, v| {v.push(file.clone());});
    }

    fn Append_(&self, name: DOMString, value: DOMString) {
        self.data.deref().borrow_mut().insert_or_update_with(name, vec!(StringData(value.clone())),
                                        |_k, v| {v.push(StringData(value.clone()));});
    }

    fn Delete(&self, name: DOMString) {
        self.data.deref().borrow_mut().remove(&name);
    }

    fn Get(&self, name: DOMString) -> Option<FileOrString> {
        if self.data.deref().borrow().contains_key_equiv(&name) {
            match self.data.deref().borrow().get(&name).get(0).clone() {
                StringData(ref s) => Some(eString(s.clone())),
                FileData(ref f) => {
                    Some(eFile(f.clone()))
                }
            }
        } else {
            None
        }
    }

    fn Has(&self, name: DOMString) -> bool {
        self.data.deref().borrow().contains_key_equiv(&name)
    }

    fn Set(&self, name: DOMString, value: &JSRef<Blob>, filename: Option<DOMString>) {
        let file = FileData(JS::from_rooted(&self.get_file_from_blob(value, filename)));
        self.data.deref().borrow_mut().insert(name, vec!(file));
    }

    fn Set_(&self, name: DOMString, value: DOMString) {
        self.data.deref().borrow_mut().insert(name, vec!(StringData(value)));
    }
}

impl Reflectable for FormData {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }
}

trait PrivateFormDataHelpers{
  fn get_file_from_blob(&self, value: &JSRef<Blob>, filename: Option<DOMString>) -> Temporary<File>;
}

impl PrivateFormDataHelpers for FormData {
    fn get_file_from_blob(&self, value: &JSRef<Blob>, filename: Option<DOMString>) -> Temporary<File> {
        let window = self.window.root();
        let f: Option<&JSRef<File>> = FileCast::to_ref(value);
        let name = filename.unwrap_or(f.map(|inner| inner.name.clone()).unwrap_or("blob".to_string()));
        File::new(&Window(*window), value, name)
    }
}
<commit_msg>Support FormData outside Window scopes.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::FormDataBinding;
use dom::bindings::codegen::InheritTypes::FileCast;
use dom::bindings::codegen::UnionTypes::FileOrString::{FileOrString, eFile, eString};
use dom::bindings::error::{Fallible};
use dom::bindings::global::{GlobalRef, GlobalField};
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::blob::Blob;
use dom::file::File;
use dom::htmlformelement::HTMLFormElement;
use servo_util::str::DOMString;
use std::cell::RefCell;
use std::collections::hashmap::HashMap;

#[deriving(Encodable, Clone)]
pub enum FormDatum {
    StringData(DOMString),
    FileData(JS<File>)
}

#[deriving(Encodable)]
pub struct FormData {
    data: Traceable<RefCell<HashMap<DOMString, Vec<FormDatum>>>>,
    reflector_: Reflector,
    global: GlobalField,
    form: Option<JS<HTMLFormElement>>
}

impl FormData {
    pub fn new_inherited(form: Option<JSRef<HTMLFormElement>>, global: &GlobalRef) -> FormData {
        FormData {
            data: Traceable::new(RefCell::new(HashMap::new())),
            reflector_: Reflector::new(),
            global: GlobalField::from_rooted(global),
            form: form.map(|f| JS::from_rooted(&f)),
        }
    }

    pub fn new(form: Option<JSRef<HTMLFormElement>>, global: &GlobalRef) -> Temporary<FormData> {
        reflect_dom_object(box FormData::new_inherited(form, global),
                           global, FormDataBinding::Wrap)
    }

    pub fn Constructor(global: &GlobalRef, form: Option<JSRef<HTMLFormElement>>) -> Fallible<Temporary<FormData>> {
        Ok(FormData::new(form, global))
    }
}

pub trait FormDataMethods {
    fn Append(&self, name: DOMString, value: &JSRef<Blob>, filename: Option<DOMString>);
    fn Append_(&self, name: DOMString, value: DOMString);
    fn Delete(&self, name: DOMString);
    fn Get(&self, name: DOMString) -> Option<FileOrString>;
    fn Has(&self, name: DOMString) -> bool;
    fn Set(&self, name: DOMString, value: &JSRef<Blob>, filename: Option<DOMString>);
    fn Set_(&self, name: DOMString, value: DOMString);
}

impl<'a> FormDataMethods for JSRef<'a, FormData> {
    fn Append(&self, name: DOMString, value: &JSRef<Blob>, filename: Option<DOMString>) {
        let file = FileData(JS::from_rooted(&self.get_file_from_blob(value, filename)));
        self.data.deref().borrow_mut().insert_or_update_with(name.clone(), vec!(file.clone()),
                                        |_k, v| {v.push(file.clone());});
    }

    fn Append_(&self, name: DOMString, value: DOMString) {
        self.data.deref().borrow_mut().insert_or_update_with(name, vec!(StringData(value.clone())),
                                        |_k, v| {v.push(StringData(value.clone()));});
    }

    fn Delete(&self, name: DOMString) {
        self.data.deref().borrow_mut().remove(&name);
    }

    fn Get(&self, name: DOMString) -> Option<FileOrString> {
        if self.data.deref().borrow().contains_key_equiv(&name) {
            match self.data.deref().borrow().get(&name).get(0).clone() {
                StringData(ref s) => Some(eString(s.clone())),
                FileData(ref f) => {
                    Some(eFile(f.clone()))
                }
            }
        } else {
            None
        }
    }

    fn Has(&self, name: DOMString) -> bool {
        self.data.deref().borrow().contains_key_equiv(&name)
    }

    fn Set(&self, name: DOMString, value: &JSRef<Blob>, filename: Option<DOMString>) {
        let file = FileData(JS::from_rooted(&self.get_file_from_blob(value, filename)));
        self.data.deref().borrow_mut().insert(name, vec!(file));
    }

    fn Set_(&self, name: DOMString, value: DOMString) {
        self.data.deref().borrow_mut().insert(name, vec!(StringData(value)));
    }
}

impl Reflectable for FormData {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }
}

trait PrivateFormDataHelpers{
  fn get_file_from_blob(&self, value: &JSRef<Blob>, filename: Option<DOMString>) -> Temporary<File>;
}

impl PrivateFormDataHelpers for FormData {
    fn get_file_from_blob(&self, value: &JSRef<Blob>, filename: Option<DOMString>) -> Temporary<File> {
        let global = self.global.root();
        let f: Option<&JSRef<File>> = FileCast::to_ref(value);
        let name = filename.unwrap_or(f.map(|inner| inner.name.clone()).unwrap_or("blob".to_string()));
        File::new(&global.root_ref(), value, name)
    }
}
<|endoftext|>