<commit_before>#![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 Zipper, 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\"))"];
    }
}
<commit_msg>Implement some more Navigator methods.<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 Zipper, 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 {
        if self.is_root() {
            return false;
        }
        self.path[self.path.len() - 1].index > 0
    }

    pub fn has_right(&self) -> bool {
        if self.is_root() {
            return false;
        }
        let parent = &self.path[self.path.len() - 1];
        parent.index + 1 < parent.tree.children.len()
    }

    pub fn to_left(&mut self) {
        match self.path.pop() {
            None => panic!["root node has no siblings"],
            Some(mut parent) => {
                if parent.index == 0 {
                    panic!["already at leftmost sibling"];
                }
                parent.index -= 1;
                self.here = &parent.tree.children[parent.index];
                self.path.push(parent);
            },
        }
    }

    pub fn to_right(&mut self) {
        match self.path.pop() {
            None => panic!["root node has no siblings"],
            Some(mut parent) => {
                parent.index += 1;
                if parent.index >= parent.tree.children.len() {
                    panic!["already at rightmost sibling"];
                }
                self.here = &parent.tree.children[parent.index];
                self.path.push(parent);
            },
        }
    }
}

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>extern crate num;

use std::ops::{Add, Sub, Mul, Div, Rem};
use std::cmp::{PartialEq, Eq};
use num::{Zero, One, Num, FromPrimitive, ToPrimitive};

macro_rules! unsigned_fixed_point_impl {
    ($name:ident: $ty:ty, $tyd:ty, $ibits:expr, $fbits:expr) => {
        struct $name {
            base: $ty,
        }

        impl Add for $name {
            type Output = Self;
            fn add(self, rhs: Self) -> Self {
                $name {
                    base: self.base + rhs.base
                }
            }
        }

        impl Sub for $name {
            type Output = Self;
            fn sub(self, rhs: Self) -> Self {
                $name {
                    base: self.base - rhs.base
                }
            }
        }

        impl Mul for $name {
            type Output = Self;
            fn mul(self, rhs: Self) -> Self {
                $name {
                    base: ((self.base as $tyd * rhs.base as $tyd) >> $fbits) as $ty,
                }
            }
        }

        impl Div for $name {
            type Output = Self;
            fn div(self, rhs: Self) -> Self {
                $name {
                    base: (((self.base as $tyd) << $fbits) / (rhs.base as $tyd)) as $ty,
                }
            }
        }

        impl Rem for $name {
            type Output = Self;
            fn rem(self, rhs: Self) -> Self {
                $name {
                    base: self.base % rhs.base,
                }
            }
        }

        impl Zero for $name {
            fn zero() -> Self {
                $name {
                    base: 0,
                }
            }

            fn is_zero(&self) -> bool {
                self.base == 0
            }
        }

        impl One for $name {
            fn one() -> Self {
                $name {
                    base: 1 << $fbits,
                }
            }
        }

        impl PartialEq for $name {
            fn eq(&self, other: &Self) -> bool {
                self.base == other.base
            }
        }

        impl Eq for $name { }

        impl Num for $name {
            type FromStrRadixErr = ();
            fn from_str_radix(_str: &str, _radix: u32) -> Result<Self, Self::FromStrRadixErr> {
                unimplemented!();
            }
        }

        impl FromPrimitive for $name {
            fn from_i64(n: i64) -> Option<Self> {
                if n < 0 || n >= (1 << $ibits) {
                    None
                } else {
                    Some($name {
                        base: n as $ty << $fbits,
                    })
                }
            }

            fn from_u64(n: u64) -> Option<Self> {
                if n >= (1 << $ibits) {
                    None
                } else {
                    Some($name {
                        base: n as $ty << $fbits,
                    })
                }
            }

            fn from_f64(n: f64) -> Option<Self> {
                if n < 0.0 || n >= (1 << $ibits) as f64 {
                    None
                } else {
                    Some($name {
                        base: (n * ((1 << $fbits) as f64)) as $ty,
                    })
                }
            }
        }

        impl ToPrimitive for $name {
            fn to_i64(&self) -> Option<i64> {
                Some((self.base >> $fbits) as i64)
            }

            fn to_u64(&self) -> Option<u64> {
                Some((self.base >> $fbits) as u64)
            }

            fn to_f64(&self) -> Option<f64> {
                Some(self.base as f64 / (1 << $fbits) as f64)
            }
        }
    };
}

unsigned_fixed_point_impl!(U24p8: u32, u64, 24, 8);
<commit_msg>Added Bounded to unsigned fixed point.<commit_after>extern crate num;

use std::ops::{Add, Sub, Mul, Div, Rem};
use std::cmp::{PartialEq, Eq};
use num::{Zero, One, Num, FromPrimitive, ToPrimitive, Bounded};

macro_rules! unsigned_fixed_point_impl {
    ($name:ident: $ty:ty, $tyd:ty, $ibits:expr, $fbits:expr) => {
        struct $name {
            base: $ty,
        }

        impl Add for $name {
            type Output = Self;
            fn add(self, rhs: Self) -> Self {
                $name {
                    base: self.base + rhs.base
                }
            }
        }

        impl Sub for $name {
            type Output = Self;
            fn sub(self, rhs: Self) -> Self {
                $name {
                    base: self.base - rhs.base
                }
            }
        }

        impl Mul for $name {
            type Output = Self;
            fn mul(self, rhs: Self) -> Self {
                $name {
                    base: ((self.base as $tyd * rhs.base as $tyd) >> $fbits) as $ty,
                }
            }
        }

        impl Div for $name {
            type Output = Self;
            fn div(self, rhs: Self) -> Self {
                $name {
                    base: (((self.base as $tyd) << $fbits) / (rhs.base as $tyd)) as $ty,
                }
            }
        }

        impl Rem for $name {
            type Output = Self;
            fn rem(self, rhs: Self) -> Self {
                $name {
                    base: self.base % rhs.base,
                }
            }
        }

        impl Zero for $name {
            fn zero() -> Self {
                $name {
                    base: 0,
                }
            }

            fn is_zero(&self) -> bool {
                self.base == 0
            }
        }

        impl One for $name {
            fn one() -> Self {
                $name {
                    base: 1 << $fbits,
                }
            }
        }

        impl PartialEq for $name {
            fn eq(&self, other: &Self) -> bool {
                self.base == other.base
            }
        }

        impl Eq for $name { }

        impl Num for $name {
            type FromStrRadixErr = ();
            fn from_str_radix(_str: &str, _radix: u32) -> Result<Self, Self::FromStrRadixErr> {
                unimplemented!();
            }
        }

        impl FromPrimitive for $name {
            fn from_i64(n: i64) -> Option<Self> {
                if n < 0 || n >= (1 << $ibits) {
                    None
                } else {
                    Some($name {
                        base: n as $ty << $fbits,
                    })
                }
            }

            fn from_u64(n: u64) -> Option<Self> {
                if n >= (1 << $ibits) {
                    None
                } else {
                    Some($name {
                        base: n as $ty << $fbits,
                    })
                }
            }

            fn from_f64(n: f64) -> Option<Self> {
                if n < 0.0 || n >= (1 << $ibits) as f64 {
                    None
                } else {
                    Some($name {
                        base: (n * ((1 << $fbits) as f64)) as $ty,
                    })
                }
            }
        }

        impl ToPrimitive for $name {
            fn to_i64(&self) -> Option<i64> {
                Some((self.base >> $fbits) as i64)
            }

            fn to_u64(&self) -> Option<u64> {
                Some((self.base >> $fbits) as u64)
            }

            fn to_f64(&self) -> Option<f64> {
                Some(self.base as f64 / (1 << $fbits) as f64)
            }
        }

        impl Bounded for $name {
            fn min_value() -> Self {
                $name {
                    base: 0,
                }
            }

            fn max_value() -> Self {
                $name {
                    base: Bounded::max_value(),
                }
            }
        }
    };
}

unsigned_fixed_point_impl!(U24p8: u32, u64, 24, 8);
<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! FFI bindings to user32.
#![no_std]
#![experimental]
extern crate winapi;
use winapi::*;
extern "system" {
    pub fn AdjustWindowRectEx(
        lpRect: LPRECT, dwStyle: DWORD, bMenu: BOOL, dwExStyle: DWORD,
    ) -> BOOL;
    pub fn BeginPaint(hwnd: HWND, lpPaint: LPPAINTSTRUCT) -> HDC;
    pub fn ChangeDisplaySettingsW(lpDevMode: *mut DEVMODEW, dwFlags: DWORD) -> LONG;
    pub fn ChangeDisplaySettingsExW(
        lpszDeviceName: LPCWSTR, lpDevMode: *mut DEVMODEW, hwnd: HWND, dwFlags: DWORD,
        lParam: LPVOID,
    ) -> LONG;
    pub fn CreateWindowExW(
        dwExStyle: DWORD, lpClassName: LPCWSTR, lpWindowName: LPCWSTR, dwStyle: DWORD, x: c_int,
        y: c_int, nWidth: c_int, nHeight: c_int, hWndParent: HWND, hMenu: HMENU,
        hInstance: HINSTANCE, lpParam: LPVOID,
    ) -> HWND;
    pub fn DefWindowProcW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT;
    pub fn DestroyWindow(hWnd: HWND) -> BOOL;
    pub fn DispatchMessageW(lpmsg: *const MSG) -> LRESULT;
    pub fn EndPaint(hWnd: HWND, lpPaint: *const PAINTSTRUCT) -> BOOL;
    pub fn EnumDisplayDevicesW(
        lpDevice: LPCWSTR, iDevNum: DWORD, lpDisplayDevice: PDISPLAY_DEVICEW, dwFlags: DWORD,
    ) -> BOOL;
    pub fn EnumDisplaySettingsExW(
        lpszDeviceName: LPCWSTR, iModeNum: DWORD, lpDevMode: *mut DEVMODEW, dwFlags: DWORD,
    ) -> BOOL;
    pub fn FillRect(hDC: HDC, lprc: *const RECT, hbr: HBRUSH) -> c_int;
    pub fn FindWindowA (lpClassName: LPCSTR, lpWindowName: LPCSTR) -> HWND;
    pub fn GetClientRect(hWnd: HWND, lpRect: LPRECT) -> BOOL;
    pub fn GetDC(hWnd: HWND) -> HDC;
    pub fn GetMessageW(lpMsg: LPMSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) -> BOOL;
    pub fn GetWindowPlacement(hWnd: HWND, lpwndpl: *mut WINDOWPLACEMENT) -> BOOL;
    pub fn GetWindowRect(hWnd: HWND, lpRect: LPRECT) -> BOOL;
    pub fn MessageBoxA(hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT) -> c_int;
    pub fn MessageBoxW(hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT) -> c_int;
    pub fn MessageBoxExA(
        hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT, wLanguageId: WORD,
    ) -> c_int;
    pub fn MessageBoxExW(
        hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT, wLanguageId: WORD,
    ) -> c_int;
    pub fn PeekMessageW(
        lpMsg: LPMSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT, wRemoveMsg: UINT,
    ) -> BOOL;
    pub fn PostMessageW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> BOOL;
    pub fn PostQuitMessage(nExitCode: c_int);
    pub fn RegisterClassExW(lpWndClass: *const WNDCLASSEXW) -> ATOM;
    pub fn SendInput(nInputs: UINT, pInputs: LPINPUT, cbSize: c_int) -> UINT;
    pub fn SetForegroundWindow(hWnd: HWND) -> BOOL;
    pub fn SetWindowPos(
        hWnd: HWND, hWndInsertAfter: HWND, X: c_int, Y: c_int, cx: c_int, cy: c_int, uFlags: UINT,
    ) -> BOOL;
    pub fn SetWindowTextW(hWnd: HWND, lpString: LPCWSTR) -> BOOL;
    pub fn ShowWindow(hWnd: HWND, nCmdShow: c_int) -> BOOL;
    pub fn TranslateMessage(lpmsg: *const MSG) -> BOOL;
    pub fn UpdateWindow(hWnd: HWND) -> BOOL;
    pub fn WaitMessage() -> BOOL;
}
<commit_msg>Add GetSystemMetrics<commit_after>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
//! FFI bindings to user32.
#![no_std]
#![experimental]
extern crate winapi;
use winapi::*;
extern "system" {
    pub fn AdjustWindowRectEx(
        lpRect: LPRECT, dwStyle: DWORD, bMenu: BOOL, dwExStyle: DWORD,
    ) -> BOOL;
    pub fn BeginPaint(hwnd: HWND, lpPaint: LPPAINTSTRUCT) -> HDC;
    pub fn ChangeDisplaySettingsW(lpDevMode: *mut DEVMODEW, dwFlags: DWORD) -> LONG;
    pub fn ChangeDisplaySettingsExW(
        lpszDeviceName: LPCWSTR, lpDevMode: *mut DEVMODEW, hwnd: HWND, dwFlags: DWORD,
        lParam: LPVOID,
    ) -> LONG;
    pub fn CreateWindowExW(
        dwExStyle: DWORD, lpClassName: LPCWSTR, lpWindowName: LPCWSTR, dwStyle: DWORD, x: c_int,
        y: c_int, nWidth: c_int, nHeight: c_int, hWndParent: HWND, hMenu: HMENU,
        hInstance: HINSTANCE, lpParam: LPVOID,
    ) -> HWND;
    pub fn DefWindowProcW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> LRESULT;
    pub fn DestroyWindow(hWnd: HWND) -> BOOL;
    pub fn DispatchMessageW(lpmsg: *const MSG) -> LRESULT;
    pub fn EndPaint(hWnd: HWND, lpPaint: *const PAINTSTRUCT) -> BOOL;
    pub fn EnumDisplayDevicesW(
        lpDevice: LPCWSTR, iDevNum: DWORD, lpDisplayDevice: PDISPLAY_DEVICEW, dwFlags: DWORD,
    ) -> BOOL;
    pub fn EnumDisplaySettingsExW(
        lpszDeviceName: LPCWSTR, iModeNum: DWORD, lpDevMode: *mut DEVMODEW, dwFlags: DWORD,
    ) -> BOOL;
    pub fn FillRect(hDC: HDC, lprc: *const RECT, hbr: HBRUSH) -> c_int;
    pub fn FindWindowA (lpClassName: LPCSTR, lpWindowName: LPCSTR) -> HWND;
    pub fn GetClientRect(hWnd: HWND, lpRect: LPRECT) -> BOOL;
    pub fn GetDC(hWnd: HWND) -> HDC;
    pub fn GetMessageW(lpMsg: LPMSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT) -> BOOL;
    pub fn GetWindowPlacement(hWnd: HWND, lpwndpl: *mut WINDOWPLACEMENT) -> BOOL;
    pub fn GetWindowRect(hWnd: HWND, lpRect: LPRECT) -> BOOL;
    pub fn GetSystemMetrics(nIndex: c_int) -> c_int;
    pub fn MessageBoxA(hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT) -> c_int;
    pub fn MessageBoxW(hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT) -> c_int;
    pub fn MessageBoxExA(
        hWnd: HWND, lpText: LPCSTR, lpCaption: LPCSTR, uType: UINT, wLanguageId: WORD,
    ) -> c_int;
    pub fn MessageBoxExW(
        hWnd: HWND, lpText: LPCWSTR, lpCaption: LPCWSTR, uType: UINT, wLanguageId: WORD,
    ) -> c_int;
    pub fn PeekMessageW(
        lpMsg: LPMSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT, wRemoveMsg: UINT,
    ) -> BOOL;
    pub fn PostMessageW(hWnd: HWND, Msg: UINT, wParam: WPARAM, lParam: LPARAM) -> BOOL;
    pub fn PostQuitMessage(nExitCode: c_int);
    pub fn RegisterClassExW(lpWndClass: *const WNDCLASSEXW) -> ATOM;
    pub fn SendInput(nInputs: UINT, pInputs: LPINPUT, cbSize: c_int) -> UINT;
    pub fn SetForegroundWindow(hWnd: HWND) -> BOOL;
    pub fn SetWindowPos(
        hWnd: HWND, hWndInsertAfter: HWND, X: c_int, Y: c_int, cx: c_int, cy: c_int, uFlags: UINT,
    ) -> BOOL;
    pub fn SetWindowTextW(hWnd: HWND, lpString: LPCWSTR) -> BOOL;
    pub fn ShowWindow(hWnd: HWND, nCmdShow: c_int) -> BOOL;
    pub fn TranslateMessage(lpmsg: *const MSG) -> BOOL;
    pub fn UpdateWindow(hWnd: HWND) -> BOOL;
    pub fn WaitMessage() -> BOOL;
}
<|endoftext|>


<commit_before>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # **glib**, **gobject** and **gio** bindings for Rust
//!
//! This library contains
//!
//! - bindings to some essential GLib, GObject, GIO types and APIs,
//!
//! - common building blocks used in both handmade and machine generated
//! bindings to GTK+ and other GLib-based libraries.
//!
//! It is the foundation for higher level libraries with uniform Rusty (safe and
//! strongly typed) APIs. It avoids exposing GLib-specific data types where
//! possible and is not meant to provide comprehensive GLib bindings, which
//! would often amount to duplicating the Rust Standard Library or other utility
//! crates.
//!
//! The library is a work in progress: expect missing functionality and breaking
//! changes.
//!
//! # Dynamic typing
//!
//! Most types in the GLib family have type identifiers
//! ([`Type`](types/enum.Type.html)). Their corresponding Rust types implement
//! the [`StaticType`](types/trait.StaticType.html) trait.
//!
//! Dynamically typed [`Value`](value/index.html) can carry values of any `T:
//! StaticType`.
//!
//! [`Variant`](variant/index.html) can carry values of `T: StaticVariantType`.
//!
//! # Errors
//!
//! Errors are represented by [`Error`](error/struct.Error.html), which can
//! carry values from various [error
//! domains](error/trait.ErrorDomain.html#implementors) (such as
//! [`FileError`](enum.FileError.html)).
//!
//! # Objects
//!
//! Each class and interface has a corresponding smart pointer struct
//! representing an instance of that type (e.g. `Object` for `GObject`,
//! `gtk::Widget` for `GtkWidget`). They are reference counted and feature
//! interior mutability similarly to Rust's `Rc<RefCell<T>>` idiom.
//! Consequently, cloning objects is cheap and their methods never require
//! mutable borrows. Two smart pointers are equal iff they point to the same
//! object.
//!
//! The root of the object hierarchy is [`Object`](object/struct.Object.html).
//! Inheritance and subtyping is denoted with the [`IsA`](object/trait.IsA.html)
//! marker trait. The [`Cast`](object/trait.Cast.html) trait enables upcasting
//! and downcasting.
//!
//! Interfaces and non-leaf classes also have corresponding traits (e.g.
//! `ObjectExt` and `gtk::WidgetExt`), which are blanketly implemented for all
//! their subtypes.
//!
//! # Under the hood
//!
//! GLib-based libraries largely operate on pointers to various boxed or
//! reference counted structures so the bindings have to implement corresponding
//! smart pointers (wrappers), which encapsulate resource management and safety
//! checks. Such wrappers are defined via the
//! [`glib_wrapper!`](macro.glib_wrapper!.html) macro, which uses abstractions
//! defined in the [`wrapper`](wrapper/index.html), [`boxed`](boxed/index.html),
//! [`shared`](shared/index.html) and [`object`](object/index.html) modules.
//!
//! The [`translate`](translate/index.html) module defines and partly implements
//! conversions between high level Rust types (including the aforementioned
//! wrappers) and their FFI counterparts.

extern crate libc;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate gio_sys as gio_ffi;

pub use bytes::Bytes;
pub use error::Error;
pub use file_error::FileError;
pub use object::{
    Cast,
    IsA,
    Object,
    ObjectExt,
};
pub use source::{
    CallbackGuard,
    Continue,
    idle_add,
    timeout_add,
    timeout_add_seconds,
};
pub use types::{
    StaticType,
    Type,
};
pub use value::{
    ToValue,
    TypedValue,
    Value,
};
pub use variant::{
    StaticVariantType,
    ToVariant,
    Variant,
};
pub use variant_type::{
    VariantTy,
    VariantType,
};
pub use time_val::{
    TimeVal,
    get_current_time,
};

#[macro_use]
pub mod wrapper;
#[macro_use]
pub mod boxed;
#[macro_use]
pub mod shared;
#[macro_use]
pub mod object;

mod bytes;
pub mod error;
mod file_error;
pub mod prelude;
pub mod signal;
mod source;
mod time_val;
pub mod translate;
pub mod types;
pub mod value;
pub mod variant;
mod variant_type;
<commit_msg>Expose *_stop_emission_* functions.<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! # **glib**, **gobject** and **gio** bindings for Rust
//!
//! This library contains
//!
//! - bindings to some essential GLib, GObject, GIO types and APIs,
//!
//! - common building blocks used in both handmade and machine generated
//! bindings to GTK+ and other GLib-based libraries.
//!
//! It is the foundation for higher level libraries with uniform Rusty (safe and
//! strongly typed) APIs. It avoids exposing GLib-specific data types where
//! possible and is not meant to provide comprehensive GLib bindings, which
//! would often amount to duplicating the Rust Standard Library or other utility
//! crates.
//!
//! The library is a work in progress: expect missing functionality and breaking
//! changes.
//!
//! # Dynamic typing
//!
//! Most types in the GLib family have type identifiers
//! ([`Type`](types/enum.Type.html)). Their corresponding Rust types implement
//! the [`StaticType`](types/trait.StaticType.html) trait.
//!
//! Dynamically typed [`Value`](value/index.html) can carry values of any `T:
//! StaticType`.
//!
//! [`Variant`](variant/index.html) can carry values of `T: StaticVariantType`.
//!
//! # Errors
//!
//! Errors are represented by [`Error`](error/struct.Error.html), which can
//! carry values from various [error
//! domains](error/trait.ErrorDomain.html#implementors) (such as
//! [`FileError`](enum.FileError.html)).
//!
//! # Objects
//!
//! Each class and interface has a corresponding smart pointer struct
//! representing an instance of that type (e.g. `Object` for `GObject`,
//! `gtk::Widget` for `GtkWidget`). They are reference counted and feature
//! interior mutability similarly to Rust's `Rc<RefCell<T>>` idiom.
//! Consequently, cloning objects is cheap and their methods never require
//! mutable borrows. Two smart pointers are equal iff they point to the same
//! object.
//!
//! The root of the object hierarchy is [`Object`](object/struct.Object.html).
//! Inheritance and subtyping is denoted with the [`IsA`](object/trait.IsA.html)
//! marker trait. The [`Cast`](object/trait.Cast.html) trait enables upcasting
//! and downcasting.
//!
//! Interfaces and non-leaf classes also have corresponding traits (e.g.
//! `ObjectExt` and `gtk::WidgetExt`), which are blanketly implemented for all
//! their subtypes.
//!
//! # Under the hood
//!
//! GLib-based libraries largely operate on pointers to various boxed or
//! reference counted structures so the bindings have to implement corresponding
//! smart pointers (wrappers), which encapsulate resource management and safety
//! checks. Such wrappers are defined via the
//! [`glib_wrapper!`](macro.glib_wrapper!.html) macro, which uses abstractions
//! defined in the [`wrapper`](wrapper/index.html), [`boxed`](boxed/index.html),
//! [`shared`](shared/index.html) and [`object`](object/index.html) modules.
//!
//! The [`translate`](translate/index.html) module defines and partly implements
//! conversions between high level Rust types (including the aforementioned
//! wrappers) and their FFI counterparts.

extern crate libc;
extern crate glib_sys as glib_ffi;
extern crate gobject_sys as gobject_ffi;
extern crate gio_sys as gio_ffi;

pub use bytes::Bytes;
pub use error::Error;
pub use file_error::FileError;
pub use object::{
    Cast,
    IsA,
    Object,
    ObjectExt,
};
pub use signal::{
    signal_stop_emission,
    signal_stop_emission_by_name
};
pub use source::{
    CallbackGuard,
    Continue,
    idle_add,
    timeout_add,
    timeout_add_seconds,
};
pub use types::{
    StaticType,
    Type,
};
pub use value::{
    ToValue,
    TypedValue,
    Value,
};
pub use variant::{
    StaticVariantType,
    ToVariant,
    Variant,
};
pub use variant_type::{
    VariantTy,
    VariantType,
};
pub use time_val::{
    TimeVal,
    get_current_time,
};

#[macro_use]
pub mod wrapper;
#[macro_use]
pub mod boxed;
#[macro_use]
pub mod shared;
#[macro_use]
pub mod object;

mod bytes;
pub mod error;
mod file_error;
pub mod prelude;
pub mod signal;
mod source;
mod time_val;
pub mod translate;
pub mod types;
pub mod value;
pub mod variant;
mod variant_type;
<|endoftext|>


<commit_before>//! # Handlebars
//! Handlebars is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for server-side page generation. It's a general-purpose library so you use it for any kind of text generation.
//!
//! ## Handlebars spec
//!
//! ### Base
//!
//! You can go to [Handlebars.js](http://handlebarsjs.com/) website for its syntax. This implementation should be compatible with most parts of the spec, except:
//!
//! * raw helper syntax `{{{raw-helper}}}...{{{/raw-helper}}}` is implemented as block helper raw.
//! * configurable logging (hard-coded to rust native logging, with fixed level `INFO`)
//!
//! ### Extensions
//!
//! We have template reuse facilities supported via built-in helpers `>`, `partial` and `block`.
//!
//! There are two ways to reuse a template:
//!
//! * include (using `>`)
//! * inheritance (using `>` together with `block` and `partial`)
//!
//! Consult [Handlebar.java document about template inheritance](http://jknack.github.io/handlebars.java/reuse.html).
//!
//! ## Usage
//!
//! ### Template Creation and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().unwrap();
//! }
//! ```
//!
//! ### Rendering Something
//!
//! I should say that rendering is a little tricky. Since handlebars is originally a JavaScript templating framework. It supports dynamic features like duck-typing, truthy/falsey values. But for a static language like Rust, this is a little difficult. As a solution, I'm using the `serialize::json::Json` internally for data rendering, which seems good by far.
//!
//! That means, if you want to render something, you have to ensure that it implements the `serialize::json::ToJson` trait. Luckily, most built-in types already have trait. However, if you want to render your custom struct, you need to implement this trait manually, or use [tojson_macros](https://github.com/sunng87/tojson_macros) to generate default `ToJson` implementation.
//!
//! You can use default `render` function to render a template into `String`. From 0.9, there's `renderw` to render text into anything of `std::io::Write`.
//!
//! ```ignore
//! extern crate rustc_serialize;
//! extern crate handlebars;
//!
//! use rustc_serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! impl ToJson for Person {
//!   fn to_json(&self) -> Json {
//!     let mut m: BTreeMap<String, Json> = BTreeMap::new();
//!     m.insert("name".to_string(), self.name.to_json());
//!     m.insert("age".to_string(), self.age.to_json());
//!     m.to_json()
//!   }
//! }
//!
//! fn main() {
//!   let source = "Hello, {{name}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_template_string("hello", source.to_string())
//!           .ok().unwrap();
//!
//!   let data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   let result = handlebars.render("hello", &data);
//! }
//! ```
//!
//! #### Escaping
//!
//! As per the handlebars spec, output using `{{expression}}` is escaped by default (to be precise, the characters `&"<>` are replaced by their respective html / xml entities). However, since the use cases of a rust template engine are probably a bit more diverse than those of a JavaScript one, this implementation allows the user to supply a custom escape function to be used instead. For more information see the `EscapeFn` type and `Handlebars::register_escape_fn()` method.
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use std::io::Write;
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context, JsonRender};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Clone, Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     try!(rc.writer.write("Ny helper dumps: ".as_bytes()));
//!     try!(rc.writer.write(value.render().into_bytes().as_ref()));
//!     Ok(())
//!   }
//! }
//!
//! // implement via bare function
//! fn another_simple_helper (c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     try!(rc.writer.write("My second helper dumps: ".as_bytes()));
//!     try!(rc.writer.write(value.render().into_bytes().as_ref()));
//!     Ok(())
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", Box::new(SimpleHelper));
//!   handlebars.register_helper("another-simple-helper", Box::new(another_simple_helper));
//!   // via closure
//!   handlebars.register_helper("closure-helper",
//!       Box::new(|c: &Context, h: &Helper, r: &Handlebars, rc: &mut RenderContext| -> Result<(), RenderError>{
//!         try!(rc.writer.write("...".as_bytes()));
//!         Ok(())
//!       }));
//!
//!   //...
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of String as params in helper, like `{{#somehelper param1 param2 param3}}`.
//! * `hash()` is a map of String key and Json value, defined in helper as `{{@somehelper a=1 b="2" c=true}}`.
//! * `template()` gives you the nested template of block helper.
//! * `inverse()` gives you the inversed template of it, inversed template is the template behind `{{else}}`.
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{#partial ...}} ... {{/partial}}` template reuse, used to replace block with same name
//! * `{{#block ...}} ... {{/block}}` template reuse, used to be replaced by partial with same name, with default content if partial not found.
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!

#[macro_use] extern crate log;
#[macro_use] extern crate quick_error;
#[macro_use] extern crate lazy_static;
#[cfg(test)] #[macro_use] extern crate maplit;

#[cfg(not(feature = "serde_type"))]
extern crate rustc_serialize as serialize;
extern crate regex;
extern crate num;
extern crate itertools;

#[cfg(feature = "serde_type")]
extern crate serde;
#[cfg(feature = "serde_type")]
extern crate serde_json;

pub use self::template::{Template};
pub use self::error::{TemplateError, TemplateFileError};
pub use self::registry::{EscapeFn, Registry as Handlebars};
pub use self::render::{Renderable, RenderError, RenderContext, Helper};
pub use self::helpers::{HelperDef};
pub use self::context::{Context, JsonRender, JsonTruthy};

mod template;
mod error;
mod registry;
mod render;
mod helpers;
mod context;
mod support;
<commit_msg>(doc) update doc<commit_after>//! # Handlebars
//! Handlebars is a modern and extensible templating solution originally created in the JavaScript world. It's used by many popular frameworks like [Ember.js](http://emberjs.com) and Chaplin. It's also ported to some other platforms such as [Java](https://github.com/jknack/handlebars.java).
//!
//! And this is handlebars Rust implementation, designed for server-side page generation. It's a general-purpose library so you use it for any kind of text generation.
//!
//! ## Handlebars spec
//!
//! ### Base
//!
//! You can go to [Handlebars.js](http://handlebarsjs.com/) website for its syntax. This implementation should be compatible with most parts of the spec, except:
//!
//! * configurable logging (hard-coded to rust native logging, with fixed level `INFO`)
//! * mustache iterators, block is not work in this implementation
//!
//! ### Extensions
//!
//! We have template reuse facilities supported via built-in helpers `>`, `partial` and `block`.
//!
//! There are two ways to reuse a template:
//!
//! * include (using `>`)
//! * inheritance (using `>` together with `block` and `partial`)
//!
//! Consult [Handlebar.java document about template inheritance](http://jknack.github.io/handlebars.java/reuse.html).
//!
//! ## Usage
//!
//! ### Template Creation and Registration
//!
//! Templates are created from String and registered to `Handlebars` with a name.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use handlebars::Handlebars;
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   let source = "hello {{world}}";
//!
//!   //compile returns an Option, we use unwrap() to deref it directly here
//!   handlebars.register_template_string("helloworld", source.to_string())
//!           .ok().unwrap();
//! }
//! ```
//!
//! ### Rendering Something
//!
//! I should say that rendering is a little tricky. Since handlebars is originally a JavaScript templating framework. It supports dynamic features like duck-typing, truthy/falsey values. But for a static language like Rust, this is a little difficult. As a solution, I'm using the `serialize::json::Json` internally for data rendering, which seems good by far.
//!
//! That means, if you want to render something, you have to ensure that it implements the `serialize::json::ToJson` trait. Luckily, most built-in types already have trait. However, if you want to render your custom struct, you need to implement this trait manually, or use [tojson_macros](https://github.com/sunng87/tojson_macros) to generate default `ToJson` implementation.
//!
//! You can use default `render` function to render a template into `String`. From 0.9, there's `renderw` to render text into anything of `std::io::Write`.
//!
//! ```ignore
//! extern crate rustc_serialize;
//! extern crate handlebars;
//!
//! use rustc_serialize::json::{Json, ToJson};
//! use std::collections::BTreeMap;
//!
//! use handlebars::Handlebars;
//!
//! struct Person {
//!   name: String,
//!   age: i16,
//! }
//!
//! impl ToJson for Person {
//!   fn to_json(&self) -> Json {
//!     let mut m: BTreeMap<String, Json> = BTreeMap::new();
//!     m.insert("name".to_string(), self.name.to_json());
//!     m.insert("age".to_string(), self.age.to_json());
//!     m.to_json()
//!   }
//! }
//!
//! fn main() {
//!   let source = "Hello, {{name}}";
//!
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_template_string("hello", source.to_string())
//!           .ok().unwrap();
//!
//!   let data = Person {
//!       name: "Ning Sun".to_string(),
//!       age: 27
//!   };
//!   let result = handlebars.render("hello", &data);
//! }
//! ```
//!
//! #### Escaping
//!
//! As per the handlebars spec, output using `{{expression}}` is escaped by default (to be precise, the characters `&"<>` are replaced by their respective html / xml entities). However, since the use cases of a rust template engine are probably a bit more diverse than those of a JavaScript one, this implementation allows the user to supply a custom escape function to be used instead. For more information see the `EscapeFn` type and `Handlebars::register_escape_fn()` method.
//!
//! ### Custom Helper
//!
//! Handlebars is nothing without helpers. You can also create your own helpers with rust. Helpers in handlebars-rust are custom struct implements the `HelperDef` trait, concretely, the `call` function. For your convenience, most of stateless helpers can be implemented as bare functions.
//!
//! ```
//!
//! extern crate handlebars;
//!
//! use std::io::Write;
//! use handlebars::{Handlebars, HelperDef, RenderError, RenderContext, Helper, Context, JsonRender};
//!
//! // implement by a structure impls HelperDef
//! #[derive(Clone, Copy)]
//! struct SimpleHelper;
//!
//! impl HelperDef for SimpleHelper {
//!   fn call(&self, c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     try!(rc.writer.write("Ny helper dumps: ".as_bytes()));
//!     try!(rc.writer.write(value.render().into_bytes().as_ref()));
//!     Ok(())
//!   }
//! }
//!
//! // implement via bare function
//! fn another_simple_helper (c: &Context, h: &Helper, _: &Handlebars, rc: &mut RenderContext) -> Result<(), RenderError> {
//!     let param = h.params().get(0).unwrap();
//!
//!     // get value from context data
//!     // rc.get_path() is current json parent path, you should always use it like this
//!     // param is the key of value you want to display
//!     let value = c.navigate(rc.get_path(), param);
//!     try!(rc.writer.write("My second helper dumps: ".as_bytes()));
//!     try!(rc.writer.write(value.render().into_bytes().as_ref()));
//!     Ok(())
//! }
//!
//!
//! fn main() {
//!   let mut handlebars = Handlebars::new();
//!   handlebars.register_helper("simple-helper", Box::new(SimpleHelper));
//!   handlebars.register_helper("another-simple-helper", Box::new(another_simple_helper));
//!   // via closure
//!   handlebars.register_helper("closure-helper",
//!       Box::new(|c: &Context, h: &Helper, r: &Handlebars, rc: &mut RenderContext| -> Result<(), RenderError>{
//!         try!(rc.writer.write("...".as_bytes()));
//!         Ok(())
//!       }));
//!
//!   //...
//! }
//! ```
//!
//! #### Arguments of HelpDef
//!
//! You can get data from the `Helper` argument about the template information:
//!
//! * `name()` for the helper name. This is known to you for most situation but if you are defining `helperMissing` or `blockHelperMissing`, this is important.
//! * `params()` is a vector of String as params in helper, like `{{#somehelper param1 param2 param3}}`.
//! * `hash()` is a map of String key and Json value, defined in helper as `{{@somehelper a=1 b="2" c=true}}`.
//! * `template()` gives you the nested template of block helper.
//! * `inverse()` gives you the inversed template of it, inversed template is the template behind `{{else}}`.
//!
//! You can learn more about helpers by looking into source code of built-in helpers.
//!
//! #### Built-in Helpers
//!
//! * `{{#raw}} ... {{/raw}}` escape handlebars expression within the block
//! * `{{#if ...}} ... {{else}} ... {{/if}}` if-else block
//! * `{{#unless ...}} ... {{else}} .. {{/unless}}` if-not-else block
//! * `{{#each ...}} ... {{/each}}` iterates over an array or object. Handlebar-rust doesn't support mustach iteration syntax so use this instead.
//! * `{{#with ...}} ... {{/with}}` change current context. Similar to {{#each}}, used for replace corresponding mustach syntax.
//! * `{{lookup ... ...}}` get value from array by `@index` or `@key`
//! * `{{#partial ...}} ... {{/partial}}` template reuse, used to replace block with same name
//! * `{{#block ...}} ... {{/block}}` template reuse, used to be replaced by partial with same name, with default content if partial not found.
//! * `{{> ...}}` include template with name
//! * `{{log ...}}` log value with rust logger, default level: INFO. Currently you cannot change the level.
//!

#[macro_use] extern crate log;
#[macro_use] extern crate quick_error;
#[macro_use] extern crate lazy_static;
#[cfg(test)] #[macro_use] extern crate maplit;

#[cfg(not(feature = "serde_type"))]
extern crate rustc_serialize as serialize;
extern crate regex;
extern crate num;
extern crate itertools;

#[cfg(feature = "serde_type")]
extern crate serde;
#[cfg(feature = "serde_type")]
extern crate serde_json;

pub use self::template::{Template};
pub use self::error::{TemplateError, TemplateFileError};
pub use self::registry::{EscapeFn, Registry as Handlebars};
pub use self::render::{Renderable, RenderError, RenderContext, Helper};
pub use self::helpers::{HelperDef};
pub use self::context::{Context, JsonRender, JsonTruthy};

mod template;
mod error;
mod registry;
mod render;
mod helpers;
mod context;
mod support;
<|endoftext|>


<commit_before>// Copyright 2015 Keegan McAllister.
// Copyright 2016 Corey Farwell.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// See `LICENSE` in this repository.

use std::io::{self, Read};
use std::panic;

mod common;
#[doc(hidden)]
pub use common::*;

// those functions are provided by the afl-llvm-rt static library
extern "C" {
    fn __afl_persistent_loop(counter: usize) -> isize;
    fn __afl_manual_init();

    static __afl_fuzz_len: *const u32;
    static __afl_fuzz_ptr: *const u8;
}

#[doc(hidden)]
#[no_mangle]
pub static __afl_sharedmem_fuzzing: i32 = 1;

/// Fuzz a closure by passing it a `&[u8]`
///
/// This slice contains a "random" quantity of "random" data.
///
/// ```rust,no_run
/// # extern crate afl;
/// # use afl::fuzz;
/// # fn main() {
/// fuzz(true, |data|{
///     if data.len() != 6 {return}
///     if data[0] != b'q' {return}
///     if data[1] != b'w' {return}
///     if data[2] != b'e' {return}
///     if data[3] != b'r' {return}
///     if data[4] != b't' {return}
///     if data[5] != b'y' {return}
///     panic!("BOOM")
/// });
/// # }
/// ```
pub fn fuzz<F>(hook: bool, mut closure: F)
where
    F: FnMut(&[u8]) + std::panic::RefUnwindSafe,
{
    // this marker strings needs to be in the produced executable for
    // afl-fuzz to detect `persistent mode` and `defered mode`
    static PERSIST_MARKER: &'static str = "##SIG_AFL_PERSISTENT##\0";
    static DEFERED_MARKER: &'static str = "##SIG_AFL_DEFER_FORKSRV##\0";

    // we now need a fake instruction to prevent the compiler from optimizing out
    // those marker strings
    unsafe { std::ptr::read_volatile(&PERSIST_MARKER) }; // hack used in https://github.com/bluss/bencher for black_box()
    unsafe { std::ptr::read_volatile(&DEFERED_MARKER) };
    // unsafe { asm!("" : : "r"(&PERSIST_MARKER)) }; // hack used in nightly's back_box(), requires feature asm
    // unsafe { asm!("" : : "r"(&DEFERED_MARKER)) };

    if hook {
        // sets panic hook to abort
        std::panic::set_hook(Box::new(|_| {
            std::process::abort();
        }));
    }

    let mut input = vec![];

    // initialize forkserver there
    unsafe { __afl_manual_init() };

    while unsafe { __afl_persistent_loop(1000) } != 0 {
        // get the testcase from the fuzzer
        let input_ref = if unsafe { __afl_fuzz_ptr.is_null() } {
            // in-memory testcase delivery is not enabled
            // get buffer from AFL++ through stdin
            let result = io::stdin().read_to_end(&mut input);
            if result.is_err() {
                return;
            }
            &input
        } else {
            unsafe {
                // get the testcase from the shared memory
                let input_len = *__afl_fuzz_len as usize;
                std::slice::from_raw_parts(__afl_fuzz_ptr, input_len)
            }
        };

        // We still catch unwinding panics just in case the fuzzed code modifies
        // the panic hook.
        // If so, the fuzzer will be unable to tell different bugs appart and you will
        // only be able to find one bug at a time before fixing it to then find a new one.
        let did_panic = std::panic::catch_unwind(panic::AssertUnwindSafe(|| {
            closure(input_ref);
        }))
        .is_err();

        if did_panic {
            // hopefully the custom panic hook will be called before and abort the
            // process before the stack frames are unwinded.
            std::process::abort();
        }
        // The version of lazy_static.rs at https://github.com/rust-fuzz/resettable-lazy-static.rs
        // provides the `reset` function.
        #[cfg(feature = "reset_lazy_static")]
        unsafe {
            lazy_static::lazy::reset();
        }
        input.clear();
    }
}

/// Fuzz a closure-like block of code by passing it an object of arbitrary type.
///
/// You can choose the type of the argument using the syntax as in the example below.
/// Please check out the `arbitrary` crate to see which types are available.
///
/// For performance reasons, it is recommended that you use the native type `&[u8]` when possible.
///
/// ```rust,no_run
/// # #[macro_use] extern crate afl;
/// # fn main() {
/// fuzz!(|data: &[u8]| {
///     if data.len() != 6 {return}
///     if data[0] != b'q' {return}
///     if data[1] != b'w' {return}
///     if data[2] != b'e' {return}
///     if data[3] != b'r' {return}
///     if data[4] != b't' {return}
///     if data[5] != b'y' {return}
///     panic!("BOOM")
/// });
/// # }
/// ```
#[macro_export]
macro_rules! fuzz {
    ( $($x:tt)* ) => { $crate::__fuzz!(true, $($x)*) }
}

/// Like `fuzz!` above, but panics that are caught inside the fuzzed code are not turned into
/// crashes.
#[macro_export]
macro_rules! fuzz_nohook {
    ( $($x:tt)* ) => { $crate::__fuzz!(false, $($x)*) }
}

#[doc(hidden)]
#[macro_export]
macro_rules! __fuzz {
    ($hook:expr, |$buf:ident| $body:block) => {
        $crate::fuzz($hook, |$buf| $body);
    };
    ($hook:expr, |$buf:ident: &[u8]| $body:block) => {
        $crate::fuzz($hook, |$buf| $body);
    };
    ($hook:expr, |$buf:ident: $dty: ty| $body:block) => {
        $crate::fuzz($hook, |$buf| {
            let $buf: $dty = {
                let mut data = ::arbitrary::Unstructured::new($buf);
                if let Ok(d) = ::arbitrary::Arbitrary::arbitrary(&mut data).map_err(|_| "") {
                    d
                } else {
                    return;
                }
            };

            $body
        });
    };
}

#[cfg(test)]
mod test {
    use std::{path, process, thread, time};

    fn target_dir_path() -> &'static path::Path {
        if path::Path::new("../target/debug/cargo-afl").exists() {
            path::Path::new("../target/debug/")
        } else if path::Path::new("target/debug/cargo-afl").exists() {
            path::Path::new("target/debug/")
        } else {
            panic!("Could not find cargo-afl binary");
        }
    }

    fn cargo_afl_path() -> path::PathBuf {
        target_dir_path().join("cargo-afl")
    }

    fn examples_hello_path() -> path::PathBuf {
        target_dir_path().join("examples").join("hello")
    }

    #[test]
    fn integration() {
        let temp_dir = tempfile::TempDir::new().expect("Could not create temporary directory");
        let temp_dir_path = temp_dir.path();
        let mut child = process::Command::new(cargo_afl_path())
            .arg("afl")
            .arg("fuzz")
            .stdout(process::Stdio::inherit())
            .stderr(process::Stdio::inherit())
            .arg("-i")
            .arg(".")
            .arg("-o")
            .arg(temp_dir_path)
            .arg(examples_hello_path())
            .spawn()
            .expect("Could not run cargo afl fuzz");
        thread::sleep(time::Duration::from_secs(10));
        for _ in 0..5 {
            thread::sleep(time::Duration::from_secs(1));
            let _ = child.kill();
        }
        assert!(temp_dir_path.join("default").join("fuzzer_stats").is_file());
    }
}
<commit_msg>Fix typo in lib.rs<commit_after>// Copyright 2015 Keegan McAllister.
// Copyright 2016 Corey Farwell.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// See `LICENSE` in this repository.

use std::io::{self, Read};
use std::panic;

mod common;
#[doc(hidden)]
pub use common::*;

// those functions are provided by the afl-llvm-rt static library
extern "C" {
    fn __afl_persistent_loop(counter: usize) -> isize;
    fn __afl_manual_init();

    static __afl_fuzz_len: *const u32;
    static __afl_fuzz_ptr: *const u8;
}

#[doc(hidden)]
#[no_mangle]
pub static __afl_sharedmem_fuzzing: i32 = 1;

/// Fuzz a closure by passing it a `&[u8]`
///
/// This slice contains a "random" quantity of "random" data.
///
/// ```rust,no_run
/// # extern crate afl;
/// # use afl::fuzz;
/// # fn main() {
/// fuzz(true, |data|{
///     if data.len() != 6 {return}
///     if data[0] != b'q' {return}
///     if data[1] != b'w' {return}
///     if data[2] != b'e' {return}
///     if data[3] != b'r' {return}
///     if data[4] != b't' {return}
///     if data[5] != b'y' {return}
///     panic!("BOOM")
/// });
/// # }
/// ```
pub fn fuzz<F>(hook: bool, mut closure: F)
where
    F: FnMut(&[u8]) + std::panic::RefUnwindSafe,
{
    // this marker strings needs to be in the produced executable for
    // afl-fuzz to detect `persistent mode` and `defered mode`
    static PERSIST_MARKER: &'static str = "##SIG_AFL_PERSISTENT##\0";
    static DEFERED_MARKER: &'static str = "##SIG_AFL_DEFER_FORKSRV##\0";

    // we now need a fake instruction to prevent the compiler from optimizing out
    // those marker strings
    unsafe { std::ptr::read_volatile(&PERSIST_MARKER) }; // hack used in https://github.com/bluss/bencher for black_box()
    unsafe { std::ptr::read_volatile(&DEFERED_MARKER) };
    // unsafe { asm!("" : : "r"(&PERSIST_MARKER)) }; // hack used in nightly's back_box(), requires feature asm
    // unsafe { asm!("" : : "r"(&DEFERED_MARKER)) };

    if hook {
        // sets panic hook to abort
        std::panic::set_hook(Box::new(|_| {
            std::process::abort();
        }));
    }

    let mut input = vec![];

    // initialize forkserver there
    unsafe { __afl_manual_init() };

    while unsafe { __afl_persistent_loop(1000) } != 0 {
        // get the testcase from the fuzzer
        let input_ref = if unsafe { __afl_fuzz_ptr.is_null() } {
            // in-memory testcase delivery is not enabled
            // get buffer from AFL++ through stdin
            let result = io::stdin().read_to_end(&mut input);
            if result.is_err() {
                return;
            }
            &input
        } else {
            unsafe {
                // get the testcase from the shared memory
                let input_len = *__afl_fuzz_len as usize;
                std::slice::from_raw_parts(__afl_fuzz_ptr, input_len)
            }
        };

        // We still catch unwinding panics just in case the fuzzed code modifies
        // the panic hook.
        // If so, the fuzzer will be unable to tell different bugs apart and you will
        // only be able to find one bug at a time before fixing it to then find a new one.
        let did_panic = std::panic::catch_unwind(panic::AssertUnwindSafe(|| {
            closure(input_ref);
        }))
        .is_err();

        if did_panic {
            // hopefully the custom panic hook will be called before and abort the
            // process before the stack frames are unwinded.
            std::process::abort();
        }
        // The version of lazy_static.rs at https://github.com/rust-fuzz/resettable-lazy-static.rs
        // provides the `reset` function.
        #[cfg(feature = "reset_lazy_static")]
        unsafe {
            lazy_static::lazy::reset();
        }
        input.clear();
    }
}

/// Fuzz a closure-like block of code by passing it an object of arbitrary type.
///
/// You can choose the type of the argument using the syntax as in the example below.
/// Please check out the `arbitrary` crate to see which types are available.
///
/// For performance reasons, it is recommended that you use the native type `&[u8]` when possible.
///
/// ```rust,no_run
/// # #[macro_use] extern crate afl;
/// # fn main() {
/// fuzz!(|data: &[u8]| {
///     if data.len() != 6 {return}
///     if data[0] != b'q' {return}
///     if data[1] != b'w' {return}
///     if data[2] != b'e' {return}
///     if data[3] != b'r' {return}
///     if data[4] != b't' {return}
///     if data[5] != b'y' {return}
///     panic!("BOOM")
/// });
/// # }
/// ```
#[macro_export]
macro_rules! fuzz {
    ( $($x:tt)* ) => { $crate::__fuzz!(true, $($x)*) }
}

/// Like `fuzz!` above, but panics that are caught inside the fuzzed code are not turned into
/// crashes.
#[macro_export]
macro_rules! fuzz_nohook {
    ( $($x:tt)* ) => { $crate::__fuzz!(false, $($x)*) }
}

#[doc(hidden)]
#[macro_export]
macro_rules! __fuzz {
    ($hook:expr, |$buf:ident| $body:block) => {
        $crate::fuzz($hook, |$buf| $body);
    };
    ($hook:expr, |$buf:ident: &[u8]| $body:block) => {
        $crate::fuzz($hook, |$buf| $body);
    };
    ($hook:expr, |$buf:ident: $dty: ty| $body:block) => {
        $crate::fuzz($hook, |$buf| {
            let $buf: $dty = {
                let mut data = ::arbitrary::Unstructured::new($buf);
                if let Ok(d) = ::arbitrary::Arbitrary::arbitrary(&mut data).map_err(|_| "") {
                    d
                } else {
                    return;
                }
            };

            $body
        });
    };
}

#[cfg(test)]
mod test {
    use std::{path, process, thread, time};

    fn target_dir_path() -> &'static path::Path {
        if path::Path::new("../target/debug/cargo-afl").exists() {
            path::Path::new("../target/debug/")
        } else if path::Path::new("target/debug/cargo-afl").exists() {
            path::Path::new("target/debug/")
        } else {
            panic!("Could not find cargo-afl binary");
        }
    }

    fn cargo_afl_path() -> path::PathBuf {
        target_dir_path().join("cargo-afl")
    }

    fn examples_hello_path() -> path::PathBuf {
        target_dir_path().join("examples").join("hello")
    }

    #[test]
    fn integration() {
        let temp_dir = tempfile::TempDir::new().expect("Could not create temporary directory");
        let temp_dir_path = temp_dir.path();
        let mut child = process::Command::new(cargo_afl_path())
            .arg("afl")
            .arg("fuzz")
            .stdout(process::Stdio::inherit())
            .stderr(process::Stdio::inherit())
            .arg("-i")
            .arg(".")
            .arg("-o")
            .arg(temp_dir_path)
            .arg(examples_hello_path())
            .spawn()
            .expect("Could not run cargo afl fuzz");
        thread::sleep(time::Duration::from_secs(10));
        for _ in 0..5 {
            thread::sleep(time::Duration::from_secs(1));
            let _ = child.kill();
        }
        assert!(temp_dir_path.join("default").join("fuzzer_stats").is_file());
    }
}
<|endoftext|>


<commit_before>pub fn read_file_data(path: &PathBuf) -> Vec<u8> {
    let mut data = Vec::new();
    let mut f = File::open(path).ok().unwrap();
    f.read_to_end(&mut data).unwrap();
    data
}

const VALIDATOR_CONFIG: Option<ValidatingParserConfig> = Some(ValidatingParserConfig {
    operator_config: OperatorValidatorConfig {
        enable_threads: true,
        enable_reference_types: true,
        enable_simd: true,
        enable_bulk_memory: true,
    },
    mutable_global_imports: true,
});

#[macro_use]
extern crate criterion;
extern crate wasmparser;

use criterion::Criterion;
use wasmparser::{
    validate, OperatorValidatorConfig, Parser, ParserState, ValidatingParser,
    ValidatingParserConfig, WasmDecoder,
};

use std::fs::{read_dir, File};
use std::io::Read;
use std::path::PathBuf;

fn read_all_wasm<'a, T>(mut d: T)
where
    T: WasmDecoder<'a>,
{
    loop {
        match *d.read() {
            ParserState::Error(e) => panic!("unexpected error {:?}", e),
            ParserState::EndWasm => return,
            _ => (),
        }
    }
}

fn it_works_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("it works benchmark", move |b| {
        for d in &mut data {
            b.iter(|| read_all_wasm(Parser::new(d.as_slice())));
        }
    });
}

fn validator_not_fails_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("validator no fails benchmark", move |b| {
        for d in &mut data {
            b.iter(|| read_all_wasm(ValidatingParser::new(d.as_slice(), VALIDATOR_CONFIG)));
        }
    });
}

fn validate_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![vec![]];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("validate benchmark", move |b| {
        for d in &mut data {
            b.iter(|| validate(&d, VALIDATOR_CONFIG));
        }
    });
}

criterion_group!(
    benchmark,
    it_works_benchmark,
    validator_not_fails_benchmark,
    validate_benchmark
);
criterion_main!(benchmark);
<commit_msg>Fix benches/benchmark.rs for multi-value.<commit_after>pub fn read_file_data(path: &PathBuf) -> Vec<u8> {
    let mut data = Vec::new();
    let mut f = File::open(path).ok().unwrap();
    f.read_to_end(&mut data).unwrap();
    data
}

const VALIDATOR_CONFIG: Option<ValidatingParserConfig> = Some(ValidatingParserConfig {
    operator_config: OperatorValidatorConfig {
        enable_threads: true,
        enable_reference_types: true,
        enable_simd: true,
        enable_bulk_memory: true,
        enable_multi_value: true,
    },
    mutable_global_imports: true,
});

#[macro_use]
extern crate criterion;
extern crate wasmparser;

use criterion::Criterion;
use wasmparser::{
    validate, OperatorValidatorConfig, Parser, ParserState, ValidatingParser,
    ValidatingParserConfig, WasmDecoder,
};

use std::fs::{read_dir, File};
use std::io::Read;
use std::path::PathBuf;

fn read_all_wasm<'a, T>(mut d: T)
where
    T: WasmDecoder<'a>,
{
    loop {
        match *d.read() {
            ParserState::Error(e) => panic!("unexpected error {:?}", e),
            ParserState::EndWasm => return,
            _ => (),
        }
    }
}

fn it_works_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("it works benchmark", move |b| {
        for d in &mut data {
            b.iter(|| read_all_wasm(Parser::new(d.as_slice())));
        }
    });
}

fn validator_not_fails_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("validator no fails benchmark", move |b| {
        for d in &mut data {
            b.iter(|| read_all_wasm(ValidatingParser::new(d.as_slice(), VALIDATOR_CONFIG)));
        }
    });
}

fn validate_benchmark(c: &mut Criterion) {
    let mut data: Vec<Vec<u8>> = vec![vec![]];
    for entry in read_dir("tests").unwrap() {
        let dir = entry.unwrap();
        if !dir.file_type().unwrap().is_file() {
            continue;
        }
        data.push(read_file_data(&dir.path()));
    }
    c.bench_function("validate benchmark", move |b| {
        for d in &mut data {
            b.iter(|| validate(&d, VALIDATOR_CONFIG));
        }
    });
}

criterion_group!(
    benchmark,
    it_works_benchmark,
    validator_not_fails_benchmark,
    validate_benchmark
);
criterion_main!(benchmark);
<|endoftext|>