<commit_before>
struct Node {
    keys: Vec<i32>,
    vals: Option<Vec<i32>>,
    children: Option<Vec<Box<Node>>>
}

struct KeyNodePair(i32, Box<Node>);

pub struct BTree {
    root: Option<Box<Node>>,
    max: usize
}

impl BTree {
    /// Makes a new empty BTree.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut map = BTree::new(16);
    ///
    /// // entries can now be inserted into the empty map
    /// map.insert(1, 1);
    /// ```
    pub fn new(max: usize) -> BTree {
        BTree{ root: None, max: max }
    }

    /// Returns the value corresponding to the key.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut map = BTree::new(16);
    /// map.insert(1, 1);
    /// assert_eq!(map.get(1), Some(1));
    /// assert_eq!(map.get(2), None);
    /// ```
    pub fn get(&self, key: i32) -> Option<i32> {
        match self.root {
            None => None,
            Some(ref node) => node.get(key)
        }
    }

    /// Returns true if the map contains no elements.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut a = BTree::new(16);
    /// assert!(a.is_empty());
    /// a.insert(1, 1);
    /// assert!(!a.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.root.is_none()
    }

    /// Inserts a key-value pair into the map.
    ///
    /// If the map did not have this key present, `None` is returned.
    ///
    /// If the map did have this key present, the value is updated, and the old
    /// value is returned.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut map = BTree::new(16);
    /// assert_eq!(map.insert(37, 1), None);
    /// assert_eq!(map.is_empty(), false);
    ///
    /// map.insert(37, 2);
    /// assert_eq!(map.insert(37, 3), Some(2));
    /// ```
    pub fn insert(&mut self, key: i32, value: i32) -> Option<i32> {
        match self.root {
            None => {
                self.root = Node::new_leaf(key, value);
                None
            },
            Some(_) => {
                let (prev, split) = self.root.as_mut().unwrap().insert(key, value, self.max);
                if split.is_some() {
                    let KeyNodePair(key, child) = split.unwrap();
                    let children = vec![self.root.take().unwrap(), child];
                    self.root = Node::new_root(key, children);
                }
                prev
            }
        }
    }
}

impl KeyNodePair {
    fn new(
        key: i32,
        keys: Vec<i32>,
        vals: Option<Vec<i32>>,
        children: Option<Vec<Box<Node>>>) -> KeyNodePair {
            KeyNodePair(key, Box::new(Node{keys:keys, vals:vals, children: children}))
    }
}

impl Node {

    fn new_leaf(key: i32, value: i32) -> Option<Box<Node>> {
        Some(Box::new(Node { keys: vec![key], vals: Some(vec![value]), children: None }))
    }

    fn new_root(key: i32, children: Vec<Box<Node>>) -> Option<Box<Node>> {
        Some(Box::new(Node { keys: vec![key], vals: None, children: Some(children) }))
    }

    fn get(&self, key: i32) -> Option<i32> {
        let position = self.keys.binary_search(&key);
        if self.vals.is_none() {
            let index = Node::index(position);
            self.child(index).get(key)
        } else {
            match position {
                Ok(index) => Some(self.value(index)),
                Err(_) => None
            }
        }
    }

    fn split(&mut self, max: usize) -> Option<KeyNodePair> {
        if self.keys.len() > max {
            let partition = self.keys.len() / 2;
            match self.children {
                Some(ref mut children) => {
                    let mut newkeys = self.keys.split_off(partition);
                    let newchildren = children.split_off(partition + 1);
                    let newkey = newkeys.remove(0);
                    Some(KeyNodePair::new(newkey, newkeys, None, Some(newchildren)))
                },
                None => {
                    let newkeys = self.keys.split_off(partition);
                    let newvals = Some(self.mut_values().split_off(partition));
                    Some(KeyNodePair::new(newkeys[0], newkeys, newvals, None))
                }
            }
        } else {
            None
        }
    }

    fn insert(&mut self, key: i32, value: i32, max: usize) -> (Option<i32>, Option<KeyNodePair>) {
        let position = self.keys.binary_search(&key);
        let prev = match self.children {
            Some(ref mut children) => {
                let index = Node::index(position);
                let (prev, newchild) = children[index].insert(key, value, max);
                if newchild.is_some() {
                    let KeyNodePair(key, newchild) = newchild.unwrap();
                    let index = Node::index(self.keys.binary_search(&key));
                    self.keys.insert(index, key);
                    children.insert(index + 1, newchild);
                }
                prev
            },
            None => {
                let prev = match position {
                    Ok(index) => Some(self.value(index)),
                    Err(_) => None
                };
                match position {
                    Ok(index) => {
                        self.mut_values()[index] = value;
                    },
                    Err(index) => {
                        self.keys.insert(index, value);
                        self.mut_values().insert(index, value);
                    }
                };
                prev
            }
        };
        (prev, self.split(max))
    }

    fn index(position: Result<usize,usize>) -> usize {
        match position {
            Ok(index) => index + 1,
            Err(index) => index,
        }
    }

    fn ref_values(&self) -> &Vec<i32> {
        self.vals.as_ref().unwrap()
    }

    fn mut_values(&mut self) -> &mut Vec<i32> {
        self.vals.as_mut().unwrap()
    }

    fn ref_children(&self) -> &Vec<Box<Node>> {
        self.children.as_ref().unwrap()
    }

    fn value(&self, index: usize) -> i32 {
        *self.ref_values().get(index).unwrap()
    }

    fn child(&self, index: usize) -> &Box<Node> {
        self.ref_children().get(index).unwrap()
    }
}

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

    #[test]
    fn basic_construction() {
        let mut tree = BTree::new(2);
        assert_eq!(tree.get(0), None);
        assert_eq!(tree.insert(0, 1), None);
        assert_eq!(tree.insert(0, 2), Some(1));
        assert_eq!(tree.get(0), Some(2));
    }

    #[test]
    fn insert_sequence() {
        let mut tree = BTree::new(2);
        for i in 0..256 {
            assert_eq!(tree.insert(i, i), None);
            assert_eq!(tree.get(i), Some(i));
        }
    }
}
<commit_msg>Partial B-tree delete implementation.<commit_after>
use std::cmp;
use std::cmp::Ordering;
use std::mem;

#[derive(PartialEq, Eq, Copy, Clone)]
enum Neighbor {
    Less,
    Greater
}

struct Node {
    keys: Vec<i32>,
    vals: Option<Vec<i32>>,
    children: Option<Vec<Box<Node>>>
}

struct KeyNodePair(i32, Box<Node>);

pub struct BTree {
    root: Option<Box<Node>>,
    max: usize
}

impl BTree {
    /// Makes a new empty BTree.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut map = BTree::new(16);
    ///
    /// // entries can now be inserted into the empty map
    /// map.insert(1, 1);
    /// ```
    pub fn new(max: usize) -> BTree {
        BTree{ root: None, max: max }
    }

    /// Returns the value corresponding to the key.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut map = BTree::new(16);
    /// map.insert(1, 1);
    /// assert_eq!(map.get(1), Some(1));
    /// assert_eq!(map.get(2), None);
    /// ```
    pub fn get(&self, key: i32) -> Option<i32> {
        match self.root {
            None => None,
            Some(ref node) => node.get(key)
        }
    }

    /// Returns true if the map contains no elements.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut a = BTree::new(16);
    /// assert!(a.is_empty());
    /// a.insert(1, 1);
    /// assert!(!a.is_empty());
    /// ```
    pub fn is_empty(&self) -> bool {
        self.root.is_none()
    }

    /// Inserts a key-value pair into the map.
    ///
    /// If the map did not have this key present, `None` is returned.
    ///
    /// If the map did have this key present, the value is updated, and the old
    /// value is returned.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```
    /// use yaar::btree::BTree;
    ///
    /// let mut map = BTree::new(16);
    /// assert_eq!(map.insert(37, 1), None);
    /// assert_eq!(map.is_empty(), false);
    ///
    /// map.insert(37, 2);
    /// assert_eq!(map.insert(37, 3), Some(2));
    /// ```
    pub fn insert(&mut self, key: i32, value: i32) -> Option<i32> {
        match self.root {
            None => {
                self.root = Node::new_leaf(key, value);
                None
            },
            Some(_) => {
                let (prev, split) = self.root.as_mut().unwrap().insert(key, value, self.max);
                if split.is_some() {
                    let KeyNodePair(key, child) = split.unwrap();
                    let children = vec![self.root.take().unwrap(), child];
                    self.root = Node::new_root(key, children);
                }
                prev
            }
        }
    }

    pub fn remove(&mut self, key: i32) -> Option<i32> {
        let min = self.max / 2;
        if self.root.is_some() {
            let (prev, empty) = {
                let node = self.root.as_mut().unwrap();
                let (prev, _) = node.remove(key, min);
                match node.children {
                    None => (prev, node.keys.len() == 0),
                    Some(ref children) => (prev, children.len() == 1)
                }
            };
            if empty {
                let node = self.root.take().unwrap();
                if node.children.is_some() {
                    self.root = Some(node.children.unwrap().remove(0));
                }
            }
            prev
        } else {
            None
        }
    }
}

impl KeyNodePair {
    fn new(
        key: i32,
        keys: Vec<i32>,
        vals: Option<Vec<i32>>,
        children: Option<Vec<Box<Node>>>) -> KeyNodePair {
            KeyNodePair(key, Box::new(Node{keys:keys, vals:vals, children: children}))
    }
}

impl Node {

    fn new_leaf(key: i32, value: i32) -> Option<Box<Node>> {
        Some(Box::new(Node { keys: vec![key], vals: Some(vec![value]), children: None }))
    }

    fn new_root(key: i32, children: Vec<Box<Node>>) -> Option<Box<Node>> {
        Some(Box::new(Node { keys: vec![key], vals: None, children: Some(children) }))
    }

    fn get(&self, key: i32) -> Option<i32> {
        let position = self.keys.binary_search(&key);
        if self.vals.is_none() {
            let index = Node::index(position);
            self.child(index).get(key)
        } else {
            match position {
                Ok(index) => Some(self.value(index)),
                Err(_) => None
            }
        }
    }

    fn split(&mut self, max: usize) -> Option<KeyNodePair> {
        if self.keys.len() > max {
            let partition = self.keys.len() / 2;
            match self.children {
                Some(ref mut children) => {
                    let mut newkeys = self.keys.split_off(partition);
                    let newchildren = children.split_off(partition + 1);
                    let newkey = newkeys.remove(0);
                    Some(KeyNodePair::new(newkey, newkeys, None, Some(newchildren)))
                },
                None => {
                    let newkeys = self.keys.split_off(partition);
                    let newvals = Some(self.mut_values().split_off(partition));
                    Some(KeyNodePair::new(newkeys[0], newkeys, newvals, None))
                }
            }
        } else {
            None
        }
    }

    fn insert(&mut self, key: i32, value: i32, max: usize) -> (Option<i32>, Option<KeyNodePair>) {
        let position = self.keys.binary_search(&key);
        let prev = match self.children {
            Some(ref mut children) => {
                let index = Node::index(position);
                let (prev, newchild) = children[index].insert(key, value, max);
                if newchild.is_some() {
                    let KeyNodePair(key, newchild) = newchild.unwrap();
                    let index = Node::index(self.keys.binary_search(&key));
                    self.keys.insert(index, key);
                    children.insert(index + 1, newchild);
                }
                prev
            },
            None => {
                let prev = match position {
                    Ok(index) => Some(self.value(index)),
                    Err(_) => None
                };
                match position {
                    Ok(index) => {
                        self.mut_values()[index] = value;
                    },
                    Err(index) => {
                        self.keys.insert(index, value);
                        self.mut_values().insert(index, value);
                    }
                };
                prev
            }
        };
        (prev, self.split(max))
    }

    fn needs_merge(&self, min: usize) -> bool {
        self.keys.len() < min
    }

    fn merge_select_sibling(&self, index: usize) -> Neighbor {
        let leftsize = if index > 0 {
            self.ref_children()[index - 1].keys.len()
        } else { 0 };
        let rightsize = if index < self.ref_children().len() - 1 {
            self.ref_children()[index + 1].keys.len()
        } else { 0 };
        if leftsize == 0 && rightsize == 0 {
            panic!("left and right children are empty");
        }
        match rightsize.cmp(&leftsize) {
            Ordering::Less | Ordering::Equal => Neighbor::Less,
            Ordering::Greater => Neighbor::Greater
        }
    }

    fn neighbor(index: usize, ord: Neighbor) -> usize {
        match ord {
            Neighbor::Less => {
                index - 1
            },
            Neighbor::Greater => {
                index + 1
            }
        }
    }

    fn partition(&mut self, index: usize, ord: Neighbor) -> (&mut Node, &mut Node) {
        match ord {
            Neighbor::Less => {
                let (left, right) = self.mut_children().split_at_mut(index);
                let index = left.len() - 1;
                (&mut right[0], &mut left[index])
            },
            Neighbor::Greater => {
                let (left, right) = self.mut_children().split_at_mut(index + 1);
                let index = left.len() - 1;
                (&mut left[index], &mut right[0])
            }
        }
    }

    fn get_parent_key(&self, index: usize, ord: Neighbor) -> i32 {
        match ord {
            Neighbor::Less => {
                self.keys[index - 1]
            },
            Neighbor::Greater => {
                self.keys[index]
            }
        }
    }

    fn set_parent_key(&mut self, key: Option<i32>, index: usize, ord: Neighbor) {
        match key {
            Some(value) => match ord {
                Neighbor::Less => {
                    self.keys[index - 1] = value;
                },
                Neighbor::Greater => {
                    self.keys[index] = value;
                }
            },
            None => {}
        }
    }

    fn pre_redistribute(sibling: &mut Vec<i32>, key: i32, ord: Neighbor) {
        match ord {
            Neighbor::Less => {
                sibling.push(key);
            },
            Neighbor::Greater => {
                sibling.insert(0, key);
            }
        }
    }

    fn redistribute<T>(src: &mut Vec<T>, dest: &mut Vec<T>, ord: Neighbor, count: usize) {
        match ord {
            Neighbor::Less => {
                let position = src.len() - count;
                let mut newdest = src.split_off(position);
                newdest.append(dest);
                *dest = newdest;
            },
            Neighbor::Greater => {
                let newsrc = src.split_off(count);
                dest.append(src);
                *src = newsrc;
            }
        }
    }

    fn post_redistribute(sibling: &mut Vec<i32>, ord: Neighbor) -> i32 {
        match ord {
            Neighbor::Less => {
                sibling.pop().unwrap()
            },
            Neighbor::Greater => {
                sibling.remove(0)
            }
        }
    }

    fn merge_redistribute(&mut self, index: usize, ord: Neighbor, min: usize) {
        let pkey = self.get_parent_key(index, ord);
        let ckey = {
            let (mut child, mut sibling) = self.partition(index, ord);
            let sibling_len = sibling.keys.len();
            let count = cmp::max(1, (sibling_len - min) / 2);
            if child.children.is_none() {
                Node::redistribute(&mut sibling.keys, &mut child.keys, ord, count);
                Node::redistribute(&mut sibling.mut_values(), &mut child.mut_values(), ord, count);
                None
            } else {
                Node::pre_redistribute(&mut sibling.keys, pkey, ord);
                Node::redistribute(&mut sibling.keys, &mut child.keys, ord, count);
                Node::redistribute(&mut sibling.mut_children(), &mut child.mut_children(), ord, count);
                Some(Node::post_redistribute(&mut sibling.keys, ord))
            }
        };
        self.set_parent_key(ckey, index, ord);
    }

    fn collapse<T>(sibling: &mut Vec<T>, child: &mut Vec<T>, ord: Neighbor) {
        match ord {
            Neighbor::Less => {
                sibling.append(child);
            },
            Neighbor::Greater => {
                child.append(sibling);
                mem::swap(child, sibling);
            }
        }
    }

    fn merge_collapse(&mut self, index: usize, ord: Neighbor) {
        {
            let (mut child, mut sibling) = self.partition(index, ord);
            if child.children.is_some() {
                debug_assert_eq!(child.keys.len() + 1, child.ref_children().len());
            } else {
                debug_assert_eq!(child.keys.len(), child.ref_values().len());
            }
            Node::collapse(&mut sibling.keys, &mut child.keys, ord);
            if child.children.is_some() {
                Node::collapse(&mut sibling.mut_children(), &mut child.mut_children(), ord);
            } else {
                Node::collapse(&mut sibling.mut_values(), &mut child.mut_values(), ord);
            }
        }
        self.mut_children().remove(index);
        match ord {
            Neighbor::Less => {
                self.keys.remove(index - 1);
            },
            Neighbor::Greater => {
                self.keys.remove(index);
            }
        }
    }

    fn merge_child(&mut self, index: usize, min: usize) {
        let ord = self.merge_select_sibling(index);
        let sib_index = Node::neighbor(index, ord);
        let sib_len = self.ref_children()[sib_index].keys.len();
        if sib_len > min {
            self.merge_redistribute(index, ord, min);
        } else {
            //self.merge_collapse(index, ord);
        }
    }

    fn remove(&mut self, key: i32, min: usize) -> (Option<i32>, bool) {
        let position = self.keys.binary_search(&key);
        let (prev, child_merge) = match self.children {
            Some(ref mut children) => {
                let index = Node::index(position);
                children[index].remove(key, min)
            },
            None => {
                match position {
                    Ok(index) => {
                        self.keys.remove(index);
                        (Some(self.mut_values().remove(index)), false)
                    }
                    Err(_) => (None, false)
                }
            }
        };
        if child_merge {
            self.merge_child(Node::index(position), min);
        }
        (prev, self.needs_merge(min))
    }

    fn index(position: Result<usize,usize>) -> usize {
        match position {
            Ok(index) => index + 1,
            Err(index) => index,
        }
    }

    fn ref_values(&self) -> &Vec<i32> {
        self.vals.as_ref().unwrap()
    }

    fn mut_values(&mut self) -> &mut Vec<i32> {
        self.vals.as_mut().unwrap()
    }

    fn ref_children(&self) -> &Vec<Box<Node>> {
        self.children.as_ref().unwrap()
    }

    fn mut_children(&mut self) -> &mut Vec<Box<Node>> {
        self.children.as_mut().unwrap()
    }

    fn value(&self, index: usize) -> i32 {
        *self.ref_values().get(index).unwrap()
    }

    fn child(&self, index: usize) -> &Box<Node> {
        self.ref_children().get(index).unwrap()
    }
}

#[test]
fn redistribute() {
    let mut vec1 = vec![1, 2, 3];
    let mut vec2 = vec![4, 5, 6];
    Node::redistribute(&mut vec1, &mut vec2, Neighbor::Less, 2);
    assert_eq!(vec1, vec![1]);
    assert_eq!(vec2, vec![2, 3, 4, 5, 6]);

    let mut vec3 = vec![1, 2, 3];
    let mut vec4 = vec![4, 5, 6];
    Node::redistribute(&mut vec4, &mut vec3, Neighbor::Greater, 2);
    assert_eq!(vec3, vec![1, 2, 3, 4, 5]);
    assert_eq!(vec4, vec![6]);
}

fn testnode() -> Box<Node> {
    Node::new_leaf(0,0).unwrap()
}

#[test]
fn redistribute_children_left() {
    let left = Box::new(Node{keys: vec![1, 2, 3, 4, 5, 6], vals: None,
        children: Some(vec![testnode(), testnode()])});
    let right = Box::new(Node{keys: vec![70], vals: None,
        children: Some(vec![testnode(), testnode(), testnode(),
        testnode(), testnode(), testnode(), testnode()])});
    let mut parent = Node{keys: vec![50], vals: None, children: Some(vec!(left, right))};
    parent.merge_redistribute(1, Neighbor::Less, 2);
    assert_eq!(parent.keys, vec![5]);
    assert_eq!(parent.ref_children()[0].keys, vec![1, 2, 3, 4]);
    assert_eq!(parent.ref_children()[1].keys, vec![6, 50, 70]);
}

#[test]
fn redistribute_children_right() {
    let left = Box::new(Node{keys: vec![15], vals: None,
        children: Some(vec![testnode(), testnode()])});
    let right = Box::new(Node{keys: vec![20, 30, 40, 50, 60, 70], vals: None,
        children: Some(vec![testnode(), testnode(), testnode(),
        testnode(), testnode(), testnode(), testnode()])});
    let mut parent = Node{keys: vec![18], vals: None, children: Some(vec!(left, right))};
    parent.merge_redistribute(0, Neighbor::Greater, 2);
    assert_eq!(parent.keys, vec![30]);
    assert_eq!(parent.ref_children()[0].keys, vec![15, 18, 20]);
    assert_eq!(parent.ref_children()[1].keys, vec![40, 50, 60, 70]);
}

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

    #[test]
    fn basic_construction() {
        let mut tree = BTree::new(4);
        assert_eq!(tree.get(0), None);
        assert_eq!(tree.insert(0, 1), None);
        assert_eq!(tree.insert(0, 2), Some(1));
        assert_eq!(tree.get(0), Some(2));
    }

    #[test]
    fn insert_sequence() {
        let mut tree = BTree::new(4);
        for i in 0..256 {
            assert_eq!(tree.insert(i, i), None);
            assert_eq!(tree.get(i), Some(i));
        }
    }

/*
    #[test]
    fn remove() {
        let mut tree = BTree::new(4);
        for i in 0..256 {
            assert_eq!(tree.insert(i, i), None);
        }
        for i in 0..256 {
            assert_eq!(tree.remove(i), Some(i));
            assert_eq!(tree.remove(i), None);
        }
    }
*/

}
<|endoftext|>


<commit_before>//! Callback methods for rustwlc
use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::*;
use rustwlc::input::{pointer, keyboard};

/// If the event is handled by way-cooler
const EVENT_HANDLED: bool = true;

/// If the event should be passed through to clients
const EVENT_PASS_THROUGH: bool = false;

// wlc callbacks

pub extern fn output_created(output: WlcOutput) -> bool {
    println!("output_created: {:?}: {}", output, output.get_name());
    return true;
}

pub extern fn output_destroyed(output: WlcOutput) {
    println!("output_destroyed");
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    println!("output_focus: {}", focused);
}

pub extern fn output_resolution(output: WlcOutput,
                            old_size_ptr: &Size, new_size_ptr: &Size) {
    println!("output_resolution: {:?} from  {:?} to {:?}",
             output, *old_size_ptr, *new_size_ptr);
}

pub extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

pub extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}

pub extern fn view_created(view: WlcView) -> bool {
    println!("view_created: {:?}: \"{}\"", view, view.get_title());
    let output = view.get_output();
    view.set_mask(output.get_mask());
    view.bring_to_front();
    view.focus();
    return true;
}

pub extern fn view_destroyed(view: WlcView) {
    println!("view_destroyed: {:?}", view);
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    println!("view_focus: {:?} {}", current, focused);
    current.set_state(VIEW_ACTIVATED, focused);
}

pub extern fn view_move_to_output(current: WlcView, o1: WlcOutput, o2: WlcOutput) {
    println!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
}

pub extern fn view_request_geometry(view: WlcView, geometry: &Geometry) {
    println!("view_request_geometry: {:?} wants {:?}", view, geometry);
    view.set_geometry(EDGE_NONE, geometry);
}

pub extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    view.set_state(state, handled);
}

pub extern fn view_request_move(view: WlcView, dest: &Point) {
    // Called by views when they have a dang resize mouse thing, we should only
    // let it happen in view floating mode
    //println!("view_request_move: to {}, start interactive mode.", *dest);
}

pub extern fn view_request_resize(view: WlcView,
                              edge: ResizeEdge, location: &Point) {
    println!("view_request_resize: edge {:?}, to {}, start interactive mode.",
             edge, location);
}

pub extern fn keyboard_key(view: WlcView, time: u32, mods_ptr: &KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    println!("keyboard_key: time {}, mods {:?}, key {:?}, state {:?}",
             time, &*mods_ptr, key, state);
    false
}

pub extern fn pointer_button(view: WlcView, button: u32,
                         mods_ptr: &KeyboardModifiers, key: u32,
                         state: ButtonState, point_ptr: &Point) -> bool {
    println!("pointer_button: pressed {} at {}", key, *point_ptr);
    if state == ButtonState::Pressed && !view.is_root() {
        view.focus();
    }
    false
}

pub extern fn pointer_scroll(view: WlcView, button: u32,
                         mods_ptr: &KeyboardModifiers, axis: ScrollAxis,
                         heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

pub extern fn pointer_motion(view: WlcView, time: u32, point: &Point) -> bool {
    pointer::set_position(point);
    false
}

pub extern fn touch(view: WlcView, time: u32, mods_ptr: &KeyboardModifiers,
               touch: TouchType, key: i32, point_ptr: &Point) -> bool {
    false
}

pub extern fn compositor_ready() {
    println!("Preparing compositor!");
}
<commit_msg>Add reference to keybindings in key callback<commit_after>//! Callback methods for rustwlc
use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::*;
use rustwlc::input::{pointer, keyboard};
use rustwlc::xkb::Keysym;

use super::keys;
use super::keys::{KeyEvent, KeyPress};

/// If the event is handled by way-cooler
const EVENT_HANDLED: bool = true;

/// If the event should be passed through to clients
const EVENT_PASS_THROUGH: bool = false;

// wlc callbacks

pub extern fn output_created(output: WlcOutput) -> bool {
    println!("output_created: {:?}: {}", output, output.get_name());
    return true;
}

pub extern fn output_destroyed(output: WlcOutput) {
    println!("output_destroyed");
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    println!("output_focus: {}", focused);
}

pub extern fn output_resolution(output: WlcOutput,
                            old_size_ptr: &Size, new_size_ptr: &Size) {
    println!("output_resolution: {:?} from  {:?} to {:?}",
             output, *old_size_ptr, *new_size_ptr);
}

pub extern fn output_render_pre(output: WlcOutput) {
    //println!("output_render_pre");
}

pub extern fn output_render_post(output: WlcOutput) {
    //println!("output_render_post");
}

pub extern fn view_created(view: WlcView) -> bool {
    println!("view_created: {:?}: \"{}\"", view, view.get_title());
    let output = view.get_output();
    view.set_mask(output.get_mask());
    view.bring_to_front();
    view.focus();
    return true;
}

pub extern fn view_destroyed(view: WlcView) {
    println!("view_destroyed: {:?}", view);
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    println!("view_focus: {:?} {}", current, focused);
    current.set_state(VIEW_ACTIVATED, focused);
}

pub extern fn view_move_to_output(current: WlcView, o1: WlcOutput, o2: WlcOutput) {
    println!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
}

pub extern fn view_request_geometry(view: WlcView, geometry: &Geometry) {
    println!("view_request_geometry: {:?} wants {:?}", view, geometry);
    view.set_geometry(EDGE_NONE, geometry);
}

pub extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    view.set_state(state, handled);
}

pub extern fn view_request_move(view: WlcView, dest: &Point) {
    // Called by views when they have a dang resize mouse thing, we should only
    // let it happen in view floating mode
    //println!("view_request_move: to {}, start interactive mode.", *dest);
}

pub extern fn view_request_resize(view: WlcView,
                              edge: ResizeEdge, location: &Point) {
    println!("view_request_resize: edge {:?}, to {}, start interactive mode.",
             edge, location);
}

pub extern fn keyboard_key(view: WlcView, time: u32, mods: &KeyboardModifiers,
                       key: u32, state: KeyState) -> bool {
    println!("keyboard_key: time {}, mods {:?}, key {:?}, state {:?}",
             time, &*mods, key, state);

    if state == KeyState::Pressed {
        let mut keys = keyboard::get_current_keys().into_iter()
            .map(|&k| Keysym::from(k)).collect();

        let press = KeyPress::new(mods.mods, keys);

        if let Some(action) = keys::get(&press) {
            action();
            return EVENT_HANDLED;
        }
    }

    return EVENT_PASS_THROUGH;
}

pub extern fn pointer_button(view: WlcView, button: u32,
                         mods_ptr: &KeyboardModifiers, key: u32,
                         state: ButtonState, point_ptr: &Point) -> bool {
    println!("pointer_button: pressed {} at {}", key, *point_ptr);
    if state == ButtonState::Pressed && !view.is_root() {
        view.focus();
    }
    false
}

pub extern fn pointer_scroll(view: WlcView, button: u32,
                         mods_ptr: &KeyboardModifiers, axis: ScrollAxis,
                         heights: [u64; 2]) -> bool {
    println!("pointer_scroll");
    false
}

pub extern fn pointer_motion(view: WlcView, time: u32, point: &Point) -> bool {
    pointer::set_position(point);
    false
}

pub extern fn touch(view: WlcView, time: u32, mods_ptr: &KeyboardModifiers,
               touch: TouchType, key: i32, point_ptr: &Point) -> bool {
    false
}

pub extern fn compositor_ready() {
    println!("Preparing compositor!");
}
<|endoftext|>


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

#[doc = "Rust wrappers around the raw JS apis"];

use std::libc::types::os::arch::c95::{size_t, c_uint};
use std::libc::{c_char, uintptr_t};
use std::num;
use std::rc;
use jsapi::*;
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use JSVAL_NULL;
use ERR;
use std::ptr;
use std::ptr::null;
use result;
use result_obj;
use std::str::raw::from_c_str;
use std::cast;
use green::task::GreenTask;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    ptr : *JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.borrow().ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

// FIXME: Is this safe once we have more than one stack segment?
extern fn gc_callback(rt: *JSRuntime, _status: JSGCStatus) {
    use std::rt::local::Local;
    use std::rt::task::Task;
    unsafe {
        let mut task = Local::borrow(None::<Task>);
        let green_task: ~GreenTask = task.get().maybe_take_runtime().unwrap();
        let c = green_task.coroutine.get_ref();
        let start = c.current_stack_segment.start() as uintptr_t;
        let end = c.current_stack_segment.end() as uintptr_t;
        JS_SetNativeStackBounds(rt, num::min(start, end), num::max(start, end));
        task.get().put_runtime(green_task);
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        JS_SetGCCallback(runtime, gc_callback);
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    ptr: *JSContext,
    rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

pub trait CxUtils {
    fn rooted_obj(&self, obj: *JSObject) -> jsobj;
    fn new_compartment(&self, globcls: *JSClass) -> Result<rc::Rc<Compartment>,()>;
    fn new_compartment_with_global(&self, global: *JSObject) -> Result<rc::Rc<Compartment>,()>;
}

impl CxUtils for rc::Rc<Cx> {
    fn rooted_obj(&self, obj: *JSObject) -> jsobj {
        let cxptr = self.borrow().ptr;
        let jsobj = rc::Rc::new(jsobj_rsrc {cx: self.clone(), cxptr: cxptr, ptr: obj});
        unsafe {
            JS_AddObjectRoot(cxptr, &jsobj.borrow().ptr);
        }
        jsobj
    }

    fn new_compartment(&self, globcls: *JSClass) -> Result<rc::Rc<Compartment>,()> {
        unsafe {
            let ptr = self.borrow().ptr;
            let globobj = JS_NewGlobalObject(ptr, globcls, null());
            result(JS_InitStandardClasses(ptr, globobj)).and_then(|_ok| {
                let compartment = rc::Rc::new(Compartment {
                    cx: self.clone(),
                    global_obj: self.rooted_obj(globobj),
                });
                self.borrow().set_cx_private(ptr::to_unsafe_ptr(compartment.borrow()) as *());
                Ok(compartment)
            })
        }
    }

    fn new_compartment_with_global(&self, global: *JSObject) -> Result<rc::Rc<Compartment>,()> {
        let compartment = rc::Rc::new(Compartment {
            cx: self.clone(),
            global_obj: self.rooted_obj(global),
        });
        unsafe {
            self.borrow().set_cx_private(ptr::to_unsafe_ptr(compartment.borrow()) as *());
        }
        Ok(compartment)
    }
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: i32) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, reportError);
        }
    }

    pub fn set_error_reporter(&self, reportfn: extern "C" fn(*JSContext, *c_char, *JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, reportfn);
        }
    }

    pub fn evaluate_script(&self, glob: jsobj, script: ~str, filename: ~str, line_num: uint)
                    -> Result<(),()> {
        let script_utf16 = script.to_utf16();
        filename.to_c_str().with_ref(|filename_cstr| {
            let rval: JSVal = JSVAL_NULL;
            debug!("Evaluating script from {:s} with content {}", filename, script);
            unsafe {
                if ERR == JS_EvaluateUCScript(self.ptr, glob.borrow().ptr,
                                              script_utf16.as_ptr(), script_utf16.len() as c_uint,
                                              filename_cstr, line_num as c_uint,
                                              ptr::to_unsafe_ptr(&rval)) {
                    debug!("...err!");
                    Err(())
                } else {
                    // we could return the script result but then we'd have
                    // to root it and so forth and, really, who cares?
                    debug!("...ok!");
                    Ok(())
                }
            }
        })
    }

    pub unsafe fn get_cx_private(&self) -> *() {
        cast::transmute(JS_GetContextPrivate(self.ptr))
    }

    pub unsafe fn set_cx_private(&self, data: *()) {
        JS_SetContextPrivate(self.ptr, cast::transmute(data));
    }

    pub unsafe fn get_obj_private(&self, obj: *JSObject) -> *() {
        cast::transmute(JS_GetPrivate(obj))
    }

    pub unsafe fn set_obj_private(&self, obj: *JSObject, data: *()) {
        JS_SetPrivate(obj, cast::transmute(data));
    }
}

pub extern fn reportError(_cx: *JSContext, msg: *c_char, report: *JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {~"none"};
        let lineno = (*report).lineno;
        let msg = from_c_str(msg);
        error!("Error at {:s}:{}: {:s}\n", fname, lineno, msg);
    }
}

// ___________________________________________________________________________
// compartment

pub struct Compartment {
    cx: rc::Rc<Cx>,
    global_obj: jsobj,
}

impl Compartment {
    pub fn define_functions(&self, specvec: &'static [JSFunctionSpec]) -> Result<(),()> {
        unsafe {
            result(JS_DefineFunctions(self.cx.borrow().ptr,
                                      self.global_obj.borrow().ptr,
                                      specvec.as_ptr()))
        }
    }
    pub fn define_properties(&self, specvec: &'static [JSPropertySpec]) -> Result<(),()> {
        unsafe {
            result(JS_DefineProperties(self.cx.borrow().ptr,
                                       self.global_obj.borrow().ptr,
                                       specvec.as_ptr()))
        }
    }
    pub fn define_property(&self,
                           name: &'static str,
                           value: JSVal,
                           getter: JSPropertyOp, setter: JSStrictPropertyOp,
                           attrs: c_uint)
        -> Result<(),()> {
        unsafe {
            name.to_c_str().with_ref(|name| {
                result(JS_DefineProperty(self.cx.borrow().ptr,
                                         self.global_obj.borrow().ptr,
                                         name,
                                         value,
                                         Some(getter),
                                         Some(setter),
                                         attrs))
            })
        }
    }
    pub fn new_object(&self, classptr: *JSClass, proto: *JSObject, parent: *JSObject)
               -> Result<jsobj, ()> {
        unsafe {
            let obj = self.cx.rooted_obj(JS_NewObject(self.cx.borrow().ptr, classptr, proto, parent));
            result_obj(obj)
        }
    }
}

// ___________________________________________________________________________
// objects

pub type jsobj = rc::Rc<jsobj_rsrc>;

pub struct jsobj_rsrc {
    cx: rc::Rc<Cx>,
    cxptr: *JSContext,
    ptr: *JSObject,
}

#[unsafe_destructor]
impl Drop for jsobj_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_RemoveObjectRoot(self.cxptr, ptr::to_unsafe_ptr(&self.ptr));
        }
    }
}

impl jsobj_rsrc {
    pub fn new_object(&self, cx: rc::Rc<Cx>, cxptr: *JSContext, ptr: *JSObject) -> jsobj {
        return rc::Rc::new(jsobj_rsrc {
            cx: cx,
            cxptr: cxptr,
            ptr: ptr
        })
    }
}

// ___________________________________________________________________________
// random utilities

pub trait to_jsstr {
    fn to_jsstr(self, cx: rc::Rc<Cx>) -> *JSString;
}

impl to_jsstr for ~str {
    fn to_jsstr(self, cx: rc::Rc<Cx>) -> *JSString {
        unsafe {
            let cbuf = cast::transmute(self.as_ptr());
            JS_NewStringCopyN(cx.borrow().ptr, cbuf, self.len() as size_t)
        }
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::super::global;
    use super::super::jsapi::{JS_GC, JS_GetRuntime};

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.borrow().set_default_options_and_version();
        cx.borrow().set_logging_error_reporter();
        cx.new_compartment(&global::BASIC_GLOBAL).and_then(|comp| {
            unsafe { JS_GC(JS_GetRuntime(cx.borrow().ptr)); }

            comp.borrow().define_functions(global::DEBUG_FNS);

            let s = ~"debug(22);";
            cx.borrow().evaluate_script(comp.borrow().global_obj.clone(), s, ~"test", 1u)
        });
    }

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

#[doc = "Rust wrappers around the raw JS apis"];

use std::libc::types::os::arch::c95::{size_t, c_uint};
use std::libc::{c_char, uintptr_t};
use std::num;
use std::rc;
use jsapi::*;
use default_stacksize;
use default_heapsize;
use JSOPTION_VAROBJFIX;
use JSOPTION_METHODJIT;
use JSOPTION_TYPE_INFERENCE;
use JSVAL_NULL;
use ERR;
use std::ptr;
use std::ptr::null;
use result;
use result_obj;
use std::str::raw::from_c_str;
use std::cast;
use green::task::GreenTask;

// ___________________________________________________________________________
// friendly Rustic API to runtimes

pub type rt = rc::Rc<rt_rsrc>;

pub struct rt_rsrc {
    ptr : *JSRuntime,
}

impl Drop for rt_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_Finish(self.ptr);
        }
    }
}

pub fn new_runtime(p: *JSRuntime) -> rt {
    return rc::Rc::new(rt_rsrc {
        ptr: p
    })
}

pub trait RtUtils {
    fn cx(&self) -> rc::Rc<Cx>;
}

impl RtUtils for rc::Rc<rt_rsrc> {
    fn cx(&self) -> rc::Rc<Cx> {
        unsafe {
            new_context(JS_NewContext(self.borrow().ptr,
                                      default_stacksize as size_t), self.clone())
        }
    }
}

// FIXME: Is this safe once we have more than one stack segment?
extern fn gc_callback(rt: *JSRuntime, _status: JSGCStatus) {
    use std::rt::local::Local;
    use std::rt::task::Task;
    unsafe {
        let mut task = Local::borrow(None::<Task>);
        let green_task: ~GreenTask = task.get().maybe_take_runtime().unwrap();
        let c = green_task.coroutine.get_ref();
        let start = c.current_stack_segment.start() as uintptr_t;
        let end = c.current_stack_segment.end() as uintptr_t;
        JS_SetNativeStackBounds(rt, num::min(start, end), num::max(start, end));
        task.get().put_runtime(green_task);
    }
}

pub fn rt() -> rt {
    unsafe {
        let runtime = JS_Init(default_heapsize);
        JS_SetGCCallback(runtime, gc_callback);
        return new_runtime(runtime);
    }
}

// ___________________________________________________________________________
// contexts

pub struct Cx {
    ptr: *JSContext,
    rt: rt,
}

#[unsafe_destructor]
impl Drop for Cx {
    fn drop(&mut self) {
        unsafe {
            JS_DestroyContext(self.ptr);
        }
    }
}

pub fn new_context(ptr: *JSContext, rt: rt) -> rc::Rc<Cx> {
    return rc::Rc::new(Cx {
        ptr: ptr,
        rt: rt,
    })
}

pub trait CxUtils {
    fn rooted_obj(&self, obj: *JSObject) -> jsobj;
    fn new_compartment(&self, globcls: *JSClass) -> Result<rc::Rc<Compartment>,()>;
    fn new_compartment_with_global(&self, global: *JSObject) -> Result<rc::Rc<Compartment>,()>;
}

impl CxUtils for rc::Rc<Cx> {
    fn rooted_obj(&self, obj: *JSObject) -> jsobj {
        let cxptr = self.borrow().ptr;
        let jsobj = rc::Rc::new(jsobj_rsrc {cx: self.clone(), cxptr: cxptr, ptr: obj});
        unsafe {
            JS_AddObjectRoot(cxptr, &jsobj.borrow().ptr);
        }
        jsobj
    }

    fn new_compartment(&self, globcls: *JSClass) -> Result<rc::Rc<Compartment>,()> {
        unsafe {
            let ptr = self.borrow().ptr;
            let globobj = JS_NewGlobalObject(ptr, globcls, null());
            result(JS_InitStandardClasses(ptr, globobj)).and_then(|_ok| {
                Ok(rc::Rc::new(Compartment {
                    cx: self.clone(),
                    global_obj: self.rooted_obj(globobj),
                }))
            })
        }
    }

    fn new_compartment_with_global(&self, global: *JSObject) -> Result<rc::Rc<Compartment>,()> {
        Ok(rc::Rc::new(Compartment {
            cx: self.clone(),
            global_obj: self.rooted_obj(global),
        }))
    }
}

impl Cx {
    pub fn set_default_options_and_version(&self) {
        self.set_options(JSOPTION_VAROBJFIX | JSOPTION_METHODJIT |
                         JSOPTION_TYPE_INFERENCE);
        self.set_version(JSVERSION_LATEST);
    }

    pub fn set_options(&self, v: c_uint) {
        unsafe {
            JS_SetOptions(self.ptr, v);
        }
    }

    pub fn set_version(&self, v: i32) {
        unsafe {
            JS_SetVersion(self.ptr, v);
        }
    }

    pub fn set_logging_error_reporter(&self) {
        unsafe {
            JS_SetErrorReporter(self.ptr, reportError);
        }
    }

    pub fn set_error_reporter(&self, reportfn: extern "C" fn(*JSContext, *c_char, *JSErrorReport)) {
        unsafe {
            JS_SetErrorReporter(self.ptr, reportfn);
        }
    }

    pub fn evaluate_script(&self, glob: jsobj, script: ~str, filename: ~str, line_num: uint)
                    -> Result<(),()> {
        let script_utf16 = script.to_utf16();
        filename.to_c_str().with_ref(|filename_cstr| {
            let rval: JSVal = JSVAL_NULL;
            debug!("Evaluating script from {:s} with content {}", filename, script);
            unsafe {
                if ERR == JS_EvaluateUCScript(self.ptr, glob.borrow().ptr,
                                              script_utf16.as_ptr(), script_utf16.len() as c_uint,
                                              filename_cstr, line_num as c_uint,
                                              ptr::to_unsafe_ptr(&rval)) {
                    debug!("...err!");
                    Err(())
                } else {
                    // we could return the script result but then we'd have
                    // to root it and so forth and, really, who cares?
                    debug!("...ok!");
                    Ok(())
                }
            }
        })
    }

    pub unsafe fn get_cx_private(&self) -> *() {
        cast::transmute(JS_GetContextPrivate(self.ptr))
    }

    pub unsafe fn set_cx_private(&self, data: *()) {
        JS_SetContextPrivate(self.ptr, cast::transmute(data));
    }

    pub unsafe fn get_obj_private(&self, obj: *JSObject) -> *() {
        cast::transmute(JS_GetPrivate(obj))
    }

    pub unsafe fn set_obj_private(&self, obj: *JSObject, data: *()) {
        JS_SetPrivate(obj, cast::transmute(data));
    }
}

pub extern fn reportError(_cx: *JSContext, msg: *c_char, report: *JSErrorReport) {
    unsafe {
        let fnptr = (*report).filename;
        let fname = if fnptr.is_not_null() {from_c_str(fnptr)} else {~"none"};
        let lineno = (*report).lineno;
        let msg = from_c_str(msg);
        error!("Error at {:s}:{}: {:s}\n", fname, lineno, msg);
    }
}

// ___________________________________________________________________________
// compartment

pub struct Compartment {
    cx: rc::Rc<Cx>,
    global_obj: jsobj,
}

impl Compartment {
    pub fn define_functions(&self, specvec: &'static [JSFunctionSpec]) -> Result<(),()> {
        unsafe {
            result(JS_DefineFunctions(self.cx.borrow().ptr,
                                      self.global_obj.borrow().ptr,
                                      specvec.as_ptr()))
        }
    }
    pub fn define_properties(&self, specvec: &'static [JSPropertySpec]) -> Result<(),()> {
        unsafe {
            result(JS_DefineProperties(self.cx.borrow().ptr,
                                       self.global_obj.borrow().ptr,
                                       specvec.as_ptr()))
        }
    }
    pub fn define_property(&self,
                           name: &'static str,
                           value: JSVal,
                           getter: JSPropertyOp, setter: JSStrictPropertyOp,
                           attrs: c_uint)
        -> Result<(),()> {
        unsafe {
            name.to_c_str().with_ref(|name| {
                result(JS_DefineProperty(self.cx.borrow().ptr,
                                         self.global_obj.borrow().ptr,
                                         name,
                                         value,
                                         Some(getter),
                                         Some(setter),
                                         attrs))
            })
        }
    }
    pub fn new_object(&self, classptr: *JSClass, proto: *JSObject, parent: *JSObject)
               -> Result<jsobj, ()> {
        unsafe {
            let obj = self.cx.rooted_obj(JS_NewObject(self.cx.borrow().ptr, classptr, proto, parent));
            result_obj(obj)
        }
    }
}

// ___________________________________________________________________________
// objects

pub type jsobj = rc::Rc<jsobj_rsrc>;

pub struct jsobj_rsrc {
    cx: rc::Rc<Cx>,
    cxptr: *JSContext,
    ptr: *JSObject,
}

#[unsafe_destructor]
impl Drop for jsobj_rsrc {
    fn drop(&mut self) {
        unsafe {
            JS_RemoveObjectRoot(self.cxptr, ptr::to_unsafe_ptr(&self.ptr));
        }
    }
}

impl jsobj_rsrc {
    pub fn new_object(&self, cx: rc::Rc<Cx>, cxptr: *JSContext, ptr: *JSObject) -> jsobj {
        return rc::Rc::new(jsobj_rsrc {
            cx: cx,
            cxptr: cxptr,
            ptr: ptr
        })
    }
}

// ___________________________________________________________________________
// random utilities

pub trait to_jsstr {
    fn to_jsstr(self, cx: rc::Rc<Cx>) -> *JSString;
}

impl to_jsstr for ~str {
    fn to_jsstr(self, cx: rc::Rc<Cx>) -> *JSString {
        unsafe {
            let cbuf = cast::transmute(self.as_ptr());
            JS_NewStringCopyN(cx.borrow().ptr, cbuf, self.len() as size_t)
        }
    }
}

#[cfg(test)]
pub mod test {
    use super::rt;
    use super::super::global;
    use super::super::jsapi::{JS_GC, JS_GetRuntime};

    #[test]
    pub fn dummy() {
        let rt = rt();
        let cx = rt.cx();
        cx.borrow().set_default_options_and_version();
        cx.borrow().set_logging_error_reporter();
        cx.new_compartment(&global::BASIC_GLOBAL).and_then(|comp| {
            unsafe { JS_GC(JS_GetRuntime(cx.borrow().ptr)); }

            comp.borrow().define_functions(global::DEBUG_FNS);

            let s = ~"debug(22);";
            cx.borrow().evaluate_script(comp.borrow().global_obj.clone(), s, ~"test", 1u)
        });
    }

}
<|endoftext|>


<commit_before>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{:?}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Display`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test

#![doc(html_root_url = "http://alexcrichton.com/toml-rs")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

#[cfg(feature = "rustc-serialize")] extern crate rustc_serialize;
#[cfg(feature = "serde")] extern crate serde;

use std::collections::BTreeMap;
use std::str::FromStr;

pub use parser::{Parser, ParserError};

#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::encoder::{Encoder, Error, encode, encode_str};
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::decoder::{Decoder, DecodeError, DecodeErrorKind, decode, decode_str};

mod parser;
mod display;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod encoder;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod decoder;

/// Representation of a TOML value.
#[derive(PartialEq, Clone, Debug)]
#[allow(missing_docs)]
pub enum Value {
    String(String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(String),
    Array(Array),
    Table(Table),
}

/// Type representing a TOML array, payload of the Value::Array variant
pub type Array = Vec<Value>;

/// Type representing a TOML table, payload of the Value::Table variant
pub type Table = BTreeMap<String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::String(..), &Value::String(..)) |
            (&Value::Integer(..), &Value::Integer(..)) |
            (&Value::Float(..), &Value::Float(..)) |
            (&Value::Boolean(..), &Value::Boolean(..)) |
            (&Value::Datetime(..), &Value::Datetime(..)) |
            (&Value::Array(..), &Value::Array(..)) |
            (&Value::Table(..), &Value::Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            Value::String(..) => "string",
            Value::Integer(..) => "integer",
            Value::Float(..) => "float",
            Value::Boolean(..) => "boolean",
            Value::Datetime(..) => "datetime",
            Value::Array(..) => "array",
            Value::Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
        match *self { Value::String(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Value::Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Value::Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Value::Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime<'a>(&'a self) -> Option<&'a str> {
        match *self { Value::Datetime(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice<'a>(&'a self) -> Option<&'a [Value]> {
        match *self { Value::Array(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table<'a>(&'a self) -> Option<&'a Table> {
        match *self { Value::Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// ```
    /// # #![allow(unstable)]
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = toml.parse().unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        let mut cur_value = self;
        for key in path.split('.') {
            match cur_value {
                &Value::Table(ref hm) => {
                    match hm.get(key) {
                        Some(v) => cur_value = v,
                        None => return None
                    }
                },
                &Value::Array(ref v) => {
                    match key.parse::<usize>().ok() {
                        Some(idx) if idx < v.len() => cur_value = &v[idx],
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)
    }
}

impl FromStr for Value {
    type Err = Vec<ParserError>;
    fn from_str(s: &str) -> Result<Value, Vec<ParserError>> {
        let mut p = Parser::new(s);
        match p.parse().map(Value::Table) {
            Some(n) => Ok(n),
            None => Err(p.errors),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Value;

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = toml.parse().unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        assert!(value.lookup("test.bar").is_none());
        assert!(value.lookup("test.foo.bar").is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = toml.parse().unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }
}
<commit_msg>Implement Value::lookup for empty path to return self<commit_after>//! A TOML-parsing library
//!
//! This library is an implementation in Rust of a parser for TOML configuration
//! files [1]. It is focused around high quality errors including specific spans
//! and detailed error messages when things go wrong.
//!
//! This implementation currently passes the language agnostic [test suite][2].
//!
//! # Example
//!
//! ```
//! let toml = r#"
//!     [test]
//!     foo = "bar"
//! "#;
//!
//! let value = toml::Parser::new(toml).parse().unwrap();
//! println!("{:?}", value);
//! ```
//!
//! # Conversions
//!
//! This library also supports using the standard `Encodable` and `Decodable`
//! traits with TOML values. This library provides the following conversion
//! capabilities:
//!
//! * `String` => `toml::Value` - via `Parser`
//! * `toml::Value` => `String` - via `Display`
//! * `toml::Value` => rust object - via `Decoder`
//! * rust object => `toml::Value` - via `Encoder`
//!
//! Convenience functions for performing multiple conversions at a time are also
//! provided.
//!
//! [1]: https://github.com/mojombo/toml
//! [2]: https://github.com/BurntSushi/toml-test

#![doc(html_root_url = "http://alexcrichton.com/toml-rs")]
#![deny(missing_docs)]
#![cfg_attr(test, deny(warnings))]

#[cfg(feature = "rustc-serialize")] extern crate rustc_serialize;
#[cfg(feature = "serde")] extern crate serde;

use std::collections::BTreeMap;
use std::str::FromStr;

pub use parser::{Parser, ParserError};

#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::encoder::{Encoder, Error, encode, encode_str};
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
pub use self::decoder::{Decoder, DecodeError, DecodeErrorKind, decode, decode_str};

mod parser;
mod display;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod encoder;
#[cfg(any(feature = "rustc-serialize", feature = "serde"))]
mod decoder;

/// Representation of a TOML value.
#[derive(PartialEq, Clone, Debug)]
#[allow(missing_docs)]
pub enum Value {
    String(String),
    Integer(i64),
    Float(f64),
    Boolean(bool),
    Datetime(String),
    Array(Array),
    Table(Table),
}

/// Type representing a TOML array, payload of the Value::Array variant
pub type Array = Vec<Value>;

/// Type representing a TOML table, payload of the Value::Table variant
pub type Table = BTreeMap<String, Value>;

impl Value {
    /// Tests whether this and another value have the same type.
    pub fn same_type(&self, other: &Value) -> bool {
        match (self, other) {
            (&Value::String(..), &Value::String(..)) |
            (&Value::Integer(..), &Value::Integer(..)) |
            (&Value::Float(..), &Value::Float(..)) |
            (&Value::Boolean(..), &Value::Boolean(..)) |
            (&Value::Datetime(..), &Value::Datetime(..)) |
            (&Value::Array(..), &Value::Array(..)) |
            (&Value::Table(..), &Value::Table(..)) => true,

            _ => false,
        }
    }

    /// Returns a human-readable representation of the type of this value.
    pub fn type_str(&self) -> &'static str {
        match *self {
            Value::String(..) => "string",
            Value::Integer(..) => "integer",
            Value::Float(..) => "float",
            Value::Boolean(..) => "boolean",
            Value::Datetime(..) => "datetime",
            Value::Array(..) => "array",
            Value::Table(..) => "table",
        }
    }

    /// Extracts the string of this value if it is a string.
    pub fn as_str<'a>(&'a self) -> Option<&'a str> {
        match *self { Value::String(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the integer value if it is an integer.
    pub fn as_integer(&self) -> Option<i64> {
        match *self { Value::Integer(i) => Some(i), _ => None }
    }

    /// Extracts the float value if it is a float.
    pub fn as_float(&self) -> Option<f64> {
        match *self { Value::Float(f) => Some(f), _ => None }
    }

    /// Extracts the boolean value if it is a boolean.
    pub fn as_bool(&self) -> Option<bool> {
        match *self { Value::Boolean(b) => Some(b), _ => None }
    }

    /// Extracts the datetime value if it is a datetime.
    ///
    /// Note that a parsed TOML value will only contain ISO 8601 dates. An
    /// example date is:
    ///
    /// ```notrust
    /// 1979-05-27T07:32:00Z
    /// ```
    pub fn as_datetime<'a>(&'a self) -> Option<&'a str> {
        match *self { Value::Datetime(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the array value if it is an array.
    pub fn as_slice<'a>(&'a self) -> Option<&'a [Value]> {
        match *self { Value::Array(ref s) => Some(&**s), _ => None }
    }

    /// Extracts the table value if it is a table.
    pub fn as_table<'a>(&'a self) -> Option<&'a Table> {
        match *self { Value::Table(ref s) => Some(s), _ => None }
    }

    /// Lookups for value at specified path.
    ///
    /// Uses '.' as a path separator.
    ///
    /// Note: arrays have zero-based indexes.
    ///
    /// Note: empty path returns self.
    ///
    /// ```
    /// # #![allow(unstable)]
    /// let toml = r#"
    ///      [test]
    ///      foo = "bar"
    ///
    ///      [[values]]
    ///      foo = "baz"
    ///
    ///      [[values]]
    ///      foo = "qux"
    /// "#;
    /// let value: toml::Value = toml.parse().unwrap();
    ///
    /// let foo = value.lookup("test.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "bar");
    ///
    /// let foo = value.lookup("values.1.foo").unwrap();
    /// assert_eq!(foo.as_str().unwrap(), "qux");
    ///
    /// let no_bar = value.lookup("test.bar");
    /// assert_eq!(no_bar.is_none(), true);
    /// ```
    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
        let mut cur_value = self;
        if path.len() == 0 {
            return Some(cur_value)
        }

        for key in path.split('.') {
            match cur_value {
                &Value::Table(ref hm) => {
                    match hm.get(key) {
                        Some(v) => cur_value = v,
                        None => return None
                    }
                },
                &Value::Array(ref v) => {
                    match key.parse::<usize>().ok() {
                        Some(idx) if idx < v.len() => cur_value = &v[idx],
                        _ => return None
                    }
                },
                _ => return None
            }
        };

        Some(cur_value)
    }
}

impl FromStr for Value {
    type Err = Vec<ParserError>;
    fn from_str(s: &str) -> Result<Value, Vec<ParserError>> {
        let mut p = Parser::new(s);
        match p.parse().map(Value::Table) {
            Some(n) => Ok(n),
            None => Err(p.errors),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::Value;

    #[test]
    fn lookup_valid() {
        let toml = r#"
              [test]
              foo = "bar"

              [[values]]
              foo = "baz"

              [[values]]
              foo = "qux"
        "#;

        let value: Value = toml.parse().unwrap();

        let test_foo = value.lookup("test.foo").unwrap();
        assert_eq!(test_foo.as_str().unwrap(), "bar");

        let foo1 = value.lookup("values.1.foo").unwrap();
        assert_eq!(foo1.as_str().unwrap(), "qux");

        assert!(value.lookup("test.bar").is_none());
        assert!(value.lookup("test.foo.bar").is_none());
    }

    #[test]
    fn lookup_invalid_index() {
        let toml = r#"
            [[values]]
            foo = "baz"
        "#;

        let value: Value = toml.parse().unwrap();

        let foo = value.lookup("test.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.100.foo");
        assert!(foo.is_none());

        let foo = value.lookup("values.str.foo");
        assert!(foo.is_none());
    }

    #[test]
    fn lookup_self() {
        let value: Value = r#"foo = "bar""#.parse().unwrap();

        let foo = value.lookup("foo").unwrap();
        assert_eq!(foo.as_str().unwrap(), "bar");

        let foo = value.lookup("").unwrap();
        assert!(foo.as_table().is_some());

        let baz = foo.lookup("foo").unwrap();
        assert_eq!(baz.as_str().unwrap(), "bar");
    }
}
<|endoftext|>


<commit_before>#[derive(PartialEq, Debug)]
struct Shoe {
    size: u32,
    style: String,
}

fn shoe_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    shoes.into_iter()
        .filter(|s| s.size == shoe_size)
        .collect()
}

#[test]
fn filters_by_size() {
    let shoes = vec![
        Shoe { size: 10, style: String::from("sneaker") },
        Shoe { size: 13, style: String::from("sandal") },
        Shoe { size: 10, style: String::from("boot") },
    ];

    let in_my_size = shoe_in_my_size(shoes, 10);
    assert_eq!(
        in_my_size,
        vec![
            Shoe { size: 10, style: String::from("sneaker") },
            Shoe { size: 10, style: String::from("boot") },
        ]
    );
}
<commit_msg>iterable counter struct<commit_after>#[derive(PartialEq, Debug)]
struct Shoe {
    size: u32,
    style: String,
}

fn shoe_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    shoes.into_iter()
        .filter(|s| s.size == shoe_size)
        .collect()
}

#[test]
fn filters_by_size() {
    let shoes = vec![
        Shoe { size: 10, style: String::from("sneaker") },
        Shoe { size: 13, style: String::from("sandal") },
        Shoe { size: 10, style: String::from("boot") },
    ];

    let in_my_size = shoe_in_my_size(shoes, 10);
    assert_eq!(
        in_my_size,
        vec![
            Shoe { size: 10, style: String::from("sneaker") },
            Shoe { size: 10, style: String::from("boot") },
        ]
    );
}

struct Counter {
    count: u32,
}

impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;

        if self.count < 6 {
            Some(self.count)
        } else {
            None
        }
    }
}

#[test]
fn calling_next_directly() {
    let mut counter = Counter::new();

    assert_eq!(counter.next(), Some(1));
    assert_eq!(counter.next(), Some(2));
    assert_eq!(counter.next(), Some(3));
    assert_eq!(counter.next(), Some(4));
    assert_eq!(counter.next(), Some(5));
    assert_eq!(counter.next(), None);
}

#[test]
fn using_other_iterator_trait_method() {
    let sum: u32 = Counter::new().zip(Counter::new().skip(1))
                                 .map(|(a, b)| a * b)
                                 .filter(|x| x % 3 == 0)
                                 .sum();
    assert_eq!(18, sum);
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    account_address::AccountAddress,
    account_config::{
        type_tag_for_currency_code, AccountResource, AccountRole, BalanceResource, ChildVASP,
        ChildVASPRole, CurrencyInfoResource, EmptyRole, ParentVASP, ParentVASPRole, UnhostedRole,
        ACCOUNT_RECEIVED_EVENT_PATH, ACCOUNT_SENT_EVENT_PATH,
    },
    block_metadata::{LibraBlockResource, NEW_BLOCK_EVENT_PATH},
    event::EventHandle,
    libra_timestamp::LibraTimestampResource,
    on_chain_config::{ConfigurationResource, OnChainConfig, ValidatorSet},
    validator_config::ValidatorConfigResource,
};
use anyhow::{bail, Error, Result};
use move_core_types::{identifier::Identifier, move_resource::MoveResource};
use serde::{de::DeserializeOwned, export::Formatter, Deserialize, Serialize};
use std::{collections::btree_map::BTreeMap, convert::TryFrom, fmt};

#[derive(Default, Deserialize, PartialEq, Serialize)]
pub struct AccountState(BTreeMap<Vec<u8>, Vec<u8>>);

impl AccountState {
    // By design and do not remove
    pub fn get_account_address(&self) -> Result<Option<AccountAddress>> {
        self.get_account_resource()
            .map(|opt_ar| opt_ar.map(|ar| ar.sent_events().key().get_creator_address()))
    }

    pub fn get_account_resource(&self) -> Result<Option<AccountResource>> {
        self.get_resource(&AccountResource::resource_path())
    }

    pub fn get_balance_resources(
        &self,
        currency_codes: &[Identifier],
    ) -> Result<BTreeMap<Identifier, BalanceResource>> {
        currency_codes
            .iter()
            .filter_map(|currency_code| {
                let currency_type_tag = type_tag_for_currency_code(currency_code.to_owned());
                // TODO: update this to use BalanceResource::resource_path once that takes type
                // parameters
                self.get_resource(&BalanceResource::access_path_for(currency_type_tag))
                    .transpose()
                    .map(|balance| balance.map(|b| (currency_code.to_owned(), b)))
            })
            .collect()
    }

    pub fn get_configuration_resource(&self) -> Result<Option<ConfigurationResource>> {
        self.get_resource(&ConfigurationResource::resource_path())
    }

    pub fn get_libra_timestamp_resource(&self) -> Result<Option<LibraTimestampResource>> {
        self.get_resource(&LibraTimestampResource::resource_path())
    }

    pub fn get_validator_config_resource(&self) -> Result<Option<ValidatorConfigResource>> {
        self.get_resource(&ValidatorConfigResource::resource_path())
    }

    pub fn get_account_role(&self) -> Result<Option<AccountRole>> {
        if self
            .0
            .contains_key(&AccountRole::access_path_for::<ParentVASP>())
        {
            self.get_resource(&AccountRole::access_path_for::<ParentVASP>())
                .map(|role| role.map(|role: ParentVASPRole| AccountRole::ParentVASP(role.role)))
        } else if self
            .0
            .contains_key(&AccountRole::access_path_for::<ChildVASP>())
        {
            self.get_resource(&AccountRole::access_path_for::<ChildVASP>())
                .map(|x| x.map(|role: ChildVASPRole| AccountRole::ChildVASP(role.role)))
        } else if self
            .0
            .contains_key(&AccountRole::access_path_for::<UnhostedRole>())
        {
            self.get_resource(&AccountRole::access_path_for::<UnhostedRole>())
                .map(|x| x.map(|_: UnhostedRole| AccountRole::Unhosted))
        } else if self
            .0
            .contains_key(&AccountRole::access_path_for::<EmptyRole>())
        {
            self.get_resource(&AccountRole::access_path_for::<EmptyRole>())
                .map(|x| x.map(|_: EmptyRole| AccountRole::Empty))
        } else {
            Ok(Some(AccountRole::Unknown))
        }
    }

    pub fn get_validator_set(&self) -> Result<Option<ValidatorSet>> {
        self.get_resource(&ValidatorSet::CONFIG_ID.access_path().path)
    }

    pub fn get_libra_block_resource(&self) -> Result<Option<LibraBlockResource>> {
        self.get_resource(&LibraBlockResource::resource_path())
    }

    pub fn get_event_handle_by_query_path(&self, query_path: &[u8]) -> Result<Option<EventHandle>> {
        let event_handle = if *ACCOUNT_RECEIVED_EVENT_PATH == query_path {
            self.get_account_resource()?
                .map(|account_resource| account_resource.received_events().clone())
        } else if *ACCOUNT_SENT_EVENT_PATH == query_path {
            self.get_account_resource()?
                .map(|account_resource| account_resource.sent_events().clone())
        } else if *NEW_BLOCK_EVENT_PATH == query_path {
            self.get_libra_block_resource()?
                .map(|libra_block_resource| libra_block_resource.new_block_events().clone())
        } else {
            bail!("Unrecognized query path: {:?}", query_path);
        };

        Ok(event_handle)
    }

    pub fn get(&self, key: &[u8]) -> Option<&Vec<u8>> {
        self.0.get(key)
    }

    pub fn get_resource<T: DeserializeOwned>(&self, key: &[u8]) -> Result<Option<T>> {
        self.0
            .get(key)
            .map(|bytes| lcs::from_bytes(bytes))
            .transpose()
            .map_err(Into::into)
    }

    pub fn insert(&mut self, key: Vec<u8>, value: Vec<u8>) -> Option<Vec<u8>> {
        self.0.insert(key, value)
    }

    pub fn remove(&mut self, key: &[u8]) -> Option<Vec<u8>> {
        self.0.remove(key)
    }

    pub fn is_empty(&self) -> bool {
        self.0.is_empty()
    }

    pub fn iter(&self) -> impl std::iter::Iterator<Item = (&Vec<u8>, &Vec<u8>)> {
        self.0.iter()
    }
}

impl fmt::Debug for AccountState {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        // TODO: add support for other types of resources
        let account_resource_str = self
            .get_account_resource()
            .map(|account_resource_opt| format!("{:#?}", account_resource_opt))
            .unwrap_or_else(|e| format!("parse error: {:#?}", e));

        let libra_timestamp_str = self
            .get_libra_timestamp_resource()
            .map(|libra_timestamp_opt| format!("{:#?}", libra_timestamp_opt))
            .unwrap_or_else(|e| format!("parse: {:#?}", e));

        let validator_config_str = self
            .get_validator_config_resource()
            .map(|validator_config_opt| format!("{:#?}", validator_config_opt))
            .unwrap_or_else(|e| format!("parse error: {:#?}", e));

        let validator_set_str = self
            .get_validator_set()
            .map(|validator_set_opt| format!("{:#?}", validator_set_opt))
            .unwrap_or_else(|e| format!("parse error: {:#?}", e));

        write!(
            f,
            "{{ \n \
             AccountResource {{ {} }} \n \
             LibraTimestamp {{ {} }} \n \
             ValidatorConfig {{ {} }} \n \
             ValidatorSet {{ {} }} \n \
             }}",
            account_resource_str, libra_timestamp_str, validator_config_str, validator_set_str,
        )
    }
}

impl TryFrom<(&AccountResource, &BalanceResource)> for AccountState {
    type Error = Error;

    fn try_from(
        (account_resource, balance_resource): (&AccountResource, &BalanceResource),
    ) -> Result<Self> {
        let mut btree_map: BTreeMap<Vec<u8>, Vec<u8>> = BTreeMap::new();
        btree_map.insert(
            AccountResource::resource_path(),
            lcs::to_bytes(account_resource)?,
        );
        btree_map.insert(
            BalanceResource::resource_path(),
            lcs::to_bytes(balance_resource)?,
        );

        Ok(Self(btree_map))
    }
}
<commit_msg>Removing is_empty from types/src/account_state.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    account_address::AccountAddress,
    account_config::{
        type_tag_for_currency_code, AccountResource, AccountRole, BalanceResource, ChildVASP,
        ChildVASPRole, EmptyRole, ParentVASP, ParentVASPRole, UnhostedRole,
        ACCOUNT_RECEIVED_EVENT_PATH, ACCOUNT_SENT_EVENT_PATH,
    },
    block_metadata::{LibraBlockResource, NEW_BLOCK_EVENT_PATH},
    event::EventHandle,
    libra_timestamp::LibraTimestampResource,
    on_chain_config::{ConfigurationResource, OnChainConfig, ValidatorSet},
    validator_config::ValidatorConfigResource,
};
use anyhow::{bail, Error, Result};
use move_core_types::{identifier::Identifier, move_resource::MoveResource};
use serde::{de::DeserializeOwned, export::Formatter, Deserialize, Serialize};
use std::{collections::btree_map::BTreeMap, convert::TryFrom, fmt};

#[derive(Default, Deserialize, PartialEq, Serialize)]
pub struct AccountState(BTreeMap<Vec<u8>, Vec<u8>>);

impl AccountState {
    // By design and do not remove
    pub fn get_account_address(&self) -> Result<Option<AccountAddress>> {
        self.get_account_resource()
            .map(|opt_ar| opt_ar.map(|ar| ar.sent_events().key().get_creator_address()))
    }

    pub fn get_account_resource(&self) -> Result<Option<AccountResource>> {
        self.get_resource(&AccountResource::resource_path())
    }

    pub fn get_balance_resources(
        &self,
        currency_codes: &[Identifier],
    ) -> Result<BTreeMap<Identifier, BalanceResource>> {
        currency_codes
            .iter()
            .filter_map(|currency_code| {
                let currency_type_tag = type_tag_for_currency_code(currency_code.to_owned());
                // TODO: update this to use BalanceResource::resource_path once that takes type
                // parameters
                self.get_resource(&BalanceResource::access_path_for(currency_type_tag))
                    .transpose()
                    .map(|balance| balance.map(|b| (currency_code.to_owned(), b)))
            })
            .collect()
    }

    pub fn get_configuration_resource(&self) -> Result<Option<ConfigurationResource>> {
        self.get_resource(&ConfigurationResource::resource_path())
    }

    pub fn get_libra_timestamp_resource(&self) -> Result<Option<LibraTimestampResource>> {
        self.get_resource(&LibraTimestampResource::resource_path())
    }

    pub fn get_validator_config_resource(&self) -> Result<Option<ValidatorConfigResource>> {
        self.get_resource(&ValidatorConfigResource::resource_path())
    }

    pub fn get_account_role(&self) -> Result<Option<AccountRole>> {
        if self
            .0
            .contains_key(&AccountRole::access_path_for::<ParentVASP>())
        {
            self.get_resource(&AccountRole::access_path_for::<ParentVASP>())
                .map(|role| role.map(|role: ParentVASPRole| AccountRole::ParentVASP(role.role)))
        } else if self
            .0
            .contains_key(&AccountRole::access_path_for::<ChildVASP>())
        {
            self.get_resource(&AccountRole::access_path_for::<ChildVASP>())
                .map(|x| x.map(|role: ChildVASPRole| AccountRole::ChildVASP(role.role)))
        } else if self
            .0
            .contains_key(&AccountRole::access_path_for::<UnhostedRole>())
        {
            self.get_resource(&AccountRole::access_path_for::<UnhostedRole>())
                .map(|x| x.map(|_: UnhostedRole| AccountRole::Unhosted))
        } else if self
            .0
            .contains_key(&AccountRole::access_path_for::<EmptyRole>())
        {
            self.get_resource(&AccountRole::access_path_for::<EmptyRole>())
                .map(|x| x.map(|_: EmptyRole| AccountRole::Empty))
        } else {
            Ok(Some(AccountRole::Unknown))
        }
    }

    pub fn get_validator_set(&self) -> Result<Option<ValidatorSet>> {
        self.get_resource(&ValidatorSet::CONFIG_ID.access_path().path)
    }

    pub fn get_libra_block_resource(&self) -> Result<Option<LibraBlockResource>> {
        self.get_resource(&LibraBlockResource::resource_path())
    }

    pub fn get_event_handle_by_query_path(&self, query_path: &[u8]) -> Result<Option<EventHandle>> {
        let event_handle = if *ACCOUNT_RECEIVED_EVENT_PATH == query_path {
            self.get_account_resource()?
                .map(|account_resource| account_resource.received_events().clone())
        } else if *ACCOUNT_SENT_EVENT_PATH == query_path {
            self.get_account_resource()?
                .map(|account_resource| account_resource.sent_events().clone())
        } else if *NEW_BLOCK_EVENT_PATH == query_path {
            self.get_libra_block_resource()?
                .map(|libra_block_resource| libra_block_resource.new_block_events().clone())
        } else {
            bail!("Unrecognized query path: {:?}", query_path);
        };

        Ok(event_handle)
    }

    pub fn get(&self, key: &[u8]) -> Option<&Vec<u8>> {
        self.0.get(key)
    }

    pub fn get_resource<T: DeserializeOwned>(&self, key: &[u8]) -> Result<Option<T>> {
        self.0
            .get(key)
            .map(|bytes| lcs::from_bytes(bytes))
            .transpose()
            .map_err(Into::into)
    }

    pub fn insert(&mut self, key: Vec<u8>, value: Vec<u8>) -> Option<Vec<u8>> {
        self.0.insert(key, value)
    }

    pub fn remove(&mut self, key: &[u8]) -> Option<Vec<u8>> {
        self.0.remove(key)
    }

    pub fn iter(&self) -> impl std::iter::Iterator<Item = (&Vec<u8>, &Vec<u8>)> {
        self.0.iter()
    }
}

impl fmt::Debug for AccountState {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        // TODO: add support for other types of resources
        let account_resource_str = self
            .get_account_resource()
            .map(|account_resource_opt| format!("{:#?}", account_resource_opt))
            .unwrap_or_else(|e| format!("parse error: {:#?}", e));

        let libra_timestamp_str = self
            .get_libra_timestamp_resource()
            .map(|libra_timestamp_opt| format!("{:#?}", libra_timestamp_opt))
            .unwrap_or_else(|e| format!("parse: {:#?}", e));

        let validator_config_str = self
            .get_validator_config_resource()
            .map(|validator_config_opt| format!("{:#?}", validator_config_opt))
            .unwrap_or_else(|e| format!("parse error: {:#?}", e));

        let validator_set_str = self
            .get_validator_set()
            .map(|validator_set_opt| format!("{:#?}", validator_set_opt))
            .unwrap_or_else(|e| format!("parse error: {:#?}", e));

        write!(
            f,
            "{{ \n \
             AccountResource {{ {} }} \n \
             LibraTimestamp {{ {} }} \n \
             ValidatorConfig {{ {} }} \n \
             ValidatorSet {{ {} }} \n \
             }}",
            account_resource_str, libra_timestamp_str, validator_config_str, validator_set_str,
        )
    }
}

impl TryFrom<(&AccountResource, &BalanceResource)> for AccountState {
    type Error = Error;

    fn try_from(
        (account_resource, balance_resource): (&AccountResource, &BalanceResource),
    ) -> Result<Self> {
        let mut btree_map: BTreeMap<Vec<u8>, Vec<u8>> = BTreeMap::new();
        btree_map.insert(
            AccountResource::resource_path(),
            lcs::to_bytes(account_resource)?,
        );
        btree_map.insert(
            BalanceResource::resource_path(),
            lcs::to_bytes(balance_resource)?,
        );

        Ok(Self(btree_map))
    }
}
<|endoftext|>


<commit_before>pub const LICENSE: &'static str = "MIT License

Copyright (c) 2016 Ansley Peduru

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the 'Software'), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.";

pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");

pub const HELP: &'static str = "Welcome to bspl!

bspl supports 32-bit operations.
You may only use decimals in your operations.
Use the following bitwise operators: ~ | & ^ << >>

Try out the following operation to get started.
12 | (1 << 12)";

pub const KEYWORDS: &'static [&'static str] = &["license", "exit", "help", "version"];
<commit_msg>Remove static qualifier from constants<commit_after>pub const LICENSE: &str = "MIT License

Copyright (c) 2016 Ansley Peduru

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the 'Software'), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.";

pub const VERSION: &str = env!("CARGO_PKG_VERSION");

pub const HELP: &str = "Welcome to bspl!

bspl supports 32-bit operations.
You may only use decimals in your operations.
Use the following bitwise operators: ~ | & ^ << >>

Try out the following operation to get started.
12 | (1 << 12)";

pub const KEYWORDS: &[&str] = &["license", "exit", "help", "version"];
<|endoftext|>