<commit_before>#![crate_name = "document"]

use std::collections::hashmap::HashMap;
use std::collections::hashmap::HashSet;

#[deriving(Show)]
pub struct Document {
    /// Storage for each maintained type
    elements: Vec<Element>,
    attributes: Vec<Attribute>,
    texts: Vec<Text>,

    // Primary associations between nodes
    children: HashMap<Parent, Vec<Child>>,
    parents: HashMap<Child, Parent>,

    // Associated attributes
    assigned_attributes: HashMap<ElementNode, HashSet<AttributeNode>>,
}

#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub struct ElementNode   { i: uint }
#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub struct AttributeNode { i: uint }
#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub struct TextNode      { i: uint }

#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub enum Parent {
    ElementParent(ElementNode),
}

impl Parent {
    pub fn element(&self) -> Option<ElementNode> {
        match self {
            &ElementParent(e) => Some(e),
        }
    }
}

pub trait ToParent {
    fn to_parent(&self) -> Parent;
}

impl ToParent for ElementNode {
    fn to_parent(&self) -> Parent { ElementParent(*self) }
}

#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub enum Child {
    ElementChild(ElementNode),
    TextChild(TextNode),
}

impl Child {
    pub fn element(&self) -> Option<ElementNode> {
        match self {
            &ElementChild(e) => Some(e),
            _ => None,
        }
    }

    pub fn text(&self) -> Option<TextNode> {
        match self {
            &TextChild(t) => Some(t),
            _ => None,
        }
    }
}

pub trait ToChild {
    fn to_child(&self) -> Child;
}

impl ToChild for ElementNode {
    fn to_child(&self) -> Child { ElementChild(*self) }
}

impl ToChild for TextNode {
    fn to_child(&self) -> Child { TextChild(*self) }
}

impl Document {
    pub fn new() -> Document {
        Document {
            elements: Vec::new(),
            attributes: Vec::new(),
            texts: Vec::new(),
            children: HashMap::new(),
            parents: HashMap::new(),
            assigned_attributes: HashMap::new(),
        }
    }

    pub fn new_element(&mut self, name: &str) -> ElementNode {
        let eref = ElementNode{i: self.elements.len()};
        self.elements.push(Element {
            name: name.to_string(),
        });
        eref
    }

    fn new_attribute(&mut self, name: &str, value: &str) -> AttributeNode {
        let aref = AttributeNode{i: self.attributes.len()} ;
        self.attributes.push(Attribute {
            name: name.to_string(),
            value: value.to_string(),
        });
        aref
    }

    fn new_text(&mut self, value: &str) -> TextNode {
        let tref = TextNode{i: self.texts.len()};
        self.texts.push(Text {
            value: value.to_string(),
        });
        tref
    }

    pub fn element<'a>(&'a self, element: ElementNode) -> &'a Element {
        &self.elements[element.i]
    }

    pub fn mut_element<'a>(&'a mut self, element: ElementNode) -> &'a mut Element {
        self.elements.get_mut(element.i)
    }

    fn attribute<'a>(&'a self, attribute: AttributeNode) -> &'a Attribute {
        &self.attributes[attribute.i]
    }

    fn mut_attribute<'a>(&'a mut self, attribute: AttributeNode) -> &'a mut Attribute {
        self.attributes.get_mut(attribute.i)
    }

    fn text<'a>(&'a self, text: TextNode) -> &'a Text {
        &self.texts[text.i]
    }

    fn mut_text<'a>(&'a mut self, text: TextNode) -> &'a mut Text {
        self.texts.get_mut(text.i)
    }

    fn attribute_for(&self, element: ElementNode, name: &str) -> Option<AttributeNode> {
        match self.assigned_attributes.find(&element) {
            Some(ref attributes) => {
                let mut node_attrs = attributes.iter().map(|node| (node, self.attribute(*node)));
                match node_attrs.find(|&(_, attr)| attr.name.as_slice() == name) {
                    Some((node, _)) => Some(*node),
                    None => None,
                }
            },
            None => None,
        }
    }

    pub fn get_attribute(&self, element: ElementNode, name: &str) -> Option<&str> {
        match self.attribute_for(element, name) {
            Some(aref) => Some(self.attribute(aref).value.as_slice()),
            None => None,
        }
    }

    pub fn set_attribute(&mut self, element: ElementNode, name: &str, value: &str) -> AttributeNode {
        match self.attribute_for(element, name) {
            Some(aref) => {
                self.mut_attribute(aref).value = value.to_string();
                aref
            },
            None => {
                let aref = self.new_attribute(name, value);
                let assigned_attributes = self.assigned_attributes.find_or_insert(element, HashSet::new());
                assigned_attributes.insert(aref);
                aref
            },
        }
    }

    fn remove_parentage(&mut self, child: Child) {
        match self.parent(child) {
            Some(ref parent) => {
                match self.children.find_mut(parent) {
                    Some(children) => {
                        match children.as_slice().position_elem(&child) {
                            Some(idx) => { children.remove(idx); },
                            None => {},
                        }
                    },
                    None => {},
                }
            },
            None => {}
        }
    }

    pub fn append_child<P: ToParent, C: ToChild>(&mut self, parent: P, child: C) {
        let parent = parent.to_parent();
        let child = child.to_child();

        {
            let kids = self.children.find_or_insert(parent, Vec::new());
            kids.push(child);
        }

        self.remove_parentage(child);
        self.parents.insert(child, parent);
    }

    pub fn children<P: ToParent>(&self, parent: P) -> Vec<Child> {
        let parent = parent.to_parent();

        match self.children.find(&parent) {
            Some(v) => v.iter().map(|r| r.clone()).collect(),
            None => vec![],
        }
    }

    pub fn parent(&self, child: Child) -> Option<Parent> {
        self.parents.find_copy(&child)
    }
}

#[deriving(Show)]
pub struct Element {
    name: String,
}

impl Element {
    pub fn name(&self) -> &str {
        self.name.as_slice()
    }

    pub fn set_name(&mut self, name: &str) {
        self.name = name.to_string();
    }
}

#[deriving(Show)]
pub struct Attribute {
    name: String,
    value: String,
}

#[deriving(Show)]
pub struct Text {
    value: String,
}

impl Text {
    pub fn value(&self) -> &str {
        self.value.as_slice()
    }

    pub fn set_value(& mut self, value: &str) {
        self.value = value.to_string()
    }
}

pub struct Comment;
pub struct Root;

#[test]
fn can_add_an_element_as_a_child() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");
    let beta  = d.new_element("beta");

    d.append_child(alpha, beta);

    let children = d.children(alpha);
    assert_eq!(1, children.len());

    let child_elem = children[0].element().unwrap();
    let result = d.element(child_elem);
    assert_eq!(result.name(), "beta");
}

#[test]
fn children_are_ordered() {
    let mut d = Document::new();
    let greek = d.new_element("greek");
    let alpha = d.new_element("alpha");
    let omega = d.new_element("omega");

    d.append_child(greek, alpha);
    d.append_child(greek, omega);
    let children = d.children(greek);

    assert_eq!(2, children.len());
    let child_elem1 = children[0].element().unwrap();
    let child_elem2 = children[1].element().unwrap();
    assert_eq!(d.element(child_elem1).name(), "alpha");
    assert_eq!(d.element(child_elem2).name(), "omega");
}

#[test]
fn children_know_their_parent() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");
    let beta  = d.new_element("beta");

    d.append_child(alpha, beta);

    let child = d.children(alpha)[0];
    let parent = d.parent(child).unwrap();

    let parent_elem = parent.element().unwrap();
    let result = d.element(parent_elem);
    assert_eq!(result.name(), "alpha");
}

#[test]
fn replacing_parent_updates_original_parent() {
    let mut d = Document::new();
    let parent1 = d.new_element("parent1");
    let parent2 = d.new_element("parent2");
    let child = d.new_element("child");

    d.append_child(parent1, child);
    d.append_child(parent2, child);

    assert!(d.children(parent1).is_empty());
    assert_eq!(1, d.children(parent2).len());
}

#[test]
fn can_rename_an_element() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    {
        let element = d.mut_element(alpha);
        element.set_name("beta");
    }

    let beta = d.element(alpha);
    assert_eq!(beta.name(), "beta");
}

#[test]
fn elements_have_attributes() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    d.set_attribute(alpha, "hello", "world");
    let val = d.get_attribute(alpha, "hello").unwrap();
    assert_eq!(val, "world");
}

#[test]
fn attributes_can_be_reset() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    d.set_attribute(alpha, "hello", "world");
    d.set_attribute(alpha, "hello", "universe");

    let val = d.get_attribute(alpha, "hello").unwrap();
    assert_eq!(val, "universe");
}

#[test]
fn elements_can_have_text_children() {
    let mut d = Document::new();
    let sentence = d.new_element("sentence");
    let text = d.new_text("Now is the winter of our discontent.");

    d.append_child(sentence, text);

    let children = d.children(sentence);
    assert_eq!(1, children.len());

    let child_text = children[0].text().unwrap();
    assert_eq!(d.text(child_text).value(), "Now is the winter of our discontent.");
}

#[test]
fn text_can_be_changed() {
    let mut d = Document::new();
    let text = d.new_text("Now is the winter of our discontent.");

    let text_data = d.mut_text(text);
    text_data.set_value("Made glorious summer by this sun of York");

    assert_eq!(text_data.value(), "Made glorious summer by this sun of York");
}
<commit_msg>Introduce a nodeset<commit_after>#![crate_name = "document"]

use std::collections::hashmap::HashMap;
use std::collections::hashmap::HashSet;

#[deriving(Show)]
pub struct Document {
    /// Storage for each maintained type
    elements: Vec<Element>,
    attributes: Vec<Attribute>,
    texts: Vec<Text>,

    // Primary associations between nodes
    children: HashMap<Parent, Vec<Child>>,
    parents: HashMap<Child, Parent>,

    // Associated attributes
    assigned_attributes: HashMap<ElementNode, HashSet<AttributeNode>>,
}

#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub struct ElementNode   { i: uint }
#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub struct AttributeNode { i: uint }
#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub struct TextNode      { i: uint }

#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub enum Parent {
    ElementParent(ElementNode),
}

impl Parent {
    pub fn element(&self) -> Option<ElementNode> {
        match self {
            &ElementParent(e) => Some(e),
        }
    }
}

pub trait ToParent {
    fn to_parent(&self) -> Parent;
}

impl ToParent for ElementNode {
    fn to_parent(&self) -> Parent { ElementParent(*self) }
}

#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub enum Child {
    ElementChild(ElementNode),
    TextChild(TextNode),
}

impl Child {
    pub fn element(&self) -> Option<ElementNode> {
        match self {
            &ElementChild(e) => Some(e),
            _ => None,
        }
    }

    pub fn text(&self) -> Option<TextNode> {
        match self {
            &TextChild(t) => Some(t),
            _ => None,
        }
    }
}

pub trait ToChild {
    fn to_child(&self) -> Child;
}

impl ToChild for ElementNode {
    fn to_child(&self) -> Child { ElementChild(*self) }
}

impl ToChild for TextNode {
    fn to_child(&self) -> Child { TextChild(*self) }
}

impl Document {
    pub fn new() -> Document {
        Document {
            elements: Vec::new(),
            attributes: Vec::new(),
            texts: Vec::new(),
            children: HashMap::new(),
            parents: HashMap::new(),
            assigned_attributes: HashMap::new(),
        }
    }

    pub fn new_element(&mut self, name: &str) -> ElementNode {
        let eref = ElementNode{i: self.elements.len()};
        self.elements.push(Element {
            name: name.to_string(),
        });
        eref
    }

    fn new_attribute(&mut self, name: &str, value: &str) -> AttributeNode {
        let aref = AttributeNode{i: self.attributes.len()} ;
        self.attributes.push(Attribute {
            name: name.to_string(),
            value: value.to_string(),
        });
        aref
    }

    fn new_text(&mut self, value: &str) -> TextNode {
        let tref = TextNode{i: self.texts.len()};
        self.texts.push(Text {
            value: value.to_string(),
        });
        tref
    }

    pub fn element<'a>(&'a self, element: ElementNode) -> &'a Element {
        &self.elements[element.i]
    }

    pub fn mut_element<'a>(&'a mut self, element: ElementNode) -> &'a mut Element {
        self.elements.get_mut(element.i)
    }

    fn attribute<'a>(&'a self, attribute: AttributeNode) -> &'a Attribute {
        &self.attributes[attribute.i]
    }

    fn mut_attribute<'a>(&'a mut self, attribute: AttributeNode) -> &'a mut Attribute {
        self.attributes.get_mut(attribute.i)
    }

    fn text<'a>(&'a self, text: TextNode) -> &'a Text {
        &self.texts[text.i]
    }

    fn mut_text<'a>(&'a mut self, text: TextNode) -> &'a mut Text {
        self.texts.get_mut(text.i)
    }

    fn attribute_for(&self, element: ElementNode, name: &str) -> Option<AttributeNode> {
        match self.assigned_attributes.find(&element) {
            Some(ref attributes) => {
                let mut node_attrs = attributes.iter().map(|node| (node, self.attribute(*node)));
                match node_attrs.find(|&(_, attr)| attr.name.as_slice() == name) {
                    Some((node, _)) => Some(*node),
                    None => None,
                }
            },
            None => None,
        }
    }

    pub fn get_attribute(&self, element: ElementNode, name: &str) -> Option<&str> {
        match self.attribute_for(element, name) {
            Some(aref) => Some(self.attribute(aref).value.as_slice()),
            None => None,
        }
    }

    pub fn set_attribute(&mut self, element: ElementNode, name: &str, value: &str) -> AttributeNode {
        match self.attribute_for(element, name) {
            Some(aref) => {
                self.mut_attribute(aref).value = value.to_string();
                aref
            },
            None => {
                let aref = self.new_attribute(name, value);
                let assigned_attributes = self.assigned_attributes.find_or_insert(element, HashSet::new());
                assigned_attributes.insert(aref);
                aref
            },
        }
    }

    fn remove_parentage(&mut self, child: Child) {
        match self.parent(child) {
            Some(ref parent) => {
                match self.children.find_mut(parent) {
                    Some(children) => {
                        match children.as_slice().position_elem(&child) {
                            Some(idx) => { children.remove(idx); },
                            None => {},
                        }
                    },
                    None => {},
                }
            },
            None => {}
        }
    }

    pub fn append_child<P: ToParent, C: ToChild>(&mut self, parent: P, child: C) {
        let parent = parent.to_parent();
        let child = child.to_child();

        {
            let kids = self.children.find_or_insert(parent, Vec::new());
            kids.push(child);
        }

        self.remove_parentage(child);
        self.parents.insert(child, parent);
    }

    pub fn children<P: ToParent>(&self, parent: P) -> Vec<Child> {
        let parent = parent.to_parent();

        match self.children.find(&parent) {
            Some(v) => v.iter().map(|r| r.clone()).collect(),
            None => vec![],
        }
    }

    pub fn parent(&self, child: Child) -> Option<Parent> {
        self.parents.find_copy(&child)
    }
}

#[deriving(Show)]
pub struct Element {
    name: String,
}

impl Element {
    pub fn name(&self) -> &str {
        self.name.as_slice()
    }

    pub fn set_name(&mut self, name: &str) {
        self.name = name.to_string();
    }
}

#[deriving(Show)]
pub struct Attribute {
    name: String,
    value: String,
}

#[deriving(Show)]
pub struct Text {
    value: String,
}

impl Text {
    pub fn value(&self) -> &str {
        self.value.as_slice()
    }

    pub fn set_value(& mut self, value: &str) {
        self.value = value.to_string()
    }
}

pub struct Comment;
pub struct Root;

#[deriving(Show,Eq,PartialEq,Hash,Clone)]
pub enum Any {
    ElementAny(ElementNode),
    AttributeAny(AttributeNode),
    TextAny(TextNode),
}

impl Any {
    fn element(&self) -> Option<ElementNode> {
        match self {
            &ElementAny(e) => Some(e),
            _ => None,
        }
    }

    fn attribute(&self) -> Option<AttributeNode> {
        match self {
            &AttributeAny(e) => Some(e),
            _ => None,
        }
    }

    fn text(&self) -> Option<TextNode> {
        match self {
            &TextAny(e) => Some(e),
            _ => None,
        }
    }
}

pub trait ToAny {
    fn to_any(&self) -> Any;
}

impl ToAny for ElementNode {
    fn to_any(&self) -> Any { ElementAny(*self) }
}

impl ToAny for AttributeNode {
    fn to_any(&self) -> Any { AttributeAny(*self) }
}

impl ToAny for TextNode {
    fn to_any(&self) -> Any { TextAny(*self) }
}

#[deriving(Show,PartialEq,Clone)]
pub struct Nodeset {
    nodes: Vec<Any>,
}

impl Nodeset {
    pub fn new() -> Nodeset {
        Nodeset{nodes: Vec::new()}
    }

    pub fn add<N: ToAny>(& mut self, node: N) {
        self.nodes.push(node.to_any());
    }

    pub fn size(&self) -> uint {
        self.nodes.len()
    }

    fn iter(&self) -> std::slice::Items<Any> {
        self.nodes.iter()
    }
}

#[test]
fn can_add_an_element_as_a_child() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");
    let beta  = d.new_element("beta");

    d.append_child(alpha, beta);

    let children = d.children(alpha);
    assert_eq!(1, children.len());

    let child_elem = children[0].element().unwrap();
    let result = d.element(child_elem);
    assert_eq!(result.name(), "beta");
}

#[test]
fn children_are_ordered() {
    let mut d = Document::new();
    let greek = d.new_element("greek");
    let alpha = d.new_element("alpha");
    let omega = d.new_element("omega");

    d.append_child(greek, alpha);
    d.append_child(greek, omega);
    let children = d.children(greek);

    assert_eq!(2, children.len());
    let child_elem1 = children[0].element().unwrap();
    let child_elem2 = children[1].element().unwrap();
    assert_eq!(d.element(child_elem1).name(), "alpha");
    assert_eq!(d.element(child_elem2).name(), "omega");
}

#[test]
fn children_know_their_parent() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");
    let beta  = d.new_element("beta");

    d.append_child(alpha, beta);

    let child = d.children(alpha)[0];
    let parent = d.parent(child).unwrap();

    let parent_elem = parent.element().unwrap();
    let result = d.element(parent_elem);
    assert_eq!(result.name(), "alpha");
}

#[test]
fn replacing_parent_updates_original_parent() {
    let mut d = Document::new();
    let parent1 = d.new_element("parent1");
    let parent2 = d.new_element("parent2");
    let child = d.new_element("child");

    d.append_child(parent1, child);
    d.append_child(parent2, child);

    assert!(d.children(parent1).is_empty());
    assert_eq!(1, d.children(parent2).len());
}

#[test]
fn can_rename_an_element() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    {
        let element = d.mut_element(alpha);
        element.set_name("beta");
    }

    let beta = d.element(alpha);
    assert_eq!(beta.name(), "beta");
}

#[test]
fn elements_have_attributes() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    d.set_attribute(alpha, "hello", "world");
    let val = d.get_attribute(alpha, "hello").unwrap();
    assert_eq!(val, "world");
}

#[test]
fn attributes_can_be_reset() {
    let mut d = Document::new();
    let alpha = d.new_element("alpha");

    d.set_attribute(alpha, "hello", "world");
    d.set_attribute(alpha, "hello", "universe");

    let val = d.get_attribute(alpha, "hello").unwrap();
    assert_eq!(val, "universe");
}

#[test]
fn elements_can_have_text_children() {
    let mut d = Document::new();
    let sentence = d.new_element("sentence");
    let text = d.new_text("Now is the winter of our discontent.");

    d.append_child(sentence, text);

    let children = d.children(sentence);
    assert_eq!(1, children.len());

    let child_text = children[0].text().unwrap();
    assert_eq!(d.text(child_text).value(), "Now is the winter of our discontent.");
}

#[test]
fn text_can_be_changed() {
    let mut d = Document::new();
    let text = d.new_text("Now is the winter of our discontent.");

    let text_data = d.mut_text(text);
    text_data.set_value("Made glorious summer by this sun of York");

    assert_eq!(text_data.value(), "Made glorious summer by this sun of York");
}

#[test]
fn nodeset_can_include_all_node_types() {
    let mut nodes = Nodeset::new();
    let mut d = Document::new();
    let e = d.new_element("element");
    let a = d.set_attribute(e, "name", "value");
    let t = d.new_text("text");

    nodes.add(e);
    nodes.add(a);
    nodes.add(t);

    let node_vec: Vec<&Any> = nodes.iter().collect();

    assert_eq!(3, node_vec.len());
    assert_eq!(e, node_vec[0].element().unwrap());
    assert_eq!(a, node_vec[1].attribute().unwrap());
    assert_eq!(t, node_vec[2].text().unwrap());
}
<|endoftext|>


<commit_before>use crate::{
    backend::Backend,
    buffer::{Buffer, Cell},
    layout::Rect,
};
use std::{fmt::Write, io};
use unicode_width::UnicodeWidthStr;

/// A backend used for the integration tests.
#[derive(Debug)]
pub struct TestBackend {
    width: u16,
    buffer: Buffer,
    height: u16,
    cursor: bool,
    pos: (u16, u16),
}

/// Returns a string representation of the given buffer for debugging purpose.
fn buffer_view(buffer: &Buffer) -> String {
    let mut view = String::with_capacity(buffer.content.len() + buffer.area.height as usize * 3);
    for cells in buffer.content.chunks(buffer.area.width as usize) {
        let mut overwritten = vec![];
        let mut skip: usize = 0;
        view.push('"');
        for (x, c) in cells.iter().enumerate() {
            if skip == 0 {
                view.push_str(&c.symbol);
            } else {
                overwritten.push((x, &c.symbol))
            }
            skip = std::cmp::max(skip, c.symbol.width()).saturating_sub(1);
        }
        view.push('"');
        if !overwritten.is_empty() {
            write!(
                &mut view,
                " Hidden by multi-width symbols: {:?}",
                overwritten
            )
            .unwrap();
        }
        view.push('\n');
    }
    view
}

impl TestBackend {
    pub fn new(width: u16, height: u16) -> TestBackend {
        TestBackend {
            width,
            height,
            buffer: Buffer::empty(Rect::new(0, 0, width, height)),
            cursor: false,
            pos: (0, 0),
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn resize(&mut self, width: u16, height: u16) {
        self.buffer.resize(Rect::new(0, 0, width, height));
        self.width = width;
        self.height = height;
    }

    pub fn assert_buffer(&self, expected: &Buffer) {
        assert_eq!(expected.area, self.buffer.area);
        let diff = expected.diff(&self.buffer);
        if diff.is_empty() {
            return;
        }

        let mut debug_info = String::from("Buffers are not equal");
        debug_info.push('\n');
        debug_info.push_str("Expected:");
        debug_info.push('\n');
        let expected_view = buffer_view(expected);
        debug_info.push_str(&expected_view);
        debug_info.push('\n');
        debug_info.push_str("Got:");
        debug_info.push('\n');
        let view = buffer_view(&self.buffer);
        debug_info.push_str(&view);
        debug_info.push('\n');

        debug_info.push_str("Diff:");
        debug_info.push('\n');
        let nice_diff = diff
            .iter()
            .enumerate()
            .map(|(i, (x, y, cell))| {
                let expected_cell = expected.get(*x, *y);
                format!(
                    "{}: at ({}, {}) expected {:?} got {:?}",
                    i, x, y, expected_cell, cell
                )
            })
            .collect::<Vec<String>>()
            .join("\n");
        debug_info.push_str(&nice_diff);
        panic!("{}", debug_info);
    }
}

impl Backend for TestBackend {
    fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
    where
        I: Iterator<Item = (u16, u16, &'a Cell)>,
    {
        for (x, y, c) in content {
            let cell = self.buffer.get_mut(x, y);
            *cell = c.clone();
        }
        Ok(())
    }

    fn hide_cursor(&mut self) -> Result<(), io::Error> {
        self.cursor = false;
        Ok(())
    }

    fn show_cursor(&mut self) -> Result<(), io::Error> {
        self.cursor = true;
        Ok(())
    }

    fn get_cursor(&mut self) -> Result<(u16, u16), io::Error> {
        Ok(self.pos)
    }

    fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
        self.pos = (x, y);
        Ok(())
    }

    fn clear(&mut self) -> Result<(), io::Error> {
        Ok(())
    }

    fn size(&self) -> Result<Rect, io::Error> {
        Ok(Rect::new(0, 0, self.width, self.height))
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        Ok(())
    }
}
<commit_msg>fix: actually clear buffer in TestBackend::clear (#461)<commit_after>use crate::{
    backend::Backend,
    buffer::{Buffer, Cell},
    layout::Rect,
};
use std::{fmt::Write, io};
use unicode_width::UnicodeWidthStr;

/// A backend used for the integration tests.
#[derive(Debug)]
pub struct TestBackend {
    width: u16,
    buffer: Buffer,
    height: u16,
    cursor: bool,
    pos: (u16, u16),
}

/// Returns a string representation of the given buffer for debugging purpose.
fn buffer_view(buffer: &Buffer) -> String {
    let mut view = String::with_capacity(buffer.content.len() + buffer.area.height as usize * 3);
    for cells in buffer.content.chunks(buffer.area.width as usize) {
        let mut overwritten = vec![];
        let mut skip: usize = 0;
        view.push('"');
        for (x, c) in cells.iter().enumerate() {
            if skip == 0 {
                view.push_str(&c.symbol);
            } else {
                overwritten.push((x, &c.symbol))
            }
            skip = std::cmp::max(skip, c.symbol.width()).saturating_sub(1);
        }
        view.push('"');
        if !overwritten.is_empty() {
            write!(
                &mut view,
                " Hidden by multi-width symbols: {:?}",
                overwritten
            )
            .unwrap();
        }
        view.push('\n');
    }
    view
}

impl TestBackend {
    pub fn new(width: u16, height: u16) -> TestBackend {
        TestBackend {
            width,
            height,
            buffer: Buffer::empty(Rect::new(0, 0, width, height)),
            cursor: false,
            pos: (0, 0),
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn resize(&mut self, width: u16, height: u16) {
        self.buffer.resize(Rect::new(0, 0, width, height));
        self.width = width;
        self.height = height;
    }

    pub fn assert_buffer(&self, expected: &Buffer) {
        assert_eq!(expected.area, self.buffer.area);
        let diff = expected.diff(&self.buffer);
        if diff.is_empty() {
            return;
        }

        let mut debug_info = String::from("Buffers are not equal");
        debug_info.push('\n');
        debug_info.push_str("Expected:");
        debug_info.push('\n');
        let expected_view = buffer_view(expected);
        debug_info.push_str(&expected_view);
        debug_info.push('\n');
        debug_info.push_str("Got:");
        debug_info.push('\n');
        let view = buffer_view(&self.buffer);
        debug_info.push_str(&view);
        debug_info.push('\n');

        debug_info.push_str("Diff:");
        debug_info.push('\n');
        let nice_diff = diff
            .iter()
            .enumerate()
            .map(|(i, (x, y, cell))| {
                let expected_cell = expected.get(*x, *y);
                format!(
                    "{}: at ({}, {}) expected {:?} got {:?}",
                    i, x, y, expected_cell, cell
                )
            })
            .collect::<Vec<String>>()
            .join("\n");
        debug_info.push_str(&nice_diff);
        panic!("{}", debug_info);
    }
}

impl Backend for TestBackend {
    fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
    where
        I: Iterator<Item = (u16, u16, &'a Cell)>,
    {
        for (x, y, c) in content {
            let cell = self.buffer.get_mut(x, y);
            *cell = c.clone();
        }
        Ok(())
    }

    fn hide_cursor(&mut self) -> Result<(), io::Error> {
        self.cursor = false;
        Ok(())
    }

    fn show_cursor(&mut self) -> Result<(), io::Error> {
        self.cursor = true;
        Ok(())
    }

    fn get_cursor(&mut self) -> Result<(u16, u16), io::Error> {
        Ok(self.pos)
    }

    fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
        self.pos = (x, y);
        Ok(())
    }

    fn clear(&mut self) -> Result<(), io::Error> {
        self.buffer.reset();
        Ok(())
    }

    fn size(&self) -> Result<Rect, io::Error> {
        Ok(Rect::new(0, 0, self.width, self.height))
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Tools for the user interface.

use error::{GrafenCliError, Result, UIErrorKind};

use std::io;
use std::io::Write;
use std::result;
use std::str::FromStr;

/// Define commands with a selection string, enum and information string.
type CommandArg<T> = (&'static str, T, &'static str);

/// These are put into a list. Unfortunately it is difficult to use
/// a const array for this since we need to send a Sized type to functions.
pub type CommandList<T> = Vec<CommandArg<T>>;

/// Finally a `CommandParser` is used to parse input strings for commands.
/// Commands are any unit type which implements `Copy`.
///
/// # Examples:
/// ```
/// # use ui::utils::{CommandList, CommandParser};
/// // enum Command { First, Second }
/// let command_list: CommandList<Command> = vec![
///     ("a", Command::First, "Select option `First` by inputting "a")
///     ("bad", Command::Second, "and `Second` by inputting "bad")
/// ];
/// let commands = CommandParser::from_list(command_list);
///
/// commands.print_menu();
/// if let Some(cmd) = commands.get_selection("bad") {
///     // Do something
/// }
/// ```
pub struct CommandParser<T: Copy> {
    commands: CommandList<T>,
}

impl<T: Copy> CommandParser<T> {
    /// Create a `CommandParser` from an input `CommandList`.
    pub fn from_list(commands: CommandList<T>) -> CommandParser<T> {
        CommandParser { commands }
    }

    /// Parse a string for a command from the input list.
    pub fn get_selection<'a>(&self, input: &'a str) -> Option<T> {
        if let Some(needle) = input.trim().to_lowercase().split_whitespace().next() {
            for &(ident, cmd, _) in self.commands.iter() {
                if needle == ident {
                    return Some(cmd);
                }
            }
        }

        None
    }

    /// Parse a string for a command from the input list and return along
    /// with the remaining string ("tail").
    pub fn get_selection_and_tail<'a>(&self, input: &'a str) -> Option<(T, String)> {
        let mut iter = input.split_whitespace();

        iter.next()
            .and_then(|needle| self.get_selection(needle))
            .and_then(|cmd| {
                let tail = iter.collect::<Vec<&str>>().join(" ");
                Some((cmd, tail))
            })
    }

    /// Print a menu of the available commands.
    pub fn print_menu(&self) {
        println!("Commands:");
        for &(ref c, _, ref info) in self.commands.iter() {
            println!("{:>4}{:4}{}", c, ' ', info);
        }
        println!("");
    }
}

/// Read and trim a string from stdin.
pub fn get_input_string(query: &'static str) -> Result<String> {
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    let mut selection = String::new();

    print!("{}: ", query);
    stdout.flush()?;
    stdin.read_line(&mut selection)?;

    Ok(selection.trim().to_string())
}

/// Parse an input string for values. Values are whitespace separated.
/// Return an Error if any value of the string could not be parsed.
pub fn parse_string<'a, T: FromStr>(tail: &'a str) -> result::Result<Vec<T>, UIErrorKind> {
    // Note to self: This uses `FromIterator` to turn a Vec<Result> into Result<Vec>. Neat!
    tail.split_whitespace()
        .map(|s| s.parse::<T>().map_err(|_| {
            UIErrorKind::BadValue(format!("'{}' is not a valid index", s))
        }))
        .collect()
}

/// Remove an item from a list. The index is parsed from the input tail and returned as a result.
pub fn remove_item<'a, T>(item_list: &mut Vec<T>, tail: &'a str) -> Result<usize> {
    let parsed = parse_string(tail)?;

    match parsed.get(0) {
        Some(&i) if i < item_list.len() => {
            item_list.remove(i);
            Ok(i)
        },
        Some(&i) => {
            Err(GrafenCliError::UIError(format!("No system with index {} exists", i)))
        },
        None => {
            Err(GrafenCliError::UIError("An index to remove is required".to_string()))
        },
    }
}

/// Swap two items of a list in-place. The indices are parsed from the input string
/// and returned as the result.
pub fn swap_items<'a, T>(item_list: &mut Vec<T>, tail: &'a str) -> Result<(usize, usize)> {
    let parsed = parse_string(tail)?;
    let max_len = item_list.len();

    match (parsed.get(0), parsed.get(1)) {
        // Assert that neither index is out of bounds with this pattern guard.
        (Some(&i), _) | (_, Some(&i)) if i >= max_len => {
            Err(GrafenCliError::UIError(format!("No system with index {} exists", i)))
        },

        (Some(&i), Some(&j)) => {
            item_list.swap(i, j);
            Ok((i, j))
        },

        _ => {
            Err(GrafenCliError::UIError("Two indices to swap order for are required".to_string()))
        },
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::error::Error;

    #[derive(Clone, Copy, Debug, PartialEq)]
    enum TestCommands {
        One,
        Two,
    }

    #[test]
    fn select_a_command() {
        let command_list = vec![
            ("a", TestCommands::One, "one"),
            ("b", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        assert_eq!(Some(TestCommands::One), commands.get_selection("a"));
        assert_eq!(Some(TestCommands::Two), commands.get_selection("b"));
        assert_eq!(None, commands.get_selection("nope"));
    }

    #[test]
    fn select_a_command_trims_and_lowercases() {
        let command_list = vec![
            ("a", TestCommands::One, "one"),
            ("b", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        assert_eq!(Some(TestCommands::One), commands.get_selection("\n\ta\n"));
        assert_eq!(Some(TestCommands::Two), commands.get_selection("  B  "));
    }

    #[test]
    fn select_a_command_checks_first_word() {
        let command_list = vec![
            ("a", TestCommands::One, "one"),
            ("b", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        assert_eq!(Some(TestCommands::One), commands.get_selection("a ignore"));
        assert_eq!(None, commands.get_selection("aignore"));
    }

    #[test]
    fn select_a_command_differentiates_between_similar() {
        let command_list = vec![
            ("at", TestCommands::One, "one"),
            ("ar", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        assert_eq!(None, commands.get_selection("a"));
        assert_eq!(Some(TestCommands::One), commands.get_selection("at"));
        assert_eq!(Some(TestCommands::Two), commands.get_selection("ar"));
    }

    #[test]
    fn select_a_command_and_tail() {
        let command_list = vec![
            ("a", TestCommands::One, "one"),
            ("b", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        let (cmd, tail) = commands.get_selection_and_tail("a and a tail").unwrap();
        assert_eq!(TestCommands::One, cmd);
        assert_eq!("and a tail", &tail);

        let (cmd, tail) = commands.get_selection_and_tail("b\twith trimming\n").unwrap();
        assert_eq!(TestCommands::Two, cmd);
        assert_eq!("with trimming", &tail);

        assert_eq!(None, commands.get_selection_and_tail(""));
        assert_eq!(None, commands.get_selection_and_tail("tail"));
    }

    #[test]
    fn parse_string_for_usize() {
        assert_eq!(vec![3, 2, 1, 100], parse_string::<usize>("3 2 1 100").unwrap());
        assert_eq!(vec![3, 2, 1, 0], parse_string::<usize>("3\t2\t1 0").unwrap());
        assert!(parse_string::<usize>("").unwrap().is_empty());
    }

    #[test]
    fn parse_string_for_usize_bad_numbers() {
        assert!(parse_string::<usize>("3a").is_err());
        assert!(parse_string::<usize>("3 1 2 a 3").is_err());
    }

    #[test]
    fn parse_and_swap_vector_order() {
        let mut vec = vec![0, 1, 2, 3];
        assert_eq!((1, 2), swap_items(&mut vec, "1 2").unwrap());
        assert_eq!(vec![0, 2, 1, 3], vec);
        assert_eq!((3, 0), swap_items(&mut vec, "3 0").unwrap());
        assert_eq!(vec![3, 2, 1, 0], vec);
        assert_eq!((1, 1), swap_items(&mut vec, "1 1").unwrap());
        assert_eq!(vec![3, 2, 1, 0], vec);
        assert_eq!((1, 2), swap_items(&mut vec, "1 2 5").unwrap()); // The extra digit is discarded
        assert_eq!(vec![3, 1, 2, 0], vec);
    }

    #[test]
    fn parse_and_swap_out_of_bounds_is_error() {
        let mut vec = vec![0, 1];
        assert!(swap_items(&mut vec, "0 2").is_err());
        assert!(swap_items(&mut vec, "2 1").is_err());
        assert!(swap_items(&mut vec, "-1 1").is_err());
        assert!(swap_items(&mut vec, "a 1").is_err());
        assert!(swap_items(&mut vec, "0 a").is_err());
    }

    #[test]
    fn parse_and_swap_error_messages_are_correct() {
        let mut vec = vec![0, 1, 2];

        // Invalid characters
        let err = swap_items(&mut vec, "a 0").unwrap_err().description().to_string();
        assert!(err.contains("'a' is not a valid index"));
        let err = swap_items(&mut vec, "-1 0").unwrap_err().description().to_string();
        assert!(err.contains("'-1' is not a valid index"));

        // Too few indices
        let err = swap_items(&mut vec, "0").unwrap_err().description().to_string();
        assert!(err.contains("Two indices to swap order for are required"));

        // First index is out of bounds
        let err = swap_items(&mut vec, "3 0").unwrap_err().description().to_string();
        assert!(err.contains("No system with index 3 exists"));

        // Second index
        let err = swap_items(&mut vec, "0 4").unwrap_err().description().to_string();
        assert!(err.contains("No system with index 4 exists"));

    }

    #[test]
    fn parse_and_remove_vector_item() {
        let mut vec = vec![1, 2, 3, 4];
        assert_eq!(1, remove_item(&mut vec, "1").unwrap());
        assert_eq!(vec![1, 3, 4], vec);
        assert_eq!(2, remove_item(&mut vec, "2").unwrap());
        assert_eq!(vec![1, 3], vec);
        assert_eq!(0, remove_item(&mut vec, "0").unwrap());
        assert_eq!(vec![3], vec);
        assert_eq!(0, remove_item(&mut vec, "0").unwrap());
        assert!(vec.is_empty());
    }

    #[test]
    fn parse_and_remove_vector_out_of_bounds_is_error() {
        let mut vec = vec![0, 1];
        let err = remove_item(&mut vec, "2").unwrap_err().description().to_string();
        assert!(err.contains("No system with index 2 exists"));
        let err = remove_item(&mut vec, "-1").unwrap_err().description().to_string();
        assert!(err.contains("'-1' is not a valid index"));
    }

    #[test]
    fn parse_and_remove_vector_without_input_is_error() {
        let mut vec = vec![1];
        let err = remove_item(&mut vec, "\t").unwrap_err().description().to_string();
        assert!(err.contains("An index to remove is required"))
    }
}
<commit_msg>Add tools for parsing an index<commit_after>//! Tools for the user interface.

use error::{GrafenCliError, Result, UIErrorKind};

use std::io;
use std::io::Write;
use std::result;
use std::str::FromStr;

/// Define commands with a selection string, enum and information string.
type CommandArg<T> = (&'static str, T, &'static str);

/// These are put into a list. Unfortunately it is difficult to use
/// a const array for this since we need to send a Sized type to functions.
pub type CommandList<T> = Vec<CommandArg<T>>;

/// Finally a `CommandParser` is used to parse input strings for commands.
/// Commands are any unit type which implements `Copy`.
///
/// # Examples:
/// ```
/// # use ui::utils::{CommandList, CommandParser};
/// // enum Command { First, Second }
/// let command_list: CommandList<Command> = vec![
///     ("a", Command::First, "Select option `First` by inputting "a")
///     ("bad", Command::Second, "and `Second` by inputting "bad")
/// ];
/// let commands = CommandParser::from_list(command_list);
///
/// commands.print_menu();
/// if let Some(cmd) = commands.get_selection("bad") {
///     // Do something
/// }
/// ```
pub struct CommandParser<T: Copy> {
    commands: CommandList<T>,
}

impl<T: Copy> CommandParser<T> {
    /// Create a `CommandParser` from an input `CommandList`.
    pub fn from_list(commands: CommandList<T>) -> CommandParser<T> {
        CommandParser { commands }
    }

    /// Parse a string for a command from the input list.
    pub fn get_selection<'a>(&self, input: &'a str) -> Option<T> {
        if let Some(needle) = input.trim().to_lowercase().split_whitespace().next() {
            for &(ident, cmd, _) in self.commands.iter() {
                if needle == ident {
                    return Some(cmd);
                }
            }
        }

        None
    }

    /// Parse a string for a command from the input list and return along
    /// with the remaining string ("tail").
    pub fn get_selection_and_tail<'a>(&self, input: &'a str) -> Option<(T, String)> {
        let mut iter = input.split_whitespace();

        iter.next()
            .and_then(|needle| self.get_selection(needle))
            .and_then(|cmd| {
                let tail = iter.collect::<Vec<&str>>().join(" ");
                Some((cmd, tail))
            })
    }

    /// Print a menu of the available commands.
    pub fn print_menu(&self) {
        println!("Commands:");
        for &(ref c, _, ref info) in self.commands.iter() {
            println!("{:>4}{:4}{}", c, ' ', info);
        }
        println!("");
    }
}

/// Read and trim a string from stdin.
pub fn get_input_string(query: &'static str) -> Result<String> {
    let stdin = io::stdin();
    let mut stdout = io::stdout();
    let mut selection = String::new();

    print!("{}: ", query);
    stdout.flush()?;
    stdin.read_line(&mut selection)?;

    Ok(selection.trim().to_string())
}

/// Parse an input string for values. Values are whitespace separated.
/// Return an Error if any value of the string could not be parsed.
pub fn parse_string<'a, T: FromStr>(tail: &'a str) -> result::Result<Vec<T>, UIErrorKind> {
    // Note to self: This uses `FromIterator` to turn a Vec<Result> into Result<Vec>. Neat!
    tail.split_whitespace()
        .map(|s| s.parse::<T>().map_err(|_| {
            UIErrorKind::BadValue(format!("'{}' is not a valid value", s))
        }))
        .collect()
}

/// Parse an input string for one value. Return an Error if a value could not be parsed.
pub fn parse_string_single<'a, T: FromStr>(tail: &'a str) -> result::Result<T, UIErrorKind> {
    let string = tail.split_whitespace().next()
        .ok_or(UIErrorKind::BadValue("Could not parse a value".to_string()))?;

    string.parse::<T>().map_err(|_| {
            UIErrorKind::BadValue(format!("'{}' is not a valid value", string))
        })
}

pub fn parse_string_for_index<T>(input: &str, list: &Vec<T>) -> Result<usize> {
    parse_string_single::<usize>(input)
        .and_then(|i| {
            if i < list.len() {
                Ok(i)
            } else {
                Err(UIErrorKind::BadValue(format!("No item with index {} exists", i)))
            }
        })
        .map_err(|err| GrafenCliError::from(err))
}

/// Remove an item from a list. The index is parsed from the input tail and returned as a result.
pub fn remove_item<'a, T>(item_list: &mut Vec<T>, tail: &'a str) -> Result<usize> {
    let index = parse_string_for_index(&tail, &item_list)?;
    item_list.remove(index);

    Ok(index)
}

/// Swap two items of a list in-place. The indices are parsed from the input string
/// and returned as the result.
pub fn swap_items<'a, T>(item_list: &mut Vec<T>, tail: &'a str) -> Result<(usize, usize)> {
    let parsed = parse_string(tail)?;
    let max_len = item_list.len();

    match (parsed.get(0), parsed.get(1)) {
        // Assert that neither index is out of bounds with this pattern guard.
        (Some(&i), _) | (_, Some(&i)) if i >= max_len => {
            Err(GrafenCliError::UIError(format!("No system with index {} exists", i)))
        },

        (Some(&i), Some(&j)) => {
            item_list.swap(i, j);
            Ok((i, j))
        },

        _ => {
            Err(GrafenCliError::UIError("Two indices to swap order for are required".to_string()))
        },
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::error::Error;

    #[derive(Clone, Copy, Debug, PartialEq)]
    enum TestCommands {
        One,
        Two,
    }

    #[test]
    fn select_a_command() {
        let command_list = vec![
            ("a", TestCommands::One, "one"),
            ("b", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        assert_eq!(Some(TestCommands::One), commands.get_selection("a"));
        assert_eq!(Some(TestCommands::Two), commands.get_selection("b"));
        assert_eq!(None, commands.get_selection("nope"));
    }

    #[test]
    fn select_a_command_trims_and_lowercases() {
        let command_list = vec![
            ("a", TestCommands::One, "one"),
            ("b", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        assert_eq!(Some(TestCommands::One), commands.get_selection("\n\ta\n"));
        assert_eq!(Some(TestCommands::Two), commands.get_selection("  B  "));
    }

    #[test]
    fn select_a_command_checks_first_word() {
        let command_list = vec![
            ("a", TestCommands::One, "one"),
            ("b", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        assert_eq!(Some(TestCommands::One), commands.get_selection("a ignore"));
        assert_eq!(None, commands.get_selection("aignore"));
    }

    #[test]
    fn select_a_command_differentiates_between_similar() {
        let command_list = vec![
            ("at", TestCommands::One, "one"),
            ("ar", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        assert_eq!(None, commands.get_selection("a"));
        assert_eq!(Some(TestCommands::One), commands.get_selection("at"));
        assert_eq!(Some(TestCommands::Two), commands.get_selection("ar"));
    }

    #[test]
    fn select_a_command_and_tail() {
        let command_list = vec![
            ("a", TestCommands::One, "one"),
            ("b", TestCommands::Two, "two")
        ];
        let commands = CommandParser::from_list(command_list);

        let (cmd, tail) = commands.get_selection_and_tail("a and a tail").unwrap();
        assert_eq!(TestCommands::One, cmd);
        assert_eq!("and a tail", &tail);

        let (cmd, tail) = commands.get_selection_and_tail("b\twith trimming\n").unwrap();
        assert_eq!(TestCommands::Two, cmd);
        assert_eq!("with trimming", &tail);

        assert_eq!(None, commands.get_selection_and_tail(""));
        assert_eq!(None, commands.get_selection_and_tail("tail"));
    }

    #[test]
    fn parse_string_for_usize() {
        assert_eq!(vec![3, 2, 1, 100], parse_string::<usize>("3 2 1 100").unwrap());
        assert_eq!(vec![3, 2, 1, 0], parse_string::<usize>("3\t2\t1 0").unwrap());
        assert!(parse_string::<usize>("").unwrap().is_empty());
    }

    #[test]
    fn parse_string_for_usize_bad_numbers() {
        assert!(parse_string::<usize>("3a").is_err());
        assert!(parse_string::<usize>("3 1 2 a 3").is_err());
    }

    #[test]
    fn parse_string_for_one_value() {
        assert_eq!(0, parse_string_single::<usize>("0").unwrap());
        assert_eq!(0, parse_string_single::<usize>("\t0\n").unwrap());
        assert_eq!(0, parse_string_single::<usize>("0 1").unwrap());
        assert!(parse_string_single::<usize>("a").is_err());
    }

    #[test]
    fn parse_and_swap_vector_order() {
        let mut vec = vec![0, 1, 2, 3];
        assert_eq!((1, 2), swap_items(&mut vec, "1 2").unwrap());
        assert_eq!(vec![0, 2, 1, 3], vec);
        assert_eq!((3, 0), swap_items(&mut vec, "3 0").unwrap());
        assert_eq!(vec![3, 2, 1, 0], vec);
        assert_eq!((1, 1), swap_items(&mut vec, "1 1").unwrap());
        assert_eq!(vec![3, 2, 1, 0], vec);
        assert_eq!((1, 2), swap_items(&mut vec, "1 2 5").unwrap()); // The extra digit is discarded
        assert_eq!(vec![3, 1, 2, 0], vec);
    }

    #[test]
    fn parse_and_swap_out_of_bounds_is_error() {
        let mut vec = vec![0, 1];
        assert!(swap_items(&mut vec, "0 2").is_err());
        assert!(swap_items(&mut vec, "2 1").is_err());
        assert!(swap_items(&mut vec, "-1 1").is_err());
        assert!(swap_items(&mut vec, "a 1").is_err());
        assert!(swap_items(&mut vec, "0 a").is_err());
    }

    #[test]
    fn parse_and_swap_error_messages_are_correct() {
        let mut vec = vec![0, 1, 2];

        // Invalid characters
        let err = swap_items(&mut vec, "a 0").unwrap_err().description().to_string();
        assert!(err.contains("'a' is not a valid value"));
        let err = swap_items(&mut vec, "-1 0").unwrap_err().description().to_string();
        assert!(err.contains("'-1' is not a valid value"));

        // Too few indices
        let err = swap_items(&mut vec, "0").unwrap_err().description().to_string();
        assert!(err.contains("Two indices to swap order for are required"));

        // First index is out of bounds
        let err = swap_items(&mut vec, "3 0").unwrap_err().description().to_string();
        assert!(err.contains("No system with index 3 exists"));

        // Second index
        let err = swap_items(&mut vec, "0 4").unwrap_err().description().to_string();
        assert!(err.contains("No system with index 4 exists"));

    }

    #[test]
    fn parse_and_remove_vector_item() {
        let mut vec = vec![1, 2, 3, 4];
        assert_eq!(1, remove_item(&mut vec, "1").unwrap());
        assert_eq!(vec![1, 3, 4], vec);
        assert_eq!(2, remove_item(&mut vec, "2").unwrap());
        assert_eq!(vec![1, 3], vec);
        assert_eq!(0, remove_item(&mut vec, "0").unwrap());
        assert_eq!(vec![3], vec);
        assert_eq!(0, remove_item(&mut vec, "0").unwrap());
        assert!(vec.is_empty());
    }

    #[test]
    fn parse_and_remove_vector_out_of_bounds_is_error() {
        let mut vec = vec![0, 1];
        let err = remove_item(&mut vec, "2").unwrap_err().description().to_string();
        assert!(err.contains("No item with index 2 exists"));
        let err = remove_item(&mut vec, "-1").unwrap_err().description().to_string();
        assert!(err.contains("'-1' is not a valid value"));
    }

    #[test]
    fn parse_and_remove_vector_without_input_is_error() {
        let mut vec = vec![1];
        assert!(remove_item(&mut vec, "\t").is_err());
    }

    #[test]
    fn parse_index_inside_vector() {
        assert_eq!(2, parse_string_for_index("2", &vec![0, 1, 2]).unwrap());
        assert_eq!(0, parse_string_for_index("0", &vec![2, 1, 0]).unwrap());
        assert!(parse_string_for_index("1", &vec![0]).is_err());
        assert!(parse_string_for_index("a", &vec![0]).is_err());
        assert!(parse_string_for_index("\n", &vec![0]).is_err());
    }
}
<|endoftext|>


<commit_before>//! This module defines the metadata on devices and services.
//!
//! Note that all the data structures in this module represent
//! snapshots of subsets of the devices available. None of these data
//! structures are live, so there is always the possibility that
//! devices may have been added or removed from the FoxBox by the time
//! these data structures are read.

use values::*;
use util::Id;

use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

/// A marker for Id.
/// Only useful for writing `Id<ServiceId>`.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Hash, Eq)]
pub struct ServiceId;

/// Metadata on a service. A service is a device or collection of devices
/// that may offer services. The FoxBox itself a service offering
/// services such as a clock, communication with the user through her
/// smart devices, etc.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Service {
    /// Tags describing the service.
    ///
    /// These tags can be set by the user, adapters or
    /// applications. They are used by applications to find services and
    /// services.
    ///
    /// For instance, a user may set tag "entrance" to all services
    /// placed in the entrance of his house, or a tag "blue" to a service
    /// controlling blue lights. An adapter may set tags "plugged" or
    /// "battery" to devices that respectively depend on a plugged
    /// power source or on a battery.
    pub tags: Vec<String>,

    /// An id unique to this service.
    pub id: Id<ServiceId>,

    /// Channels connected directly to this service.
    pub getters: Vec<Channel<Getter>>,
    pub setters: Vec<Channel<Setter>>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

/// The kind of the service, i.e. a strongly-typed description of
/// _what_ the service can do. Used both for locating services
/// (e.g. "I need a clock" or "I need something that can provide
/// pictures") and for determining the data structure that these
/// services can provide or consume.
///
/// A number of service kinds are standardized, and provided as a set
/// of strongly-typed enum constructors. It is clear, however, that
/// many devices will offer services that cannot be described by
/// pre-existing constructors. For this purpose, this enumeration
/// offers a constructor `Extension`, designed to describe novel
/// services.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ChannelKind {
    ///
    /// # No payload
    ///

    /// The service is ready. Used for instance once a countdown has
    /// reached completion.
    Ready,

    ///
    /// # Boolean
    ///

    /// The service is used to detect or decide whether some device
    /// is on or off.
    OnOff,

    /// The service is used to detect or decide whether some device
    /// is open or closed.
    OpenClosed,

    ///
    /// # Time
    ///

    /// The service is used to read or set the current absolute time.
    /// Used for instance to wait until a specific time and day before
    /// triggering an action, or to set the appropriate time on a new
    /// device.
    CurrentTime,

    /// The service is used to read or set the current time of day.
    /// Used for instance to trigger an action at a specific hour
    /// every day.
    CurrentTimeOfDay,

    /// The service is part of a countdown. This is the time
    /// remaining until the countdown is elapsed.
    RemainingTime,

    ///
    /// # Temperature
    ///

    Thermostat,
    ActualTemperature,

    /// TODO: Add more

    /// An operation of a kind that has not been standardized yet.
    Extension {
        /// The vendor. Used for namespacing purposes, to avoid
        /// confusing two incompatible extensions with similar
        /// names. For instance, "foxlink@mozilla.com".
        vendor: String,

        /// Identification of the adapter introducing this operation.
        /// Designed to aid with tracing and debugging.
        adapter: String,

        /// A string describing the nature of the value, designed to
        /// let applications discover the devices.
        ///
        /// Examples: `"GroundHumidity"`.
        kind: String,

        /// The data type of the value.
        typ: Type
    }
}

impl ChannelKind {
    /// Get the type of values used to communicate with this service.
    pub fn get_type(&self) -> Type {
        use self::ChannelKind::*;
        use values::Type::*;
        match *self {
            Ready => Unit,
            OnOff | OpenClosed => Bool,
            CurrentTime => TimeStamp,
            CurrentTimeOfDay | RemainingTime => Duration,
            Thermostat | ActualTemperature => Temperature,
            Extension { ref typ, ..} => typ.clone(),
        }
    }
}

/// A getter operation available on a channel.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Getter {
    /// The kind of value that can be obtained from this channel.
    pub kind: ChannelKind,

    /// If `Some(duration)`, this channel can be polled, i.e. it
    /// will respond when the FoxBox requests the latest value.
    /// Parameter `duration` indicates the smallest interval
    /// between two updates.
    ///
    /// Otherwise, the channel cannot be polled and will push
    /// data to the FoxBox when it is available.
    ///
    /// # Examples
    ///
    /// - Long-running pollution or humidity sensors typically
    ///   do not accept requests and rather send batches of
    ///   data every 24h.
    #[serde(default)]
    pub poll: Option<ValDuration>,

    /// If `Some(duration)`, this channel can send the data to
    /// the FoxBox whenever it is updated. Parameter `duration`
    /// indicates the smallest interval between two updates.
    ///
    /// Otherwise, the channel cannot send data to the FoxBox
    /// and needs to be polled.
    #[serde(default)]
    pub trigger: Option<ValDuration>,

    /// If `true`, this channel supports watching for specific
    /// changes.
    #[serde(default)]
    pub watch: bool,

    /// Date at which the latest value was received, whether through
    /// polling or through a trigger.
    pub updated: Option<TimeStamp>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl IOMechanism for Getter {
}

/// An setter operation available on an channel.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Setter {
    /// The kind of value that can be sent to this channel.
    pub kind: ChannelKind,

    /// If `Some(duration)`, this channel supports pushing,
    /// i.e. the FoxBox can send values.
    #[serde(default)]
    pub push: Option<ValDuration>,

    /// Date at which the latest value was sent to the channel.
    #[serde(default)]
    pub updated: Option<TimeStamp>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}
impl IOMechanism for Setter {
}

/// An channel represents a single place where data can enter or
/// leave a device. Note that channels support either a single kind
/// of getter or a single kind of setter. Devices that support both
/// getters or setters, or several kinds of getters, or several kinds of
/// setters, are represented as services containing several channels.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Channel<IO> where IO: IOMechanism {
    /// Tags describing the channel.
    ///
    /// These tags can be set by the user, adapters or
    /// applications. They are used to regroup channels for rules.
    ///
    /// For instance "entrance".
    #[serde(default)]
    pub tags: Vec<String>,

    /// An id unique to this channel.
    pub id: Id<IO>,

    /// The service owning this channel.
    pub service: Id<ServiceId>,

    /// The update mechanism for this channel.
    pub mechanism: IO,

    /// The last time the device was seen.
    #[serde(default)]
    pub last_seen: Option<TimeStamp>,

    /// Make sure that we can't instantiate from another crate.
    #[serde(default, skip_serializing)]
    private: (),
}

/// The communication mechanism used by the channel.
pub trait IOMechanism: Deserialize + Serialize {
}

<commit_msg>[fxbox/taxonomy] Mmmmhhh... looks like these `private` are not very useful after all<commit_after>//! This module defines the metadata on devices and services.
//!
//! Note that all the data structures in this module represent
//! snapshots of subsets of the devices available. None of these data
//! structures are live, so there is always the possibility that
//! devices may have been added or removed from the FoxBox by the time
//! these data structures are read.

use values::*;
use util::Id;

use serde::ser::{Serialize, Serializer};
use serde::de::{Deserialize, Deserializer, Error};

/// A marker for Id.
/// Only useful for writing `Id<ServiceId>`.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Hash, Eq)]
pub struct ServiceId;

/// Metadata on a service. A service is a device or collection of devices
/// that may offer services. The FoxBox itself a service offering
/// services such as a clock, communication with the user through her
/// smart devices, etc.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Service {
    /// Tags describing the service.
    ///
    /// These tags can be set by the user, adapters or
    /// applications. They are used by applications to find services and
    /// services.
    ///
    /// For instance, a user may set tag "entrance" to all services
    /// placed in the entrance of his house, or a tag "blue" to a service
    /// controlling blue lights. An adapter may set tags "plugged" or
    /// "battery" to devices that respectively depend on a plugged
    /// power source or on a battery.
    pub tags: Vec<String>,

    /// An id unique to this service.
    pub id: Id<ServiceId>,

    /// Channels connected directly to this service.
    pub getters: Vec<Channel<Getter>>,
    pub setters: Vec<Channel<Setter>>,
}

/// The kind of the service, i.e. a strongly-typed description of
/// _what_ the service can do. Used both for locating services
/// (e.g. "I need a clock" or "I need something that can provide
/// pictures") and for determining the data structure that these
/// services can provide or consume.
///
/// A number of service kinds are standardized, and provided as a set
/// of strongly-typed enum constructors. It is clear, however, that
/// many devices will offer services that cannot be described by
/// pre-existing constructors. For this purpose, this enumeration
/// offers a constructor `Extension`, designed to describe novel
/// services.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ChannelKind {
    ///
    /// # No payload
    ///

    /// The service is ready. Used for instance once a countdown has
    /// reached completion.
    Ready,

    ///
    /// # Boolean
    ///

    /// The service is used to detect or decide whether some device
    /// is on or off.
    OnOff,

    /// The service is used to detect or decide whether some device
    /// is open or closed.
    OpenClosed,

    ///
    /// # Time
    ///

    /// The service is used to read or set the current absolute time.
    /// Used for instance to wait until a specific time and day before
    /// triggering an action, or to set the appropriate time on a new
    /// device.
    CurrentTime,

    /// The service is used to read or set the current time of day.
    /// Used for instance to trigger an action at a specific hour
    /// every day.
    CurrentTimeOfDay,

    /// The service is part of a countdown. This is the time
    /// remaining until the countdown is elapsed.
    RemainingTime,

    ///
    /// # Temperature
    ///

    Thermostat,
    ActualTemperature,

    /// TODO: Add more

    /// An operation of a kind that has not been standardized yet.
    Extension {
        /// The vendor. Used for namespacing purposes, to avoid
        /// confusing two incompatible extensions with similar
        /// names. For instance, "foxlink@mozilla.com".
        vendor: String,

        /// Identification of the adapter introducing this operation.
        /// Designed to aid with tracing and debugging.
        adapter: String,

        /// A string describing the nature of the value, designed to
        /// let applications discover the devices.
        ///
        /// Examples: `"GroundHumidity"`.
        kind: String,

        /// The data type of the value.
        typ: Type
    }
}

impl ChannelKind {
    /// Get the type of values used to communicate with this service.
    pub fn get_type(&self) -> Type {
        use self::ChannelKind::*;
        use values::Type::*;
        match *self {
            Ready => Unit,
            OnOff | OpenClosed => Bool,
            CurrentTime => TimeStamp,
            CurrentTimeOfDay | RemainingTime => Duration,
            Thermostat | ActualTemperature => Temperature,
            Extension { ref typ, ..} => typ.clone(),
        }
    }
}

/// A getter operation available on a channel.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Getter {
    /// The kind of value that can be obtained from this channel.
    pub kind: ChannelKind,

    /// If `Some(duration)`, this channel can be polled, i.e. it
    /// will respond when the FoxBox requests the latest value.
    /// Parameter `duration` indicates the smallest interval
    /// between two updates.
    ///
    /// Otherwise, the channel cannot be polled and will push
    /// data to the FoxBox when it is available.
    ///
    /// # Examples
    ///
    /// - Long-running pollution or humidity sensors typically
    ///   do not accept requests and rather send batches of
    ///   data every 24h.
    #[serde(default)]
    pub poll: Option<ValDuration>,

    /// If `Some(duration)`, this channel can send the data to
    /// the FoxBox whenever it is updated. Parameter `duration`
    /// indicates the smallest interval between two updates.
    ///
    /// Otherwise, the channel cannot send data to the FoxBox
    /// and needs to be polled.
    #[serde(default)]
    pub trigger: Option<ValDuration>,

    /// If `true`, this channel supports watching for specific
    /// changes.
    #[serde(default)]
    pub watch: bool,

    /// Date at which the latest value was received, whether through
    /// polling or through a trigger.
    pub updated: Option<TimeStamp>,
}
impl IOMechanism for Getter {
}

/// An setter operation available on an channel.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Setter {
    /// The kind of value that can be sent to this channel.
    pub kind: ChannelKind,

    /// If `Some(duration)`, this channel supports pushing,
    /// i.e. the FoxBox can send values.
    #[serde(default)]
    pub push: Option<ValDuration>,

    /// Date at which the latest value was sent to the channel.
    #[serde(default)]
    pub updated: Option<TimeStamp>,
}
impl IOMechanism for Setter {
}

/// An channel represents a single place where data can enter or
/// leave a device. Note that channels support either a single kind
/// of getter or a single kind of setter. Devices that support both
/// getters or setters, or several kinds of getters, or several kinds of
/// setters, are represented as services containing several channels.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Channel<IO> where IO: IOMechanism {
    /// Tags describing the channel.
    ///
    /// These tags can be set by the user, adapters or
    /// applications. They are used to regroup channels for rules.
    ///
    /// For instance "entrance".
    #[serde(default)]
    pub tags: Vec<String>,

    /// An id unique to this channel.
    pub id: Id<IO>,

    /// The service owning this channel.
    pub service: Id<ServiceId>,

    /// The update mechanism for this channel.
    pub mechanism: IO,

    /// The last time the device was seen.
    #[serde(default)]
    pub last_seen: Option<TimeStamp>,
}

/// The communication mechanism used by the channel.
pub trait IOMechanism: Deserialize + Serialize {
}

<|endoftext|>


<commit_before>extern crate sdl2;
extern crate sdl2_ttf;

use std::env;
use std::path::Path;

use sdl2::*;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

static SCREEN_WIDTH : i32 = 800;
static SCREEN_HEIGHT : i32 = 600;

// fail when error
macro_rules! trying(
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("failed: {}", e) })
);

// hadle the annoying Rect i32
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        sdl2::rect::Rect::new($x as i32, $y as i32, $w as u32, $h as u32)
    )
);

fn run(filename: &Path) {
    let sdl_context = sdl2::init().unwrap();
    let video_subsys = sdl_context.video().unwrap();
    sdl2_ttf::init();

    let window = video_subsys.window("rust-sdl2 demo: Video", 800, 600)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    // Load a font
    let font = trying!(sdl2_ttf::Font::from_file(filename, 128));

    // render a surface, and convert it to a texture bound to the renderer
    let surface = trying!(font.render_str_blended("Hello Rust!", sdl2::pixels::Color::RGBA(255, 0, 0, 255)));
    let mut texture = trying!(renderer.create_texture_from_surface(&surface));

    renderer.set_draw_color(sdl2::pixels::Color::RGBA(195, 217, 255, 255));
    renderer.clear();

    let (w, h) = { let q = texture.query(); (q.width, q.height) };

    renderer.copy(&mut texture, None, Some(rect!((SCREEN_WIDTH as u32 - w)/ 2, (SCREEN_HEIGHT as u32 - h)/ 2, w, h)).unwrap().unwrap());

    renderer.present();

    'mainloop: loop {
        for event in sdl_context.event_pump().unwrap().poll_iter() {
            match event {
                Event::Quit{..} => break 'mainloop,
                Event::KeyDown {keycode: Some(Keycode::Escape), ..} => break 'mainloop,
                _ => {}
            }
        }
    }

    sdl2_ttf::quit();
}

fn main() {
    let args: Vec<_> = env::args().collect();

    println!("linked sdl2_ttf: {}", sdl2_ttf::get_linked_version());

    if args.len() < 2 {
        println!("Usage: ./demo font.[ttf|ttc|fon]")
    } else {
        let path: &Path = Path::new(&args[1]);
        run(path);
    }
}
<commit_msg>No more integer overflow on font centering in the demo<commit_after>extern crate sdl2;
extern crate sdl2_ttf;

use std::env;
use std::path::Path;

use sdl2::*;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::rect::Rect;
use sdl2::render::TextureQuery;
use sdl2::pixels::Color;

static SCREEN_WIDTH : u32 = 800;
static SCREEN_HEIGHT : u32 = 600;

// fail when error
macro_rules! trying(
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => panic!("failed: {}", e) })
);

// hadle the annoying Rect i32
macro_rules! rect(
    ($x:expr, $y:expr, $w:expr, $h:expr) => (
        Rect::new_unwrap($x as i32, $y as i32, $w as u32, $h as u32)
    )
);

// Scale fonts to a reasonable size when they're too big (though they might look less smooth)
fn get_centered_rect(rect_width: u32, rect_height: u32, cons_width: u32, cons_height: u32) -> Rect {
    let wr = rect_width as f32 / cons_width as f32;
    let hr = rect_height as f32 / cons_height as f32;

    let (w, h) = if wr > 1f32 || hr > 1f32 {
        if wr > hr {
            println!("Scaling down! The text will look worse!");
            let h = (rect_height as f32 / wr) as i32;
            (cons_width as i32, h)
        } else {
            println!("Scaling down! The text will look worse!");
            let w = (rect_width as f32 / hr) as i32;
            (w, cons_height as i32)
        }
    } else {
        (rect_width as i32, rect_height as i32)
    };

    let cx = (SCREEN_WIDTH as i32 - w) / 2;
    let cy = (SCREEN_HEIGHT as i32 - h) / 2;
    rect!(cx, cy, w, h)
}

fn run(filename: &Path) {
    let sdl_context = sdl2::init().unwrap();
    let video_subsys = sdl_context.video().unwrap();
    sdl2_ttf::init();

    let window = video_subsys.window("rust-sdl2 demo: Video", SCREEN_WIDTH, SCREEN_HEIGHT)
        .position_centered()
        .opengl()
        .build()
        .unwrap();

    let mut renderer = window.renderer().build().unwrap();

    // Load a font
    let font = trying!(sdl2_ttf::Font::from_file(filename, 128));

    // render a surface, and convert it to a texture bound to the renderer
    let surface = trying!(font.render_str_blended("Hello Rust!", Color::RGBA(255, 0, 0, 255)));
    let mut texture = trying!(renderer.create_texture_from_surface(&surface));

    renderer.set_draw_color(Color::RGBA(195, 217, 255, 255));
    renderer.clear();

    let TextureQuery { width, height, .. } = texture.query();

    // If the example text is too big for the screen, downscale it (and center irregardless)
    let padding = 64;
    let target = get_centered_rect(width, height, SCREEN_WIDTH - padding, SCREEN_HEIGHT - padding);

    renderer.copy(&mut texture, None, Some(target));
    renderer.present();

    'mainloop: loop {
        for event in sdl_context.event_pump().unwrap().poll_iter() {
            match event {
                Event::Quit{..} => break 'mainloop,
                Event::KeyDown {keycode: Some(Keycode::Escape), ..} => break 'mainloop,
                _ => {}
            }
        }
    }

    sdl2_ttf::quit();
}

fn main() {
    let args: Vec<_> = env::args().collect();

    println!("linked sdl2_ttf: {}", sdl2_ttf::get_linked_version());

    if args.len() < 2 {
        println!("Usage: ./demo font.[ttf|ttc|fon]")
    } else {
        let path: &Path = Path::new(&args[1]);
        run(path);
    }
}
<|endoftext|>


<commit_before>extern crate cursive;

use cursive::{Cursive};
use cursive::view::{Dialog,IdView,EditView,Selector,TextView};

fn main() {
    let mut siv = Cursive::new();

    // Create a dialog with an edit text and a button.
    siv.add_layer(Dialog::new(IdView::new("edit", EditView::new().min_length(20)))
                  .title("Enter your name")
                  .button("Ok", |s| {
                      // When the button is clicked, read the text and print it in a new dialog.
                      let content = {
                          let name = s.find::<EditView>(&Selector::Id("edit")).unwrap().get_content();
                          format!("Hello {}", name)
                      };
                      s.pop_layer();
                      s.add_layer(Dialog::new(TextView::new(&content))
                                  .button("Quit", |s| s.quit()));
                  }));

    siv.run();
}
<commit_msg>Update edit example<commit_after>extern crate cursive;

use cursive::{Cursive};
use cursive::view::{Dialog,IdView,EditView,Selector,TextView};

fn main() {
    let mut siv = Cursive::new();

    // Create a dialog with an edit text and a button.
    siv.add_layer(Dialog::new(IdView::new("edit", EditView::new().min_length(20)))
                  .padding((1,1,1,0))
                  .title("Enter your name")
                  .button("Ok", |s| {
                      // When the button is clicked, read the text and print it in a new dialog.
                      let content = {
                          let name = s.find::<EditView>(&Selector::Id("edit")).unwrap().get_content();
                          format!("Hello {}!", name)
                      };
                      s.pop_layer();
                      s.add_layer(Dialog::new(TextView::new(&content))
                                  .button("Quit", |s| s.quit()));
                  }));

    siv.run();
}
<|endoftext|>


<commit_before>extern crate cursive;

use cursive::{Cursive, Printer};
use cursive::vec::Vec2;
use cursive::traits::*;

use std::sync::mpsc;
use std::thread;
use std::time::Duration;
use std::iter::Chain;
use std::slice::Iter;

fn main() {
    // As usual, create the Cursive root
    let mut siv = Cursive::new();

    // We want to refresh the page even when no input is given.
    siv.set_fps(10);
    siv.add_global_callback('q', |s| s.quit());

    // A channel will communicate data from our running task to the UI.
    let (tx, rx) = mpsc::channel();

    // Generate data in a separate thread.
    thread::spawn(move || {
        generate_logs(&tx);
    });

    // And sets the view to read from the other end of the channel.
    siv.add_layer(BufferView::new(200, rx).full_screen());

    siv.run();
}

// We will only simulate log generation here.
// In real life, this may come from a running task, a separate process, ...
fn generate_logs(tx: &mpsc::Sender<String>) {
    let mut i = 1;
    loop {
        let line = format!("Interesting log line {}", i);
        i += 1;
        // The send will fail when the other side is dropped.
        // (When the application ends).
        if tx.send(line).is_err() {
            return;
        }
        thread::sleep(Duration::from_millis(30));
    }
}

// Let's define a buffer view, that shows the last lines from a stream.
struct BufferView {
    // We will emulate a ring buffer
    buffer: Vec<String>,
    // Current position in the buffer
    pos: usize,
    // Receiving end of the stream
    rx: mpsc::Receiver<String>,
}

impl BufferView {
    // Creates a new view with the given buffer size
    fn new(size: usize, rx: mpsc::Receiver<String>) -> Self {
        BufferView {
            rx: rx,
            buffer: (0..size).map(|_| String::new()).collect(),
            pos: 0,
        }
    }

    // Reads available data from the stream into the buffer
    fn update(&mut self) {
        let mut i = self.pos;
        while let Ok(line) = self.rx.try_recv() {
            self.buffer[i] = line;
            i = (i + 1) % self.buffer.len();
        }
        self.pos = i;
    }

    // Chain together the two parts of the buffer to appear as a circular one.
    // TODO: Use `-> impl Iterator<Item=String>`...
    fn ring(&self) -> Chain<Iter<String>, Iter<String>> {
        // The main buffer is "circular" starting at self.pos
        // So we chain the two parts as one
        self.buffer[self.pos..].iter().chain(self.buffer[..self.pos].iter())
    }
}

impl View for BufferView {
    fn layout(&mut self, _: Vec2) {
        // Before drawing, we'll want to update the buffer
        self.update();
    }

    fn draw(&self, printer: &Printer) {

        // If the buffer is large, we'll discard the beginning and keep the end.
        // If the buffer is too small, only print a part of it with an offset.
        let (discard, offset) = if self.buffer.len() >
                                   printer.size.y as usize {
            (self.buffer.len() - printer.size.y as usize, 0)
        } else {
            (0, printer.size.y - self.buffer.len())
        };

        for (i, line) in self.ring().skip(discard).enumerate() {
            printer.print((0, offset + i), line);
        }
    }
}
<commit_msg>Update examples/logs.rs to use VecDeque<commit_after>extern crate cursive;

use cursive::{Cursive, Printer};
use cursive::traits::*;
use cursive::vec::Vec2;
use std::collections::VecDeque;
use std::iter::Chain;
use std::slice::Iter;

use std::sync::mpsc;
use std::thread;
use std::time::Duration;

fn main() {
    // As usual, create the Cursive root
    let mut siv = Cursive::new();

    // We want to refresh the page even when no input is given.
    siv.set_fps(10);
    siv.add_global_callback('q', |s| s.quit());

    // A channel will communicate data from our running task to the UI.
    let (tx, rx) = mpsc::channel();

    // Generate data in a separate thread.
    thread::spawn(move || { generate_logs(&tx); });

    // And sets the view to read from the other end of the channel.
    siv.add_layer(BufferView::new(200, rx).full_screen());

    siv.run();
}

// We will only simulate log generation here.
// In real life, this may come from a running task, a separate process, ...
fn generate_logs(tx: &mpsc::Sender<String>) {
    let mut i = 1;
    loop {
        let line = format!("Interesting log line {}", i);
        i += 1;
        // The send will fail when the other side is dropped.
        // (When the application ends).
        if tx.send(line).is_err() {
            return;
        }
        thread::sleep(Duration::from_millis(30));
    }
}

// Let's define a buffer view, that shows the last lines from a stream.
struct BufferView {
    // We'll use a ring buffer
    buffer: VecDeque<String>,
    // Receiving end of the stream
    rx: mpsc::Receiver<String>,
}

impl BufferView {
    // Creates a new view with the given buffer size
    fn new(size: usize, rx: mpsc::Receiver<String>) -> Self {
        let mut buffer = VecDeque::new();
        buffer.resize(size, String::new());
        BufferView {
            rx: rx,
            buffer: buffer,
        }
    }

    // Reads available data from the stream into the buffer
    fn update(&mut self) {
        // Add each available line to the end of the buffer.
        while let Ok(line) = self.rx.try_recv() {
            self.buffer.push_back(line);
            self.buffer.pop_front();
        }
    }
}

impl View for BufferView {
    fn layout(&mut self, _: Vec2) {
        // Before drawing, we'll want to update the buffer
        self.update();
    }

    fn draw(&self, printer: &Printer) {
        // Print the end of the buffer
        for (i, line) in self.buffer
                .iter()
                .rev()
                .take(printer.size.y)
                .enumerate() {
            printer.print((0, printer.size.y - 1 - i), line);
        }
    }
}
<|endoftext|>


<commit_before>extern crate gurobi;

fn main() {
  // the name of log file must not be 'mip1.log' (why?)
  let logfilename = "mip_1.log";
  let env = gurobi::Env::new(logfilename).unwrap();
  assert_eq!(env.get_str_param("LogFile").unwrap(), logfilename);

  let mut model = env.new_model("mip1", gurobi::Maximize).unwrap();

  model.add_bvar("x", 1.0).unwrap();
  model.add_bvar("y", 1.0).unwrap();
  model.add_bvar("z", 2.0).unwrap();
  model.update().unwrap();

  model.add_constr("c0", &[0, 1, 2], &[1., 2., 3.], gurobi::Less, 4.0)
    .unwrap();
  model.add_constr("c1", &[0, 1], &[1., 1.], gurobi::Greater, 1.0).unwrap();

  model.optimize().unwrap();

  // fixes the model
  let model = model;

  let status = model.get_int(gurobi::IntAttr::Status).unwrap();
  assert_eq!(status, 2);

  let objval = model.get_double(gurobi::DoubleAttr::ObjVal).unwrap();
  assert!((objval - 1.0).abs() < 1e-12);

  let xval = model.get_double_array(gurobi::DoubleAttr::X, 0, 3).unwrap();
  assert_eq!(xval[0], 0.0);
  assert_eq!(xval[1], 1.0);
  assert_eq!(xval[2], 0.0);

  model.write("mip1.lp").unwrap();
}
<commit_msg>fix example<commit_after>extern crate gurobi;

fn main() {
  // the name of log file must not be 'mip1.log' (why?)
  let logfilename = "mip_1.log";
  let env = gurobi::Env::new(logfilename).unwrap();
  assert_eq!(env.get_str_param("LogFile").unwrap(), logfilename);

  let mut model = env.new_model("mip1", gurobi::Maximize).unwrap();

  model.add_bvar("x", 1.0).unwrap();
  model.add_bvar("y", 1.0).unwrap();
  model.add_bvar("z", 2.0).unwrap();
  model.update().unwrap();

  model.add_constr("c0", &[0, 1, 2], &[1., 2., 3.], gurobi::Less, 4.0)
    .unwrap();
  model.add_constr("c1", &[0, 1], &[1., 1.], gurobi::Greater, 1.0).unwrap();

  model.optimize().unwrap();

  // fixes the model
  let model = model;

  let status = model.get_int(gurobi::IntAttr::Status).unwrap();
  assert_eq!(status, 2);

  let objval = model.get_double(gurobi::DoubleAttr::ObjVal).unwrap();
  assert!((objval - 1.0).abs() < 1e-12);

  let numvars = model.get_int(gurobi::IntAttr::NumVars).unwrap() as usize;
  assert_eq!(numvars, 3);

  let xval = model.get_double_array(gurobi::DoubleAttr::X, 0, numvars).unwrap();
  assert_eq!(xval[0], 0.0);
  assert_eq!(xval[1], 1.0);
  assert_eq!(xval[2], 0.0);

  model.write("mip1.lp").unwrap();
}
<|endoftext|>


<commit_before>extern crate rsoundio;
extern crate rb;

use rb::{RB, SpscRb, RbProducer, RbConsumer};
use std::f32::consts::PI as PI32;
use std::thread;
use std::time::Duration;

fn main() {
    let rb = SpscRb::new(4096);
    let (producer, consumer) = (rb.producer(), rb.consumer());
    // create an audio context
    let mut sio = rsoundio::SoundIo::default();
    sio.set_name("rsoundio-example").unwrap();
    // connect to the default audio backend
    sio.connect().unwrap();
    let backend = sio.current_backend().unwrap();
    println!("Connected to backend: {}", backend);
    sio.flush_events();
    // get default output device
    let dev = sio.default_output_device().unwrap();
    assert!(dev.probe_error().is_none());
    println!("Using output device: {}", dev);
    // create output stream
    let mut out = dev.create_outstream().unwrap();
    assert!(out.set_name("sine").is_ok());
    out.set_format(rsoundio::SioFormat::Float32LE).unwrap();
    println!("Output format: {}", out.format().unwrap());

    thread::spawn(move || {
        const LEN: usize = 1024;
        let mut pos = 0;
        loop {
            const F: f32 = 440.0;
            const W: f32 = 2.0 * F * PI32 / 48_000.0;
            const A: f32 = 0.6;
            const CYCLE: usize = (48_000f32 / F) as usize;

            let samples: Vec<f32> = (0..LEN)
                                        .map(|i| (W * (i + pos) as f32).sin() * A)
                                        .collect();
            producer.write_blocking(&samples).unwrap();
            pos = (pos + LEN) % CYCLE;
        }
    });

    // register callbacks
    out.register_write_callback(|out: rsoundio::OutStream,
                                 min_frame_count: u32,
                                 max_frame_count: u32| {
        const BUF_SIZE: usize = 2048;
        let mut data = vec![0.0f32; BUF_SIZE];
        let len = if backend != rsoundio::SioBackend::PulseAudio {
            ::std::cmp::min(BUF_SIZE, max_frame_count as usize)
        } else {
            BUF_SIZE
        };
        consumer.read_blocking(&mut data[..len]);
        let frames = vec![data[..len].iter().cloned().collect(),
                          data[..len].iter().cloned().collect()];
        out.write_stream_f32(min_frame_count, &frames).unwrap();
    });
    out.register_underflow_callback(|out: rsoundio::OutStream| {
        println!("Underflow in {} occured!", out.name().unwrap())
    });
    out.register_error_callback(|out: rsoundio::OutStream, err: rsoundio::SioError| {
        println!("{} error: {}", out.name().unwrap(), err)
    });

    // open output stream
    out.open().unwrap();
    let sr = out.sample_rate();
    println!("Sample rate: {}", sr);

    match out.latency() {
        Ok(latency) => println!("SW latency: {}", latency),
        Err(err) => println!("err: {}", err),
    }
    let layout = out.layout();
    println!("Output channel layout: {}", layout);
    // start audio output (now the `write_callback` will be called periodically)
    out.start().unwrap();
    thread::sleep(Duration::new(3, 0));
    println!("Pause for 1s");
    out.pause();
    thread::sleep(Duration::new(1, 0));
    println!("Unpausing");
    out.unpause();
    thread::sleep(Duration::new(3, 0));
}
<commit_msg>Use global `BUF_SIZE` constant<commit_after>extern crate rsoundio;
extern crate rb;

use rb::{RB, SpscRb, RbProducer, RbConsumer};
use std::f32::consts::PI as PI32;
use std::thread;
use std::time::Duration;

const BUF_SIZE: usize = 2048;

fn main() {
    let rb = SpscRb::new(BUF_SIZE);
    let (producer, consumer) = (rb.producer(), rb.consumer());
    // create an audio context
    let mut sio = rsoundio::SoundIo::default();
    sio.set_name("rsoundio-example").unwrap();
    // connect to the default audio backend
    sio.connect().unwrap();
    let backend = sio.current_backend().unwrap();
    println!("Connected to backend: {}", backend);
    sio.flush_events();
    // get default output device
    let dev = sio.default_output_device().unwrap();
    assert!(dev.probe_error().is_none());
    println!("Using output device: {}", dev);
    // create output stream
    let mut out = dev.create_outstream().unwrap();
    assert!(out.set_name("sine").is_ok());
    out.set_format(rsoundio::SioFormat::Float32LE).unwrap();
    println!("Output format: {}", out.format().unwrap());

    thread::spawn(move || {
        const LEN: usize = BUF_SIZE/16;
        let mut pos = 0;
        loop {
            const F: f32 = 440.0;
            const W: f32 = 2.0 * F * PI32 / 48_000.0;
            const A: f32 = 0.6;
            const CYCLE: usize = (48_000f32 / F) as usize;

            let samples: Vec<f32> = (0..LEN)
                                        .map(|i| (W * (i + pos) as f32).sin() * A)
                                        .collect();
            producer.write_blocking(&samples).unwrap();
            pos = (pos + LEN) % CYCLE;
        }
    });

    // register callbacks
    out.register_write_callback(|out: rsoundio::OutStream,
                                 min_frame_count: u32,
                                 max_frame_count: u32| {
        let mut data = vec![0.0f32; BUF_SIZE];
        let len = if backend != rsoundio::SioBackend::PulseAudio {
            ::std::cmp::min(BUF_SIZE, max_frame_count as usize)
        } else {
            BUF_SIZE
        };
        consumer.read_blocking(&mut data[..len]);
        let frames = vec![data[..len].iter().cloned().collect(),
                          data[..len].iter().cloned().collect()];
        out.write_stream_f32(min_frame_count, &frames).unwrap();
    });
    out.register_underflow_callback(|out: rsoundio::OutStream| {
        println!("Underflow in {} occured!", out.name().unwrap())
    });
    out.register_error_callback(|out: rsoundio::OutStream, err: rsoundio::SioError| {
        println!("{} error: {}", out.name().unwrap(), err)
    });

    // open output stream
    out.open().unwrap();
    let sr = out.sample_rate();
    println!("Sample rate: {}", sr);

    match out.latency() {
        Ok(latency) => println!("SW latency: {}", latency),
        Err(err) => println!("err: {}", err),
    }
    let layout = out.layout();
    println!("Output channel layout: {}", layout);
    // start audio output (now the `write_callback` will be called periodically)
    out.start().unwrap();
    thread::sleep(Duration::new(3, 0));
    println!("Pause for 1s");
    out.pause();
    thread::sleep(Duration::new(1, 0));
    println!("Unpausing");
    out.unpause();
    thread::sleep(Duration::new(3, 0));
}
<|endoftext|>


<commit_before>
extern crate curved_gear;
extern crate env_logger;
extern crate mioco;

use std::net::SocketAddr;

use curved_gear::*;
use mioco::udp::UdpSocket;

fn main() {
    env_logger::init().unwrap();

    let client_id = Identity::new(Extension::from_barr(b"client"));
    let server_id = Identity::new(Extension::from_barr(b"server"));
    let server_addr: SocketAddr = "0.0.0.0:7777".parse().unwrap();
    let remote_addr: SocketAddr = "127.0.0.1:7777".parse().unwrap();

    mioco::start(move || -> Result<()> {
        let mut listener = CCPListener::new(server_id.clone(), UdpSocket::bound(&server_addr).unwrap());

        mioco::spawn(move || -> Result<()> {
            let mut sock = try!(CCPClientSocket::connect(UdpSocket::v4().unwrap(),
                client_id, server_id.create_remote(remote_addr)));

            try!(sock.send("Hello world".as_bytes()));
            let buf = try!(sock.recv());
            println!("{}", String::from_utf8_lossy(&buf));
            try!(sock.send("".as_bytes()));

            Ok(())
        });

        {
            let mut sock = try!(listener.accept_sock());

            mioco::spawn(move || -> Result<()> {
                loop {
                    let msg = try!(sock.recv());
                    println!("msg.len() = {}", msg.len());
                    if msg.len() == 0 { break; }
                    try!(sock.send(&msg));
                }

                Ok(())
            });
        }

        Ok(())
    }).unwrap().unwrap();
}
<commit_msg>Multple connections on example<commit_after>
extern crate curved_gear;
extern crate env_logger;
extern crate mioco;

use std::net::SocketAddr;

use curved_gear::*;
use mioco::udp::UdpSocket;

fn main() {
    env_logger::init().unwrap();

    let client_id = Identity::new(Extension::from_barr(b"client"));
    let server_id = Identity::new(Extension::from_barr(b"server"));
    let server_addr: SocketAddr = "0.0.0.0:7777".parse().unwrap();
    let remote_addr: SocketAddr = "127.0.0.1:7777".parse().unwrap();
    let remote_id = server_id.create_remote(remote_addr);

    mioco::start(move || -> Result<()> {
        let mut listener = CCPListener::new(server_id.clone(), UdpSocket::bound(&server_addr).unwrap());

        for i in 1..5 {
            let client_id_c = client_id.clone();
            let remote_id_c = remote_id.clone();

            mioco::spawn(move || -> Result<()> {
                let mut sock = try!(CCPClientSocket::connect(UdpSocket::v4().unwrap(),
                    client_id_c, remote_id_c));

                println!("Client connection {}", i);
                try!(sock.send("Hello world".as_bytes()));
                let buf = try!(sock.recv());
                println!("{}", String::from_utf8_lossy(&buf));
                try!(sock.send("".as_bytes()));

                Ok(())
            });
        }

        for i in 1..5 {
            let mut sock = try!(listener.accept_sock());

            println!("Server connection {}", i);

            mioco::spawn(move || -> Result<()> {
                loop {
                    let msg = try!(sock.recv());
                    println!("msg.len() = {}", msg.len());
                    if msg.len() == 0 { break; }
                    try!(sock.send(&msg));
                }

                Ok(())
            });
        }

        Ok(())
    }).unwrap().unwrap();
}
<|endoftext|>