<commit_before>use std::fs::File;
use std::io::SeekFrom;
use std::io::BufReader;
use std::io::prelude::*;
use std::thread::sleep;
use std::time::Duration;
use std::os::unix::fs::MetadataExt;
use std::io::ErrorKind;

pub struct FileWatcher{
    filename: String,
    inode: u64,
    position: u64,
    reader: BufReader<File>,
    close: bool
}

impl FileWatcher {
    pub fn new(filename: String) -> Result<FileWatcher, ::std::io::Error> {
        let file = match File::open(filename.clone()) {
            Ok(f) => f,
            Err(err) => return Err(err)
        };

        let metadata = match file.metadata() {
            Ok(m) => m,
            Err(err) => return Err(err)
        };

        let mut reader = BufReader::new(file);
		let position = metadata.len();
        reader.seek(SeekFrom::Start(position)).unwrap();
        Ok(FileWatcher{filename: filename,
                      inode: metadata.ino(),
                      position: position,
                      reader: reader,
                      close: false})
    }

	pub fn reposition(&mut self, inode: u64, start_pos: u64) -> Result<&mut FileWatcher, &'static str> {
		if inode > 0 && self.inode != inode {
			return Err("last watcher file inode is can't be match!");
		}
		self.position = start_pos;
        self.reader.seek(SeekFrom::Start(self.position)).unwrap();
		Ok(self)
	}

    fn reopen(&mut self){
        loop {
            match File::open(self.filename.clone()) {
                Ok(x) => {
                    let f = x;
                    let metadata = match f.metadata() {
                        Ok(m) => m,
                        Err(_) => {
                            sleep(Duration::new(1, 0));
                            continue;
                        }
                    };
                    if metadata.ino() != self.inode{
                        self.reader = BufReader::new(f);
                        self.position = 0;
                        self.inode = metadata.ino();
                    } else {
                        sleep(Duration::new(1, 0));
                    }
                    break;
                },
                Err(err) => {
                    if err.kind() == ErrorKind::NotFound{
						if self.close {
							break;
						}
                        sleep(Duration::new(1, 0));
                        continue;
                    }
                }
            };
        }
    }

    fn read(&mut self) -> Option<String> {
        let mut line = String::new();
        let resp = self.reader.read_line(&mut line);
        match resp{
			Ok(0) => {
                if self.close {
                    None
                } else {
                    self.reopen();
                    self.reader.seek(SeekFrom::Start(self.position)).unwrap();
					Some("".to_owned())
                }
			},
            Ok(len) => {
                if self.close {
                    return None;
                }
                self.position += len as u64;
                self.reader.seek(SeekFrom::Start(self.position)).unwrap();
				Some(line)
            },
            Err(err) => panic!("Can't read: {}", err)
        }
    }
}

impl Iterator for FileWatcher {
    type Item = String;

    fn next(&mut self) -> Option<String> {
		self.read()
    }
}

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

    #[test]
    fn it_works() {
		let mut times = 0;
		let mut watcher = match FileWatcher::new("Cargo.toml".to_string()) {
			Ok(w) => w,
			Err(err) => panic!("Can't read: {}", err)
		};

		let inode = watcher.inode;
		let mut watcher = match watcher.reposition(inode, 0) {
				Ok(w) => w,
				Err(err) => panic!("Can't reposition: {}", err)
			};

		loop {
		    match watcher.next() {
		        Some(line) => {
					if line == ""{
						println!("None None!!!");
					} else {
						println!("{:?}", line);
					}
		        },
		        None => break
		    }

			println!("filename: {:?}", watcher.filename);
			println!("file inode: {:?}", watcher.inode);
			println!("file position: {:?}", watcher.position);

			if times == 5 {
				watcher.close = true;
			}
			times += 1;
		}
    }
}<commit_msg>add fn get_filename(), get_inode(), get_position(), close()<commit_after>use std::fs::File;
use std::io::SeekFrom;
use std::io::BufReader;
use std::io::prelude::*;
use std::thread::sleep;
use std::time::Duration;
use std::os::unix::fs::MetadataExt;
use std::io::ErrorKind;

pub struct FileWatcher {
    filename: String,
    inode: u64,
    position: u64,
    reader: BufReader<File>,
	finish: bool
}

impl FileWatcher {
    pub fn new(filename: String) -> Result<FileWatcher, ::std::io::Error> {
        let file = match File::open(filename.clone()) {
            Ok(f) => f,
            Err(err) => return Err(err)
        };

        let metadata = match file.metadata() {
            Ok(m) => m,
            Err(err) => return Err(err)
        };

        let mut reader = BufReader::new(file);
		let position = metadata.len();
        reader.seek(SeekFrom::Start(position)).unwrap();
        Ok(FileWatcher{filename: filename,
                      inode: metadata.ino(),
                      position: position,
                      reader: reader,
                      finish: false})
    }

	pub fn reposition(&mut self, inode: u64, start_pos: u64) -> Result<&mut FileWatcher, &'static str> {
		if inode > 0 && self.inode != inode {
			return Err("last watcher file inode is can't be match!");
		}
		self.position = start_pos;
        self.reader.seek(SeekFrom::Start(self.position)).unwrap();
		Ok(self)
	}

	pub fn get_filename(&mut self) -> String {
		self.filename.clone()
	}

	pub fn get_inode(&mut self) -> u64 {
		self.inode
	}

	pub fn get_position(&mut self) -> u64 {
		self.position
	}

	pub fn close(&mut self){
		self.finish = true;
	}

    fn reopen(&mut self){
        loop {
            match File::open(self.filename.clone()) {
                Ok(x) => {
                    let f = x;
                    let metadata = match f.metadata() {
                        Ok(m) => m,
                        Err(_) => {
                            sleep(Duration::new(1, 0));
                            continue;
                        }
                    };
                    if metadata.ino() != self.inode{
                        self.reader = BufReader::new(f);
                        self.position = 0;
                        self.inode = metadata.ino();
                    } else {
                        sleep(Duration::new(1, 0));
                    }
                    break;
                },
                Err(err) => {
                    if err.kind() == ErrorKind::NotFound{
						if self.finish {
							break;
						}
                        sleep(Duration::new(1, 0));
                        continue;
                    }
                }
            };
        }
    }

    fn read(&mut self) -> Option<String> {
        let mut line = String::new();
        let resp = self.reader.read_line(&mut line);
        match resp{
			Ok(0) => {
                if self.finish {
                    None
                } else {
                    self.reopen();
                    self.reader.seek(SeekFrom::Start(self.position)).unwrap();
					Some("".to_owned())
                }
			},
            Ok(len) => {
                if self.finish {
                    return None;
                }
                self.position += len as u64;
                self.reader.seek(SeekFrom::Start(self.position)).unwrap();
				Some(line)
            },
            Err(err) => panic!("Can't read: {}", err)
        }
    }
}

impl Iterator for FileWatcher {
    type Item = String;

    fn next(&mut self) -> Option<String> {
		self.read()
    }
}

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

    #[test]
    fn it_works() {
		let mut times = 0;
		let mut watcher = match FileWatcher::new("Cargo.toml".to_string()) {
			Ok(w) => w,
			Err(err) => panic!("Can't read: {}", err)
		};

		let inode = watcher.inode;
		let mut watcher = match watcher.reposition(inode, 0) {
				Ok(w) => w,
				Err(err) => panic!("Can't reposition: {}", err)
			};

		loop {
		    match watcher.next() {
		        Some(line) => {
					if line == ""{
						println!("None None!!!");
					} else {
						println!("{:?}", line);
					}
		        },
		        None => break
		    }

			println!("filename: {:?}", watcher.get_filename());
			println!("file inode: {:?}", watcher.get_inode());
			println!("file position: {:?}", watcher.get_position());

			if times == 5 {
				watcher.close();
			}
			times += 1;
		}
    }
}<|endoftext|>


<commit_before>//!
//! ### Namespaces
//!
//! The XPath specification assumes that the XML being processed has a
//! prefix defined for every namespace present in the document. If you
//! are processing XML that was parsed from text, this will be true by
//! construction.
//!
//! If you have programmatically created XML with namespaces but not
//! defined prefixes, some XPath behavior may be confusing:
//!
//! 1. The `name` method will not include a prefix, even if the
//! element or attribute has a namespace.
//! 2. The `namespace` axis will not include namespaces without
//! prefixes.
//!

#![crate_name = "xpath"]

#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(std_misc)]

#[macro_use]
extern crate peresil;
extern crate document;

use std::borrow::ToOwned;
use std::collections::HashMap;
use std::num::Float;
use std::{iter,string};

use self::Value::{Boolean,Number,String};

use nodeset::{Nodeset,Node,ToNode};
use parser::Parser;
use tokenizer::{Tokenizer,TokenDeabbreviator};

pub use function::Function;
pub use expression::Expression;

#[macro_use]
pub mod macros;
pub mod nodeset;
pub mod axis;
mod expression;
pub mod function;
mod node_test;
pub mod parser;
mod token;
pub mod tokenizer;

#[derive(PartialEq,Debug,Clone)]
enum LiteralValue {
    Boolean(bool),
    Number(f64),
    String(string::String),
}

impl LiteralValue {
    fn into_value<'d>(self) -> Value<'d> {
        match self {
            LiteralValue::Boolean(v) => Boolean(v),
            LiteralValue::Number(v)  => Number(v),
            LiteralValue::String(v)  => String(v),
        }
    }
}

#[derive(PartialEq,Debug,Clone)]
pub enum Value<'d> {
    Boolean(bool),
    Number(f64),
    String(string::String),
    Nodeset(Nodeset<'d>),
}

fn str_to_num(s: &str) -> f64 {
    s.trim().parse().unwrap_or(Float::nan())
}

impl<'d> Value<'d> {
    pub fn boolean(&self) -> bool {
        use Value::*;
        match *self {
            Boolean(val) => val,
            Number(n) => n != 0.0 && ! n.is_nan(),
            String(ref s) => ! s.is_empty(),
            Nodeset(ref nodeset) => nodeset.size() > 0,
        }
    }

    pub fn number(&self) -> f64 {
        use Value::*;
        match *self {
            Boolean(val) => if val { 1.0 } else { 0.0 },
            Number(val) => val,
            String(ref s) => str_to_num(s),
            Nodeset(..) => str_to_num(&self.string()),
        }
    }

    pub fn string(&self) -> string::String {
        use Value::*;
        match *self {
            Boolean(v) => v.to_string(),
            Number(n) => {
                if n.is_infinite() {
                    if n.signum() < 0.0 {
                        "-Infinity".to_owned()
                    } else {
                        "Infinity".to_owned()
                    }
                } else {
                    n.to_string()
                }
            },
            String(ref val) => val.clone(),
            Nodeset(ref ns) => match ns.document_order_first() {
                Some(n) => n.string_value(),
                None => "".to_owned(),
            },
        }
    }

    #[allow(dead_code)]
    fn into_literal_value(self) -> LiteralValue {
        use Value::*;
        match self {
            Boolean(v) => LiteralValue::Boolean(v),
            Number(v)  => LiteralValue::Number(v),
            String(v)  => LiteralValue::String(v),
            Nodeset(_) => panic!("Cannot convert a nodeset to a literal"),
        }
    }
}

type BoxFunc = Box<Function + 'static>;
pub type Functions = HashMap<string::String, BoxFunc>;
pub type Variables<'d> = HashMap<string::String, Value<'d>>;
pub type Namespaces = HashMap<string::String, string::String>;

#[derive(Copy,Clone)]
pub struct EvaluationContext<'a, 'd : 'a> {
    node: Node<'d>,
    functions: &'a Functions,
    variables: &'a Variables<'d>,
    namespaces: &'a Namespaces,
    position: usize,
    size: usize,
}

impl<'a, 'd> EvaluationContext<'a, 'd> {
    pub fn new<N>(node: N,
                  functions: &'a Functions,
                  variables: &'a Variables<'d>,
                  namespaces: &'a Namespaces)
                  -> EvaluationContext<'a, 'd>
        where N: ToNode<'d>
    {
        EvaluationContext {
            node: node.into_node(),
            functions: functions,
            variables: variables,
            namespaces: namespaces,
            position: 1,
            size: 1,
        }
    }

    fn new_context_for<N>(&self, node: N) -> EvaluationContext<'a, 'd>
        where N: ToNode<'d>
    {
        EvaluationContext {
            node: node.into_node(),
            .. *self
        }
    }

    fn position(&self) -> usize {
        self.position
    }

    fn size(&self) -> usize {
        self.size
    }

    fn function_for_name(&self, name: &str) -> Option<&'a BoxFunc> {
        self.functions.get(&name.to_owned())
    }

    fn value_of(&self, name: &str) -> Option<&Value<'d>> {
        self.variables.get(&name.to_owned())
    }

    fn namespace_for(&self, prefix: &str) -> Option<&str> {
        self.namespaces.get(prefix).map(|ns| &ns[..])
    }

    fn predicate_iter<'p>(&'p self, nodes: Nodeset<'d>)
                          -> EvaluationContextPredicateIter<'a, 'd, 'p>
    {
        let sz = nodes.size();
        EvaluationContextPredicateIter {
            parent: self,
            nodes: nodes.into_iter().enumerate(),
            size: sz,
        }
    }
}

struct EvaluationContextPredicateIter<'a : 'p, 'd : 'a + 'p, 'p> {
    parent: &'p EvaluationContext<'a, 'd>,
    nodes: iter::Enumerate<nodeset::IntoIter<'d>>,
    size: usize,
}

impl<'a, 'd, 'p> Iterator for EvaluationContextPredicateIter<'a, 'd, 'p> {
    type Item = EvaluationContext<'a, 'd>;

    fn next(&mut self) -> Option<EvaluationContext<'a, 'd>> {
        self.nodes.next().map(|(idx, node)| {
            EvaluationContext {
                node: node,
                position: idx + 1,
                size: self.size,
                .. *self.parent
            }
        })
    }
}

pub struct Factory {
    parser: Parser,
}

impl Factory {
    pub fn new() -> Factory {
        Factory { parser: Parser::new() }
    }

    pub fn build(&self, xpath: &str) -> parser::ParseResult {
        let tokenizer = Tokenizer::new(xpath);
        let deabbreviator = TokenDeabbreviator::new(tokenizer);

        self.parser.parse(deabbreviator)
    }
}

#[cfg(test)]
mod test {
    use std::borrow::ToOwned;
    use std::num::Float;

    use document::Package;

    use super::Value;

    #[test]
    fn number_of_string_is_ieee_754_number() {
        let v = Value::String("1.5".to_owned());
        assert_eq!(1.5, v.number());
    }

    #[test]
    fn number_of_string_with_negative_is_negative_number() {
        let v = Value::String("-1.5".to_owned());
        assert_eq!(-1.5, v.number());
    }

    #[test]
    fn number_of_string_with_surrounding_whitespace_is_number_without_whitespace() {
        let v = Value::String("\r\n1.5 \t".to_owned());
        assert_eq!(1.5, v.number());
    }

    #[test]
    fn number_of_garbage_string_is_nan() {
        let v = Value::String("I am not an IEEE 754 number".to_owned());
        assert!(v.number().is_nan());
    }

    #[test]
    fn number_of_boolean_true_is_1() {
        let v = Value::Boolean(true);
        assert_eq!(1.0, v.number());
    }

    #[test]
    fn number_of_boolean_false_is_0() {
        let v = Value::Boolean(false);
        assert_eq!(0.0, v.number());
    }

    #[test]
    fn number_of_nodeset_is_number_value_of_first_node_in_document_order() {
        let package = Package::new();
        let doc = package.as_document();

        let c1 = doc.create_comment("42.42");
        let c2 = doc.create_comment("1234");
        doc.root().append_child(c1);
        doc.root().append_child(c2);

        let v = Value::Nodeset(nodeset![c2, c1]);
        assert_eq!(42.42, v.number());
    }

    #[test]
    fn string_of_true_is_true() {
        let v = Value::Boolean(true);
        assert_eq!("true", v.string());
    }

    #[test]
    fn string_of_false_is_false() {
        let v = Value::Boolean(false);
        assert_eq!("false", v.string());
    }

    #[test]
    fn string_of_nan_is_nan() {
        let v = Value::Number(Float::nan());
        assert_eq!("NaN", v.string());
    }

    #[test]
    fn string_of_positive_zero_is_zero() {
        let v = Value::Number(Float::zero());
        assert_eq!("0", v.string());
    }

    #[test]
    fn string_of_negative_zero_is_zero() {
        let v = Value::Number(Float::neg_zero());
        assert_eq!("0", v.string());
    }

    #[test]
    fn string_of_positive_infinity_is_infinity() {
        let v = Value::Number(Float::infinity());
        assert_eq!("Infinity", v.string());
    }

    #[test]
    fn string_of_negative_infinity_is_minus_infinity() {
        let v = Value::Number(Float::neg_infinity());
        assert_eq!("-Infinity", v.string());
    }

    #[test]
    fn string_of_integer_has_no_decimal() {
        let v = Value::Number(-42.0);
        assert_eq!("-42", v.string());
    }

    #[test]
    fn string_of_decimal_has_fractional_part() {
        let v = Value::Number(1.2);
        assert_eq!("1.2", v.string());
    }

    #[test]
    fn string_of_nodeset_is_string_value_of_first_node_in_document_order() {
        let package = Package::new();
        let doc = package.as_document();

        let c1 = doc.create_comment("comment 1");
        let c2 = doc.create_comment("comment 2");
        doc.root().append_child(c1);
        doc.root().append_child(c2);

        let v = Value::Nodeset(nodeset![c2, c1]);
        assert_eq!("comment 1", v.string());
    }
}
<commit_msg>Work around exported non-public type issue<commit_after>//!
//! ### Namespaces
//!
//! The XPath specification assumes that the XML being processed has a
//! prefix defined for every namespace present in the document. If you
//! are processing XML that was parsed from text, this will be true by
//! construction.
//!
//! If you have programmatically created XML with namespaces but not
//! defined prefixes, some XPath behavior may be confusing:
//!
//! 1. The `name` method will not include a prefix, even if the
//! element or attribute has a namespace.
//! 2. The `namespace` axis will not include namespaces without
//! prefixes.
//!

#![crate_name = "xpath"]

#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(std_misc)]

#[macro_use]
extern crate peresil;
extern crate document;

use std::borrow::ToOwned;
use std::collections::HashMap;
use std::num::Float;
use std::{iter,string};

use self::Value::{Boolean,Number,String};

use nodeset::{Nodeset,Node,ToNode};
use parser::Parser;
use tokenizer::{Tokenizer,TokenDeabbreviator};

pub use function::Function;
pub use expression::Expression;

#[macro_use]
pub mod macros;
pub mod nodeset;
pub mod axis;
mod expression;
pub mod function;
mod node_test;
pub mod parser;
mod token;
pub mod tokenizer;

// TODO - this doesn't need to be public, figure out how to make it so
#[derive(PartialEq,Debug,Clone)]
pub enum LiteralValue {
    Boolean(bool),
    Number(f64),
    String(string::String),
}

impl LiteralValue {
    fn into_value<'d>(self) -> Value<'d> {
        match self {
            LiteralValue::Boolean(v) => Boolean(v),
            LiteralValue::Number(v)  => Number(v),
            LiteralValue::String(v)  => String(v),
        }
    }
}

#[derive(PartialEq,Debug,Clone)]
pub enum Value<'d> {
    Boolean(bool),
    Number(f64),
    String(string::String),
    Nodeset(Nodeset<'d>),
}

fn str_to_num(s: &str) -> f64 {
    s.trim().parse().unwrap_or(Float::nan())
}

impl<'d> Value<'d> {
    pub fn boolean(&self) -> bool {
        use Value::*;
        match *self {
            Boolean(val) => val,
            Number(n) => n != 0.0 && ! n.is_nan(),
            String(ref s) => ! s.is_empty(),
            Nodeset(ref nodeset) => nodeset.size() > 0,
        }
    }

    pub fn number(&self) -> f64 {
        use Value::*;
        match *self {
            Boolean(val) => if val { 1.0 } else { 0.0 },
            Number(val) => val,
            String(ref s) => str_to_num(s),
            Nodeset(..) => str_to_num(&self.string()),
        }
    }

    pub fn string(&self) -> string::String {
        use Value::*;
        match *self {
            Boolean(v) => v.to_string(),
            Number(n) => {
                if n.is_infinite() {
                    if n.signum() < 0.0 {
                        "-Infinity".to_owned()
                    } else {
                        "Infinity".to_owned()
                    }
                } else {
                    n.to_string()
                }
            },
            String(ref val) => val.clone(),
            Nodeset(ref ns) => match ns.document_order_first() {
                Some(n) => n.string_value(),
                None => "".to_owned(),
            },
        }
    }

    #[allow(dead_code)]
    fn into_literal_value(self) -> LiteralValue {
        use Value::*;
        match self {
            Boolean(v) => LiteralValue::Boolean(v),
            Number(v)  => LiteralValue::Number(v),
            String(v)  => LiteralValue::String(v),
            Nodeset(_) => panic!("Cannot convert a nodeset to a literal"),
        }
    }
}

type BoxFunc = Box<Function + 'static>;
pub type Functions = HashMap<string::String, BoxFunc>;
pub type Variables<'d> = HashMap<string::String, Value<'d>>;
pub type Namespaces = HashMap<string::String, string::String>;

#[derive(Copy,Clone)]
pub struct EvaluationContext<'a, 'd : 'a> {
    node: Node<'d>,
    functions: &'a Functions,
    variables: &'a Variables<'d>,
    namespaces: &'a Namespaces,
    position: usize,
    size: usize,
}

impl<'a, 'd> EvaluationContext<'a, 'd> {
    pub fn new<N>(node: N,
                  functions: &'a Functions,
                  variables: &'a Variables<'d>,
                  namespaces: &'a Namespaces)
                  -> EvaluationContext<'a, 'd>
        where N: ToNode<'d>
    {
        EvaluationContext {
            node: node.into_node(),
            functions: functions,
            variables: variables,
            namespaces: namespaces,
            position: 1,
            size: 1,
        }
    }

    fn new_context_for<N>(&self, node: N) -> EvaluationContext<'a, 'd>
        where N: ToNode<'d>
    {
        EvaluationContext {
            node: node.into_node(),
            .. *self
        }
    }

    fn position(&self) -> usize {
        self.position
    }

    fn size(&self) -> usize {
        self.size
    }

    fn function_for_name(&self, name: &str) -> Option<&'a BoxFunc> {
        self.functions.get(&name.to_owned())
    }

    fn value_of(&self, name: &str) -> Option<&Value<'d>> {
        self.variables.get(&name.to_owned())
    }

    fn namespace_for(&self, prefix: &str) -> Option<&str> {
        self.namespaces.get(prefix).map(|ns| &ns[..])
    }

    fn predicate_iter<'p>(&'p self, nodes: Nodeset<'d>)
                          -> EvaluationContextPredicateIter<'a, 'd, 'p>
    {
        let sz = nodes.size();
        EvaluationContextPredicateIter {
            parent: self,
            nodes: nodes.into_iter().enumerate(),
            size: sz,
        }
    }
}

struct EvaluationContextPredicateIter<'a : 'p, 'd : 'a + 'p, 'p> {
    parent: &'p EvaluationContext<'a, 'd>,
    nodes: iter::Enumerate<nodeset::IntoIter<'d>>,
    size: usize,
}

impl<'a, 'd, 'p> Iterator for EvaluationContextPredicateIter<'a, 'd, 'p> {
    type Item = EvaluationContext<'a, 'd>;

    fn next(&mut self) -> Option<EvaluationContext<'a, 'd>> {
        self.nodes.next().map(|(idx, node)| {
            EvaluationContext {
                node: node,
                position: idx + 1,
                size: self.size,
                .. *self.parent
            }
        })
    }
}

pub struct Factory {
    parser: Parser,
}

impl Factory {
    pub fn new() -> Factory {
        Factory { parser: Parser::new() }
    }

    pub fn build(&self, xpath: &str) -> parser::ParseResult {
        let tokenizer = Tokenizer::new(xpath);
        let deabbreviator = TokenDeabbreviator::new(tokenizer);

        self.parser.parse(deabbreviator)
    }
}

#[cfg(test)]
mod test {
    use std::borrow::ToOwned;
    use std::num::Float;

    use document::Package;

    use super::Value;

    #[test]
    fn number_of_string_is_ieee_754_number() {
        let v = Value::String("1.5".to_owned());
        assert_eq!(1.5, v.number());
    }

    #[test]
    fn number_of_string_with_negative_is_negative_number() {
        let v = Value::String("-1.5".to_owned());
        assert_eq!(-1.5, v.number());
    }

    #[test]
    fn number_of_string_with_surrounding_whitespace_is_number_without_whitespace() {
        let v = Value::String("\r\n1.5 \t".to_owned());
        assert_eq!(1.5, v.number());
    }

    #[test]
    fn number_of_garbage_string_is_nan() {
        let v = Value::String("I am not an IEEE 754 number".to_owned());
        assert!(v.number().is_nan());
    }

    #[test]
    fn number_of_boolean_true_is_1() {
        let v = Value::Boolean(true);
        assert_eq!(1.0, v.number());
    }

    #[test]
    fn number_of_boolean_false_is_0() {
        let v = Value::Boolean(false);
        assert_eq!(0.0, v.number());
    }

    #[test]
    fn number_of_nodeset_is_number_value_of_first_node_in_document_order() {
        let package = Package::new();
        let doc = package.as_document();

        let c1 = doc.create_comment("42.42");
        let c2 = doc.create_comment("1234");
        doc.root().append_child(c1);
        doc.root().append_child(c2);

        let v = Value::Nodeset(nodeset![c2, c1]);
        assert_eq!(42.42, v.number());
    }

    #[test]
    fn string_of_true_is_true() {
        let v = Value::Boolean(true);
        assert_eq!("true", v.string());
    }

    #[test]
    fn string_of_false_is_false() {
        let v = Value::Boolean(false);
        assert_eq!("false", v.string());
    }

    #[test]
    fn string_of_nan_is_nan() {
        let v = Value::Number(Float::nan());
        assert_eq!("NaN", v.string());
    }

    #[test]
    fn string_of_positive_zero_is_zero() {
        let v = Value::Number(Float::zero());
        assert_eq!("0", v.string());
    }

    #[test]
    fn string_of_negative_zero_is_zero() {
        let v = Value::Number(Float::neg_zero());
        assert_eq!("0", v.string());
    }

    #[test]
    fn string_of_positive_infinity_is_infinity() {
        let v = Value::Number(Float::infinity());
        assert_eq!("Infinity", v.string());
    }

    #[test]
    fn string_of_negative_infinity_is_minus_infinity() {
        let v = Value::Number(Float::neg_infinity());
        assert_eq!("-Infinity", v.string());
    }

    #[test]
    fn string_of_integer_has_no_decimal() {
        let v = Value::Number(-42.0);
        assert_eq!("-42", v.string());
    }

    #[test]
    fn string_of_decimal_has_fractional_part() {
        let v = Value::Number(1.2);
        assert_eq!("1.2", v.string());
    }

    #[test]
    fn string_of_nodeset_is_string_value_of_first_node_in_document_order() {
        let package = Package::new();
        let doc = package.as_document();

        let c1 = doc.create_comment("comment 1");
        let c2 = doc.create_comment("comment 2");
        doc.root().append_child(c1);
        doc.root().append_child(c2);

        let v = Value::Nodeset(nodeset![c2, c1]);
        assert_eq!("comment 1", v.string());
    }
}
<|endoftext|>


<commit_before>//! A work-stealing fork-join queue used to perform processors' work asynchronously.
//! This is intended to be short-lived. Long running asynchronous tasks should use another method.
//! For infinite loops, the longest-running of tasks, behavior will be as expected.
#![cfg_attr(nightly, feature(core_intrinsics))]

mod job;
mod queue;
mod pool;

use self::job::Job;
use self::pool::Pool;
use self::queue::Queue;

use std::io::Error;
use std::marker::PhantomData;
use std::sync::Arc;
use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;

const MAX_JOBS: usize = 4096;

// messages to workers.
enum ToWorker {
    Start, // start
    Clear, // run all jobs to completion, then reset the pool.
    Shutdown, // all workers are clear and no jobs are running. safe to tear down pools.
}
// messages to the leader from workers.
enum ToLeader {
    Cleared, // done clearing. will wait for start or shutdown
    Panicked,
}

struct WorkerHandle {
    tx: Sender<ToWorker>,
    rx: Receiver<ToLeader>,
    thread: Option<thread::JoinHandle<()>>,
}

// Finite state machine for controlling workers.
#[derive(Clone, Copy, PartialEq)]
enum State {
    Running, // running jobs normally. waiting for state change.
    Paused, // paused, waiting for start or shutdown message.
}

struct Worker {
    queues: Arc<Vec<Queue>>,
    pools: Arc<Vec<Pool>>,
    idx: usize, // the index of this worker's queue and pool in the Vec.
}

// TODO: implement !Sync for Worker.

impl Worker {
    // pop a job from the worker's queue, or steal one from the queue with the most work.
    unsafe fn pop_or_steal(&self) -> Option<*mut Job> {
        if let Some(job) = self.queues[self.idx].pop() {
            return Some(job);
        }

        // if the queue is empty (pop failed), we can clear the pool for this queue.
        // this works only because
        // A) we push pool-allocated jobs only onto the local queue,
        // B) pop gets priority when racing against "steal".
        self.pools[self.idx].reset();

        let (mut most_work, mut most_idx) = (0, None);
        for (i, queue) in self.queues.iter().enumerate() {
            let len = queue.len();
            if len > most_work {
                most_work = len;
                most_idx = Some(i);
            }
        }

        if let Some(idx) = most_idx {
            self.queues[idx].steal()
        } else {
            None
        }
    }

    // do a sweep through all the queues, saying whether all
    // were observed to be empty initially.
    fn clear_pass(&self) -> bool {
        let mut all_clear = true;
        for (idx, queue) in self.queues.iter().enumerate() {
            if idx != self.idx {
                while let Some(job) = queue.steal() {
                    all_clear = false;
                    unsafe { (*job).call(self) }
                }
            } else {
                while let Some(job) = unsafe { queue.pop() } {
                    all_clear = false;
                    unsafe { (*job).call(self) }
                }
            }
        }

        all_clear
    }

    fn clear(&self) {
        while !self.clear_pass() {}
    }

    // run the next job.
    unsafe fn run_next(&self) {
        if let Some(job) = self.pop_or_steal() {
            (*job).call(self)
        }
    }

    // This must be called on the thread the worker is active on.
    unsafe fn submit_internal<F>(&self, counter: *const AtomicUsize, f: F)
        where F: Send + FnOnce(&Worker)
    {
        let job = Job::new(counter, f);
        let job_ptr = self.pools[self.idx].alloc(job);
        self.queues[self.idx].push(job_ptr);
    }

    // construct a new spawning scope.
    // this waits for all jobs submitted internally
    // to complete.
    fn scope<'pool, 'new, F>(&'pool self, f: F)
        where F: FnOnce(&Spawner<'pool, 'new>)
    {
        let counter = AtomicUsize::new(0);
        let s = make_spawner(self, &counter);
        f(&s);

        while counter.load(Ordering::Acquire) != 0 {
            unsafe { self.run_next() }
        }
    }
}

/// A job spawner associated with a specific scope.
/// Jobs spawned using this may spawn new jobs with the same lifetime.
pub struct Spawner<'pool, 'scope> {
    worker: &'pool Worker,
    counter: *const AtomicUsize,
    // invariant lifetime.
    _marker: PhantomData<*mut &'scope mut ()>,
}

impl<'pool, 'scope> Spawner<'pool, 'scope> {
    /// Execute a function which necessarily outlives the scope which
    /// this resides in.
    pub fn submit<F>(&self, f: F)
        where F: 'scope + Send + FnOnce(&Spawner<'pool, 'scope>)
    {
        use std::mem;

        // for sending the counter pointer across thread boundaries.
        struct SendCounter(*const AtomicUsize);
        unsafe impl Send for SendCounter {}

        unsafe {
            // increment the counter first just in case, somehow, this job
            // gets grabbed before we have a chance to increment it,
            // and we wait for all jobs to complete.
            let counter: SendCounter = SendCounter(self.counter);
            (*self.counter).fetch_add(1, Ordering::AcqRel);
            self.worker.submit_internal(self.counter, move |worker| {
                let SendCounter(count_ptr) = counter;
                // make a new spawner associated with the same scope,
                // but with the correct worker for the thread -- so if
                // this job spawns any children, we won't break any
                // invariants by accessing other workers' queues/pools
                // in unexpected ways.
                let spawner = make_spawner(worker, count_ptr);
                f(&mem::transmute(spawner))
            });
        }
    }

    /// Construct a new spawning scope smaller than the one this spawner resides in.
    pub fn scope<'new, F>(&self, f: F)
        where 'scope: 'new,
              F: FnOnce(&Spawner<'pool, 'new>)
    {
        self.worker.scope(f);
    }

    /// Execute two closures, possibly asynchronously, and return their results.
    pub fn join<A, B, R_A, R_B>(&self, oper_a: A, oper_b: B) -> (R_A, R_B)
    where A: Send + FnOnce(&Spawner) -> R_A,
          B: Send + FnOnce(&Spawner) -> R_B,
          R_A: Send,
          R_B: Send
    {
        let mut a = None;
        let mut b = None;
        self.scope(|spawner| {
            spawner.submit(|s| a = Some(oper_a(s)));
            spawner.submit(|s| b = Some(oper_b(s)));
        });

        (a.unwrap(), b.unwrap())
    }
}
fn make_spawner<'a, 'b>(worker: &'a Worker, counter: *const AtomicUsize) -> Spawner<'a, 'b> {
    Spawner {
        worker: worker,
        counter: counter,
        _marker: PhantomData,
    }
}

fn worker_main(tx: Sender<ToLeader>, rx: Receiver<ToWorker>, worker: Worker) {
    struct PanicGuard(Sender<ToLeader>);
    impl Drop for PanicGuard {
        fn drop(&mut self) {
            if thread::panicking() {
                let _ = self.0.send(ToLeader::Panicked);
            }
        }
    }
    // if the worker for this thread panics,
    let _guard = PanicGuard(tx.clone());

    let mut state = State::Paused;
    loop {
        match state {
            State::Running => {
                match rx.try_recv() {
                    Ok(ToWorker::Clear) => {
                        worker.clear();
                        tx.send(ToLeader::Cleared).expect("Pool hung up on worker");
                        state = State::Paused;
                    }
                    Ok(_) => unreachable!(),
                    Err(TryRecvError::Disconnected) => panic!("Pool hung up on worker"),
                    _ => {}
                }

                unsafe { worker.run_next() }
            }

            State::Paused => {
                if let Ok(msg) = rx.recv() {
                    match msg {
                        ToWorker::Start => {
                            state = State::Running;
                            continue;
                        }

                        ToWorker::Shutdown => {
                            break;
                        }

                        _ => unreachable!(),
                    }
                } else {
                    panic!("Pool hung up on worker");
                }
            }
        }
    }
}

/// The work pool manages worker threads in a
/// work-stealing fork-join thread pool.
// The fields here are put in Vecs for cache contiguity.
pub struct WorkPool {
    workers: Vec<WorkerHandle>,
    local_worker: Worker,
    state: State,
}

impl WorkPool {
    /// Creates a work pool with `n` worker threads.
    pub fn new(n: usize) -> Result<Self, Error> {
        // one extra queue and pool for the job system.
        let queues = Arc::new((0..n + 1).map(|_| Queue::new()).collect::<Vec<_>>());
        let pools = Arc::new((0..n + 1).map(|_| Pool::new()).collect::<Vec<_>>());
        let mut workers = Vec::with_capacity(n);

        for i in 0..n {
            let (work_send, work_recv) = channel();
            let (lead_send, lead_recv) = channel();

            let worker = Worker {
                queues: queues.clone(),
                pools: pools.clone(),
                idx: i + 1,
            };

            let builder = thread::Builder::new().name(format!("worker_{}", i));
            let handle = try!(builder.spawn(|| worker_main(lead_send, work_recv, worker)));

            workers.push(WorkerHandle {
                tx: work_send,
                rx: lead_recv,
                thread: Some(handle),
            });
        }

        let mut pool = WorkPool {
            workers: workers,
            local_worker: Worker {
                queues: queues,
                pools: pools,
                idx: 0,
            },
            state: State::Paused,
        };

        pool.spin_up();

        Ok(pool)
    }

    /// Finish all current jobs which are queued, and synchronize the workers until
    /// it's time to start again.
    ///
    /// If any of the threads have panicked, that panic
    /// will be propagated to this thread. Until the next job is submitted,
    /// workers will block, allowing other threads to have higher priority.
    pub fn synchronize(&mut self) {
        self.clear_all();
    }

    /// Create a new spawning scope for submitting jobs.
    /// Any jobs submitted in this scope will be completed
    /// by the end of this function call.
    pub fn scope<'pool, 'new, F>(&'pool mut self, f: F)
        where F: FnOnce(&Spawner<'pool, 'new>)
    {
        self.spin_up();
        self.local_worker.scope(f);
    }

    /// Execute a job which strictly owns its contents.
    /// The execution of this function may be deferred to beyond
    /// this function call.
    /// In the general case, it is safe to submit jobs which only
    /// strictly outlive the pool. However, there is always the
    /// chance that the pool could be leaked, violating the invariant
    /// that the job is completed before the borrow of the data is.
    pub fn submit<'a, F>(&'a mut self, f: F)
        where F: 'static + Send + FnOnce(&Spawner<'a, 'static>)
    {
        use std::mem;
        use std::ptr;

        self.spin_up();
        // make a job without a counter.
        unsafe {
            self.local_worker.submit_internal(ptr::null_mut(), move |worker| {
                let spawner = make_spawner(&worker, ptr::null_mut());
                f(&mem::transmute(spawner))
            })
        }
    }

    /// Spin up all the workers, in case they were in a paused
    /// state.
    pub fn spin_up(&mut self) {
        if self.state != State::Running {
            for worker in &self.workers {
                worker.tx.send(ToWorker::Start).expect("Worker hung up on pool");
            }

            self.state = State::Running;
        }
    }

    // clear all the workers and sets the state to paused.
    fn clear_all(&mut self) {
        if self.state == State::Paused {
            return;
        }
        // send every worker a clear message
        for worker in &self.workers {
            worker.tx.send(ToWorker::Clear).ok().expect("Worker hung up on pool.");
        }

        // do a clear run on the local worker as well.
        self.local_worker.clear();

        let mut panicked = false;
        // wait for confirmation from each worker.
        // the queues are not guaranteed to be empty until the last one responds!
        for worker in &self.workers {
            match worker.rx.recv() {
                Ok(msg) => {
                    match msg {
                        ToLeader::Cleared => continue,
                        ToLeader::Panicked => {
                            panicked = true;
                        }
                    }
                }

                Err(_) => panic!("Worker hung up on job system."),
            }
        }

        // reset the counters in every queue so there's no chance of
        // overlap.
        for queue in self.local_worker.queues.iter() {
            // asserts that len == 0 in debug mode.
            queue.reset_counters();
        }

        // reset all the pools.
        for pool in self.local_worker.pools.iter() {
            pool.reset();
        }

        // cleared and panicked workers are waiting for a shutdown message.
        if panicked {
            panic!("Propagating worker thread panic")
        }

        self.state = State::Paused;
    }
}

impl Drop for WorkPool {
    fn drop(&mut self) {
        // finish all work.
        self.clear_all();

        // now tell every worker they can shut down safely.
        for worker in &self.workers {
            worker.tx.send(ToWorker::Shutdown).ok().expect("Worker hung up on job system");
        }

        // join the threads (although they should already be at this point).
        for worker in &mut self.workers {
            worker.thread.take().map(|handle| handle.join());
        }
    }
}

/// Create a pool with `n` worker threads.
pub fn make_pool(n: usize) -> Result<WorkPool, Error> {
    WorkPool::new(n)
}

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

    #[test]
    fn creation_destruction() {
        for i in 0..32 {
            let _ = WorkPool::new(i).unwrap();
        }
    }

    #[test]
    fn split_work() {
        let mut pool = WorkPool::new(4).unwrap();
        let mut v = vec![0; 1024];
        pool.scope(|spawner| {
            for (idx, v) in v.iter_mut().enumerate() {
                spawner.submit(move |_| {
                    *v += idx;
                });
            }
        });

        assert_eq!(v, (0..1024).collect::<Vec<_>>());
    }

    #[test]
    fn multilevel_scoping() {
        let mut pool = WorkPool::new(4).unwrap();
        pool.scope(|spawner| {
            let mut v = vec![0; 256];
            spawner.scope(|s| {
                for i in &mut v {
                    s.submit(move |_| *i += 1)
                }
            });
            // job is forcibly joined here.

            assert_eq!(v, (0..256).map(|_| 1).collect::<Vec<_>>())
        }); // any other jobs would be forcibly joined here.
    }

    #[test]
    fn multiple_synchronizations() {
        let mut pool = WorkPool::new(4).unwrap();
        for _ in 0..100 {
            pool.synchronize();
        }
    }

    #[test]
    fn outlives_pool() {
        let mut v = vec![0; 256];
        let mut pool = WorkPool::new(4).unwrap();

        // can only execute 'static functions here -- otherwise,
        // some person might make the dumb mistake of calling `forget` the
        // pool before it has the chance to run all submitted jobs.
        pool.submit(move |_| {
            for i in &mut v {
                *i += 1
            }
        });
    }

    #[test]
    #[should_panic]
    fn job_panic() {
        let mut pool = WorkPool::new(4).unwrap();

        pool.submit(|_| panic!("Eep!"));
    }
}
<commit_msg>Can now get the top-level spawner.<commit_after>//! A work-stealing fork-join queue used to perform processors' work asynchronously.
//! This is intended to be short-lived. Long running asynchronous tasks should use another method.
//! For infinite loops, the longest-running of tasks, behavior will be as expected.
#![cfg_attr(nightly, feature(core_intrinsics))]

mod job;
mod queue;
mod pool;

use self::job::Job;
use self::pool::Pool;
use self::queue::Queue;

use std::io::Error;
use std::marker::PhantomData;
use std::sync::Arc;
use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread;

const MAX_JOBS: usize = 4096;

// messages to workers.
enum ToWorker {
    Start, // start
    Clear, // run all jobs to completion, then reset the pool.
    Shutdown, // all workers are clear and no jobs are running. safe to tear down pools.
}
// messages to the leader from workers.
enum ToLeader {
    Cleared, // done clearing. will wait for start or shutdown
    Panicked,
}

struct WorkerHandle {
    tx: Sender<ToWorker>,
    rx: Receiver<ToLeader>,
    thread: Option<thread::JoinHandle<()>>,
}

// Finite state machine for controlling workers.
#[derive(Clone, Copy, PartialEq)]
enum State {
    Running, // running jobs normally. waiting for state change.
    Paused, // paused, waiting for start or shutdown message.
}

struct Worker {
    queues: Arc<Vec<Queue>>,
    pools: Arc<Vec<Pool>>,
    idx: usize, // the index of this worker's queue and pool in the Vec.
}

// TODO: implement !Sync for Worker.

impl Worker {
    // pop a job from the worker's queue, or steal one from the queue with the most work.
    unsafe fn pop_or_steal(&self) -> Option<*mut Job> {
        if let Some(job) = self.queues[self.idx].pop() {
            return Some(job);
        }

        // if the queue is empty (pop failed), we can clear the pool for this queue.
        // this works only because
        // A) we push pool-allocated jobs only onto the local queue,
        // B) pop gets priority when racing against "steal".
        self.pools[self.idx].reset();

        let (mut most_work, mut most_idx) = (0, None);
        for (i, queue) in self.queues.iter().enumerate() {
            let len = queue.len();
            if len > most_work {
                most_work = len;
                most_idx = Some(i);
            }
        }

        if let Some(idx) = most_idx {
            self.queues[idx].steal()
        } else {
            None
        }
    }

    // do a sweep through all the queues, saying whether all
    // were observed to be empty initially.
    fn clear_pass(&self) -> bool {
        let mut all_clear = true;
        for (idx, queue) in self.queues.iter().enumerate() {
            if idx != self.idx {
                while let Some(job) = queue.steal() {
                    all_clear = false;
                    unsafe { (*job).call(self) }
                }
            } else {
                while let Some(job) = unsafe { queue.pop() } {
                    all_clear = false;
                    unsafe { (*job).call(self) }
                }
            }
        }

        all_clear
    }

    fn clear(&self) {
        while !self.clear_pass() {}
    }

    // run the next job.
    unsafe fn run_next(&self) {
        if let Some(job) = self.pop_or_steal() {
            (*job).call(self)
        }
    }

    // This must be called on the thread the worker is active on.
    unsafe fn submit_internal<F>(&self, counter: *const AtomicUsize, f: F)
        where F: Send + FnOnce(&Worker)
    {
        let job = Job::new(counter, f);
        let job_ptr = self.pools[self.idx].alloc(job);
        self.queues[self.idx].push(job_ptr);
    }

    // construct a new spawning scope.
    // this waits for all jobs submitted internally
    // to complete.
    fn scope<'pool, 'new, F>(&'pool self, f: F)
        where F: FnOnce(&Spawner<'pool, 'new>)
    {
        let counter = AtomicUsize::new(0);
        let s = make_spawner(self, &counter);
        f(&s);

        while counter.load(Ordering::Acquire) != 0 {
            unsafe { self.run_next() }
        }
    }
}

/// A job spawner associated with a specific scope.
/// Jobs spawned using this may spawn new jobs with the same lifetime.
pub struct Spawner<'pool, 'scope> {
    worker: &'pool Worker,
    counter: *const AtomicUsize,
    // invariant lifetime.
    _marker: PhantomData<*mut &'scope mut ()>,
}

impl<'pool, 'scope> Spawner<'pool, 'scope> {
    /// Execute a function which necessarily outlives the scope which
    /// this resides in.
    pub fn submit<F>(&self, f: F)
        where F: 'scope + Send + FnOnce(&Spawner<'pool, 'scope>)
    {
        use std::mem;

        // for sending the counter pointer across thread boundaries.
        struct SendCounter(*const AtomicUsize);
        unsafe impl Send for SendCounter {}

        unsafe {
            // increment the counter first just in case, somehow, this job
            // gets grabbed before we have a chance to increment it,
            // and we wait for all jobs to complete.
            let counter: SendCounter = SendCounter(self.counter);
            (*self.counter).fetch_add(1, Ordering::AcqRel);
            self.worker.submit_internal(self.counter, move |worker| {
                let SendCounter(count_ptr) = counter;
                // make a new spawner associated with the same scope,
                // but with the correct worker for the thread -- so if
                // this job spawns any children, we won't break any
                // invariants by accessing other workers' queues/pools
                // in unexpected ways.
                let spawner = make_spawner(worker, count_ptr);
                f(&mem::transmute(spawner))
            });
        }
    }

    /// Construct a new spawning scope smaller than the one this spawner resides in.
    pub fn scope<'new, F>(&self, f: F)
        where 'scope: 'new,
              F: FnOnce(&Spawner<'pool, 'new>)
    {
        self.worker.scope(f);
    }

    /// Execute two closures, possibly asynchronously, and return their results.
    pub fn join<A, B, R_A, R_B>(&self, oper_a: A, oper_b: B) -> (R_A, R_B)
    where A: Send + FnOnce(&Spawner) -> R_A,
          B: Send + FnOnce(&Spawner) -> R_B,
          R_A: Send,
          R_B: Send
    {
        let mut a = None;
        let mut b = None;
        self.scope(|spawner| {
            spawner.submit(|s| a = Some(oper_a(s)));
            spawner.submit(|s| b = Some(oper_b(s)));
        });

        (a.unwrap(), b.unwrap())
    }
}
fn make_spawner<'a, 'b>(worker: &'a Worker, counter: *const AtomicUsize) -> Spawner<'a, 'b> {
    Spawner {
        worker: worker,
        counter: counter,
        _marker: PhantomData,
    }
}

fn worker_main(tx: Sender<ToLeader>, rx: Receiver<ToWorker>, worker: Worker) {
    struct PanicGuard(Sender<ToLeader>);
    impl Drop for PanicGuard {
        fn drop(&mut self) {
            if thread::panicking() {
                let _ = self.0.send(ToLeader::Panicked);
            }
        }
    }
    // if the worker for this thread panics,
    let _guard = PanicGuard(tx.clone());

    let mut state = State::Paused;
    loop {
        match state {
            State::Running => {
                match rx.try_recv() {
                    Ok(ToWorker::Clear) => {
                        worker.clear();
                        tx.send(ToLeader::Cleared).expect("Pool hung up on worker");
                        state = State::Paused;
                    }
                    Ok(_) => unreachable!(),
                    Err(TryRecvError::Disconnected) => panic!("Pool hung up on worker"),
                    _ => {}
                }

                unsafe { worker.run_next() }
            }

            State::Paused => {
                if let Ok(msg) = rx.recv() {
                    match msg {
                        ToWorker::Start => {
                            state = State::Running;
                            continue;
                        }

                        ToWorker::Shutdown => {
                            break;
                        }

                        _ => unreachable!(),
                    }
                } else {
                    panic!("Pool hung up on worker");
                }
            }
        }
    }
}

/// The work pool manages worker threads in a
/// work-stealing fork-join thread pool.
// The fields here are put in Vecs for cache contiguity.
pub struct WorkPool {
    workers: Vec<WorkerHandle>,
    local_worker: Worker,
    state: State,
}

impl WorkPool {
    /// Creates a work pool with `n` worker threads.
    pub fn new(n: usize) -> Result<Self, Error> {
        // one extra queue and pool for the job system.
        let queues = Arc::new((0..n + 1).map(|_| Queue::new()).collect::<Vec<_>>());
        let pools = Arc::new((0..n + 1).map(|_| Pool::new()).collect::<Vec<_>>());
        let mut workers = Vec::with_capacity(n);

        for i in 0..n {
            let (work_send, work_recv) = channel();
            let (lead_send, lead_recv) = channel();

            let worker = Worker {
                queues: queues.clone(),
                pools: pools.clone(),
                idx: i + 1,
            };

            let builder = thread::Builder::new().name(format!("worker_{}", i));
            let handle = try!(builder.spawn(|| worker_main(lead_send, work_recv, worker)));

            workers.push(WorkerHandle {
                tx: work_send,
                rx: lead_recv,
                thread: Some(handle),
            });
        }

        let mut pool = WorkPool {
            workers: workers,
            local_worker: Worker {
                queues: queues,
                pools: pools,
                idx: 0,
            },
            state: State::Paused,
        };

        pool.spin_up();

        Ok(pool)
    }

    /// Finish all current jobs which are queued, and synchronize the workers until
    /// it's time to start again.
    ///
    /// If any of the threads have panicked, that panic
    /// will be propagated to this thread. Until the next job is submitted,
    /// workers will block, allowing other threads to have higher priority.
    pub fn synchronize(&mut self) {
        self.clear_all();
    }

    /// Create a new spawning scope for submitting jobs.
    /// Any jobs submitted in this scope will be completed
    /// by the end of this function call.
    pub fn scope<'pool, 'new, F>(&'pool mut self, f: F)
        where F: FnOnce(&Spawner<'pool, 'new>)
    {
        self.spin_up();
        self.local_worker.scope(f);
    }

    /// Execute a job which strictly owns its contents.
    /// The execution of this function may be deferred to beyond
    /// this function call.
    /// In the general case, it is safe to submit jobs which only
    /// strictly outlive the pool. However, there is always the
    /// chance that the pool could be leaked, violating the invariant
    /// that the job is completed before the borrow of the data is.
    pub fn submit<'a, F>(&'a mut self, f: F)
        where F: 'static + Send + FnOnce(&Spawner<'a, 'static>)
    {
        self.spawner().submit(f);
    }

    /// Spin up all the workers, in case they were in a paused
    /// state.
    pub fn spin_up(&mut self) {
        if self.state != State::Running {
            for worker in &self.workers {
                worker.tx.send(ToWorker::Start).expect("Worker hung up on pool");
            }

            self.state = State::Running;
        }
    }

    /// Get a reference to the local spawner.
    /// This can only be used to spawn static jobs.
    pub fn spawner<'a>(&'a mut self) -> Spawner<'a, 'static> {
        use std::ptr;

        self.spin_up();
        make_spawner(&self.local_worker, ptr::null_mut())
    }

    // clear all the workers and sets the state to paused.
    fn clear_all(&mut self) {
        if self.state == State::Paused {
            return;
        }
        // send every worker a clear message
        for worker in &self.workers {
            worker.tx.send(ToWorker::Clear).ok().expect("Worker hung up on pool.");
        }

        // do a clear run on the local worker as well.
        self.local_worker.clear();

        let mut panicked = false;
        // wait for confirmation from each worker.
        // the queues are not guaranteed to be empty until the last one responds!
        for worker in &self.workers {
            match worker.rx.recv() {
                Ok(msg) => {
                    match msg {
                        ToLeader::Cleared => continue,
                        ToLeader::Panicked => {
                            panicked = true;
                        }
                    }
                }

                Err(_) => panic!("Worker hung up on job system."),
            }
        }

        // reset the counters in every queue so there's no chance of
        // overlap.
        for queue in self.local_worker.queues.iter() {
            // asserts that len == 0 in debug mode.
            queue.reset_counters();
        }

        // reset all the pools.
        for pool in self.local_worker.pools.iter() {
            pool.reset();
        }

        // cleared and panicked workers are waiting for a shutdown message.
        if panicked {
            panic!("Propagating worker thread panic")
        }

        self.state = State::Paused;
    }
}

impl Drop for WorkPool {
    fn drop(&mut self) {
        // finish all work.
        self.clear_all();

        // now tell every worker they can shut down safely.
        for worker in &self.workers {
            worker.tx.send(ToWorker::Shutdown).ok().expect("Worker hung up on job system");
        }

        // join the threads (although they should already be at this point).
        for worker in &mut self.workers {
            worker.thread.take().map(|handle| handle.join());
        }
    }
}

/// Create a pool with `n` worker threads.
pub fn make_pool(n: usize) -> Result<WorkPool, Error> {
    WorkPool::new(n)
}

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

    #[test]
    fn creation_destruction() {
        for i in 0..32 {
            let _ = WorkPool::new(i).unwrap();
        }
    }

    #[test]
    fn split_work() {
        let mut pool = WorkPool::new(4).unwrap();
        let mut v = vec![0; 1024];
        pool.scope(|spawner| {
            for (idx, v) in v.iter_mut().enumerate() {
                spawner.submit(move |_| {
                    *v += idx;
                });
            }
        });

        assert_eq!(v, (0..1024).collect::<Vec<_>>());
    }

    #[test]
    fn multilevel_scoping() {
        let mut pool = WorkPool::new(4).unwrap();
        pool.scope(|spawner| {
            let mut v = vec![0; 256];
            spawner.scope(|s| {
                for i in &mut v {
                    s.submit(move |_| *i += 1)
                }
            });
            // job is forcibly joined here.

            assert_eq!(v, (0..256).map(|_| 1).collect::<Vec<_>>())
        }); // any other jobs would be forcibly joined here.
    }

    #[test]
    fn multiple_synchronizations() {
        let mut pool = WorkPool::new(4).unwrap();
        for _ in 0..100 {
            pool.synchronize();
        }
    }

    #[test]
    fn outlives_pool() {
        let mut v = vec![0; 256];
        let mut pool = WorkPool::new(4).unwrap();

        // can only execute 'static functions here -- otherwise,
        // some person might make the dumb mistake of calling `forget` the
        // pool before it has the chance to run all submitted jobs.
        pool.submit(move |_| {
            for i in &mut v {
                *i += 1
            }
        });
    }

    #[test]
    #[should_panic]
    fn job_panic() {
        let mut pool = WorkPool::new(4).unwrap();

        pool.submit(|_| panic!("Eep!"));
    }
}
<|endoftext|>


<commit_before>use display_list::DisplayListBuilder;
use euclid::Point2D;
use ipc_channel::ipc::{self, IpcSender};
use stacking_context::StackingContext;
use std::cell::Cell;
use types::{ColorF, DisplayListId, Epoch, FontKey, StackingContextId};
use types::{ImageKey, ImageFormat, NativeFontHandle, PipelineId};

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct IdNamespace(pub u32);

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct ResourceId(pub u32);

#[derive(Serialize, Deserialize)]
pub enum ApiMsg {
    AddRawFont(FontKey, Vec<u8>),
    AddNativeFont(FontKey, NativeFontHandle),
    AddImage(ImageKey, u32, u32, ImageFormat, Vec<u8>),
    UpdateImage(ImageKey, u32, u32, ImageFormat, Vec<u8>),
    AddDisplayList(DisplayListId, PipelineId, Epoch, DisplayListBuilder),
    AddStackingContext(StackingContextId, PipelineId, Epoch, StackingContext),
    CloneApi(IpcSender<IdNamespace>),
    SetRootStackingContext(StackingContextId, ColorF, Epoch, PipelineId),
    SetRootPipeline(PipelineId),
    Scroll(Point2D<f32>),
    TranslatePointToLayerSpace(Point2D<f32>, IpcSender<Point2D<f32>>),
}

#[derive(Serialize, Deserialize, Clone)]
pub struct RenderApiSender(IpcSender<ApiMsg>);

impl RenderApiSender {
    pub fn new(tx: IpcSender<ApiMsg>) -> RenderApiSender {
        RenderApiSender(tx)
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender(ref tx) = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        tx.send(msg).unwrap();
        RenderApi {
            tx: tx.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub tx: IpcSender<ApiMsg>,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.tx.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.tx.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.tx.send(msg).unwrap();
        key
    }

    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.tx.send(msg).unwrap();
        key
    }

    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.tx.send(msg).unwrap();
    }

    pub fn add_display_list(&self,
                            display_list: DisplayListBuilder,
                            stacking_context: &mut StackingContext,
                            pipeline_id: PipelineId,
                            epoch: Epoch) -> Option<DisplayListId> {
        //TODO! debug_assert!(display_list.item_count() > 0, "Avoid adding empty lists!");
        let new_id = self.next_unique_id();
        let id = DisplayListId(new_id.0, new_id.1);
        stacking_context.has_stacking_contexts = stacking_context.has_stacking_contexts ||
                                                 display_list.has_stacking_contexts;
        let msg = ApiMsg::AddDisplayList(id, pipeline_id, epoch, display_list);
        self.tx.send(msg).unwrap();
        stacking_context.display_lists.push(id);

        Some(id)
    }

    pub fn add_stacking_context(&self,
                                stacking_context: StackingContext,
                                pipeline_id: PipelineId,
                                epoch: Epoch) -> StackingContextId {
        let new_id = self.next_unique_id();
        let id = StackingContextId(new_id.0, new_id.1);
        let msg = ApiMsg::AddStackingContext(id, pipeline_id, epoch, stacking_context);
        self.tx.send(msg).unwrap();
        id
    }

    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.tx.send(msg).unwrap();
    }

    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id);
        self.tx.send(msg).unwrap();
    }

    pub fn scroll(&self, delta: Point2D<f32>) {
        let msg = ApiMsg::Scroll(delta);
        self.tx.send(msg).unwrap();
    }

    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>) -> Point2D<f32> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.tx.send(msg).unwrap();
        rx.recv().unwrap()
    }

    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}
<commit_msg>Temporary disable native fonts until fixed properly with e10s support.<commit_after>use display_list::DisplayListBuilder;
use euclid::Point2D;
use ipc_channel::ipc::{self, IpcSender};
use stacking_context::StackingContext;
use std::cell::Cell;
use types::{ColorF, DisplayListId, Epoch, FontKey, StackingContextId};
use types::{ImageKey, ImageFormat, NativeFontHandle, PipelineId};

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct IdNamespace(pub u32);

#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct ResourceId(pub u32);

#[derive(Serialize, Deserialize)]
pub enum ApiMsg {
    AddRawFont(FontKey, Vec<u8>),
    //AddNativeFont(FontKey, NativeFontHandle),
    AddImage(ImageKey, u32, u32, ImageFormat, Vec<u8>),
    UpdateImage(ImageKey, u32, u32, ImageFormat, Vec<u8>),
    AddDisplayList(DisplayListId, PipelineId, Epoch, DisplayListBuilder),
    AddStackingContext(StackingContextId, PipelineId, Epoch, StackingContext),
    CloneApi(IpcSender<IdNamespace>),
    SetRootStackingContext(StackingContextId, ColorF, Epoch, PipelineId),
    SetRootPipeline(PipelineId),
    Scroll(Point2D<f32>),
    TranslatePointToLayerSpace(Point2D<f32>, IpcSender<Point2D<f32>>),
}

#[derive(Serialize, Deserialize, Clone)]
pub struct RenderApiSender(IpcSender<ApiMsg>);

impl RenderApiSender {
    pub fn new(tx: IpcSender<ApiMsg>) -> RenderApiSender {
        RenderApiSender(tx)
    }

    pub fn create_api(&self) -> RenderApi {
        let RenderApiSender(ref tx) = *self;
        let (sync_tx, sync_rx) = ipc::channel().unwrap();
        let msg = ApiMsg::CloneApi(sync_tx);
        tx.send(msg).unwrap();
        RenderApi {
            tx: tx.clone(),
            id_namespace: sync_rx.recv().unwrap(),
            next_id: Cell::new(ResourceId(0)),
        }
    }
}

pub struct RenderApi {
    pub tx: IpcSender<ApiMsg>,
    pub id_namespace: IdNamespace,
    pub next_id: Cell<ResourceId>,
}

impl RenderApi {
    pub fn clone_sender(&self) -> RenderApiSender {
        RenderApiSender::new(self.tx.clone())
    }

    pub fn add_raw_font(&self, bytes: Vec<u8>) -> FontKey {
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddRawFont(key, bytes);
        self.tx.send(msg).unwrap();
        key
    }

    pub fn add_native_font(&self, native_font_handle: NativeFontHandle) -> FontKey {
        panic!("TODO: Get this working again with the e10s changes!");
        /*
        let new_id = self.next_unique_id();
        let key = FontKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddNativeFont(key, native_font_handle);
        self.tx.send(msg).unwrap();
        key*/
    }

    pub fn alloc_image(&self) -> ImageKey {
        let new_id = self.next_unique_id();
        ImageKey::new(new_id.0, new_id.1)
    }

    pub fn add_image(&self,
                     width: u32,
                     height: u32,
                     format: ImageFormat,
                     bytes: Vec<u8>) -> ImageKey {
        let new_id = self.next_unique_id();
        let key = ImageKey::new(new_id.0, new_id.1);
        let msg = ApiMsg::AddImage(key, width, height, format, bytes);
        self.tx.send(msg).unwrap();
        key
    }

    // TODO: Support changing dimensions (and format) during image update?
    pub fn update_image(&self,
                        key: ImageKey,
                        width: u32,
                        height: u32,
                        format: ImageFormat,
                        bytes: Vec<u8>) {
        let msg = ApiMsg::UpdateImage(key, width, height, format, bytes);
        self.tx.send(msg).unwrap();
    }

    pub fn add_display_list(&self,
                            display_list: DisplayListBuilder,
                            stacking_context: &mut StackingContext,
                            pipeline_id: PipelineId,
                            epoch: Epoch) -> Option<DisplayListId> {
        //TODO! debug_assert!(display_list.item_count() > 0, "Avoid adding empty lists!");
        let new_id = self.next_unique_id();
        let id = DisplayListId(new_id.0, new_id.1);
        stacking_context.has_stacking_contexts = stacking_context.has_stacking_contexts ||
                                                 display_list.has_stacking_contexts;
        let msg = ApiMsg::AddDisplayList(id, pipeline_id, epoch, display_list);
        self.tx.send(msg).unwrap();
        stacking_context.display_lists.push(id);

        Some(id)
    }

    pub fn add_stacking_context(&self,
                                stacking_context: StackingContext,
                                pipeline_id: PipelineId,
                                epoch: Epoch) -> StackingContextId {
        let new_id = self.next_unique_id();
        let id = StackingContextId(new_id.0, new_id.1);
        let msg = ApiMsg::AddStackingContext(id, pipeline_id, epoch, stacking_context);
        self.tx.send(msg).unwrap();
        id
    }

    pub fn set_root_pipeline(&self, pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootPipeline(pipeline_id);
        self.tx.send(msg).unwrap();
    }

    pub fn set_root_stacking_context(&self,
                                     stacking_context_id: StackingContextId,
                                     background_color: ColorF,
                                     epoch: Epoch,
                                     pipeline_id: PipelineId) {
        let msg = ApiMsg::SetRootStackingContext(stacking_context_id,
                                                 background_color,
                                                 epoch,
                                                 pipeline_id);
        self.tx.send(msg).unwrap();
    }

    pub fn scroll(&self, delta: Point2D<f32>) {
        let msg = ApiMsg::Scroll(delta);
        self.tx.send(msg).unwrap();
    }

    pub fn translate_point_to_layer_space(&self, point: &Point2D<f32>) -> Point2D<f32> {
        let (tx, rx) = ipc::channel().unwrap();
        let msg = ApiMsg::TranslatePointToLayerSpace(*point, tx);
        self.tx.send(msg).unwrap();
        rx.recv().unwrap()
    }

    fn next_unique_id(&self) -> (u32, u32) {
        let IdNamespace(namespace) = self.id_namespace;
        let ResourceId(id) = self.next_id.get();
        self.next_id.set(ResourceId(id + 1));
        (namespace, id)
    }
}
<|endoftext|>


<commit_before>extern crate num;
extern crate rand;
extern crate rutorch;

use rutorch::*;
use std::ops::{Index, IndexMut};
use rand::Rng;
//use std::convert::From;
use num::Num;
use std::cmp::max;

struct BaseIter<'a, T, P: 'a + Index<isize>> {
	idx: usize,
	parent: &'a P,
	t: std::marker::PhantomData<T>,
}

impl <'a, T, P: Index<isize> >BaseIter<'a, T, P> {
	fn new(parent: &'a P) -> Self {
		BaseIter { idx: 0, parent: parent, t: std::default::Default::default()}
	}
}

trait Storage {
	fn new() -> Self;
	fn sized(len: isize) -> Self;
}

struct FloatStorage {
	t: *mut THFloatStorage,
}

impl Storage for FloatStorage {
	fn new() -> Self {
		unsafe { FloatStorage  {t : THFloatStorage_new()} }
	}
	fn sized(size: isize) ->Self {
		unsafe { FloatStorage  {t : THFloatStorage_newWithSize(size)} }
	}
}

impl FloatStorage {
	fn iter(&mut self) -> BaseIter<f32, FloatStorage> {
		BaseIter::new(&self)
	}
}

impl Index<isize> for FloatStorage {
	type Output = f32;

	fn index(&self, idx: isize) -> &f32 {
		unsafe {&*(*self.t).data.offset(idx)}
	}
}

impl IndexMut<isize> for FloatStorage {
	fn index_mut(&mut self, idx: isize) -> &mut f32 {
		unsafe {&mut *(*self.t).data.offset(idx)}
	}
}

impl <'a, f32, FloatStorage >Iterator for BaseIter<'a, f32, FloatStorage>
	where FloatStorage: std::ops::Index<isize> {
	type Item = f32;

	fn next(&mut self) -> Option<f32> {
		// XXX check length ---
		let ret = (*self.parent).index(self.idx as isize);
		self.idx += 1;
		Some(*ret)
	}
}

//fn from(args: &ArgsArray<T>) -> Self;

trait Tensor<'a> : Index<&'a [isize]> {
	fn new() -> Self;
	fn sized(size: &'a [isize]) -> Self;
	fn randn(dims: &'a [isize]) -> Self;
}

struct FloatTensor {
	t: *mut THFloatTensor,
	storage: FloatStorage,
	dims: Vec<isize>,
}

impl <'a>Tensor<'a> for FloatTensor {
	fn new() -> Self {
		unsafe { FloatTensor { t : THFloatTensor_new(), storage: FloatStorage::new(), dims: Vec::new()  }}
	}
	fn sized(dims: &'a [isize]) -> Self {
		let size = dims.iter().product();
		let storage = FloatStorage::sized(size);
		let strides = vec![1; dims.len()];
		let mut t = THFloatTensor { size : dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
			stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
			nDimension : dims.len() as i32, storage: storage.t, storageOffset: 0, refcount: 1,
			flag: TH_TENSOR_REFCOUNTED as i8};
		FloatTensor {t : &mut t, storage: storage, dims: Vec::from(dims)}
	}
	fn randn(dims: &'a [isize]) -> Self {
		/* XXX */
		let t = Tensor::sized(dims);
//		x = random::<f32>();
		t
	}
}

impl <'a> Index<&'a [isize]> for FloatTensor {
	type Output = f32;

	fn index(&self, idx: &'a [isize]) -> &f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&self.storage[index]
	}
}

impl <'a> IndexMut<&'a [isize]> for FloatTensor {
	fn index_mut(&mut self, idx: &'a [isize]) -> &mut f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&mut self.storage[index]
	}
}

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

    }
}
<commit_msg>make Iterator (mostly) happy<commit_after>extern crate num;
extern crate rand;
extern crate rutorch;

use rutorch::*;
use std::ops::{Index, IndexMut};
use rand::Rng;
//use std::convert::From;
use num::Num;
use std::cmp::max;

struct BaseIter<'a, T, P: 'a + Index<isize>> {
	idx: usize,
	parent: &'a P,
	t: std::marker::PhantomData<T>,
}

impl <'a, T, P: Index<isize> >BaseIter<'a, T, P> {
	fn new(parent: &'a P) -> Self {
		BaseIter { idx: 0, parent: parent, t: std::default::Default::default()}
	}
}

trait Storage {
	fn new() -> Self;
	fn sized(len: isize) -> Self;
}

struct FloatStorage {
	t: *mut THFloatStorage,
}

impl Storage for FloatStorage {
	fn new() -> Self {
		unsafe { FloatStorage  {t : THFloatStorage_new()} }
	}
	fn sized(size: isize) ->Self {
		unsafe { FloatStorage  {t : THFloatStorage_newWithSize(size)} }
	}
}

impl FloatStorage {
	fn iter(&mut self) -> BaseIter<f32, FloatStorage> {
		BaseIter::new(self)
	}
}

impl Index<isize> for FloatStorage {
	type Output = f32;

	fn index(&self, idx: isize) -> &f32 {
		unsafe {&*(*self.t).data.offset(idx)}
	}
}

impl IndexMut<isize> for FloatStorage {
	fn index_mut(&mut self, idx: isize) -> &mut f32 {
		unsafe {&mut *(*self.t).data.offset(idx)}
	}
}

impl <'a, f32, T>Iterator for BaseIter<'a, f32, T>
	where T: std::ops::Index<isize, Output=f32> {
	type Item = f32;

	fn next(&mut self) -> Option<f32> {
		// XXX check length ---
		let ret = *(*self.parent).index(self.idx as isize);
		self.idx += 1;
		Some(ret)
	}
}

//fn from(args: &ArgsArray<T>) -> Self;

trait Tensor<'a> : Index<&'a [isize]> {
	fn new() -> Self;
	fn sized(size: &'a [isize]) -> Self;
	fn randn(dims: &'a [isize]) -> Self;
}

struct FloatTensor {
	t: *mut THFloatTensor,
	storage: FloatStorage,
	dims: Vec<isize>,
}

impl <'a>Tensor<'a> for FloatTensor {
	fn new() -> Self {
		unsafe { FloatTensor { t : THFloatTensor_new(), storage: FloatStorage::new(), dims: Vec::new()  }}
	}
	fn sized(dims: &'a [isize]) -> Self {
		let size = dims.iter().product();
		let storage = FloatStorage::sized(size);
		let strides = vec![1; dims.len()];
		let mut t = THFloatTensor { size : dims.clone().as_ptr() as *mut ::std::os::raw::c_long,
			stride: strides.as_ptr() as *mut ::std::os::raw::c_long,
			nDimension : dims.len() as i32, storage: storage.t, storageOffset: 0, refcount: 1,
			flag: TH_TENSOR_REFCOUNTED as i8};
		FloatTensor {t : &mut t, storage: storage, dims: Vec::from(dims)}
	}
	fn randn(dims: &'a [isize]) -> Self {
		/* XXX */
		let t = Tensor::sized(dims);
//		x = random::<f32>();
		t
	}
}

impl <'a> Index<&'a [isize]> for FloatTensor {
	type Output = f32;

	fn index(&self, idx: &'a [isize]) -> &f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&self.storage[index]
	}
}

impl <'a> IndexMut<&'a [isize]> for FloatTensor {
	fn index_mut(&mut self, idx: &'a [isize]) -> &mut f32 {
		let mut index : isize = 0;
		let lastidx = max(0, idx.len() as isize - 1) as usize;
		if idx.len() != self.dims.len() { panic!("bad dimlen")}
		for i in 0..lastidx {
			if idx[i] >= self.dims[i] { panic!("bad dimlen")}
			index += idx[i] * self.dims[i]
		}
		if idx[lastidx] >= self.dims[lastidx] { panic!("bad dimlen")}
		index += idx[lastidx];
		&mut self.storage[index]
	}
}

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

    }
}
<|endoftext|>


<commit_before>#![warn(rust_2018_idioms)]

extern crate http;

use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::net::SocketAddr;

pub use http::{header, HeaderMap, Method, Request, Response, StatusCode, Version};

pub use self::typemap::TypeMap;
mod typemap;

pub type ResponseResult<Error> = Result<Response<Body>, Error>;
pub type HttpResult = ResponseResult<http::Error>;

pub type BoxError = Box<dyn Error + Send>;
pub type HandlerResult = Result<Response<Body>, BoxError>;

pub enum Body {
    Static(&'static [u8]),
    Owned(Vec<u8>),
    File(File),
}

impl Body {
    pub fn empty() -> Self {
        Self::from_static(b"")
    }

    pub fn from_static(bytes: &'static [u8]) -> Self {
        Self::Static(bytes)
    }

    pub fn from_vec(bytes: Vec<u8>) -> Self {
        Self::Owned(bytes)
    }
}

pub fn box_error<E: Error + Send + 'static>(error: E) -> BoxError {
    Box::new(error)
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Scheme {
    Http,
    Https,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Host<'a> {
    Name(&'a str),
    Socket(SocketAddr),
}

/// A Dictionary for extensions provided by the server or middleware
pub type Extensions = TypeMap;

pub trait RequestExt {
    /// The version of HTTP being used
    fn http_version(&self) -> Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method(&self) -> &Method;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_addr(&self) -> SocketAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<u64>;

    /// The request's headers, as conduit::Headers.
    fn headers(&self) -> &HeaderMap;

    /// A Reader for the body of the request
    fn body<'a>(&'a mut self) -> &'a mut dyn Read;

    /// A readable map of extensions
    fn extensions<'a>(&'a self) -> &'a Extensions;

    /// A mutable map of extensions
    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions;
}

/// A Handler takes a request and returns a response or an error.
/// By default, a bare function implements `Handler`.
pub trait Handler: Sync + Send + 'static {
    fn call(&self, request: &mut dyn RequestExt) -> HandlerResult;
}

impl<F, E> Handler for F
where
    F: Fn(&mut dyn RequestExt) -> ResponseResult<E> + Sync + Send + 'static,
    E: Error + Send + 'static,
{
    fn call(&self, request: &mut dyn RequestExt) -> HandlerResult {
        (*self)(request).map_err(box_error)
    }
}
<commit_msg>Add some documentation<commit_after>#![warn(rust_2018_idioms)]

extern crate http;

use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::net::SocketAddr;

pub use http::{header, HeaderMap, Method, Request, Response, StatusCode, Version};

pub use self::typemap::TypeMap;
mod typemap;

pub type ResponseResult<Error> = Result<Response<Body>, Error>;
pub type HttpResult = ResponseResult<http::Error>;

pub type BoxError = Box<dyn Error + Send>;
pub type HandlerResult = Result<Response<Body>, BoxError>;

/// A type representing a `Response` body.
///
/// This type is intended exclusively for use as part of a `Response<Body>`.
/// Each conduit server provides its own request type that implements
/// `RequestExt` which provides the request body as a `&'a mut dyn Read`.
pub enum Body {
    Static(&'static [u8]),
    Owned(Vec<u8>),
    File(File),
}

impl Body {
    /// Create a new `Body` from an empty static slice.
    pub fn empty() -> Self {
        Self::from_static(b"")
    }

    /// Create a new `Body` from the provided static byte slice.
    pub fn from_static(bytes: &'static [u8]) -> Self {
        Self::Static(bytes)
    }

    /// Create a new `Body` by taking ownership of the provided bytes.
    pub fn from_vec(bytes: Vec<u8>) -> Self {
        Self::Owned(bytes)
    }
}

/// A helper to convert a concrete error type into a `Box<dyn Error + Send>`
///
/// # Example
///
/// ```
/// # use std::error::Error;
/// # use conduit::{box_error, Body, Response};
/// # let _: Result<Response<Body>, Box<dyn Error + Send>> =
/// Response::builder().body(Body::empty()).map_err(box_error);
/// ```
pub fn box_error<E: Error + Send + 'static>(error: E) -> BoxError {
    Box::new(error)
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Scheme {
    Http,
    Https,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Host<'a> {
    Name(&'a str),
    Socket(SocketAddr),
}

/// A Dictionary for extensions provided by the server or middleware
pub type Extensions = TypeMap;

pub trait RequestExt {
    /// The version of HTTP being used
    fn http_version(&self) -> Version;

    /// The request method, such as GET, POST, PUT, DELETE or PATCH
    fn method(&self) -> &Method;

    /// The scheme part of the request URL
    fn scheme(&self) -> Scheme;

    /// The host part of the requested URL
    fn host<'a>(&'a self) -> Host<'a>;

    /// The initial part of the request URL's path that corresponds
    /// to a virtual root. This allows an application to have a
    /// virtual location that consumes part of the path.
    fn virtual_root<'a>(&'a self) -> Option<&'a str>;

    /// The remainder of the path.
    fn path<'a>(&'a self) -> &'a str;

    /// The portion of the request URL that follows the "?"
    fn query_string<'a>(&'a self) -> Option<&'a str>;

    /// The remote IP address of the client or the last proxy that
    /// sent the request.
    fn remote_addr(&self) -> SocketAddr;

    /// The byte-size of the body, if any
    fn content_length(&self) -> Option<u64>;

    /// The request's headers, as conduit::Headers.
    fn headers(&self) -> &HeaderMap;

    /// A Reader for the body of the request
    ///
    /// # Blocking
    ///
    /// The returned value implements the blocking `Read` API and should only
    /// be read from while in a blocking context.
    fn body<'a>(&'a mut self) -> &'a mut dyn Read;

    /// A readable map of extensions
    fn extensions<'a>(&'a self) -> &'a Extensions;

    /// A mutable map of extensions
    fn mut_extensions<'a>(&'a mut self) -> &'a mut Extensions;
}

/// A Handler takes a request and returns a response or an error.
/// By default, a bare function implements `Handler`.
pub trait Handler: Sync + Send + 'static {
    fn call(&self, request: &mut dyn RequestExt) -> HandlerResult;
}

impl<F, E> Handler for F
where
    F: Fn(&mut dyn RequestExt) -> ResponseResult<E> + Sync + Send + 'static,
    E: Error + Send + 'static,
{
    fn call(&self, request: &mut dyn RequestExt) -> HandlerResult {
        (*self)(request).map_err(box_error)
    }
}
<|endoftext|>


<commit_before>use app::App;
use cgmath::vector::{Vector2};
use color::rgb::consts::*;
use glutil::glrenderer::GlRenderer;
use key;
use rand;
use renderer::Renderer;
use renderer;
use world::area::{Area, Location, ChartPos};
use world::area;
use world::areaview;
use world::fov;
use world::mapgen::MapGen;
use world::mob::Mob;
use world::sprite;
use world::state;
use world::transform::Transform;

static VERSION: &'static str = include!("../../gen/git_version.inc");

pub struct State {
    area: Area,
    loc: Location,
}

impl state::State for State {
    fn transform(&self) -> Transform { Transform::new(ChartPos::from_location(self.loc)) }
    fn fov(&self, _loc: Location) -> fov::FovStatus { fov::Seen }
    fn drawable_mob_at<'a>(&'a self, _loc: Location) -> Option<&'a Mob> { None }
    fn area<'a>(&'a self) -> &'a Area { &self.area }
}

impl State {
    pub fn new() -> State {
        let mut area = Area::new(area::Tree);
        let mut rng = rand::StdRng::new().unwrap();
        area.gen_herringbone(&mut rng);
        State {
            area: area,
            loc: Location::new(0i8, 0i8),
        }
    }
}

pub fn main() {
    let mut app : App<GlRenderer> = App::new(640, 360, format!("Tech demo ({})", VERSION));
    areaview::init_tiles(&mut app);

    let mut state = State::new();

    while app.alive {
        areaview::draw_area(&state, &mut app);
        loop {
            match app.r.pop_key() {
                Some(key) => {
                    match key.code {
                        key::ESC => { app.quit(); }
                        key::F12 => { app.r.screenshot("/tmp/shot.png"); }
                        key::UP => { state.loc = state.loc + Vector2::new(-1, -1); }
                        key::DOWN => { state.loc = state.loc + Vector2::new(1, 1); }
                        key::LEFT => { state.loc = state.loc + Vector2::new(-1, 1); }
                        key::RIGHT => { state.loc = state.loc + Vector2::new(1, -1); }
                        _ => (),
                    }
                }
                _ => { break; }
            }
        }

        let mouse = app.r.get_mouse();
        let xf = Transform::new(ChartPos::from_location(state.loc));
        let cursor_chart_pos = xf.to_chart(&mouse.pos);
        app.r.draw_tile(areaview::CURSOR_BOTTOM, &xf.to_screen(cursor_chart_pos), sprite::FLOOR_Z, &FIREBRICK, renderer::ColorKeyDraw);
        app.r.draw_tile(areaview::CURSOR_TOP, &xf.to_screen(cursor_chart_pos), sprite::BLOCK_Z, &FIREBRICK, renderer::ColorKeyDraw);

        app.r.flush();
    }
}
<commit_msg>Map rendering demo with new engine<commit_after>use cgmath::vector::{Vector2};
use color::rgb::consts::*;
use key;
use rand;
use world::area::{Area, Location, ChartPos};
use world::area;
use world::areaview;
use world::fov;
use world::mapgen::MapGen;
use world::mob::Mob;
use world::sprite;
use world::state;
use world::transform::Transform;
use engine::{App, Engine, Key, Image};
use engine;

static VERSION: &'static str = include!("../../gen/git_version.inc");

pub struct State {
    area: Area,
    loc: Location,
    tiles: Vec<Image>,
}

impl state::State for State {
    fn transform(&self) -> Transform { Transform::new(ChartPos::from_location(self.loc)) }
    fn fov(&self, _loc: Location) -> fov::FovStatus { fov::Seen }
    fn drawable_mob_at<'a>(&'a self, _loc: Location) -> Option<&'a Mob> { None }
    fn area<'a>(&'a self) -> &'a Area { &self.area }
}

impl State {
    pub fn new() -> State {
        let mut area = Area::new(area::Tree);
        let mut rng = rand::StdRng::new().unwrap();
        area.gen_herringbone(&mut rng);
        State {
            area: area,
            loc: Location::new(0i8, 0i8),
            tiles: vec!(),
        }
    }
}

impl App for State {
    fn setup(&mut self, ctx: &mut Engine) {
        self.tiles = areaview::init_tiles(ctx);
    }

    fn key_pressed(&mut self, ctx: &mut Engine, key: Key) {
        match key {
            engine::KeyEscape => { ctx.quit(); }
            engine::KeyF12 => { ctx.screenshot("/tmp/shot.png"); }
            engine::KeyUp => { self.loc = self.loc + Vector2::new(-1, -1); }
            engine::KeyDown => { self.loc = self.loc + Vector2::new(1, 1); }
            engine::KeyLeft => { self.loc = self.loc + Vector2::new(-1, 1); }
            engine::KeyRight => { self.loc = self.loc + Vector2::new(1, -1); }
            _ => (),
        }
    }

    fn draw(&mut self, ctx: &mut Engine) {
        areaview::draw_area(ctx, self, &self.tiles);

        let mouse = ctx.get_mouse();
        let xf = Transform::new(ChartPos::from_location(self.loc));
        let cursor_chart_pos = xf.to_chart(&mouse.pos);

        ctx.set_color(&FIREBRICK);
        ctx.set_layer(sprite::FLOOR_Z);
        ctx.draw_image(self.tiles.get(areaview::CURSOR_BOTTOM), &xf.to_screen(cursor_chart_pos));
        ctx.set_layer(sprite::BLOCK_Z);
        ctx.draw_image(self.tiles.get(areaview::CURSOR_TOP), &xf.to_screen(cursor_chart_pos));
    }
}

pub fn main() {
    let mut app = State::new();
    Engine::run(&mut app);
}
<|endoftext|>


<commit_before>use sea_canal::Analyzer;
use sea_canal::Pattern;
use sea_canal::PatternElem::*;

#[test]
fn meta_find_any_pattern() {
    let slice = &[1, 2, 4, 7, 11];
    let analyzer = Analyzer::with_meta(slice);

    assert_eq!(Some(pat!(Meta(pat!(Plus(1), Plus(2), Plus(3), Plus(4))))), analyzer.find_any_pattern(1));
}

#[test]
fn meta_find_patterns_of_length() {
    let slice = &[10, 11, 10, 12, 10, 13, 10];
    let analyzer = Analyzer::with_meta(slice);

    assert_eq!(Vec::<Pattern>::new(), analyzer.find_patterns_of_length(1));
    assert_eq!(
        vec![
            pat!(Meta(pat!(Plus(1), Plus(2), Plus(3))), Const(10)),
            pat!(Meta(pat!(Plus(1), Plus(2), Plus(3))), Meta(pat!(Plus(-1), Plus(-2), Plus(-3))))
        ],
        analyzer.find_patterns_of_length(2));
}
<commit_msg>add test for mixed-operand meta-patterns<commit_after>use sea_canal::Analyzer;
use sea_canal::Pattern;
use sea_canal::PatternElem::*;

#[test]
fn meta_find_any_pattern() {
    let slice = &[1, 2, 4, 7, 11];
    let analyzer = Analyzer::with_meta(slice);

    assert_eq!(Some(pat!(Meta(pat!(Plus(1), Plus(2), Plus(3), Plus(4))))), analyzer.find_any_pattern(1));
}

#[test]
fn meta_find_patterns_of_length() {
    let slice = &[10, 11, 10, 12, 10, 13, 10];
    let analyzer = Analyzer::with_meta(slice);

    assert_eq!(Vec::<Pattern>::new(), analyzer.find_patterns_of_length(1));
    assert_eq!(
        vec![
            pat!(Meta(pat!(Plus(1), Plus(2), Plus(3))), Const(10)),
            pat!(Meta(pat!(Plus(1), Plus(2), Plus(3))), Meta(pat!(Plus(-1), Plus(-2), Plus(-3))))
        ],
        analyzer.find_patterns_of_length(2));
}

#[test]
fn mixed_operand_meta_pattern() {
    let slice = &[10, 11, 10, 20, 10, 13, 10, 40];
    let analyzer = Analyzer::with_meta(slice);

    assert_eq!(None, analyzer.find_any_pattern(1));
    assert_eq!(Some(pat!(Meta(pat!(Plus(1), Mult(2), Plus(3), Mult(4))), Const(10))), analyzer.find_any_pattern(4));
}
<|endoftext|>