<commit_before>//! It's a tree!

use std::ptr;

use rustwlc::handle::WlcView;

use super::container::*;

#[derive(Debug, PartialEq, Eq)]
pub struct Node {
    // We need a mut pointer so we can modify the parent
    parent: *mut Node,
    val: Container,
    children: Vec<Node>
}

impl Node {
    /// Create a new node with the existing value.
    /// For root-style constructors.
    pub fn new(val: Container) -> Node {
        Node {
            parent: ptr::null_mut(),
            val: val,
            children: Vec::new()
        }
    }

    /// Add a new child node to this node, using a value
    pub fn new_child(&mut self, val: Container) -> &mut Node {
        let self_mut = self as *mut Node;
        self.children.push(Node {
            parent: self_mut,
            val: val,
            children: Vec::new()
        });
        let last_ix = self.children.len() -1;
        &mut self.children[last_ix]
    }

    /// Whether this node has a (currently-reachable) parent
    #[allow(dead_code)]
    pub fn has_parent(&self) -> bool {
        !self.parent.is_null()
    }

    /// Gets the type of container this node holds
    pub fn get_container_type(&self) -> ContainerType {
        self.val.get_type()
    }

    /// Tries to get an ancestor of the requested type
    pub fn get_ancestor_of_type(&self, container_type: ContainerType)
                                -> Option<&Node> {
        let mut maybe_parent = self.get_parent();
        loop {
            if let Some(parent) = maybe_parent {
                if parent.get_container_type() == container_type {
                    return Some(parent);
                }
                maybe_parent = parent.get_parent();
            }
            else {
                return None;
            }
        }
    }

    /// Gets a node by handle
    pub fn find_view_by_handle(&self, view_handle: &WlcView) -> Option<&Node>{
        match self.get_val() {
            &Container::View { ref handle, .. } => {
                if view_handle == handle {
                    Some(self)
                } else {
                    None
                }
            },
            _ => {
                for child in self.get_children() {
                    if let Some(view) = child.find_view_by_handle(view_handle) {
                        return Some(view);
                    }
                }
                return None;
            }
        }
    }

    /// Gets the parent of this node (if it exists)
    pub fn get_parent(&self) -> Option<&mut Node> {
        if self.parent.is_null() {
            return None;
        }
        unsafe {
            return Some(&mut *self.parent);
        }
    }

    /// Borrow the children of this node.
    pub fn get_children(&self) -> &[Node] {
        &self.children
    }

    /// Mutably borrow the children of this mutable node
    pub fn get_children_mut(&mut self) -> &mut[Node] {
        &mut self.children
    }

    /// Remove a child at the given index
    #[allow(dead_code)]
    pub fn remove_child_at(&mut self, index: usize) -> Option<Node> {
        if index > self.children.len() - 1 {
            return None;
        }
        let mut child = self.children.remove(index);
        child.parent = ptr::null_mut();
        return Some(child);
    }

    /// Moves another node to be a sibling of this node.
    #[allow(dead_code)]
    pub fn add_sibling(&self, node: Node) -> Result<(), ()> {
        if let Some(parent) = self.get_parent() {
            node.move_to(parent);
            Ok(())
        }
        else {
            Err(())
        }
    }

    /// Whether this node is a parent of another node
    #[allow(dead_code)]
    pub fn is_parent_of(&self, other: &Node) -> bool {
        // Fun fact, other.parent == self as *const Node won't compile
        self as *const Node == other.parent
    }

    /// Remove a node from its parent.
    /// This method will mutate the parent if it exists.
    pub fn remove_from_parent(&mut self) -> Option<Node> {
        let mut result: Option<Node> = None;
        if let Some(mut parent) = self.get_parent() {
            if let Some(index) = parent.children.iter().position(|c| c == self) {
                result = Some(parent.children.remove(index));
            }
        }
        self.parent = ptr::null_mut();
        result
    }

    /// Removes a child from self
    pub fn remove_child(&mut self, other: &Node) -> Option<Node> {
        if let Some(index) = self.children.iter().position(|c| c == other) {
            let mut child = self.children.remove(index);
            child.parent = ptr::null_mut();
            Some(child)
        }
        else {
            None
        }
    }

    /// Removes this node from its current parent and adds it to the given node
    /// as a child
    pub fn move_to(mut self, new_parent: &mut Node) {
        self.remove_from_parent();
        self.parent = new_parent as *mut Node;
        new_parent.children.push(self);
    }

    /// Gets the container that this node has
    pub fn get_val(&self) -> &Container {
        &self.val
    }

    /// Sets the visibility of the container and its children
    pub fn set_visibility(&mut self, visibility: bool) {
        self.val.set_visibility(visibility);
        for child in self.get_children_mut() {
            child.set_visibility(visibility);
        }
    }
}

impl Drop for Node {
    fn drop(&mut self) {
        println!("Dropping a node.");
        let children: &mut Vec<Node> = &mut self.children;
        for mut child in children {
            child.parent = ptr::null_mut();
        }
    }
}

unsafe impl Sync for Node {}
unsafe impl Send for Node {}

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

    /// Nodes can have children added to them
    #[test]
    fn new_child() {
        let mut root = Node::new(Container::Root);
        root.new_child(Container::Root);
        root.new_child(Container::Root); // This is okay
        {
            let mut third_child = root.new_child(Container::Root);
            third_child.new_child(Container::Root);
            //root.new_child(Root); // Have to wait for 3rd child to drop
        }
        root.new_child(Container::Root); // Now this works
        assert_eq!(root.children.len(), 4);
    }

    #[test]
    fn has_get_parent() {
        let mut root = Node::new(Container::Root);
        assert!(!root.has_parent(), "Root has a parent");
        assert_eq!(root.get_parent(), None);

        let child = root.new_child(Container::Root);
        assert!(child.has_parent(), "Child does not have parent");
        assert!(child.get_parent().is_some(), "Child does not have parent");
        let parent = child.get_parent().expect("Asserted child has parent");
        assert_eq!(parent.get_container_type(), ContainerType::Root);
    }

    #[test]
    fn get_container_type() {
        let mut root = Node::new(Container::Root);
        assert_eq!(root.get_container_type(), ContainerType::Root);
        {
            let wksp = root.new_child(
                Container::Workspace { name: "Foo".to_string(),
                                       focused: false });
            assert_eq!(wksp.get_container_type(), ContainerType::Workspace);
        }
        {
            let container = root.new_child(Container::Container {
                layout: Layout::Horizontal, visible: false,
                floating: false, focused: false
            });
            assert_eq!(container.get_container_type(), ContainerType::Container);
        }
    }

    #[test]
    fn get_children() {
        // Create a root with 3 children. The 3rd child has 2 children.
        let mut root = Node::new(Container::Root);
        root.new_child(Container::Root);
        root.new_child(Container::Root);
        {
            let third_child = root.new_child(Container::Root);
            third_child.new_child(Container::Root);
            third_child.new_child(Container::Root);
        }
        let root_children = root.get_children();
        assert!(!root_children.is_empty(), "Root has children");
        assert_eq!(root_children.len(), 3);
        assert!(root_children.last().is_some(), "Root has final child");
        let third_child = root_children.last().expect("Asserted unwrap!");
        assert_eq!(third_child.get_children().len(), 2);
        let third_child_second_child = third_child.get_children().last()
            .expect("Asserted unwrap!");
        assert!(third_child_second_child.get_children().is_empty(),
                "Grandchild doesn't have children");
    }

    #[test]
    fn get_children_mut() {
        // Start out with one child, use get_mut_children to add grandchild.
        let mut root = Node::new(Container::Root);
        root.new_child(Container::Root);

        assert!(root.get_children().last().expect("Root has child")
                .get_children().is_empty(), "Root has no grandchildren");

        {
            let mut children = root.get_children_mut();
            assert_eq!(children.len(), 1);

            let mut child = &mut children[0];
            child.new_child(Container::Root);
        }

        assert_eq!(root.get_children().last().expect("Asserted unwrap!")
                .get_children().len(), 1);
    }

    #[test]
    fn remove_child_at() {
        let mut root = Node::new(Container::Root);
        root.new_child(Container::Root);
        root.new_child(Container::Workspace {
            name: "Foo".to_string(), focused: false
        });
        root.new_child(Container::Root);

        let worksp = root.remove_child_at(1).expect("Index should be valid");
        assert_eq!(worksp.get_container_type(), ContainerType::Workspace);
        assert_eq!(root.get_children().len(), 2)
    }
}
<commit_msg>Remove printing 'dropping a node'<commit_after>//! It's a tree!

use std::ptr;

use rustwlc::handle::WlcView;

use super::container::*;

#[derive(Debug, PartialEq, Eq)]
pub struct Node {
    // We need a mut pointer so we can modify the parent
    parent: *mut Node,
    val: Container,
    children: Vec<Node>
}

impl Node {
    /// Create a new node with the existing value.
    /// For root-style constructors.
    pub fn new(val: Container) -> Node {
        Node {
            parent: ptr::null_mut(),
            val: val,
            children: Vec::new()
        }
    }

    /// Add a new child node to this node, using a value
    pub fn new_child(&mut self, val: Container) -> &mut Node {
        let self_mut = self as *mut Node;
        self.children.push(Node {
            parent: self_mut,
            val: val,
            children: Vec::new()
        });
        let last_ix = self.children.len() -1;
        &mut self.children[last_ix]
    }

    /// Whether this node has a (currently-reachable) parent
    #[allow(dead_code)]
    pub fn has_parent(&self) -> bool {
        !self.parent.is_null()
    }

    /// Gets the type of container this node holds
    pub fn get_container_type(&self) -> ContainerType {
        self.val.get_type()
    }

    /// Tries to get an ancestor of the requested type
    pub fn get_ancestor_of_type(&self, container_type: ContainerType)
                                -> Option<&Node> {
        let mut maybe_parent = self.get_parent();
        loop {
            if let Some(parent) = maybe_parent {
                if parent.get_container_type() == container_type {
                    return Some(parent);
                }
                maybe_parent = parent.get_parent();
            }
            else {
                return None;
            }
        }
    }

    /// Gets a node by handle
    pub fn find_view_by_handle(&self, view_handle: &WlcView) -> Option<&Node>{
        match self.get_val() {
            &Container::View { ref handle, .. } => {
                if view_handle == handle {
                    Some(self)
                } else {
                    None
                }
            },
            _ => {
                for child in self.get_children() {
                    if let Some(view) = child.find_view_by_handle(view_handle) {
                        return Some(view);
                    }
                }
                return None;
            }
        }
    }

    /// Gets the parent of this node (if it exists)
    pub fn get_parent(&self) -> Option<&mut Node> {
        if self.parent.is_null() {
            return None;
        }
        unsafe {
            return Some(&mut *self.parent);
        }
    }

    /// Borrow the children of this node.
    pub fn get_children(&self) -> &[Node] {
        &self.children
    }

    /// Mutably borrow the children of this mutable node
    pub fn get_children_mut(&mut self) -> &mut[Node] {
        &mut self.children
    }

    /// Remove a child at the given index
    #[allow(dead_code)]
    pub fn remove_child_at(&mut self, index: usize) -> Option<Node> {
        if index > self.children.len() - 1 {
            return None;
        }
        let mut child = self.children.remove(index);
        child.parent = ptr::null_mut();
        return Some(child);
    }

    /// Moves another node to be a sibling of this node.
    #[allow(dead_code)]
    pub fn add_sibling(&self, node: Node) -> Result<(), ()> {
        if let Some(parent) = self.get_parent() {
            node.move_to(parent);
            Ok(())
        }
        else {
            Err(())
        }
    }

    /// Whether this node is a parent of another node
    #[allow(dead_code)]
    pub fn is_parent_of(&self, other: &Node) -> bool {
        // Fun fact, other.parent == self as *const Node won't compile
        self as *const Node == other.parent
    }

    /// Remove a node from its parent.
    /// This method will mutate the parent if it exists.
    pub fn remove_from_parent(&mut self) -> Option<Node> {
        let mut result: Option<Node> = None;
        if let Some(mut parent) = self.get_parent() {
            if let Some(index) = parent.children.iter().position(|c| c == self) {
                result = Some(parent.children.remove(index));
            }
        }
        self.parent = ptr::null_mut();
        result
    }

    /// Removes a child from self
    pub fn remove_child(&mut self, other: &Node) -> Option<Node> {
        if let Some(index) = self.children.iter().position(|c| c == other) {
            let mut child = self.children.remove(index);
            child.parent = ptr::null_mut();
            Some(child)
        }
        else {
            None
        }
    }

    /// Removes this node from its current parent and adds it to the given node
    /// as a child
    pub fn move_to(mut self, new_parent: &mut Node) {
        self.remove_from_parent();
        self.parent = new_parent as *mut Node;
        new_parent.children.push(self);
    }

    /// Gets the container that this node has
    pub fn get_val(&self) -> &Container {
        &self.val
    }

    /// Sets the visibility of the container and its children
    pub fn set_visibility(&mut self, visibility: bool) {
        self.val.set_visibility(visibility);
        for child in self.get_children_mut() {
            child.set_visibility(visibility);
        }
    }
}

impl Drop for Node {
    fn drop(&mut self) {
        let children: &mut Vec<Node> = &mut self.children;
        for mut child in children {
            child.parent = ptr::null_mut();
        }
    }
}

unsafe impl Sync for Node {}
unsafe impl Send for Node {}

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

    /// Nodes can have children added to them
    #[test]
    fn new_child() {
        let mut root = Node::new(Container::Root);
        root.new_child(Container::Root);
        root.new_child(Container::Root); // This is okay
        {
            let mut third_child = root.new_child(Container::Root);
            third_child.new_child(Container::Root);
            //root.new_child(Root); // Have to wait for 3rd child to drop
        }
        root.new_child(Container::Root); // Now this works
        assert_eq!(root.children.len(), 4);
    }

    #[test]
    fn has_get_parent() {
        let mut root = Node::new(Container::Root);
        assert!(!root.has_parent(), "Root has a parent");
        assert_eq!(root.get_parent(), None);

        let child = root.new_child(Container::Root);
        assert!(child.has_parent(), "Child does not have parent");
        assert!(child.get_parent().is_some(), "Child does not have parent");
        let parent = child.get_parent().expect("Asserted child has parent");
        assert_eq!(parent.get_container_type(), ContainerType::Root);
    }

    #[test]
    fn get_container_type() {
        let mut root = Node::new(Container::Root);
        assert_eq!(root.get_container_type(), ContainerType::Root);
        {
            let wksp = root.new_child(
                Container::Workspace { name: "Foo".to_string(),
                                       focused: false });
            assert_eq!(wksp.get_container_type(), ContainerType::Workspace);
        }
        {
            let container = root.new_child(Container::Container {
                layout: Layout::Horizontal, visible: false,
                floating: false, focused: false
            });
            assert_eq!(container.get_container_type(), ContainerType::Container);
        }
    }

    #[test]
    fn get_children() {
        // Create a root with 3 children. The 3rd child has 2 children.
        let mut root = Node::new(Container::Root);
        root.new_child(Container::Root);
        root.new_child(Container::Root);
        {
            let third_child = root.new_child(Container::Root);
            third_child.new_child(Container::Root);
            third_child.new_child(Container::Root);
        }
        let root_children = root.get_children();
        assert!(!root_children.is_empty(), "Root has children");
        assert_eq!(root_children.len(), 3);
        assert!(root_children.last().is_some(), "Root has final child");
        let third_child = root_children.last().expect("Asserted unwrap!");
        assert_eq!(third_child.get_children().len(), 2);
        let third_child_second_child = third_child.get_children().last()
            .expect("Asserted unwrap!");
        assert!(third_child_second_child.get_children().is_empty(),
                "Grandchild doesn't have children");
    }

    #[test]
    fn get_children_mut() {
        // Start out with one child, use get_mut_children to add grandchild.
        let mut root = Node::new(Container::Root);
        root.new_child(Container::Root);

        assert!(root.get_children().last().expect("Root has child")
                .get_children().is_empty(), "Root has no grandchildren");

        {
            let mut children = root.get_children_mut();
            assert_eq!(children.len(), 1);

            let mut child = &mut children[0];
            child.new_child(Container::Root);
        }

        assert_eq!(root.get_children().last().expect("Asserted unwrap!")
                .get_children().len(), 1);
    }

    #[test]
    fn remove_child_at() {
        let mut root = Node::new(Container::Root);
        root.new_child(Container::Root);
        root.new_child(Container::Workspace {
            name: "Foo".to_string(), focused: false
        });
        root.new_child(Container::Root);

        let worksp = root.remove_child_at(1).expect("Index should be valid");
        assert_eq!(worksp.get_container_type(), ContainerType::Workspace);
        assert_eq!(root.get_children().len(), 2)
    }
}
<|endoftext|>


<commit_before>/**
A macro for declaring lazily evaluated statics.
Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.

Forked from https://github.com/rust-lang-nursery/lazy-static.rs

This version uses atomics instead of `std::sync::Once`, so it works also for `#![no_std]` builds.
It requires a nightly Rust version.

# Syntax
```text
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```
Metadata (such as doc comments) is allowed on each ref.
# Semantic
For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)
On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.
Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.
# Example
Using the macro:

```rust
#![feature(const_fn, core_intrinsics)]

#[macro_use]
extern crate once;
use std::collections::HashMap;
lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}
fn times_two(n: u32) -> u32 { n * 2 }
fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```
# Implementation details
The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access.
**/
#[macro_export]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(MAKE TY, $VIS, $(#[$attr])*, $N);
        impl $crate::__core::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                #[inline(always)]
                fn __static_ref_initialize() -> $T { $e }

                unsafe {
                    use $crate::__core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

                    #[inline(always)]
                    fn require_sync<T: Sync>(_: &T) { }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        use $crate::__core::cell::UnsafeCell;

                        struct SyncCell(UnsafeCell<Option<$T>>);
                        unsafe impl Sync for SyncCell {}

                        static DATA: SyncCell = SyncCell(UnsafeCell::new(None));
                        static INITIALIZED: AtomicUsize = ATOMIC_USIZE_INIT;

                        if INITIALIZED.load(Ordering::Relaxed) != 2 {
                            // not initialized yet

                            // set state to `initializing`
                            match INITIALIZED.compare_and_swap(0, 1, Ordering::Relaxed) {
                                0 => {
                                    // initialize
                                    *DATA.0.get() = Some(__static_ref_initialize());
                                    // set state to `initialized`
                                    INITIALIZED.store(2, Ordering::Relaxed);
                                },
                                1 => {
                                    // currently initializing in another thread, keep spinning
                                    while INITIALIZED.load(Ordering::Relaxed) != 2 {}
                                },
                                2 => {}, // now it's initialized
                                _ => $crate::__core::intrinsics::unreachable(),
                            }
                        }

                        match *DATA.0.get() {
                            Some(ref x) => x,
                            None => $crate::__core::intrinsics::unreachable(),
                        }
                    }

                    let static_ref = __stability();
                    require_sync(static_ref);
                    static_ref
                }
            }
        }
        lazy_static!($($t)*);
    };
    (MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<commit_msg>Use unreachable macro instead of intrinsic<commit_after>/**
A macro for declaring lazily evaluated statics.
Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.

Forked from https://github.com/rust-lang-nursery/lazy-static.rs

This version uses atomics instead of `std::sync::Once`, so it works also for `#![no_std]` builds.
It requires a nightly Rust version.

# Syntax
```text
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```
Metadata (such as doc comments) is allowed on each ref.
# Semantic
For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)
On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.
Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.
# Example
Using the macro:

```rust
#![feature(const_fn, core_intrinsics)]

#[macro_use]
extern crate once;
use std::collections::HashMap;
lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}
fn times_two(n: u32) -> u32 { n * 2 }
fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```
# Implementation details
The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access.
**/
#[macro_export]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(MAKE TY, $VIS, $(#[$attr])*, $N);
        impl $crate::__core::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                #[inline(always)]
                fn __static_ref_initialize() -> $T { $e }

                unsafe {
                    use $crate::__core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

                    #[inline(always)]
                    fn require_sync<T: Sync>(_: &T) { }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        use $crate::__core::cell::UnsafeCell;

                        struct SyncCell(UnsafeCell<Option<$T>>);
                        unsafe impl Sync for SyncCell {}

                        static DATA: SyncCell = SyncCell(UnsafeCell::new(None));
                        static INITIALIZED: AtomicUsize = ATOMIC_USIZE_INIT;

                        if INITIALIZED.load(Ordering::Relaxed) != 2 {
                            // not initialized yet

                            // set state to `initializing`
                            match INITIALIZED.compare_and_swap(0, 1, Ordering::Relaxed) {
                                0 => {
                                    // initialize
                                    *DATA.0.get() = Some(__static_ref_initialize());
                                    // set state to `initialized`
                                    INITIALIZED.store(2, Ordering::Relaxed);
                                },
                                1 => {
                                    // currently initializing in another thread, keep spinning
                                    while INITIALIZED.load(Ordering::Relaxed) != 2 {}
                                },
                                2 => {}, // now it's initialized
                                _ => unreachable!(),
                            }
                        }

                        match *DATA.0.get() {
                            Some(ref x) => x,
                            None => unreachable!(),
                        }
                    }

                    let static_ref = __stability();
                    require_sync(static_ref);
                    static_ref
                }
            }
        }
        lazy_static!($($t)*);
    };
    (MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
//! `Any` itself can be used to get a `TypeId`, and has more features when used
//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
//! `downcast_ref` methods, to test if the contained value is of a given type,
//! and to get a reference to the inner value as a type. As `&mut Any`, there
//! is also the `downcast_mut` method, for getting a mutable reference to the
//! inner value. `Box<Any>` adds the `downcast` method, which attempts to
//! convert to a `Box<T>`. See the [`Box`] documentation for the full details.
//!
//! Note that &Any is limited to testing whether a value is of a specified
//! concrete type, and cannot be used to test whether a type implements a trait.
//!
//! [`Box`]: ../../std/boxed/struct.Box.html
//!
//! # Examples
//!
//! Consider a situation where we want to log out a value passed to a function.
//! We know the value we're working on implements Debug, but we don't know its
//! concrete type.  We want to give special treatment to certain types: in this
//! case printing out the length of String values prior to their value.
//! We don't know the concrete type of our value at compile time, so we need to
//! use runtime reflection instead.
//!
//! ```rust
//! use std::fmt::Debug;
//! use std::any::Any;
//!
//! // Logger function for any type that implements Debug.
//! fn log<T: Any + Debug>(value: &T) {
//!     let value_any = value as &Any;
//!
//!     // try to convert our value to a String.  If successful, we want to
//!     // output the String's length as well as its value.  If not, it's a
//!     // different type: just print it out unadorned.
//!     match value_any.downcast_ref::<String>() {
//!         Some(as_string) => {
//!             println!("String ({}): {}", as_string.len(), as_string);
//!         }
//!         None => {
//!             println!("{:?}", value);
//!         }
//!     }
//! }
//!
//! // This function wants to log its parameter out prior to doing work with it.
//! fn do_work<T: Any + Debug>(value: &T) {
//!     log(value);
//!     // ...do some other work
//! }
//!
//! fn main() {
//!     let my_string = "Hello World".to_string();
//!     do_work(&my_string);
//!
//!     let my_i8: i8 = 100;
//!     do_work(&my_i8);
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use fmt;
use intrinsics;

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// A type to emulate dynamic typing.
///
/// Most types implement `Any`. However, any type which contains a non-`'static` reference does not.
/// See the [module-level documentation][mod] for more details.
///
/// [mod]: index.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Any: 'static {
    /// Gets the `TypeId` of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(get_type_id)]
    ///
    /// use std::any::{Any, TypeId};
    ///
    /// fn is_string(s: &Any) -> bool {
    ///     TypeId::of::<String>() == s.get_type_id()
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(is_string(&0), false);
    ///     assert_eq!(is_string(&"cookie monster".to_owned()), true);
    /// }
    /// ```
    #[unstable(feature = "get_type_id",
               reason = "this method will likely be replaced by an associated static",
               issue = "27745")]
    fn get_type_id(&self) -> TypeId;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: 'static + ?Sized > Any for T {
    fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
///////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

// Ensure that the result of e.g. joining a thread can be printed and
// hence used with `unwrap`. May eventually no longer be needed if
// dispatch works with upcasting.
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any + Send {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

impl Any {
    /// Returns true if the boxed type is the same as `T`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn is_string(s: &Any) {
    ///     if s.is::<String>() {
    ///         println!("It's a string!");
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     is_string(&0);
    ///     is_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn print_if_string(s: &Any) {
    ///     if let Some(string) = s.downcast_ref::<String>() {
    ///         println!("It's a string({}): '{}'", string.len(), string);
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     print_if_string(&0);
    ///     print_if_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        if self.is::<T>() {
            unsafe {
                Some(&*(self as *const Any as *const T))
            }
        } else {
            None
        }
    }

    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn modify_if_u32(s: &mut Any) {
    ///     if let Some(num) = s.downcast_mut::<u32>() {
    ///         *num = 42;
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let mut x = 10u32;
    ///     let mut s = "starlord".to_owned();
    ///
    ///     modify_if_u32(&mut x);
    ///     modify_if_u32(&mut s);
    ///
    ///     assert_eq!(x, 42);
    ///     assert_eq!(&s, "starlord");
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        if self.is::<T>() {
            unsafe {
                Some(&mut *(self as *mut Any as *mut T))
            }
        } else {
            None
        }
    }
}

impl Any+Send {
    /// Forwards to the method defined on the type `Any`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn is_string(s: &(Any + Send)) {
    ///     if s.is::<String>() {
    ///         println!("It's a string!");
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     is_string(&0);
    ///     is_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        Any::is::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn print_if_string(s: &(Any + Send)) {
    ///     if let Some(string) = s.downcast_ref::<String>() {
    ///         println!("It's a string({}): '{}'", string.len(), string);
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     print_if_string(&0);
    ///     print_if_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        Any::downcast_ref::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn modify_if_u32(s: &mut (Any+ Send)) {
    ///     if let Some(num) = s.downcast_mut::<u32>() {
    ///         *num = 42;
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let mut x = 10u32;
    ///     let mut s = "starlord".to_owned();
    ///
    ///     modify_if_u32(&mut x);
    ///     modify_if_u32(&mut s);
    ///
    ///     assert_eq!(x, 42);
    ///     assert_eq!(&s, "starlord");
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        Any::downcast_mut::<T>(self)
    }
}

///////////////////////////////////////////////////////////////////////////////
// TypeID and its methods
///////////////////////////////////////////////////////////////////////////////

/// A `TypeId` represents a globally unique identifier for a type.
///
/// Each `TypeId` is an opaque object which does not allow inspection of what's
/// inside but does allow basic operations such as cloning, comparison,
/// printing, and showing.
///
/// A `TypeId` is currently only available for types which ascribe to `'static`,
/// but this limitation may be removed in the future.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TypeId {
    t: u64,
}

impl TypeId {
    /// Returns the `TypeId` of the type this generic function has been
    /// instantiated with.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(get_type_id)]
    ///
    /// use std::any::{Any, TypeId};
    ///
    /// fn is_string(s: &Any) -> bool {
    ///     TypeId::of::<String>() == s.get_type_id()
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(is_string(&0), false);
    ///     assert_eq!(is_string(&"cookie monster".to_owned()), true);
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn of<T: ?Sized + 'static>() -> TypeId {
        TypeId {
            t: unsafe { intrinsics::type_id::<T>() },
        }
    }
}
<commit_msg>Add stable example to TypeId<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
//! `Any` itself can be used to get a `TypeId`, and has more features when used
//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
//! `downcast_ref` methods, to test if the contained value is of a given type,
//! and to get a reference to the inner value as a type. As `&mut Any`, there
//! is also the `downcast_mut` method, for getting a mutable reference to the
//! inner value. `Box<Any>` adds the `downcast` method, which attempts to
//! convert to a `Box<T>`. See the [`Box`] documentation for the full details.
//!
//! Note that &Any is limited to testing whether a value is of a specified
//! concrete type, and cannot be used to test whether a type implements a trait.
//!
//! [`Box`]: ../../std/boxed/struct.Box.html
//!
//! # Examples
//!
//! Consider a situation where we want to log out a value passed to a function.
//! We know the value we're working on implements Debug, but we don't know its
//! concrete type.  We want to give special treatment to certain types: in this
//! case printing out the length of String values prior to their value.
//! We don't know the concrete type of our value at compile time, so we need to
//! use runtime reflection instead.
//!
//! ```rust
//! use std::fmt::Debug;
//! use std::any::Any;
//!
//! // Logger function for any type that implements Debug.
//! fn log<T: Any + Debug>(value: &T) {
//!     let value_any = value as &Any;
//!
//!     // try to convert our value to a String.  If successful, we want to
//!     // output the String's length as well as its value.  If not, it's a
//!     // different type: just print it out unadorned.
//!     match value_any.downcast_ref::<String>() {
//!         Some(as_string) => {
//!             println!("String ({}): {}", as_string.len(), as_string);
//!         }
//!         None => {
//!             println!("{:?}", value);
//!         }
//!     }
//! }
//!
//! // This function wants to log its parameter out prior to doing work with it.
//! fn do_work<T: Any + Debug>(value: &T) {
//!     log(value);
//!     // ...do some other work
//! }
//!
//! fn main() {
//!     let my_string = "Hello World".to_string();
//!     do_work(&my_string);
//!
//!     let my_i8: i8 = 100;
//!     do_work(&my_i8);
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use fmt;
use intrinsics;

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// A type to emulate dynamic typing.
///
/// Most types implement `Any`. However, any type which contains a non-`'static` reference does not.
/// See the [module-level documentation][mod] for more details.
///
/// [mod]: index.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Any: 'static {
    /// Gets the `TypeId` of `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// #![feature(get_type_id)]
    ///
    /// use std::any::{Any, TypeId};
    ///
    /// fn is_string(s: &Any) -> bool {
    ///     TypeId::of::<String>() == s.get_type_id()
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(is_string(&0), false);
    ///     assert_eq!(is_string(&"cookie monster".to_owned()), true);
    /// }
    /// ```
    #[unstable(feature = "get_type_id",
               reason = "this method will likely be replaced by an associated static",
               issue = "27745")]
    fn get_type_id(&self) -> TypeId;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: 'static + ?Sized > Any for T {
    fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
///////////////////////////////////////////////////////////////////////////////

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

// Ensure that the result of e.g. joining a thread can be printed and
// hence used with `unwrap`. May eventually no longer be needed if
// dispatch works with upcasting.
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Any + Send {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Any")
    }
}

impl Any {
    /// Returns true if the boxed type is the same as `T`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn is_string(s: &Any) {
    ///     if s.is::<String>() {
    ///         println!("It's a string!");
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     is_string(&0);
    ///     is_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn print_if_string(s: &Any) {
    ///     if let Some(string) = s.downcast_ref::<String>() {
    ///         println!("It's a string({}): '{}'", string.len(), string);
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     print_if_string(&0);
    ///     print_if_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        if self.is::<T>() {
            unsafe {
                Some(&*(self as *const Any as *const T))
            }
        } else {
            None
        }
    }

    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn modify_if_u32(s: &mut Any) {
    ///     if let Some(num) = s.downcast_mut::<u32>() {
    ///         *num = 42;
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let mut x = 10u32;
    ///     let mut s = "starlord".to_owned();
    ///
    ///     modify_if_u32(&mut x);
    ///     modify_if_u32(&mut s);
    ///
    ///     assert_eq!(x, 42);
    ///     assert_eq!(&s, "starlord");
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        if self.is::<T>() {
            unsafe {
                Some(&mut *(self as *mut Any as *mut T))
            }
        } else {
            None
        }
    }
}

impl Any+Send {
    /// Forwards to the method defined on the type `Any`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn is_string(s: &(Any + Send)) {
    ///     if s.is::<String>() {
    ///         println!("It's a string!");
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     is_string(&0);
    ///     is_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn is<T: Any>(&self) -> bool {
        Any::is::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn print_if_string(s: &(Any + Send)) {
    ///     if let Some(string) = s.downcast_ref::<String>() {
    ///         println!("It's a string({}): '{}'", string.len(), string);
    ///     } else {
    ///         println!("Not a string...");
    ///     }
    /// }
    ///
    /// fn main() {
    ///     print_if_string(&0);
    ///     print_if_string(&"cookie monster".to_owned());
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
        Any::downcast_ref::<T>(self)
    }

    /// Forwards to the method defined on the type `Any`.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::Any;
    ///
    /// fn modify_if_u32(s: &mut (Any+ Send)) {
    ///     if let Some(num) = s.downcast_mut::<u32>() {
    ///         *num = 42;
    ///     }
    /// }
    ///
    /// fn main() {
    ///     let mut x = 10u32;
    ///     let mut s = "starlord".to_owned();
    ///
    ///     modify_if_u32(&mut x);
    ///     modify_if_u32(&mut s);
    ///
    ///     assert_eq!(x, 42);
    ///     assert_eq!(&s, "starlord");
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
        Any::downcast_mut::<T>(self)
    }
}

///////////////////////////////////////////////////////////////////////////////
// TypeID and its methods
///////////////////////////////////////////////////////////////////////////////

/// A `TypeId` represents a globally unique identifier for a type.
///
/// Each `TypeId` is an opaque object which does not allow inspection of what's
/// inside but does allow basic operations such as cloning, comparison,
/// printing, and showing.
///
/// A `TypeId` is currently only available for types which ascribe to `'static`,
/// but this limitation may be removed in the future.
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct TypeId {
    t: u64,
}

impl TypeId {
    /// Returns the `TypeId` of the type this generic function has been
    /// instantiated with.
    ///
    /// # Examples
    ///
    /// ```
    /// use std::any::{Any, TypeId};
    ///
    /// fn is_string<T: ?Sized + Any>(_s: &T) -> bool {
    ///     TypeId::of::<String>() == TypeId::of::<T>()
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(is_string(&0), false);
    ///     assert_eq!(is_string(&"cookie monster".to_owned()), true);
    /// }
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn of<T: ?Sized + 'static>() -> TypeId {
        TypeId {
            t: unsafe { intrinsics::type_id::<T>() },
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Terminal formatting library.
//!
//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
//! Terminal][ansi] to provide color printing, among other things. There are two implementations,
//! the `TerminfoTerminal`, which uses control characters from a
//! [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
//! API][win].
//!
//! ## Example
//!
//! ```no_run
//! extern crate term;
//!
//! fn main() {
//!     let mut t = term::stdout().unwrap();
//!
//!     t.fg(term::color::GREEN).unwrap();
//!     (write!(t, "hello, ")).unwrap();
//!
//!     t.fg(term::color::RED).unwrap();
//!     (writeln!(t, "world!")).unwrap();
//!
//!     t.reset().unwrap();
//! }
//! ```
//!
//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo

#![crate_name = "term"]
#![experimental]
#![comment = "Simple ANSI color library"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/master/",
       html_playground_url = "http://play.rust-lang.org/")]

#![allow(unknown_features)]
#![feature(macro_rules, phase, slicing_syntax)]

#![deny(missing_doc)]

#[phase(plugin, link)] extern crate log;

pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
pub use win::WinConsole;

use std::io::IoResult;

pub mod terminfo;

#[cfg(windows)]
mod win;

/// A hack to work around the fact that `Box<Writer + Send>` does not
/// currently implement `Writer`.
pub struct WriterWrapper {
    wrapped: Box<Writer + Send>,
}

impl Writer for WriterWrapper {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.wrapped.write(buf)
    }

    #[inline]
    fn flush(&mut self) -> IoResult<()> {
        self.wrapped.flush()
    }
}

#[cfg(not(windows))]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
    let ti: Option<TerminfoTerminal<WriterWrapper>>
        = Terminal::new(WriterWrapper {
            wrapped: box std::io::stdout() as Box<Writer + Send>,
        });
    ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
}

#[cfg(windows)]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
    let ti: Option<TerminfoTerminal<WriterWrapper>>
        = Terminal::new(WriterWrapper {
            wrapped: box std::io::stdout() as Box<Writer + Send>,
        });

    match ti {
        Some(t) => Some(box t as Box<Terminal<WriterWrapper> + Send>),
        None => {
            let wc: Option<WinConsole<WriterWrapper>>
                = Terminal::new(WriterWrapper {
                    wrapped: box std::io::stdout() as Box<Writer + Send>,
                });
            wc.map(|w| box w as Box<Terminal<WriterWrapper> + Send>)
        }
    }
}

#[cfg(not(windows))]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
    let ti: Option<TerminfoTerminal<WriterWrapper>>
        = Terminal::new(WriterWrapper {
            wrapped: box std::io::stderr() as Box<Writer + Send>,
        });
    ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
}

#[cfg(windows)]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
    let ti: Option<TerminfoTerminal<WriterWrapper>>
        = Terminal::new(WriterWrapper {
            wrapped: box std::io::stderr() as Box<Writer + Send>,
        });

    match ti {
        Some(t) => Some(box t as Box<Terminal<WriterWrapper> + Send>),
        None => {
            let wc: Option<WinConsole<WriterWrapper>>
                = Terminal::new(WriterWrapper {
                    wrapped: box std::io::stderr() as Box<Writer + Send>,
                });
            wc.map(|w| box w as Box<Terminal<WriterWrapper> + Send>)
        }
    }
}

/// Terminal color definitions
pub mod color {
    /// Number for a terminal color
    pub type Color = u16;

    pub static BLACK:   Color = 0u16;
    pub static RED:     Color = 1u16;
    pub static GREEN:   Color = 2u16;
    pub static YELLOW:  Color = 3u16;
    pub static BLUE:    Color = 4u16;
    pub static MAGENTA: Color = 5u16;
    pub static CYAN:    Color = 6u16;
    pub static WHITE:   Color = 7u16;

    pub static BRIGHT_BLACK:   Color = 8u16;
    pub static BRIGHT_RED:     Color = 9u16;
    pub static BRIGHT_GREEN:   Color = 10u16;
    pub static BRIGHT_YELLOW:  Color = 11u16;
    pub static BRIGHT_BLUE:    Color = 12u16;
    pub static BRIGHT_MAGENTA: Color = 13u16;
    pub static BRIGHT_CYAN:    Color = 14u16;
    pub static BRIGHT_WHITE:   Color = 15u16;
}

/// Terminal attributes
pub mod attr {
    /// Terminal attributes for use with term.attr().
    ///
    /// Most attributes can only be turned on and must be turned off with term.reset().
    /// The ones that can be turned off explicitly take a boolean value.
    /// Color is also represented as an attribute for convenience.
    pub enum Attr {
        /// Bold (or possibly bright) mode
        Bold,
        /// Dim mode, also called faint or half-bright. Often not supported
        Dim,
        /// Italics mode. Often not supported
        Italic(bool),
        /// Underline mode
        Underline(bool),
        /// Blink mode
        Blink,
        /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
        Standout(bool),
        /// Reverse mode, inverts the foreground and background colors
        Reverse,
        /// Secure mode, also called invis mode. Hides the printed text
        Secure,
        /// Convenience attribute to set the foreground color
        ForegroundColor(super::color::Color),
        /// Convenience attribute to set the background color
        BackgroundColor(super::color::Color)
    }
}

/// A terminal with similar capabilities to an ANSI Terminal
/// (foreground/background colors etc).
pub trait Terminal<T: Writer>: Writer {
    /// Returns `None` whenever the terminal cannot be created for some
    /// reason.
    fn new(out: T) -> Option<Self>;

    /// Sets the foreground color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn fg(&mut self, color: color::Color) -> IoResult<bool>;

    /// Sets the background color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn bg(&mut self, color: color::Color) -> IoResult<bool>;

    /// Sets the given terminal attribute, if supported.  Returns `Ok(true)`
    /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if
    /// there was an I/O error.
    fn attr(&mut self, attr: attr::Attr) -> IoResult<bool>;

    /// Returns whether the given terminal attribute is supported.
    fn supports_attr(&self, attr: attr::Attr) -> bool;

    /// Resets all terminal attributes and color to the default.
    /// Returns `Ok()`.
    fn reset(&mut self) -> IoResult<()>;

    /// Returns the contained stream, destroying the `Terminal`
    fn unwrap(self) -> T;

    /// Gets an immutable reference to the stream inside
    fn get_ref<'a>(&'a self) -> &'a T;

    /// Gets a mutable reference to the stream inside
    fn get_mut<'a>(&'a mut self) -> &'a mut T;
}
<commit_msg>term: Convert statics to constants<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Terminal formatting library.
//!
//! This crate provides the `Terminal` trait, which abstracts over an [ANSI
//! Terminal][ansi] to provide color printing, among other things. There are two implementations,
//! the `TerminfoTerminal`, which uses control characters from a
//! [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console
//! API][win].
//!
//! ## Example
//!
//! ```no_run
//! extern crate term;
//!
//! fn main() {
//!     let mut t = term::stdout().unwrap();
//!
//!     t.fg(term::color::GREEN).unwrap();
//!     (write!(t, "hello, ")).unwrap();
//!
//!     t.fg(term::color::RED).unwrap();
//!     (writeln!(t, "world!")).unwrap();
//!
//!     t.reset().unwrap();
//! }
//! ```
//!
//! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo

#![crate_name = "term"]
#![experimental]
#![comment = "Simple ANSI color library"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/master/",
       html_playground_url = "http://play.rust-lang.org/")]

#![allow(unknown_features)]
#![feature(macro_rules, phase, slicing_syntax)]

#![deny(missing_doc)]

#[phase(plugin, link)] extern crate log;

pub use terminfo::TerminfoTerminal;
#[cfg(windows)]
pub use win::WinConsole;

use std::io::IoResult;

pub mod terminfo;

#[cfg(windows)]
mod win;

/// A hack to work around the fact that `Box<Writer + Send>` does not
/// currently implement `Writer`.
pub struct WriterWrapper {
    wrapped: Box<Writer + Send>,
}

impl Writer for WriterWrapper {
    #[inline]
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        self.wrapped.write(buf)
    }

    #[inline]
    fn flush(&mut self) -> IoResult<()> {
        self.wrapped.flush()
    }
}

#[cfg(not(windows))]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
    let ti: Option<TerminfoTerminal<WriterWrapper>>
        = Terminal::new(WriterWrapper {
            wrapped: box std::io::stdout() as Box<Writer + Send>,
        });
    ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
}

#[cfg(windows)]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
    let ti: Option<TerminfoTerminal<WriterWrapper>>
        = Terminal::new(WriterWrapper {
            wrapped: box std::io::stdout() as Box<Writer + Send>,
        });

    match ti {
        Some(t) => Some(box t as Box<Terminal<WriterWrapper> + Send>),
        None => {
            let wc: Option<WinConsole<WriterWrapper>>
                = Terminal::new(WriterWrapper {
                    wrapped: box std::io::stdout() as Box<Writer + Send>,
                });
            wc.map(|w| box w as Box<Terminal<WriterWrapper> + Send>)
        }
    }
}

#[cfg(not(windows))]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
    let ti: Option<TerminfoTerminal<WriterWrapper>>
        = Terminal::new(WriterWrapper {
            wrapped: box std::io::stderr() as Box<Writer + Send>,
        });
    ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
}

#[cfg(windows)]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
    let ti: Option<TerminfoTerminal<WriterWrapper>>
        = Terminal::new(WriterWrapper {
            wrapped: box std::io::stderr() as Box<Writer + Send>,
        });

    match ti {
        Some(t) => Some(box t as Box<Terminal<WriterWrapper> + Send>),
        None => {
            let wc: Option<WinConsole<WriterWrapper>>
                = Terminal::new(WriterWrapper {
                    wrapped: box std::io::stderr() as Box<Writer + Send>,
                });
            wc.map(|w| box w as Box<Terminal<WriterWrapper> + Send>)
        }
    }
}

/// Terminal color definitions
pub mod color {
    /// Number for a terminal color
    pub type Color = u16;

    pub const BLACK:   Color = 0u16;
    pub const RED:     Color = 1u16;
    pub const GREEN:   Color = 2u16;
    pub const YELLOW:  Color = 3u16;
    pub const BLUE:    Color = 4u16;
    pub const MAGENTA: Color = 5u16;
    pub const CYAN:    Color = 6u16;
    pub const WHITE:   Color = 7u16;

    pub const BRIGHT_BLACK:   Color = 8u16;
    pub const BRIGHT_RED:     Color = 9u16;
    pub const BRIGHT_GREEN:   Color = 10u16;
    pub const BRIGHT_YELLOW:  Color = 11u16;
    pub const BRIGHT_BLUE:    Color = 12u16;
    pub const BRIGHT_MAGENTA: Color = 13u16;
    pub const BRIGHT_CYAN:    Color = 14u16;
    pub const BRIGHT_WHITE:   Color = 15u16;
}

/// Terminal attributes
pub mod attr {
    /// Terminal attributes for use with term.attr().
    ///
    /// Most attributes can only be turned on and must be turned off with term.reset().
    /// The ones that can be turned off explicitly take a boolean value.
    /// Color is also represented as an attribute for convenience.
    pub enum Attr {
        /// Bold (or possibly bright) mode
        Bold,
        /// Dim mode, also called faint or half-bright. Often not supported
        Dim,
        /// Italics mode. Often not supported
        Italic(bool),
        /// Underline mode
        Underline(bool),
        /// Blink mode
        Blink,
        /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold
        Standout(bool),
        /// Reverse mode, inverts the foreground and background colors
        Reverse,
        /// Secure mode, also called invis mode. Hides the printed text
        Secure,
        /// Convenience attribute to set the foreground color
        ForegroundColor(super::color::Color),
        /// Convenience attribute to set the background color
        BackgroundColor(super::color::Color)
    }
}

/// A terminal with similar capabilities to an ANSI Terminal
/// (foreground/background colors etc).
pub trait Terminal<T: Writer>: Writer {
    /// Returns `None` whenever the terminal cannot be created for some
    /// reason.
    fn new(out: T) -> Option<Self>;

    /// Sets the foreground color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn fg(&mut self, color: color::Color) -> IoResult<bool>;

    /// Sets the background color to the given color.
    ///
    /// If the color is a bright color, but the terminal only supports 8 colors,
    /// the corresponding normal color will be used instead.
    ///
    /// Returns `Ok(true)` if the color was set, `Ok(false)` otherwise, and `Err(e)`
    /// if there was an I/O error.
    fn bg(&mut self, color: color::Color) -> IoResult<bool>;

    /// Sets the given terminal attribute, if supported.  Returns `Ok(true)`
    /// if the attribute was supported, `Ok(false)` otherwise, and `Err(e)` if
    /// there was an I/O error.
    fn attr(&mut self, attr: attr::Attr) -> IoResult<bool>;

    /// Returns whether the given terminal attribute is supported.
    fn supports_attr(&self, attr: attr::Attr) -> bool;

    /// Resets all terminal attributes and color to the default.
    /// Returns `Ok()`.
    fn reset(&mut self) -> IoResult<()>;

    /// Returns the contained stream, destroying the `Terminal`
    fn unwrap(self) -> T;

    /// Gets an immutable reference to the stream inside
    fn get_ref<'a>(&'a self) -> &'a T;

    /// Gets a mutable reference to the stream inside
    fn get_mut<'a>(&'a mut self) -> &'a mut T;
}
<|endoftext|>


<commit_before>//! Line ending detection and conversion.

use std::fmt::Debug;

/// Supported line endings. Like in the Rust standard library, two line
/// endings are supported: `\r\n` and `\n`
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LineEnding {
    /// _Carriage return and line feed_ – a line ending sequence
    /// historically used in Windows. Corresponds to the sequence
    /// of ASCII control characters `0x0D 0x0A` or `\r\n`
    CRLF,
    /// _Line feed_ – a line ending historically used in Unix.
    ///  Corresponds to the ASCII control character `0x0A` or `\n`
    LF,
}

impl LineEnding {
    /// Turns this [`LineEnding`] value into its ASCII representation.
    #[inline]
    pub const fn as_str(&self) -> &'static str {
        match self {
            Self::CRLF => "\r\n",
            Self::LF => "\n",
        }
    }
}

/// An iterator over the lines of a string, as tuples of string slice
/// and [`LineEnding`] value; it only emits non-empty lines (i.e. having
/// some content before the terminating `\r\n` or `\n`).
///
/// This struct is used internally by the library.
#[derive(Debug, Clone, Copy)]
pub(crate) struct NonEmptyLines<'a>(pub &'a str);

impl<'a> Iterator for NonEmptyLines<'a> {
    type Item = (&'a str, Option<LineEnding>);

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(lf) = self.0.find('\n') {
            if lf == 0 || (lf == 1 && self.0.as_bytes()[lf - 1] == b'\r') {
                self.0 = &self.0[(lf + 1)..];
                continue;
            }
            let trimmed = match self.0.as_bytes()[lf - 1] {
                b'\r' => (&self.0[..(lf - 1)], Some(LineEnding::CRLF)),
                _ => (&self.0[..lf], Some(LineEnding::LF)),
            };
            self.0 = &self.0[(lf + 1)..];
            return Some(trimmed);
        }
        if self.0.len() > 0 {
            let result = Some((self.0, None));
            self.0 = "";
            return result;
        } else {
            return None;
        }
    }
}

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

    #[test]
    fn non_empty_lines_full_case() {
        assert_eq!(
            NonEmptyLines("LF\nCRLF\r\n\r\n\nunterminated")
                .collect::<Vec<(&str, Option<LineEnding>)>>(),
            vec![
                ("LF", Some(LineEnding::LF)),
                ("CRLF", Some(LineEnding::CRLF)),
                ("unterminated", None),
            ]
        );
    }

    #[test]
    fn non_empty_lines_new_lines_only() {
        assert_eq!(NonEmptyLines("\r\n\n\n\r\n").next(), None);
    }

    #[test]
    fn non_empty_lines_no_input() {
        assert_eq!(NonEmptyLines("").next(), None);
    }
}
<commit_msg>Implement small recommendations from Clippy<commit_after>//! Line ending detection and conversion.

use std::fmt::Debug;

/// Supported line endings. Like in the Rust standard library, two line
/// endings are supported: `\r\n` and `\n`
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LineEnding {
    /// _Carriage return and line feed_ – a line ending sequence
    /// historically used in Windows. Corresponds to the sequence
    /// of ASCII control characters `0x0D 0x0A` or `\r\n`
    CRLF,
    /// _Line feed_ – a line ending historically used in Unix.
    ///  Corresponds to the ASCII control character `0x0A` or `\n`
    LF,
}

impl LineEnding {
    /// Turns this [`LineEnding`] value into its ASCII representation.
    #[inline]
    pub const fn as_str(&self) -> &'static str {
        match self {
            Self::CRLF => "\r\n",
            Self::LF => "\n",
        }
    }
}

/// An iterator over the lines of a string, as tuples of string slice
/// and [`LineEnding`] value; it only emits non-empty lines (i.e. having
/// some content before the terminating `\r\n` or `\n`).
///
/// This struct is used internally by the library.
#[derive(Debug, Clone, Copy)]
pub(crate) struct NonEmptyLines<'a>(pub &'a str);

impl<'a> Iterator for NonEmptyLines<'a> {
    type Item = (&'a str, Option<LineEnding>);

    fn next(&mut self) -> Option<Self::Item> {
        while let Some(lf) = self.0.find('\n') {
            if lf == 0 || (lf == 1 && self.0.as_bytes()[lf - 1] == b'\r') {
                self.0 = &self.0[(lf + 1)..];
                continue;
            }
            let trimmed = match self.0.as_bytes()[lf - 1] {
                b'\r' => (&self.0[..(lf - 1)], Some(LineEnding::CRLF)),
                _ => (&self.0[..lf], Some(LineEnding::LF)),
            };
            self.0 = &self.0[(lf + 1)..];
            return Some(trimmed);
        }
        if self.0.is_empty() {
            None
        } else {
            let line = std::mem::take(&mut self.0);
            Some((line, None))
        }
    }
}

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

    #[test]
    fn non_empty_lines_full_case() {
        assert_eq!(
            NonEmptyLines("LF\nCRLF\r\n\r\n\nunterminated")
                .collect::<Vec<(&str, Option<LineEnding>)>>(),
            vec![
                ("LF", Some(LineEnding::LF)),
                ("CRLF", Some(LineEnding::CRLF)),
                ("unterminated", None),
            ]
        );
    }

    #[test]
    fn non_empty_lines_new_lines_only() {
        assert_eq!(NonEmptyLines("\r\n\n\n\r\n").next(), None);
    }

    #[test]
    fn non_empty_lines_no_input() {
        assert_eq!(NonEmptyLines("").next(), None);
    }
}
<|endoftext|>


<commit_before>use rustc_serialize::json::{Json,Array};

pub fn path<'a>(json: &'a Json, path: &str) -> &'a Json {
    let parts = path.split(".");
    let mut cur = json;
    for p in parts {
        cur = cur.as_object().unwrap().get(p).unwrap();
    }
    cur
}

pub fn array<'a>(json: &'a Json, path: &str) -> &'a Array {
    self::path(json, path).as_array().unwrap()
}

pub fn string<'a>(json: &'a Json, path: &str) -> &'a str{
    self::path(json, path).as_string().unwrap()
}
<commit_msg>matrix: json: provide more useful errors with bad paths<commit_after>use rustc_serialize::json::{Json,Array};

pub fn path<'a>(json: &'a Json, path: &str) -> &'a Json {
    let parts = path.split(".");
    let mut cur = json;
    for p in parts {
        cur = match cur.as_object().unwrap().get(p) {
            Some(c) => c,
            None => panic!("Could not find {} in {:?} (lost at {})", path, json, p)
        }
    }
    cur
}

pub fn array<'a>(json: &'a Json, path: &str) -> &'a Array {
    match self::path(json, path).as_array() {
        Some(p) => p,
        None => panic!("{} in {:?} is not an array", path, json)
    }
}

pub fn string<'a>(json: &'a Json, path: &str) -> &'a str{
    match self::path(json, path).as_string() {
        Some(p) => p,
        None => panic!("{} in {:?} is not an array", path, json)
    }
}
<|endoftext|>