<commit_before>#![feature(core)]

use std::borrow::Borrow;
use std::cell::RefCell;
use std::fmt::{Debug, Error, Formatter};
use std::num::{Int, SignedInt};
use std::rc::Rc;

// Basic use cases:
//  - Fixed tree (built once). Handled by ?building, Tree, Navigator.
//  - Fixed-topology tree (data mutates). Handled by ?building, Tree,
//    Navigator with RefCell<T> for data.
//  - Shared-data tree (topology fixed). Handled by ?building, Tree,
//    Navigator with RefCell<T> for data.
//  - Shared-topology tree (data fixed).
//  - Shared-both tree.

pub struct Tree<T> {
    data: T,
    children: Vec<Tree<T>>,
}

// Like a stack frame when recursively descending a tree.
struct NavigatorCell<'a, T: 'a> {
    tree: &'a Tree<T>,
    index: usize,
}

pub struct Navigator<'a, T: 'a> {
    here: &'a Tree<T>,
    path: Vec<NavigatorCell<'a, T>>,
}

struct ZipperCell<'a, T: 'a> {
    tree: Rc<RefCell<&'a mut Tree<T>>>,
    index: usize,
}

pub struct Zipper<'a, T: 'a> {
    here: ZipperCell<'a, T>,
    path: Vec<ZipperCell<'a, T>>,
}

impl<T> Tree<T> {
    pub fn leaf(data: T) -> Tree<T> {
        Tree {
            data: data,
            children: Vec::new(),
        }
    }

    pub fn data<'s>(&'s self) -> &'s T {
        &self.data
    }

    pub fn data_mut<'s>(&'s mut self) -> &'s mut T {
        &mut self.data
    }

    pub fn children<'s>(&'s self) -> &'s [Tree<T>] {
        self.children.as_slice()
    }

    pub fn children_mut<'s>(&'s mut self) -> &'s mut [Tree<T>] {
        self.children.as_mut_slice()
    }

    pub fn remove_child(&mut self, index: usize) {
        self.children.remove(index);
    }

    pub fn insert_child(&mut self, index: usize, child: Tree<T>) {
        self.children.insert(index, child);
    }

    pub fn pop_child(&mut self) -> Option<Tree<T>> {
        self.children.pop()
    }

    pub fn push_child(&mut self, child: Tree<T>) {
        self.children.push(child);
    }

    pub fn navigator<'s>(&'s self) -> Navigator<'s, T> {
        Navigator { here: self, path: Vec::new(), }
    }
}

#[macro_export]
macro_rules! tree {
    ($data:expr) => ($crate::Tree::leaf($data));
    ($data:expr, [$($first:tt)*] $(,[$($rest:tt)*])*) =>
        ($crate::Tree { data: $data,
                        children: vec![tree![$($first)*]
                                       $(,tree![$($rest)*])*] });
}

impl<T: Debug> Debug for Tree<T> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        enum Walk<T> { Down(T), Up, };
        let mut stack = Vec::new();
        try![write!(f, "({:?}", self.data)];
        stack.push(Walk::Up);
        for c in self.children.iter().rev() {
            stack.push(Walk::Down(c));
        }
        loop {
            match stack.pop() {
                None => return Ok(()),
                Some(Walk::Up) => try![write!(f, ")")],
                Some(Walk::Down(t)) => {
                    try![write!(f, " ({:?}", t.data)];
                    stack.push(Walk::Up);
                    for c in t.children.iter().rev() {
                        stack.push(Walk::Down(c));
                    }
                },
            }
        }
    }
}

impl<T: Clone> Clone for Tree<T> {
    fn clone(&self) -> Tree<T> {
        Tree {
            data: self.data.clone(),
            children: self.children.clone(),
        }
    }

    fn clone_from(&mut self, source: &Tree<T>) {
        self.data.clone_from(&source.data);
        self.children.clone_from(&source.children);
    }
}

impl<T: PartialEq> PartialEq for Tree<T> {
    fn eq(&self, other: &Tree<T>) -> bool {
        let mut stack = Vec::new();
        stack.push((self, other));
        loop {
            match stack.pop() {
                Some((x, y)) => {
                    if x.data != y.data {
                        return false;
                    } else if x.children.len() != y.children.len() {
                        return false;
                    } else {
                        let mut xi = x.children.iter();
                        let mut yi = y.children.iter();
                        loop {
                            match (xi.next(), yi.next()) {
                                (Some(xt), Some(yt)) => stack.push((xt, yt)),
                                (None, None) => break,
                                _ => panic!("Tree corruption"),
                            }
                        }
                    }
                },
                None => return true,
            }
        }
    }
}

impl<'a, T: 'a> Navigator<'a, T> {
    pub fn is_root(&self) -> bool {
        self.path.is_empty()
    }

    pub fn is_leaf(&self) -> bool {
        self.here.children.is_empty()
    }

    pub fn to_parent(&mut self) {
        loop {
            match self.path.pop() {
                None => return,
                Some(traversal) => {
                    self.here = &traversal.tree.children[traversal.index]
                },
            }
        }
    }

    pub fn tree<'s>(&'s self) -> &'s Tree<T> {
        &self.here
    }

    pub fn seek_sibling(&mut self, offset: isize) {
        assert![!self.is_root()];
        if offset == 0 {
            return;
        }
        let mut cell = self.path.pop().expect("tree corruption");
        let offset_abs = offset.abs();
        let new_index =
            if offset_abs < 0 {
                // offset is Int::min_value().
                cell.index
                    .checked_sub(1).expect("index undeflow")
                    .checked_sub((offset_abs + 1isize).abs() as usize).expect("index underflow")
            } else {
                if offset < 0 {
                    cell.index.checked_sub(offset_abs as usize).expect("index underflow")
                } else {
                    cell.index.checked_add(offset_abs as usize).expect("index overflow")
                }
            };
        assert![new_index < cell.tree.children.len(),
                "sibling index {} out of range (only {} siblings)",
                new_index, cell.tree.children.len()];
        self.here = &cell.tree.children[new_index];
        cell.index = new_index;
        self.path.push(cell);
    }

    pub fn seek_child(&mut self, child_index: usize) {
        assert![child_index < self.here.children.len(),
                "child index {} out of range (only {} children)",
                child_index, self.here.children.len()];
        self.path.push(NavigatorCell { tree: self.here,
                                       index: child_index });
        self.here = &self.here.children[child_index];
    }
}

impl<'a, T: 'a> Borrow<Tree<T>> for Navigator<'a, T> {
    fn borrow(&self) -> &Tree<T> {
        self.here
    }
}

// impl<'a, T: 'a> Zipper<'a, T> {
//     pub fn seek_child(&'a mut self, child_index: usize) {
//         self.here = {
//             let here_cell = &self.here;
//             let here = here_cell.borrow_mut();
//             assert![child_index < here.children.len(),
//                     "child index {} out of range (only {} children)",
//                     child_index, here.children.len()];
//             self.path.push(ZipperCell { tree: self.here.clone(),
//                                         index: child_index });
//             Rc::new(RefCell::new(&mut here.children[child_index]))
//         };
//     }
// }

#[cfg(test)]
mod test {
    use ::Tree;

    #[test]
    fn test_leaf() {
        assert![Tree::leaf("hi") == tree!["hi"]];
        assert![Tree { data: "hi", children: Vec::new(), } == tree!["hi"]];
        let leaf = tree!["hi"];
        assert![leaf.data() == &"hi"];
        assert![leaf.children().len() == 0];
    }

    #[test]
    fn test_nested_01() {
        let reference = Tree { data: "hi",
                               children: vec![Tree::leaf("a"),
                                              Tree::leaf("b")] };
        assert![reference == tree!["hi", ["a"], ["b"]]];
    }

    #[test]
    fn test_nested_02() {
        let mut reference = Tree::leaf("hi");
        reference.push_child(Tree::leaf("a"));
        reference.push_child(Tree::leaf("b"));
        assert![reference == tree!["hi", ["a"], ["b"]]];
    }

    #[test]
    fn test_nested_03() {
        let reference = Tree { data: "hi",
                               children: vec![Tree { data: "a",
                                                     children: vec![Tree::leaf("b"),
                                                                    Tree::leaf("c")] },
                                              Tree { data: "d",
                                                     children: vec![Tree {
                                                         data: "e",
                                                         children: vec![Tree::leaf("f"), Tree::leaf("g")]
                                                     }],
                                              }],
        };
        assert![reference == tree!["hi", ["a", ["b"], ["c"]], ["d", ["e", ["f"], ["g"]]]]];
    }

    #[test]
    fn test_debug_format() {
        assert![format!("{:?}", tree!["a"]) == "(\"a\")"];
        assert![format!("{:?}", tree!["hi", ["a", ["b"], ["c"]], ["d", ["e", ["f"], ["g"]]]]) == "(\"hi\" (\"a\" (\"b\") (\"c\")) (\"d\" (\"e\" (\"f\") (\"g\"))))"];
        assert![format!("{:?}", tree!["a", ["b"], ["c"], ["d"], ["e"]]) == "(\"a\" (\"b\") (\"c\") (\"d\") (\"e\"))"];
    }
}
<commit_msg>Finally starting to feel good about a Vec-based tree and zipper.<commit_after>#![feature(core)]

use std::borrow::{Borrow, BorrowMut};
use std::fmt::{Debug, Error, Formatter};
use std::mem;
use std::num::{Int, SignedInt};

// Basic use cases:
//  - Fixed tree (built once). Handled by Zipper, Tree, Navigator.
//  - Fixed-topology tree (data mutates). Handled by Zipper, Tree, Navigator.
//  - Shared-data tree (topology fixed). Handled by ?building, Tree, Navigator
//    with RefCell<T> or Mutex<T> for data.
//  - Shared-topology tree (data fixed).
//  - Shared-data, shared-topology tree.

pub struct Tree<T> {
    data: T,
    children: Vec<Tree<T>>,
}

// Like a stack frame when recursively descending a tree.
struct NavigatorCell<'a, T: 'a> {
    tree: &'a Tree<T>,
    index: usize,
}

pub struct Navigator<'a, T: 'a> {
    here: &'a Tree<T>,
    path: Vec<NavigatorCell<'a, T>>,
}

struct ZipperCell<T> {
    tree: *mut Tree<T>,
    index: usize,
}

pub struct Zipper<'a, T: 'a> {
    here: &'a mut Tree<T>,
    path: Vec<ZipperCell<T>>,
}

impl<T> Tree<T> {
    pub fn leaf(data: T) -> Tree<T> {
        Tree {
            data: data,
            children: Vec::new(),
        }
    }

    pub fn data<'s>(&'s self) -> &'s T {
        &self.data
    }

    pub fn data_mut<'s>(&'s mut self) -> &'s mut T {
        &mut self.data
    }

    pub fn children<'s>(&'s self) -> &'s [Tree<T>] {
        self.children.as_slice()
    }

    pub fn children_mut<'s>(&'s mut self) -> &'s mut [Tree<T>] {
        self.children.as_mut_slice()
    }

    pub fn remove_child(&mut self, index: usize) {
        self.children.remove(index);
    }

    pub fn insert_child(&mut self, index: usize, child: Tree<T>) {
        self.children.insert(index, child);
    }

    pub fn pop_child(&mut self) -> Option<Tree<T>> {
        self.children.pop()
    }

    pub fn push_child(&mut self, child: Tree<T>) {
        self.children.push(child);
    }

    pub fn navigator<'s>(&'s self) -> Navigator<'s, T> {
        Navigator { here: self, path: Vec::new(), }
    }
}

#[macro_export]
macro_rules! tree {
    ($data:expr) => ($crate::Tree::leaf($data));
    ($data:expr, [$($first:tt)*] $(,[$($rest:tt)*])*) =>
        ($crate::Tree { data: $data,
                        children: vec![tree![$($first)*]
                                       $(,tree![$($rest)*])*] });
    ($data:expr, ($($first:tt)*) $(,($($rest:tt)*))*) =>
        ($crate::Tree { data: $data,
                        children: vec![tree![$($first)*]
                                       $(,tree![$($rest)*])*] });
    ($data:expr, {$($first:tt)*} $(,{$($rest:tt)*})*) =>
        ($crate::Tree { data: $data,
                        children: vec![tree![$($first)*]
                                       $(,tree![$($rest)*])*] });
}

impl<T: Debug> Debug for Tree<T> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        enum Walk<T> { Down(T), Up, };
        let mut stack = Vec::new();
        try![write!(f, "({:?}", self.data)];
        stack.push(Walk::Up);
        for c in self.children.iter().rev() {
            stack.push(Walk::Down(c));
        }
        loop {
            match stack.pop() {
                None => return Ok(()),
                Some(Walk::Up) => try![write!(f, ")")],
                Some(Walk::Down(t)) => {
                    try![write!(f, " ({:?}", t.data)];
                    stack.push(Walk::Up);
                    for c in t.children.iter().rev() {
                        stack.push(Walk::Down(c));
                    }
                },
            }
        }
    }
}

impl<T: Clone> Clone for Tree<T> {
    fn clone(&self) -> Tree<T> {
        Tree {
            data: self.data.clone(),
            children: self.children.clone(),
        }
    }

    fn clone_from(&mut self, source: &Tree<T>) {
        self.data.clone_from(&source.data);
        self.children.clone_from(&source.children);
    }
}

impl<T: PartialEq> PartialEq for Tree<T> {
    fn eq(&self, other: &Tree<T>) -> bool {
        let mut stack = Vec::new();
        stack.push((self, other));
        loop {
            match stack.pop() {
                Some((x, y)) => {
                    if x.data != y.data {
                        return false;
                    } else if x.children.len() != y.children.len() {
                        return false;
                    } else {
                        let mut xi = x.children.iter();
                        let mut yi = y.children.iter();
                        loop {
                            match (xi.next(), yi.next()) {
                                (Some(xt), Some(yt)) => stack.push((xt, yt)),
                                (None, None) => break,
                                _ => panic!("Tree corruption"),
                            }
                        }
                    }
                },
                None => return true,
            }
        }
    }
}

impl<'a, T: 'a> Navigator<'a, T> {
    pub fn is_root(&self) -> bool {
        self.path.is_empty()
    }

    pub fn is_leaf(&self) -> bool {
        self.here.children.is_empty()
    }

    pub fn to_parent(&mut self) {
        match self.path.pop() {
            None => panic!["already at root"],
            Some(traversal) => self.here = &traversal.tree,
        }
    }

    pub fn to_root(&mut self) {
        loop {
            match self.path.pop() {
                None => return,
                Some(traversal) => self.here = &traversal.tree,
            }
        }
    }

    pub fn tree<'s>(&'s self) -> &'s Tree<T> {
        &self.here
    }

    pub fn seek_sibling(&mut self, offset: isize) {
        assert![!self.is_root()];
        if offset == 0 {
            return;
        }
        let mut cell = self.path.pop().expect("tree corruption");
        let offset_abs = offset.abs();
        let new_index =
            if offset_abs < 0 {
                // offset is Int::min_value().
                cell.index
                    .checked_sub(1).expect("index undeflow")
                    .checked_sub((offset_abs + 1isize).abs() as usize).expect("index underflow")
            } else {
                if offset < 0 {
                    cell.index.checked_sub(offset_abs as usize).expect("index underflow")
                } else {
                    cell.index.checked_add(offset_abs as usize).expect("index overflow")
                }
            };
        assert![new_index < cell.tree.children.len(),
                "sibling index {} out of range (only {} siblings)",
                new_index, cell.tree.children.len()];
        self.here = &cell.tree.children[new_index];
        cell.index = new_index;
        self.path.push(cell);
    }

    pub fn seek_child(&mut self, child_index: usize) {
        assert![child_index < self.here.children.len(),
                "child index {} out of range (only {} children)",
                child_index, self.here.children.len()];
        self.path.push(NavigatorCell { tree: self.here,
                                       index: child_index });
        self.here = &self.here.children[child_index];
    }

    // pub fn has_left(&self) -> bool {
    // }

    // pub fn has_right(&self) -> bool {
    // }

    // pub fn to_left(&mut self) {
    // }

    // pub fn to_right(&mut self) {
    // }
}

impl<'a, T: 'a> Borrow<Tree<T>> for Navigator<'a, T> {
    fn borrow(&self) -> &Tree<T> {
        self.here
    }
}

impl<'a, T: 'a> Zipper<'a, T> {
    pub fn is_root(&self) -> bool {
        self.path.is_empty()
    }

    pub fn to_root(&mut self) {
        loop {
            match self.path.pop() {
                None => return,
                Some(traversal) => self.here = unsafe {
                    mem::transmute(traversal.tree)
                },
            }
        }
    }

    pub fn to_parent(&mut self) {
        match self.path.pop() {
            None => panic!["already at root"],
            Some(traversal) => self.here = unsafe {
                mem::transmute(traversal.tree)
            },
        }
    }

    pub fn seek_sibling(&mut self, offset: isize) {
        assert![!self.is_root()];
        if offset == 0 {
            return;
        }
        let mut cell = self.path.pop().expect("tree corruption");
        let offset_abs = offset.abs();
        let new_index =
            if offset_abs < 0 {
                // offset is Int::min_value().
                cell.index
                    .checked_sub(1).expect("index underflow")
                    .checked_sub((offset_abs + 1isize).abs() as usize).expect("index underflow")
            } else {
                if offset < 0 {
                    cell.index.checked_sub(offset_abs as usize).expect("index underflow")
                } else {
                    cell.index.checked_add(offset_abs as usize).expect("index overflow")
                }
            };
        {
            let parent: &mut Tree<T> = unsafe {
                mem::transmute(cell.tree)
            };
            assert![new_index < parent.children.len(),
                    "sibling index {} out of range (only {} siblings)",
                    new_index, parent.children.len()];
            self.here = unsafe {
                mem::transmute(&mut parent.children[new_index])
            };
        }
        cell.index = new_index;
        self.path.push(cell);
    }

    pub fn seek_child(&mut self, child_index: usize) {
        assert![child_index < self.here.children.len(),
                "child index {} out of range (only {} children)",
                child_index, self.here.children.len()];
        let raw_here = self.here as *mut Tree<T>;
        self.path.push(ZipperCell { tree: raw_here, index: child_index });
        self.here = unsafe {
            mem::transmute(&mut self.here.children[child_index])
        };
    }

    // pub fn insert_sibling(&mut self, offset: isize, t: Tree<T>) {
    // }

    // pub fn insert_child(&mut self, index: usize, t: Tree<T>) {
    // }

    // pub fn push_child(&mut self, t: Tree<T>) {
    // }

    // pub fn delete(&mut self) {
    // }

    // pub fn delete_child(&mut self, index: usize) {
    // }

    // pub fn delete_sibling(&mut self, offset: isize) {
    // }

    // pub fn pop_child(&mut self) -> Option<Tree<T>> {
    // }

    // pub fn swap_sibling(&mut self, offset: isize) {
    // }
}

impl<'a, T: 'a> Borrow<Tree<T>> for Zipper<'a, T> {
    fn borrow(&self) -> &Tree<T> {
        self.here
    }
}

impl<'a, T: 'a> BorrowMut<Tree<T>> for Zipper<'a, T> {
    fn borrow_mut(&mut self) -> &mut Tree<T> {
        self.here
    }
}

#[cfg(test)]
mod test {
    use ::Tree;

    #[test]
    fn test_leaf() {
        assert![Tree::leaf("hi") == tree!["hi"]];
        assert![Tree { data: "hi", children: Vec::new(), } == tree!["hi"]];
        let leaf = tree!["hi"];
        assert![leaf.data() == &"hi"];
        assert![leaf.children().len() == 0];
    }

    #[test]
    fn test_nested_01() {
        let reference = Tree { data: "hi",
                               children: vec![Tree::leaf("a"),
                                              Tree::leaf("b")] };
        assert![reference == tree!["hi", ["a"], ["b"]]];
    }

    #[test]
    fn test_nested_02() {
        let mut reference = Tree::leaf("hi");
        reference.push_child(Tree::leaf("a"));
        reference.push_child(Tree::leaf("b"));
        assert![reference == tree!["hi", ["a"], ["b"]]];
    }

    #[test]
    fn test_nested_03() {
        let reference = Tree { data: "hi",
                               children: vec![Tree { data: "a",
                                                     children: vec![Tree::leaf("b"),
                                                                    Tree::leaf("c")] },
                                              Tree { data: "d",
                                                     children: vec![Tree {
                                                         data: "e",
                                                         children: vec![Tree::leaf("f"), Tree::leaf("g")]
                                                     }],
                                              }],
        };
        assert![reference == tree!["hi", ["a", ["b"], ["c"]], ["d", ["e", ["f"], ["g"]]]]];
    }

    #[test]
    fn test_debug_format() {
        assert![format!("{:?}", tree!["a"]) == "(\"a\")"];
        assert![format!("{:?}", tree!["hi", ["a", ["b"], ["c"]], ["d", ["e", ["f"], ["g"]]]]) == "(\"hi\" (\"a\" (\"b\") (\"c\")) (\"d\" (\"e\" (\"f\") (\"g\"))))"];
        assert![format!("{:?}", tree!["a", ["b"], ["c"], ["d"], ["e"]]) == "(\"a\" (\"b\") (\"c\") (\"d\") (\"e\"))"];
    }

    #[test]
    fn test_recursive_mutating_bfs() {
        fn mutable_bfs(t: &mut Tree<&str>) {
            if t.children.len() == 0 {
                t.data = "leaf";
            } else {
                for child in &mut t.children {
                    mutable_bfs(child);
                }
            }
        }

        let mut t = tree!["a", ["b", ["c"], ["d"], ["e"]], ["f"]];
        mutable_bfs(&mut t);
        assert_eq![format!["{:?}", t],
                   "(\"a\" (\"b\" (\"leaf\") (\"leaf\") (\"leaf\")) (\"leaf\"))"];
    }
}
<|endoftext|>


<commit_before>#![feature(io)]
#![doc(html_root_url = "http://cpjreynolds.github.io/rustty/rustty/index.html")]

//! Terminal UI library.

extern crate nix;

mod core;
mod util;

pub use core::terminal::Terminal;
pub use core::cellbuffer::{
    Cell,
    Style,
    Color,
    Attr,
};
pub use core::input::Event;
pub use core::cursor::Cursor;
pub use util::error::Error;

<commit_msg>use collections unstable<commit_after>#![feature(io)]
#![feature(collections)]
#![doc(html_root_url = "http://cpjreynolds.github.io/rustty/rustty/index.html")]

//! Terminal UI library.

extern crate nix;

mod core;
mod util;

pub use core::terminal::Terminal;
pub use core::cellbuffer::{
    Cell,
    Style,
    Color,
    Attr,
};
pub use core::input::Event;
pub use core::cursor::Cursor;
pub use util::error::Error;

<|endoftext|>


<commit_before>//! `refraction` is a lens library for Rust.  Its design is based broadly on
//! that of [the Haskell `lens`
//! package](https://hackage.haskell.org/package/lens), but reworked and
//! reorganized to become more Rusty.
//!
//! The `nightly` cargo feature flag can be used to enable some features only
//! available on nightly Rust:
//!
//! - Lenticuloids that deal with the `!` type
//! - `const fn` support
//! - More efficient implementation of some macros

#![cfg_attr(feature = "nightly", feature(never_type, const_fn))]
#![cfg_attr(feature = "cargo-clippy", allow(expl_impl_clone_on_copy, type_complexity))]

use std::fmt;
use std::marker::PhantomData;
extern crate nodrop;

/// A [prelude module](https://doc.rust-lang.org/std/prelude/#other-preludes)
/// suitible for glob-importing.
pub mod prelude {
    pub use super::{AndThenExt, ComposeExt, Identity, InvertExt, Iso, Lens, PartialLens, Prism};
}

/// Some utility functions used inside this crate, but possibly useful for
/// others as well.
pub mod util {
    pub fn once_to_mut<'a, X, Y, F>(f_once: F) -> Box<FnMut(X) -> Option<Y> + 'a>
        where F: FnOnce(X) -> Y + 'a
    {
        let mut f_opt: Option<F> = Some(f_once);
        Box::new(move |x| f_opt.take().map(move |f| f(x)))
    }

    pub fn once_to_mut_flatten<'a, X, Y, F>(f_once: F) -> Box<FnMut(X) -> Option<Y> + 'a>
        where F: FnOnce(X) -> Option<Y> + 'a
    {
        let mut f_opt: Option<F> = Some(f_once);
        Box::new(move |x| f_opt.take().and_then(move |f| f(x)))
    }
}

/// The supertype of all lenticuloids.
pub trait Lenticuloid {
    type InitialSource;

    type InitialTarget;

    type FinalSource;

    type FinalTarget;

    type AtInitial: Lenticuloid<InitialSource = Self::InitialSource,
                InitialTarget = Self::InitialTarget,
                FinalSource = Self::InitialSource,
                FinalTarget = Self::InitialTarget,
                AtInitial = Self::AtInitial,
                AtFinal = Self::AtInitial>;

    fn at_initial(&self) -> Self::AtInitial;

    type AtFinal: Lenticuloid<InitialSource = Self::FinalSource,
                InitialTarget = Self::FinalTarget,
                FinalSource = Self::FinalSource,
                FinalTarget = Self::FinalTarget,
                AtInitial = Self::AtFinal,
                AtFinal = Self::AtFinal>;

    fn at_final(&self) -> Self::AtFinal;
}

/// The identity lenticuloid.
pub struct Identity<S, T> {
    phantom_ss: PhantomData<Fn(S) -> S>,
    phantom_tt: PhantomData<Fn(T) -> T>,
}

impl<S, T> fmt::Debug for Identity<S, T> {
    fn fmt(&self, fm: &mut fmt::Formatter) -> fmt::Result {
        fm.debug_struct("Identity")
          .field("phantom_ss", &self.phantom_ss)
          .field("phantom_tt", &self.phantom_tt)
          .finish()
    }
}

impl<S, T> Clone for Identity<S, T> {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }

    #[inline]
    fn clone_from(&mut self, source: &Self) {
        *self = *source;
    }
}

impl<S, T> Copy for Identity<S, T> {}

impl<S, T> Default for Identity<S, T> {
    #[inline]
    fn default() -> Self {
        Self::mk()
    }
}

impl<S, T> Identity<S, T> {
    #[cfg(not(feature = "nightly"))]
    #[inline]
    pub fn mk() -> Self {
        Identity { phantom_ss: PhantomData,
                   phantom_tt: PhantomData, }
    }

    #[cfg(feature = "nightly")]
    #[inline]
    pub const fn mk() -> Self {
        Identity { phantom_ss: PhantomData,
                   phantom_tt: PhantomData, }
    }
}

impl<S, T> Lenticuloid for Identity<S, T> {
    type InitialSource = S;

    type InitialTarget = S;

    type FinalSource = T;

    type FinalTarget = T;

    type AtInitial = Identity<S, S>;

    fn at_initial(&self) -> Self::AtInitial {
        Identity::mk()
    }

    type AtFinal = Identity<T, T>;

    fn at_final(&self) -> Self::AtFinal {
        Identity::mk()
    }
}

/// Composition of lenticuloids.
#[derive(Clone,Copy,Debug,Default)]
pub struct Compose<LF, LS: ?Sized> {
    first: LF,
    second: LS,
}

impl<LF, LS> Compose<LF, LS> {
    #[inline]
    pub fn of(lf: LF, ls: LS) -> Self {
        Compose { first: lf,
                  second: ls, }
    }
}

impl<LF: Lenticuloid, LS: ?Sized> Lenticuloid for Compose<LF, LS>
    where LS: Lenticuloid<InitialTarget = LF::InitialSource, FinalTarget = LF::FinalSource>
{
    type InitialSource = LS::InitialSource;

    type InitialTarget = LF::InitialTarget;

    type FinalSource = LS::FinalSource;

    type FinalTarget = LF::FinalTarget;

    type AtInitial = Compose<LF::AtInitial, LS::AtInitial>;

    fn at_initial(&self) -> Self::AtInitial {
        Compose::of(self.first.at_initial(), self.second.at_initial())
    }

    type AtFinal = Compose<LF::AtFinal, LS::AtFinal>;

    fn at_final(&self) -> Self::AtFinal {
        Compose::of(self.first.at_final(), self.second.at_final())
    }
}

/// The inversion of a lenticuloid.
#[derive(Clone,Copy,Debug,Default)]
pub struct Invert<L: ?Sized> {
    deinvert: L,
}

impl<L> Invert<L> {
    #[inline]
    pub fn of(l: L) -> Self {
        Invert { deinvert: l }
    }
}

impl<L: Lenticuloid + ?Sized> Lenticuloid for Invert<L> {
    type InitialSource = L::FinalTarget;

    type InitialTarget = L::FinalSource;

    type FinalSource = L::InitialTarget;

    type FinalTarget = L::InitialSource;

    type AtInitial = Invert<L::AtFinal>;

    fn at_initial(&self) -> Self::AtInitial {
        Invert::of(self.deinvert.at_final())
    }

    type AtFinal = Invert<L::AtInitial>;

    fn at_final(&self) -> Self::AtFinal {
        Invert::of(self.deinvert.at_initial())
    }
}

mod partial_lens;
pub use partial_lens::*;

mod lens;
pub use lens::*;

mod prism;
pub use prism::*;

mod iso;
pub use iso::*;

#[macro_use]
mod ops;
pub use ops::*;

pub mod access;

pub mod meta;

pub mod terminal;

pub mod conv;

pub mod errors;

pub mod collections;
<commit_msg>Doc wrangling.<commit_after>//! `refraction` is a lens library for Rust.  Its design is based broadly on
//! that of [the Haskell `lens`
//! package](https://hackage.haskell.org/package/lens), but reworked and
//! reorganized to become more Rusty.
//!
//! The `nightly` cargo feature flag can be used to enable some features only
//! available on nightly Rust:
//!
//! - Lenticuloids that deal with the `!` type
//! - `const fn` support
//! - More efficient implementation of some macros
//!
//! To get started easily, import
//! [`refraction::prelude::*`](prelude/index.html).

#![cfg_attr(feature = "nightly", feature(never_type, const_fn))]
#![cfg_attr(feature = "cargo-clippy", allow(expl_impl_clone_on_copy, type_complexity))]

use std::fmt;
use std::marker::PhantomData;
extern crate nodrop;

/// A [prelude module](https://doc.rust-lang.org/std/prelude/#other-preludes)
/// suitible for glob-importing.
pub mod prelude {
    #[doc(no_inline)]
    pub use ::{AndThenExt, ComposeExt, Identity, InvertExt, Iso, Lens, PartialLens, Prism};
}

/// Some utility functions used inside this crate, but possibly useful for
/// others as well.
pub mod util {
    pub fn once_to_mut<'a, X, Y, F>(f_once: F) -> Box<FnMut(X) -> Option<Y> + 'a>
        where F: FnOnce(X) -> Y + 'a
    {
        let mut f_opt: Option<F> = Some(f_once);
        Box::new(move |x| f_opt.take().map(move |f| f(x)))
    }

    pub fn once_to_mut_flatten<'a, X, Y, F>(f_once: F) -> Box<FnMut(X) -> Option<Y> + 'a>
        where F: FnOnce(X) -> Option<Y> + 'a
    {
        let mut f_opt: Option<F> = Some(f_once);
        Box::new(move |x| f_opt.take().and_then(move |f| f(x)))
    }
}

/// The supertype of all lenticuloids.
pub trait Lenticuloid {
    type InitialSource;

    type InitialTarget;

    type FinalSource;

    type FinalTarget;

    type AtInitial: Lenticuloid<InitialSource = Self::InitialSource,
                InitialTarget = Self::InitialTarget,
                FinalSource = Self::InitialSource,
                FinalTarget = Self::InitialTarget,
                AtInitial = Self::AtInitial,
                AtFinal = Self::AtInitial>;

    fn at_initial(&self) -> Self::AtInitial;

    type AtFinal: Lenticuloid<InitialSource = Self::FinalSource,
                InitialTarget = Self::FinalTarget,
                FinalSource = Self::FinalSource,
                FinalTarget = Self::FinalTarget,
                AtInitial = Self::AtFinal,
                AtFinal = Self::AtFinal>;

    fn at_final(&self) -> Self::AtFinal;
}

/// The identity lenticuloid.
pub struct Identity<S, T> {
    phantom_ss: PhantomData<Fn(S) -> S>,
    phantom_tt: PhantomData<Fn(T) -> T>,
}

impl<S, T> fmt::Debug for Identity<S, T> {
    fn fmt(&self, fm: &mut fmt::Formatter) -> fmt::Result {
        fm.debug_struct("Identity")
          .field("phantom_ss", &self.phantom_ss)
          .field("phantom_tt", &self.phantom_tt)
          .finish()
    }
}

impl<S, T> Clone for Identity<S, T> {
    #[inline]
    fn clone(&self) -> Self {
        *self
    }

    #[inline]
    fn clone_from(&mut self, source: &Self) {
        *self = *source;
    }
}

impl<S, T> Copy for Identity<S, T> {}

impl<S, T> Default for Identity<S, T> {
    #[inline]
    fn default() -> Self {
        Self::mk()
    }
}

impl<S, T> Identity<S, T> {
    #[cfg(not(feature = "nightly"))]
    #[inline]
    pub fn mk() -> Self {
        Identity { phantom_ss: PhantomData,
                   phantom_tt: PhantomData, }
    }

    #[cfg(feature = "nightly")]
    #[inline]
    pub const fn mk() -> Self {
        Identity { phantom_ss: PhantomData,
                   phantom_tt: PhantomData, }
    }
}

impl<S, T> Lenticuloid for Identity<S, T> {
    type InitialSource = S;

    type InitialTarget = S;

    type FinalSource = T;

    type FinalTarget = T;

    type AtInitial = Identity<S, S>;

    fn at_initial(&self) -> Self::AtInitial {
        Identity::mk()
    }

    type AtFinal = Identity<T, T>;

    fn at_final(&self) -> Self::AtFinal {
        Identity::mk()
    }
}

/// Composition of lenticuloids.
#[derive(Clone,Copy,Debug,Default)]
pub struct Compose<LF, LS: ?Sized> {
    first: LF,
    second: LS,
}

impl<LF, LS> Compose<LF, LS> {
    #[inline]
    pub fn of(lf: LF, ls: LS) -> Self {
        Compose { first: lf,
                  second: ls, }
    }
}

impl<LF: Lenticuloid, LS: ?Sized> Lenticuloid for Compose<LF, LS>
    where LS: Lenticuloid<InitialTarget = LF::InitialSource, FinalTarget = LF::FinalSource>
{
    type InitialSource = LS::InitialSource;

    type InitialTarget = LF::InitialTarget;

    type FinalSource = LS::FinalSource;

    type FinalTarget = LF::FinalTarget;

    type AtInitial = Compose<LF::AtInitial, LS::AtInitial>;

    fn at_initial(&self) -> Self::AtInitial {
        Compose::of(self.first.at_initial(), self.second.at_initial())
    }

    type AtFinal = Compose<LF::AtFinal, LS::AtFinal>;

    fn at_final(&self) -> Self::AtFinal {
        Compose::of(self.first.at_final(), self.second.at_final())
    }
}

/// The inversion of a lenticuloid.
#[derive(Clone,Copy,Debug,Default)]
pub struct Invert<L: ?Sized> {
    deinvert: L,
}

impl<L> Invert<L> {
    #[inline]
    pub fn of(l: L) -> Self {
        Invert { deinvert: l }
    }
}

impl<L: Lenticuloid + ?Sized> Lenticuloid for Invert<L> {
    type InitialSource = L::FinalTarget;

    type InitialTarget = L::FinalSource;

    type FinalSource = L::InitialTarget;

    type FinalTarget = L::InitialSource;

    type AtInitial = Invert<L::AtFinal>;

    fn at_initial(&self) -> Self::AtInitial {
        Invert::of(self.deinvert.at_final())
    }

    type AtFinal = Invert<L::AtInitial>;

    fn at_final(&self) -> Self::AtFinal {
        Invert::of(self.deinvert.at_initial())
    }
}

mod partial_lens;
pub use partial_lens::*;

mod lens;
pub use lens::*;

mod prism;
pub use prism::*;

mod iso;
pub use iso::*;

#[macro_use]
mod ops;
pub use ops::*;

pub mod access;

pub mod meta;

pub mod terminal;

pub mod conv;

pub mod errors;

pub mod collections;
<|endoftext|>


<commit_before>extern crate nalgebra as na;

use std::io::{self, Write};
pub use bounds::Bounds;
pub use na::Vec2;

pub mod bounds;

pub type Position = na::Pnt2<f32>;

fn pmin(p1: Position, p2: Position) -> Position {
    Position::new(p1.x.min(p2.x), p1.y.min(p2.y))
}

fn pmax(p1: Position, p2: Position) -> Position {
    Position::new(p1.x.max(p2.x), p1.y.max(p2.y))
}

fn ptransform(p: Position, translation: Vec2<f32>, scale: Vec2<f32>) -> Position {
    let n = p + translation;
    Position::new(n.x * scale.x, n.y * scale.y)
}

pub trait Shape {
    fn bounds(&self) -> Bounds;
    fn write_eps(&self, wr: &mut Write) -> io::Result<()>;
    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>);
}

pub struct SetRGB(pub f32, pub f32, pub f32);
pub struct Point(pub Position, pub f32);
pub struct Points(pub Vec<Position>, pub f32);
pub struct Line(pub Position, pub Position);
pub struct Lines(pub Vec<(Position, Position)>);

impl Shape for SetRGB {
    fn bounds(&self) -> Bounds {
        Bounds::new()
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr, "{:.2} {:.2} {:.2} setrgbcolor", self.0, self.1, self.2)
    }

    fn transform(&mut self, _translation: Vec2<f32>, _scale: Vec2<f32>) {}
}

impl Shape for Point {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        b.add_position(self.0);
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr,
                 "newpath {} {} {} 0 360 arc fill",
                 self.0.x,
                 self.0.y,
                 self.1)
    }

    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>) {
        self.0 = ptransform(self.0, translation, scale);
    }
}

impl Shape for Points {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        for &pos in &self.0 {
            b.add_position(pos);
        }
        b
    }

    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>) {
        for p in self.0.iter_mut() {
            *p = ptransform(*p, translation, scale);
        }
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        try!(writeln!(wr,
                      "/p {{
2 dict begin
/y exch def
/x exch def
gsave
newpath x y {} 0 360 \
                       arc fill
grestore
end
}} def",
                      self.1));
        for pos in &self.0 {
            try!(writeln!(wr, "{:.4} {:.4} p", pos.x, pos.y));
        }

        Ok(())
    }
}

impl Shape for Lines {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        for &(p1, p2) in &self.0 {
            b.add_position(p1);
            b.add_position(p2);
        }
        b
    }

    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>) {
        for &mut (ref mut p1, ref mut p2) in self.0.iter_mut() {
            *p1 = ptransform(*p1, translation, scale);
            *p2 = ptransform(*p2, translation, scale);
        }
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        try!(writeln!(wr,
                      "/l {{
2 dict begin
/y2 exch def
/x2 exch def
/y1 exch def
/x1 exch def
\
                       gsave
newpath x1 y1 moveto x2 y2 lineto stroke
grestore
end
}} def"));
        for &(p1, p2) in &self.0 {
            try!(writeln!(wr, "{:.4} {:.4} {:.4} {:.4} l", p1.x, p1.y, p2.x, p2.y));
        }

        Ok(())
    }
}

impl Shape for Line {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        b.add_position(self.0);
        b.add_position(self.1);
        b
    }

    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>) {
        self.0 = ptransform(self.0, translation, scale);
        self.1 = ptransform(self.1, translation, scale);
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr,
                 "newpath {} {} moveto {} {} lineto stroke",
                 self.0.x,
                 self.0.y,
                 self.1.x,
                 self.1.y)
    }
}

pub struct EpsDocument {
    shapes: Vec<Box<Shape>>,
}

impl EpsDocument {
    pub fn new() -> EpsDocument {
        EpsDocument { shapes: Vec::new() }
    }

    pub fn add_shape(&mut self, shape: Box<Shape>) {
        self.shapes.push(shape);
    }

    pub fn get_bounds(&self) -> Bounds {
        // Determine extend of canvas
        let mut bounds = Bounds::new();

        for shape in &self.shapes {
            bounds.extend(shape.bounds());
        }

        bounds
    }

    pub fn transform(&mut self, translate: Vec2<f32>, scale: Vec2<f32>) {
        for shape in self.shapes.iter_mut() {
            shape.transform(translate, scale);
        }
    }

    /// Write as Embedded Postscript (EPS)
    pub fn write_eps(&self, wr: &mut Write, min_width: f32, min_height: f32) -> io::Result<()> {
        let bounds = self.get_bounds();

        let width = bounds.width().max(min_width);
        let height = bounds.height().max(min_height);
        let border_percent = 0.1;

        let scale = 1.0 + 2.0 * border_percent;

        try!(writeln!(wr,
                      r#"%%!PS-Adobe-3.0 EPSF-3.0
%%Creator: https://github.com/mneumann/eps-writer-rs
%%DocumentData: Clean7Bit
%%Origin: 0 0
%%BoundingBox: {} {} {} {}
%%HiResBoundingBox: {} {} {} {}
%%LanguageLevel: 2
%%Pages: 1
%%Page: 1 1
"#,
                      (bounds.min_x() - border_percent * width) as isize,
                      (bounds.min_y() - border_percent * height) as isize,
                      (bounds.max_x() + border_percent * width) as isize,
                      (bounds.max_y() + border_percent * height) as isize,

                      bounds.min_x() - border_percent * width,
                      bounds.min_y() - border_percent * height,
                      bounds.max_x() + border_percent * width,
                      bounds.max_y() + border_percent * height));

        // use a stroke width of 0.1% of the width or height of the canvas
        let stroke_width = scale * width.max(height) / 1000.0;
        try!(writeln!(wr, r#"{} setlinewidth"#, stroke_width));

        for shape in &self.shapes {
            try!(shape.write_eps(wr));
        }

        writeln!(wr, "%%EOF")
    }
}
<commit_msg>Add PolyLine<commit_after>extern crate nalgebra as na;

use std::io::{self, Write};
pub use bounds::Bounds;
pub use na::Vec2;

pub mod bounds;

pub type Position = na::Pnt2<f32>;

fn pmin(p1: Position, p2: Position) -> Position {
    Position::new(p1.x.min(p2.x), p1.y.min(p2.y))
}

fn pmax(p1: Position, p2: Position) -> Position {
    Position::new(p1.x.max(p2.x), p1.y.max(p2.y))
}

fn ptransform(p: Position, translation: Vec2<f32>, scale: Vec2<f32>) -> Position {
    let n = p + translation;
    Position::new(n.x * scale.x, n.y * scale.y)
}

pub trait Shape {
    fn bounds(&self) -> Bounds;
    fn write_eps(&self, wr: &mut Write) -> io::Result<()>;
    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>);
}

pub struct SetRGB(pub f32, pub f32, pub f32);
pub struct Point(pub Position, pub f32);
pub struct Points(pub Vec<Position>, pub f32);
pub struct Line(pub Position, pub Position);
pub struct Lines(pub Vec<(Position, Position)>);
pub struct PolyLine(pub Vec<Position>);

impl Shape for SetRGB {
    fn bounds(&self) -> Bounds {
        Bounds::new()
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr, "{:.2} {:.2} {:.2} setrgbcolor", self.0, self.1, self.2)
    }

    fn transform(&mut self, _translation: Vec2<f32>, _scale: Vec2<f32>) {}
}

impl Shape for Point {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        b.add_position(self.0);
        b
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr,
                 "newpath {} {} {} 0 360 arc fill",
                 self.0.x,
                 self.0.y,
                 self.1)
    }

    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>) {
        self.0 = ptransform(self.0, translation, scale);
    }
}

impl Shape for Points {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        for &pos in &self.0 {
            b.add_position(pos);
        }
        b
    }

    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>) {
        for p in self.0.iter_mut() {
            *p = ptransform(*p, translation, scale);
        }
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        try!(writeln!(wr,
                      "/p {{
2 dict begin
/y exch def
/x exch def
gsave
newpath x y {} 0 360 \
                       arc fill
grestore
end
}} def",
                      self.1));
        for pos in &self.0 {
            try!(writeln!(wr, "{:.4} {:.4} p", pos.x, pos.y));
        }

        Ok(())
    }
}

impl Shape for Lines {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        for &(p1, p2) in &self.0 {
            b.add_position(p1);
            b.add_position(p2);
        }
        b
    }

    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>) {
        for &mut (ref mut p1, ref mut p2) in self.0.iter_mut() {
            *p1 = ptransform(*p1, translation, scale);
            *p2 = ptransform(*p2, translation, scale);
        }
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        try!(writeln!(wr,
                      "/l {{
2 dict begin
/y2 exch def
/x2 exch def
/y1 exch def
/x1 exch def
\
                       gsave
newpath x1 y1 moveto x2 y2 lineto stroke
grestore
end
}} def"));
        for &(p1, p2) in &self.0 {
            try!(writeln!(wr, "{:.4} {:.4} {:.4} {:.4} l", p1.x, p1.y, p2.x, p2.y));
        }

        Ok(())
    }
}

impl Shape for Line {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        b.add_position(self.0);
        b.add_position(self.1);
        b
    }

    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>) {
        self.0 = ptransform(self.0, translation, scale);
        self.1 = ptransform(self.1, translation, scale);
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        writeln!(wr,
                 "newpath {} {} moveto {} {} lineto stroke",
                 self.0.x,
                 self.0.y,
                 self.1.x,
                 self.1.y)
    }
}

impl Shape for PolyLine {
    fn bounds(&self) -> Bounds {
        let mut b = Bounds::new();
        for &p in &self.0 {
            b.add_position(p);
        }
        b
    }

    fn transform(&mut self, translation: Vec2<f32>, scale: Vec2<f32>) {
        for p in self.0.iter_mut() {
            *p = ptransform(*p, translation, scale);
        }
    }

    fn write_eps(&self, wr: &mut Write) -> io::Result<()> {
        match self.0.split_first() {
            Some((first, tail)) if tail.len() > 0 => {
                try!(write!(wr, "newpath {:.4} {:.4} moveto ", first.x, first.y));
                for l in tail {
                    try!(write!(wr, "{:.4} {:.4} lineto ", l.x, l.y));
                }
                try!(writeln!(wr, "stroke"));
            }
            _ => {}
        }
        Ok(())
    }
}

pub struct EpsDocument {
    shapes: Vec<Box<Shape>>,
}

impl EpsDocument {
    pub fn new() -> EpsDocument {
        EpsDocument { shapes: Vec::new() }
    }

    pub fn add_shape(&mut self, shape: Box<Shape>) {
        self.shapes.push(shape);
    }

    pub fn get_bounds(&self) -> Bounds {
        // Determine extend of canvas
        let mut bounds = Bounds::new();

        for shape in &self.shapes {
            bounds.extend(shape.bounds());
        }

        bounds
    }

    pub fn transform(&mut self, translate: Vec2<f32>, scale: Vec2<f32>) {
        for shape in self.shapes.iter_mut() {
            shape.transform(translate, scale);
        }
    }

    /// Write as Embedded Postscript (EPS)
    pub fn write_eps(&self, wr: &mut Write, min_width: f32, min_height: f32) -> io::Result<()> {
        let bounds = self.get_bounds();

        let width = bounds.width().max(min_width);
        let height = bounds.height().max(min_height);
        let border_percent = 0.1;

        let scale = 1.0 + 2.0 * border_percent;

        try!(writeln!(wr,
                      r#"%%!PS-Adobe-3.0 EPSF-3.0
%%Creator: https://github.com/mneumann/eps-writer-rs
%%DocumentData: Clean7Bit
%%Origin: 0 0
%%BoundingBox: {} {} {} {}
%%HiResBoundingBox: {} {} {} {}
%%LanguageLevel: 2
%%Pages: 1
%%Page: 1 1
"#,
                      (bounds.min_x() - border_percent * width) as isize,
                      (bounds.min_y() - border_percent * height) as isize,
                      (bounds.max_x() + border_percent * width) as isize,
                      (bounds.max_y() + border_percent * height) as isize,

                      bounds.min_x() - border_percent * width,
                      bounds.min_y() - border_percent * height,
                      bounds.max_x() + border_percent * width,
                      bounds.max_y() + border_percent * height));

        // use a stroke width of 0.1% of the width or height of the canvas
        let stroke_width = scale * width.max(height) / 1000.0;
        try!(writeln!(wr, r#"{} setlinewidth"#, stroke_width));

        for shape in &self.shapes {
            try!(shape.write_eps(wr));
        }

        writeln!(wr, "%%EOF")
    }
}
<|endoftext|>


<commit_before>//! A pure-Rust LDAP library using the Tokio stack.
//!
//! ## Usage
//!
//! In `Cargo.toml`:
//!
//! ```
//! [dependencies.ldap3]
//! version = "0.4"
//! ```
//!
//! In the crate root:
//!
//! ```
//! extern crate ldap3;
//! ```
//! ## Summary
//!
//! Although the library provides both synchronous and asynchronous interfaces,
//! presently the synchronous one is less likely to undergo breaking changes,
//! and is the preferred way to use the library. __The [`LdapConn`](struct.LdapConn.html)
//! structure is the starting point for all synchronous operations.__ [`LdapConnAsync`]
//! (struct.LdapConnAsync) is its asynchronous analogue, and [`Ldap`](struct.Ldap) is
//! the low-level asynchronous connection handle used by both.
//!
//! In the [struct list](#structs), async-related structs have an asterisk (__*__) after
//! the short description.
//!
//! Since the library is still in development, none of the interfaces should be considered
//! stable. If a breaking change of some component is planned, it will be noted in the
//! documentation with a bolded __Note__, and a link to the GitHub issue discussing the
//! change, if applicable. General, crate-level issues with the documentation can be
//! discussed [here](https://github.com/inejge/ldap3/issues/3).
//!
//! The documentation is written for readers familiar with LDAP concepts and terminology,
//! which it won't attempt to explain.

extern crate bytes;
extern crate byteorder;
#[macro_use]
extern crate futures;
#[macro_use]
extern crate lazy_static;
extern crate lber;
#[macro_use]
extern crate log;
#[cfg(feature = "tls")]
extern crate native_tls;
#[macro_use]
extern crate nom;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_proto;
extern crate tokio_service;
#[cfg(feature = "tls")]
extern crate tokio_tls;
#[cfg(all(unix, not(feature = "minimal")))]
extern crate tokio_uds;
#[cfg(all(unix, not(feature = "minimal")))]
extern crate tokio_uds_proto;
extern crate url;

mod abandon;
mod add;
mod bind;
mod compare;
mod conn;
pub mod controls {
    //! Control construction and parsing.
    //!
    //! A control can be associated with a request or a response. Several common
    //! controls, such as [`PagedResults`](struct.PagedResults.html), are implemented
    //! directly by this library. If an implemented control has the same form for
    //! the request and the response, there will be a single structure for both uses.
    //! (This is the case for `PagedResults`.) If the response control is different,
    //! its name will consist of the request control name with the `Resp` suffix.
    //!
    //! A request control can be created by instantiating its structure and converting
    //! it to ASN.1 with `into()` when constructing the request control vector in the
    //! call to [`with_controls()`](../struct.LdapConn.html#method.with_controls).
    //! A third-party control must implement the conversion from an instance
    //! of itself to [`RawControl`](struct.RawControl.html), a general form of control.
    //!
    //! `RawControl`, together with an optional instance of [`ControlType`]
    //! (types/index.html), forms the type [`Control`](struct.Control.html); a vector
    //! of `Control`s is part of the result of all LDAP operation which return one.
    //!
    //! The first element of `Control` will have a value if the parser recognizes
    //! the control's OID as one that is implemented by the library itself. Since the
    //! list of implemented controls is expected to grow, matching those values must
    //! be done through reexported types in the [`types`](types/index.html) module,
    //! and cannot be exhaustive.
    //!
    //! A recognized response control can be parsed by calling [`parse()`]
    //! (struct.RawControl.html#method.parse) on the instance of `RawControl` representing it.
    //! A third-party control must implement the [`ControlParser`](trait.ControlParser.html)
    //! trait to support this interface.
    pub use controls_impl::{Control, ControlParser, CriticalControl, MakeCritical, RawControl};
    pub use controls_impl::{Assertion, PagedResults, ProxyAuth, RelaxRules};
    pub use controls_impl::{PostRead, PostReadResp, PreRead, PreReadResp, ReadEntryResp};
    pub use controls_impl::types;
}
mod controls_impl;
mod delete;
mod extended;
mod exop_impl;
pub mod exop {
    //! Extended operation construction and parsing.
    //!
    //! A generic exop is represented by [`Exop`](struct.Exop.html). If a particular
    //! exop is implemented by this library, it may have one or two associated structs;
    //! one for constructing requests, and another for parsing responses. If request and
    //! response are the same, there is only the request struct; if they are different,
    //! the response struct's name will consist of the request struct name with the
    //! `Resp` suffix.
    //!
    //! A request struct must implement the `From` conversion of itself into `Exop`.
    //! A response struct must implement the [`ExopParser`](trait.ExopParser.html)
    //! trait.
    pub use exop_impl::{Exop, ExopParser, WhoAmI, WhoAmIResp};
}
mod filter;
mod ldap;
mod modify;
mod modifydn;
mod protocol;
pub mod result;
mod search;
mod unbind;
mod util;

pub use conn::{EntryStream, LdapConn, LdapConnAsync, LdapConnBuilder};
pub use filter::parse as parse_filter;
pub use ldap::Ldap;
pub use modify::Mod;
pub use result::LdapResult;
pub use search::{DerefAliases, ResultEntry, Scope, SearchEntry, SearchOptions, SearchStream};
pub use util::ldap_escape;

pub mod asn1 {
    //! ASN.1 structure construction and parsing.
    //!
    //! This section is deliberately under-documented; it's expected that the ASN.1 subsystem will
    //! be extensively overhauled in the future. If you need examples of using the present interface
    //! for, e.g., implementing a new extended operation or a control, consult the source of existing
    //! exops/controls.
    pub use lber::IResult;
    pub use lber::common::TagClass;
    pub use lber::structure::{PL, StructureTag};
    pub use lber::structures::{ASNTag, Boolean, Enumerated, ExplicitTag, Integer, Null, OctetString, Sequence, Set, Tag};
    pub use lber::parse::{parse_tag, parse_uint};
    pub use lber::write;
}
<commit_msg>Align docs with README.md and prepare for 0.5<commit_after>//! A pure-Rust LDAP library using the Tokio stack.
//!
//! ## Usage
//!
//! In `Cargo.toml`:
//!
//! ```
//! [dependencies.ldap3]
//! version = "0.5"
//! ```
//!
//! In the crate root (`src/lib.rs` or `src/main.rs`):
//!
//! ```
//! extern crate ldap3;
//! ```
//! ## Summary
//!
//! The library provides both synchronous and asynchronous interfaces. The [`LdapConn`]
//! (struct.LdapConn.html) structure is the starting point for all synchronous operations.
//! [`LdapConnAsync`](struct.LdapConnAsync) is its asynchronous analogue, and [`Ldap`](struct.Ldap) is
//! the low-level asynchronous connection handle used by both.
//!
//! In the [struct list](#structs), async-related structs have an asterisk (__*__) after
//! the short description.
//!
//! Since the library is still in development, none of the interfaces should be considered
//! stable. If a breaking change of some component is planned, it will be noted in the
//! documentation with a bolded __Note__, and a link to the GitHub issue discussing the
//! change, if applicable. General, crate-level issues with the documentation can be
//! discussed [here](https://github.com/inejge/ldap3/issues/3).
//!
//! The documentation is written for readers familiar with LDAP concepts and terminology,
//! which it won't attempt to explain.
//!
//! ## Examples
//!
//! The two examples in the text perform exactly the same operation and should produce identical
//! results. They should be run against the example server in the `data` subdirectory of the crate source.
//! Other sample programs expecting the same server setup can be found in the `examples` subdirectory.
//!
//! ### Synchronous search
//!
//! ```rust,no_run
//! extern crate ldap3;
//!
//! use std::error::Error;
//!
//! use ldap3::{LdapConn, Scope, SearchEntry};
//!
//! fn main() {
//!     match do_search() {
//!         Ok(_) => (),
//!         Err(e) => println!("{}", e),
//!     }
//! }
//!
//! fn do_search() -> Result<(), Box<Error>> {
//!     let ldap = LdapConn::new("ldap://localhost:2389")?;
//!     let (rs, _res) = ldap.search(
//!         "ou=Places,dc=example,dc=org",
//!         Scope::Subtree,
//!         "(&(objectClass=locality)(l=ma*))",
//!         vec!["l"]
//!     )?.success()?;
//!     for entry in rs {
//!         println!("{:?}", SearchEntry::construct(entry));
//!     }
//!     Ok(())
//! }
//! ```
//!
//! ### Asynchronous search
//!
//! ```rust,no_run
//! extern crate futures;
//! extern crate ldap3;
//! extern crate tokio_core;
//!
//! use std::error::Error;
//!
//! use futures::Future;
//! use ldap3::{LdapConnAsync, Scope, SearchEntry};
//! use tokio_core::reactor::Core;
//!
//! fn main() {
//!     match do_search() {
//!         Ok(_) => (),
//!         Err(e) => println!("{}", e),
//!     }
//! }
//!
//! fn do_search() -> Result<(), Box<Error>> {
//!     let mut core = Core::new()?;
//!     let handle = core.handle();
//!     let ldap = LdapConnAsync::new("ldap://localhost:2389", &handle)?;
//!     let srch = ldap.and_then(|ldap|
//!         ldap.search(
//!             "ou=Places,dc=example,dc=org",
//!             Scope::Subtree,
//!             "(&(objectClass=locality)(l=ma*))",
//!             vec!["l"]
//!         ))
//!         .and_then(|response| response.success())
//!         .and_then(|(rs, _res)| Ok(rs));
//!     let rs = core.run(srch)?;
//!     for entry in rs {
//!         println!("{:?}", SearchEntry::construct(entry));
//!     }
//!     Ok(())
//! }
//! ```

extern crate bytes;
extern crate byteorder;
#[macro_use]
extern crate futures;
#[macro_use]
extern crate lazy_static;
extern crate lber;
#[macro_use]
extern crate log;
#[cfg(feature = "tls")]
extern crate native_tls;
#[macro_use]
extern crate nom;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_proto;
extern crate tokio_service;
#[cfg(feature = "tls")]
extern crate tokio_tls;
#[cfg(all(unix, not(feature = "minimal")))]
extern crate tokio_uds;
#[cfg(all(unix, not(feature = "minimal")))]
extern crate tokio_uds_proto;
extern crate url;

mod abandon;
mod add;
mod bind;
mod compare;
mod conn;
pub mod controls {
    //! Control construction and parsing.
    //!
    //! A control can be associated with a request or a response. Several common
    //! controls, such as [`PagedResults`](struct.PagedResults.html), are implemented
    //! directly by this library. If an implemented control has the same form for
    //! the request and the response, there will be a single structure for both.
    //! (This is the case for `PagedResults`.) If the response control is different,
    //! its name will consist of the request control name with the `Resp` suffix.
    //!
    //! A request control can be created by instantiating its structure and converting
    //! it to ASN.1 with `into()` when passing the instance or constructing the request
    //! control vector in the call to [`with_controls()`](../struct.LdapConn.html#method.with_controls).
    //! A third-party control must implement the conversion from an instance
    //! of itself to [`RawControl`](struct.RawControl.html), a general form of control.
    //!
    //! `RawControl`, together with an optional instance of [`ControlType`]
    //! (types/index.html), forms the type [`Control`](struct.Control.html); a vector
    //! of `Control`s is part of the result of all LDAP operation which return one.
    //!
    //! The first element of `Control` will have a value if the parser recognizes
    //! the control's OID as one that is implemented by the library itself. Since the
    //! list of implemented controls is expected to grow, matching those values must
    //! be done through reexported types in the [`types`](types/index.html) module,
    //! and cannot be exhaustive.
    //!
    //! A recognized response control can be parsed by calling [`parse()`]
    //! (struct.RawControl.html#method.parse) on the instance of `RawControl` representing it.
    //! A third-party control must implement the [`ControlParser`](trait.ControlParser.html)
    //! trait to support this interface.
    pub use controls_impl::{Control, ControlParser, CriticalControl, MakeCritical, RawControl};
    pub use controls_impl::{Assertion, PagedResults, ProxyAuth, RelaxRules};
    pub use controls_impl::{PostRead, PostReadResp, PreRead, PreReadResp, ReadEntryResp};
    pub use controls_impl::types;
}
mod controls_impl;
mod delete;
mod extended;
mod exop_impl;
pub mod exop {
    //! Extended operation construction and parsing.
    //!
    //! A generic exop is represented by [`Exop`](struct.Exop.html). If a particular
    //! exop is implemented by this library, it may have one or two associated structs;
    //! one for constructing requests, and another for parsing responses. If request and
    //! response are the same, there is only the request struct; if they are different,
    //! the response struct's name will consist of the request struct name with the
    //! `Resp` suffix.
    //!
    //! A request struct must implement the `From` conversion of itself into `Exop`.
    //! A response struct must implement the [`ExopParser`](trait.ExopParser.html)
    //! trait.
    pub use exop_impl::{Exop, ExopParser, WhoAmI, WhoAmIResp};
}
mod filter;
mod ldap;
mod modify;
mod modifydn;
mod protocol;
pub mod result;
mod search;
mod unbind;
mod util;

pub use conn::{EntryStream, LdapConn, LdapConnAsync, LdapConnBuilder};
pub use filter::parse as parse_filter;
pub use ldap::Ldap;
pub use modify::Mod;
pub use result::LdapResult;
pub use search::{DerefAliases, ResultEntry, Scope, SearchEntry, SearchOptions, SearchStream};
pub use util::ldap_escape;

pub mod asn1 {
    //! ASN.1 structure construction and parsing.
    //!
    //! This section is deliberately under-documented; it's expected that the ASN.1 subsystem will
    //! be extensively overhauled in the future. If you need examples of using the present interface
    //! for, e.g., implementing a new extended operation or a control, consult the source of existing
    //! exops/controls.
    pub use lber::IResult;
    pub use lber::common::TagClass;
    pub use lber::structure::{PL, StructureTag};
    pub use lber::structures::{ASNTag, Boolean, Enumerated, ExplicitTag, Integer, Null, OctetString, Sequence, Set, Tag};
    pub use lber::parse::{parse_tag, parse_uint};
    pub use lber::write;
}
<|endoftext|>


<commit_before>extern crate num;

use num::traits::{ Float, ToPrimitive };

pub fn parse_numbers (args : &[String]) -> Vec<f64> {
    args.iter().enumerate().map(|(i, x)| {
        x.parse::<f64>().ok().expect(&format!("Argument \"{}\" was not a number :(", args[i]))
    }).collect()
}

/// Find the minimum and maximum for a slice of Float values.
///
/// ```
/// use sparkline::*;
/// let (x, y) = min_max_for_data(&vec![0.0, 1.0, 2.0], None, None);
/// assert_eq!(x, 0.0);
/// assert_eq!(y, 2.0);
/// let (x, y) = min_max_for_data(&vec![0.0, 1.0, 2.0], Some(-1.0), None);
/// assert_eq!(x, -1.0);
/// assert_eq!(y, 2.0);
/// let (x, y) = min_max_for_data(&vec![0.0, 1.0, 2.0], Some(1.0), None);
/// assert_eq!(x, 1.0);
/// assert_eq!(y, 2.0);
/// let (x, y) = min_max_for_data(&vec![0.0, 1.0, 2.0], None, Some(1.5));
/// assert_eq!(x, 0.0);
/// assert_eq!(y, 1.5);
/// ```
pub fn min_max_for_data<T>(numbers: &[T], min_opt: Option<T>, max_opt: Option<T>) -> (f64, f64) where T: Float {
    let max = match max_opt {
        Some(m) => m,
        None => numbers.iter().fold(T::min_value(), |a, b| a.max(*b)),
    };
    let min = match min_opt {
        Some(m) => m,
        None => numbers.iter().fold(T::max_value(), |a, b| a.min(*b)),
    };
    (min.to_f64().unwrap(), max.to_f64().unwrap())
}

pub trait SparkTheme {
    fn start(&mut self, min : f64, max : f64);
    fn spark(&mut self, num : f64) -> &str;
    fn end(&mut self) {}

    fn minmax(&self) -> (f64, f64);
    fn proportion(&self, num : f64) -> f64 {
        let (min, max) = self.minmax();

        (num - min) / (max - min)
    }
}

pub struct MappingTheme {
    pub sparks : Vec<String>,
    min : f64,
    max : f64,
}

impl SparkTheme for MappingTheme {
    fn start(&mut self, min : f64, max : f64) {
        self.min = min;
        self.max = max;
    }

    fn minmax(&self) -> (f64, f64) {
        (self.min, self.max)
    }

    fn spark(&mut self, num : f64) -> &str {
        let increments = self.sparks.len() as f64;

        let mut proportion = (increments) * self.proportion(num);

        // If num == max, then proportion will be out of bounds, so drop one
        if proportion == increments {
            proportion = proportion - 1.0;
        }

        &self.sparks[proportion.to_usize().unwrap()]
    }
}

fn colorise(x : &str) -> String {
    let reset = "\x1B[0m";

    match x {
        "▁"|"▂" => "\x1B[0;32m".to_owned() + x + reset,
        "▃"|"▄" => "\x1B[0;33m".to_owned() + x + reset,
        "▅"|"▆" => "\x1B[0;33m".to_owned() + x + reset,
        "▇"|"█" => "\x1B[0;31m".to_owned() + x + reset,
        _ => x.to_string(),
    }
}

pub fn select_sparkline(st : &str) -> Box<SparkTheme> {
    let sparks = "▁▂▃▄▅▆▇█";
    match st {
        "colour" => {
            let spark_chars : Vec<String> = sparks.chars().map(|x| colorise(&x.to_string())).collect();
            Box::new(MappingTheme {
                min: 0.0, max: 0.0,
                sparks: spark_chars
            })
        },
        _ => {
            Box::new(MappingTheme {
                min: 0.0, max: 0.0,
                sparks: sparks.chars().map(|x| x.to_string()).collect()
            })
        },
    }
}

#[test]
fn test_sparkline_mapping() {
    use SparkTheme;
    let (min, max) : (f64, f64) = (0.0, 10.0);
    let values = vec![2.0, 3.0, 2.0, 6.0, 9.0];
    let expected = "▂▃▂▅█".to_owned();
    let sparky = select_sparkline(SparkThemeName::Classic);

    for (num, compare) in values.iter().zip(expected.chars()) {
        let s : &String = sparky.spark(min, max, *num);
        println!("{}", num);
        assert_eq!(*s, compare.to_string());
    }

}
<commit_msg>fix test<commit_after>extern crate num;

use num::traits::{ Float, ToPrimitive };

pub fn parse_numbers (args : &[String]) -> Vec<f64> {
    args.iter().enumerate().map(|(i, x)| {
        x.parse::<f64>().ok().expect(&format!("Argument \"{}\" was not a number :(", args[i]))
    }).collect()
}

/// Find the minimum and maximum for a slice of Float values.
///
/// ```
/// use sparkline::*;
/// let (x, y) = min_max_for_data(&vec![0.0, 1.0, 2.0], None, None);
/// assert_eq!(x, 0.0);
/// assert_eq!(y, 2.0);
/// let (x, y) = min_max_for_data(&vec![0.0, 1.0, 2.0], Some(-1.0), None);
/// assert_eq!(x, -1.0);
/// assert_eq!(y, 2.0);
/// let (x, y) = min_max_for_data(&vec![0.0, 1.0, 2.0], Some(1.0), None);
/// assert_eq!(x, 1.0);
/// assert_eq!(y, 2.0);
/// let (x, y) = min_max_for_data(&vec![0.0, 1.0, 2.0], None, Some(1.5));
/// assert_eq!(x, 0.0);
/// assert_eq!(y, 1.5);
/// ```
pub fn min_max_for_data<T>(numbers: &[T], min_opt: Option<T>, max_opt: Option<T>) -> (f64, f64) where T: Float {
    let max = match max_opt {
        Some(m) => m,
        None => numbers.iter().fold(T::min_value(), |a, b| a.max(*b)),
    };
    let min = match min_opt {
        Some(m) => m,
        None => numbers.iter().fold(T::max_value(), |a, b| a.min(*b)),
    };
    (min.to_f64().unwrap(), max.to_f64().unwrap())
}

pub trait SparkTheme {
    fn start(&mut self, min : f64, max : f64);
    fn spark(&mut self, num : f64) -> &str;
    fn end(&mut self) {}

    fn minmax(&self) -> (f64, f64);
    fn proportion(&self, num : f64) -> f64 {
        let (min, max) = self.minmax();

        (num - min) / (max - min)
    }
}

pub struct MappingTheme {
    pub sparks : Vec<String>,
    min : f64,
    max : f64,
}

impl SparkTheme for MappingTheme {
    fn start(&mut self, min : f64, max : f64) {
        self.min = min;
        self.max = max;
    }

    fn minmax(&self) -> (f64, f64) {
        (self.min, self.max)
    }

    fn spark(&mut self, num : f64) -> &str {
        let increments = self.sparks.len() as f64;

        let mut proportion = (increments) * self.proportion(num);

        // If num == max, then proportion will be out of bounds, so drop one
        if proportion == increments {
            proportion = proportion - 1.0;
        }

        &self.sparks[proportion.to_usize().unwrap()]
    }
}

fn colorise(x : &str) -> String {
    let reset = "\x1B[0m";

    match x {
        "▁"|"▂" => "\x1B[0;32m".to_owned() + x + reset,
        "▃"|"▄" => "\x1B[0;33m".to_owned() + x + reset,
        "▅"|"▆" => "\x1B[0;33m".to_owned() + x + reset,
        "▇"|"█" => "\x1B[0;31m".to_owned() + x + reset,
        _ => x.to_string(),
    }
}

pub fn select_sparkline(st : &str) -> Box<SparkTheme> {
    let sparks = "▁▂▃▄▅▆▇█";
    match st {
        "colour" => {
            let spark_chars : Vec<String> = sparks.chars().map(|x| colorise(&x.to_string())).collect();
            Box::new(MappingTheme {
                min: 0.0, max: 0.0,
                sparks: spark_chars
            })
        },
        _ => {
            Box::new(MappingTheme {
                min: 0.0, max: 0.0,
                sparks: sparks.chars().map(|x| x.to_string()).collect()
            })
        },
    }
}

#[test]
fn test_sparkline_mapping() {
    let (min, max) : (f64, f64) = (0.0, 10.0);
    let values = vec![2.0, 3.0, 2.0, 6.0, 9.0];
    let expected = "▂▃▂▅█".to_owned();
    let mut sparky = select_sparkline("classic");

    sparky.start(min, max);
    for (num, compare) in values.iter().zip(expected.chars()) {
        let s : &str= sparky.spark(*num);
        println!("{}", num);
        assert_eq!(s, &compare.to_string());
    }

}
<|endoftext|>


<commit_before>#[macro_use] extern crate error_chain;
extern crate xcb;

#[macro_use] pub mod error;

use std::thread;
use xcb::{ Connection, Window, Atom,  };

pub struct Atoms {
    pub primary: Atom,
    pub clipboard: Atom,
    pub property: Atom,
    pub targets: Atom,
    pub string: Atom,
    pub utf8_string: Atom,
    pub incr: Atom
}

pub struct Clipboard {
    pub connection: Connection,
    pub window: Window,
    pub atoms: Atoms
}

impl Clipboard {
    pub fn new<'a, D>(displayname: D) -> error::Result<Self>
        where D: Into<Option<&'a str>>
    {
        let (connection, screen) = Connection::connect(displayname.into())
            .map_err(|err| err!(XcbConn, err))?;
        let window = connection.generate_id();

        {
            let screen = connection.get_setup().roots().nth(screen as usize)
                .ok_or(err!(XcbConn, ::xcb::ConnError::ClosedInvalidScreen))?;
            xcb::create_window(
                &connection,
                xcb::COPY_FROM_PARENT as u8,
                window, screen.root(),
                0, 0, 1, 1,
                0,
                xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                screen.root_visual(),
                &[(
                    xcb::CW_EVENT_MASK,
                    xcb::EVENT_MASK_STRUCTURE_NOTIFY | xcb::EVENT_MASK_PROPERTY_CHANGE
                )]
            );
            connection.flush();
        }

        Self::from_connection(connection, window)
    }

    pub fn from_connection(connection: Connection, window: Window) -> error::Result<Self> {
        macro_rules! intern_atom {
            ( $name:expr ) => {
                xcb::intern_atom(&connection, false, $name)
                    .get_reply()
                    .map_err(|err| err!(XcbGeneric, err))?.atom()
            }
        }

        let atoms = Atoms {
            primary: xcb::ATOM_PRIMARY,
            clipboard: intern_atom!("CLIPBOARD"),
            property: intern_atom!("THIS_CLIPBOARD_OUT"),
            targets: intern_atom!("TARGETS"),
            string: xcb::ATOM_STRING,
            utf8_string: intern_atom!("UTF8_STRING"),
            incr: intern_atom!("INCR")
        };

        Ok(Clipboard { connection, window, atoms })
    }

    pub fn load(&self, selection: Atom, target: Atom, property: Atom) -> error::Result<Vec<u8>> {
        let mut buff = Vec::new();
        let mut is_incr = false;

        xcb::convert_selection(
            &self.connection, self.window,
            selection, target, property,
            xcb::CURRENT_TIME
                // FIXME Clients should not use CurrentTime for the time argument of a ConvertSelection request.
                // Instead, they should use the timestamp of the event that caused the request to be made.
        );
        self.connection.flush();

        while let Some(event) = self.connection.wait_for_event() {
            match (event.response_type() & !0x80) {
                xcb::SELECTION_NOTIFY => {
                    let event = xcb::cast_event::<xcb::SelectionNotifyEvent>(&event);

                    if event.selection() != selection || event.property() != property {
                        continue
                    }

                    let reply = xcb::get_property(
                        &self.connection,
                        false, self.window,
                        event.property(), xcb::ATOM_ANY,
                        buff.len() as u32, ::std::u32::MAX // FIXME reasonable buffer size
                    )
                        .get_reply()
                        .map_err(|err| err!(XcbGeneric, err))?;

                    if reply.type_() == self.atoms.incr {
                        buff.reserve(reply.value::<isize>()[0] as usize);
                        xcb::delete_property(&self.connection, self.window, property);
                        is_incr = true;
                        continue
                    }

                    if reply.type_() != self.atoms.string
                        && reply.type_() != self.atoms.utf8_string
                    {
                        let name = xcb::get_atom_name(&self.connection, reply.type_())
                            .get_reply()
                            .map(|reply| reply.name().to_string())
                            .unwrap_or(String::from("Unknown"));
                        return Err(err!(NotSupportType, name));
                    }

                    buff.extend_from_slice(reply.value());
                    break
                },
                xcb::PROPERTY_NOTIFY if is_incr => {
                    // XXX how to test it?

                    let event = xcb::cast_event::<xcb::PropertyNotifyEvent>(&event);

                    if event.state() != xcb::PROPERTY_NEW_VALUE as u8 {
                        continue
                    }

                    let reply = xcb::get_property(
                        &self.connection,
                        true, self.window,
                        property, xcb::ATOM_ANY,
                        buff.len() as u32, ::std::u32::MAX // FIXME reasonable buffer size
                    )
                        .get_reply()
                        .map_err(|err| err!(XcbGeneric, err))?;

                    if reply.type_() != self.atoms.string
                        && reply.type_() != self.atoms.utf8_string
                    {
                        let name = xcb::get_atom_name(&self.connection, reply.type_())
                            .get_reply()
                            .map(|reply| reply.name().to_string())
                            .unwrap_or(String::from("Unknown"));
                        return Err(err!(NotSupportType, name));
                    }

                    if reply.bytes_after() == 0 {
                        break
                    } else {
                        buff.extend_from_slice(reply.value())
                    }
                }
                _ => ()
            }
        }

        xcb::delete_property(&self.connection, self.window, property);
        Ok(buff)
    }

    fn store(&self, selection: Atom, target: Atom, property: Atom) -> error::Result<()> {
        unimplemented!()
    }
}
<commit_msg>[Fixed] INCR support<commit_after>#[macro_use] extern crate error_chain;
extern crate xcb;

#[macro_use] pub mod error;

use std::thread;
use xcb::{ Connection, Window, Atom };

pub struct Atoms {
    pub primary: Atom,
    pub clipboard: Atom,
    pub property: Atom,
    pub targets: Atom,
    pub string: Atom,
    pub utf8_string: Atom,
    pub incr: Atom
}

pub struct Clipboard {
    pub connection: Connection,
    pub window: Window,
    pub atoms: Atoms
}

impl Clipboard {
    pub fn new<'a, D>(displayname: D) -> error::Result<Self>
        where D: Into<Option<&'a str>>
    {
        let (connection, screen) = Connection::connect(displayname.into())
            .map_err(|err| err!(XcbConn, err))?;
        let window = connection.generate_id();

        {
            let screen = connection.get_setup().roots().nth(screen as usize)
                .ok_or(err!(XcbConn, ::xcb::ConnError::ClosedInvalidScreen))?;
            xcb::create_window(
                &connection,
                xcb::COPY_FROM_PARENT as u8,
                window, screen.root(),
                0, 0, 1, 1,
                0,
                xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                screen.root_visual(),
                &[(
                    xcb::CW_EVENT_MASK,
                    xcb::EVENT_MASK_STRUCTURE_NOTIFY | xcb::EVENT_MASK_PROPERTY_CHANGE
                )]
            );
            connection.flush();
        }

        Self::from_connection(connection, window)
    }

    pub fn from_connection(connection: Connection, window: Window) -> error::Result<Self> {
        macro_rules! intern_atom {
            ( $name:expr ) => {
                xcb::intern_atom(&connection, false, $name)
                    .get_reply()
                    .map_err(|err| err!(XcbGeneric, err))?.atom()
            }
        }

        let atoms = Atoms {
            primary: xcb::ATOM_PRIMARY,
            clipboard: intern_atom!("CLIPBOARD"),
            property: intern_atom!("THIS_CLIPBOARD_OUT"),
            targets: intern_atom!("TARGETS"),
            string: xcb::ATOM_STRING,
            utf8_string: intern_atom!("UTF8_STRING"),
            incr: intern_atom!("INCR")
        };

        Ok(Clipboard { connection, window, atoms })
    }

    pub fn load(&self, selection: Atom, target: Atom, property: Atom) -> error::Result<Vec<u8>> {
        let mut buff = Vec::new();
        let mut is_incr = false;

        xcb::convert_selection(
            &self.connection, self.window,
            selection, target, property,
            xcb::CURRENT_TIME
                // FIXME Clients should not use CurrentTime for the time argument of a ConvertSelection request.
                // Instead, they should use the timestamp of the event that caused the request to be made.
        );
        self.connection.flush();

        while let Some(event) = self.connection.wait_for_event() {
            match (event.response_type() & !0x80) {
                xcb::SELECTION_NOTIFY => {
                    let event = xcb::cast_event::<xcb::SelectionNotifyEvent>(&event);

                    if event.selection() != selection || event.property() != property {
                        continue
                    }

                    let reply = xcb::get_property(
                        &self.connection,
                        false, self.window,
                        event.property(), xcb::ATOM_ANY,
                        buff.len() as u32, ::std::u32::MAX // FIXME reasonable buffer size
                    )
                        .get_reply()
                        .map_err(|err| err!(XcbGeneric, err))?;

                    if reply.type_() == self.atoms.incr {
                        buff.reserve(reply.value::<i32>()[0] as usize);
                        xcb::delete_property(&self.connection, self.window, property);
                        self.connection.flush();
                        is_incr = true;
                        continue
                    }

                    if reply.type_() != self.atoms.string
                        && reply.type_() != self.atoms.utf8_string
                    {
                        let name = xcb::get_atom_name(&self.connection, reply.type_())
                            .get_reply()
                            .map(|reply| reply.name().to_string())
                            .unwrap_or(format!("Unknown({})", reply.type_()));
                        return Err(err!(NotSupportType, name));
                    }

                    buff.extend_from_slice(reply.value());
                    break
                },
                xcb::PROPERTY_NOTIFY if is_incr => {
                    let event = xcb::cast_event::<xcb::PropertyNotifyEvent>(&event);

                    if event.state() != xcb::PROPERTY_NEW_VALUE as u8 {
                        continue
                    }

                    let length = xcb::get_property(
                        &self.connection,
                        false, self.window,
                        property, xcb::ATOM_ANY,
                        0, 0
                    )
                        .get_reply()
                        .map(|reply| reply.bytes_after())
                        .map_err(|err| err!(XcbGeneric, err))?;

                    let reply = xcb::get_property(
                        &self.connection,
                        true, self.window,
                        property, xcb::ATOM_ANY,
                        0, length
                    )
                        .get_reply()
                        .map_err(|err| err!(XcbGeneric, err))?;

                    if reply.type_() != self.atoms.string
                        && reply.type_() != self.atoms.utf8_string
                    {
                        continue
                    }

                    buff.extend_from_slice(reply.value());

                    if reply.value_len() == 0 {
                        break
                    }
                },
                _ => ()
            }
        }

        xcb::delete_property(&self.connection, self.window, property);
        self.connection.flush();
        Ok(buff)
    }

    fn store(&self, selection: Atom, target: Atom, property: Atom, value: &[u8]) -> error::Result<()> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::fmt;

#[derive(Clone, PartialEq, Eq)]
pub enum Token {
    Output,
    Input,
    Loop(Vec<Token>),
    Move(i32),
    Add(i32, i32),
    Set(i32, i32),
    MulCopy(i32, i32, i32),
    Scan(i32),
    LoadOut(i32, i32),
    LoadOutSet(i32),
    If(i32, Vec<Token>),
}
use Token::*;

impl fmt::Debug for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Output => write!(f, "Output"),
            Input => write!(f, "Input"),
            Move(offset) => write!(f, "Move(offset={})", offset),
            Add(offset, value) => write!(f, "Add(offset={}, value={})", offset, value),
            Set(offset, value) => write!(f, "Set(offset={}, value={})", offset, value),
            MulCopy(src, dest, mul) => {
                write!(f, "MulCopy(src={}, dest={}, mul={})", src, dest, mul)
            }
            Scan(offset) => write!(f, "Scan(offset={})", offset),
            LoadOut(offset, add) => write!(f, "LoadOut(offset={}, add={})", offset, add),
            LoadOutSet(value) => write!(f, "LoadOutSet(value={})", value),
            Loop(ref content) => write!(f, "Loop(content={:?})", content),
            If(offset, ref content) => write!(f, "If(offset={}, content={:?})", offset, content),
        }
    }
}

pub fn parse(code: &str) -> Vec<Token> {
    _parse(&mut code.chars())
}

fn _parse(chars: &mut std::str::Chars) -> Vec<Token> {
    let mut tokens = Vec::new();
    while let Some(i) = chars.next() {
        match i {
            '+' => tokens.push(Add(0, 1)),
            '-' => tokens.push(Add(0, -1)),
            '>' => tokens.push(Move(1)),
            '<' => tokens.push(Move(-1)),
            '[' => tokens.push(Loop(_parse(chars))),
            ']' => {
                break;
            }
            ',' => tokens.push(Input),
            '.' => {
                tokens.push(LoadOut(0, 0));
                tokens.push(Output);
            }
            _ => (),
        };
    }

    tokens
}

fn _optimize(tokens: &Vec<Token>) -> (Vec<Token>, BTreeMap<i32, i32>, BTreeMap<i32, i32>, i32) {
    let mut newtokens: Vec<Token> = Vec::with_capacity(tokens.len());
    let mut shift = 0;
    let mut do_output = false;
    // With HashMap, the order sometimes switches
    // in recursion, and the optimizer never exits.
    let mut adds: BTreeMap<i32, i32> = BTreeMap::new();
    let mut sets: BTreeMap<i32, i32> = BTreeMap::new();

    for token in tokens.iter() {
        match *token {
            Set(..) | Add(..) | Move(_) | LoadOut(..) | LoadOutSet(_) | Output => {}
            _ => {
                if do_output {
                    newtokens.push(Output);
                    do_output = false;
                }

                for (offset, value) in sets.iter() {
                    newtokens.push(Set(*offset, *value));
                }
                for (offset, value) in adds.iter() {
                    newtokens.push(Add(*offset, *value));
                }
                sets.clear();
                adds.clear();
            }
        }

        if shift != 0 {
            match *token {
                Loop(_) | Input | Scan(_) => {
                    newtokens.push(Move(shift));
                    shift = 0;
                }
                _ => {}
            }
        }

        match *token {
            Set(mut offset, val) => {
                offset += shift;
                // Add before Set does nothing; remove it
                adds.remove(&offset);
                sets.insert(offset, val);
            }
            Add(mut offset, mut val) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    val = sets.get(&offset).unwrap() + val;
                    sets.insert(offset, val);
                } else {
                    val = adds.get(&offset).unwrap_or(&0) + val;
                    adds.insert(offset, val);
                }
            }
            MulCopy(src, dest, mul) => newtokens.push(MulCopy(src + shift, dest + shift, mul)),
            // XXX Deal with shift in if, if those are ever generated
            // TODO Optimize inside of If?
            If(offset, ref contents) => newtokens.push(If(offset + shift, contents.clone())),
            Move(offset) => shift += offset,
            Output => do_output = true,
            LoadOut(mut offset, add) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    newtokens.push(LoadOutSet(sets.get(&offset).unwrap() + add));
                } else {
                    newtokens.push(LoadOut(offset, adds.get(&offset).unwrap_or(&0) + add));
                }
            }
            Loop(ref contents) => {
                if let Some(token) = _optimize_loop(contents, &mut sets, &mut adds, &mut shift) {
                    newtokens.push(token);
                }
            }
            LoadOutSet(value) => newtokens.push(LoadOutSet(value)),
            Input => newtokens.push(Input),
            Scan(offset) => newtokens.push(Scan(offset + shift)),
        }
    }

    if do_output {
        newtokens.push(Output);
    }

    (newtokens, sets, adds, shift)
}

fn _optimize_loop(tokens: &Vec<Token>,
                  outer_sets: &mut BTreeMap<i32, i32>,
                  outer_adds: &mut BTreeMap<i32, i32>,
                  outer_shift: &mut i32)
                  -> Option<Token> {
    let (mut newtokens, sets, adds, shift) = _optimize(tokens);

    if shift != 0 && sets.is_empty() && adds.is_empty() && newtokens.is_empty() {
        Some(Scan(shift))
    } else if shift == 0 && newtokens.is_empty() && adds.contains_key(&0) && adds.len() == 1 &&
              sets.is_empty() {
        // TODO: Implement when !sets.is_empty()
        outer_sets.insert(0, 0);

        None
    } else {
        for (offset, value) in sets.iter() {
            newtokens.push(Set(*offset, *value));
        }
        for (offset, value) in adds.iter() {
            newtokens.push(Add(*offset, *value));
        }
        if shift != 0 {
            newtokens.push(Move(shift));
        }

        Some(Loop(newtokens))
    }
}

pub fn optimize(tokens: Vec<Token>) -> Vec<Token> {
    let mut oldtokens = tokens;
    // Ignore sets/adds/shifts at end of file
    let mut newtokens = _optimize(&oldtokens).0;
    while newtokens != oldtokens {
        oldtokens = newtokens;
        newtokens = _optimize(&oldtokens).0;
    }
    newtokens
}
<commit_msg>Pass outer tokens as argument to _optimize_loop()<commit_after>use std::collections::BTreeMap;
use std::fmt;

#[derive(Clone, PartialEq, Eq)]
pub enum Token {
    Output,
    Input,
    Loop(Vec<Token>),
    Move(i32),
    Add(i32, i32),
    Set(i32, i32),
    MulCopy(i32, i32, i32),
    Scan(i32),
    LoadOut(i32, i32),
    LoadOutSet(i32),
    If(i32, Vec<Token>),
}
use Token::*;

impl fmt::Debug for Token {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Output => write!(f, "Output"),
            Input => write!(f, "Input"),
            Move(offset) => write!(f, "Move(offset={})", offset),
            Add(offset, value) => write!(f, "Add(offset={}, value={})", offset, value),
            Set(offset, value) => write!(f, "Set(offset={}, value={})", offset, value),
            MulCopy(src, dest, mul) => {
                write!(f, "MulCopy(src={}, dest={}, mul={})", src, dest, mul)
            }
            Scan(offset) => write!(f, "Scan(offset={})", offset),
            LoadOut(offset, add) => write!(f, "LoadOut(offset={}, add={})", offset, add),
            LoadOutSet(value) => write!(f, "LoadOutSet(value={})", value),
            Loop(ref content) => write!(f, "Loop(content={:?})", content),
            If(offset, ref content) => write!(f, "If(offset={}, content={:?})", offset, content),
        }
    }
}

pub fn parse(code: &str) -> Vec<Token> {
    _parse(&mut code.chars())
}

fn _parse(chars: &mut std::str::Chars) -> Vec<Token> {
    let mut tokens = Vec::new();
    while let Some(i) = chars.next() {
        match i {
            '+' => tokens.push(Add(0, 1)),
            '-' => tokens.push(Add(0, -1)),
            '>' => tokens.push(Move(1)),
            '<' => tokens.push(Move(-1)),
            '[' => tokens.push(Loop(_parse(chars))),
            ']' => {
                break;
            }
            ',' => tokens.push(Input),
            '.' => {
                tokens.push(LoadOut(0, 0));
                tokens.push(Output);
            }
            _ => (),
        };
    }

    tokens
}

fn _optimize(tokens: &Vec<Token>) -> (Vec<Token>, BTreeMap<i32, i32>, BTreeMap<i32, i32>, i32) {
    let mut newtokens: Vec<Token> = Vec::with_capacity(tokens.len());
    let mut shift = 0;
    let mut do_output = false;
    // With HashMap, the order sometimes switches
    // in recursion, and the optimizer never exits.
    let mut adds: BTreeMap<i32, i32> = BTreeMap::new();
    let mut sets: BTreeMap<i32, i32> = BTreeMap::new();

    for token in tokens.iter() {
        match *token {
            Set(..) | Add(..) | Move(_) | LoadOut(..) | LoadOutSet(_) | Output => {}
            _ => {
                if do_output {
                    newtokens.push(Output);
                    do_output = false;
                }

                for (offset, value) in sets.iter() {
                    newtokens.push(Set(*offset, *value));
                }
                for (offset, value) in adds.iter() {
                    newtokens.push(Add(*offset, *value));
                }
                sets.clear();
                adds.clear();
            }
        }

        if shift != 0 {
            match *token {
                Loop(_) | Input | Scan(_) => {
                    newtokens.push(Move(shift));
                    shift = 0;
                }
                _ => {}
            }
        }

        match *token {
            Set(mut offset, val) => {
                offset += shift;
                // Add before Set does nothing; remove it
                adds.remove(&offset);
                sets.insert(offset, val);
            }
            Add(mut offset, mut val) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    val = sets.get(&offset).unwrap() + val;
                    sets.insert(offset, val);
                } else {
                    val = adds.get(&offset).unwrap_or(&0) + val;
                    adds.insert(offset, val);
                }
            }
            MulCopy(src, dest, mul) => newtokens.push(MulCopy(src + shift, dest + shift, mul)),
            // XXX Deal with shift in if, if those are ever generated
            // TODO Optimize inside of If?
            If(offset, ref contents) => newtokens.push(If(offset + shift, contents.clone())),
            Move(offset) => shift += offset,
            Output => do_output = true,
            LoadOut(mut offset, add) => {
                offset += shift;
                if sets.contains_key(&offset) {
                    newtokens.push(LoadOutSet(sets.get(&offset).unwrap() + add));
                } else {
                    newtokens.push(LoadOut(offset, adds.get(&offset).unwrap_or(&0) + add));
                }
            }
            Loop(ref contents) => {
                _optimize_loop(contents, &mut newtokens, &mut sets, &mut adds, &mut shift)
            }
            LoadOutSet(value) => newtokens.push(LoadOutSet(value)),
            Input => newtokens.push(Input),
            Scan(offset) => newtokens.push(Scan(offset + shift)),
        }
    }

    if do_output {
        newtokens.push(Output);
    }

    (newtokens, sets, adds, shift)
}

fn _optimize_loop(tokens: &Vec<Token>,
                  outer_tokens: &mut Vec<Token>,
                  outer_sets: &mut BTreeMap<i32, i32>,
                  outer_adds: &mut BTreeMap<i32, i32>,
                  outer_shift: &mut i32) {
    let (mut newtokens, sets, adds, shift) = _optimize(tokens);

    if shift != 0 && sets.is_empty() && adds.is_empty() && newtokens.is_empty() {
        outer_tokens.push(Scan(shift));
    } else if shift == 0 && newtokens.is_empty() && adds.contains_key(&0) && adds.len() == 1 &&
              sets.is_empty() {
        // TODO: Implement when !sets.is_empty()
        outer_sets.insert(0, 0);
    } else {
        for (offset, value) in sets.iter() {
            newtokens.push(Set(*offset, *value));
        }
        for (offset, value) in adds.iter() {
            newtokens.push(Add(*offset, *value));
        }
        if shift != 0 {
            newtokens.push(Move(shift));
        }

        outer_tokens.push(Loop(newtokens));
    }
}

pub fn optimize(tokens: Vec<Token>) -> Vec<Token> {
    let mut oldtokens = tokens;
    // Ignore sets/adds/shifts at end of file
    let mut newtokens = _optimize(&oldtokens).0;
    while newtokens != oldtokens {
        oldtokens = newtokens;
        newtokens = _optimize(&oldtokens).0;
    }
    newtokens
}
<|endoftext|>