<commit_before>#[cfg(test)]
mod tests;

use std::collections::HashMap;
use ast::Expr;

type Alias = (String, String);

#[derive(Debug)]
struct Namespace {
    mappings: HashMap<String, Expr>,
    aliases: HashMap<String, Alias>,
}

impl Namespace {
    fn new() -> Namespace {
        Namespace {
            mappings: HashMap::new(),
            aliases: HashMap::new(),
        }
    }

    fn get(&self, name: &String) -> Option<&Expr> {
        self.mappings.get(name)
    }

    fn insert(&mut self, name: String, expr: Expr) -> Option<Expr> {
        self.mappings.insert(name, expr)
    }

    fn get_alias(&self, alias: &String) -> Option<&Alias> {
        self.aliases.get(alias)
    }

    fn insert_alias(&mut self, alias: String, ns: String, name: String) -> Option<Alias> {
        self.aliases.insert(alias, (ns, name))
    }
}

#[derive(Debug)]
pub struct State<'s> {
    current: String,
    namespaces: HashMap<String, Namespace>,
    parent: Option<&'s State<'s>>,
    id: usize,
}

impl<'s> State<'s> {
    pub fn new(current: String) -> State<'s> {
        let mut current_ns = Namespace::new();
        current_ns.insert("nil".to_string(), e_list![]);
        current_ns.insert("true".to_string(), e_bool!(true));
        current_ns.insert("false".to_string(), e_bool!(false));

        let mut namespaces = HashMap::new();
        namespaces.insert(current.clone(), current_ns);

        State {
            current: current,
            namespaces: namespaces,
            parent: None,
            id: 0,
        }
    }

    pub fn new_chained(parent: &'s State<'s>) -> State<'s> {
        let mut state = State::new(format!("{}_chained", parent.current));
        state.parent = Some(parent);
        state
    }

    pub fn insert(&mut self, name: String, expr: Expr) -> Option<Expr> {
        self.namespaces
            .get_mut(&self.current)
            .and_then(|scope| scope.insert(name, expr))
    }

    pub fn get(&self, ns: Option<&String>, name: &String) -> Option<&Expr> {
        let mut state = self;
        loop {
            let v = state.namespaces
                         .get(ns.unwrap_or(&state.current))
                         .and_then(|scope| scope.get(name));
            if v.is_none() && state.parent.is_some() {
                state = state.parent.unwrap();
            } else {
                return v
            }
        }
    }

    pub fn get_current(&self) -> &String {
        &self.current
    }

    pub fn set_current(&mut self, current: String) -> String {
        if !self.namespaces.contains_key(&current) {
            self.namespaces.insert(current.clone(), Namespace::new());
        }
        let old_current = self.current.clone();
        self.current = current;
        old_current
    }

    pub fn next_id(&mut self) -> usize {
        let next = self.id;
        self.id += 1;
        next
    }
}
<commit_msg>Remove aliases<commit_after>#[cfg(test)]
mod tests;

use std::collections::HashMap;
use ast::Expr;

#[derive(Debug)]
struct Namespace {
    mappings: HashMap<String, Expr>,
}

impl Namespace {
    fn new() -> Namespace {
        Namespace {
            mappings: HashMap::new(),
        }
    }

    fn get(&self, name: &String) -> Option<&Expr> {
        self.mappings.get(name)
    }

    fn insert(&mut self, name: String, expr: Expr) -> Option<Expr> {
        self.mappings.insert(name, expr)
    }
}

#[derive(Debug)]
pub struct State<'s> {
    current: String,
    namespaces: HashMap<String, Namespace>,
    parent: Option<&'s State<'s>>,
    id: usize,
}

impl<'s> State<'s> {
    pub fn new(current: String) -> State<'s> {
        let mut current_ns = Namespace::new();
        current_ns.insert("nil".to_string(), e_list![]);
        current_ns.insert("true".to_string(), e_bool!(true));
        current_ns.insert("false".to_string(), e_bool!(false));

        let mut namespaces = HashMap::new();
        namespaces.insert(current.clone(), current_ns);

        State {
            current: current,
            namespaces: namespaces,
            parent: None,
            id: 0,
        }
    }

    pub fn new_chained(parent: &'s State<'s>) -> State<'s> {
        let mut state = State::new(format!("{}_chained", parent.current));
        state.parent = Some(parent);
        state
    }

    pub fn insert(&mut self, name: String, expr: Expr) -> Option<Expr> {
        self.namespaces
            .get_mut(&self.current)
            .and_then(|scope| scope.insert(name, expr))
    }

    pub fn get(&self, ns: Option<&String>, name: &String) -> Option<&Expr> {
        let mut state = self;
        loop {
            let v = state.namespaces
                         .get(ns.unwrap_or(&state.current))
                         .and_then(|scope| scope.get(name));
            if v.is_none() && state.parent.is_some() {
                state = state.parent.unwrap();
            } else {
                return v
            }
        }
    }

    pub fn get_current(&self) -> &String {
        &self.current
    }

    pub fn set_current(&mut self, current: String) -> String {
        if !self.namespaces.contains_key(&current) {
            self.namespaces.insert(current.clone(), Namespace::new());
        }
        let old_current = self.current.clone();
        self.current = current;
        old_current
    }

    pub fn next_id(&mut self) -> usize {
        let next = self.id;
        self.id += 1;
        next
    }
}
<|endoftext|>


<commit_before>#![macro_escape]

extern crate time;

use std::cell::{RefCell, Ref};
use std::rc::Rc;
use std::collections::HashMap;

/// A simple stopwatch taht can time events and print stats about them.
#[deriving(Send)]
pub struct Stopwatch {
  pub total_time: u64,
  // number of time windows we've clocked
  pub number_of_windows: u64,
}

impl Stopwatch {
  #[inline]
  /// Creates a new stopwatch.
  pub fn new() -> Stopwatch {
    Stopwatch {
      total_time: 0,
      number_of_windows: 0,
    }
  }

  #[inline]
  /// Times a function, updating stats as necessary.
  pub fn timed<T>(&mut self, event: | | -> T) -> T {
    let then = time::precise_time_ns();
    let ret = event();
    self.total_time += time::precise_time_ns() - then;
    self.number_of_windows += 1;
    ret
  }

  /// Prints out timing statistics of this stopwatch.
  fn print(&self, name: &str) {
    if self.number_of_windows == 0 {
      println!("{} never ran", name);
    } else {
      println!(
        "{}: {}ms over {} samples (avg {}us)",
        name,
        self.total_time / 1000000,
        self.number_of_windows,
        (self.total_time / self.number_of_windows / 1000),
      );
    }
  }

}

/// A set of stopwatches for multiple, named events.
pub struct TimerSet {
  timers: RefCell<HashMap<String, Rc<RefCell<Stopwatch>>>>,
}

impl TimerSet {
  /// Creates a new set of timers.
  pub fn new() -> TimerSet {
    TimerSet { timers: RefCell::new(HashMap::new()) }
  }

  /// Times the execution of a function, and logs it under a timer with
  /// the given name.
  ///
  /// You probably want to use the `time!` macro instead of using this
  /// directly.
  ///
  /// This function is not marked `mut` because borrow checking is done
  /// dynamically.
  pub fn time<T>(&self, name: &str, f: || -> T) -> T {
    let has_key = self.timers.borrow().contains_key_equiv(&name);

    let timer : Rc<RefCell<Stopwatch>> =
      if has_key {
        self.timers.borrow().find_equiv(&name).unwrap().clone()
      } else {
        {
          self.timers
              .borrow_mut()
              .insert(String::from_str(name), Rc::new(RefCell::new(Stopwatch::new())));
        }
        self.timers.borrow().find_equiv(&name).unwrap().clone()
      };

    timer.borrow_mut().timed(f)
  }

  /// Prints all the timer statistics to stdout, each tagged with their name.
  pub fn print(&self) {
    let timers = self.timers.borrow();

    let mut timer_vec : Vec<(&str, Ref<Stopwatch>)> =
      timers
        .iter()
        .map(|(name, sw)| (name.as_slice(), sw.borrow()))
        .collect();

    timer_vec.sort_by(|&(k1, _), &(k2, _)| k1.cmp(&k2));

    for &(name, ref timer) in timer_vec.iter() {
      timer.print(name);
    }
  }
}

#[test]
fn test_simple() {
  let ts = TimerSet::new();
  ts.time("hello", || {});
}

#[test]
fn test_nested() {
  let ts = TimerSet::new();
  ts.time("hello", || {
    ts.time("world", || {});
  });
}

#[macro_export]
macro_rules! time(
  ($timers:expr, $name:expr, $f:expr) => (
    unsafe { unwrap!(($timers as *const stopwatch::TimerSet).to_option()) }.time($name, $f)
  );
)
<commit_msg>added check for recursive usage of the same timer<commit_after>#![macro_escape]

extern crate time;

use std::cell::{RefCell, Ref};
use std::rc::Rc;
use std::collections::HashMap;

/// A simple stopwatch taht can time events and print stats about them.
#[deriving(Send)]
pub struct Stopwatch {
  pub total_time: u64,
  // number of time windows we've clocked
  pub number_of_windows: u64,
}

impl Stopwatch {
  #[inline]
  /// Creates a new stopwatch.
  pub fn new() -> Stopwatch {
    Stopwatch {
      total_time: 0,
      number_of_windows: 0,
    }
  }

  #[inline]
  /// Times a function, updating stats as necessary.
  pub fn timed<T>(&mut self, event: | | -> T) -> T {
    let then = time::precise_time_ns();
    let ret = event();
    self.total_time += time::precise_time_ns() - then;
    self.number_of_windows += 1;
    ret
  }

  /// Prints out timing statistics of this stopwatch.
  fn print(&self, name: &str) {
    if self.number_of_windows == 0 {
      println!("{} never ran", name);
    } else {
      println!(
        "{}: {}ms over {} samples (avg {}us)",
        name,
        self.total_time / 1000000,
        self.number_of_windows,
        (self.total_time / self.number_of_windows / 1000),
      );
    }
  }

}

/// A set of stopwatches for multiple, named events.
pub struct TimerSet {
  timers: RefCell<HashMap<String, Rc<RefCell<Stopwatch>>>>,
}

impl TimerSet {
  /// Creates a new set of timers.
  pub fn new() -> TimerSet {
    TimerSet { timers: RefCell::new(HashMap::new()) }
  }

  /// Times the execution of a function, and logs it under a timer with
  /// the given name.
  ///
  /// You probably want to use the `time!` macro instead of using this
  /// directly.
  ///
  /// This function is not marked `mut` because borrow checking is done
  /// dynamically.
  pub fn time<T>(&self, name: &str, f: || -> T) -> T {
    if !self.timers.borrow().contains_key_equiv(&name) {
      self.timers
          .borrow_mut()
          .insert(String::from_str(name), Rc::new(RefCell::new(Stopwatch::new())));
    };

    let timer : Rc<RefCell<Stopwatch>> =
      self.timers.borrow().find_equiv(&name).unwrap().clone();

    match timer.try_borrow_mut() {
      None => fail!("timer \"{}\" used recursively", name),
      Some(mut timer) => timer.timed(f),
    }
  }

  /// Prints all the timer statistics to stdout, each tagged with their name.
  pub fn print(&self) {
    let timers = self.timers.borrow();

    let mut timer_vec : Vec<(&str, Ref<Stopwatch>)> =
      timers
        .iter()
        .map(|(name, sw)| (name.as_slice(), sw.borrow()))
        .collect();

    timer_vec.sort_by(|&(k1, _), &(k2, _)| k1.cmp(&k2));

    for &(name, ref timer) in timer_vec.iter() {
      timer.print(name);
    }
  }
}

#[test]
fn test_simple() {
  let ts = TimerSet::new();
  ts.time("hello", || {});
}

#[test]
fn test_nested() {
  let ts = TimerSet::new();
  ts.time("hello", || {
    ts.time("world", || {});
  });
}

#[macro_export]
macro_rules! time(
  ($timers:expr, $name:expr, $f:expr) => (
    unsafe { unwrap!(($timers as *const stopwatch::TimerSet).to_option()) }.time($name, $f)
  );
)
<|endoftext|>


<commit_before>/// The tokenizer for the query interpreter

use error::*;
use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub enum Token {
    Identifier {
        ident: String,
        next: Option<Rc<Token>>
    },

    Index {
        idx: i64,
        next: Option<Rc<Token>>
    }
}

impl Token {

    #[cfg(test)]
    pub fn identifier(&self) -> &String {
        match self {
            &Token::Identifier { ident: ref ident, .. } => &ident,
            _ => unreachable!(),
        }
    }

    #[cfg(test)]
    pub fn idx(&self) -> i64 {
        match self {
            &Token::Index { idx: i, .. } => i,
            _ => unreachable!(),
        }
    }
}

pub fn tokenize_with_seperator(query: &String, seperator: char) -> Result<Token> {
    unimplemented!()
}

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier {
                ident: ident,
                next: None
            } => {
                assert_eq!(String::from("example"), ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        use std::ops::Deref;

        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Rc::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Rc::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Rc::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    quickcheck! {
        fn test_array_index(i: i64) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index {
                    idx: i,
                    next: None,
                }) => true,
                _ => false,
            }
        }
    }

}
<commit_msg>Impl tokenize_with_seperator to fix test_tokenize_empty_query_to_error<commit_after>/// The tokenizer for the query interpreter

use error::*;
use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub enum Token {
    Identifier {
        ident: String,
        next: Option<Rc<Token>>
    },

    Index {
        idx: i64,
        next: Option<Rc<Token>>
    }
}

impl Token {

    #[cfg(test)]
    pub fn identifier(&self) -> &String {
        match self {
            &Token::Identifier { ident: ref ident, .. } => &ident,
            _ => unreachable!(),
        }
    }

    #[cfg(test)]
    pub fn idx(&self) -> i64 {
        match self {
            &Token::Index { idx: i, .. } => i,
            _ => unreachable!(),
        }
    }
}

pub fn tokenize_with_seperator(query: &String, seperator: char) -> Result<Token> {
    return Err(Error::from(ErrorKind::EmptyQueryError))
}

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

    use std::ops::Deref;

    #[test]
    fn test_tokenize_empty_query_to_error() {
        let tokens = tokenize_with_seperator(&String::from(""), '.');
        assert!(tokens.is_err());
        let tokens = tokens.unwrap_err();

        let errkind = tokens.kind();
        assert!(is_match!(errkind, &ErrorKind::EmptyQueryError { .. }));
    }

    #[test]
    fn test_tokenize_single_token_query() {
        let tokens = tokenize_with_seperator(&String::from("example"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier {
                ident: ident,
                next: None
            } => {
                assert_eq!(String::from("example"), ident);
                true
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_double_token_query() {
        let tokens = tokenize_with_seperator(&String::from("a.b"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                assert_eq!("b", next.deref().identifier());
                match next.deref() {
                    &Token::Identifier { next: None, .. } => true,
                    _ => false
                }
            },
            _ => false,
        });
        assert_eq!("a", tokens.identifier());
    }

    #[test]
    fn test_tokenize_ident_then_array_query() {
        let tokens = tokenize_with_seperator(&String::from("a.[0]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());
        assert!(match tokens {
            Token::Identifier { next: Some(ref next), .. } => {
                assert_eq!(1, Rc::strong_count(&next));
                match next.deref() {
                    &Token::Index { idx: 0, next: None } => true,
                    _ => false
                }
            },
            _ => false,
        });
    }

    #[test]
    fn test_tokenize_many_idents_then_array_query() {
        use std::ops::Deref;

        let tokens = tokenize_with_seperator(&String::from("a.b.c.[1000]"), '.');
        assert!(tokens.is_ok());
        let tokens = tokens.unwrap();

        assert_eq!("a", tokens.identifier());

        let expected =
            Token::Identifier {
                ident: String::from("a"),
                next: Some(Rc::new(Token::Identifier {
                    ident: String::from("b"),
                    next: Some(Rc::new(Token::Identifier {
                        ident: String::from("c"),
                        next: Some(Rc::new(Token::Index {
                            idx: 1000,
                            next: None,
                        })),
                    })),
                })),
            };

        assert_eq!(expected, tokens);
    }

    quickcheck! {
        fn test_array_index(i: i64) -> bool {
            match tokenize_with_seperator(&format!("[{}]", i), '.') {
                Ok(Token::Index {
                    idx: i,
                    next: None,
                }) => true,
                _ => false,
            }
        }
    }

}
<|endoftext|>


<commit_before>
use vertex::{RawVertex, Vertex};
use edge::{RawEdge, Edge};
use graph::TraversableToVertex;
use path::{Path, Element};
use std::iter::Extend;
use std::iter::Filter;

// use std::iter::Iterator;

// define a traversal as a series of stages

pub struct GraphQuery {
    // many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<Vertex>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
            let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

    pub fn get_paths(&self) -> &Vec<Path> {
        &self.paths
    }
    pub fn push(&mut self, path:Path) {
        self.paths.push(path)
    }

    /*
    generic mapper for our queries
    future this may use worker threads to perform
    traversals

    TODO make sure that if nothing comes back we don't keep it in the path

     */
    fn map<F: Fn(&Path) -> Vec<Element>>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
        for path in self.paths.iter() {
            let mut tmp = closure(&path);
            // let mut tmp2 = tmp.as_slice();
            // currently gets back a Vec<Path> but what if it gets Elements?
            let new_elements = path.permute(&tmp);
            result.paths.extend(new_elements);
        }
        result
    }

    pub fn outV(&self, labels: &[&str]) -> GraphQuery {
        // map can figure out the rest
        let f = |path: &Path| {
            //take the final element in the path
            let element = path.last().unwrap();

            let result : Vec<Element> = match element {
                &Element::Vertex(v) =>
                    v.outV(&labels).iter().map(|v| Element::Vertex(*v)).collect(),
                    // Vec::new(),
                &Element::Edge(ref e) =>
                    Vec::new()
            };
            // apply outV
            result
        };
        self.map(f)
    }

    pub fn filter<F: Fn(&&Path) -> bool>(&self, closure: F) -> GraphQuery {
        let result = GraphQuery::empty();
        // apply the filter to each path
        let tmp = self.paths.iter().filter(closure).map(|x| x.clone());
        let paths : Vec<Path> = tmp.collect();
        // result.paths = paths;
        return result
    }

//    pub fn inV(&self) -> GraphQuery {
//        let g = GraphQuery::empty();
//        let f = |element: &Element| {
//            element.inV()
//        };
//        self.map(f)
//    }
}
<commit_msg>may have working filtering<commit_after>
use vertex::{RawVertex, Vertex};
use edge::{RawEdge, Edge};
use graph::TraversableToVertex;
use path::{Path, Element};
use std::iter::Extend;
use std::iter::Filter;

// use std::iter::Iterator;

// define a traversal as a series of stages

pub struct GraphQuery {
    // many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<Vertex>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
            let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }
    pub fn new_with_paths(paths: Vec<Path>) -> GraphQuery {
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

    pub fn get_paths(&self) -> &Vec<Path> {
        &self.paths
    }
    pub fn push(&mut self, path:Path) {
        self.paths.push(path)
    }

    /*
    generic mapper for our queries
    future this may use worker threads to perform
    traversals

    TODO make sure that if nothing comes back we don't keep it in the path

     */
    fn map<F: Fn(&Path) -> Vec<Element>>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
        for path in self.paths.iter() {
            let mut tmp = closure(&path);
            // let mut tmp2 = tmp.as_slice();
            // currently gets back a Vec<Path> but what if it gets Elements?
            let new_elements = path.permute(&tmp);
            result.paths.extend(new_elements);
        }
        result
    }

    pub fn outV(&self, labels: &[&str]) -> GraphQuery {
        // map can figure out the rest
        let f = |path: &Path| {
            //take the final element in the path
            let element = path.last().unwrap();

            let result : Vec<Element> = match element {
                &Element::Vertex(v) =>
                    v.outV(&labels).iter().map(|v| Element::Vertex(*v)).collect(),
                    // Vec::new(),
                &Element::Edge(ref e) =>
                    Vec::new()
            };
            // apply outV
            result
        };
        self.map(f)
    }

    pub fn filter<F: Fn(&&Path) -> bool>(&self, closure: F) -> GraphQuery {
        // apply the filter to each path
        let tmp = self.paths.iter().filter(closure).map(|x| x.clone());
        let paths : Vec<Path> = tmp.collect();
        GraphQuery::new_with_paths(paths)
    }

//    pub fn inV(&self) -> GraphQuery {
//        let g = GraphQuery::empty();
//        let f = |element: &Element| {
//            element.inV()
//        };
//        self.map(f)
//    }
}
<|endoftext|>


<commit_before>use argparse::ArgumentStore;
use std::fs::{self, DirEntry, ReadDir};
use std::path::PathBuf;
use std::env;
use std::io::Result;
use std::ffi::OsString;

pub struct HitIterator<'a> {
    args: ArgumentStore<'a>,
    readdirs: Vec<ReadDir>,
}

// impl<'a> HitIterator<'a> {
//     fn new(args: ArgumentStore) -> HitIterator {
//     }
// }

impl<'a> Iterator for HitIterator<'a> {

    type Item = OsString;

    fn next(&mut self) -> Option<OsString> {
        if self.readdirs.len() == 0 {
            return None;
        }
        let mut readdir = self.readdirs.pop().unwrap();

        match readdir.next() {
            Some(v) => {
                // TODO dont panic, always retrun None on Error?
                // what if permission to one dir fails, but rest would work?
                self.readdirs.push(readdir);
                let entry = v.unwrap();
                if entry.file_type().unwrap().is_dir() {
                    self.readdirs.push(fs::read_dir(entry.path()).unwrap());
                    return self.next();
                }

                let filename = entry.file_name();
                if filename.to_str().unwrap().contains(self.args.pattern.unwrap()) {
                    return Some(filename);
                }

               return self.next();
            },
            None => {
                return self.next();
            }

        }

        //Some("hello")
        None
    }
}

fn find(args: ArgumentStore) -> Result<HitIterator> {

    let dir: PathBuf = if args.dir.is_some() {
        PathBuf::from(args.dir.unwrap())
    } else {
        env::current_dir().unwrap()
    };

    Ok(HitIterator {args: args, readdirs: vec![try!(fs::read_dir(dir))]})
}

//fn search(args: &ArgumentStore, callback: &Fn(&str)) {}

#[cfg(test)]
mod filesearchtest {

    use argparse::ArgumentStore;
    use std::path::PathBuf;
    use std::env;
    use std::io;
    use std::fs::remove_dir_all;
    use std::fs::create_dir;
    use std::fs::File;
    use filesearch::{self, HitIterator};
    //use filesearch::search;
    use std::ffi::OsString;

    fn createfile(path: &PathBuf, filename: &str) {
        let mut path = path.clone();
        path.push(filename);
        File::create(path).expect("Can not create file in temporary testing directory");
    }

    fn preparetestfiles() {
        let mut tempdir: PathBuf = env::temp_dir();
        tempdir.push("elicit_temporary_test_dir");
        if tempdir.exists() {
            remove_dir_all(&tempdir).expect("Can not remove old testing directory.");
        }
        create_dir(&tempdir).expect("Can not create temporary testing directory");

        createfile(&tempdir, "hello");
        createfile(&tempdir, "whatuphelloworld");
        createfile(&tempdir, "no_he_ll_o_in_this_file_name");
    }

    #[test]
    fn filesearch_by_pattern() {
        preparetestfiles();

        let mut tempdir: PathBuf = env::temp_dir();
        tempdir.push("elicit_temporary_test_dir");
        assert!(tempdir.exists());

        let args = ArgumentStore{pattern:Some("hello"), dir: tempdir.to_str(), isregex: false};

        let mut hititer = filesearch::find(args).unwrap();

        let mut results : Vec<OsString> = hititer.collect();
        results.sort();

        assert_eq!(results.len(), 2);
        assert_eq!(results[0], OsString::from("hello"));
        assert_eq!(results[1], OsString::from("whatuphelloworld"));
    }

}
<commit_msg>test and iterator for recursive search<commit_after>use argparse::ArgumentStore;
use std::fs::{self, DirEntry, ReadDir};
use std::path::PathBuf;
use std::env;
use std::io::Result;
use std::ffi::OsString;

pub struct HitIterator<'a> {
    args: ArgumentStore<'a>,
    readdirs: Vec<ReadDir>,
}

// impl<'a> HitIterator<'a> {
//     fn new(args: ArgumentStore) -> HitIterator {
//     }
// }

impl<'a> Iterator for HitIterator<'a> {

    type Item = OsString;

    fn next(&mut self) -> Option<OsString> {
        if self.readdirs.len() == 0 {
            return None;
        }
        //let mut readdir = self.readdirs.get_mut(0).unwrap();

        match self.readdirs.get_mut(0).unwrap().next() {
            Some(v) => {
                // TODO dont panic, always retrun None on Error?
                // what if permission to one dir fails, but rest would work?
                let entry = v.unwrap();
                if entry.file_type().unwrap().is_dir() {
                    //TODO lower levels should have the parent path in them (until search root levelt)
                    self.readdirs.push(fs::read_dir(entry.path()).unwrap());
                    return self.next();
                }

                let filename = entry.file_name();
                if filename.to_str().unwrap().contains(self.args.pattern.unwrap()) {
                    return Some(filename);
                }

               return self.next();
            },
            None => {
                self.readdirs.remove(0);
                return self.next();
            }

        }

        //Some("hello")
        None
    }
}

fn find(args: ArgumentStore) -> Result<HitIterator> {

    let dir: PathBuf = if args.dir.is_some() {
        PathBuf::from(args.dir.unwrap())
    } else {
        env::current_dir().unwrap()
    };

    Ok(HitIterator {args: args, readdirs: vec![try!(fs::read_dir(dir))]})
}

//fn search(args: &ArgumentStore, callback: &Fn(&str)) {}

#[cfg(test)]
mod filesearchtest {

    use argparse::ArgumentStore;
    use std::path::PathBuf;
    use std::env;
    use std::io;
    use std::fs::remove_dir_all;
    use std::fs::create_dir;
    use std::fs::File;
    use filesearch::{self, HitIterator};
    //use filesearch::search;
    use std::ffi::OsString;

    fn createfile(path: &PathBuf, filename: &str) {
        let mut path = path.clone();
        path.push(filename);
        File::create(path).expect("Can not create file in temporary testing directory");
    }

    fn preparetestfiles() {
        let mut tempdir: PathBuf = env::temp_dir();
        tempdir.push("elicit_temporary_test_dir");
        if tempdir.exists() {
            remove_dir_all(&tempdir).expect("Can not remove old testing directory.");
        }
        create_dir(&tempdir).expect("Can not create temporary testing directory");

        createfile(&tempdir, "hello");
        createfile(&tempdir, "whatuphelloworld");
        createfile(&tempdir, "no_he_ll_o_in_this_file_name");

        tempdir.push("2nd level");
        create_dir(&tempdir).expect("Can not create 2nd level temporary testing directory");

        createfile(&tempdir, "2nd level hello");
        createfile(&tempdir, "another none match");
        createfile(&tempdir, "xyz");

        tempdir.push("3rd level");
        create_dir(&tempdir).expect("Can not create 3rd level temporary testing directory");
        createfile(&tempdir, "hello from the 3rd level");
        createfile(&tempdir, "another none match");
    }

    #[test]
    fn filesearch_by_pattern() {
        preparetestfiles();

        let mut tempdir: PathBuf = env::temp_dir();
        tempdir.push("elicit_temporary_test_dir");
        assert!(tempdir.exists());

        let args = ArgumentStore{pattern:Some("hello"), dir: tempdir.to_str(), isregex: false};

        let mut hititer = filesearch::find(args).unwrap();

        let mut results : Vec<OsString> = hititer.collect();
        assert_eq!(results.len(), 4);
        let mut lvl2results = results.split_off(2);
        results.sort();

        assert_eq!(results[0], OsString::from("hello"));
        assert_eq!(results[1], OsString::from("whatuphelloworld"));
        assert_eq!(lvl2results[0], OsString::from("2nd level hello"));
        assert_eq!(lvl2results[1], OsString::from("hello from the 3rd level"));
    }

}
<|endoftext|>


<commit_before>use argparse::ArgumentStore;
use std::fs::{self, ReadDir};
use std::path::PathBuf;
use std::iter::Iterator;
use std::env;
use std::io::{self, Result, Error, Write};

pub struct HitIterator<'a> {
    args: ArgumentStore<'a>,
    readdirs: Vec<ReadDir>,
}

// impl<'a> HitIterator<'a> {
//     fn new(args: ArgumentStore) -> HitIterator {
//     }
// }

fn print_err(err: &Error) {
    let r = writeln!(&mut io::stderr(), "{}", err);
    r.expect("Failed to write error to stderr!");
}

impl<'a> Iterator for HitIterator<'a> {
    type Item = PathBuf;

    fn next(&mut self) -> Option<PathBuf> {
        if self.readdirs.len() == 0 {
            return None;
        }
        // TODO macro the error stuff, maybe allow the user to specify an error function
        // add the path to error where it occured (currently only "Permission denied (os error 13)")
        match self.readdirs.get_mut(0).unwrap().next() {
            Some(v) => {
                let entry = match v {
                    Ok(v) => v,
                    Err(e) => {
                        print_err(&e);
                        return self.next();
                    }
                };
                match entry.file_type() {
                    Ok(v) => {
                        if v.is_dir() {
                            match fs::read_dir(entry.path()) {
                                Ok(v) => {
                                    self.readdirs.push(v);
                                }
                                Err(e) => {
                                    print_err(&e);
                                }
                            }
                            return self.next();
                        }
                    }
                    Err(e) => {
                        print_err(&e);
                        return self.next();
                    }
                }

                let filename = entry.file_name();
                // TODO don't panic
                if filename.to_str().unwrap().contains(self.args.pattern.unwrap()) {
                    return Some(entry.path());
                }

                return self.next();
            }
            None => {
                self.readdirs.remove(0);
                return self.next();
            }

        }
    }
}

pub fn find(args: ArgumentStore) -> Result<HitIterator> {

    let dir: PathBuf = if args.dir.is_some() {
        PathBuf::from(args.dir.unwrap())
    } else {
        //TODO platform independent relative path
        PathBuf::from("./")
        // this would give the full current path
        //try![env::current_dir()]
    };

    Ok(HitIterator {
        args: args,
        readdirs: vec![try!(fs::read_dir(dir))],
    })
}

// fn search(args: &ArgumentStore, callback: &Fn(&str)) {}

#[cfg(test)]
mod filesearchtest {

    use argparse::ArgumentStore;
    use std::path::PathBuf;
    use std::env;
    use std::fs::remove_dir_all;
    use std::fs::create_dir;
    use std::fs::File;
    use filesearch::{self, HitIterator};

    fn createfile(path: &PathBuf, filename: &str) {
        let mut path = path.clone();
        path.push(filename);
        File::create(path).expect("Can not create file in temporary testing directory");
    }

    fn preparetestfiles() {
        let mut tempdir: PathBuf = env::temp_dir();
        tempdir.push("elicit_temporary_test_dir");
        if tempdir.exists() {
            remove_dir_all(&tempdir).expect("Can not remove old testing directory.");
        }
        create_dir(&tempdir).expect("Can not create temporary testing directory");

        createfile(&tempdir, "hello");
        createfile(&tempdir, "whatuphelloworld");
        createfile(&tempdir, "no_he_ll_o_in_this_file_name");

        tempdir.push("2nd level");
        create_dir(&tempdir).expect("Can not create 2nd level temporary testing directory");

        createfile(&tempdir, "2nd level hello");
        createfile(&tempdir, "another none match");
        createfile(&tempdir, "xyz");

        tempdir.push("3rd level");
        create_dir(&tempdir).expect("Can not create 3rd level temporary testing directory");

        createfile(&tempdir, "hello from the 3rd level");
        createfile(&tempdir, "another none match");
    }

    #[test]
    fn filesearch_by_pattern() {
        preparetestfiles();

        let mut tempdir: PathBuf = env::temp_dir();
        tempdir.push("elicit_temporary_test_dir");
        assert!(tempdir.exists());
        let dirstr = tempdir.to_str().unwrap();
        let args = ArgumentStore {
            pattern: Some("hello"),
            dir: Some(dirstr),
            isregex: false,
        };

        let hititer = filesearch::find(args).unwrap();

        let mut results: Vec<PathBuf> = hititer.collect();
        assert_eq!(results.len(), 4);
        let lvl2results = results.split_off(2);
        results.sort();

        //TODO use platform independent path separator
        assert_eq!(results[0].to_str().unwrap(), format!("{}/hello", dirstr));
        assert_eq!(results[1].to_str().unwrap(),
                   format!("{}/whatuphelloworld", dirstr));
        assert_eq!(lvl2results[0].to_str().unwrap(),
                   format!("{}/2nd level/2nd level hello", dirstr));
        assert_eq!(lvl2results[1].to_str().unwrap(),
                   format!("{}/2nd level/3rd level/hello from the 3rd level", dirstr));
    }
}
<commit_msg>simplified the iterator code with a helper method and try! macro<commit_after>use argparse::ArgumentStore;
use std::fs::{self, ReadDir, DirEntry};
use std::path::PathBuf;
use std::iter::Iterator;
use std::io::{self, Result, Error, Write};

pub struct HitIterator<'a> {
    args: ArgumentStore<'a>,
    readdirs: Vec<ReadDir>,
}

impl<'a> HitIterator<'a> {
    fn next_result(&mut self) -> Result<Option<PathBuf>> {

        if self.readdirs.len() == 0 {
            return Ok(None);
        }
        // get_mut should be save, because of the above check
        match self.readdirs.get_mut(0).unwrap().next() {
            Some(v) => {
                let entry: DirEntry = try!(v);
                if try!(entry.file_type()).is_dir() {
                    let nextreaddir = try!(fs::read_dir(entry.path()));
                    self.readdirs.push(nextreaddir);
                    return self.next_result();
                }

                let filename = entry.file_name();
                // TODO don't panic if the filename cannot be convertet to a string
                if filename.into_string().unwrap().contains(self.args.pattern.unwrap()) {
                    return Ok(Some(entry.path()));
                }

                return self.next_result();
            }
            None => {
                self.readdirs.remove(0);
                return self.next_result();
            }

        }
    }
}

fn print_err(err: &Error) {
    let r = writeln!(&mut io::stderr(), "{}", err);
    r.expect("Failed to write error to stderr!");
}

impl<'a> Iterator for HitIterator<'a> {
    type Item = PathBuf;

    fn next(&mut self) -> Option<PathBuf> {
        match self.next_result() {
            Ok(res) => {
                return res;
            }
            Err(e) => {
                print_err(&e);
                return self.next();
            }
        };
    }
}

pub fn find(args: ArgumentStore) -> Result<HitIterator> {

    let dir: PathBuf = if args.dir.is_some() {
        PathBuf::from(args.dir.unwrap())
    } else {
        // TODO platform independent relative path
        PathBuf::from("./")
        // this would give the full current path
        // try![env::current_dir()]
    };

    Ok(HitIterator {
        args: args,
        readdirs: vec![try!(fs::read_dir(dir))],
    })
}

// fn search(args: &ArgumentStore, callback: &Fn(&str)) {}

#[cfg(test)]
mod filesearchtest {

    use argparse::ArgumentStore;
    use std::path::PathBuf;
    use std::env;
    use std::fs::remove_dir_all;
    use std::fs::create_dir;
    use std::fs::File;
    use filesearch::{self, HitIterator};

    fn createfile(path: &PathBuf, filename: &str) {
        let mut path = path.clone();
        path.push(filename);
        File::create(path).expect("Can not create file in temporary testing directory");
    }

    fn preparetestfiles() {
        let mut tempdir: PathBuf = env::temp_dir();
        tempdir.push("elicit_temporary_test_dir");
        if tempdir.exists() {
            remove_dir_all(&tempdir).expect("Can not remove old testing directory.");
        }
        create_dir(&tempdir).expect("Can not create temporary testing directory");

        createfile(&tempdir, "hello");
        createfile(&tempdir, "whatuphelloworld");
        createfile(&tempdir, "no_he_ll_o_in_this_file_name");

        tempdir.push("2nd level");
        create_dir(&tempdir).expect("Can not create 2nd level temporary testing directory");

        createfile(&tempdir, "2nd level hello");
        createfile(&tempdir, "another none match");
        createfile(&tempdir, "xyz");

        tempdir.push("3rd level");
        create_dir(&tempdir).expect("Can not create 3rd level temporary testing directory");

        createfile(&tempdir, "hello from the 3rd level");
        createfile(&tempdir, "another none match");
    }

    #[test]
    fn filesearch_by_pattern() {
        preparetestfiles();

        let mut tempdir: PathBuf = env::temp_dir();
        tempdir.push("elicit_temporary_test_dir");
        assert!(tempdir.exists());
        let dirstr = tempdir.to_str().unwrap();
        let args = ArgumentStore {
            pattern: Some("hello"),
            dir: Some(dirstr),
            isregex: false,
        };

        let hititer = filesearch::find(args).unwrap();

        let mut results: Vec<PathBuf> = hititer.collect();
        assert_eq!(results.len(), 4);
        let lvl2results = results.split_off(2);
        results.sort();

        // TODO use platform independent path separator
        assert_eq!(results[0].to_str().unwrap(), format!("{}/hello", dirstr));
        assert_eq!(results[1].to_str().unwrap(),
                   format!("{}/whatuphelloworld", dirstr));
        assert_eq!(lvl2results[0].to_str().unwrap(),
                   format!("{}/2nd level/2nd level hello", dirstr));
        assert_eq!(lvl2results[1].to_str().unwrap(),
                   format!("{}/2nd level/3rd level/hello from the 3rd level", dirstr));
    }
}
<|endoftext|>


<commit_before>//! Headers container, and common header fields.
//!
//! hyper has the opinion that Headers should be strongly-typed, because that's
//! why we're using Rust in the first place. To set or get any header, an object
//! must implement the `Header` trait from this module. Several common headers
//! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others.
use std::ascii::{AsciiExt, ASCII_LOWER_MAP};
use std::fmt::{mod, Show};
use std::hash;
use std::intrinsics::TypeId;
use std::mem::{transmute, transmute_copy};
use std::raw::TraitObject;
use std::str::{from_utf8, SendStr, Slice, Owned};
use std::string::raw;
use std::collections::hashmap::{HashMap, Entries, Occupied, Vacant};

use uany::UncheckedAnyDowncast;
use typeable::Typeable;

use http::read_header;
use {HttpResult};

/// Common Headers
pub mod common;

/// A trait for any object that will represent a header field and value.
pub trait Header: Typeable {
    /// Returns the name of the header field this belongs to.
    ///
    /// The market `Option` is to hint to the type system which implementation
    /// to call. This can be done away with once UFCS arrives.
    fn header_name(marker: Option<Self>) -> &'static str;
    /// Parse a header from a raw stream of bytes.
    ///
    /// It's possible that a request can include a header field more than once,
    /// and in that case, the slice will have a length greater than 1. However,
    /// it's not necessarily the case that a Header is *allowed* to have more
    /// than one field value. If that's the case, you **should** return `None`
    /// if `raw.len() > 1`.
    fn parse_header(raw: &[Vec<u8>]) -> Option<Self>;
    /// Format a header to be output into a TcpStream.
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result;
}

#[doc(hidden)]
trait Is {
    fn is<T: 'static>(self) -> bool;
}

impl<'a> Is for &'a Header {
    fn is<T: 'static>(self) -> bool {
        self.get_type() == TypeId::of::<T>()
    }
}

impl<'a> UncheckedAnyDowncast<'a> for &'a Header {
    #[inline]
    unsafe fn downcast_ref_unchecked<T: 'static>(self) -> &'a T {
        let to: TraitObject = transmute_copy(&self);
        transmute(to.data)
    }
}

fn header_name<T: Header>() -> &'static str {
    let name = Header::header_name(None::<T>);
    name
}

/// A map of header fields on requests and responses.
pub struct Headers {
    data: HashMap<CaseInsensitive, Item>
}

impl Headers {

    /// Creates a new, empty headers map.
    pub fn new() -> Headers {
        Headers {
            data: HashMap::new()
        }
    }

    #[doc(hidden)]
    pub fn from_raw<R: Reader>(rdr: &mut R) -> HttpResult<Headers> {
        let mut headers = Headers::new();
        loop {
            match try!(read_header(rdr)) {
                Some((name, value)) => {
                    // read_header already checks that name is a token, which
                    // means its safe utf8
                    let name = unsafe {
                        raw::from_utf8(name)
                    };

                    let item = match headers.data.entry(CaseInsensitive(Owned(name))) {
                        Vacant(entry) => entry.set(Raw(vec![])),
                        Occupied(entry) => entry.into_mut()
                    };

                    match *item {
                        Raw(ref mut raw) => raw.push(value),
                        // Unreachable
                        _ => {}
                    };
                },
                None => break,
            }
        }
        Ok(headers)
    }

    /// Set a header field to the corresponding value.
    ///
    /// The field is determined by the type of the value being set.
    pub fn set<H: Header>(&mut self, value: H) {
        self.data.insert(CaseInsensitive(Slice(header_name::<H>())), Typed(box value as Box<Header>));
    }

    /// Get a clone of the header field's value, if it exists.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let content_type = headers.get::<ContentType>();
    /// ```
    pub fn get<H: Header + Clone>(&mut self) -> Option<H> {
        self.get_ref().map(|v: &H| v.clone())
    }

    /// Access the raw value of a header, if it exists and has not
    /// been already parsed.
    ///
    /// If the header field has already been parsed into a typed header,
    /// then you *must* access it through that representation.
    ///
    /// Example:
    /// ```
    /// # use hyper::header::Headers;
    /// # let mut headers = Headers::new();
    /// let raw_content_type = unsafe { headers.get_raw("content-type") };
    /// ```
    pub unsafe fn get_raw(&self, name: &'static str) -> Option<&[Vec<u8>]> {
        self.data.find(&CaseInsensitive(Slice(name))).and_then(|item| {
            match *item {
                Raw(ref raw) => Some(raw.as_slice()),
                _ => None
            }
        })
    }

    /// Get a reference to the header field's value, if it exists.
    pub fn get_ref<H: Header>(&mut self) -> Option<&H> {
        self.data.find_mut(&CaseInsensitive(Slice(header_name::<H>()))).and_then(|item| {
            debug!("get_ref, name={}, val={}", header_name::<H>(), item);
            let header = match *item {
                // Huge borrowck hack here, should be refactored to just return here.
                Typed(ref typed) if typed.is::<H>() => None,
                // Typed, wrong type
                Typed(_) => return None,
                Raw(ref raw) => match Header::parse_header(raw.as_slice()) {
                    Some::<H>(h) => {
                        Some(h)
                    },
                    None => return None
                },
            };

            match header {
                Some(header) => {
                    *item = Typed(box header as Box<Header>);
                    Some(item)
                },
                None => {
                    Some(item)
                }
            }
        }).and_then(|item| {
            debug!("downcasting {}", item);
            let ret = match *item {
                Typed(ref val) => {
                    unsafe { Some(val.downcast_ref_unchecked()) }
                },
                _ => unreachable!()
            };
            ret
        })
    }

    /// Returns a boolean of whether a certain header is in the map.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let has_type = headers.has::<ContentType>();
    /// ```
    pub fn has<H: Header>(&self) -> bool {
        self.data.contains_key(&CaseInsensitive(Slice(header_name::<H>())))
    }

    /// Removes a header from the map, if one existed.
    /// Returns true if a header has been removed.
    pub fn remove<H: Header>(&mut self) -> bool {
        self.data.remove(&CaseInsensitive(Slice(Header::header_name(None::<H>))))
    }

    /// Returns an iterator over the header fields.
    pub fn iter<'a>(&'a self) -> HeadersItems<'a> {
        HeadersItems {
            inner: self.data.iter()
        }
    }
}

impl fmt::Show for Headers {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!("Headers {\n".fmt(fmt));
        for (k, v) in self.iter() {
            try!(write!(fmt, "\t{}: {}\n", k, v));
        }
        "}".fmt(fmt)
    }
}

/// An `Iterator` over the fields in a `Headers` map.
pub struct HeadersItems<'a> {
    inner: Entries<'a, CaseInsensitive, Item>
}

impl<'a> Iterator<(&'a str, HeaderView<'a>)> for HeadersItems<'a> {
    fn next(&mut self) -> Option<(&'a str, HeaderView<'a>)> {
        match self.inner.next() {
            Some((k, v)) => Some((k.as_slice(), HeaderView(v))),
            None => None
        }
    }
}

/// Returned with the `HeadersItems` iterator.
pub struct HeaderView<'a>(&'a Item);

impl<'a> fmt::Show for HeaderView<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let HeaderView(item) = *self;
        item.fmt(fmt)
    }
}

impl Collection for Headers {
    fn len(&self) -> uint {
        self.data.len()
    }
}

impl Mutable for Headers {
    fn clear(&mut self) {
        self.data.clear()
    }
}

enum Item {
    Raw(Vec<Vec<u8>>),
    Typed(Box<Header>)
}

impl fmt::Show for Item {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Typed(ref h) => h.fmt_header(fmt),
            Raw(ref raw) => {
                for part in raw.iter() {
                    try!(fmt.write(part.as_slice()));
                }
                Ok(())
            },
        }
    }
}

struct CaseInsensitive(SendStr);

impl Str for CaseInsensitive {
    fn as_slice(&self) -> &str {
        let CaseInsensitive(ref s) = *self;
        s.as_slice()
    }

}

impl fmt::Show for CaseInsensitive {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(fmt)
    }
}

impl PartialEq for CaseInsensitive {
    fn eq(&self, other: &CaseInsensitive) -> bool {
        self.as_slice().eq_ignore_ascii_case(other.as_slice())
    }
}

impl Eq for CaseInsensitive {}

impl<H: hash::Writer> hash::Hash<H> for CaseInsensitive {
    #[inline]
    fn hash(&self, hasher: &mut H) {
        for byte in self.as_slice().bytes() {
            hasher.write([ASCII_LOWER_MAP[byte as uint]].as_slice());
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io::MemReader;
    use std::fmt;
    use std::str::Slice;
    use std::hash::sip::hash;
    use mime::{Mime, Text, Plain};
    use super::CaseInsensitive;
    use super::{Headers, Header};
    use super::common::{ContentLength, ContentType};

    fn mem(s: &str) -> MemReader {
        MemReader::new(s.as_bytes().to_vec())
    }

    #[test]
    fn test_case_insensitive() {
        let a = CaseInsensitive(Slice("foobar"));
        let b = CaseInsensitive(Slice("FOOBAR"));

        assert_eq!(a, b);
        assert_eq!(hash(&a), hash(&b));
    }

    #[test]
    fn test_from_raw() {
        let mut headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        assert_eq!(headers.get_ref(), Some(&ContentLength(10)));
    }

    #[test]
    fn test_content_type() {
        let content_type = Header::parse_header(["text/plain".as_bytes().to_vec()].as_slice());
        assert_eq!(content_type, Some(ContentType(Mime(Text, Plain, vec![]))));
    }

    #[deriving(Clone)]
    struct CrazyLength(Option<bool>, uint);

    impl Header for CrazyLength {
        fn header_name(_: Option<CrazyLength>) -> &'static str {
            "content-length"
        }
        fn parse_header(raw: &[Vec<u8>]) -> Option<CrazyLength> {
            use std::str::from_utf8;
            use std::from_str::FromStr;

            if raw.len() != 1 {
                return None;
            }
            // we JUST checked that raw.len() == 1, so raw[0] WILL exist.
            match from_utf8(unsafe { raw.as_slice().unsafe_get(0).as_slice() }) {
                Some(s) => FromStr::from_str(s),
                None => None
            }.map(|u| CrazyLength(Some(false), u))
        }
        fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            use std::fmt::Show;
            let CrazyLength(_, ref value) = *self;
            value.fmt(fmt)
        }
    }

    #[test]
    fn test_different_structs_for_same_header() {
        let mut headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        let ContentLength(_) = headers.get::<ContentLength>().unwrap();
        assert!(headers.get::<CrazyLength>().is_none());
    }
}
<commit_msg>Store Header Items behind an RWLock<commit_after>//! Headers container, and common header fields.
//!
//! hyper has the opinion that Headers should be strongly-typed, because that's
//! why we're using Rust in the first place. To set or get any header, an object
//! must implement the `Header` trait from this module. Several common headers
//! are already provided, such as `Host`, `ContentType`, `UserAgent`, and others.
use std::ascii::{AsciiExt, ASCII_LOWER_MAP};
use std::fmt::{mod, Show};
use std::hash;
use std::intrinsics::TypeId;
use std::mem::{transmute, transmute_copy};
use std::raw::TraitObject;
use std::str::{from_utf8, SendStr, Slice, Owned};
use std::string::raw;
use std::collections::hashmap::{HashMap, Entries, Occupied, Vacant};
use std::sync::RWLock;

use uany::UncheckedAnyDowncast;
use typeable::Typeable;

use http::read_header;
use {HttpResult};

/// Common Headers
pub mod common;

/// A trait for any object that will represent a header field and value.
pub trait Header: Typeable + Send + Sync {
    /// Returns the name of the header field this belongs to.
    ///
    /// The market `Option` is to hint to the type system which implementation
    /// to call. This can be done away with once UFCS arrives.
    fn header_name(marker: Option<Self>) -> &'static str;
    /// Parse a header from a raw stream of bytes.
    ///
    /// It's possible that a request can include a header field more than once,
    /// and in that case, the slice will have a length greater than 1. However,
    /// it's not necessarily the case that a Header is *allowed* to have more
    /// than one field value. If that's the case, you **should** return `None`
    /// if `raw.len() > 1`.
    fn parse_header(raw: &[Vec<u8>]) -> Option<Self>;
    /// Format a header to be output into a TcpStream.
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result;
}

#[doc(hidden)]
trait Is {
    fn is<T: 'static>(self) -> bool;
}

impl<'a> Is for &'a Header {
    fn is<T: 'static>(self) -> bool {
        self.get_type() == TypeId::of::<T>()
    }
}

impl<'a> UncheckedAnyDowncast<'a> for &'a Header {
    #[inline]
    unsafe fn downcast_ref_unchecked<T: 'static>(self) -> &'a T {
        let to: TraitObject = transmute_copy(&self);
        transmute(to.data)
    }
}

fn header_name<T: Header>() -> &'static str {
    let name = Header::header_name(None::<T>);
    name
}

/// A map of header fields on requests and responses.
pub struct Headers {
    data: HashMap<CaseInsensitive, RWLock<Item>>
}

impl Headers {

    /// Creates a new, empty headers map.
    pub fn new() -> Headers {
        Headers {
            data: HashMap::new()
        }
    }

    #[doc(hidden)]
    pub fn from_raw<R: Reader>(rdr: &mut R) -> HttpResult<Headers> {
        let mut headers = Headers::new();
        loop {
            match try!(read_header(rdr)) {
                Some((name, value)) => {
                    // read_header already checks that name is a token, which
                    // means its safe utf8
                    let name = unsafe {
                        raw::from_utf8(name)
                    };

                    let name = CaseInsensitive(Owned(name));
                    let item = match headers.data.entry(name) {
                        Vacant(entry) => entry.set(RWLock::new(Raw(vec![]))),
                        Occupied(entry) => entry.into_mut()
                    };

                    match &mut *item.write() {
                        &Raw(ref mut raw) => raw.push(value),
                        // Unreachable
                        _ => {}
                    };
                },
                None => break,
            }
        }
        Ok(headers)
    }

    /// Set a header field to the corresponding value.
    ///
    /// The field is determined by the type of the value being set.
    pub fn set<H: Header>(&mut self, value: H) {
        self.data.insert(CaseInsensitive(Slice(header_name::<H>())), RWLock::new(Typed(box value as Box<Header + Send + Sync>)));
    }

    /// Get a clone of the header field's value, if it exists.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let content_type = headers.get::<ContentType>();
    /// ```
    pub fn get<H: Header + Clone>(&self) -> Option<H> {
        self.get_ref().map(|v: &H| v.clone())
    }

    /// Access the raw value of a header, if it exists and has not
    /// been already parsed.
    ///
    /// If the header field has already been parsed into a typed header,
    /// then you *must* access it through that representation.
    ///
    /// This operation is unsafe because the raw representation can be
    /// invalidated by lasting too long or by the header being parsed
    /// while you still have a reference to the data.
    ///
    /// Example:
    /// ```
    /// # use hyper::header::Headers;
    /// # let mut headers = Headers::new();
    /// let raw_content_type = unsafe { headers.get_raw("content-type") };
    /// ```
    pub unsafe fn get_raw(&self, name: &'static str) -> Option<*const [Vec<u8>]> {
        self.data.find(&CaseInsensitive(Slice(name))).and_then(|item| {
            match *item.read() {
                Raw(ref raw) => Some(raw.as_slice() as *const [Vec<u8>]),
                _ => None
            }
        })
    }

    /// Get a reference to the header field's value, if it exists.
    pub fn get_ref<H: Header>(&self) -> Option<&H> {
        self.data.find(&CaseInsensitive(Slice(header_name::<H>()))).and_then(|item| {
            let header = match *item.read() {
                // Huge borrowck hack here, should be refactored to just return here.
                Typed(ref typed) if typed.is::<H>() => None,
                // Typed, wrong type
                Typed(_) => return None,
                Raw(ref raw) => match Header::parse_header(raw.as_slice()) {
                    Some::<H>(h) => {
                        Some(h)
                    },
                    None => return None
                },
            };

            match header {
                Some(header) => {
                    *item.write() = Typed(box header as Box<Header + Send + Sync>);
                    Some(item)
                },
                None => {
                    Some(item)
                }
            }
        }).and_then(|item| {
            let read = item.read();
            debug!("downcasting {}", *read);
            let ret = match *read {
                Typed(ref val) => {
                    unsafe { Some(val.downcast_ref_unchecked()) }
                },
                _ => unreachable!()
            };
            unsafe { transmute::<Option<&H>, Option<&H>>(ret) }
        })
    }

    /// Returns a boolean of whether a certain header is in the map.
    ///
    /// Example:
    ///
    /// ```
    /// # use hyper::header::Headers;
    /// # use hyper::header::common::ContentType;
    /// # let mut headers = Headers::new();
    /// let has_type = headers.has::<ContentType>();
    /// ```
    pub fn has<H: Header>(&self) -> bool {
        self.data.contains_key(&CaseInsensitive(Slice(header_name::<H>())))
    }

    /// Removes a header from the map, if one existed.
    /// Returns true if a header has been removed.
    pub fn remove<H: Header>(&mut self) -> bool {
        self.data.remove(&CaseInsensitive(Slice(Header::header_name(None::<H>))))
    }

    /// Returns an iterator over the header fields.
    pub fn iter<'a>(&'a self) -> HeadersItems<'a> {
        HeadersItems {
            inner: self.data.iter()
        }
    }
}

impl fmt::Show for Headers {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!("Headers {\n".fmt(fmt));
        for (k, v) in self.iter() {
            try!(write!(fmt, "\t{}: {}\n", k, v));
        }
        "}".fmt(fmt)
    }
}

/// An `Iterator` over the fields in a `Headers` map.
pub struct HeadersItems<'a> {
    inner: Entries<'a, CaseInsensitive, RWLock<Item>>
}

impl<'a> Iterator<(&'a str, HeaderView<'a>)> for HeadersItems<'a> {
    fn next(&mut self) -> Option<(&'a str, HeaderView<'a>)> {
        match self.inner.next() {
            Some((k, v)) => Some((k.as_slice(), HeaderView(v))),
            None => None
        }
    }
}

/// Returned with the `HeadersItems` iterator.
pub struct HeaderView<'a>(&'a RWLock<Item>);

impl<'a> fmt::Show for HeaderView<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let HeaderView(item) = *self;
        item.read().fmt(fmt)
    }
}

impl Collection for Headers {
    fn len(&self) -> uint {
        self.data.len()
    }
}

impl Mutable for Headers {
    fn clear(&mut self) {
        self.data.clear()
    }
}

enum Item {
    Raw(Vec<Vec<u8>>),
    Typed(Box<Header + Send + Sync>)
}

impl fmt::Show for Item {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Typed(ref h) => h.fmt_header(fmt),
            Raw(ref raw) => {
                for part in raw.iter() {
                    try!(fmt.write(part.as_slice()));
                }
                Ok(())
            },
        }
    }
}

struct CaseInsensitive(SendStr);

impl Str for CaseInsensitive {
    fn as_slice(&self) -> &str {
        let CaseInsensitive(ref s) = *self;
        s.as_slice()
    }

}

impl fmt::Show for CaseInsensitive {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(fmt)
    }
}

impl PartialEq for CaseInsensitive {
    fn eq(&self, other: &CaseInsensitive) -> bool {
        self.as_slice().eq_ignore_ascii_case(other.as_slice())
    }
}

impl Eq for CaseInsensitive {}

impl<H: hash::Writer> hash::Hash<H> for CaseInsensitive {
    #[inline]
    fn hash(&self, hasher: &mut H) {
        for byte in self.as_slice().bytes() {
            hasher.write([ASCII_LOWER_MAP[byte as uint]].as_slice());
        }
    }
}

#[cfg(test)]
mod tests {
    use std::io::MemReader;
    use std::fmt;
    use std::str::Slice;
    use std::hash::sip::hash;
    use mime::{Mime, Text, Plain};
    use super::CaseInsensitive;
    use super::{Headers, Header};
    use super::common::{ContentLength, ContentType};

    fn mem(s: &str) -> MemReader {
        MemReader::new(s.as_bytes().to_vec())
    }

    #[test]
    fn test_case_insensitive() {
        let a = CaseInsensitive(Slice("foobar"));
        let b = CaseInsensitive(Slice("FOOBAR"));

        assert_eq!(a, b);
        assert_eq!(hash(&a), hash(&b));
    }

    #[test]
    fn test_from_raw() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        assert_eq!(headers.get_ref(), Some(&ContentLength(10)));
    }

    #[test]
    fn test_content_type() {
        let content_type = Header::parse_header(["text/plain".as_bytes().to_vec()].as_slice());
        assert_eq!(content_type, Some(ContentType(Mime(Text, Plain, vec![]))));
    }

    #[deriving(Clone)]
    struct CrazyLength(Option<bool>, uint);

    impl Header for CrazyLength {
        fn header_name(_: Option<CrazyLength>) -> &'static str {
            "content-length"
        }
        fn parse_header(raw: &[Vec<u8>]) -> Option<CrazyLength> {
            use std::str::from_utf8;
            use std::from_str::FromStr;

            if raw.len() != 1 {
                return None;
            }
            // we JUST checked that raw.len() == 1, so raw[0] WILL exist.
            match from_utf8(unsafe { raw.as_slice().unsafe_get(0).as_slice() }) {
                Some(s) => FromStr::from_str(s),
                None => None
            }.map(|u| CrazyLength(Some(false), u))
        }
        fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            use std::fmt::Show;
            let CrazyLength(_, ref value) = *self;
            value.fmt(fmt)
        }
    }

    #[test]
    fn test_different_structs_for_same_header() {
        let headers = Headers::from_raw(&mut mem("Content-Length: 10\r\n\r\n")).unwrap();
        let ContentLength(_) = headers.get::<ContentLength>().unwrap();
        assert!(headers.get::<CrazyLength>().is_none());
    }
}

<|endoftext|>


<commit_before>/*! Functions for changing world and entity state. */

use std::io::prelude::*;
use std::path::{Path};
use std::fs::{self, File};
use rand::StdRng;
use rand::SeedableRng;
use std::iter::Filter;
use calx::{Dijkstra, Dir6};
use calx_ecs::{Entity};
use world::{World};
use flags;
use area::{Area};
use location::{Location};
use content::{Biome, AreaSpec};
use item::{Slot};
use components::{CompositeStats};
use ::{Msg};
use msg;
use query::{self, ControlState};

/// Player input action.
#[derive(Copy, Eq, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum Input {
    /// Take a step in the given direction.
    Step(Dir6),
    /// Melee attack in the given direction.
    Melee(Dir6),
    /// Shoot in the given direction.
    Shoot(Dir6),
    /// Do nothing for a turn.
    Pass,
}

/// Top-level game state update function. Only valid to call if
/// control_state() returned ReadyToUpdate.
pub fn update(w: &mut World) {
    assert!(query::control_state(w) == ControlState::ReadyToUpdate);

    ai_main(w);

    w.flags.tick += 1;
    w.flags.player_acted = false;
}

/// Run AI for all autonomous mobs.
fn ai_main(w: &mut World) {
    let actives: Vec<Entity> = w.ecs.brain.iter().map(|(&e, _)| e).collect();
    for e in actives.into_iter() { update_entity(w, e); }
}

pub fn update_entity(w: &mut World, e: Entity) {
    if query::is_mob(w, e) && !query::is_player(w, e) && query::ticks_this_frame(w, e) {
        mob_ai(w, e);
    }
}

pub fn mob_ai(w: &mut World, e: Entity) {
    unimplemented!();
    /*
        assert!(self.is_mob());
        assert!(!self.is_player());
        assert!(self.ticks_this_frame());

        if self.brain_state() == Some(BrainState::Asleep) {
            if let Some(p) = action::player() {
                // TODO: Line-of-sight, stealth concerns, other enemies than
                // player etc.
                if let Some(d) = p.distance_from(self) {
                    if d < 6 {
                        self.wake_up();
                    }
                }
            }

            return;
        }

        if let Some(p) = action::player() {
            let loc = self.location().expect("no location");

            let vec_to_enemy = loc.v2_at(p.location().expect("no location"));
            if let Some(v) = vec_to_enemy {
                if v.hex_dist() == 1 {
                    // Melee range, hit.
                    self.melee(Dir6::from_v2(v));
                } else {
                    // Walk towards.
                    let pathing_depth = 16;
                    let pathing = Dijkstra::new(
                        vec![p.location().expect("no location")], |&loc| !loc.blocks_walk(),
                        pathing_depth);

                    let steps = pathing.sorted_neighbors(&loc);
                    if steps.len() > 0 {
                        self.step(loc.dir6_towards(steps[0]).expect("No loc pair orientation"));
                    } else {
                        self.step(rng().gen());
                        // TODO: Fall asleep if things get boring.
                    }
                }
            }
        }
        */
}

/// Give player input. Only valid to call if control_state() returned
/// AwaitingInput.
pub fn input(w: &mut World, input: Input) {
    assert!(query::control_state(w) == ControlState::AwaitingInput);
    let p = query::player(w).expect("No player to receive input");
    match input {
        Input::Step(d) => {
            step(w, p, d);
        }
        Input::Melee(d) => {
            melee(w, p, d);
        }
        Input::Shoot(d) => {
            shoot(w, p, d);
        }
        Input::Pass => {
        }
    }
    w.flags.player_acted = true;

    // Run one world update cycle right away, so that we don't get awkward
    // single frames rendered where the player has acted and the rest of the
    // world hasn't.
    if query::control_state(w) == ControlState::ReadyToUpdate {
        update(w);
    }
}

/// Try to move the entity in direction.
pub fn step(w: &mut World, e: Entity, dir: Dir6) {
    unimplemented!();
    /*
    let place = world::with(|w| w.spatial.get(self));
    if let Some(Place::At(loc)) = place {
        let new_loc = loc + dir.to_v2();
        if self.can_enter(new_loc) {
            world::with_mut(|w| w.spatial.insert_at(self, new_loc));
            self.on_move_to(new_loc);
        }
    }
    */
}

pub fn melee(w: &mut World, e: Entity, dir: Dir6) {
    unimplemented!();
    /*
    let loc = self.location().expect("no location") + dir.to_v2();
    if let Some(e) = loc.mob_at() {
        let us = self.stats();
        e.damage(us.power + us.attack);
    }
    */
}

pub fn shoot(w: &mut World, e: Entity, dir: Dir6) {
    unimplemented!();
    /*
    let stats = self.stats();

    if stats.ranged_range > 0 {
        action::shoot(self.location().unwrap(), dir, stats.ranged_range, stats.ranged_power);
    }
    */
}

pub fn pick_up(w: &mut World, picker: Entity, item: Entity) -> bool {
    if !query::can_be_picked_up(w, item) {
        return false;
    }

    match query::free_bag_slot(w, picker) {
        Some(slot) => {
            equip(w, item, picker, slot);
            return true;
        }
        // Inventory full.
        None => { return false; }
    }
}

/// Equip an item to a slot. Slot must be empty.
pub fn equip(w: &mut World, item: Entity, e: Entity, slot: Slot) {
    w.spatial.equip(item, e, slot);
    recompose_stats(w, e)
}

/// Generate composed stats from base stats and the stats of equipped items.
/// This function must be called after any operation that changes the composed
/// stats affecting state of an entity.
pub fn recompose_stats(w: &mut World, e: Entity) {
    let mut stats = query::base_stats(w, e);
    for &slot in [
        Slot::Body,
        Slot::Feet,
        Slot::Head,
        Slot::Melee,
        Slot::Ranged,
        Slot::TrinketF,
        Slot::TrinketG,
        Slot::TrinketH,
        Slot::TrinketI].iter() {
        if let Some(item) = w.spatial.entity_equipped(e, slot) {
            stats = stats + query::stats(w, item);
        }
    }

    w.ecs.composite_stats.insert(e, CompositeStats(stats));
}

pub fn start_level(w: &mut World, depth: i32) {
    let biome = match depth {
        1 => Biome::Overland,
        _ => Biome::Dungeon,
    };

    clear_nonplayers(w);

    let seed = w.flags.seed;

    w.area = Area::new(
        seed,
        AreaSpec::new(biome, depth));

    /*
    // TODO: Get spawns working again.
    let mut rng: StdRng = SeedableRng::from_seed(&[seed as usize + depth as usize][..]);
    for (spawn, loc) in world::with(|w| w.area.get_spawns()).into_iter() {
        spawn.spawn(&mut rng, loc);
    }
    */

    let start_loc = w.area.player_entrance();
    // Either reuse the existing player or create a new one.
    match query::player(w) {
        Some(p) => {
            forget_map(w, p);
            w.spatial.insert_at(p, start_loc);
        }
        None => {
            // TODO: Use factory.
            use calx::color;
            use content::Brush;
            use components::{Desc, MapMemory, Health, Brain, BrainState, Alignment};
            use stats::{Stats};
            use stats::Intrinsic::*;
            let player = w.ecs.make();
            w.ecs.desc.insert(player, Desc::new("player", Brush::Human, color::AZURE));
            w.ecs.map_memory.insert(player, MapMemory::new());
            w.ecs.brain.insert(player, Brain { state: BrainState::PlayerControl, alignment: Alignment::Good });
            w.ecs.stats.insert(player, Stats::new(10, &[Hands]).mana(5));
            recompose_stats(w, player);

            w.flags.player = Some(player);

            w.spatial.insert_at(player, start_loc);
            // TODO: run FOV
        }
    };
    w.flags.camera = start_loc;
}

fn clear_nonplayers(w: &mut World) {
    let po = query::player(w);
    let entities: Vec<Entity> = w.ecs.iter().map(|&e| e).collect();
    for e in entities.into_iter() {
        // Don't destroy player or player's inventory.
        if let Some(p) = po {
            if e == p || w.spatial.contains(p, e) {
                continue;
            }
        }

        if query::location(w, e).is_some() {
            w.ecs.remove(e);
        }
    }
}

/// Clear map memory of an entity.
pub fn forget_map(w: &mut World, e: Entity) {
    w.ecs.map_memory.get_mut(e).map(
        |mm| {
            mm.seen.clear();
            mm.remembered.clear();
        });
}

/*
/// Return the player entity if one exists.
pub fn player() -> Option<Entity> {
    world::with(|w| w.flags.player)
}

/// Return true if the game has ended and the player can make no further
/// actions.
pub fn is_game_over() -> bool {
    player().is_none()
}

/// Spawn a specific type of entity
pub fn spawn_named(name: &str, loc: Location) -> Result<Entity, ()> {
    unimplemented!();
}

// World update state machine //////////////////////////////////////////

/// Get the current control state.
pub fn control_state() -> ControlState {
    if world::with(|w| w.flags.player_acted) { return ControlState::ReadyToUpdate; }
    match player() {
        Some(p) if p.acts_this_frame() => ControlState::AwaitingInput,
        _ => ControlState::ReadyToUpdate,
    }
}

// Entities ////////////////////////////////////////////////////////////

/// Return an iterator of all the world entities.
pub fn entities() -> EntityIter {
    world::with(|w| w.old_ecs.iter())
}

/// Return an iterator of all the world mobs.
pub fn _mobs() -> Filter<EntityIter, fn(&Entity) -> bool> {
    fn _is_mob(e: &Entity) -> bool { e.is_mob() }
    entities().filter(_is_mob)
}

// World logic /////////////////////////////////////////////////////////

/// Return the current floor depth. Greater depths mean more powerful monsters
/// and stranger terrain.
pub fn current_depth() -> i32 { world::with(|w| w.area.seed.spec.depth) }

/// Move the player to the next level.
pub fn next_level() {
    // This is assuming a really simple, original Rogue style descent-only, no
    // persistent maps style world.
    start_level(current_depth() + 1);
    caption!("Depth {}", current_depth() - 1);
}

// Effects /////////////////////////////////////////////////////////////

/// Create a projectile arc in dir from origin.
pub fn shoot(origin: Location, dir: Dir6, range: u32, power: i32) {
    let mut loc = origin;
    if range == 0 { return; }
    for i in 1..(range + 1) {
        loc = origin + dir.to_v2() * (i as i32);
        if loc.terrain().blocks_shot() {
            msg::push(::Msg::Sparks(loc));
            break;
        }
        if let Some(e) = loc.mob_at() {
            e.damage(power);
            break;
        }
    }
    msg::push(::Msg::Beam(origin, loc));
}

/// Generate an explosion at location.
pub fn explode(center: Location, power: i32) {
    // Add more complex parametrization if needed.
    msg::push(Msg::Explosion(center));

    // Damage the center.
    if let Some(e) = center.mob_at() {
        e.damage(power);
    }

    for d in Dir6::iter() {
        if let Some(e) = (center + d.to_v2()).mob_at() {
            // Explosions with enough power push back mobs.
            // TODO: Pushback might consider mob size, big guys get pushed
            // around less.
            let push_threshold = 4;
            if power >= push_threshold {
                e.push(*d, ((power - push_threshold) / 2 + 1) as u32);
            }
            if e.exists() {
                e.damage(power);
            }
        }
    }
}

////////////////////////////////////////////////////////////////////////

/// Build a Dijkstra map towards the unexplored corners of the player's FOV.
///
/// Pathing_depth is the depth of the search map. Low pathing depths may not
/// reach distant unexplored cells, but high pathing depths take longer to
/// calculate.
pub fn autoexplore_map(pathing_depth: u32) -> Option<Dijkstra<Location>> {
    let locs = world::with(|w| w.area.terrain.iter()
                           .map(|(&loc, _)| loc)
                           .filter(|loc| loc.fov_status().is_none())
                           .collect::<Vec<Location>>());

    if locs.len() == 0 {
        return None;
    }

    Some(Dijkstra::new(locs, |&loc| !loc.blocks_walk(), pathing_depth))
}

*/
////////////////////////////////////////////////////////////////////////

static SAVE_FILENAME: &'static str = "magog_save.json";

pub fn save_game(w: &World) {
    // Only save if there's still a living player around.
    if query::game_over(w) {
        return;
    }

    let save_data = w.save();
    File::create(SAVE_FILENAME).unwrap()
        .write_all(&save_data.into_bytes()).unwrap();
}

pub fn load_game() -> Result<World, ()> {
    if !save_exists() { return Err(()); }
    let path = Path::new(SAVE_FILENAME);
    let mut save_data = String::new();
    File::open(&path).unwrap().read_to_string(&mut save_data).unwrap();
    // TODO: Informative error message if load fails.
    match World::load(&save_data[..]) {
        Ok(w) => Ok(w),
        _ => Err(())
    }
}

pub fn _delete_save() {
    let _ = fs::remove_file(SAVE_FILENAME);
}

pub fn save_exists() -> bool { fs::metadata(SAVE_FILENAME).is_ok() }

<commit_msg>Remove commented-out old code<commit_after>/*! Functions for changing world and entity state. */

use std::io::prelude::*;
use std::path::{Path};
use std::fs::{self, File};
use rand::StdRng;
use rand::SeedableRng;
use std::iter::Filter;
use calx::{Dijkstra, Dir6};
use calx_ecs::{Entity};
use world::{World};
use flags;
use area::{Area};
use location::{Location};
use content::{Biome, AreaSpec};
use item::{Slot};
use components::{CompositeStats};
use ::{Msg};
use msg;
use query::{self, ControlState};

/// Player input action.
#[derive(Copy, Eq, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum Input {
    /// Take a step in the given direction.
    Step(Dir6),
    /// Melee attack in the given direction.
    Melee(Dir6),
    /// Shoot in the given direction.
    Shoot(Dir6),
    /// Do nothing for a turn.
    Pass,
}

/// Top-level game state update function. Only valid to call if
/// control_state() returned ReadyToUpdate.
pub fn update(w: &mut World) {
    assert!(query::control_state(w) == ControlState::ReadyToUpdate);

    ai_main(w);

    w.flags.tick += 1;
    w.flags.player_acted = false;
}

/// Run AI for all autonomous mobs.
fn ai_main(w: &mut World) {
    let actives: Vec<Entity> = w.ecs.brain.iter().map(|(&e, _)| e).collect();
    for e in actives.into_iter() { update_entity(w, e); }
}

pub fn update_entity(w: &mut World, e: Entity) {
    if query::is_mob(w, e) && !query::is_player(w, e) && query::ticks_this_frame(w, e) {
        mob_ai(w, e);
    }
}

pub fn mob_ai(w: &mut World, e: Entity) {
    unimplemented!();
    /*
        assert!(self.is_mob());
        assert!(!self.is_player());
        assert!(self.ticks_this_frame());

        if self.brain_state() == Some(BrainState::Asleep) {
            if let Some(p) = action::player() {
                // TODO: Line-of-sight, stealth concerns, other enemies than
                // player etc.
                if let Some(d) = p.distance_from(self) {
                    if d < 6 {
                        self.wake_up();
                    }
                }
            }

            return;
        }

        if let Some(p) = action::player() {
            let loc = self.location().expect("no location");

            let vec_to_enemy = loc.v2_at(p.location().expect("no location"));
            if let Some(v) = vec_to_enemy {
                if v.hex_dist() == 1 {
                    // Melee range, hit.
                    self.melee(Dir6::from_v2(v));
                } else {
                    // Walk towards.
                    let pathing_depth = 16;
                    let pathing = Dijkstra::new(
                        vec![p.location().expect("no location")], |&loc| !loc.blocks_walk(),
                        pathing_depth);

                    let steps = pathing.sorted_neighbors(&loc);
                    if steps.len() > 0 {
                        self.step(loc.dir6_towards(steps[0]).expect("No loc pair orientation"));
                    } else {
                        self.step(rng().gen());
                        // TODO: Fall asleep if things get boring.
                    }
                }
            }
        }
        */
}

/// Give player input. Only valid to call if control_state() returned
/// AwaitingInput.
pub fn input(w: &mut World, input: Input) {
    assert!(query::control_state(w) == ControlState::AwaitingInput);
    let p = query::player(w).expect("No player to receive input");
    match input {
        Input::Step(d) => {
            step(w, p, d);
        }
        Input::Melee(d) => {
            melee(w, p, d);
        }
        Input::Shoot(d) => {
            shoot(w, p, d);
        }
        Input::Pass => {
        }
    }
    w.flags.player_acted = true;

    // Run one world update cycle right away, so that we don't get awkward
    // single frames rendered where the player has acted and the rest of the
    // world hasn't.
    if query::control_state(w) == ControlState::ReadyToUpdate {
        update(w);
    }
}

/// Try to move the entity in direction.
pub fn step(w: &mut World, e: Entity, dir: Dir6) {
    unimplemented!();
    /*
    let place = world::with(|w| w.spatial.get(self));
    if let Some(Place::At(loc)) = place {
        let new_loc = loc + dir.to_v2();
        if self.can_enter(new_loc) {
            world::with_mut(|w| w.spatial.insert_at(self, new_loc));
            self.on_move_to(new_loc);
        }
    }
    */
}

pub fn melee(w: &mut World, e: Entity, dir: Dir6) {
    unimplemented!();
    /*
    let loc = self.location().expect("no location") + dir.to_v2();
    if let Some(e) = loc.mob_at() {
        let us = self.stats();
        e.damage(us.power + us.attack);
    }
    */
}

pub fn shoot(w: &mut World, e: Entity, dir: Dir6) {
    unimplemented!();
    /*
    let stats = self.stats();

    if stats.ranged_range > 0 {
        action::shoot(self.location().unwrap(), dir, stats.ranged_range, stats.ranged_power);
    }
    */
}

pub fn pick_up(w: &mut World, picker: Entity, item: Entity) -> bool {
    if !query::can_be_picked_up(w, item) {
        return false;
    }

    match query::free_bag_slot(w, picker) {
        Some(slot) => {
            equip(w, item, picker, slot);
            return true;
        }
        // Inventory full.
        None => { return false; }
    }
}

/// Equip an item to a slot. Slot must be empty.
pub fn equip(w: &mut World, item: Entity, e: Entity, slot: Slot) {
    w.spatial.equip(item, e, slot);
    recompose_stats(w, e)
}

/// Generate composed stats from base stats and the stats of equipped items.
/// This function must be called after any operation that changes the composed
/// stats affecting state of an entity.
pub fn recompose_stats(w: &mut World, e: Entity) {
    let mut stats = query::base_stats(w, e);
    for &slot in [
        Slot::Body,
        Slot::Feet,
        Slot::Head,
        Slot::Melee,
        Slot::Ranged,
        Slot::TrinketF,
        Slot::TrinketG,
        Slot::TrinketH,
        Slot::TrinketI].iter() {
        if let Some(item) = w.spatial.entity_equipped(e, slot) {
            stats = stats + query::stats(w, item);
        }
    }

    w.ecs.composite_stats.insert(e, CompositeStats(stats));
}

pub fn start_level(w: &mut World, depth: i32) {
    let biome = match depth {
        1 => Biome::Overland,
        _ => Biome::Dungeon,
    };

    clear_nonplayers(w);

    let seed = w.flags.seed;

    w.area = Area::new(
        seed,
        AreaSpec::new(biome, depth));

    /*
    // TODO: Get spawns working again.
    let mut rng: StdRng = SeedableRng::from_seed(&[seed as usize + depth as usize][..]);
    for (spawn, loc) in world::with(|w| w.area.get_spawns()).into_iter() {
        spawn.spawn(&mut rng, loc);
    }
    */

    let start_loc = w.area.player_entrance();
    // Either reuse the existing player or create a new one.
    match query::player(w) {
        Some(p) => {
            forget_map(w, p);
            w.spatial.insert_at(p, start_loc);
        }
        None => {
            // TODO: Use factory.
            use calx::color;
            use content::Brush;
            use components::{Desc, MapMemory, Health, Brain, BrainState, Alignment};
            use stats::{Stats};
            use stats::Intrinsic::*;
            let player = w.ecs.make();
            w.ecs.desc.insert(player, Desc::new("player", Brush::Human, color::AZURE));
            w.ecs.map_memory.insert(player, MapMemory::new());
            w.ecs.brain.insert(player, Brain { state: BrainState::PlayerControl, alignment: Alignment::Good });
            w.ecs.stats.insert(player, Stats::new(10, &[Hands]).mana(5));
            recompose_stats(w, player);

            w.flags.player = Some(player);

            w.spatial.insert_at(player, start_loc);
            // TODO: run FOV
        }
    };
    w.flags.camera = start_loc;
}

fn clear_nonplayers(w: &mut World) {
    let po = query::player(w);
    let entities: Vec<Entity> = w.ecs.iter().map(|&e| e).collect();
    for e in entities.into_iter() {
        // Don't destroy player or player's inventory.
        if let Some(p) = po {
            if e == p || w.spatial.contains(p, e) {
                continue;
            }
        }

        if query::location(w, e).is_some() {
            w.ecs.remove(e);
        }
    }
}

/// Clear map memory of an entity.
pub fn forget_map(w: &mut World, e: Entity) {
    w.ecs.map_memory.get_mut(e).map(
        |mm| {
            mm.seen.clear();
            mm.remembered.clear();
        });
}

////////////////////////////////////////////////////////////////////////

static SAVE_FILENAME: &'static str = "magog_save.json";

pub fn save_game(w: &World) {
    // Only save if there's still a living player around.
    if query::game_over(w) {
        return;
    }

    let save_data = w.save();
    File::create(SAVE_FILENAME).unwrap()
        .write_all(&save_data.into_bytes()).unwrap();
}

pub fn load_game() -> Result<World, ()> {
    if !save_exists() { return Err(()); }
    let path = Path::new(SAVE_FILENAME);
    let mut save_data = String::new();
    File::open(&path).unwrap().read_to_string(&mut save_data).unwrap();
    // TODO: Informative error message if load fails.
    match World::load(&save_data[..]) {
        Ok(w) => Ok(w),
        _ => Err(())
    }
}

pub fn _delete_save() {
    let _ = fs::remove_file(SAVE_FILENAME);
}

pub fn save_exists() -> bool { fs::metadata(SAVE_FILENAME).is_ok() }

<|endoftext|>


<commit_before><commit_msg>rename: base64n::enc.encode_byte -> base64n::enc.encode_bytes<commit_after><|endoftext|>


<commit_before>use cripes::util::intrusive::*;

#[derive(Debug)]
struct Foo { refcount: usize, foo: &'static str }
default_refcounted_impl!(Foo, refcount);

trait Shower {
    fn show(&self);
}

impl Shower for Foo {
    fn show(&self) {
        println!("{}", self.foo);
    }
    fn bar(x: Ref<Foo>) {
        x.show();
    }
}

#[test]
fn ref_to_stack() {
    let x = Foo{refcount: 1, foo: "all i want for christmas is my two front teeth"};
    assert_eq!(1, x.refcount);
    assert_eq!("all i want for christmas is my two front teeth", x.foo);
    // println!("{:?} @ {:p}", x, &x);

    let y: Ref<Foo> = x.ref_to_self();
    assert!(y.foo == x.foo );
    // println!("{:?}", y);

    y.show();
    y.bar();

    let z: Ref<Shower> = x.ref_to_self();
    z.show();

    panic_unless!(x.refcount == 2, "invalid refcount on stack-allocated object with external reference");
    drop(y);

    panic_unless!(x.refcount == 1, "invalid refcount on stack-allocated object with dropped external reference");
}

#[test]
fn ref_to_new() {
    let r: Ref<_> = Reference::new_on_heap(Foo{refcount: 99, foo: "problems"});
    panic_unless!(r.refcount == 1, "invalid refcount on heap-allocated object");
    assert_eq!("problems", r.foo);
}
<commit_msg>test: corrected location/nesting of a fn in test_intrusive_ref.rs<commit_after>use cripes::util::intrusive::*;

#[derive(Debug)]
struct Foo { refcount: usize, foo: &'static str }
default_refcounted_impl!(Foo, refcount);

trait Shower {
    fn show(&self);
}

impl Shower for Foo {
    fn show(&self) {
        println!("{}", self.foo);
    }
}

fn bar(x: Ref<Foo>) {
    x.show();
}

#[test]
fn ref_to_stack() {
    let x = Foo{refcount: 1, foo: "all i want for christmas is my two front teeth"};
    assert_eq!(1, x.refcount);
    assert_eq!("all i want for christmas is my two front teeth", x.foo);
    // println!("{:?} @ {:p}", x, &x);

    let y: Ref<Foo> = x.ref_to_self();
    assert!(y.foo == x.foo );
    // println!("{:?}", y);

    y.show();
    y.bar();

    let z: Ref<Shower> = x.ref_to_self();
    z.show();

    panic_unless!(x.refcount == 2, "invalid refcount on stack-allocated object with external reference");
    drop(y);

    panic_unless!(x.refcount == 1, "invalid refcount on stack-allocated object with dropped external reference");
}

#[test]
fn ref_to_new() {
    let r: Ref<_> = Reference::new_on_heap(Foo{refcount: 99, foo: "problems"});
    panic_unless!(r.refcount == 1, "invalid refcount on heap-allocated object");
    assert_eq!("problems", r.foo);
}
<|endoftext|>


<commit_before>use nom::{Err, error::ErrorKind, IResult};
use nom::character::complete::digit1;
use nom::bytes::complete::{escaped, escaped_transform, tag};
use nom::character::complete::one_of;

fn esc(s: &str) -> IResult<&str, &str> {
    escaped(digit1, '\\', one_of("\"n\\"))(s)
}

fn esc_trans(s: &str) -> IResult<&str, String> {
    escaped_transform(digit1, '\\', |i: &str| tag("n")(i))(s)
}

#[test]
fn test_escaped() {
    assert_eq!(esc("abcd"), Err(Err::Error(("abcd", ErrorKind::Escaped))));
    assert_eq!(esc_trans("abcd"), Err(Err::Error(("abcd", ErrorKind::EscapedTransform))));
}<commit_msg>fix unit tests<commit_after>use nom::{Err, error::ErrorKind, IResult};
use nom::character::complete::digit1;
use nom::bytes::complete::escaped;
use nom::character::complete::one_of;

fn esc(s: &str) -> IResult<&str, &str> {
    escaped(digit1, '\\', one_of("\"n\\"))(s)
}

#[cfg(feature="alloc")]
fn esc_trans(s: &str) -> IResult<&str, String> {
    use nom::bytes::complete::{escaped_transform, tag};
    escaped_transform(digit1, '\\', |i: &str| tag("n")(i))(s)
}

#[test]
fn test_escaped() {
    assert_eq!(esc("abcd"), Err(Err::Error(("abcd", ErrorKind::Escaped))));
}

#[test]
#[cfg(feature="alloc")]
fn test_escaped_transform() {
    assert_eq!(esc_trans("abcd"), Err(Err::Error(("abcd", ErrorKind::EscapedTransform))));
}
<|endoftext|>