<commit_before>#[macro_export]
macro_rules! test_driver_read {
  ($tests:path) => {
    mod read {
      use super::*;

      use ::ardite::value::{Object, Value};
      use ::ardite::query::{Condition, SortRule, Range, Query};
      // TODO: Find a way to remove this dependency.
      use ::linear_map::LinearMap;

      fn val_a() -> Value {
        let mut object = Object::new();
        // TODO: Use more flexible insert.
        object.insert("a".to_owned(), Value::I64(1));
        object.insert("b".to_owned(), Value::I64(2));
        object.insert("c".to_owned(), Value::I64(3));
        object.insert("d".to_owned(), Value::I64(4));
        Value::Object(object)
      }

      fn val_b() -> Value {
        let mut object = Object::new();
        object.insert("b".to_owned(), Value::I64(2));
        object.insert("c".to_owned(), Value::I64(4));
        object.insert("hello".to_owned(), Value::String("world".to_owned()));
        object.insert("doc_a".to_owned(), val_a());
        Value::Object(object)
      }

      fn val_c() -> Value {
        let mut object = Object::new();
        object.insert("a".to_owned(), Value::I64(1));
        object.insert("c".to_owned(), Value::I64(3));
        object.insert("doc_b".to_owned(), val_b());
        Value::Object(object)
      }

      fn vals() -> Vec<Value> {
        let mut vals = Vec::new();
        vals.push(val_a());
        vals.push(val_b());
        vals.push(val_c());
        vals
      }

      #[test]
      fn test_read_all() {
        let driver = <$tests as $crate::Tests>::test_driver("read_all", vals());
        assert_eq!(
          driver.read(
            "read_all",
            Default::default(),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_b(), val_c()]
        );
      }

      #[test]
      fn test_read_condition() {
        let driver = <$tests as $crate::Tests>::test_driver("read_condition", vals());
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::False,
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![]
        );
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::And(vec![Condition::True, Condition::False]),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![]
        );
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::Or(vec![Condition::True, Condition::False]),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_b(), val_c()]
        );
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::Keys({
              let mut keys = LinearMap::new();
              keys.insert("c".to_owned(), Condition::Equal(Value::I64(3)));
              keys
            }),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_c()]
        );
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::Keys({
              let mut keys = LinearMap::new();
              keys.insert("doc_b".to_owned(), Condition::Keys({
                let mut keys = LinearMap::new();
                keys.insert("doc_a".to_owned(), Condition::Keys({
                  let mut keys = LinearMap::new();
                  keys.insert("d".to_owned(), Condition::Equal(Value::I64(4)));
                  keys
                }));
                keys
              }));
              keys
            }),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_c()]
        );
      }

      #[test]
      fn test_read_sort() {
        let driver = <$tests as $crate::Tests>::test_driver("read_sort", vals());
        assert_eq!(
          driver.read(
            "read_sort",
            Default::default(),
            vec![SortRule::new(vec!["c".to_owned()], true)],
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_c(), val_b()]
        );
        assert_eq!(
          driver.read(
            "read_sort",
            Default::default(),
            vec![SortRule::new(vec!["c".to_owned()], false)],
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_b(), val_a(), val_c()]
        );
      }

      #[test]
      fn test_read_range() {
        let driver = <$tests as $crate::Tests>::test_driver("read_range", vals());
        assert_eq!(
          driver.read(
            "read_range",
            Default::default(),
            Default::default(),
            Range::new(None, Some(2)),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_b()]
        );
        assert_eq!(
          driver.read(
            "read_range",
            Default::default(),
            Default::default(),
            Range::new(Some(1), Some(1)),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_b()]
        );
        assert_eq!(
          driver.read(
            "read_range",
            Default::default(),
            Default::default(),
            Range::new(Some(1), None),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_b(), val_c()]
        );
        assert_eq!(
          driver.read(
            "read_range",
            Default::default(),
            Default::default(),
            Range::new(Some(2), Some(40)),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_c()]
        );
      }

      #[test]
      fn test_read_query() {
        let driver = <$tests as $crate::Tests>::test_driver("read_query", vals());
        assert_eq!(
          driver.read(
            "read_query",
            Default::default(),
            Default::default(),
            Default::default(),
            Query::All
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_b(), val_c()]
        );
        assert_eq!(
          driver.read(
            "read_query",
            Default::default(),
            Default::default(),
            Default::default(),
            Query::Keys({
              let mut keys = LinearMap::new();
              keys.insert("a".to_owned(), Query::All);
              keys.insert("c".to_owned(), Query::All);
              keys.insert("hello".to_owned(), Query::All);
              keys.insert("doc_a".to_owned(), Query::Keys({
                let mut keys = LinearMap::new();
                keys.insert("b".to_owned(), Query::All);
                keys
              }));
              keys.insert("doc_b".to_owned(), Query::Keys({
                let mut keys = LinearMap::new();
                keys.insert("hello".to_owned(), Query::All);
                keys.insert("doc_a".to_owned(), Query::Keys({
                  let mut keys = LinearMap::new();
                  keys.insert("b".to_owned(), Query::All);
                  keys
                }));
                keys
              }));
              keys
            })
          ).unwrap().collect::<Vec<Value>>(),
          vec![
            {
              let mut object = Object::new();
              object.insert("a".to_owned(), Value::I64(1));
              object.insert("c".to_owned(), Value::I64(3));
              Value::Object(object)
            },
            {
              let mut object = Object::new();
              object.insert("c".to_owned(), Value::I64(4));
              object.insert("hello".to_owned(), Value::String("world".to_owned()));
              object.insert("doc_a".to_owned(), {
                let mut object = Object::new();
                object.insert("b".to_owned(), Value::I64(2));
                Value::Object(object)
              });
              Value::Object(object)
            },
            {
              let mut object = Object::new();
              object.insert("a".to_owned(), Value::I64(1));
              object.insert("c".to_owned(), Value::I64(3));
              object.insert("doc_b".to_owned(), {
                let mut object = Object::new();
                object.insert("hello".to_owned(), Value::String("world".to_owned()));
                object.insert("doc_a".to_owned(), {
                  let mut object = Object::new();
                  object.insert("b".to_owned(), Value::I64(2));
                  Value::Object(object)
                });
                Value::Object(object)
              });
              Value::Object(object)
            }
          ]
        );
      }
    }
  }
}
<commit_msg>fix(read): update key condition<commit_after>#[macro_export]
macro_rules! test_driver_read {
  ($tests:path) => {
    mod read {
      use super::*;

      use ::ardite::value::{Object, Value};
      use ::ardite::query::{Condition, SortRule, Range, Query};
      // TODO: Find a way to remove this dependency.
      use ::linear_map::LinearMap;

      fn val_a() -> Value {
        let mut object = Object::new();
        // TODO: Use more flexible insert.
        object.insert("a".to_owned(), Value::I64(1));
        object.insert("b".to_owned(), Value::I64(2));
        object.insert("c".to_owned(), Value::I64(3));
        object.insert("d".to_owned(), Value::I64(4));
        Value::Object(object)
      }

      fn val_b() -> Value {
        let mut object = Object::new();
        object.insert("b".to_owned(), Value::I64(2));
        object.insert("c".to_owned(), Value::I64(4));
        object.insert("hello".to_owned(), Value::String("world".to_owned()));
        object.insert("doc_a".to_owned(), val_a());
        Value::Object(object)
      }

      fn val_c() -> Value {
        let mut object = Object::new();
        object.insert("a".to_owned(), Value::I64(1));
        object.insert("c".to_owned(), Value::I64(3));
        object.insert("doc_b".to_owned(), val_b());
        Value::Object(object)
      }

      fn vals() -> Vec<Value> {
        let mut vals = Vec::new();
        vals.push(val_a());
        vals.push(val_b());
        vals.push(val_c());
        vals
      }

      #[test]
      fn test_read_all() {
        let driver = <$tests as $crate::Tests>::test_driver("read_all", vals());
        assert_eq!(
          driver.read(
            "read_all",
            Default::default(),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_b(), val_c()]
        );
      }

      #[test]
      fn test_read_condition() {
        let driver = <$tests as $crate::Tests>::test_driver("read_condition", vals());
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::False,
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![]
        );
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::And(vec![Condition::True, Condition::False]),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![]
        );
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::Or(vec![Condition::True, Condition::False]),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_b(), val_c()]
        );
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::Key("c".to_owned(), Box::new(Condition::Equal(Value::I64(3)))),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_c()]
        );
        assert_eq!(
          driver.read(
            "read_condition",
            Condition::Key(
              "doc_b".to_owned(),
              Box::new(Condition::Key(
                "doc_a".to_owned(),
                Box::new(Condition::Key(
                  "d".to_owned(),
                  Box::new(Condition::Equal(Value::I64(4)))
                ))
              ))
            ),
            Default::default(),
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_c()]
        );
      }

      #[test]
      fn test_read_sort() {
        let driver = <$tests as $crate::Tests>::test_driver("read_sort", vals());
        assert_eq!(
          driver.read(
            "read_sort",
            Default::default(),
            vec![SortRule::new(vec!["c".to_owned()], true)],
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_c(), val_b()]
        );
        assert_eq!(
          driver.read(
            "read_sort",
            Default::default(),
            vec![SortRule::new(vec!["c".to_owned()], false)],
            Default::default(),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_b(), val_a(), val_c()]
        );
      }

      #[test]
      fn test_read_range() {
        let driver = <$tests as $crate::Tests>::test_driver("read_range", vals());
        assert_eq!(
          driver.read(
            "read_range",
            Default::default(),
            Default::default(),
            Range::new(None, Some(2)),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_b()]
        );
        assert_eq!(
          driver.read(
            "read_range",
            Default::default(),
            Default::default(),
            Range::new(Some(1), Some(1)),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_b()]
        );
        assert_eq!(
          driver.read(
            "read_range",
            Default::default(),
            Default::default(),
            Range::new(Some(1), None),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_b(), val_c()]
        );
        assert_eq!(
          driver.read(
            "read_range",
            Default::default(),
            Default::default(),
            Range::new(Some(2), Some(40)),
            Default::default()
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_c()]
        );
      }

      #[test]
      fn test_read_query() {
        let driver = <$tests as $crate::Tests>::test_driver("read_query", vals());
        assert_eq!(
          driver.read(
            "read_query",
            Default::default(),
            Default::default(),
            Default::default(),
            Query::All
          ).unwrap().collect::<Vec<Value>>(),
          vec![val_a(), val_b(), val_c()]
        );
        assert_eq!(
          driver.read(
            "read_query",
            Default::default(),
            Default::default(),
            Default::default(),
            Query::Keys({
              let mut keys = LinearMap::new();
              keys.insert("a".to_owned(), Query::All);
              keys.insert("c".to_owned(), Query::All);
              keys.insert("hello".to_owned(), Query::All);
              keys.insert("doc_a".to_owned(), Query::Keys({
                let mut keys = LinearMap::new();
                keys.insert("b".to_owned(), Query::All);
                keys
              }));
              keys.insert("doc_b".to_owned(), Query::Keys({
                let mut keys = LinearMap::new();
                keys.insert("hello".to_owned(), Query::All);
                keys.insert("doc_a".to_owned(), Query::Keys({
                  let mut keys = LinearMap::new();
                  keys.insert("b".to_owned(), Query::All);
                  keys
                }));
                keys
              }));
              keys
            })
          ).unwrap().collect::<Vec<Value>>(),
          vec![
            {
              let mut object = Object::new();
              object.insert("a".to_owned(), Value::I64(1));
              object.insert("c".to_owned(), Value::I64(3));
              Value::Object(object)
            },
            {
              let mut object = Object::new();
              object.insert("c".to_owned(), Value::I64(4));
              object.insert("hello".to_owned(), Value::String("world".to_owned()));
              object.insert("doc_a".to_owned(), {
                let mut object = Object::new();
                object.insert("b".to_owned(), Value::I64(2));
                Value::Object(object)
              });
              Value::Object(object)
            },
            {
              let mut object = Object::new();
              object.insert("a".to_owned(), Value::I64(1));
              object.insert("c".to_owned(), Value::I64(3));
              object.insert("doc_b".to_owned(), {
                let mut object = Object::new();
                object.insert("hello".to_owned(), Value::String("world".to_owned()));
                object.insert("doc_a".to_owned(), {
                  let mut object = Object::new();
                  object.insert("b".to_owned(), Value::I64(2));
                  Value::Object(object)
                });
                Value::Object(object)
              });
              Value::Object(object)
            }
          ]
        );
      }
    }
  }
}
<|endoftext|>


<commit_before>use std::io::fs;
use std::path::posix::Path;
use std::os::homedir;
#[cfg(test)] use test_helper::{cleanup_dir,random_name};

static MUXED_NAME_STR: &'static str = "muxed";
#[cfg(test)] static MUXED_PATH: Path = Path::new(format!("/tmp/.{}/", &MUXED_NAME_STR.to_string()));
//#[cfg(not_test)] static MUXED_DIR: Path = Path::new(format!("{}/.{}/", root::homedir_string(), &DEFAULT_MUXED_DIR.to_string()));

/// Create the muxed directory and return the path if creation is successful.
pub fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

/// Return the users current homedir as a string.
pub fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

pub fn muxed_dir() -> Path {
    match MUXED_DIR.exists() {
        true  => MUXED_DIR,
        false => create_muxed_dir(MUXED_DIR)
    }
}

#[test]
fn muxed_dir_exists_returns_false() {
    assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
    let dir = random_name();
    create_muxed_dir(&dir);
    assert!(muxed_dir_exists(&dir));

    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    cleanup_dir(muxed_path);
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    cleanup_dir(muxed_path);
}
<commit_msg>Better output message. Cleanup the Signature to accept a Path instead. This conforms to using the new static Path method.<commit_after>use std::io::fs;
use std::path::posix::Path;
use std::os::homedir;
#[cfg(test)] use test_helper::{cleanup_dir,random_name};

static MUXED_NAME_STR: &'static str = "muxed";
#[cfg(test)] static MUXED_PATH: Path = Path::new(format!("/tmp/.{}/", &MUXED_NAME_STR.to_string()));
//#[cfg(not_test)] static MUXED_DIR: Path = Path::new(format!("{}/.{}/", root::homedir_string(), &DEFAULT_MUXED_DIR.to_string()));

/// Create the muxed directory and return the path if creation is successful.
pub fn create_muxed_dir(name: &Path) -> Path {
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (),
        Err(_e) => println!("Failed to create muxed directory: {}", path.filename())
    }

    path.clone()
}

/// Return the users current homedir as a string.
pub fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

pub fn muxed_dir() -> Path {
    match MUXED_DIR.exists() {
        true  => MUXED_DIR,
        false => create_muxed_dir(MUXED_DIR)
    }
}

#[test]
fn muxed_dir_exists_returns_false() {
    assert!(!muxed_dir_exists(&random_name()));
}

#[test]
fn muxed_dir_exists_returns_true() {
    let dir = random_name();
    create_muxed_dir(&dir);
    assert!(muxed_dir_exists(&dir));

    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    cleanup_dir(muxed_path);
}

#[test]
fn creates_muxed_dir() {
    let dir = random_name();
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    cleanup_dir(muxed_path);
}
<|endoftext|>


<commit_before>use super::Rdx;

use std::slice;
use std::fmt;

enum Node<T> where T: Rdx {
    Inner(NodeInner<T>),
    Child(T),
    Free,
}

struct NodeInner<T> where T: Rdx {
    round: usize,
    children: Vec<Node<T>>,
}

impl<T> NodeInner<T> where T: Rdx {
    fn new(round: usize, nbuckets: usize) -> NodeInner<T> {
        let mut children = Vec::with_capacity(nbuckets);
        for _ in 0..nbuckets {
            children.push(Node::Free);
        }
        NodeInner {
            round: round,
            children: children,
        }
    }

    fn insert(&mut self, x: T) {
        let bucket = x.get_bucket(self.round - 1);

        if self.round > 1 {
            let clen = self.children.len();
            let replace = match self.children[bucket] {
                Node::Free => {
                    let mut inner = NodeInner::new(self.round - 1, clen);
                    inner.insert(x);
                    Some(inner)
                },
                Node::Inner(ref mut inner) => {
                    inner.insert(x);
                    None
                },
                Node::Child(_) => unreachable!(),
            };

            if let Some(inner) = replace {
                self.children[bucket] = Node::Inner(inner);
            }
        } else {
            let alloc = match self.children[bucket] {
                Node::Free => true,
                Node::Child(_) => false,
                Node::Inner(_) => unreachable!(),
            };

            if alloc {
                self.children[bucket] = Node::Child(x);
            } else {
                match self.children[bucket] {
                    Node::Child(ref mut y) => *y = x,  // XXX: is that a good idea?
                    _ => unreachable!(),
                }
            }
        }
    }

    fn nnodes(&self) -> usize {
        let mut result = 1;
        for c in self.children.iter() {
            match c {
                &Node::Inner(ref inner) => {
                    result += inner.nnodes();
                },
                _ => {}
            }
        }
        result
    }
}

pub struct RdxTree<T> where T: Rdx {
    root: Node<T>,
}

impl<T> RdxTree<T> where T: Rdx {
    pub fn new() -> RdxTree<T> {
        let rounds = <T as Rdx>::cfg_nrounds();
        let buckets = <T as Rdx>::cfg_nbuckets();
        RdxTree {
            root: Node::Inner(NodeInner::<T>::new(rounds, buckets)),
        }
    }

    pub fn insert(&mut self, x: T) {
        match self.root {
            Node::Inner(ref mut inner) => {
                inner.insert(x);
            },
            _ => {
                unreachable!();
            }
        }
    }

    pub fn iter<'a>(&'a self) -> RdxTreeIter<'a, T> {
        let mut iters = Vec::new();
        match self.root {
            Node::Inner(ref inner) => {
                iters.push(inner.children.iter());
            },
            _ => unreachable!(),
        }
        RdxTreeIter {
            iters: iters,
        }
    }

    pub fn nnodes(&self) -> usize {
        match self.root {
            Node::Inner(ref inner) => {
                inner.nnodes()
            },
            _ => {
                unreachable!()
            }
        }
    }
}

pub struct RdxTreeIter<'a, T> where T: Rdx + 'a {
    iters: Vec<slice::Iter<'a, Node<T>>>,
}

impl<'a, T> Iterator for RdxTreeIter<'a, T> where T: Rdx + 'a {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        let mut result: Option<&'a T> = None;

        while self.iters.len() > 0 && result.is_none() {
            let mut push: Option<slice::Iter<'a, Node<T>>> = None;
            let mut pop = false;

            if let Some(mut it) = self.iters.last_mut() {
                match it.next() {
                    Some(&Node::Free) => {},
                    Some(&Node::Child(ref x)) => {
                        result = Some(x);
                    },
                    Some(&Node::Inner(ref inner)) => {
                        push = Some(inner.children.iter());
                    },
                    None => {
                        pop = true;
                    },
                }
            } else {
                unreachable!();
            }

            if pop {
                self.iters.pop();
            } else if let Some(next) = push {
                self.iters.push(next);
            }
        }

        result
    }
}

fn print_node<T>(node: &Node<T>, depth: usize) where T: fmt::Display + Rdx {
    let prefix: String = (0..depth).map(|_| ' ').collect();
    match *node {
        Node::Inner(ref inner) => {
            for (i, c) in inner.children.iter().enumerate() {
                println!("{}{}:", prefix, i);
                print_node(c, depth + 1);
            }
        },
        Node::Child(ref x) => {
            println!("{}=> {}", prefix, x);
        },
        Node::Free => {
            println!("{}X", prefix);
        },
    }
}

fn print_tree<T>(tree: &RdxTree<T>) where T: fmt::Display + Rdx {
    print_node(&tree.root, 0);
}

#[test]
fn test_insert() {
    let mut tree: RdxTree<u32> = RdxTree::new();
    tree.insert(1);
    tree.insert(22);
    tree.insert(2);
    tree.insert(1024);
    tree.insert(0);

    let should = vec![0, 1, 2, 22, 1024];
    let is: Vec<u32> = tree.iter().cloned().collect();
    assert_eq!(should, is);
    assert_eq!(tree.nnodes(), 11);
}
<commit_msg>implement tree pruning<commit_after>use super::Rdx;

use std::cell::RefCell;
use std::marker::PhantomData;
use std::fmt;
use std::rc::Rc;

#[derive(Clone)]
enum Node<T> where T: Clone + Rdx {
    Inner(Rc<RefCell<NodeInner<T>>>),
    Pruned(Rc<RefCell<NodePruned<T>>>),
    Child(T),
    Free,
}

#[derive(Clone)]
enum NodeLimited<T> where T: Clone + Rdx {
    Inner(Rc<RefCell<NodeInner<T>>>),
    Child(T),
}

impl<'a, T> From<&'a NodeLimited<T>> for Node<T> where T: Clone + Rdx {
    fn from(obj: &'a NodeLimited<T>) -> Node<T> {
        match obj {
            &NodeLimited::Inner(ref inner) => Node::Inner(inner.clone()),
            &NodeLimited::Child(ref x) => Node::Child(x.clone()),
        }
    }
}

#[derive(Clone)]
struct NodeInner<T> where T: Clone + Rdx {
    round: usize,
    children: Vec<Node<T>>,
}

#[derive(Clone)]
struct NodePruned<T> where T: Clone + Rdx {
    round: usize,
    nbuckets: usize,
    buckets: Vec<usize>,
    child: NodeLimited<T>,
}

impl<T> NodeInner<T> where T: Clone + Rdx {
    fn new(round: usize, nbuckets: usize) -> NodeInner<T> {
        let mut children = Vec::with_capacity(nbuckets);
        for _ in 0..nbuckets {
            children.push(Node::Free);
        }
        NodeInner {
            round: round,
            children: children,
        }
    }

    fn insert(&mut self, x: T) {
        let bucket = x.get_bucket(self.round - 1);

        if self.round > 1 {
            let clen = self.children.len();
            let replace = match self.children[bucket] {
                Node::Free => {
                    let pruned = Rc::new(RefCell::new(NodePruned::new(self.round - 1, clen, x)));
                    Some(Node::Pruned(pruned))
                },
                Node::Inner(ref mut inner) => {
                    inner.borrow_mut().insert(x);
                    None
                },
                Node::Pruned(ref mut pruned) => {
                    Some(pruned.borrow().insert_or_split(x))
                }
                Node::Child(_) => unreachable!(),
            };

            if let Some(obj) = replace {
                self.children[bucket] = obj;
            }
        } else {
            let alloc = match self.children[bucket] {
                Node::Free => true,
                Node::Child(_) => false,
                Node::Inner(_) => unreachable!(),
                Node::Pruned(_) => unreachable!(),
            };

            if alloc {
                self.children[bucket] = Node::Child(x);
            } else {
                match self.children[bucket] {
                    Node::Child(ref mut y) => *y = x,  // XXX: is that a good idea?
                    _ => unreachable!(),
                }
            }
        }
    }

    fn nnodes(&self) -> (usize, usize, usize, usize) {
        let mut result = (1, 0, 0, 0);
        for c in self.children.iter() {
            match c {
                &Node::Inner(ref inner) => {
                    let tmp = inner.borrow().nnodes();
                    result.0 += tmp.0;
                    result.1 += tmp.1;
                    result.2 += tmp.2;
                    result.3 += tmp.3;
                },
                &Node::Pruned(ref pruned) => {
                    let tmp = pruned.borrow().nnodes();
                    result.0 += tmp.0;
                    result.1 += tmp.1;
                    result.2 += tmp.2;
                    result.3 += tmp.3;
                },
                &Node::Child(_) => {
                    result.2 += 1;
                },
                &Node::Free => {
                    result.3 += 1;
                },
            }
        }
        result
    }
}

impl<T> NodePruned<T> where T: Clone + Rdx {
    fn new(round: usize, nbuckets: usize, x: T) -> NodePruned<T> {
        let mut buckets = Vec::with_capacity(round);
        for i in 0..round {
            let r = round - i;
            let bucket = x.get_bucket(r - 1);
            buckets.push(bucket);
        }
        let child = NodeLimited::Child(x);
        NodePruned {
            round: round,
            nbuckets: nbuckets,
            buckets: buckets,
            child: child,
        }
    }

    fn insert_or_split(&self, x: T) -> Node<T> {
        for i in 0..self.buckets.len() {
            let r = self.round - i;
            let bucket_y = self.buckets[i];
            let bucket_x = x.get_bucket(r - 1);

            if bucket_x != bucket_y {
                // === outcome a: split ===
                //
                //     [head][middle/diff][tail]
                //
                // becomes
                //
                //                     |-[tail1]
                //     [head]-[middle]-|
                //                     |-[tail2]
                //

                // split head, middle and tail
                let mut buckets_head = self.buckets.clone();
                let buckets_tail = buckets_head.split_off(i + 1);
                buckets_head.pop();  // remove middle part

                // inner node = middle part
                let mut inner = NodeInner::new(self.round - buckets_head.len(), self.nbuckets);

                // add old tail and new branch to inner node
                if buckets_tail.is_empty() {
                    inner.children[bucket_y] = (&self.child).into();
                } else {
                    let tail = Rc::new(RefCell::new(NodePruned {
                        round: self.round - i - 1,
                        nbuckets: self.nbuckets,
                        buckets: buckets_tail,
                        child: self.child.clone(),
                    }));
                    inner.children[bucket_y] = Node::Pruned(tail);
                }
                inner.insert(x);

                // either return inner node (when head is empty) or create new head
                if buckets_head.is_empty() {
                    return Node::Inner(Rc::new(RefCell::new(inner)));
                } else {
                    let head = Rc::new(RefCell::new(NodePruned {
                        round: self.round,
                        nbuckets: self.nbuckets,
                        buckets: buckets_head,
                        child: NodeLimited::Inner(Rc::new(RefCell::new(inner))),
                    }));
                    return Node::Pruned(head);
                }
            }
        }

        // === outcome b: insert ===
        // INFO: Copying seems to be faster than returning an Option and do the change in-place.
        //       I don't know why this is the case.
        let mut cpy = self.clone();
        match cpy.child {
            NodeLimited::Inner(ref mut inner) => {
                inner.borrow_mut().insert(x);
            },
            NodeLimited::Child(ref mut y) => {
                *y = x;
            },
        }
        Node::Pruned(Rc::new(RefCell::new(cpy)))
    }

    fn nnodes(&self) -> (usize, usize, usize, usize) {
        let mut result = (0, 1, 0, 0);
        match self.child {
            NodeLimited::Inner(ref inner) => {
                let tmp = inner.borrow().nnodes();
                result.0 += tmp.0;
                result.1 += tmp.1;
                result.2 += tmp.2;
                result.3 += tmp.3;
            },
            NodeLimited::Child(_) => {
                result.2 += 1;
            },
        }
        result
    }
}

pub struct RdxTree<T> where T: Clone + Rdx {
    root: Node<T>,
}

impl<T> RdxTree<T> where T: Clone + Rdx {
    pub fn new() -> RdxTree<T> {
        let rounds = <T as Rdx>::cfg_nrounds();
        let buckets = <T as Rdx>::cfg_nbuckets();
        RdxTree {
            root: Node::Inner(
                Rc::new(RefCell::new(NodeInner::<T>::new(rounds, buckets)))
            ),
        }
    }

    pub fn insert(&mut self, x: T) {
        match self.root {
            Node::Inner(ref mut inner) => {
                inner.borrow_mut().insert(x);
            },
            _ => {
                unreachable!();
            }
        }
    }

    pub fn iter<'a>(&'a self) -> RdxTreeIter<'a, T> {
        let mut iters = Vec::new();
        match self.root {
            Node::Inner(ref inner) => {
                iters.push((inner.clone(), 0));
            },
            _ => unreachable!(),
        }
        RdxTreeIter {
            iters: iters,
            phantom: PhantomData,
        }
    }

    pub fn nnodes(&self) -> (usize, usize, usize, usize) {
        match self.root {
            Node::Inner(ref inner) => {
                inner.borrow().nnodes()
            },
            _ => {
                unreachable!()
            }
        }
    }
}

pub struct RdxTreeIter<'a, T> where T: Clone + Rdx + 'a {
    iters: Vec<(Rc<RefCell<NodeInner<T>>>, usize)>,  // do not work with iterators directly since we need a checked but dynamic borrow
    phantom: PhantomData<&'a RdxTree<T>>,            // keep tree borrow intact
}

impl<'a, T> Iterator for RdxTreeIter<'a, T> where T: Clone + Rdx + 'a {
    type Item = T;  // XXX: do not copy!

    fn next(&mut self) -> Option<Self::Item> {
        let mut result: Option<T> = None;

        while self.iters.len() > 0 && result.is_none() {
            let mut push: Option<Rc<RefCell<NodeInner<T>>>> = None;
            let mut pop = false;

            if let Some(pair) = self.iters.last_mut() {
                let &mut (ref rc, ref mut i) = pair;
                let borrow = rc.borrow();
                if *i >= borrow.children.len() {
                    pop = true;
                } else {
                    match borrow.children[*i] {
                        Node::Free => {},
                        Node::Child(ref x) => {
                            result = Some(x.clone());
                        },
                        Node::Inner(ref inner) => {
                            push = Some(inner.clone());
                        },
                        Node::Pruned(ref pruned) => {
                            match pruned.borrow().child {
                                NodeLimited::Child(ref x) => {
                                    result = Some(x.clone());
                                },
                                NodeLimited::Inner(ref inner) => {
                                    push = Some(inner.clone());
                                },
                            }
                        },
                    }

                    *i += 1;
                }
            } else {
                unreachable!();
            }

            if pop {
                self.iters.pop();
            } else if let Some(next) = push {
                self.iters.push((next, 0));
            }
        }

        result
    }
}

fn print_node<T>(node: &Node<T>, depth: usize) where T: Clone + fmt::Display + Rdx {
    let prefix: String = (0..depth).map(|_| ' ').collect();
    match *node {
        Node::Inner(ref inner) => {
            for (i, c) in inner.borrow().children.iter().enumerate() {
                println!("{}{}:", prefix, i);
                print_node(c, depth + 1);
            }
        },
        Node::Pruned(ref pruned) => {
            let borrowed = pruned.borrow();
            println!("{}P: [{:?}]", prefix, borrowed.buckets);
            let c = (&(borrowed.child)).into();
            print_node(&c, depth + borrowed.buckets.len());
        },
        Node::Child(ref x) => {
            println!("{}=> {}", prefix, x);
        },
        Node::Free => {
            println!("{}X", prefix);
        },
    }
}

fn print_tree<T>(tree: &RdxTree<T>) where T: Clone + fmt::Display + Rdx {
    print_node(&tree.root, 0);
}

#[test]
fn test_insert() {
    let mut tree: RdxTree<u32> = RdxTree::new();
    tree.insert(1);
    tree.insert(22);
    tree.insert(2);
    tree.insert(1024);
    tree.insert(0);

    let should = vec![0, 1, 2, 22, 1024];
    let is: Vec<u32> = tree.iter().collect();
    assert_eq!(should, is);
    assert_eq!(tree.nnodes(), (4, 3, 5, 56));
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Error, Formatter};
use std::rc::Rc;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Tree<T> {
    Tip,
    Node(Rc<Tree<T>>, T, Rc<Tree<T>>),
}

use tree::Tree::{Node, Tip};

impl<T: Display> Display for Tree<T> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        fn _loop<T: Display>(f: &mut Formatter, t: &Tree<T>, right: bool, indent: &str) -> Result<(), Error> {
            match *t {
                Node(ref l, ref v, ref r) => {
                    try!(_loop(f, r, true, &(indent.to_string() + if right { "        " } else { " |      " })));

                    try!(write!(f, "{}", indent));
                    try!(if right { write!(f, "{}", " /") } else { write!(f, "{}", " \\") });
                    try!(write!(f, "{}", "----- "));

                    try!(writeln!(f, "{}", *v));

                    _loop(f, l, false, &(indent.to_string() + if right { " |      " } else { "        " }))
                },
                Tip => Result::Ok(())
            }
        }

        match *self {
            Node(ref l, ref v, ref r) => {
                try!(_loop(f, r, true, ""));
                try!(writeln!(f, "{}", *v));
                _loop(f, l, false, "")
            }
            Tip => Result::Ok(())
        }
    }
}

impl<T: Ord> Tree<T> {
    // Exercise 2.2:
    // only performs at most d + 1 comparisons, where d is the depth of the tree
    pub fn member2(&self, x: T) -> bool {
        match *self {
            Tip => false,
            Node(_, ref v, _) => {
                fn member_aux<T: Ord>(t: &Tree<T>, x: T, c: &T) -> bool {
                    match *t {
                        Tip => x == *c,
                        Node(ref l, ref v, ref r) =>
                            if x < *v {
                                member_aux(l, x, c)
                            } else {
                                member_aux(r, x, v)
                            }
                    }
                }

                member_aux(self, x, v)
            },
        }
    }
}
<commit_msg>pretty print tree vertically<commit_after>use std::cmp::max;
use std::fmt::{Display, Error, Formatter};
use std::num::Int;
use std::rc::Rc;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Tree<T> {
    Tip,
    Node(Rc<Tree<T>>, T, Rc<Tree<T>>),
}

use tree::Tree::{Node, Tip};

impl<T: Display + PartialEq + Clone> Display for Tree<T> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        fn depth<T>(t: &Tree<T>) -> usize {
            match *t {
                Tip => 0,
                Node(ref l, _, ref r) => 1 + max(depth(l), depth(r))
            }
        }

        fn print_whitespace(n: usize, f: &mut Formatter) -> Result<(), Error> {
            for _ in (0..n) {
                try!(write!(f, " "));
            }
            Result::Ok(())
        }

        fn aux<T: Clone + Display + PartialEq>(nodes: Vec<Tree<T>>, level: usize, max_level: usize, f: &mut Formatter) -> Result<(), Error> {
            if nodes.iter().all(|n| *n == Tip) { return Result::Ok(()) }

            let floor = max_level - level;
            let edge_lines = 2.pow(max(floor - 1, 0)) as usize;
            let first_spaces = 2.pow(floor) - 1 as usize;
            let between_spaces = 2.pow(floor + 1) - 1 as usize;

            try!(print_whitespace(first_spaces, f));

            let new_nodes =
                nodes.iter().fold(vec![], |mut acc, n| {
                    let ret =
                        match *n {
                            Node(ref l, ref v, ref r) => {
                                write!(f, "{}", v);
                                acc.push((**l).clone());
                                acc.push((**r).clone());
                                acc
                            },
                            Tip => {
                                write!(f, " ");
                                acc.push(Tip);
                                acc.push(Tip);
                                acc
                            }
                        };

                    print_whitespace(between_spaces, f);

                    ret
                });

            try!(writeln!(f, ""));

            for i in (1..(edge_lines + 1)) {
                for node in nodes.iter() {
                    try!(print_whitespace(first_spaces - i, f));
                    match *node {
                        Tip => { try!(print_whitespace(edge_lines + edge_lines + i + 1, f)); },
                        Node(ref l, _, ref r) => {
                            if **l != Tip { try!(write!(f, "/")); }
                            else { try!(write!(f, " ")); }

                            try!(print_whitespace(i + i - 1, f));

                            if **r != Tip { try!(write!(f, "\\")); }
                            else { try!(write!(f, " ")); }

                            try!(print_whitespace(edge_lines + edge_lines - 1, f));
                        }
                    }
                }

                try!(writeln!(f, ""));
            }

            aux(new_nodes, level + 1, max_level, f)
        }

        aux(vec![(*self).clone()], 1, depth(self), f)
    }
}

impl<T: Ord> Tree<T> {
    // Exercise 2.2:
    // only performs at most d + 1 comparisons, where d is the depth of the tree
    pub fn member2(&self, x: T) -> bool {
        match *self {
            Tip => false,
            Node(_, ref v, _) => {
                fn member_aux<T: Ord>(t: &Tree<T>, x: T, c: &T) -> bool {
                    match *t {
                        Tip => x == *c,
                        Node(ref l, ref v, ref r) =>
                            if x < *v {
                                member_aux(l, x, c)
                            } else {
                                member_aux(r, x, v)
                            }
                    }
                }

                member_aux(self, x, v)
            },
        }
    }
}
<|endoftext|>


<commit_before>use super::{Dictionary, Stream};
use std::collections::BTreeMap;
use std::io::{Cursor, Read};

use crate::{Error, Result};

#[derive(Debug, Clone)]
pub struct Xref {
	/// Entries for indirect object.
	pub entries: BTreeMap<u32, XrefEntry>,

	/// Total number of entries (including free entries), equal to the highest object number plus 1.
	pub size: u32,
}

#[derive(Debug, Clone)]
pub enum XrefEntry {
	Free,
	Normal { offset: u32, generation: u16 },
	Compressed { container: u32, index: u16 },
}

impl Xref {
	pub fn new(size: u32) -> Xref {
		Xref { entries: BTreeMap::new(), size }
	}

	pub fn get(&self, id: u32) -> Option<&XrefEntry> {
		self.entries.get(&id)
	}

	pub fn insert(&mut self, id: u32, entry: XrefEntry) {
		self.entries.insert(id, entry);
	}

	pub fn extend(&mut self, xref: Xref) {
		for (id, entry) in xref.entries {
			self.entries.entry(id).or_insert(entry);
		}
	}

	pub fn clear(&mut self) {
		self.entries.clear()
	}

	pub fn max_id(&self) -> u32 {
		match self.entries.keys().max() {
			Some(&id) => id,
			None => 0,
		}
	}
}

use crate::object::Object;
use self::XrefEntry::*;
impl XrefEntry {
	pub fn is_normal(&self) -> bool {
		match *self {
			Normal { .. } => true,
			_ => false,
		}
	}

	pub fn is_compressed(&self) -> bool {
		match *self {
			Compressed { .. } => true,
			_ => false,
		}
	}
}

pub fn decode_xref_stream(mut stream: Stream) -> Result<(Xref, Dictionary)> {
	stream.decompress();
	let mut dict = stream.dict;
	let mut reader = Cursor::new(stream.content);
	let size = dict.get(b"Size").and_then(Object::as_i64).ok_or(Error::Trailer)?;
	let mut xref = Xref::new(size as u32);
	{
		let section_indice = dict
			.get(b"Index")
			.and_then(Object::as_array)
			.map(|array| array.iter().map(|n| n.as_i64().unwrap()).collect())
			.unwrap_or_else(|| vec![0, size]);
		let field_widths: Vec<usize> = dict
			.get(b"W")
			.and_then(Object::as_array)
			.map(|array| array.iter().map(|n| n.as_i64().unwrap() as usize).collect())
			.ok_or(Error::Trailer)?;
		let mut bytes1 = vec![0_u8; field_widths[0]];
		let mut bytes2 = vec![0_u8; field_widths[1]];
		let mut bytes3 = vec![0_u8; field_widths[2]];

		for i in 0..section_indice.len() / 2 {
			let start = section_indice[2 * i];
			let count = section_indice[2 * i + 1];

			for j in 0..count {
				let entry_type = if !bytes1.is_empty() { read_big_endian_interger(&mut reader, bytes1.as_mut_slice()) } else { 1 };
				match entry_type {
					0 => {
						//free object
						read_big_endian_interger(&mut reader, bytes2.as_mut_slice());
						read_big_endian_interger(&mut reader, bytes3.as_mut_slice());
					}
					1 => {
						//normal object
						let offset = read_big_endian_interger(&mut reader, bytes2.as_mut_slice());
						let generation = if !bytes3.is_empty() { read_big_endian_interger(&mut reader, bytes3.as_mut_slice()) } else { 0 } as u16;
						xref.insert(
							(start + j) as u32,
							XrefEntry::Normal {
								offset,
								generation,
							},
						);
					}
					2 => {
						//compressed object
						let container = read_big_endian_interger(&mut reader, bytes2.as_mut_slice());
						let index = read_big_endian_interger(&mut reader, bytes3.as_mut_slice()) as u16;
						xref.insert((start + j) as u32, XrefEntry::Compressed { container, index });
					}
					_ => {}
				}
			}
		}
	}
	dict.remove(b"Length");
	dict.remove(b"W");
	dict.remove(b"Index");
	Ok((xref, dict))
}

fn read_big_endian_interger(reader: &mut Cursor<Vec<u8>>, buffer: &mut [u8]) -> u32 {
	reader.read_exact(buffer).unwrap();
	let mut value = 0;
	for &mut byte in buffer {
		value = (value << 8) + u32::from(byte);
	}
	value
}
<commit_msg>Remove more panic paths in xref parsing.<commit_after>use super::{Dictionary, Stream};
use std::collections::BTreeMap;
use std::io::{Cursor, Read};

use crate::{Error, Result};
use crate::error::XrefError;

#[derive(Debug, Clone)]
pub struct Xref {
	/// Entries for indirect object.
	pub entries: BTreeMap<u32, XrefEntry>,

	/// Total number of entries (including free entries), equal to the highest object number plus 1.
	pub size: u32,
}

#[derive(Debug, Clone)]
pub enum XrefEntry {
	Free,
	Normal { offset: u32, generation: u16 },
	Compressed { container: u32, index: u16 },
}

impl Xref {
	pub fn new(size: u32) -> Xref {
		Xref { entries: BTreeMap::new(), size }
	}

	pub fn get(&self, id: u32) -> Option<&XrefEntry> {
		self.entries.get(&id)
	}

	pub fn insert(&mut self, id: u32, entry: XrefEntry) {
		self.entries.insert(id, entry);
	}

	pub fn extend(&mut self, xref: Xref) {
		for (id, entry) in xref.entries {
			self.entries.entry(id).or_insert(entry);
		}
	}

	pub fn clear(&mut self) {
		self.entries.clear()
	}

	pub fn max_id(&self) -> u32 {
		match self.entries.keys().max() {
			Some(&id) => id,
			None => 0,
		}
	}
}

use crate::object::Object;
use self::XrefEntry::*;
impl XrefEntry {
	pub fn is_normal(&self) -> bool {
		match *self {
			Normal { .. } => true,
			_ => false,
		}
	}

	pub fn is_compressed(&self) -> bool {
		match *self {
			Compressed { .. } => true,
			_ => false,
		}
	}
}

pub fn decode_xref_stream(mut stream: Stream) -> Result<(Xref, Dictionary)> {
	stream.decompress();
	let mut dict = stream.dict;
	let mut reader = Cursor::new(stream.content);
	let size = dict.get(b"Size").and_then(Object::as_i64).ok_or(Error::Xref(XrefError::Parse))?;
	let mut xref = Xref::new(size as u32);
	{
		let section_indice = dict
			.get(b"Index")
			.and_then(parse_integer_array)
			.unwrap_or_else(|| vec![0, size]);
		let field_widths = dict
			.get(b"W")
			.and_then(parse_integer_array)
			.ok_or(Error::Xref(XrefError::Parse))?;

		if field_widths.len() < 3 {
			return Err(Error::Xref(XrefError::Parse));
		}

		let mut bytes1 = vec![0_u8; field_widths[0] as usize];
		let mut bytes2 = vec![0_u8; field_widths[1] as usize];
		let mut bytes3 = vec![0_u8; field_widths[2] as usize];

		for i in 0..section_indice.len() / 2 {
			let start = section_indice[2 * i];
			let count = section_indice[2 * i + 1];

			for j in 0..count {
				let entry_type = if !bytes1.is_empty() { read_big_endian_integer(&mut reader, bytes1.as_mut_slice())? } else { 1 };
				match entry_type {
					0 => {
						//free object
						read_big_endian_integer(&mut reader, bytes2.as_mut_slice())?;
						read_big_endian_integer(&mut reader, bytes3.as_mut_slice())?;
					}
					1 => {
						//normal object
						let offset = read_big_endian_integer(&mut reader, bytes2.as_mut_slice())?;
						let generation = if !bytes3.is_empty() { read_big_endian_integer(&mut reader, bytes3.as_mut_slice())? } else { 0 } as u16;
						xref.insert(
							(start + j) as u32,
							XrefEntry::Normal {
								offset,
								generation,
							},
						);
					}
					2 => {
						//compressed object
						let container = read_big_endian_integer(&mut reader, bytes2.as_mut_slice())?;
						let index = read_big_endian_integer(&mut reader, bytes3.as_mut_slice())? as u16;
						xref.insert((start + j) as u32, XrefEntry::Compressed { container, index });
					}
					_ => {}
				}
			}
		}
	}
	dict.remove(b"Length");
	dict.remove(b"W");
	dict.remove(b"Index");
	Ok((xref, dict))
}

fn read_big_endian_integer(reader: &mut Cursor<Vec<u8>>, buffer: &mut [u8]) -> Result<u32> {
	reader.read_exact(buffer)?;
	let mut value = 0;
	for &mut byte in buffer {
		value = (value << 8) + u32::from(byte);
	}
	Ok(value)
}

fn parse_integer_array(array: &Object) -> Option<Vec<i64>> {
	let array = array.as_array()?;
	let mut out = Vec::with_capacity(array.len());

	for n in array {
		out.push(n.as_i64()?);
	}

	Some(out)
}
<|endoftext|>


<commit_before>//! Unix specific definitions
use std;
use std::io::{self, Chars, Read, Write};
use std::sync;
use std::sync::atomic;
use libc;
use nix;
use nix::poll;
use nix::sys::signal;
use nix::sys::termios;

use consts::{self, KeyPress};
use ::Result;
use ::error;
use super::{RawMode, RawReader, Term};

const STDIN_FILENO: libc::c_int = libc::STDIN_FILENO;
const STDOUT_FILENO: libc::c_int = libc::STDOUT_FILENO;

/// Unsupported Terminals that don't support RAW mode
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb", "cons25", "emacs"];

#[cfg(any(target_os = "macos", target_os = "freebsd"))]
const TIOCGWINSZ: libc::c_ulong = 0x40087468;

#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_os = "android"))]
const TIOCGWINSZ: libc::c_ulong = 0x5413;

#[cfg(all(target_os = "linux", target_env = "musl"))]
const TIOCGWINSZ: libc::c_int = 0x5413;

fn get_win_size() -> (usize, usize) {
    use std::mem::zeroed;
    use libc::c_ushort;

    unsafe {
        #[repr(C)]
        struct winsize {
            ws_row: c_ushort,
            ws_col: c_ushort,
            ws_xpixel: c_ushort,
            ws_ypixel: c_ushort,
        }

        let mut size: winsize = zeroed();
        match libc::ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut size) {
            0 => (size.ws_col as usize, size.ws_row as usize), // TODO getCursorPosition
            _ => (80, 24),
        }
    }
}

/// Check TERM environment variable to see if current term is in our
/// unsupported list
fn is_unsupported_term() -> bool {
    use std::ascii::AsciiExt;
    match std::env::var("TERM") {
        Ok(term) => {
            for iter in &UNSUPPORTED_TERM {
                if (*iter).eq_ignore_ascii_case(&term) {
                    return true;
                }
            }
            false
        }
        Err(_) => false,
    }
}

/// Return whether or not STDIN, STDOUT or STDERR is a TTY
fn is_a_tty(fd: libc::c_int) -> bool {
    unsafe { libc::isatty(fd) != 0 }
}

pub type Mode = termios::Termios;

impl RawMode for Mode {
    /// Disable RAW mode for the terminal.
    fn disable_raw_mode(&self) -> Result<()> {
        try!(termios::tcsetattr(STDIN_FILENO, termios::TCSADRAIN, self));
        Ok(())
    }
}

// Rust std::io::Stdin is buffered with no way to know if bytes are available.
// So we use low-level stuff instead...
struct StdinRaw {}

impl Read for StdinRaw {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        loop {
            let res = unsafe {
                libc::read(STDIN_FILENO,
                           buf.as_mut_ptr() as *mut libc::c_void,
                           buf.len() as libc::size_t)
            };
            if res == -1 {
                let error = io::Error::last_os_error();
                if error.kind() != io::ErrorKind::Interrupted {
                    return Err(error);
                }
            } else {
                return Ok(res as usize);
            }
        }
    }
}

/// Console input reader
pub struct PosixRawReader {
    chars: Chars<StdinRaw>,
}

impl PosixRawReader {
    fn new() -> Result<PosixRawReader> {
        let stdin = StdinRaw {};
        Ok(PosixRawReader { chars: stdin.chars() })
    }

    fn escape_sequence(&mut self) -> Result<KeyPress> {
        // Read the next two bytes representing the escape sequence.
        let seq1 = try!(self.next_char());
        if seq1 == '[' {
            // ESC [ sequences.
            let seq2 = try!(self.next_char());
            if seq2.is_digit(10) {
                // Extended escape, read additional byte.
                let seq3 = try!(self.next_char());
                if seq3 == '~' {
                    match seq2 {
                        // '1' => Ok(KeyPress::Home),
                        '3' => Ok(KeyPress::Delete),
                        // '4' => Ok(KeyPress::End),
                        '5' => Ok(KeyPress::PageUp),
                        '6' => Ok(KeyPress::PageDown),
                        '7' => Ok(KeyPress::Home),
                        '8' => Ok(KeyPress::End),
                        _ => Ok(KeyPress::UnknownEscSeq),
                    }
                } else {
                    Ok(KeyPress::UnknownEscSeq)
                }
            } else {
                match seq2 {
                    'A' => Ok(KeyPress::Up), // ANSI
                    'B' => Ok(KeyPress::Down),
                    'C' => Ok(KeyPress::Right),
                    'D' => Ok(KeyPress::Left),
                    'F' => Ok(KeyPress::End),
                    'H' => Ok(KeyPress::Home),
                    _ => Ok(KeyPress::UnknownEscSeq),
                }
            }
        } else if seq1 == 'O' {
            // ESC O sequences.
            let seq2 = try!(self.next_char());
            match seq2 {
                'A' => Ok(KeyPress::Up),
                'B' => Ok(KeyPress::Down),
                'C' => Ok(KeyPress::Right),
                'D' => Ok(KeyPress::Left),
                'F' => Ok(KeyPress::End),
                'H' => Ok(KeyPress::Home),
                _ => Ok(KeyPress::UnknownEscSeq),
            }
        } else {
            // TODO ESC-N (n): search history forward not interactively
            // TODO ESC-P (p): search history backward not interactively
            // TODO ESC-R (r): Undo all changes made to this line.
            match seq1 {
                '\x08' => Ok(KeyPress::Meta('\x08')), // Backspace
                '<' => Ok(KeyPress::Meta('<')),
                '>' => Ok(KeyPress::Meta('>')),
                'b' | 'B' => Ok(KeyPress::Meta('B')),
                'c' | 'C' => Ok(KeyPress::Meta('C')),
                'd' | 'D' => Ok(KeyPress::Meta('D')),
                'f' | 'F' => Ok(KeyPress::Meta('F')),
                'l' | 'L' => Ok(KeyPress::Meta('L')),
                't' | 'T' => Ok(KeyPress::Meta('T')),
                'u' | 'U' => Ok(KeyPress::Meta('U')),
                'y' | 'Y' => Ok(KeyPress::Meta('Y')),
                '\x7f' => Ok(KeyPress::Meta('\x7f')), // Delete
                _ => {
                    // writeln!(io::stderr(), "key: {:?}, seq1: {:?}", KeyPress::Esc, seq1).unwrap();
                    Ok(KeyPress::UnknownEscSeq)
                }
            }
        }
    }
}

impl RawReader for PosixRawReader {
    fn next_key(&mut self, timeout_ms: i32) -> Result<KeyPress> {
        let c = try!(self.next_char());

        let mut key = consts::char_to_key_press(c);
        if key == KeyPress::Esc {
            let mut fds =
                [poll::PollFd::new(STDIN_FILENO, poll::POLLIN, poll::EventFlags::empty())];
            match poll::poll(&mut fds, timeout_ms) {
                Ok(n) if n == 0 => {
                    // single escape
                }
                Ok(_) => {
                    // escape sequence
                    key = try!(self.escape_sequence())
                }
                // Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
                Err(e) => return Err(e.into()),
            }
        }
        Ok(key)
    }

    fn next_char(&mut self) -> Result<char> {
        match self.chars.next() {
            Some(c) => Ok(try!(c)),
            None => Err(error::ReadlineError::Eof),
        }
    }
}

static SIGWINCH_ONCE: sync::Once = sync::ONCE_INIT;
static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;

fn install_sigwinch_handler() {
    SIGWINCH_ONCE.call_once(|| unsafe {
        let sigwinch = signal::SigAction::new(signal::SigHandler::Handler(sigwinch_handler),
                                              signal::SaFlags::empty(),
                                              signal::SigSet::empty());
        let _ = signal::sigaction(signal::SIGWINCH, &sigwinch);
    });
}

extern "C" fn sigwinch_handler(_: libc::c_int) {
    SIGWINCH.store(true, atomic::Ordering::SeqCst);
}

pub type Terminal = PosixTerminal;

#[derive(Clone,Debug)]
pub struct PosixTerminal {
    unsupported: bool,
    stdin_isatty: bool,
}

impl Term for PosixTerminal {
    type Reader = PosixRawReader;
    type Mode = Mode;

    fn new() -> PosixTerminal {
        let term = PosixTerminal {
            unsupported: is_unsupported_term(),
            stdin_isatty: is_a_tty(STDIN_FILENO),
        };
        if !term.unsupported && term.stdin_isatty && is_a_tty(STDOUT_FILENO) {
            install_sigwinch_handler();
        }
        term
    }

    // Init checks:

    /// Check if current terminal can provide a rich line-editing user interface.
    fn is_unsupported(&self) -> bool {
        self.unsupported
    }

    /// check if stdin is connected to a terminal.
    fn is_stdin_tty(&self) -> bool {
        self.stdin_isatty
    }

    // Interactive loop:

    /// Try to get the number of columns in the current terminal,
    /// or assume 80 if it fails.
    fn get_columns(&self) -> usize {
        let (cols, _) = get_win_size();
        cols
    }

    /// Try to get the number of rows in the current terminal,
    /// or assume 24 if it fails.
    fn get_rows(&self) -> usize {
        let (_, rows) = get_win_size();
        rows
    }

    fn enable_raw_mode(&self) -> Result<Mode> {
        use nix::errno::Errno::ENOTTY;
        use nix::sys::termios::{BRKINT, CS8, ECHO, ICANON, ICRNL, IEXTEN, INPCK, ISIG, ISTRIP,
                                IXON, /* OPOST, */ VMIN, VTIME};
        if !self.stdin_isatty {
            try!(Err(nix::Error::from_errno(ENOTTY)));
        }
        let original_mode = try!(termios::tcgetattr(STDIN_FILENO));
        let mut raw = original_mode;
        // disable BREAK interrupt, CR to NL conversion on input,
        // input parity check, strip high bit (bit 8), output flow control
        raw.c_iflag = raw.c_iflag & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        // we don't want raw output, it turns newlines into straight linefeeds
        // raw.c_oflag = raw.c_oflag & !(OPOST); // disable all output processing
        raw.c_cflag = raw.c_cflag | (CS8); // character-size mark (8 bits)
        // disable echoing, canonical mode, extended input processing and signals
        raw.c_lflag = raw.c_lflag & !(ECHO | ICANON | IEXTEN | ISIG);
        raw.c_cc[VMIN] = 1; // One character-at-a-time input
        raw.c_cc[VTIME] = 0; // with blocking read
        try!(termios::tcsetattr(STDIN_FILENO, termios::TCSADRAIN, &raw));
        Ok(original_mode)
    }

    /// Create a RAW reader
    fn create_reader(&self) -> Result<PosixRawReader> {
        PosixRawReader::new()
    }

    /// Check if a SIGWINCH signal has been received
    fn sigwinch(&self) -> bool {
        SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst)
    }

    /// Clear the screen. Used to handle ctrl+l
    fn clear_screen(&mut self, w: &mut Write) -> Result<()> {
        try!(w.write_all(b"\x1b[H\x1b[2J"));
        try!(w.flush());
        Ok(())
    }
}

#[cfg(unix)]
pub fn suspend() -> Result<()> {
    // For macos:
    try!(signal::kill(nix::unistd::getppid(), signal::SIGTSTP));
    try!(signal::kill(nix::unistd::getpid(), signal::SIGTSTP));
    Ok(())
}

#[cfg(all(unix,test))]
mod test {
    #[test]
    fn test_unsupported_term() {
        ::std::env::set_var("TERM", "xterm");
        assert_eq!(false, super::is_unsupported_term());

        ::std::env::set_var("TERM", "dumb");
        assert_eq!(true, super::is_unsupported_term());
    }
}
<commit_msg>Added escape sequence for Home ([1~) and End ([4~) keys for xterm<commit_after>//! Unix specific definitions
use std;
use std::io::{self, Chars, Read, Write};
use std::sync;
use std::sync::atomic;
use libc;
use nix;
use nix::poll;
use nix::sys::signal;
use nix::sys::termios;

use consts::{self, KeyPress};
use ::Result;
use ::error;
use super::{RawMode, RawReader, Term};

const STDIN_FILENO: libc::c_int = libc::STDIN_FILENO;
const STDOUT_FILENO: libc::c_int = libc::STDOUT_FILENO;

/// Unsupported Terminals that don't support RAW mode
static UNSUPPORTED_TERM: [&'static str; 3] = ["dumb", "cons25", "emacs"];

#[cfg(any(target_os = "macos", target_os = "freebsd"))]
const TIOCGWINSZ: libc::c_ulong = 0x40087468;

#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_os = "android"))]
const TIOCGWINSZ: libc::c_ulong = 0x5413;

#[cfg(all(target_os = "linux", target_env = "musl"))]
const TIOCGWINSZ: libc::c_int = 0x5413;

fn get_win_size() -> (usize, usize) {
    use std::mem::zeroed;
    use libc::c_ushort;

    unsafe {
        #[repr(C)]
        struct winsize {
            ws_row: c_ushort,
            ws_col: c_ushort,
            ws_xpixel: c_ushort,
            ws_ypixel: c_ushort,
        }

        let mut size: winsize = zeroed();
        match libc::ioctl(STDOUT_FILENO, TIOCGWINSZ, &mut size) {
            0 => (size.ws_col as usize, size.ws_row as usize), // TODO getCursorPosition
            _ => (80, 24),
        }
    }
}

/// Check TERM environment variable to see if current term is in our
/// unsupported list
fn is_unsupported_term() -> bool {
    use std::ascii::AsciiExt;
    match std::env::var("TERM") {
        Ok(term) => {
            for iter in &UNSUPPORTED_TERM {
                if (*iter).eq_ignore_ascii_case(&term) {
                    return true;
                }
            }
            false
        }
        Err(_) => false,
    }
}

/// Return whether or not STDIN, STDOUT or STDERR is a TTY
fn is_a_tty(fd: libc::c_int) -> bool {
    unsafe { libc::isatty(fd) != 0 }
}

pub type Mode = termios::Termios;

impl RawMode for Mode {
    /// Disable RAW mode for the terminal.
    fn disable_raw_mode(&self) -> Result<()> {
        try!(termios::tcsetattr(STDIN_FILENO, termios::TCSADRAIN, self));
        Ok(())
    }
}

// Rust std::io::Stdin is buffered with no way to know if bytes are available.
// So we use low-level stuff instead...
struct StdinRaw {}

impl Read for StdinRaw {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        loop {
            let res = unsafe {
                libc::read(STDIN_FILENO,
                           buf.as_mut_ptr() as *mut libc::c_void,
                           buf.len() as libc::size_t)
            };
            if res == -1 {
                let error = io::Error::last_os_error();
                if error.kind() != io::ErrorKind::Interrupted {
                    return Err(error);
                }
            } else {
                return Ok(res as usize);
            }
        }
    }
}

/// Console input reader
pub struct PosixRawReader {
    chars: Chars<StdinRaw>,
}

impl PosixRawReader {
    fn new() -> Result<PosixRawReader> {
        let stdin = StdinRaw {};
        Ok(PosixRawReader { chars: stdin.chars() })
    }

    fn escape_sequence(&mut self) -> Result<KeyPress> {
        // Read the next two bytes representing the escape sequence.
        let seq1 = try!(self.next_char());
        if seq1 == '[' {
            // ESC [ sequences.
            let seq2 = try!(self.next_char());
            if seq2.is_digit(10) {
                // Extended escape, read additional byte.
                let seq3 = try!(self.next_char());
                if seq3 == '~' {
                    match seq2 {
                        '1' => Ok(KeyPress::Home), // xterm
                        '3' => Ok(KeyPress::Delete),
                        '4' => Ok(KeyPress::End), // xterm
                        '5' => Ok(KeyPress::PageUp),
                        '6' => Ok(KeyPress::PageDown),
                        '7' => Ok(KeyPress::Home),
                        '8' => Ok(KeyPress::End),
                        _ => Ok(KeyPress::UnknownEscSeq),
                    }
                } else {
                    Ok(KeyPress::UnknownEscSeq)
                }
            } else {
                match seq2 {
                    'A' => Ok(KeyPress::Up), // ANSI
                    'B' => Ok(KeyPress::Down),
                    'C' => Ok(KeyPress::Right),
                    'D' => Ok(KeyPress::Left),
                    'F' => Ok(KeyPress::End),
                    'H' => Ok(KeyPress::Home),
                    _ => Ok(KeyPress::UnknownEscSeq),
                }
            }
        } else if seq1 == 'O' {
            // ESC O sequences.
            let seq2 = try!(self.next_char());
            match seq2 {
                'A' => Ok(KeyPress::Up),
                'B' => Ok(KeyPress::Down),
                'C' => Ok(KeyPress::Right),
                'D' => Ok(KeyPress::Left),
                'F' => Ok(KeyPress::End),
                'H' => Ok(KeyPress::Home),
                _ => Ok(KeyPress::UnknownEscSeq),
            }
        } else {
            // TODO ESC-N (n): search history forward not interactively
            // TODO ESC-P (p): search history backward not interactively
            // TODO ESC-R (r): Undo all changes made to this line.
            match seq1 {
                '\x08' => Ok(KeyPress::Meta('\x08')), // Backspace
                '<' => Ok(KeyPress::Meta('<')),
                '>' => Ok(KeyPress::Meta('>')),
                'b' | 'B' => Ok(KeyPress::Meta('B')),
                'c' | 'C' => Ok(KeyPress::Meta('C')),
                'd' | 'D' => Ok(KeyPress::Meta('D')),
                'f' | 'F' => Ok(KeyPress::Meta('F')),
                'l' | 'L' => Ok(KeyPress::Meta('L')),
                't' | 'T' => Ok(KeyPress::Meta('T')),
                'u' | 'U' => Ok(KeyPress::Meta('U')),
                'y' | 'Y' => Ok(KeyPress::Meta('Y')),
                '\x7f' => Ok(KeyPress::Meta('\x7f')), // Delete
                _ => {
                    // writeln!(io::stderr(), "key: {:?}, seq1: {:?}", KeyPress::Esc, seq1).unwrap();
                    Ok(KeyPress::UnknownEscSeq)
                }
            }
        }
    }
}

impl RawReader for PosixRawReader {
    fn next_key(&mut self, timeout_ms: i32) -> Result<KeyPress> {
        let c = try!(self.next_char());

        let mut key = consts::char_to_key_press(c);
        if key == KeyPress::Esc {
            let mut fds =
                [poll::PollFd::new(STDIN_FILENO, poll::POLLIN, poll::EventFlags::empty())];
            match poll::poll(&mut fds, timeout_ms) {
                Ok(n) if n == 0 => {
                    // single escape
                }
                Ok(_) => {
                    // escape sequence
                    key = try!(self.escape_sequence())
                }
                // Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
                Err(e) => return Err(e.into()),
            }
        }
        Ok(key)
    }

    fn next_char(&mut self) -> Result<char> {
        match self.chars.next() {
            Some(c) => Ok(try!(c)),
            None => Err(error::ReadlineError::Eof),
        }
    }
}

static SIGWINCH_ONCE: sync::Once = sync::ONCE_INIT;
static SIGWINCH: atomic::AtomicBool = atomic::ATOMIC_BOOL_INIT;

fn install_sigwinch_handler() {
    SIGWINCH_ONCE.call_once(|| unsafe {
        let sigwinch = signal::SigAction::new(signal::SigHandler::Handler(sigwinch_handler),
                                              signal::SaFlags::empty(),
                                              signal::SigSet::empty());
        let _ = signal::sigaction(signal::SIGWINCH, &sigwinch);
    });
}

extern "C" fn sigwinch_handler(_: libc::c_int) {
    SIGWINCH.store(true, atomic::Ordering::SeqCst);
}

pub type Terminal = PosixTerminal;

#[derive(Clone,Debug)]
pub struct PosixTerminal {
    unsupported: bool,
    stdin_isatty: bool,
}

impl Term for PosixTerminal {
    type Reader = PosixRawReader;
    type Mode = Mode;

    fn new() -> PosixTerminal {
        let term = PosixTerminal {
            unsupported: is_unsupported_term(),
            stdin_isatty: is_a_tty(STDIN_FILENO),
        };
        if !term.unsupported && term.stdin_isatty && is_a_tty(STDOUT_FILENO) {
            install_sigwinch_handler();
        }
        term
    }

    // Init checks:

    /// Check if current terminal can provide a rich line-editing user interface.
    fn is_unsupported(&self) -> bool {
        self.unsupported
    }

    /// check if stdin is connected to a terminal.
    fn is_stdin_tty(&self) -> bool {
        self.stdin_isatty
    }

    // Interactive loop:

    /// Try to get the number of columns in the current terminal,
    /// or assume 80 if it fails.
    fn get_columns(&self) -> usize {
        let (cols, _) = get_win_size();
        cols
    }

    /// Try to get the number of rows in the current terminal,
    /// or assume 24 if it fails.
    fn get_rows(&self) -> usize {
        let (_, rows) = get_win_size();
        rows
    }

    fn enable_raw_mode(&self) -> Result<Mode> {
        use nix::errno::Errno::ENOTTY;
        use nix::sys::termios::{BRKINT, CS8, ECHO, ICANON, ICRNL, IEXTEN, INPCK, ISIG, ISTRIP,
                                IXON, /* OPOST, */ VMIN, VTIME};
        if !self.stdin_isatty {
            try!(Err(nix::Error::from_errno(ENOTTY)));
        }
        let original_mode = try!(termios::tcgetattr(STDIN_FILENO));
        let mut raw = original_mode;
        // disable BREAK interrupt, CR to NL conversion on input,
        // input parity check, strip high bit (bit 8), output flow control
        raw.c_iflag = raw.c_iflag & !(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
        // we don't want raw output, it turns newlines into straight linefeeds
        // raw.c_oflag = raw.c_oflag & !(OPOST); // disable all output processing
        raw.c_cflag = raw.c_cflag | (CS8); // character-size mark (8 bits)
        // disable echoing, canonical mode, extended input processing and signals
        raw.c_lflag = raw.c_lflag & !(ECHO | ICANON | IEXTEN | ISIG);
        raw.c_cc[VMIN] = 1; // One character-at-a-time input
        raw.c_cc[VTIME] = 0; // with blocking read
        try!(termios::tcsetattr(STDIN_FILENO, termios::TCSADRAIN, &raw));
        Ok(original_mode)
    }

    /// Create a RAW reader
    fn create_reader(&self) -> Result<PosixRawReader> {
        PosixRawReader::new()
    }

    /// Check if a SIGWINCH signal has been received
    fn sigwinch(&self) -> bool {
        SIGWINCH.compare_and_swap(true, false, atomic::Ordering::SeqCst)
    }

    /// Clear the screen. Used to handle ctrl+l
    fn clear_screen(&mut self, w: &mut Write) -> Result<()> {
        try!(w.write_all(b"\x1b[H\x1b[2J"));
        try!(w.flush());
        Ok(())
    }
}

#[cfg(unix)]
pub fn suspend() -> Result<()> {
    // For macos:
    try!(signal::kill(nix::unistd::getppid(), signal::SIGTSTP));
    try!(signal::kill(nix::unistd::getpid(), signal::SIGTSTP));
    Ok(())
}

#[cfg(all(unix,test))]
mod test {
    #[test]
    fn test_unsupported_term() {
        ::std::env::set_var("TERM", "xterm");
        assert_eq!(false, super::is_unsupported_term());

        ::std::env::set_var("TERM", "dumb");
        assert_eq!(true, super::is_unsupported_term());
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::ops::Deref;

use serde::de::{Deserialize, Deserializer, Error};
use serde::ser::{Serialize, Serializer};

use types::*;

/// Unique identifier for the target chat or username of the
/// target channel (in the format @channelusername)
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ChatRef<'a> {
    Id(ChatId),
    #[doc(hidden)]
    ChannelUsername(Cow<'a, str>,),
}

impl<'a> ChatRef<'a> {
    pub fn from_chat_id(chat_id: ChatId) -> ChatRef<'a> {
        ChatRef::Id(chat_id)
    }
}

pub trait ToChatRef<'a> {
    fn to_chat_ref(&self) -> ChatRef<'a>;
}

impl<'a, S> ToChatRef<'a> for S where S: Deref, S::Target: ToChatRef<'a> {
    fn to_chat_ref(&self) -> ChatRef<'a> {
        self.deref().to_chat_ref()
    }
}

impl<'a> ToChatRef<'a> for Chat {
    fn to_chat_ref(&self) -> ChatRef<'a> {
        self.id().to_chat_ref()
    }
}

impl<'a> ToChatRef<'a> for ChatMember {
    fn to_chat_ref(&self) -> ChatRef<'a> {
        self.user.to_chat_ref()
    }
}

impl<'a> Serialize for ChatRef<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        match *self {
            ChatRef::Id(id) => serializer.serialize_i64(id.into()),
            ChatRef::ChannelUsername(ref username) => serializer.serialize_str(&username),
        }
    }
}

macro_rules! chat_id_impls {
    ($id: ident) => {
        integer_id_impls!($id);

        impl<'a> ToChatRef<'a> for $id {
            fn to_chat_ref(&self) -> ChatRef<'a> {
                ChatRef::from_chat_id((*self).into())
            }
        }
    };
}

macro_rules! specific_chat_id_impls {
    ($id: ident, $typ: ident) => {
        chat_id_impls!($id);

        impl From<$id> for ChatId {
            fn from(c: $id) -> Self {
                ChatId::new(c.into())
            }
        }

        impl<'a> ToChatRef<'a> for $typ {
            fn to_chat_ref(&self) -> ChatRef<'a> {
                self.id.to_chat_ref()
            }
        }
    };
}

pub trait ToUserId {
    fn to_user_id(&self) -> UserId;
}

impl<S> ToUserId for S where S: Deref, S::Target: ToUserId {
    fn to_user_id(&self) -> UserId {
        self.deref().to_user_id()
    }
}

impl ToUserId for UserId {
    fn to_user_id(&self) -> UserId {
        *self
    }
}

impl ToUserId for ChatMember {
    fn to_user_id(&self) -> UserId {
        self.user.id
    }
}

impl ToUserId for User {
    fn to_user_id(&self) -> UserId {
        self.id
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UserId(Integer);
specific_chat_id_impls!(UserId, User);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GroupId(Integer);
specific_chat_id_impls!(GroupId, Group);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SupergroupId(Integer);
specific_chat_id_impls!(SupergroupId, Supergroup);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChannelId(Integer);
specific_chat_id_impls!(ChannelId, Channel);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChatId(Integer);
chat_id_impls!(ChatId);

/// This object represents a Telegram user or bot.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct User {
    /// Unique identifier for this user or bot.
    pub id: UserId,
    /// User‘s or bot’s first name.
    pub first_name: String,
    /// User‘s or bot’s last name.
    pub last_name: Option<String>,
    /// User‘s or bot’s username.
    pub username: Option<String>,
}

/// This object represents a group.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Group {
    /// Unique identifier for this chat.
    pub id: GroupId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: bool,
}

/// This object represents a supergroup.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Supergroup {
    /// Unique identifier for this chat.
    pub id: SupergroupId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for supergroup.
    pub username: Option<String>,
}

/// This object represents a channel.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Channel {
    /// Unique identifier for this chat.
    pub id: ChannelId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for channel.
    pub username: Option<String>,
}

/// This object represents a chat.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Chat {
    Private(User),
    Group(Group),
    Supergroup(Supergroup),
    Channel(Channel),
    #[doc(hidden)]
    Unknown(RawChat),
}

impl Chat {
    pub fn id(&self) -> ChatId {
        match *self {
            Chat::Private(ref x) => x.id.into(),
            Chat::Group(ref x) => x.id.into(),
            Chat::Supergroup(ref x) => x.id.into(),
            Chat::Channel(ref x) => x.id.into(),
            Chat::Unknown(ref x) => x.id.into(),
        }
    }
}

impl<'de> Deserialize<'de> for Chat {
    fn deserialize<D>(deserializer: D) -> Result<Chat, D::Error>
        where D: Deserializer<'de>
    {
        let raw: RawChat = Deserialize::deserialize(deserializer)?;

        macro_rules! required_field {
            ($name:ident) => {{
                match raw.$name {
                    Some(val) => val,
                    None => return Err(D::Error::missing_field(stringify!($name)))
                }
            }}
        }

        Ok(match raw.type_.as_ref() {
            "private" => {
                Chat::Private(User {
                    id: raw.id.into(),
                    username: raw.username,
                    first_name: required_field!(first_name),
                    last_name: raw.last_name,
                })
            }
            "group" => {
                Chat::Group(Group {
                    id: raw.id.into(),
                    title: required_field!(title),
                    all_members_are_administrators: required_field!(all_members_are_administrators),
                })
            }
            "supergroup" => {
                Chat::Supergroup(Supergroup {
                    id: raw.id.into(),
                    title: required_field!(title),
                    username: raw.username,
                })
            }
            "channel" => {
                Chat::Channel(Channel {
                    id: raw.id.into(),
                    title: required_field!(title),
                    username: raw.username,
                })
            }
            _ => Chat::Unknown(raw),
        })
    }
}

/// This object represents a chat, directly mapped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawChat {
    /// Unique identifier for this chat.
    pub id: Integer,
    /// Type of chat, can be either “private”, “group”, “supergroup” or “channel”
    #[serde(rename="type")]
    pub type_: String,
    /// Title, for supergroups, channels and group chats
    pub title: Option<String>,
    /// Username, for private chats, supergroups and channels if available
    pub username: Option<String>,
    /// First name of the other party in a private chat
    pub first_name: Option<String>,
    /// Last name of the other party in a private chat
    pub last_name: Option<String>,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: Option<bool>,
}
<commit_msg>feat: implement ToChatRef for ChatRef<commit_after>use std::borrow::Cow;
use std::ops::Deref;

use serde::de::{Deserialize, Deserializer, Error};
use serde::ser::{Serialize, Serializer};

use types::*;

/// Unique identifier for the target chat or username of the
/// target channel (in the format @channelusername)
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum ChatRef<'a> {
    Id(ChatId),
    #[doc(hidden)]
    ChannelUsername(Cow<'a, str>,),
}

impl<'a> ChatRef<'a> {
    pub fn from_chat_id(chat_id: ChatId) -> ChatRef<'a> {
        ChatRef::Id(chat_id)
    }
}

pub trait ToChatRef<'a> {
    fn to_chat_ref(&self) -> ChatRef<'a>;
}

impl<'a, S> ToChatRef<'a> for S where S: Deref, S::Target: ToChatRef<'a> {
    fn to_chat_ref(&self) -> ChatRef<'a> {
        self.deref().to_chat_ref()
    }
}

impl<'a> ToChatRef<'a> for ChatRef<'a> {
    fn to_chat_ref(&self) -> ChatRef<'a> {
        self.clone()
    }
}

impl<'a> ToChatRef<'a> for Chat {
    fn to_chat_ref(&self) -> ChatRef<'a> {
        self.id().to_chat_ref()
    }
}

impl<'a> ToChatRef<'a> for ChatMember {
    fn to_chat_ref(&self) -> ChatRef<'a> {
        self.user.to_chat_ref()
    }
}

impl<'a> Serialize for ChatRef<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        match *self {
            ChatRef::Id(id) => serializer.serialize_i64(id.into()),
            ChatRef::ChannelUsername(ref username) => serializer.serialize_str(&username),
        }
    }
}

macro_rules! chat_id_impls {
    ($id: ident) => {
        integer_id_impls!($id);

        impl<'a> ToChatRef<'a> for $id {
            fn to_chat_ref(&self) -> ChatRef<'a> {
                ChatRef::from_chat_id((*self).into())
            }
        }
    };
}

macro_rules! specific_chat_id_impls {
    ($id: ident, $typ: ident) => {
        chat_id_impls!($id);

        impl From<$id> for ChatId {
            fn from(c: $id) -> Self {
                ChatId::new(c.into())
            }
        }

        impl<'a> ToChatRef<'a> for $typ {
            fn to_chat_ref(&self) -> ChatRef<'a> {
                self.id.to_chat_ref()
            }
        }
    };
}

pub trait ToUserId {
    fn to_user_id(&self) -> UserId;
}

impl<S> ToUserId for S where S: Deref, S::Target: ToUserId {
    fn to_user_id(&self) -> UserId {
        self.deref().to_user_id()
    }
}

impl ToUserId for UserId {
    fn to_user_id(&self) -> UserId {
        *self
    }
}

impl ToUserId for ChatMember {
    fn to_user_id(&self) -> UserId {
        self.user.id
    }
}

impl ToUserId for User {
    fn to_user_id(&self) -> UserId {
        self.id
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct UserId(Integer);
specific_chat_id_impls!(UserId, User);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GroupId(Integer);
specific_chat_id_impls!(GroupId, Group);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SupergroupId(Integer);
specific_chat_id_impls!(SupergroupId, Supergroup);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChannelId(Integer);
specific_chat_id_impls!(ChannelId, Channel);

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ChatId(Integer);
chat_id_impls!(ChatId);

/// This object represents a Telegram user or bot.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct User {
    /// Unique identifier for this user or bot.
    pub id: UserId,
    /// User‘s or bot’s first name.
    pub first_name: String,
    /// User‘s or bot’s last name.
    pub last_name: Option<String>,
    /// User‘s or bot’s username.
    pub username: Option<String>,
}

/// This object represents a group.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Group {
    /// Unique identifier for this chat.
    pub id: GroupId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: bool,
}

/// This object represents a supergroup.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Supergroup {
    /// Unique identifier for this chat.
    pub id: SupergroupId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for supergroup.
    pub username: Option<String>,
}

/// This object represents a channel.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Channel {
    /// Unique identifier for this chat.
    pub id: ChannelId,
    /// Title, for supergroups, channels and group chats.
    pub title: String,
    /// Username for channel.
    pub username: Option<String>,
}

/// This object represents a chat.
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum Chat {
    Private(User),
    Group(Group),
    Supergroup(Supergroup),
    Channel(Channel),
    #[doc(hidden)]
    Unknown(RawChat),
}

impl Chat {
    pub fn id(&self) -> ChatId {
        match *self {
            Chat::Private(ref x) => x.id.into(),
            Chat::Group(ref x) => x.id.into(),
            Chat::Supergroup(ref x) => x.id.into(),
            Chat::Channel(ref x) => x.id.into(),
            Chat::Unknown(ref x) => x.id.into(),
        }
    }
}

impl<'de> Deserialize<'de> for Chat {
    fn deserialize<D>(deserializer: D) -> Result<Chat, D::Error>
        where D: Deserializer<'de>
    {
        let raw: RawChat = Deserialize::deserialize(deserializer)?;

        macro_rules! required_field {
            ($name:ident) => {{
                match raw.$name {
                    Some(val) => val,
                    None => return Err(D::Error::missing_field(stringify!($name)))
                }
            }}
        }

        Ok(match raw.type_.as_ref() {
            "private" => {
                Chat::Private(User {
                    id: raw.id.into(),
                    username: raw.username,
                    first_name: required_field!(first_name),
                    last_name: raw.last_name,
                })
            }
            "group" => {
                Chat::Group(Group {
                    id: raw.id.into(),
                    title: required_field!(title),
                    all_members_are_administrators: required_field!(all_members_are_administrators),
                })
            }
            "supergroup" => {
                Chat::Supergroup(Supergroup {
                    id: raw.id.into(),
                    title: required_field!(title),
                    username: raw.username,
                })
            }
            "channel" => {
                Chat::Channel(Channel {
                    id: raw.id.into(),
                    title: required_field!(title),
                    username: raw.username,
                })
            }
            _ => Chat::Unknown(raw),
        })
    }
}

/// This object represents a chat, directly mapped.
#[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize)]
pub struct RawChat {
    /// Unique identifier for this chat.
    pub id: Integer,
    /// Type of chat, can be either “private”, “group”, “supergroup” or “channel”
    #[serde(rename="type")]
    pub type_: String,
    /// Title, for supergroups, channels and group chats
    pub title: Option<String>,
    /// Username, for private chats, supergroups and channels if available
    pub username: Option<String>,
    /// First name of the other party in a private chat
    pub first_name: Option<String>,
    /// Last name of the other party in a private chat
    pub last_name: Option<String>,
    /// True if a group has ‘All Members Are Admins’ enabled.
    pub all_members_are_administrators: Option<bool>,
}
<|endoftext|>