<commit_before>//! An rope.
//!
//! A rope is an efficient data structure for large mutable strings. It's
//! essentially a binary tree whose leaves are strings.
//!
//! For more information, see the following resources:
//! + http://scienceblogs.com/goodmath/2009/01/26/ropes-twining-together-strings/
//! + https://www.ibm.com/developerworks/library/j-ropes/
//! + http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.14.9450&rep=rep1&type=pdf

#![feature(const_fn)]
#![feature(box_syntax, box_patterns)]

use std::cmp;
use std::ops;
use std::convert;

#[derive(Debug)]
pub struct Rope<T> {
    // can we get away with having these be of &str or will they need
    // to be string?
    root: Node<T>
}

use self::Node::*;

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a vector of `T`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Debug)]
enum Node<T> {
    /// A leaf node
    Leaf(Vec<T>)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch {
        /// The length of this node
        len: usize
      , /// The weight of a node is the summed weight of its left subtree
        weight: usize
      , /// The left branch node
        left: Option<Box<Node<T>>>
      , /// The right branch node
        right: Option<Box<Node<T>>>
    }
}

impl<T> Node<T> {
    const fn none() -> Self {
        Branch { len: 0
               , weight: 0
               , left: None
               , right: None
               }
    }

    /// Concatenate two `Node`s to return a new `Branch` node.
    fn branch(left: Self, right: Self) -> Self {
        Branch { len: left.len() + right.len()
               , weight: left.weight()
               , left: Some(box left)
               , right: Some(box right)
        }
    }

    #[inline]
    fn leaf(data: Vec<T>) -> Self {
        Leaf(data)
    }

    /// Returns true if this node is balanced
    #[inline]
    fn is_balanced(&self) -> bool {
        unimplemented!()
    }

    /// Returns the height in the tree of a node
    #[inline]
    fn height(&self) -> usize {
        use std::cmp::max;

        match self {
            &Node::Leaf(_) => 1
          , &Node::Branch { ref left, ref right, ..} =>
                max( left.as_ref().map(Box::as_ref).map_or(0, Node::height)
                   , right.as_ref().map(Box::as_ref).map_or(0, Node::height)
                   ) + 1
            }
    }

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    fn len(&self) -> usize {
        match self { &Node::Leaf(ref v) => v.len()
                   , &Node::Branch { ref left, ref right, .. } =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::len) +
                        right.as_ref().map(Box::as_ref).map_or(0, Node::len)
                    }
    }

    /// Returns the weight of a node
    fn weight (&self) -> usize {
        match self { &Node::Leaf(ref v) => v.len()
                   , &Node::Branch { ref left, .. } =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::weight)
                    }
    }
}

impl<T> ops::Add for Node<T> {
    type Output = Self;
    /// Concatenate two `Node`s, returning a `Branch` node.
    fn add(self, right: Self) -> Self { Node::branch(self, right) }
}

impl<T> Rope<T> {

    /// Returns a new empty Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::<u8>::new();
    /// assert_eq!(an_rope.len(), 0);
    /// ```
    pub const fn new() -> Rope<T> {
        Rope { root: Node::<T>::none() }
    }

    /// Returns the length of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::new();
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::from(String::from(""));
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("a string"));
    /// assert_eq!(an_rope.len(), "a string".len());
    /// ```
    pub fn len(&self) -> usize {
        // self.root.len()
        unimplemented!()
    }

    /// Appends a `Rope` to the end of this `Rope`, returning a new `Rope`
    ///
    /// Note that this is equivalent to using the `+` operator.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let an_rope = Rope::from(String::from("abcd"));
    /// let another_rope = an_rope.merge(Rope::from(String::from("efgh")))
    /// assert_eq!(another_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn merge(&self, other: &Rope<T>) -> Rope<T> {
        unimplemented!()
    }

    /// Appends a `Rope` to the end of this `Rope`, updating it in place.
    ///
    /// Note that this is equivalent to using the `+=` operator.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// an_rope.update(Rope::from(String::from("efgh")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn update(&mut self, other: Rope<T>) {
        unimplemented!()
    }

    /// Splits the rope into two ropes at the given index.
    ///
    /// Consumes this rope.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// let (ab, cd) = an_rope.split(2);
    /// assert_eq!(ab, Rope::from(String::from("ab")));
    /// assert_eq!(cd, Rope::from(String::from("cd")));
    /// ```
    pub fn split(self, index: usize) -> (Rope<T>, Rope<T>) {
        unimplemented!()
    }

    /// Rebalances this entire `Rope`, returning a balanced `Rope`.
    fn rebalance(self) -> Self {
        if self.is_balanced() {
            // the rope is already balanced, do nothing
            self
        } else {
            // rebalance the rope
            unimplemented!()
        }
    }

    /// Returns true if this `Rope` is balanced.
    #[inline]
    fn is_balanced(&self) -> bool {
        self.root.is_balanced()
    }
}

impl<T> ops::Index<usize> for Node<T> {
    type Output = T;

    fn index(&self, i: usize) -> &T {
        // let len = self.len();
        // match self { &Node::Leaf(ref vec) => { &vec[i] }
        //             , &Node::Branch { right: Some(box ref r), .. } if len < i =>
        //                 &r[i - len]
        //             , &Node::Branch { left: Some(box ref l), .. } => &l[i]
        //             , &Node::Branch { left: None, right: None, .. } =>
        //                 panic!("Index out of bounds!")
        //             }
        unimplemented!()
    }
}

impl<T> convert::Into<Vec<T>> for Rope<T> {
    fn into(self) -> Vec<T> {
        unimplemented!()
    }

}

impl convert::From<String> for Rope<u8> {
    fn from(string: String) -> Rope<u8> {
        Rope {
            root: if string.len() == 0 { Node::none() }
                  else { Node::Leaf(string.into_bytes()) }
        }
    }
}

//-- comparisons ----------------------------------------------------
impl<T> cmp::PartialEq for Rope<T> {
    fn eq(&self, other: &Rope<T>) -> bool {
        unimplemented!()
    }
}

impl<T> cmp::PartialEq<str> for Rope<T> {
    fn eq(&self, other: &str) -> bool {
        unimplemented!()
    }
}

//-- concatenation --------------------------------------------------
impl<'a, T> ops::Add for &'a Rope<T> {
    type Output = Rope<T>;
    /// Non-destructively concatenate two `Rope`s, returning a new `Rope`.
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( &rope + &Rope::from(String::from("cd"))
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: Self) -> Rope<T> { self.merge(other) }

}

impl<T> ops::Add for Rope<T> {
    type Output = Rope<T>;
    /// Non-destructively concatenate two `Rope`s, returning a new `Rope`.
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( rope + Rope::from(String::from("cd"))
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: Self) -> Rope<T> { self.merge(&other) }
}

impl ops::Add<String> for Rope<u8> {
    type Output = Rope<u8>;
    /// Non-destructively concatenate a `Rope` and a `String`.
    ///
    /// Returns a new `Rope`
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( rope + String::from("cd"))
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: String) -> Rope<u8> {
         self.merge(&Rope::from(other))
    }
}

impl<'a, 'b> ops::Add<&'b str> for &'a Rope<u8> {
    type Output = Rope<u8>;
    /// Non-destructively concatenate a `Rope` and an `&str`.
    ///
    /// Returns a new `Rope`
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( &rope + "cd")
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: &'b str) -> Rope<u8> {
         self.merge(&Rope::from(other.to_owned()))
     }

}

impl<'a> ops::Add<&'a str> for Rope<u8> {
    type Output = Rope<u8>;
    /// Non-destructively concatenate a `Rope` and an `&str`.
    ///
    /// Returns a new `Rope`
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( rope + "cd")
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: &'a str) -> Rope<u8> {
         self.merge(&Rope::from(other.to_owned()))
     }

}

impl<T> ops::AddAssign for Rope<T> {

    /// Concatenate two `Rope`s mutably.
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += Rope::from(String::from("cd"));
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, other: Rope<T>) {
        self.update(other)
    }
}

impl ops::AddAssign<String> for Rope<u8> {

    /// Concatenate a `String` onto a `Rope` mutably.
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, string: String) {
        self.update(Rope::from(string))
    }
}

impl<'a> ops::AddAssign<&'a str> for Rope<u8> {

    /// Concatenate an `&str` onto a `Rope` mutably.
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, string: &'a str) {
        self.update(Rope::from(string.to_owned()))
    }
}

impl<T> ops::Index<usize> for Rope<T> {
    type Output = T;

    /// Recursively index the Rope to return the `i` th character.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let an_rope = Rope::from(String::from("abcd"));
    /// assert_eq!(&an_rope[0], "a");
    /// assert_eq!(&an_rope[1], "b");
    /// assert_eq!(&an_rope[2], "c");
    /// assert_eq!(&an_rope[3], "d");
    /// ```
    ///
    /// # Time complexity
    /// _O_(log _n_)
    ///
    #[inline]
    fn index(&self, i: usize) -> &T {
        &self.root[i]
    }
}

//-- slicing operators ----------------------------------------------
impl<T> ops::Index<ops::Range<usize>> for Rope<T> {
    type Output = [T];

    // Index a substring
    fn index(&self, i: ops::Range<usize>) -> &[T] {
        unimplemented!()
    }
}

impl<T> ops::Index<ops::RangeTo<usize>> for Rope<T> {
    type Output = [T];

    fn index(&self, i: ops::RangeTo<usize>) -> &[T] {
        unimplemented!()
    }
}

impl<T> ops::Index<ops::RangeFrom<usize>> for Rope<T> {
    type Output = [T];

    fn index(&self, i: ops::RangeFrom<usize>) -> &[T] {
        unimplemented!()
    }
}

impl<T> ops::IndexMut<ops::Range<usize>> for Rope<T> {
    fn index_mut(&mut self, i: ops::Range<usize>) -> &mut [T] {
        unimplemented!()
    }
}

impl<T> ops::IndexMut<ops::RangeTo<usize>> for Rope<T> {
    fn index_mut(&mut self, i: ops::RangeTo<usize>) -> &mut [T] {
        unimplemented!()
    }
}

impl<T> ops::IndexMut<ops::RangeFrom<usize>> for Rope<T> {
    fn index_mut(&mut self, i: ops::RangeFrom<usize>) -> &mut [T] {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>rope: remove genericity from Rope again<commit_after>//! An rope.
//!
//! A rope is an efficient data structure for large mutable strings. It's
//! essentially a binary tree whose leaves are strings.
//!
//! For more information, see the following resources:
//! + http://scienceblogs.com/goodmath/2009/01/26/ropes-twining-together-strings/
//! + https://www.ibm.com/developerworks/library/j-ropes/
//! + http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.14.9450&rep=rep1&type=pdf

#![feature(const_fn)]
#![feature(box_syntax, box_patterns)]

use std::cmp;
use std::ops;
use std::convert;

#[derive(Debug)]
pub struct Rope {
    // can we get away with having these be of &str or will they need
    // to be string?
    root: Node
}

use self::Node::*;

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a `String`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Debug)]
enum Node {
    /// A leaf node
    Leaf(String)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch {
        /// The length of this node
        len: usize
      , /// The weight of a node is the summed weight of its left subtree
        weight: usize
      , /// The left branch node
        left: Option<Box<Node>>
      , /// The right branch node
        right: Option<Box<Node>>
    }
}

impl Node {
    const fn none() -> Self {
        Branch { len: 0
               , weight: 0
               , left: None
               , right: None
               }
    }

    /// Concatenate two `Node`s to return a new `Branch` node.
    fn branch(left: Self, right: Self) -> Self {
        Branch { len: left.len() + right.len()
               , weight: left.weight()
               , left: Some(box left)
               , right: Some(box right)
        }
    }

    #[inline]
    fn leaf(string: String) -> Self {
        Leaf(string)
    }

    /// Returns true if this node is balanced
    #[inline]
    fn is_balanced(&self) -> bool {
        unimplemented!()
    }

    /// Returns the height in the tree of a node
    #[inline]
    fn height(&self) -> usize {
        use std::cmp::max;

        match self {
            &Node::Leaf(_) => 1
          , &Node::Branch { ref left, ref right, ..} =>
                max( left.as_ref().map(Box::as_ref).map_or(0, Node::height)
                   , right.as_ref().map(Box::as_ref).map_or(0, Node::height)
                   ) + 1
            }
    }

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    fn len(&self) -> usize {
        match self { &Node::Leaf(ref s) => s.len()
                   , &Node::Branch { ref left, ref right, .. } =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::len) +
                        right.as_ref().map(Box::as_ref).map_or(0, Node::len)
                    }
    }

    /// Returns the weight of a node
    fn weight (&self) -> usize {
        match self { &Node::Leaf(ref s) => s.len()
                   , &Node::Branch { ref left, .. } =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::weight)
                    }
    }
}

impl ops::Add for Node {
    type Output = Self;
    /// Concatenate two `Node`s, returning a `Branch` node.
    fn add(self, right: Self) -> Self { Node::branch(self, right) }
}

impl Rope {

    /// Returns a new empty Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::<u8>::new();
    /// assert_eq!(an_rope.len(), 0);
    /// ```
    pub const fn new() -> Rope {
        Rope { root: Node::none() }
    }

    /// Returns the length of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::new();
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::from(String::from(""));
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("a string"));
    /// assert_eq!(an_rope.len(), "a string".len());
    /// ```
    pub fn len(&self) -> usize {
        // self.root.len()
        unimplemented!()
    }

    /// Appends a `Rope` to the end of this `Rope`, returning a new `Rope`
    ///
    /// Note that this is equivalent to using the `+` operator.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let an_rope = Rope::from(String::from("abcd"));
    /// let another_rope = an_rope.merge(Rope::from(String::from("efgh")))
    /// assert_eq!(another_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn merge(&self, other: &Rope) -> Rope {
        unimplemented!()
    }

    /// Appends a `Rope` to the end of this `Rope`, updating it in place.
    ///
    /// Note that this is equivalent to using the `+=` operator.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// an_rope.update(Rope::from(String::from("efgh")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn update(&mut self, other: Rope) {
        unimplemented!()
    }

    /// Splits the rope into two ropes at the given index.
    ///
    /// Consumes this rope.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// let (ab, cd) = an_rope.split(2);
    /// assert_eq!(ab, Rope::from(String::from("ab")));
    /// assert_eq!(cd, Rope::from(String::from("cd")));
    /// ```
    pub fn split(self, index: usize) -> (Rope, Rope) {
        unimplemented!()
    }

    /// Rebalances this entire `Rope`, returning a balanced `Rope`.
    fn rebalance(self) -> Self {
        if self.is_balanced() {
            // the rope is already balanced, do nothing
            self
        } else {
            // rebalance the rope
            unimplemented!()
        }
    }

    /// Returns true if this `Rope` is balanced.
    ///
    /// Balancing invariant:
    /// the rope length needs to be less than _F_(rope_length) where F is fibonacci
    #[inline]
    fn is_balanced(&self) -> bool {
        self.root.is_balanced()
    }
}

impl ops::Index<usize> for Node {
    type Output = str;

    fn index(&self, i: usize) -> &str {
        let len = self.len();
        match *self { Node::Leaf(ref vec) => { &vec[i..i+1] }
                    , Node::Branch { right: Some(box ref r), .. } if len < i =>
                        &r[i - len]
                    , Node::Branch { left: Some(box ref l), .. } => &l[i]
                    , _ =>
                        panic!("Index out of bounds!")
                    }
    }
}

impl convert::Into<Vec<u8>> for Rope {
    fn into(self) -> Vec<u8> {
        unimplemented!()
    }

}

impl convert::From<String> for Rope {
    fn from(string: String) -> Rope {
        Rope {
            root: if string.len() == 0 { Node::none() }
                  else { Node::Leaf(string) }
        }
    }
}

//-- comparisons ----------------------------------------------------
impl cmp::PartialEq for Rope {
    fn eq(&self, other: &Rope) -> bool {
        unimplemented!()
    }
}

impl cmp::PartialEq<str> for Rope {
    fn eq(&self, other: &str) -> bool {
        unimplemented!()
    }
}

//-- concatenation --------------------------------------------------
impl<'a> ops::Add for &'a Rope {
    type Output = Rope;
    /// Non-destructively concatenate two `Rope`s, returning a new `Rope`.
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( &rope + &Rope::from(String::from("cd"))
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: Self) -> Rope { self.merge(other) }

}

impl ops::Add for Rope {
    type Output = Rope;
    /// Non-destructively concatenate two `Rope`s, returning a new `Rope`.
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( rope + Rope::from(String::from("cd"))
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: Self) -> Rope { self.merge(&other) }
}

impl ops::Add<String> for Rope {
    type Output = Rope;
    /// Non-destructively concatenate a `Rope` and a `String`.
    ///
    /// Returns a new `Rope`
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( rope + String::from("cd"))
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: String) -> Rope {
         self.merge(&Rope::from(other))
    }
}

impl<'a, 'b> ops::Add<&'b str> for &'a Rope {
    type Output = Rope;
    /// Non-destructively concatenate a `Rope` and an `&str`.
    ///
    /// Returns a new `Rope`
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( &rope + "cd")
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: &'b str) -> Rope {
         self.merge(&Rope::from(other.to_owned()))
     }

}

impl<'a> ops::Add<&'a str> for Rope {
    type Output = Rope;
    /// Non-destructively concatenate a `Rope` and an `&str`.
    ///
    /// Returns a new `Rope`
    ///
    /// # Examples
    /// ```
    /// let rope = Rope::from(String::from("ab"));
    /// assert_eq!( rope + "cd")
    ///           , Rope::from(String::from("abcd")));
    /// ```
    #[inline] fn add(self, other: &'a str) -> Rope {
         self.merge(&Rope::from(other.to_owned()))
     }

}

impl ops::AddAssign for Rope {

    /// Concatenate two `Rope`s mutably.
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += Rope::from(String::from("cd"));
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, other: Rope) {
        self.update(other)
    }
}

impl ops::AddAssign<String> for Rope {

    /// Concatenate a `String` onto a `Rope` mutably.
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, string: String) {
        self.update(Rope::from(string))
    }
}

impl<'a> ops::AddAssign<&'a str> for Rope {

    /// Concatenate an `&str` onto a `Rope` mutably.
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, string: &'a str) {
        self.update(Rope::from(string.to_owned()))
    }
}

impl ops::Index<usize> for Rope {
    type Output = str;

    /// Recursively index the Rope to return the `i` th character.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let an_rope = Rope::from(String::from("abcd"));
    /// assert_eq!(&an_rope[0], "a");
    /// assert_eq!(&an_rope[1], "b");
    /// assert_eq!(&an_rope[2], "c");
    /// assert_eq!(&an_rope[3], "d");
    /// ```
    ///
    /// # Time complexity
    /// _O_(log _n_)
    ///
    #[inline]
    fn index(&self, i: usize) -> &str {
        &self.root[i]
    }
}

//-- slicing operators ----------------------------------------------
impl ops::Index<ops::Range<usize>> for Rope {
    type Output = str;

    // Index a substring
    fn index(&self, i: ops::Range<usize>) -> &str {
        unimplemented!()
    }
}

impl ops::Index<ops::RangeTo<usize>> for Rope {
    type Output = str;

    fn index(&self, i: ops::RangeTo<usize>) -> &str {
        unimplemented!()
    }
}

impl ops::Index<ops::RangeFrom<usize>> for Rope {
    type Output = str;

    fn index(&self, i: ops::RangeFrom<usize>) -> &str {
        unimplemented!()
    }
}

impl ops::IndexMut<ops::Range<usize>> for Rope {
    fn index_mut(&mut self, i: ops::Range<usize>) -> &mut str {
        unimplemented!()
    }
}

impl ops::IndexMut<ops::RangeTo<usize>> for Rope {
    fn index_mut(&mut self, i: ops::RangeTo<usize>) -> &mut str {
        unimplemented!()
    }
}

impl ops::IndexMut<ops::RangeFrom<usize>> for Rope {
    fn index_mut(&mut self, i: ops::RangeFrom<usize>) -> &mut str {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


<commit_before>//! An rope.
//!
//! A rope is an efficient data structure for large mutable strings. It's
//! essentially a binary tree whose leaves are strings.
//!
//! For more information, see the following resources:
//! + http://scienceblogs.com/goodmath/2009/01/26/ropes-twining-together-strings/
//! + https://www.ibm.com/developerworks/library/j-ropes/
//! + http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.14.9450&rep=rep1&type=pdf

#![feature(const_fn)]
#![feature(box_syntax, box_patterns)]

use std::cmp;
use std::ops;
use std::convert;

#[derive(Debug)]
pub struct Rope<T> {
    // can we get away with having these be of &str or will they need
    // to be string?
    root: Node<T>
}

use self::Node::*;

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a vector of `T`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Debug)]
enum Node<T> {
    /// A leaf node
    Leaf(Vec<T>)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch {
        /// The length of this node
        len: usize
      , /// The weight of a node is the summed weight of its left subtree
        weight: usize
      , /// The left branch node
        left: Option<Box<Node<T>>>
      , /// The right branch node
        right: Option<Box<Node<T>>>
    }
}

impl<T> Node<T> {
    const fn none() -> Self {
        Branch { len: 0
               , weight: 0
               , left: None
               , right: None
               }
    }

    /// Concatenate two `Node`s to return a new `Branch` node.
    fn branch(left: Self, right: Self) -> Self {
        Branch { len: left.len() + right.len()
               , weight: left.weight()
               , left: Some(box left)
               , right: Some(box right)
        }
    }

    #[inline]
    fn leaf(data: Vec<T>) -> Self {
        Leaf(data)
    }

    /// Returns the height in the tree of a node
    #[inline]
    fn height(&self) -> usize {
        use std::cmp::max;

        match self {
            &Node::Leaf(_) => 1
          , &Node::Branch { ref left, ref right, ..} =>
                max( left.as_ref().map(Box::as_ref).map_or(0, Node::height)
                   , right.as_ref().map(Box::as_ref).map_or(0, Node::height)
                   ) + 1
            }
    }
}

impl<T> Rope<T> {

    /// Returns a new empty Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::<u8>::new();
    /// assert_eq!(an_rope.len(), 0);
    /// ```
    pub const fn new() -> Rope<T> {
        Rope { root: Node::<T>::none() }
    }

    /// Returns the length of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::new();
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::from(String::from(""));
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("a string"));
    /// assert_eq!(an_rope.len(), "a string".len());
    /// ```
    pub fn len(&self) -> usize {
        // self.root.len()
        unimplemented!()
    }

    /// Appends a rope to the end of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// an_rope.append(Rope::from(String::from("efgh")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn append(&mut self, other: Rope<T>) {
        unimplemented!()
    }

    /// Prepends a rope to the front of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("efgh"));
    /// an_rope.preend(Rope::from(String::from("abcd")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn prepend(&mut self, other: Rope<T>) {
        unimplemented!()
    }

    /// Splits the rope into two ropes at the given index.
    ///
    /// Consumes this rope.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// let (ab, cd) = an_rope.split(2);
    /// assert_eq!(ab, Rope::from(String::from("ab")));
    /// assert_eq!(cd, Rope::from(String::from("cd")));
    /// ```
    pub fn split(self, index: usize) -> (Rope<T>, Rope<T>) {
        unimplemented!()
    }
}

impl<T> ops::Index<usize> for Node<T> {
    type Output = T;

    fn index(&self, i: usize) -> &T {
        // let len = self.len();
        // match self { &Node::Leaf(ref vec) => { &vec[i] }
        //             , &Node::Branch { right: Some(box ref r), .. } if len < i =>
        //                 &r[i - len]
        //             , &Node::Branch { left: Some(box ref l), .. } => &l[i]
        //             , &Node::Branch { left: None, right: None, .. } =>
        //                 panic!("Index out of bounds!")
        //             }
        unimplemented!()
    }
}

impl<T> Node<T> {

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    fn len(&self) -> usize {
        match self { &Node::Leaf(ref v) => v.len()
                   , &Node::Branch { ref left, ref right, .. } =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::len) +
                        right.as_ref().map(Box::as_ref).map_or(0, Node::len)
                    }
    }

    /// Returns the weight of a node
    fn weight (&self) -> usize {
        match self { &Node::Leaf(ref v) => v.len()
                   , &Node::Branch { ref left, .. } =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::weight)
                    }
    }

}

impl<T> convert::Into<Vec<T>> for Rope<T> {
    fn into(self) -> Vec<T> {
        unimplemented!()
    }

}

impl convert::From<String> for Rope<u8> {
    fn from(string: String) -> Rope<u8> {
        Rope {
            root: if string.len() == 0 { Node::none() }
                  else { Node::Leaf(string.into_bytes()) }
        }
    }
}

//-- comparisons ----------------------------------------------------
impl<T> cmp::PartialEq for Rope<T> {
    fn eq(&self, other: &Rope<T>) -> bool {
        unimplemented!()
    }
}

impl<T> cmp::PartialEq<str> for Rope<T> {
    fn eq(&self, other: &str) -> bool {
        unimplemented!()
    }
}

//-- concatenation --------------------------------------------------
impl ops::AddAssign for Rope<u8> {

    /// Concatenate two `Rope`s.
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += Rope::from(String::from("cd"));
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, other: Rope<u8>) {
        self.append(other)
    }
}

impl ops::AddAssign<String> for Rope<u8> {

    /// Concatenate a `String` onto a `Rope`
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, string: String) {
        self.append(Rope::from(string))
    }
}

impl<'a> ops::AddAssign<&'a str> for Rope<u8> {

    /// Concatenate an `&str` onto a `Rope`
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, string: &'a str) {
        self.append(Rope::from(string.to_owned()))
    }
}

impl<T> ops::Index<usize> for Rope<T> {
    type Output = T;

    /// Recursively index the Rope to return the `i` th character.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let an_rope = Rope::from(String::from("abcd"));
    /// assert_eq!(&an_rope[0], "a");
    /// assert_eq!(&an_rope[1], "b");
    /// assert_eq!(&an_rope[2], "c");
    /// assert_eq!(&an_rope[3], "d");
    /// ```
    ///
    /// # Time complexity
    /// _O_(log _n_)
    ///
    #[inline]
    fn index(&self, i: usize) -> &T {
        &self.root[i]
    }
}

//-- slicing operators ----------------------------------------------
impl<T> ops::Index<ops::Range<usize>> for Rope<T> {
    type Output = [T];

    // Index a substring
    fn index(&self, i: ops::Range<usize>) -> &[T] {
        unimplemented!()
    }
}

impl<T> ops::Index<ops::RangeTo<usize>> for Rope<T> {
    type Output = [T];

    fn index(&self, i: ops::RangeTo<usize>) -> &[T] {
        unimplemented!()
    }
}

impl<T> ops::Index<ops::RangeFrom<usize>> for Rope<T> {
    type Output = [T];

    fn index(&self, i: ops::RangeFrom<usize>) -> &[T] {
        unimplemented!()
    }
}

impl<T> ops::IndexMut<ops::Range<usize>> for Rope<T> {
    fn index_mut(&mut self, i: ops::Range<usize>) -> &mut [T] {
        unimplemented!()
    }
}

impl<T> ops::IndexMut<ops::RangeTo<usize>> for Rope<T> {
    fn index_mut(&mut self, i: ops::RangeTo<usize>) -> &mut [T] {
        unimplemented!()
    }
}

impl<T> ops::IndexMut<ops::RangeFrom<usize>> for Rope<T> {
    fn index_mut(&mut self, i: ops::RangeFrom<usize>) -> &mut [T] {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<commit_msg>rope: fix separate impl blocks for node<commit_after>//! An rope.
//!
//! A rope is an efficient data structure for large mutable strings. It's
//! essentially a binary tree whose leaves are strings.
//!
//! For more information, see the following resources:
//! + http://scienceblogs.com/goodmath/2009/01/26/ropes-twining-together-strings/
//! + https://www.ibm.com/developerworks/library/j-ropes/
//! + http://citeseer.ist.psu.edu/viewdoc/download?doi=10.1.1.14.9450&rep=rep1&type=pdf

#![feature(const_fn)]
#![feature(box_syntax, box_patterns)]

use std::cmp;
use std::ops;
use std::convert;

#[derive(Debug)]
pub struct Rope<T> {
    // can we get away with having these be of &str or will they need
    // to be string?
    root: Node<T>
}

use self::Node::*;

/// A `Node` in the `Rope`'s tree.
///
/// A `Node` is either a `Leaf` holding a vector of `T`, or a
/// a `Branch` concatenating together two `Node`s.
#[derive(Debug)]
enum Node<T> {
    /// A leaf node
    Leaf(Vec<T>)
  , /// A branch concatenating together `l`eft and `r`ight nodes.
    Branch {
        /// The length of this node
        len: usize
      , /// The weight of a node is the summed weight of its left subtree
        weight: usize
      , /// The left branch node
        left: Option<Box<Node<T>>>
      , /// The right branch node
        right: Option<Box<Node<T>>>
    }
}

impl<T> Node<T> {
    const fn none() -> Self {
        Branch { len: 0
               , weight: 0
               , left: None
               , right: None
               }
    }

    /// Concatenate two `Node`s to return a new `Branch` node.
    fn branch(left: Self, right: Self) -> Self {
        Branch { len: left.len() + right.len()
               , weight: left.weight()
               , left: Some(box left)
               , right: Some(box right)
        }
    }

    #[inline]
    fn leaf(data: Vec<T>) -> Self {
        Leaf(data)
    }

    /// Returns the height in the tree of a node
    #[inline]
    fn height(&self) -> usize {
        use std::cmp::max;

        match self {
            &Node::Leaf(_) => 1
          , &Node::Branch { ref left, ref right, ..} =>
                max( left.as_ref().map(Box::as_ref).map_or(0, Node::height)
                   , right.as_ref().map(Box::as_ref).map_or(0, Node::height)
                   ) + 1
            }
    }

    /// Returns the length of a node
    //  TODO: do we want to cache this?
    fn len(&self) -> usize {
        match self { &Node::Leaf(ref v) => v.len()
                   , &Node::Branch { ref left, ref right, .. } =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::len) +
                        right.as_ref().map(Box::as_ref).map_or(0, Node::len)
                    }
    }

    /// Returns the weight of a node
    fn weight (&self) -> usize {
        match self { &Node::Leaf(ref v) => v.len()
                   , &Node::Branch { ref left, .. } =>
                        left.as_ref().map(Box::as_ref).map_or(0, Node::weight)
                    }
    }
}

impl<T> Rope<T> {

    /// Returns a new empty Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::<u8>::new();
    /// assert_eq!(an_rope.len(), 0);
    /// ```
    pub const fn new() -> Rope<T> {
        Rope { root: Node::<T>::none() }
    }

    /// Returns the length of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::new();
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_empty_rope = Rope::from(String::from(""));
    /// assert_eq!(an_empty_rope.len(), 0);
    /// ```
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("a string"));
    /// assert_eq!(an_rope.len(), "a string".len());
    /// ```
    pub fn len(&self) -> usize {
        // self.root.len()
        unimplemented!()
    }

    /// Appends a rope to the end of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// an_rope.append(Rope::from(String::from("efgh")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn append(&mut self, other: Rope<T>) {
        unimplemented!()
    }

    /// Prepends a rope to the front of this Rope
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("efgh"));
    /// an_rope.preend(Rope::from(String::from("abcd")))
    /// assert_eq!(an_rope, Rope::from(String::from("abcdefgh")));
    /// ```
    pub fn prepend(&mut self, other: Rope<T>) {
        unimplemented!()
    }

    /// Splits the rope into two ropes at the given index.
    ///
    /// Consumes this rope.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let mut an_rope = Rope::from(String::from("abcd"));
    /// let (ab, cd) = an_rope.split(2);
    /// assert_eq!(ab, Rope::from(String::from("ab")));
    /// assert_eq!(cd, Rope::from(String::from("cd")));
    /// ```
    pub fn split(self, index: usize) -> (Rope<T>, Rope<T>) {
        unimplemented!()
    }
}

impl<T> ops::Index<usize> for Node<T> {
    type Output = T;

    fn index(&self, i: usize) -> &T {
        // let len = self.len();
        // match self { &Node::Leaf(ref vec) => { &vec[i] }
        //             , &Node::Branch { right: Some(box ref r), .. } if len < i =>
        //                 &r[i - len]
        //             , &Node::Branch { left: Some(box ref l), .. } => &l[i]
        //             , &Node::Branch { left: None, right: None, .. } =>
        //                 panic!("Index out of bounds!")
        //             }
        unimplemented!()
    }
}

impl<T> convert::Into<Vec<T>> for Rope<T> {
    fn into(self) -> Vec<T> {
        unimplemented!()
    }

}

impl convert::From<String> for Rope<u8> {
    fn from(string: String) -> Rope<u8> {
        Rope {
            root: if string.len() == 0 { Node::none() }
                  else { Node::Leaf(string.into_bytes()) }
        }
    }
}

//-- comparisons ----------------------------------------------------
impl<T> cmp::PartialEq for Rope<T> {
    fn eq(&self, other: &Rope<T>) -> bool {
        unimplemented!()
    }
}

impl<T> cmp::PartialEq<str> for Rope<T> {
    fn eq(&self, other: &str) -> bool {
        unimplemented!()
    }
}

//-- concatenation --------------------------------------------------
impl ops::AddAssign for Rope<u8> {

    /// Concatenate two `Rope`s.
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += Rope::from(String::from("cd"));
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, other: Rope<u8>) {
        self.append(other)
    }
}

impl ops::AddAssign<String> for Rope<u8> {

    /// Concatenate a `String` onto a `Rope`
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, string: String) {
        self.append(Rope::from(string))
    }
}

impl<'a> ops::AddAssign<&'a str> for Rope<u8> {

    /// Concatenate an `&str` onto a `Rope`
    ///
    /// # Examples
    /// ```
    /// let mut rope = Rope::from(String::from("ab"));
    /// rope += String::from("cd");
    /// assert_eq!(rope, Rope::from(String::from("abcd")));
    /// ```
    #[inline]
    fn add_assign(&mut self, string: &'a str) {
        self.append(Rope::from(string.to_owned()))
    }
}

impl<T> ops::Index<usize> for Rope<T> {
    type Output = T;

    /// Recursively index the Rope to return the `i` th character.
    ///
    /// # Examples
    /// ```
    /// use an_rope::Rope;
    /// let an_rope = Rope::from(String::from("abcd"));
    /// assert_eq!(&an_rope[0], "a");
    /// assert_eq!(&an_rope[1], "b");
    /// assert_eq!(&an_rope[2], "c");
    /// assert_eq!(&an_rope[3], "d");
    /// ```
    ///
    /// # Time complexity
    /// _O_(log _n_)
    ///
    #[inline]
    fn index(&self, i: usize) -> &T {
        &self.root[i]
    }
}

//-- slicing operators ----------------------------------------------
impl<T> ops::Index<ops::Range<usize>> for Rope<T> {
    type Output = [T];

    // Index a substring
    fn index(&self, i: ops::Range<usize>) -> &[T] {
        unimplemented!()
    }
}

impl<T> ops::Index<ops::RangeTo<usize>> for Rope<T> {
    type Output = [T];

    fn index(&self, i: ops::RangeTo<usize>) -> &[T] {
        unimplemented!()
    }
}

impl<T> ops::Index<ops::RangeFrom<usize>> for Rope<T> {
    type Output = [T];

    fn index(&self, i: ops::RangeFrom<usize>) -> &[T] {
        unimplemented!()
    }
}

impl<T> ops::IndexMut<ops::Range<usize>> for Rope<T> {
    fn index_mut(&mut self, i: ops::Range<usize>) -> &mut [T] {
        unimplemented!()
    }
}

impl<T> ops::IndexMut<ops::RangeTo<usize>> for Rope<T> {
    fn index_mut(&mut self, i: ops::RangeTo<usize>) -> &mut [T] {
        unimplemented!()
    }
}

impl<T> ops::IndexMut<ops::RangeFrom<usize>> for Rope<T> {
    fn index_mut(&mut self, i: ops::RangeFrom<usize>) -> &mut [T] {
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "arbitrary")]
use base::storage::Owned;
#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};

use num::One;
use rand::distributions::{Distribution, Standard};
use rand::Rng;

use alga::general::Real;
use alga::linear::Rotation as AlgaRotation;

use base::allocator::Allocator;
use base::dimension::{DimName, U2, U3};
use base::{DefaultAllocator, Vector2, Vector3};

use geometry::{
    Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation, UnitComplex,
    UnitQuaternion,
};

impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new identity isometry.
    #[inline]
    pub fn identity() -> Self {
        Self::from_parts(Translation::identity(), R::identity())
    }

    /// The isometry that applies the rotation `r` with its axis passing through the point `p`.
    /// This effectively lets `p` invariant.
    #[inline]
    pub fn rotation_wrt_point(r: R, p: Point<N, D>) -> Self {
        let shift = r.transform_vector(&-&p.coords);
        Self::from_parts(Translation::from_vector(shift + p.coords), r)
    }
}

impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> One for Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new identity isometry.
    #[inline]
    fn one() -> Self {
        Self::identity()
    }
}

impl<N: Real, D: DimName, R> Distribution<Isometry<N, D, R>> for Standard
where
    R: AlgaRotation<Point<N, D>>,
    Standard: Distribution<N> + Distribution<R>,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> Isometry<N, D, R> {
        Isometry::from_parts(rng.gen(), rng.gen())
    }
}

#[cfg(feature = "arbitrary")]
impl<N, D: DimName, R> Arbitrary for Isometry<N, D, R>
where
    N: Real + Arbitrary + Send,
    R: AlgaRotation<Point<N, D>> + Arbitrary + Send,
    Owned<N, D>: Send,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn arbitrary<G: Gen>(rng: &mut G) -> Self {
        Self::from_parts(Arbitrary::arbitrary(rng), Arbitrary::arbitrary(rng))
    }
}

/*
 *
 * Constructors for various static dimensions.
 *
 */

// 2D rotation.
impl<N: Real> Isometry<N, U2, Rotation2<N>> {
    /// Creates a new isometry from a translation and a rotation angle.
    #[inline]
    pub fn new(translation: Vector2<N>, angle: N) -> Self {
        Self::from_parts(
            Translation::from_vector(translation),
            Rotation::<N, U2>::new(angle),
        )
    }
}

impl<N: Real> Isometry<N, U2, UnitComplex<N>> {
    /// Creates a new isometry from a translation and a rotation angle.
    #[inline]
    pub fn new(translation: Vector2<N>, angle: N) -> Self {
        Self::from_parts(
            Translation::from_vector(translation),
            UnitComplex::from_angle(angle),
        )
    }
}

// 3D rotation.
macro_rules! isometry_construction_impl(
    ($RotId: ident < $($RotParams: ident),*>, $RRDim: ty, $RCDim: ty) => {
        impl<N: Real> Isometry<N, U3, $RotId<$($RotParams),*>> {
            /// Creates a new isometry from a translation and a rotation axis-angle.
            #[inline]
            pub fn new(translation: Vector3<N>, axisangle: Vector3<N>) -> Self {
                Self::from_parts(
                    Translation::from_vector(translation),
                    $RotId::<$($RotParams),*>::from_scaled_axis(axisangle))
            }

            /// Creates an isometry that corresponds to the local frame of an observer standing at the
            /// point `eye` and looking toward `target`.
            ///
            /// It maps the view direction `target - eye` to the positive `z` axis and the origin to the
            /// `eye`.
            ///
            /// # Arguments
            ///   * eye - The observer position.
            ///   * target - The target position.
            ///   * up - Vertical direction. The only requirement of this parameter is to not be collinear
            ///   to `eye - at`. Non-collinearity is not checked.
            #[inline]
            pub fn new_observer_frame(eye:    &Point3<N>,
                                      target: &Point3<N>,
                                      up:     &Vector3<N>)
                                      -> Self {
                Self::from_parts(
                    Translation::from_vector(eye.coords.clone()),
                    $RotId::new_observer_frame(&(target - eye), up))
            }

            /// Builds a right-handed look-at view matrix.
            ///
            /// This conforms to the common notion of right handed look-at matrix from the computer
            /// graphics community.
            ///
            /// # Arguments
            ///   * eye - The eye position.
            ///   * target - The target position.
            ///   * up - A vector approximately aligned with required the vertical axis. The only
            ///   requirement of this parameter is to not be collinear to `target - eye`.
            #[inline]
            pub fn look_at_rh(eye:    &Point3<N>,
                              target: &Point3<N>,
                              up:     &Vector3<N>)
                              -> Self {
                let rotation = $RotId::look_at_rh(&(target - eye), up);
                let trans    = &rotation * (-eye);

                Self::from_parts(Translation::from_vector(trans.coords), rotation)
            }

            /// Builds a left-handed look-at view matrix.
            ///
            /// This conforms to the common notion of left handed look-at matrix from the computer
            /// graphics community.
            ///
            /// # Arguments
            ///   * eye - The eye position.
            ///   * target - The target position.
            ///   * up - A vector approximately aligned with required the vertical axis. The only
            ///   requirement of this parameter is to not be collinear to `target - eye`.
            #[inline]
            pub fn look_at_lh(eye:    &Point3<N>,
                              target: &Point3<N>,
                              up:     &Vector3<N>)
                              -> Self {
                let rotation = $RotId::look_at_lh(&(target - eye), up);
                let trans    = &rotation * (-eye);

                Self::from_parts(Translation::from_vector(trans.coords), rotation)
            }
        }
    }
);

isometry_construction_impl!(Rotation3<N>, U3, U3);
isometry_construction_impl!(UnitQuaternion<N>, U4, U1);
<commit_msg>Add doc-tests to isometry_construction.rs<commit_after>#[cfg(feature = "arbitrary")]
use base::storage::Owned;
#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};

use num::One;
use rand::distributions::{Distribution, Standard};
use rand::Rng;

use alga::general::Real;
use alga::linear::Rotation as AlgaRotation;

use base::allocator::Allocator;
use base::dimension::{DimName, U2, U3};
use base::{DefaultAllocator, Vector2, Vector3};

use geometry::{
    Isometry, Point, Point3, Rotation, Rotation2, Rotation3, Translation, UnitComplex,
    UnitQuaternion,
};

impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new identity isometry.
    ///
    /// # Example
    ///
    /// ```
    /// # use nalgebra::{Isometry2, Point2};
    /// let iso = Isometry2::identity();
    /// let pt = Point2::new(1.0, 2.0);
    ///
    /// assert_eq!(iso * pt, pt);
    /// ```
    #[inline]
    pub fn identity() -> Self {
        Self::from_parts(Translation::identity(), R::identity())
    }

    /// The isometry that applies the rotation `r` with its axis passing through the point `p`.
    /// This effectively lets `p` invariant.
    ///
    /// # Example
    ///
    /// ```
    /// # #[macro_use] extern crate approx;
    /// # extern crate nalgebra;
    /// # use std::f32;
    /// # use nalgebra::{Isometry2, Point2, UnitComplex};
    /// let rot = UnitComplex::new(f32::consts::PI);
    /// let pt = Point2::new(1.0, 0.0);
    /// let iso = Isometry2::rotation_wrt_point(rot, pt);
    ///
    /// assert_eq!(iso * pt, pt); // The rotation center is not affected.
    /// assert_relative_eq!(iso * Point2::new(1.0, 2.0), Point2::new(1.0, -2.0), epsilon = 1.0e-6);
    /// ```
    #[inline]
    pub fn rotation_wrt_point(r: R, p: Point<N, D>) -> Self {
        let shift = r.transform_vector(&-&p.coords);
        Self::from_parts(Translation::from_vector(shift + p.coords), r)
    }
}

impl<N: Real, D: DimName, R: AlgaRotation<Point<N, D>>> One for Isometry<N, D, R>
where DefaultAllocator: Allocator<N, D>
{
    /// Creates a new identity isometry.
    #[inline]
    fn one() -> Self {
        Self::identity()
    }
}

impl<N: Real, D: DimName, R> Distribution<Isometry<N, D, R>> for Standard
where
    R: AlgaRotation<Point<N, D>>,
    Standard: Distribution<N> + Distribution<R>,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn sample<'a, G: Rng + ?Sized>(&self, rng: &'a mut G) -> Isometry<N, D, R> {
        Isometry::from_parts(rng.gen(), rng.gen())
    }
}

#[cfg(feature = "arbitrary")]
impl<N, D: DimName, R> Arbitrary for Isometry<N, D, R>
where
    N: Real + Arbitrary + Send,
    R: AlgaRotation<Point<N, D>> + Arbitrary + Send,
    Owned<N, D>: Send,
    DefaultAllocator: Allocator<N, D>,
{
    #[inline]
    fn arbitrary<G: Gen>(rng: &mut G) -> Self {
        Self::from_parts(Arbitrary::arbitrary(rng), Arbitrary::arbitrary(rng))
    }
}

/*
 *
 * Constructors for various static dimensions.
 *
 */

// 2D rotation.
impl<N: Real> Isometry<N, U2, Rotation2<N>> {
    /// Creates a new 2D isometry from a translation and a rotation angle.
    ///
    /// Its rotational part is represented as a 2x2 rotation matrix.
    ///
    /// # Example
    ///
    /// ```
    /// # use std::f32;
    /// # use nalgebra::{Isometry2, Vector2, Point2};
    /// let iso = Isometry2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2);
    ///
    /// assert_eq!(iso * Point2::new(3.0, 4.0), Point2::new(-3.0, 5.0));
    /// ```
    #[inline]
    pub fn new(translation: Vector2<N>, angle: N) -> Self {
        Self::from_parts(
            Translation::from_vector(translation),
            Rotation::<N, U2>::new(angle),
        )
    }
}

impl<N: Real> Isometry<N, U2, UnitComplex<N>> {
    /// Creates a new 2D isometry from a translation and a rotation angle.
    ///
    /// Its rotational part is represented as an unit complex number.
    ///
    /// # Example
    ///
    /// ```
    /// # use std::f32;
    /// # use nalgebra::{IsometryMatrix2, Point2, Vector2};
    /// let iso = IsometryMatrix2::new(Vector2::new(1.0, 2.0), f32::consts::FRAC_PI_2);
    ///
    /// assert_eq!(iso * Point2::new(3.0, 4.0), Point2::new(-3.0, 5.0));
    /// ```
    #[inline]
    pub fn new(translation: Vector2<N>, angle: N) -> Self {
        Self::from_parts(
            Translation::from_vector(translation),
            UnitComplex::from_angle(angle),
        )
    }
}

// 3D rotation.
macro_rules! isometry_construction_impl(
    ($RotId: ident < $($RotParams: ident),*>, $RRDim: ty, $RCDim: ty) => {
        impl<N: Real> Isometry<N, U3, $RotId<$($RotParams),*>> {
            /// Creates a new isometry from a translation and a rotation axis-angle.
            ///
            /// # Example
            ///
            /// ```
            /// # #[macro_use] extern crate approx;
            /// # extern crate nalgebra;
            /// # use std::f32;
            /// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
            /// let axisangle = Vector3::y() * f32::consts::FRAC_PI_2;
            /// let translation = Vector3::new(1.0, 2.0, 3.0);
            ///
            /// // Isometry with its rotation part represented as a UnitQuaternion
            /// let iso = Isometry3::new(translation, axisangle);
            /// assert_relative_eq!(iso * Point3::new(4.0, 5.0, 6.0), Point3::new(7.0, 7.0, -1.0), epsilon = 1.0e-6);
            /// assert_relative_eq!(iso * Vector3::new(4.0, 5.0, 6.0), Vector3::new(6.0, 5.0, -4.0), epsilon = 1.0e-6);
            /// ```
            ///
            /// // Isometry with its rotation part represented as a Rotation3 (a 3x3 rotation matrix).
            /// let iso = IsometryMatrix3::new(translation, axisangle);
            /// assert_relative_eq!(iso * Point3::new(4.0, 5.0, 6.0), Point3::new(7.0, 7.0, -1.0), epsilon = 1.0e-6);
            /// assert_relative_eq!(iso * Vector3::new(4.0, 5.0, 6.0), Vector3::new(6.0, 5.0, -4.0), epsilon = 1.0e-6);
            /// ```
            #[inline]
            pub fn new(translation: Vector3<N>, axisangle: Vector3<N>) -> Self {
                Self::from_parts(
                    Translation::from_vector(translation),
                    $RotId::<$($RotParams),*>::from_scaled_axis(axisangle))
            }

            /// Creates an isometry that corresponds to the local frame of an observer standing at the
            /// point `eye` and looking toward `target`.
            ///
            /// It maps the `z` axis to the view direction `target - eye`and the origin to teh `eye`.
            ///
            /// # Arguments
            ///   * eye - The observer position.
            ///   * target - The target position.
            ///   * up - Vertical direction. The only requirement of this parameter is to not be collinear
            ///   to `eye - at`. Non-collinearity is not checked.
            ///
            /// # Example
            ///
            /// ```
            /// # #[macro_use] extern crate approx;
            /// # extern crate nalgebra;
            /// # use std::f32;
            /// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
            /// let eye = Point3::new(1.0, 2.0, 3.0);
            /// let target = Point3::new(2.0, 2.0, 3.0);
            /// let up = Vector3::y();
            ///
            /// // Isometry with its rotation part represented as a UnitQuaternion
            /// let iso = Isometry3::new_observer_frame(&eye, &target, &up);
            /// assert_eq!(iso * Point3::origin(), eye);
            /// assert_relative_eq!(iso * Vector3::z(), Vector3::x());
            ///
            /// // Isometry with its rotation part represented as Rotation3 (a 3x3 rotation matrix).
            /// let iso = IsometryMatrix3::new_observer_frame(&eye, &target, &up);
            /// assert_eq!(iso * Point3::origin(), eye);
            /// assert_relative_eq!(iso * Vector3::z(), Vector3::x());
            /// ```
            #[inline]
            pub fn new_observer_frame(eye:    &Point3<N>,
                                      target: &Point3<N>,
                                      up:     &Vector3<N>)
                                      -> Self {
                Self::from_parts(
                    Translation::from_vector(eye.coords.clone()),
                    $RotId::new_observer_frame(&(target - eye), up))
            }

            /// Builds a right-handed look-at view matrix.
            ///
            /// It maps the view direction `target - eye` to the **negative** `z` axis to and the `eye` to the origin.
            /// This conforms to the common notion of right handed camera look-at **view matrix** from
            /// the computer graphics community, i.e. the camera is assumed to look toward its local `-z` axis.
            ///
            /// # Arguments
            ///   * eye - The eye position.
            ///   * target - The target position.
            ///   * up - A vector approximately aligned with required the vertical axis. The only
            ///   requirement of this parameter is to not be collinear to `target - eye`.
            ///
            /// # Example
            ///
            /// ```
            /// # #[macro_use] extern crate approx;
            /// # extern crate nalgebra;
            /// # use std::f32;
            /// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
            /// let eye = Point3::new(1.0, 2.0, 3.0);
            /// let target = Point3::new(2.0, 2.0, 3.0);
            /// let up = Vector3::y();
            ///
            /// // Isometry with its rotation part represented as a UnitQuaternion
            /// let iso = Isometry3::look_at_rh(&eye, &target, &up);
            /// assert_eq!(iso * eye, Point3::origin());
            /// assert_relative_eq!(iso * Vector3::x(), -Vector3::z());
            ///
            /// // Isometry with its rotation part represented as Rotation3 (a 3x3 rotation matrix).
            /// let iso = IsometryMatrix3::look_at_rh(&eye, &target, &up);
            /// assert_eq!(iso * eye, Point3::origin());
            /// assert_relative_eq!(iso * Vector3::x(), -Vector3::z());
            /// ```
            #[inline]
            pub fn look_at_rh(eye:    &Point3<N>,
                              target: &Point3<N>,
                              up:     &Vector3<N>)
                              -> Self {
                let rotation = $RotId::look_at_rh(&(target - eye), up);
                let trans    = &rotation * (-eye);

                Self::from_parts(Translation::from_vector(trans.coords), rotation)
            }

            /// Builds a left-handed look-at view matrix.
            ///
            /// It maps the view direction `target - eye` to the **positive** `z` axis and the `eye` to the origin.
            /// This conforms to the common notion of right handed camera look-at **view matrix** from
            /// the computer graphics community, i.e. the camera is assumed to look toward its local `z` axis.
            ///
            /// # Arguments
            ///   * eye - The eye position.
            ///   * target - The target position.
            ///   * up - A vector approximately aligned with required the vertical axis. The only
            ///   requirement of this parameter is to not be collinear to `target - eye`.
            ///
            /// # Example
            ///
            /// ```
            /// # #[macro_use] extern crate approx;
            /// # extern crate nalgebra;
            /// # use std::f32;
            /// # use nalgebra::{Isometry3, IsometryMatrix3, Point3, Vector3};
            /// let eye = Point3::new(1.0, 2.0, 3.0);
            /// let target = Point3::new(2.0, 2.0, 3.0);
            /// let up = Vector3::y();
            ///
            /// // Isometry with its rotation part represented as a UnitQuaternion
            /// let iso = Isometry3::look_at_lh(&eye, &target, &up);
            /// assert_eq!(iso * eye, Point3::origin());
            /// assert_relative_eq!(iso * Vector3::x(), Vector3::z());
            ///
            /// // Isometry with its rotation part represented as Rotation3 (a 3x3 rotation matrix).
            /// let iso = IsometryMatrix3::look_at_lh(&eye, &target, &up);
            /// assert_eq!(iso * eye, Point3::origin());
            /// assert_relative_eq!(iso * Vector3::x(), Vector3::z());
            /// ```
            #[inline]
            pub fn look_at_lh(eye:    &Point3<N>,
                              target: &Point3<N>,
                              up:     &Vector3<N>)
                              -> Self {
                let rotation = $RotId::look_at_lh(&(target - eye), up);
                let trans    = &rotation * (-eye);

                Self::from_parts(Translation::from_vector(trans.coords), rotation)
            }
        }
    }
);

isometry_construction_impl!(Rotation3<N>, U3, U3);
isometry_construction_impl!(UnitQuaternion<N>, U4, U1);
<|endoftext|>


<commit_before>extern crate piston;
extern crate ai_behavior;
extern crate sprite;
extern crate graphics;
extern crate sdl2_window;
extern crate opengl_graphics;

use std::path::Path;
use std::cell::RefCell;
use std::rc::Rc;

use sprite::*;
use ai_behavior::{
    Action,
    Sequence,
    Wait,
    WaitForever,
    While,
};

use sdl2_window::Sdl2Window;
use opengl_graphics::{
    GlGraphics,
    OpenGL,
    Texture,
};
use piston::window::{ WindowSettings, Size };

fn main() {
    let (width, height) = (300, 300);
    let opengl = OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings::new(
            "piston-example-sprite".to_string(),
            Size { width: width, height: height }
        )
        .exit_on_esc(true)
    );

    let id;
    let mut scene = Scene::new();
    let tex = Path::new("./bin/assets/rust-logo.png");
    let tex = Rc::new(Texture::from_path(&tex).unwrap());
    let mut sprite = Sprite::from_texture(tex.clone());
    sprite.set_position(width as f64 / 2.0, height as f64 / 2.0);

    id = scene.add_child(sprite);

    // Run a sequence or animations.
    let seq = Sequence(vec![
        Action(Ease(EaseFunction::CubicOut, Box::new(ScaleTo(2.0, 0.5, 0.5)))),
        Action(Ease(EaseFunction::BounceOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Ease(EaseFunction::ElasticOut, Box::new(MoveBy(2.0, 0.0, -100.0)))),
        Action(Ease(EaseFunction::BackInOut, Box::new(MoveBy(1.0, 0.0, -100.0)))),
        Wait(0.5),
        Action(Ease(EaseFunction::ExponentialInOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Blink(1.0, 5)),
        While(Box::new(WaitForever), vec![
            Action(Ease(EaseFunction::QuadraticIn, Box::new(FadeOut(1.0)))),
            Action(Ease(EaseFunction::QuadraticOut, Box::new(FadeIn(1.0)))),
        ]),
    ]);
    scene.run(&id, &seq);

    // This animation and the one above can run in parallel.
    let rotate = Action(Ease(EaseFunction::ExponentialInOut,
        Box::new(RotateTo(2.0, 360.0))));
    scene.run(&id, &rotate);

    println!("Press any key to pause/resume the animation!");

    let ref mut gl = GlGraphics::new(opengl);
    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;

        scene.event(&e);

        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([1.0, 1.0, 1.0, 1.0], gl);
                scene.draw(c.transform, gl);
            });
        }
        if let Some(_) = e.press_args() {
            scene.toggle(&id, &seq);
            scene.toggle(&id, &rotate);
        }
    }
}
<commit_msg>fix fallout of Uuid becoming Copy<commit_after>extern crate piston;
extern crate ai_behavior;
extern crate sprite;
extern crate graphics;
extern crate sdl2_window;
extern crate opengl_graphics;

use std::path::Path;
use std::cell::RefCell;
use std::rc::Rc;

use sprite::*;
use ai_behavior::{
    Action,
    Sequence,
    Wait,
    WaitForever,
    While,
};

use sdl2_window::Sdl2Window;
use opengl_graphics::{
    GlGraphics,
    OpenGL,
    Texture,
};
use piston::window::{ WindowSettings, Size };

fn main() {
    let (width, height) = (300, 300);
    let opengl = OpenGL::_3_2;
    let window = Sdl2Window::new(
        opengl,
        WindowSettings::new(
            "piston-example-sprite".to_string(),
            Size { width: width, height: height }
        )
        .exit_on_esc(true)
    );

    let id;
    let mut scene = Scene::new();
    let tex = Path::new("./bin/assets/rust-logo.png");
    let tex = Rc::new(Texture::from_path(&tex).unwrap());
    let mut sprite = Sprite::from_texture(tex.clone());
    sprite.set_position(width as f64 / 2.0, height as f64 / 2.0);

    id = scene.add_child(sprite);

    // Run a sequence or animations.
    let seq = Sequence(vec![
        Action(Ease(EaseFunction::CubicOut, Box::new(ScaleTo(2.0, 0.5, 0.5)))),
        Action(Ease(EaseFunction::BounceOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Ease(EaseFunction::ElasticOut, Box::new(MoveBy(2.0, 0.0, -100.0)))),
        Action(Ease(EaseFunction::BackInOut, Box::new(MoveBy(1.0, 0.0, -100.0)))),
        Wait(0.5),
        Action(Ease(EaseFunction::ExponentialInOut, Box::new(MoveBy(1.0, 0.0, 100.0)))),
        Action(Blink(1.0, 5)),
        While(Box::new(WaitForever), vec![
            Action(Ease(EaseFunction::QuadraticIn, Box::new(FadeOut(1.0)))),
            Action(Ease(EaseFunction::QuadraticOut, Box::new(FadeIn(1.0)))),
        ]),
    ]);
    scene.run(id, &seq);

    // This animation and the one above can run in parallel.
    let rotate = Action(Ease(EaseFunction::ExponentialInOut,
        Box::new(RotateTo(2.0, 360.0))));
    scene.run(id, &rotate);

    println!("Press any key to pause/resume the animation!");

    let ref mut gl = GlGraphics::new(opengl);
    let window = Rc::new(RefCell::new(window));
    for e in piston::events(window) {
        use piston::event::*;

        scene.event(&e);

        if let Some(args) = e.render_args() {
            use graphics::*;
            gl.draw([0, 0, args.width as i32, args.height as i32], |c, gl| {
                graphics::clear([1.0, 1.0, 1.0, 1.0], gl);
                scene.draw(c.transform, gl);
            });
        }
        if let Some(_) = e.press_args() {
            scene.toggle(id, &seq);
            scene.toggle(id, &rotate);
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Refactoring to avoid typechecking blow up.<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2010-2013, Susumu Yata
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

/*
#include <algorithm>
#include <cstring>
#include <sstream>

#include <marisa/grimoire/trie/config.h>
#include <marisa/grimoire/trie/header.h>
#include <marisa/grimoire/trie/key.h>
#include <marisa/grimoire/trie/range.h>
#include <marisa/grimoire/trie/tail.h>
#include <marisa/grimoire/trie/state.h>

#include "marisa-assert.h"

namespace {

void TestConfig() {
  TEST_START();

  marisa::grimoire::trie::Config config;

  ASSERT(config.num_tries() == MARISA_DEFAULT_NUM_TRIES);
  ASSERT(config.tail_mode() == MARISA_DEFAULT_TAIL);
  ASSERT(config.node_order() == MARISA_DEFAULT_ORDER);
  ASSERT(config.cache_level() == MARISA_DEFAULT_CACHE);

  config.parse(10 | MARISA_BINARY_TAIL | MARISA_LABEL_ORDER |
      MARISA_TINY_CACHE);

  ASSERT(config.num_tries() == 10);
  ASSERT(config.tail_mode() == MARISA_BINARY_TAIL);
  ASSERT(config.node_order() == MARISA_LABEL_ORDER);
  ASSERT(config.cache_level() == MARISA_TINY_CACHE);

  config.parse(0);

  ASSERT(config.num_tries() == MARISA_DEFAULT_NUM_TRIES);
  ASSERT(config.tail_mode() == MARISA_DEFAULT_TAIL);
  ASSERT(config.node_order() == MARISA_DEFAULT_ORDER);
  ASSERT(config.cache_level() == MARISA_DEFAULT_CACHE);

  TEST_END();
}

void TestHeader() {
  TEST_START();

  marisa::grimoire::trie::Header header;

  {
    marisa::grimoire::Writer writer;
    writer.open("trie-test.dat");
    header.write(writer);
  }

  {
    marisa::grimoire::Mapper mapper;
    mapper.open("trie-test.dat");
    header.map(mapper);
  }

  {
    marisa::grimoire::Reader reader;
    reader.open("trie-test.dat");
    header.read(reader);
  }

  TEST_END();
}

void TestKey() {
  TEST_START();

  marisa::grimoire::trie::Key key;

  ASSERT(key.ptr() == NULL);
  ASSERT(key.length() == 0);
  ASSERT(key.id() == 0);
  ASSERT(key.terminal() == 0);

  const char *str = "xyz";

  key.set_str(str, 3);
  key.set_weight(10.0F);
  key.set_id(20);

  ASSERT(key.ptr() == str);
  ASSERT(key.length() == 3);
  ASSERT(key[0] == 'x');
  ASSERT(key[1] == 'y');
  ASSERT(key[2] == 'z');
  ASSERT(key.weight() == 10.0F);
  ASSERT(key.id() == 20);

  key.set_terminal(30);
  ASSERT(key.terminal() == 30);

  key.substr(1, 2);

  ASSERT(key.ptr() == str + 1);
  ASSERT(key.length() == 2);
  ASSERT(key[0] == 'y');
  ASSERT(key[1] == 'z');

  marisa::grimoire::trie::Key key2;
  key2.set_str("abc", 3);

  ASSERT(key == key);
  ASSERT(key != key2);
  ASSERT(key > key2);
  ASSERT(key2 < key);

  marisa::grimoire::trie::ReverseKey r_key;

  ASSERT(r_key.ptr() == NULL);
  ASSERT(r_key.length() == 0);
  ASSERT(r_key.id() == 0);
  ASSERT(r_key.terminal() == 0);

  r_key.set_str(str, 3);
  r_key.set_weight(100.0F);
  r_key.set_id(200);

  ASSERT(r_key.ptr() == str);
  ASSERT(r_key.length() == 3);
  ASSERT(r_key[0] == 'z');
  ASSERT(r_key[1] == 'y');
  ASSERT(r_key[2] == 'x');
  ASSERT(r_key.weight() == 100.0F);
  ASSERT(r_key.id() == 200);

  r_key.set_terminal(300);
  ASSERT(r_key.terminal() == 300);

  r_key.substr(1, 2);

  ASSERT(r_key.ptr() == str);
  ASSERT(r_key.length() == 2);
  ASSERT(r_key[0] == 'y');
  ASSERT(r_key[1] == 'x');

  marisa::grimoire::trie::ReverseKey r_key2;
  r_key2.set_str("abc", 3);

  ASSERT(r_key == r_key);
  ASSERT(r_key != r_key2);
  ASSERT(r_key > r_key2);
  ASSERT(r_key2 < r_key);

  TEST_END();
}

void TestRange() {
  TEST_START();

  marisa::grimoire::trie::Range range;

  ASSERT(range.begin() == 0);
  ASSERT(range.end() == 0);
  ASSERT(range.key_pos() == 0);

  range.set_begin(1);
  range.set_end(2);
  range.set_key_pos(3);

  ASSERT(range.begin() == 1);
  ASSERT(range.end() == 2);
  ASSERT(range.key_pos() == 3);

  range = marisa::grimoire::trie::make_range(10, 20, 30);

  ASSERT(range.begin() == 10);
  ASSERT(range.end() == 20);
  ASSERT(range.key_pos() == 30);

  marisa::grimoire::trie::WeightedRange w_range;

  ASSERT(w_range.begin() == 0);
  ASSERT(w_range.end() == 0);
  ASSERT(w_range.key_pos() == 0);
  ASSERT(w_range.weight() == 0.0F);

  w_range.set_begin(10);
  w_range.set_end(20);
  w_range.set_key_pos(30);
  w_range.set_weight(40.0F);

  ASSERT(w_range.begin() == 10);
  ASSERT(w_range.end() == 20);
  ASSERT(w_range.key_pos() == 30);
  ASSERT(w_range.weight() == 40.0F);

  marisa::grimoire::trie::WeightedRange w_range2 =
      marisa::grimoire::trie::make_weighted_range(100, 200, 300, 400.0F);

  ASSERT(w_range2.begin() == 100);
  ASSERT(w_range2.end() == 200);
  ASSERT(w_range2.key_pos() == 300);
  ASSERT(w_range2.weight() == 400.0F);

  ASSERT(w_range < w_range2);
  ASSERT(w_range2 > w_range);

  TEST_END();
}

void TestEntry() {
  TEST_START();

  marisa::grimoire::trie::Entry entry;

  ASSERT(entry.ptr() == NULL);
  ASSERT(entry.length() == 0);
  ASSERT(entry.id() == 0);

  const char *str = "XYZ";

  entry.set_str(str, 3);
  entry.set_id(123);

  ASSERT(entry.ptr() == str);
  ASSERT(entry.length() == 3);
  ASSERT(entry[0] == 'Z');
  ASSERT(entry[1] == 'Y');
  ASSERT(entry[2] == 'X');
  ASSERT(entry.id() == 123);

  TEST_END();
}

void TestTextTail() {
  TEST_START();

  marisa::grimoire::trie::Tail tail;
  marisa::grimoire::Vector<marisa::grimoire::trie::Entry> entries;
  marisa::grimoire::Vector<marisa::UInt32> offsets;
  tail.build(entries, &offsets, MARISA_TEXT_TAIL);

  ASSERT(tail.mode() == MARISA_TEXT_TAIL);
  ASSERT(tail.size() == 0);
  ASSERT(tail.empty());
  ASSERT(tail.total_size() == tail.size());
  ASSERT(tail.io_size() == (sizeof(marisa::UInt64) * 6));

  ASSERT(offsets.empty());

  marisa::grimoire::trie::Entry entry;
  entry.set_str("X", 1);
  entries.push_back(entry);

  tail.build(entries, &offsets, MARISA_TEXT_TAIL);

  ASSERT(tail.mode() == MARISA_TEXT_TAIL);
  ASSERT(tail.size() == 2);
  ASSERT(!tail.empty());
  ASSERT(tail.total_size() == tail.size());
  ASSERT(tail.io_size() == (sizeof(marisa::UInt64) * 7));

  ASSERT(offsets.size() == entries.size());
  ASSERT(offsets[0] == 0);
  ASSERT(tail[offsets[0]] == 'X');
  ASSERT(tail[offsets[0] + 1] == '\0');

  entries.clear();
  entry.set_str("abc", 3);
  entries.push_back(entry);
  entry.set_str("bc", 2);
  entries.push_back(entry);
  entry.set_str("abc", 3);
  entries.push_back(entry);
  entry.set_str("c", 1);
  entries.push_back(entry);
  entry.set_str("ABC", 3);
  entries.push_back(entry);
  entry.set_str("AB", 2);
  entries.push_back(entry);

  tail.build(entries, &offsets, MARISA_TEXT_TAIL);
  std::sort(entries.begin(), entries.end(),
      marisa::grimoire::trie::Entry::IDComparer());

  ASSERT(tail.size() == 11);
  ASSERT(offsets.size() == entries.size());
  for (std::size_t i = 0; i < entries.size(); ++i) {
    const char * const ptr = &tail[offsets[i]];
    ASSERT(std::strlen(ptr) == entries[i].length());
    ASSERT(std::strcmp(ptr, entries[i].ptr()) == 0);
  }

  {
    marisa::grimoire::Writer writer;
    writer.open("trie-test.dat");
    tail.write(writer);
  }

  tail.clear();

  ASSERT(tail.size() == 0);
  ASSERT(tail.total_size() == tail.size());

  {
    marisa::grimoire::Mapper mapper;
    mapper.open("trie-test.dat");
    tail.map(mapper);

    ASSERT(tail.mode() == MARISA_TEXT_TAIL);
    ASSERT(tail.size() == 11);
    for (std::size_t i = 0; i < entries.size(); ++i) {
      const char * const ptr = &tail[offsets[i]];
    ASSERT(std::strlen(ptr) == entries[i].length());
    ASSERT(std::strcmp(ptr, entries[i].ptr()) == 0);
    }
    tail.clear();
  }

  {
    marisa::grimoire::Reader reader;
    reader.open("trie-test.dat");
    tail.read(reader);
  }

  ASSERT(tail.size() == 11);
  ASSERT(offsets.size() == entries.size());
  for (std::size_t i = 0; i < entries.size(); ++i) {
    const char * const ptr = &tail[offsets[i]];
    ASSERT(std::strlen(ptr) == entries[i].length());
    ASSERT(std::strcmp(ptr, entries[i].ptr()) == 0);
  }

  {
    std::stringstream stream;
    marisa::grimoire::Writer writer;
    writer.open(stream);
    tail.write(writer);
    tail.clear();
    marisa::grimoire::Reader reader;
    reader.open(stream);
    tail.read(reader);
  }

  ASSERT(tail.size() == 11);
  ASSERT(offsets.size() == entries.size());
  for (std::size_t i = 0; i < entries.size(); ++i) {
    const char * const ptr = &tail[offsets[i]];
    ASSERT(std::strlen(ptr) == entries[i].length());
    ASSERT(std::strcmp(ptr, entries[i].ptr()) == 0);
  }

  TEST_END();
}

void TestBinaryTail() {
  TEST_START();

  marisa::grimoire::trie::Tail tail;
  marisa::grimoire::Vector<marisa::grimoire::trie::Entry> entries;
  marisa::grimoire::Vector<marisa::UInt32> offsets;
  tail.build(entries, &offsets, MARISA_BINARY_TAIL);

  ASSERT(tail.mode() == MARISA_TEXT_TAIL);
  ASSERT(tail.size() == 0);
  ASSERT(tail.empty());
  ASSERT(tail.total_size() == tail.size());
  ASSERT(tail.io_size() == (sizeof(marisa::UInt64) * 6));

  ASSERT(offsets.empty());

  marisa::grimoire::trie::Entry entry;
  entry.set_str("X", 1);
  entries.push_back(entry);

  tail.build(entries, &offsets, MARISA_BINARY_TAIL);

  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
  ASSERT(tail.size() == 1);
  ASSERT(!tail.empty());
  ASSERT(tail.total_size() == (tail.size() + sizeof(marisa::UInt64)));
  ASSERT(tail.io_size() == (sizeof(marisa::UInt64) * 8));

  ASSERT(offsets.size() == entries.size());
  ASSERT(offsets[0] == 0);

  const char binary_entry[] = { 'N', 'P', '\0', 'T', 'r', 'i', 'e' };
  entries[0].set_str(binary_entry, sizeof(binary_entry));

  tail.build(entries, &offsets, MARISA_TEXT_TAIL);

  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
  ASSERT(tail.size() == entries[0].length());

  ASSERT(offsets.size() == entries.size());
  ASSERT(offsets[0] == 0);

  entries.clear();
  entry.set_str("abc", 3);
  entries.push_back(entry);
  entry.set_str("bc", 2);
  entries.push_back(entry);
  entry.set_str("abc", 3);
  entries.push_back(entry);
  entry.set_str("c", 1);
  entries.push_back(entry);
  entry.set_str("ABC", 3);
  entries.push_back(entry);
  entry.set_str("AB", 2);
  entries.push_back(entry);

  tail.build(entries, &offsets, MARISA_BINARY_TAIL);
  std::sort(entries.begin(), entries.end(),
      marisa::grimoire::trie::Entry::IDComparer());

  ASSERT(tail.mode() == MARISA_BINARY_TAIL);
  ASSERT(tail.size() == 8);
  ASSERT(offsets.size() == entries.size());
  for (std::size_t i = 0; i < entries.size(); ++i) {
    const char * const ptr = &tail[offsets[i]];
    ASSERT(std::memcmp(ptr, entries[i].ptr(), entries[i].length()) == 0);
  }

  TEST_END();
}

void TestHistory() {
  TEST_START();

  marisa::grimoire::trie::History history;

  ASSERT(history.node_id() == 0);
  ASSERT(history.louds_pos() == 0);
  ASSERT(history.key_pos() == 0);
  ASSERT(history.link_id() == MARISA_INVALID_LINK_ID);
  ASSERT(history.key_id() == MARISA_INVALID_KEY_ID);

  history.set_node_id(100);
  history.set_louds_pos(200);
  history.set_key_pos(300);
  history.set_link_id(400);
  history.set_key_id(500);

  ASSERT(history.node_id() == 100);
  ASSERT(history.louds_pos() == 200);
  ASSERT(history.key_pos() == 300);
  ASSERT(history.link_id() == 400);
  ASSERT(history.key_id() == 500);

  TEST_END();
}

void TestState() {
  TEST_START();

  marisa::grimoire::trie::State state;

  ASSERT(state.key_buf().empty());
  ASSERT(state.history().empty());
  ASSERT(state.node_id() == 0);
  ASSERT(state.query_pos() == 0);
  ASSERT(state.history_pos() == 0);
  ASSERT(state.status_code() == marisa::grimoire::trie::MARISA_READY_TO_ALL);

  state.set_node_id(10);
  state.set_query_pos(100);
  state.set_history_pos(1000);
  state.set_status_code(
      marisa::grimoire::trie::MARISA_END_OF_PREDICTIVE_SEARCH);

  ASSERT(state.node_id() == 10);
  ASSERT(state.query_pos() == 100);
  ASSERT(state.history_pos() == 1000);
  ASSERT(state.status_code() ==
      marisa::grimoire::trie::MARISA_END_OF_PREDICTIVE_SEARCH);

  state.lookup_init();
  ASSERT(state.status_code() == marisa::grimoire::trie::MARISA_READY_TO_ALL);

  state.reverse_lookup_init();
  ASSERT(state.status_code() == marisa::grimoire::trie::MARISA_READY_TO_ALL);

  state.common_prefix_search_init();
  ASSERT(state.status_code() ==
      marisa::grimoire::trie::MARISA_READY_TO_COMMON_PREFIX_SEARCH);

  state.predictive_search_init();
  ASSERT(state.status_code() ==
      marisa::grimoire::trie::MARISA_READY_TO_PREDICTIVE_SEARCH);

  TEST_END();
}

}  // namespace

int main() try {
  TestConfig();
  TestHeader();
  TestKey();
  TestRange();
  TestEntry();
  TestTextTail();
  TestBinaryTail();
  TestHistory();
  TestState();

  return 0;
} catch (const marisa::Exception &ex) {
  std::cerr << ex.what() << std::endl;
  throw;
}
*/
<commit_msg>move tail tests<commit_after>// Copyright (c) 2010-2013, Susumu Yata
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

/*
#include <algorithm>
#include <cstring>
#include <sstream>

#include <marisa/grimoire/trie/config.h>
#include <marisa/grimoire/trie/header.h>
#include <marisa/grimoire/trie/key.h>
#include <marisa/grimoire/trie/range.h>
#include <marisa/grimoire/trie/tail.h>
#include <marisa/grimoire/trie/state.h>

#include "marisa-assert.h"

namespace {

void TestConfig() {
  TEST_START();

  marisa::grimoire::trie::Config config;

  ASSERT(config.num_tries() == MARISA_DEFAULT_NUM_TRIES);
  ASSERT(config.tail_mode() == MARISA_DEFAULT_TAIL);
  ASSERT(config.node_order() == MARISA_DEFAULT_ORDER);
  ASSERT(config.cache_level() == MARISA_DEFAULT_CACHE);

  config.parse(10 | MARISA_BINARY_TAIL | MARISA_LABEL_ORDER |
      MARISA_TINY_CACHE);

  ASSERT(config.num_tries() == 10);
  ASSERT(config.tail_mode() == MARISA_BINARY_TAIL);
  ASSERT(config.node_order() == MARISA_LABEL_ORDER);
  ASSERT(config.cache_level() == MARISA_TINY_CACHE);

  config.parse(0);

  ASSERT(config.num_tries() == MARISA_DEFAULT_NUM_TRIES);
  ASSERT(config.tail_mode() == MARISA_DEFAULT_TAIL);
  ASSERT(config.node_order() == MARISA_DEFAULT_ORDER);
  ASSERT(config.cache_level() == MARISA_DEFAULT_CACHE);

  TEST_END();
}

void TestHeader() {
  TEST_START();

  marisa::grimoire::trie::Header header;

  {
    marisa::grimoire::Writer writer;
    writer.open("trie-test.dat");
    header.write(writer);
  }

  {
    marisa::grimoire::Mapper mapper;
    mapper.open("trie-test.dat");
    header.map(mapper);
  }

  {
    marisa::grimoire::Reader reader;
    reader.open("trie-test.dat");
    header.read(reader);
  }

  TEST_END();
}

void TestKey() {
  TEST_START();

  marisa::grimoire::trie::Key key;

  ASSERT(key.ptr() == NULL);
  ASSERT(key.length() == 0);
  ASSERT(key.id() == 0);
  ASSERT(key.terminal() == 0);

  const char *str = "xyz";

  key.set_str(str, 3);
  key.set_weight(10.0F);
  key.set_id(20);

  ASSERT(key.ptr() == str);
  ASSERT(key.length() == 3);
  ASSERT(key[0] == 'x');
  ASSERT(key[1] == 'y');
  ASSERT(key[2] == 'z');
  ASSERT(key.weight() == 10.0F);
  ASSERT(key.id() == 20);

  key.set_terminal(30);
  ASSERT(key.terminal() == 30);

  key.substr(1, 2);

  ASSERT(key.ptr() == str + 1);
  ASSERT(key.length() == 2);
  ASSERT(key[0] == 'y');
  ASSERT(key[1] == 'z');

  marisa::grimoire::trie::Key key2;
  key2.set_str("abc", 3);

  ASSERT(key == key);
  ASSERT(key != key2);
  ASSERT(key > key2);
  ASSERT(key2 < key);

  marisa::grimoire::trie::ReverseKey r_key;

  ASSERT(r_key.ptr() == NULL);
  ASSERT(r_key.length() == 0);
  ASSERT(r_key.id() == 0);
  ASSERT(r_key.terminal() == 0);

  r_key.set_str(str, 3);
  r_key.set_weight(100.0F);
  r_key.set_id(200);

  ASSERT(r_key.ptr() == str);
  ASSERT(r_key.length() == 3);
  ASSERT(r_key[0] == 'z');
  ASSERT(r_key[1] == 'y');
  ASSERT(r_key[2] == 'x');
  ASSERT(r_key.weight() == 100.0F);
  ASSERT(r_key.id() == 200);

  r_key.set_terminal(300);
  ASSERT(r_key.terminal() == 300);

  r_key.substr(1, 2);

  ASSERT(r_key.ptr() == str);
  ASSERT(r_key.length() == 2);
  ASSERT(r_key[0] == 'y');
  ASSERT(r_key[1] == 'x');

  marisa::grimoire::trie::ReverseKey r_key2;
  r_key2.set_str("abc", 3);

  ASSERT(r_key == r_key);
  ASSERT(r_key != r_key2);
  ASSERT(r_key > r_key2);
  ASSERT(r_key2 < r_key);

  TEST_END();
}

void TestRange() {
  TEST_START();

  marisa::grimoire::trie::Range range;

  ASSERT(range.begin() == 0);
  ASSERT(range.end() == 0);
  ASSERT(range.key_pos() == 0);

  range.set_begin(1);
  range.set_end(2);
  range.set_key_pos(3);

  ASSERT(range.begin() == 1);
  ASSERT(range.end() == 2);
  ASSERT(range.key_pos() == 3);

  range = marisa::grimoire::trie::make_range(10, 20, 30);

  ASSERT(range.begin() == 10);
  ASSERT(range.end() == 20);
  ASSERT(range.key_pos() == 30);

  marisa::grimoire::trie::WeightedRange w_range;

  ASSERT(w_range.begin() == 0);
  ASSERT(w_range.end() == 0);
  ASSERT(w_range.key_pos() == 0);
  ASSERT(w_range.weight() == 0.0F);

  w_range.set_begin(10);
  w_range.set_end(20);
  w_range.set_key_pos(30);
  w_range.set_weight(40.0F);

  ASSERT(w_range.begin() == 10);
  ASSERT(w_range.end() == 20);
  ASSERT(w_range.key_pos() == 30);
  ASSERT(w_range.weight() == 40.0F);

  marisa::grimoire::trie::WeightedRange w_range2 =
      marisa::grimoire::trie::make_weighted_range(100, 200, 300, 400.0F);

  ASSERT(w_range2.begin() == 100);
  ASSERT(w_range2.end() == 200);
  ASSERT(w_range2.key_pos() == 300);
  ASSERT(w_range2.weight() == 400.0F);

  ASSERT(w_range < w_range2);
  ASSERT(w_range2 > w_range);

  TEST_END();
}

void TestEntry() {
  TEST_START();

  marisa::grimoire::trie::Entry entry;

  ASSERT(entry.ptr() == NULL);
  ASSERT(entry.length() == 0);
  ASSERT(entry.id() == 0);

  const char *str = "XYZ";

  entry.set_str(str, 3);
  entry.set_id(123);

  ASSERT(entry.ptr() == str);
  ASSERT(entry.length() == 3);
  ASSERT(entry[0] == 'Z');
  ASSERT(entry[1] == 'Y');
  ASSERT(entry[2] == 'X');
  ASSERT(entry.id() == 123);

  TEST_END();
}

void TestHistory() {
  TEST_START();

  marisa::grimoire::trie::History history;

  ASSERT(history.node_id() == 0);
  ASSERT(history.louds_pos() == 0);
  ASSERT(history.key_pos() == 0);
  ASSERT(history.link_id() == MARISA_INVALID_LINK_ID);
  ASSERT(history.key_id() == MARISA_INVALID_KEY_ID);

  history.set_node_id(100);
  history.set_louds_pos(200);
  history.set_key_pos(300);
  history.set_link_id(400);
  history.set_key_id(500);

  ASSERT(history.node_id() == 100);
  ASSERT(history.louds_pos() == 200);
  ASSERT(history.key_pos() == 300);
  ASSERT(history.link_id() == 400);
  ASSERT(history.key_id() == 500);

  TEST_END();
}

void TestState() {
  TEST_START();

  marisa::grimoire::trie::State state;

  ASSERT(state.key_buf().empty());
  ASSERT(state.history().empty());
  ASSERT(state.node_id() == 0);
  ASSERT(state.query_pos() == 0);
  ASSERT(state.history_pos() == 0);
  ASSERT(state.status_code() == marisa::grimoire::trie::MARISA_READY_TO_ALL);

  state.set_node_id(10);
  state.set_query_pos(100);
  state.set_history_pos(1000);
  state.set_status_code(
      marisa::grimoire::trie::MARISA_END_OF_PREDICTIVE_SEARCH);

  ASSERT(state.node_id() == 10);
  ASSERT(state.query_pos() == 100);
  ASSERT(state.history_pos() == 1000);
  ASSERT(state.status_code() ==
      marisa::grimoire::trie::MARISA_END_OF_PREDICTIVE_SEARCH);

  state.lookup_init();
  ASSERT(state.status_code() == marisa::grimoire::trie::MARISA_READY_TO_ALL);

  state.reverse_lookup_init();
  ASSERT(state.status_code() == marisa::grimoire::trie::MARISA_READY_TO_ALL);

  state.common_prefix_search_init();
  ASSERT(state.status_code() ==
      marisa::grimoire::trie::MARISA_READY_TO_COMMON_PREFIX_SEARCH);

  state.predictive_search_init();
  ASSERT(state.status_code() ==
      marisa::grimoire::trie::MARISA_READY_TO_PREDICTIVE_SEARCH);

  TEST_END();
}

}  // namespace

int main() try {
  TestConfig();
  TestHeader();
  TestKey();
  TestRange();
  TestEntry();
  TestTextTail();
  TestBinaryTail();
  TestHistory();
  TestState();

  return 0;
} catch (const marisa::Exception &ex) {
  std::cerr << ex.what() << std::endl;
  throw;
}
*/
<|endoftext|>