<commit_before>
extern crate serialize;

use serialize::json;
use serialize::json::{Json, JsonObject, ToJson, I64};
use std::collections::TreeMap;

use mutable_json::MutableJson;

mod mutable_json;

#[deriving(Show)]
pub enum ValicoErrorKind {
	PresenceError,
	CoerceError,
	ValidationError,
    Other
}

#[deriving(Show)]
pub struct ValicoError {
    pub kind: ValicoErrorKind,
    pub message: String
}

pub type ValicoResult<T> = Result<T, TreeMap<String, ValicoError>>;

fn single_error(err: ValicoError) -> TreeMap<String, ValicoError> {
	let mut tree = TreeMap::new();
	tree.insert("0".to_string(), err);

	tree
}

fn singe_coerce_error(err_msg: String) -> TreeMap<String, ValicoError> {
	let mut tree = TreeMap::new();
	let error = ValicoError {
		kind: CoerceError,
		message: err_msg
	};
	tree.insert("0".to_string(), error);

	tree
}

trait Coercer: Send + Sync {
	fn coerce(&self, &mut Json, Option<&Builder>) -> ValicoResult<Option<Json>>;
}

struct StringCoercer;

impl Coercer for StringCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_string() {
			Ok(None)
		} else if val.is_number() {
			Ok(Some(val.to_string().to_json()))
		} else {
			Err(
				singe_coerce_error(format!("Can't coerce object {} to string", val))
			)
		}
	}
}

struct I64Coercer;

impl Coercer for I64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_i64() {
			return Ok(None)
		} else if val.is_u64() {
			let val = val.as_u64().unwrap();
			return Ok(Some((val as i64).to_json()));
		} else if val.is_f64() {
			let val = val.as_f64().unwrap();
			return Ok(Some((val as i64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<i64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(singe_coerce_error(format!("Can't string value {} to i64", val)))
			}
		} else {
			Err(singe_coerce_error(format!("Can't coerce object {} to i64", val)))
		}
	}
}

struct U64Coercer;

impl Coercer for U64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_u64() {
			return Ok(None)
		} else if val.is_i64() {
			let val = val.as_i64().unwrap();
			return Ok(Some((val as u64).to_json()));
		} else if val.is_f64() {
			let val = val.as_f64().unwrap();
			return Ok(Some((val as u64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<u64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(singe_coerce_error(format!("Can't string value {} to u64", val)))
			}
		} else {
			Err(singe_coerce_error(format!("Can't coerce object {} to u64", val)))
		}
	}
}

struct F64Coercer;

impl Coercer for F64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_f64() {
			return Ok(None)
		} else if val.is_i64() {
			let val = val.as_i64().unwrap();
			return Ok(Some((val as f64).to_json()));
		} else if val.is_u64() {
			let val = val.as_u64().unwrap();
			return Ok(Some((val as f64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<f64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(singe_coerce_error(format!("Can't coerce string value {} to f64", val)))
			}
		} else {
			Err(singe_coerce_error(format!("Can't coerce object {} to f64", val)))
		}
	}
}

struct BooleanCoercer;

impl Coercer for BooleanCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_boolean() {
			Ok(None)
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			if val == "true" {
				Ok(Some(true.to_json()))
			} else if val == "false" {
				Ok(Some(false.to_json()))
			} else {
				Err(singe_coerce_error(format!("Can't coerce string value {} to boolean. Correct values is 'true' and 'false'", val)))
			}
		} else {
			Err(singe_coerce_error(format!("Can't coerce object {} to boolean", val)))
		}
	}
}

struct NullCoercer;

impl Coercer for NullCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_null() {
			Ok(None)
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			if val == "" {
				Ok(Some(json::Null))
			} else {
				Err(singe_coerce_error(format!("Can't coerce string value {} to null. Correct value is only empty string", val)))
			}
		} else {
			Err(singe_coerce_error(format!("Can't coerce object {} to null", val)))
		}
	}
}

struct ListCoercer {
	sub_coercer: Option<Box<Coercer + Send + Sync>>
}

impl ListCoercer {
	pub fn new() -> ListCoercer {
		ListCoercer {
			sub_coercer: None
		}
	}

	pub fn with_type(sub_coercer: Box<Coercer + Send + Sync>) -> ListCoercer {
		ListCoercer {
			sub_coercer: Some(sub_coercer)
		}
	}
}

impl Coercer for ListCoercer {
	fn coerce(&self, val: &mut Json, extra: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_list() {
			let list = val.as_list_mut().unwrap();
			let mut errors = TreeMap::new();
			if extra.is_some() {
				for (idx, item) in list.iter_mut().enumerate() {
					if item.is_object() {
						// todo match
						extra.unwrap().process(item.as_object_mut().unwrap());
					} else {
						errors.insert(idx.to_string(), ValicoError {
							kind: CoerceError, message: format!("List item {} is not and object", item)
						});
					}
				}

				if errors.len() == 0 {
					Ok(None)
				} else {
					Err(errors)
				}
			} else if self.sub_coercer.is_some() {
				let sub_coercer = self.sub_coercer.as_ref().unwrap();
				let mut errors = TreeMap::new();
				for i in range(0, list.len() - 1) {
					match sub_coercer.coerce(list.get_mut(i), None) {
						Ok(Some(value)) => {
							list.remove(i);
							list.insert(i, value);
						},
						Ok(None) => (),
						Err(err) => {
							errors.insert(i.to_string(), ValicoError {
								kind: CoerceError, message: err.to_string()
							});
						}
					}
				}

				if errors.len() == 0 {
					Ok(None)
				} else {
					Err(errors)
				}
			} else {
				Ok(None)
			}
		} else {
			Err(singe_coerce_error(format!("Can't coerce object {} to null", val)))
		}
	}
}

struct ObjectCoercer;

impl Coercer for ObjectCoercer {
	fn coerce(&self, val: &mut Json, extra: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_object() {
			// todo match
			extra.unwrap().process(val.as_object_mut().unwrap());
			Ok(None)
		} else {
			Err(singe_coerce_error(format!("Can't coerce non-object value {} to object", val)))
		}
	}
}

struct Param {
	pub name: String,
	pub coercer: Box<Coercer>,
	pub extra: Option<Builder>
}

impl Param {
	pub fn new(name: &str, coercer: Box<Coercer>) -> Param {
		Param {
			name: name.to_string(),
			coercer: coercer,
			extra: None
		}
	}

	pub fn new_with_extra(name: &str, coercer: Box<Coercer>, extra: Builder) -> Param {
		Param {
			name: name.to_string(),
			coercer: coercer,
			extra: Some(extra)
		}
	}

	pub fn process(&self, val: &mut Json) -> ValicoResult<Option<Json>> {
		return (*self.coercer).coerce(val, self.extra.as_ref())
	}
}

struct Builder {
	requires: Vec<Param>,
	optional: Vec<Param>
}

fn has_value(obj: &JsonObject, key: &String) -> bool {
	match obj.find(key) {
		Some(_) => true,
		None => false
	}
}

impl Builder {

	pub fn new() -> Builder {
		Builder {
			requires: vec![],
			optional: vec![]
		}
	}

	fn from_function(rules: |params: &mut Builder|) -> Builder {
		let mut builder = Builder::new();
		rules(&mut builder);

		builder
	}

	fn req(&mut self, name: &str) {
		let params = Param::new(name, box StringCoercer);
		self.requires.push(params);
	}

	fn req_type(&mut self, name: &str, coercer: Box<Coercer>) {
		let params = Param::new(name, coercer);
		self.requires.push(params);
	}

	fn req_nest(&mut self, name: &str, coercer: Box<Coercer>, extra: |params: &mut Builder|) {
		let extra_builder = Builder::from_function(extra);
		let params = Param::new_with_extra(name, coercer, extra_builder);
		self.requires.push(params);
	}

	fn process(&self, tree: &mut JsonObject)  {

		for param in self.requires.iter() {
			let ref name = param.name;
			let present = has_value(tree, name);
			if present {
				match param.process(tree.find_mut(name).unwrap()) {
					Ok(result) => {
						match result {
							Some(new_value) => { tree.insert(name.clone(), new_value); },
							None => ()
						}
					},
					Err(_) => ()
				}
			} else {
				// required error!
			}

		}

	}

	// pub fn optional(name: &str, kind: Coeletrcer);
	// pub fn group(name: &str);
	// pub fn mutually_exclusive();
}

#[test]
fn it_works() {
	use serialize::json;

	let params = Builder::from_function(|params: &mut Builder| {
		params.req("name");
		params.req_type("test", box StringCoercer);
		params.req_nest("test", box StringCoercer, |params: &mut Builder| {
			params.req("type");
		});
	});

	let mut json = json::from_str(r#"{"name": 1}"#).unwrap();
	params.process(json.as_object_mut().unwrap());
}
<commit_msg>feat: add optional coercer to Param<commit_after>
extern crate serialize;

use serialize::json;
use serialize::json::{Json, JsonObject, ToJson, I64};
use std::collections::TreeMap;

use mutable_json::MutableJson;

mod mutable_json;

pub type ValicoResult<T> = Result<T, JsonObject>;

fn single_coerce_error(err: String) -> JsonObject {
	let mut tree = TreeMap::new();
	tree.insert("type".to_string(), "coerce".to_string().to_json());
	tree.insert("message".to_string(), err.to_json());

	tree
}

trait Coercer: Send + Sync {
	fn coerce(&self, &mut Json, Option<&Builder>) -> ValicoResult<Option<Json>>;
}

struct StringCoercer;

impl Coercer for StringCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_string() {
			Ok(None)
		} else if val.is_number() {
			Ok(Some(val.to_string().to_json()))
		} else {
			Err(
				single_coerce_error(format!("Can't coerce object {} to string", val))
			)
		}
	}
}

struct I64Coercer;

impl Coercer for I64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_i64() {
			return Ok(None)
		} else if val.is_u64() {
			let val = val.as_u64().unwrap();
			return Ok(Some((val as i64).to_json()));
		} else if val.is_f64() {
			let val = val.as_f64().unwrap();
			return Ok(Some((val as i64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<i64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(single_coerce_error(format!("Can't coerce string value {} to i64", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to i64", val)))
		}
	}
}

struct U64Coercer;

impl Coercer for U64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_u64() {
			return Ok(None)
		} else if val.is_i64() {
			let val = val.as_i64().unwrap();
			return Ok(Some((val as u64).to_json()));
		} else if val.is_f64() {
			let val = val.as_f64().unwrap();
			return Ok(Some((val as u64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<u64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(single_coerce_error(format!("Can't coerce string value {} to u64", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to u64", val)))
		}
	}
}

struct F64Coercer;

impl Coercer for F64Coercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_f64() {
			return Ok(None)
		} else if val.is_i64() {
			let val = val.as_i64().unwrap();
			return Ok(Some((val as f64).to_json()));
		} else if val.is_u64() {
			let val = val.as_u64().unwrap();
			return Ok(Some((val as f64).to_json()));
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			let converted: Option<f64> = from_str(val);
			match converted {
				Some(num) => Ok(Some(num.to_json())),
				None => Err(single_coerce_error(format!("Can't coerce string value {} to f64", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to f64", val)))
		}
	}
}

struct BooleanCoercer;

impl Coercer for BooleanCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_boolean() {
			Ok(None)
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			if val == "true" {
				Ok(Some(true.to_json()))
			} else if val == "false" {
				Ok(Some(false.to_json()))
			} else {
				Err(single_coerce_error(format!("Can't coerce string value {} to boolean. Correct values is 'true' and 'false'", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to boolean", val)))
		}
	}
}

struct NullCoercer;

impl Coercer for NullCoercer {
	fn coerce(&self, val: &mut Json, _: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_null() {
			Ok(None)
		} else if val.is_string() {
			let val = val.as_string().unwrap();
			if val == "" {
				Ok(Some(json::Null))
			} else {
				Err(single_coerce_error(format!("Can't coerce string value {} to null. Correct value is only empty string", val)))
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to null", val)))
		}
	}
}

struct ListCoercer {
	sub_coercer: Option<Box<Coercer + Send + Sync>>
}

impl ListCoercer {
	pub fn new() -> ListCoercer {
		ListCoercer {
			sub_coercer: None
		}
	}

	pub fn with_type(sub_coercer: Box<Coercer + Send + Sync>) -> ListCoercer {
		ListCoercer {
			sub_coercer: Some(sub_coercer)
		}
	}
}

impl Coercer for ListCoercer {
	fn coerce(&self, val: &mut Json, extra: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_list() {
			let list = val.as_list_mut().unwrap();
			let mut errors = TreeMap::new();
			if extra.is_some() {
				for (idx, item) in list.iter_mut().enumerate() {
					if item.is_object() {
						// todo match
						match extra.unwrap().process(item.as_object_mut().unwrap()) {
							Ok(()) => (),
							Err(err) => { errors.insert(idx.to_string(), err.to_json()); }
						}
					} else {
						errors.insert(idx.to_string(), format!("List item {} is not and object", item).to_json());
					}
				}

				if errors.len() == 0 {
					Ok(None)
				} else {
					Err(errors)
				}
			} else if self.sub_coercer.is_some() {
				let sub_coercer = self.sub_coercer.as_ref().unwrap();
				let mut errors = TreeMap::new();
				for i in range(0, list.len() - 1) {
					match sub_coercer.coerce(list.get_mut(i), None) {
						Ok(Some(value)) => {
							list.remove(i);
							list.insert(i, value);
						},
						Ok(None) => (),
						Err(err) => {
							errors.insert(i.to_string(), err.to_json());
						}
					}
				}

				if errors.len() == 0 {
					Ok(None)
				} else {
					Err(errors)
				}
			} else {
				Ok(None)
			}
		} else {
			Err(single_coerce_error(format!("Can't coerce object {} to null", val)))
		}
	}
}

struct ObjectCoercer;

impl Coercer for ObjectCoercer {
	fn coerce(&self, val: &mut Json, extra: Option<&Builder>) -> ValicoResult<Option<Json>> {
		if val.is_object() {
			// todo match
			extra.unwrap().process(val.as_object_mut().unwrap());
			Ok(None)
		} else {
			Err(single_coerce_error(format!("Can't coerce non-object value {} to object", val)))
		}
	}
}

struct Param {
	pub name: String,
	pub coercer: Option<Box<Coercer>>,
	pub extra: Option<Builder>
}

impl Param {
	pub fn new(name: &str) -> Param {
		Param {
			name: name.to_string(),
			coercer: None,
			extra: None
		}
	}

	pub fn new_with_coercer(name: &str, coercer: Box<Coercer>) -> Param {
		Param {
			name: name.to_string(),
			coercer: Some(coercer),
			extra: None
		}
	}

	pub fn new_with_extra(name: &str, coercer: Box<Coercer>, extra: Builder) -> Param {
		Param {
			name: name.to_string(),
			coercer: Some(coercer),
			extra: Some(extra)
		}
	}

	pub fn process(&self, val: &mut Json) -> ValicoResult<Option<Json>> {
		match self.coercer.as_ref() {
			Some(coercer) => coercer.coerce(val, self.extra.as_ref()),
			None => Ok(None)
		}
	}
}

struct Builder {
	requires: Vec<Param>,
	optional: Vec<Param>
}

fn has_value(obj: &JsonObject, key: &String) -> bool {
	match obj.find(key) {
		Some(_) => true,
		None => false
	}
}

impl Builder {

	pub fn new() -> Builder {
		Builder {
			requires: vec![],
			optional: vec![]
		}
	}

	fn from_function(rules: |params: &mut Builder|) -> Builder {
		let mut builder = Builder::new();
		rules(&mut builder);

		builder
	}

	fn req(&mut self, name: &str) {
		let params = Param::new(name);
		self.requires.push(params);
	}

	fn req_type(&mut self, name: &str, coercer: Box<Coercer>) {
		let params = Param::new_with_coercer(name, coercer);
		self.requires.push(params);
	}

	fn req_nest(&mut self, name: &str, coercer: Box<Coercer>, extra: |params: &mut Builder|) {
		let extra_builder = Builder::from_function(extra);
		let params = Param::new_with_extra(name, coercer, extra_builder);
		self.requires.push(params);
	}

	fn process(&self, tree: &mut JsonObject) -> ValicoResult<()>  {

		let mut errors = TreeMap::new();

		for param in self.requires.iter() {
			let ref name = param.name;
			let present = has_value(tree, name);
			if present {
				match param.process(tree.find_mut(name).unwrap()) {
					Ok(result) => {
						match result {
							Some(new_value) => { tree.insert(name.clone(), new_value); },
							None => ()
						}
					},
					Err(err) => {
						errors.insert(name.to_string(), err.to_json());
					}
				}
			} else {
				errors.insert(name.to_string(), "Field is required but missing".to_string().to_json());
			}
		}

		if errors.len() == 0 {
			Ok(())
		} else {
			Err(errors)
		}
	}

	// pub fn optional(name: &str, kind: Coeletrcer);
	// pub fn group(name: &str);
	// pub fn mutually_exclusive();
}

fn test_result(params: &Builder, body: &str, result: &str) {
	let mut obj = json::from_str(body);
	match obj {
		Ok(mut json) => {
			match params.process(json.as_object_mut().unwrap()) {
				Ok(()) => {
					return assert_eq!(json.to_string(), result.to_string());
				},
				Err(err) => {
					fail!("Error during process: {}", err.to_json().to_pretty_str());
				}
			}
		},
		Err(_) => {
			fail!("Invalid JSON");
		}
	}
}

fn test_get_error(params: &Builder, body: &str) -> JsonObject {
	let mut obj = json::from_str(body);
	match obj {
		Ok(mut json) => {
			match params.process(json.as_object_mut().unwrap()) {
				Ok(()) => {
					fail!("Success responce when we await some errors");
				},
				Err(err) => {
					return err;
				}
			}
		},
		Err(_) => {
			fail!("Invalid JSON");
		}
	}
}

#[test]
fn is_process_simple_require() {

	let params = Builder::from_function(|params: &mut Builder| {
		params.req("name");
	});

	test_result(&params, r#"{"name":1}"#, r#"{"name":1}"#);
	println!("{}", test_get_error(&params, r#"{}"#));
	fail!("");
}
<|endoftext|>


<commit_before>/// Functions for use in euler projects

#[warn(non_camel_case_types)]
#[warn(non_snake_case)]
#[warn(unnecessary_qualification)]
#[warn(non_uppercase_statics)]
#[warn(missing_doc)]

use std::collections::TrieSet;

use std::collections::HashMap;
use std::collections::hashmap::{Occupied, Vacant};

pub use primesieve::PrimeSet;

pub mod primesieve;

/// Count the number of occurrences of each value in an iterator
pub fn counter<K : std::hash::Hash + Eq, I : Iterator<K>>(mut list : I) -> HashMap<K, uint> {
	let mut counter : HashMap<K, uint> = HashMap::new();
	for key in list {
		match counter.entry(key) {
			Vacant(entry) => {entry.set(1);},
			Occupied(entry) => {(*entry.into_mut()) += 1;}
		}
	}
	counter
}

pub fn isqrt_opt(n : uint) -> Option<uint> {
	if n <= 1 {return Some(n);}
	let mut x = n / 2;
	let mut usedset = TrieSet::new();

	//println!("New x: {}", x);

	while x*x != n {
		usedset.insert(x);
		// let addx = x + n / x;
		x = (x + n / x + 1) / 2;
		//println!("New x: {} ({})", x, addx);
		if usedset.contains(&x) {
			//println!("Seen! {} ({}, {})", x, x*x, n);
			return None;
		}
	}
	Some(x)
}

pub fn isqrt(n : uint) -> uint {
	if n <= 1 { return n; }
	let mut x = n / 2;
	let mut usedset = TrieSet::new();

	while x*x != n {
		usedset.insert(x);
		let lastx = x;
		x = (x + n / x + 1) / 2;
		//if usedset.contains(&x) {
		if x == lastx {
			if x*x < n {
				return x;
			} else {
				return x-1;
			}
		}
	}
	return x
}

pub fn is_palindrome(n : uint) -> bool {
	let s = n.to_string();
	//let s_rev = String::from_utf8(s.into_bytes().iter().rev().collect());
	let s_rev = s.as_slice().as_bytes().iter().rev();
	let s_rev_vec : Vec<u8> = s_rev.map(|&b| b).collect();
	let s_rev = String::from_utf8(s_rev_vec);
	match s_rev {
		Ok(s2) => {s == s2},
		_ => false
	}
}

#[test]
fn test_square(){
	assert_eq!(isqrt_opt(4), Some(2));
	assert_eq!(isqrt_opt(5), None);

	let mut ntests = vec![1,7,8,9,10,11,12,189654,4294967295];

	for _ in range(0u, 1000u){
		let mut n = std::rand::random::<uint>();
		n = n % std::num::pow(2u, std::uint::BITS / 2);
		ntests.push(n);
	}

	for &n in ntests.iter(){
		println!("n: {}, n*n: {}", n, n*n);
		assert!(n < std::num::pow(2u, std::uint::BITS / 2));
		assert_eq!(isqrt_opt(n*n), Some(n));
		if n > 1 {
			assert_eq!(isqrt_opt(n*n - 1), None);
		} else {
			assert_eq!(isqrt_opt(n*n - 1), Some(0));
		}
		assert_eq!(isqrt_opt(n*n + 1), None);
	}
}

#[test]
fn test_isqrt(){
	assert_eq!(isqrt(0), 0);
	let mut ntests = vec![1,7,8,9,10,11,12,189654,4294967295];

	for i in range(1u, 1001u){
		let mut n = std::rand::random::<uint>();
		n = n % std::num::pow(2u, std::uint::BITS / 2);
		ntests.push(n);
		ntests.push(i);
	}

	for &n in ntests.iter() {
		assert!(n < std::num::pow(2u, std::uint::BITS / 2));
		let x = isqrt(n);
		assert!(x*x <= n);
		assert!((x+1)*(x+1) > n);
		assert_eq!(isqrt(n*n - 1), n-1);
		assert_eq!(isqrt(n*n + 1), n);
	}
}

#[test]
fn test_palindrome(){
	assert!(is_palindrome(1));
	assert!(is_palindrome(2));
	assert!(is_palindrome(8));
	assert!(!is_palindrome(10));
	assert!(!is_palindrome(12));
	assert!(!is_palindrome(100));
	assert!(!is_palindrome(11110));
	assert!(!is_palindrome(21111));
	assert!(!is_palindrome(12131));
	assert!(is_palindrome(11));
	assert!(is_palindrome(111));
	assert!(is_palindrome(232));
	assert!(is_palindrome(181));
}
<commit_msg>Add Pairs<commit_after>/// Functions for use in euler projects

#[warn(non_camel_case_types)]
#[warn(non_snake_case)]
#[warn(unnecessary_qualification)]
#[warn(non_uppercase_statics)]
#[warn(missing_doc)]

use std::collections::TrieSet;

use std::collections::HashMap;
use std::collections::hashmap::{Occupied, Vacant};

pub use primesieve::PrimeSet;

pub mod primesieve;

/// Count the number of occurrences of each value in an iterator
pub fn counter<K : std::hash::Hash + Eq, I : Iterator<K>>(mut list : I) -> HashMap<K, uint> {
	let mut counter : HashMap<K, uint> = HashMap::new();
	for key in list {
		match counter.entry(key) {
			Vacant(entry) => {entry.set(1);},
			Occupied(entry) => {(*entry.into_mut()) += 1;}
		}
	}
	counter
}

pub fn isqrt_opt(n : uint) -> Option<uint> {
	if n <= 1 {return Some(n);}
	let mut x = n / 2;
	let mut usedset = TrieSet::new();

	//println!("New x: {}", x);

	while x*x != n {
		usedset.insert(x);
		// let addx = x + n / x;
		x = (x + n / x + 1) / 2;
		//println!("New x: {} ({})", x, addx);
		if usedset.contains(&x) {
			//println!("Seen! {} ({}, {})", x, x*x, n);
			return None;
		}
	}
	Some(x)
}

pub fn isqrt(n : uint) -> uint {
	if n <= 1 { return n; }
	let mut x = n / 2;
	let mut usedset = TrieSet::new();

	while x*x != n {
		usedset.insert(x);
		let lastx = x;
		x = (x + n / x + 1) / 2;
		//if usedset.contains(&x) {
		if x == lastx {
			if x*x < n {
				return x;
			} else {
				return x-1;
			}
		}
	}
	return x
}

pub fn is_palindrome(n : uint) -> bool {
	let s = n.to_string();
	//let s_rev = String::from_utf8(s.into_bytes().iter().rev().collect());
	let s_rev = s.as_slice().as_bytes().iter().rev();
	let s_rev_vec : Vec<u8> = s_rev.map(|&b| b).collect();
	let s_rev = String::from_utf8(s_rev_vec);
	match s_rev {
		Ok(s2) => {s == s2},
		_ => false
	}
}

#[deriving(Clone)]
pub struct Pairs<'a, T :'a>{
	vector : &'a [T],
	first : uint,
	second : uint
}

impl<'a, T> Iterator<(&'a T, &'a T)> for Pairs<'a, T> {
	fn next(&mut self) -> Option<(&'a T, &'a T)> {
		let l = self.vector.len();
		if self.second >= l-1 && self.first >= l-2 {return None;}
		self.second += 1;

		if self.second >= l {
			self.first += 1;
			self.second = self.first + 1;
		}

		return unsafe { Some((self.vector.unsafe_get(self.first), self.vector.unsafe_get(self.second)))}
	}
}

pub fn pairs<'a, T>(vec : &'a [T]) -> Pairs<'a, T>{
	Pairs {
		vector : vec,
		first : 0,
		second : 0
	}
}

#[test]
fn test_square(){
	assert_eq!(isqrt_opt(4), Some(2));
	assert_eq!(isqrt_opt(5), None);

	let mut ntests = vec![1,7,8,9,10,11,12,189654,4294967295];

	for _ in range(0u, 1000u){
		let mut n = std::rand::random::<uint>();
		n = n % std::num::pow(2u, std::uint::BITS / 2);
		ntests.push(n);
	}

	for &n in ntests.iter(){
		println!("n: {}, n*n: {}", n, n*n);
		assert!(n < std::num::pow(2u, std::uint::BITS / 2));
		assert_eq!(isqrt_opt(n*n), Some(n));
		if n > 1 {
			assert_eq!(isqrt_opt(n*n - 1), None);
		} else {
			assert_eq!(isqrt_opt(n*n - 1), Some(0));
		}
		assert_eq!(isqrt_opt(n*n + 1), None);
	}
}

#[test]
fn test_isqrt(){
	assert_eq!(isqrt(0), 0);
	let mut ntests = vec![1,7,8,9,10,11,12,189654,4294967295];

	for i in range(1u, 1001u){
		let mut n = std::rand::random::<uint>();
		n = n % std::num::pow(2u, std::uint::BITS / 2);
		ntests.push(n);
		ntests.push(i);
	}

	for &n in ntests.iter() {
		assert!(n < std::num::pow(2u, std::uint::BITS / 2));
		let x = isqrt(n);
		assert!(x*x <= n);
		assert!((x+1)*(x+1) > n);
		assert_eq!(isqrt(n*n - 1), n-1);
		assert_eq!(isqrt(n*n + 1), n);
	}
}

#[test]
fn test_palindrome(){
	assert!(is_palindrome(1));
	assert!(is_palindrome(2));
	assert!(is_palindrome(8));
	assert!(!is_palindrome(10));
	assert!(!is_palindrome(12));
	assert!(!is_palindrome(100));
	assert!(!is_palindrome(11110));
	assert!(!is_palindrome(21111));
	assert!(!is_palindrome(12131));
	assert!(is_palindrome(11));
	assert!(is_palindrome(111));
	assert!(is_palindrome(232));
	assert!(is_palindrome(181));
}

#[test]
fn test_pairs(){
	let v = [1,2,5,4u];
	let mut my_pairs = pairs(v);

	assert_eq!(my_pairs.next(), Some((&v[0], &v[1])));
	assert_eq!(my_pairs.next(), Some((&v[0], &v[2])));
	assert_eq!(my_pairs.next(), Some((&v[0], &v[3])));
	assert_eq!(my_pairs.next(), Some((&v[1], &v[2])));
	assert_eq!(my_pairs.next(), Some((&v[1], &v[3])));
	assert_eq!(my_pairs.next(), Some((&v[2], &v[3])));
	//~ assert_eq!(my_pairs.next(), Some((&1, &5)));
	//~ assert_eq!(my_pairs.next(), Some((&1, &4)));
	//~ assert_eq!(my_pairs.next(), Some((&2, &5)));
	//~ assert_eq!(my_pairs.next(), Some((&2, &4)));
	//~ assert_eq!(my_pairs.next(), Some((&5, &4)));
	assert_eq!(my_pairs.next(), None);
	assert_eq!(my_pairs.next(), None);
}
<|endoftext|>


<commit_before>#![feature(custom_derive)]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
<commit_msg>import files<commit_after>#![feature(custom_derive)]
#[macro_use]
extern crate serde_derive;
extern crate serde_json;

mod list;
mod storage;
mod todo;
<|endoftext|>


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

//! Abstraction of a thread pool for basic parallelism.

#![feature(unsafe_destructor)]

use std::mem;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::{self, JoinGuard};

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

#[unsafe_destructor]
impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            spawn_in_pool(self.jobs.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```rust
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone());
        }

        ThreadPool { jobs: tx }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs);

        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The Taskpool was dropped.
                Err(..) => break
            }
        }

        sentinel.cancel();
    });
}

/// A scoped thread pool used to execute functions in parallel.
///
/// `ScopedPool` is different from `TaskPool` in that:
///
/// * When dropped, it propagates panics that occur in the worker threads.
/// * It doesn't require the `'static` bound on the functions that are executed.
/// * Worker threads are joined when the `ScopedPool` is dropped.
///
/// # Example
///
/// ```rust
/// use threadpool::ScopedPool;
///
/// let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
///
/// // We need an extra scope to shorten the lifetime of the pool
/// {
///     let pool = ScopedPool::new(4);
///     for x in &mut numbers[..] {
///         pool.execute(move|| {
///             *x += 1;
///         });
///     }
/// }
///
/// assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
/// ```
pub struct ScopedPool<'pool> {
    sender: Option<Sender<Thunk<'pool>>>,
    _guards: Vec<JoinGuard<'pool, ()>>
}

impl<'pool> ScopedPool<'pool> {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: u32) -> ScopedPool<'pool> {
        assert!(threads >= 1);

        let (sender, receiver) = channel();
        let receiver = Arc::new(Mutex::new(receiver));

        let mut guards = Vec::with_capacity(threads as usize);
        for _ in 0..threads {
            guards.push(spawn_scoped_in_pool(receiver.clone()));
        }

        ScopedPool { sender: Some(sender), _guards: guards }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F: FnOnce() + Send + 'pool
    {
        self.sender.as_ref().unwrap().send(Box::new(job)).unwrap();
    }
}

#[unsafe_destructor]
impl<'a> Drop for ScopedPool<'a> {
    fn drop(&mut self) {
        // We need to ensure that the sender is dropped before the JoinGuards
        // Otherwise the threads will be joined and wait forever in the loop
        mem::replace(&mut self.sender, None);
    }
}

fn spawn_scoped_in_pool<'a>(jobs: Arc<Mutex<Receiver<Thunk<'a>>>>) -> JoinGuard<'a, ()>
{
    thread::scoped(move || {
        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The pool was dropped.
                Err(..) => break
            }
        }
    })
}

#[cfg(test)]
mod test {
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_fail]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}

#[cfg(test)]
mod test_scoped {
    use super::ScopedPool;
    use std::sync::mpsc::channel;

    const TEST_TASKS: u32 = 4;

    #[test]
    fn test_works_1() {
        let pool = ScopedPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS as usize).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_works_2() {
        let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        {
            let pool = ScopedPool::new(TEST_TASKS);
            for x in numbers.iter_mut() {
                pool.execute(move || {
                    *x += 1;
                });
            }
        }
        assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
    }

    #[test]
    #[should_fail]
    fn test_zero_tasks_panic() {
        ScopedPool::new(0);
    }

    #[test]
    #[should_fail]
    fn test_panic_propagation() {
        let pool = ScopedPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }
    }
}
<commit_msg>Rename TaskPool -> ThreadPool in doc/comment<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Abstraction of a thread pool for basic parallelism.

#![feature(unsafe_destructor)]

use std::mem;
use std::sync::{Arc, Mutex};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::{self, JoinGuard};

trait FnBox {
    fn call_box(self: Box<Self>);
}

impl<F: FnOnce()> FnBox for F {
    fn call_box(self: Box<F>) {
        (*self)()
    }
}

type Thunk<'a> = Box<FnBox + Send + 'a>;

struct Sentinel<'a> {
    jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>,
    active: bool
}

impl<'a> Sentinel<'a> {
    fn new(jobs: &'a Arc<Mutex<Receiver<Thunk<'static>>>>) -> Sentinel<'a> {
        Sentinel {
            jobs: jobs,
            active: true
        }
    }

    // Cancel and destroy this sentinel.
    fn cancel(mut self) {
        self.active = false;
    }
}

#[unsafe_destructor]
impl<'a> Drop for Sentinel<'a> {
    fn drop(&mut self) {
        if self.active {
            spawn_in_pool(self.jobs.clone())
        }
    }
}

/// A thread pool used to execute functions in parallel.
///
/// Spawns `n` worker threads and replenishes the pool if any worker threads
/// panic.
///
/// # Example
///
/// ```rust
/// use threadpool::ThreadPool;
/// use std::sync::mpsc::channel;
///
/// let pool = ThreadPool::new(4);
///
/// let (tx, rx) = channel();
/// for i in 0..8 {
///     let tx = tx.clone();
///     pool.execute(move|| {
///         tx.send(i).unwrap();
///     });
/// }
///
/// assert_eq!(rx.iter().take(8).fold(0, |a, b| a + b), 28);
/// ```
pub struct ThreadPool {
    // How the threadpool communicates with subthreads.
    //
    // This is the only such Sender, so when it is dropped all subthreads will
    // quit.
    jobs: Sender<Thunk<'static>>
}

impl ThreadPool {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: usize) -> ThreadPool {
        assert!(threads >= 1);

        let (tx, rx) = channel::<Thunk<'static>>();
        let rx = Arc::new(Mutex::new(rx));

        // Threadpool threads
        for _ in 0..threads {
            spawn_in_pool(rx.clone());
        }

        ThreadPool { jobs: tx }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F : FnOnce() + Send + 'static
    {
        self.jobs.send(Box::new(move || job())).unwrap();
    }
}

fn spawn_in_pool(jobs: Arc<Mutex<Receiver<Thunk<'static>>>>) {
    thread::spawn(move || {
        // Will spawn a new thread on panic unless it is cancelled.
        let sentinel = Sentinel::new(&jobs);

        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The Threadpool was dropped.
                Err(..) => break
            }
        }

        sentinel.cancel();
    });
}

/// A scoped thread pool used to execute functions in parallel.
///
/// `ScopedPool` is different from `ThreadPool` in that:
///
/// * When dropped, it propagates panics that occur in the worker threads.
/// * It doesn't require the `'static` bound on the functions that are executed.
/// * Worker threads are joined when the `ScopedPool` is dropped.
///
/// # Example
///
/// ```rust
/// use threadpool::ScopedPool;
///
/// let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
///
/// // We need an extra scope to shorten the lifetime of the pool
/// {
///     let pool = ScopedPool::new(4);
///     for x in &mut numbers[..] {
///         pool.execute(move|| {
///             *x += 1;
///         });
///     }
/// }
///
/// assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
/// ```
pub struct ScopedPool<'pool> {
    sender: Option<Sender<Thunk<'pool>>>,
    _guards: Vec<JoinGuard<'pool, ()>>
}

impl<'pool> ScopedPool<'pool> {
    /// Spawns a new thread pool with `threads` threads.
    ///
    /// # Panics
    ///
    /// This function will panic if `threads` is 0.
    pub fn new(threads: u32) -> ScopedPool<'pool> {
        assert!(threads >= 1);

        let (sender, receiver) = channel();
        let receiver = Arc::new(Mutex::new(receiver));

        let mut guards = Vec::with_capacity(threads as usize);
        for _ in 0..threads {
            guards.push(spawn_scoped_in_pool(receiver.clone()));
        }

        ScopedPool { sender: Some(sender), _guards: guards }
    }

    /// Executes the function `job` on a thread in the pool.
    pub fn execute<F>(&self, job: F)
        where F: FnOnce() + Send + 'pool
    {
        self.sender.as_ref().unwrap().send(Box::new(job)).unwrap();
    }
}

#[unsafe_destructor]
impl<'a> Drop for ScopedPool<'a> {
    fn drop(&mut self) {
        // We need to ensure that the sender is dropped before the JoinGuards
        // Otherwise the threads will be joined and wait forever in the loop
        mem::replace(&mut self.sender, None);
    }
}

fn spawn_scoped_in_pool<'a>(jobs: Arc<Mutex<Receiver<Thunk<'a>>>>) -> JoinGuard<'a, ()>
{
    thread::scoped(move || {
        loop {
            let message = {
                // Only lock jobs for the time it takes
                // to get a job, not run it.
                let lock = jobs.lock().unwrap();
                lock.recv()
            };

            match message {
                Ok(job) => job.call_box(),

                // The pool was dropped.
                Err(..) => break
            }
        }
    })
}

#[cfg(test)]
mod test {
    use super::ThreadPool;
    use std::sync::mpsc::channel;
    use std::sync::{Arc, Barrier};

    const TEST_TASKS: usize = 4;

    #[test]
    fn test_works() {
        let pool = ThreadPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    #[should_fail]
    fn test_zero_tasks_panic() {
        ThreadPool::new(0);
    }

    #[test]
    fn test_recovery_from_subtask_panic() {
        let pool = ThreadPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }

        // Ensure new threads were spawned to compensate.
        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_should_not_panic_on_drop_if_subtasks_panic_after_drop() {

        let pool = ThreadPool::new(TEST_TASKS);
        let waiter = Arc::new(Barrier::new(TEST_TASKS + 1));

        // Panic all the existing threads in a bit.
        for _ in 0..TEST_TASKS {
            let waiter = waiter.clone();
            pool.execute(move|| {
                waiter.wait();
                panic!();
            });
        }

        drop(pool);

        // Kick off the failure.
        waiter.wait();
    }
}

#[cfg(test)]
mod test_scoped {
    use super::ScopedPool;
    use std::sync::mpsc::channel;

    const TEST_TASKS: u32 = 4;

    #[test]
    fn test_works_1() {
        let pool = ScopedPool::new(TEST_TASKS);

        let (tx, rx) = channel();
        for _ in 0..TEST_TASKS {
            let tx = tx.clone();
            pool.execute(move|| {
                tx.send(1).unwrap();
            });
        }

        assert_eq!(rx.iter().take(TEST_TASKS as usize).fold(0, |a, b| a + b), TEST_TASKS);
    }

    #[test]
    fn test_works_2() {
        let mut numbers: &mut [u32] = &mut [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        {
            let pool = ScopedPool::new(TEST_TASKS);
            for x in numbers.iter_mut() {
                pool.execute(move || {
                    *x += 1;
                });
            }
        }
        assert_eq!(numbers, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]);
    }

    #[test]
    #[should_fail]
    fn test_zero_tasks_panic() {
        ScopedPool::new(0);
    }

    #[test]
    #[should_fail]
    fn test_panic_propagation() {
        let pool = ScopedPool::new(TEST_TASKS);

        // Panic all the existing threads.
        for _ in 0..TEST_TASKS {
            pool.execute(move|| -> () { panic!() });
        }
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;
extern crate chrono;
extern crate itertools;
extern crate rustc_serialize;
extern crate xml as xml_rs;

pub mod binary;
pub mod xml;
mod builder;

pub use builder::{Builder, BuilderError, BuilderResult};

use chrono::{DateTime, UTC};
use chrono::format::ParseError as ChronoParseError;
use std::collections::HashMap;
use std::io::{Read, Seek, SeekFrom};
use std::io::Error as IoError;

#[derive(Clone, Debug, PartialEq)]
pub enum Plist {
	Array(Vec<Plist>),
	Dictionary(HashMap<String, Plist>),
	Boolean(bool),
	Data(Vec<u8>),
	Date(DateTime<UTC>),
	Real(f64),
	Integer(i64),
	String(String)
}

#[derive(Debug, PartialEq)]
pub enum PlistEvent {
	StartPlist,
	EndPlist,

	StartArray(Option<u64>),
	EndArray,

	StartDictionary(Option<u64>),
	EndDictionary,

	BooleanValue(bool),
	DataValue(Vec<u8>),
	DateValue(DateTime<UTC>),
	IntegerValue(i64),
	RealValue(f64),
	StringValue(String),
}

pub type ParserResult<T> = Result<T, ParserError>;

#[derive(Debug)]
pub enum ParserError {
	InvalidData,
	UnexpectedEof,
	UnsupportedType,
	Io(IoError)
}

impl From<IoError> for ParserError {
	fn from(io_error: IoError) -> ParserError {
		ParserError::Io(io_error)
	}
}

impl From<ChronoParseError> for ParserError {
	fn from(_: ChronoParseError) -> ParserError {
		ParserError::InvalidData
	}
}

pub enum StreamingParser<R: Read+Seek> {
	Xml(xml::StreamingParser<R>),
	Binary(binary::StreamingParser<R>)
}

impl<R: Read+Seek> StreamingParser<R> {
	pub fn new(mut reader: R) -> StreamingParser<R> {
		match StreamingParser::is_binary(&mut reader) {
			Ok(true) => StreamingParser::Binary(binary::StreamingParser::new(reader)),
			Ok(false) | Err(_) => StreamingParser::Xml(xml::StreamingParser::new(reader))
		}
	}

	fn is_binary(reader: &mut R) -> Result<bool, IoError> {
		try!(reader.seek(SeekFrom::Start(0)));
		let mut magic = [0; 8];
		try!(reader.read(&mut magic));

		Ok(if &magic == b"bplist00" {
			true
		} else {
			false
		})
	}
}

impl<R: Read+Seek> Iterator for StreamingParser<R> {
	type Item = ParserResult<PlistEvent>;

	fn next(&mut self) -> Option<ParserResult<PlistEvent>> {
		match *self {
			StreamingParser::Xml(ref mut parser) => parser.next(),
			StreamingParser::Binary(ref mut parser) => parser.next()
		}
	}
}<commit_msg>Make PlistEvent cloneable again<commit_after>extern crate byteorder;
extern crate chrono;
extern crate itertools;
extern crate rustc_serialize;
extern crate xml as xml_rs;

pub mod binary;
pub mod xml;
mod builder;

pub use builder::{Builder, BuilderError, BuilderResult};

use chrono::{DateTime, UTC};
use chrono::format::ParseError as ChronoParseError;
use std::collections::HashMap;
use std::io::{Read, Seek, SeekFrom};
use std::io::Error as IoError;

#[derive(Clone, Debug, PartialEq)]
pub enum Plist {
	Array(Vec<Plist>),
	Dictionary(HashMap<String, Plist>),
	Boolean(bool),
	Data(Vec<u8>),
	Date(DateTime<UTC>),
	Real(f64),
	Integer(i64),
	String(String)
}

#[derive(Clone, Debug, PartialEq)]
pub enum PlistEvent {
	StartPlist,
	EndPlist,

	StartArray(Option<u64>),
	EndArray,

	StartDictionary(Option<u64>),
	EndDictionary,

	BooleanValue(bool),
	DataValue(Vec<u8>),
	DateValue(DateTime<UTC>),
	IntegerValue(i64),
	RealValue(f64),
	StringValue(String),
}

pub type ParserResult<T> = Result<T, ParserError>;

#[derive(Debug)]
pub enum ParserError {
	InvalidData,
	UnexpectedEof,
	UnsupportedType,
	Io(IoError)
}

impl From<IoError> for ParserError {
	fn from(io_error: IoError) -> ParserError {
		ParserError::Io(io_error)
	}
}

impl From<ChronoParseError> for ParserError {
	fn from(_: ChronoParseError) -> ParserError {
		ParserError::InvalidData
	}
}

pub enum StreamingParser<R: Read+Seek> {
	Xml(xml::StreamingParser<R>),
	Binary(binary::StreamingParser<R>)
}

impl<R: Read+Seek> StreamingParser<R> {
	pub fn new(mut reader: R) -> StreamingParser<R> {
		match StreamingParser::is_binary(&mut reader) {
			Ok(true) => StreamingParser::Binary(binary::StreamingParser::new(reader)),
			Ok(false) | Err(_) => StreamingParser::Xml(xml::StreamingParser::new(reader))
		}
	}

	fn is_binary(reader: &mut R) -> Result<bool, IoError> {
		try!(reader.seek(SeekFrom::Start(0)));
		let mut magic = [0; 8];
		try!(reader.read(&mut magic));

		Ok(if &magic == b"bplist00" {
			true
		} else {
			false
		})
	}
}

impl<R: Read+Seek> Iterator for StreamingParser<R> {
	type Item = ParserResult<PlistEvent>;

	fn next(&mut self) -> Option<ParserResult<PlistEvent>> {
		match *self {
			StreamingParser::Xml(ref mut parser) => parser.next(),
			StreamingParser::Binary(ref mut parser) => parser.next()
		}
	}
}<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/libffi/0.8.0")]
//! Rust bindings for [libffi](https://sourceware.org/libffi/).
//!
//! The C libffi library provides two main facilities: assembling calls
//! to functions dynamically, and creating closures that can be called
//! as ordinary C functions. In Rust, the latter means that we can turn
//! a Rust lambda (or any object implementing `Fn`/`FnMut`) into an
//! ordinary C function pointer that we can pass as a callback to C.
//!
//! The easiest way to use this library is via the
//! [`high`](high/index.html) layer module, but more flexibility (and
//! less checking) is provided by the [`middle`](middle/index.html) and
//! [`low`](low/index.html) layers.
//!
//! # Usage
//!
//! Building libffi will build lifbffi-sys, which will in turn build the
//! libffi C library [from github](https://github.com/libffi/libffi), which
//! requires that you have a working make, C compiler, automake, and
//! autoconf first. It’s [on crates.io](https://crates.io/crates/libffi), so
//! you can add
//!
//! ```toml
//! [dependencies]
//! libffi = "0.8.0"
//! ```
//!
//! This crate depends on [the `libffi-sys` crate], which by default
//! attempts to build its own version of the C libffi library. In order to
//! use your system’s C libffi instead, enable this crate’s  `system`
//! feature in your `Cargo.toml`:
//!
//! ```toml
//! [features]
//! libffi = { version = "0.8.0", features = ["system"] }
//! ```
//!
//! See [the `libffi-sys` documentation] for more information about how it
//! finds C libffi.
//!
//! This crate supports Rust version 1.36 and later.
//!
//! # Organization
//!
//! This library is organized in four layers, each of which attempts to
//! provide more safety and a simpler interface than the next layer
//! down. From top to bottom:
//!
//!   - The [`high`](high/index.html) layer provides safe(?) and
//!     automatic marshalling of Rust closures into C function pointers.
//!   - The [`middle`](middle/index.html) layer provides memory-managed
//!     abstractions for assembling calls and closures, but is unsafe
//!     because it doesn’t check argument types.
//!   - The [`low`](low/index.html) layer makes no attempts at safety,
//!     but provides a more idiomatically “Rusty” API than the underlying
//!     C library.
//!   - The [`raw`](raw/index.html) layer is a re-export of the
//!     [`libffi-sys`](https://crates.io/crates/libffi-sys) crate,
//!     a direct mapping of the C libffi library into Rust, generated by
//!     [bindgen](https://crates.io/crates/bindgen).
//!
//! It should be possible to use any layer without dipping into lower
//! layers (and it will be considered a bug to the extent that it
//! isn’t).
//!
//! # Examples
//!
//! In this example, we convert a Rust lambda containing a free variable
//! into an ordinary C code pointer. The type of `fun` below is
//! `extern "C" fn(u64, u64) -> u64`.
//!
//! ```
//! use libffi::high::Closure2;
//!
//! let x = 5u64;
//! let f = |y: u64, z: u64| x + y + z;
//!
//! let closure = Closure2::new(&f);
//! let fun     = closure.code_ptr();
//!
//! assert_eq!(18, fun(6, 7));
//! ```
//!
//! [the `libffi-sys` crate]: https://crates.io/crates/libffi-sys/
//!
//! [the `libffi-sys` documentation]: https://docs.rs/libffi-sys/#usage
//!

#![deny(missing_docs)]
#![deny(warnings)]

/// Raw definitions imported from the C library (via bindgen).
///
/// This module is generated by bindgen and undocumented. It’s intended
/// as the basis for higher-level bindings, but you can see the [C libffi
/// documentation](http://www.atmark-techno.com/~yashi/libffi.html).
pub mod raw {
    pub use libffi_sys::*;
}

pub mod high;
pub mod middle;
pub mod low;
<commit_msg>Removed deny(warnings); too fragile.<commit_after>#![doc(html_root_url = "https://docs.rs/libffi/0.8.0")]
//! Rust bindings for [libffi](https://sourceware.org/libffi/).
//!
//! The C libffi library provides two main facilities: assembling calls
//! to functions dynamically, and creating closures that can be called
//! as ordinary C functions. In Rust, the latter means that we can turn
//! a Rust lambda (or any object implementing `Fn`/`FnMut`) into an
//! ordinary C function pointer that we can pass as a callback to C.
//!
//! The easiest way to use this library is via the
//! [`high`](high/index.html) layer module, but more flexibility (and
//! less checking) is provided by the [`middle`](middle/index.html) and
//! [`low`](low/index.html) layers.
//!
//! # Usage
//!
//! Building libffi will build lifbffi-sys, which will in turn build the
//! libffi C library [from github](https://github.com/libffi/libffi), which
//! requires that you have a working make, C compiler, automake, and
//! autoconf first. It’s [on crates.io](https://crates.io/crates/libffi), so
//! you can add
//!
//! ```toml
//! [dependencies]
//! libffi = "0.8.0"
//! ```
//!
//! This crate depends on [the `libffi-sys` crate], which by default
//! attempts to build its own version of the C libffi library. In order to
//! use your system’s C libffi instead, enable this crate’s  `system`
//! feature in your `Cargo.toml`:
//!
//! ```toml
//! [features]
//! libffi = { version = "0.8.0", features = ["system"] }
//! ```
//!
//! See [the `libffi-sys` documentation] for more information about how it
//! finds C libffi.
//!
//! This crate supports Rust version 1.36 and later.
//!
//! # Organization
//!
//! This library is organized in four layers, each of which attempts to
//! provide more safety and a simpler interface than the next layer
//! down. From top to bottom:
//!
//!   - The [`high`](high/index.html) layer provides safe(?) and
//!     automatic marshalling of Rust closures into C function pointers.
//!   - The [`middle`](middle/index.html) layer provides memory-managed
//!     abstractions for assembling calls and closures, but is unsafe
//!     because it doesn’t check argument types.
//!   - The [`low`](low/index.html) layer makes no attempts at safety,
//!     but provides a more idiomatically “Rusty” API than the underlying
//!     C library.
//!   - The [`raw`](raw/index.html) layer is a re-export of the
//!     [`libffi-sys`](https://crates.io/crates/libffi-sys) crate,
//!     a direct mapping of the C libffi library into Rust, generated by
//!     [bindgen](https://crates.io/crates/bindgen).
//!
//! It should be possible to use any layer without dipping into lower
//! layers (and it will be considered a bug to the extent that it
//! isn’t).
//!
//! # Examples
//!
//! In this example, we convert a Rust lambda containing a free variable
//! into an ordinary C code pointer. The type of `fun` below is
//! `extern "C" fn(u64, u64) -> u64`.
//!
//! ```
//! use libffi::high::Closure2;
//!
//! let x = 5u64;
//! let f = |y: u64, z: u64| x + y + z;
//!
//! let closure = Closure2::new(&f);
//! let fun     = closure.code_ptr();
//!
//! assert_eq!(18, fun(6, 7));
//! ```
//!
//! [the `libffi-sys` crate]: https://crates.io/crates/libffi-sys/
//!
//! [the `libffi-sys` documentation]: https://docs.rs/libffi-sys/#usage
//!

#![deny(missing_docs)]

/// Raw definitions imported from the C library (via bindgen).
///
/// This module is generated by bindgen and undocumented. It’s intended
/// as the basis for higher-level bindings, but you can see the [C libffi
/// documentation](http://www.atmark-techno.com/~yashi/libffi.html).
pub mod raw {
    pub use libffi_sys::*;
}

pub mod high;
pub mod middle;
pub mod low;
<|endoftext|>


<commit_before>//! Show and Edit Cargo's Manifest Files
#![cfg_attr(test, allow(dead_code))]
#![warn(
    missing_docs,
    missing_debug_implementations,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]

#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;

extern crate failure;

mod crate_name;
mod dependency;
mod errors;
mod fetch;
mod manifest;

pub use crate::crate_name::CrateName;
pub use crate::dependency::Dependency;
pub use crate::errors::*;
pub use crate::fetch::{
    get_crate_name_from_github, get_crate_name_from_gitlab, get_crate_name_from_path,
    get_latest_dependency,
};
pub use crate::manifest::{find, LocalManifest, Manifest};
<commit_msg>No need to specify `extern crate` in Rust 2018!<commit_after>//! Show and Edit Cargo's Manifest Files
#![cfg_attr(test, allow(dead_code))]
#![warn(
    missing_docs,
    missing_debug_implementations,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]

#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate serde_derive;

mod crate_name;
mod dependency;
mod errors;
mod fetch;
mod manifest;

pub use crate::crate_name::CrateName;
pub use crate::dependency::Dependency;
pub use crate::errors::*;
pub use crate::fetch::{
    get_crate_name_from_github, get_crate_name_from_gitlab, get_crate_name_from_path,
    get_latest_dependency,
};
pub use crate::manifest::{find, LocalManifest, Manifest};
<|endoftext|>


<commit_before>#[macro_use]
extern crate hyper;
extern crate rustc_serialize;

use std::io::Read;

use hyper::Client;
use hyper::status::StatusCode;

use rustc_serialize::json;

header! { (XStarfighterAuthorization, "X-Starfighter-Authorization") => [String] }

#[derive(RustcDecodable, RustcEncodable)]
struct Heartbeat {
    ok: bool,
    error: String,
}

#[derive(RustcDecodable, RustcEncodable)]
struct VenueHeartbeat {
    ok: bool,
    // venue is not present on error
    venue: Option<String>,
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct Quote {
    ok: bool,
    symbol: String,
    venue: String,
    bid: Option<usize>,
    ask: Option<usize>,
    bid_size: Option<usize>,
    ask_size: Option<usize>,
    bid_depth: Option<usize>,
    ask_depth: Option<usize>,
    last: usize,
    last_size: Option<usize>,
    last_trade: Option<String>,
    quote_time: Option<String>,
}

#[derive(Debug, PartialEq, Eq)]
pub enum StockfighterError {
    ApiDown,
    VenueDown(String),
    ApiError
}

pub struct Stockfighter {
    api_key: String,
}

impl Stockfighter {

    pub fn new<S>(api_key: S) -> Stockfighter where S: Into<String> {
        Stockfighter { api_key: api_key.into() }
    }

    ///
    /// Check that the Stockfighter API is up
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.heartbeat().is_ok());
    /// ```
    pub fn heartbeat(&self) -> Result<(), StockfighterError> {
        let client = Client::new();
        let mut res = client
            .get("https://api.stockfighter.io/ob/api/heartbeat")
            .send()
            .unwrap();

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiDown);
        }

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        let hb: Heartbeat = json::decode(&body).unwrap();

        match hb.ok {
            true => Ok(()),
            false => Err(StockfighterError::ApiDown)
        }
    }

    pub fn venue_heartbeat(&self, venue: &str) -> Result<(), StockfighterError> {
        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/heartbeat", venue);
        let client = Client::new();
        let mut res = client
            .get(&url)
            .send()
            .unwrap();

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::VenueDown(venue.to_owned()));
        }

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        let hb: VenueHeartbeat = json::decode(&body).unwrap();

        match hb.ok {
            true => Ok(()),
            false => Err(StockfighterError::VenueDown(venue.to_owned()))
        }
    }

    pub fn quote(&self, venue: &str, stock: &str) -> Result<Quote, StockfighterError> {

        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/stocks/{}/quote", venue, stock);

        let client = Client::new();

        let mut res = client
            .get(&url)
            .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix the use of clone here
            .send()
            .unwrap();

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiError);
        }

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        let quote: Quote = json::decode(&body).unwrap();

        match quote.ok {
            true => Ok(quote),
            false => Err(StockfighterError::ApiError)
        }
    }
}

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

    #[test]
    fn test_heartbeat() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.heartbeat().is_ok());
    }

    #[test]
    fn test_venue() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.venue_heartbeat("TESTEX").is_ok());
        assert_eq!(StockfighterError::VenueDown("INVALID".to_owned()), sf.venue_heartbeat("INVALID").unwrap_err());
    }

    #[test]
    fn test_quote() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.quote("TESTEX", "FOOBAR").is_ok());
        assert_eq!(true, sf.quote("INVALID", "FOOBAR").is_err());
        assert_eq!(true, sf.quote("TESTEX", "INVALID").is_err());
        assert_eq!(true, sf.quote("INVALID", "INVALID").is_err());
    }
}
<commit_msg>Added Stocks On a Venue #9<commit_after>#[macro_use]
extern crate hyper;
extern crate rustc_serialize;

use std::io::Read;

use hyper::Client;
use hyper::status::StatusCode;

use rustc_serialize::json;

header! { (XStarfighterAuthorization, "X-Starfighter-Authorization") => [String] }

#[derive(RustcDecodable, RustcEncodable)]
struct Heartbeat {
    ok: bool,
    error: String,
}

#[derive(RustcDecodable, RustcEncodable)]
struct VenueHeartbeat {
    ok: bool,
    // venue is not present on error
    venue: Option<String>,
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct Quote {
    ok: bool,
    symbol: String,
    venue: String,
    bid: Option<usize>,
    ask: Option<usize>,
    bid_size: Option<usize>,
    ask_size: Option<usize>,
    bid_depth: Option<usize>,
    ask_depth: Option<usize>,
    last: usize,
    last_size: Option<usize>,
    last_trade: Option<String>,
    quote_time: Option<String>,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub enum OrderDirection {
    Buy,
    Sell,
}

// https://starfighter.readme.io/docs/place-new-order#order-types
#[derive(RustcDecodable, RustcEncodable, Debug)]
pub enum OrderType {
    Limit,
    Market,
    FillOrKill,
    ImmediateOrCancel,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct StockTicker {
    name: String,
    symbol: String,
}

#[derive(RustcDecodable, RustcEncodable, Debug)]
pub struct StockList {
    ok: bool,
    symbols: Vec< StockTicker>,
}

#[derive(Debug, PartialEq, Eq)]
pub enum StockfighterError {
    ApiDown,
    VenueDown(String), // Also means unknown venue
    ApiError
}

pub struct Stockfighter {
    api_key: String,
}

impl Stockfighter {

    pub fn new<S>(api_key: S) -> Stockfighter where S: Into<String> {
        Stockfighter { api_key: api_key.into() }
    }

    ///
    /// Check that the Stockfighter API is up
    ///
    /// # Example
    ///
    /// ```rust
    /// use stockfighter::Stockfighter;
    ///
    /// let sf = Stockfighter::new("fake api key");
    /// assert_eq!(true, sf.heartbeat().is_ok());
    /// ```
    pub fn heartbeat(&self) -> Result<(), StockfighterError> {
        let client = Client::new();
        let mut res = client
            .get("https://api.stockfighter.io/ob/api/heartbeat")
            .send()
            .unwrap();

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiDown);
        }

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        let hb: Heartbeat = json::decode(&body).unwrap();

        match hb.ok {
            true => Ok(()),
            false => Err(StockfighterError::ApiDown)
        }
    }

    pub fn venue_heartbeat(&self, venue: &str) -> Result<(), StockfighterError> {
        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/heartbeat", venue);
        let client = Client::new();
        let mut res = client
            .get(&url)
            .send()
            .unwrap();

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::VenueDown(venue.to_owned()));
        }

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        let hb: VenueHeartbeat = json::decode(&body).unwrap();

        match hb.ok {
            true => Ok(()),
            false => Err(StockfighterError::VenueDown(venue.to_owned()))
        }
    }

    pub fn quote(&self, venue: &str, stock: &str) -> Result<Quote, StockfighterError> {

        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/stocks/{}/quote", venue, stock);

        let client = Client::new();

        let mut res = client
            .get(&url)
            .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix the use of clone here
            .send()
            .unwrap();

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::ApiError);
        }

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        let quote: Quote = json::decode(&body).unwrap();

        match quote.ok {
            true => Ok(quote),
            false => Err(StockfighterError::ApiError)
        }
    }
    pub fn stocks_on_a_venue( &self, venue : &str ) -> Result<StockList, StockfighterError> {

        let url = format!("https://api.stockfighter.io/ob/api/venues/{}/stocks", venue );

        let client = Client::new();

        let mut res = client
            .get(&url)
            .header(XStarfighterAuthorization(self.api_key.clone())) // TODO fix the use of clone here
            .send()
            .unwrap();

        if res.status != StatusCode::Ok {
            return Err(StockfighterError::VenueDown(venue.to_owned()));
        }

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        let stocklist: StockList = json::decode(&body).unwrap();

        match stocklist.ok {
            true => Ok(stocklist),
            false => Err(StockfighterError::ApiError)
        }
    }
}

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

    #[test]
    fn test_heartbeat() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.heartbeat().is_ok());
    }

    #[test]
    fn test_venue() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.venue_heartbeat("TESTEX").is_ok());
        assert_eq!(StockfighterError::VenueDown("INVALID".to_owned()), sf.venue_heartbeat("INVALID").unwrap_err());
    }

    #[test]
    fn test_quote() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.quote("TESTEX", "FOOBAR").is_ok());
        assert_eq!(true, sf.quote("INVALID", "FOOBAR").is_err());
        assert_eq!(true, sf.quote("TESTEX", "INVALID").is_err());
        assert_eq!(true, sf.quote("INVALID", "INVALID").is_err());
    }

    #[test]
    fn test_stocks_on_a_venue() {
        let sf = Stockfighter::new("");
        assert_eq!(true, sf.stocks_on_a_venue("TESTEX").is_ok());
        println!("{:?}", sf.stocks_on_a_venue("TESTEX") );
        assert_eq!(StockfighterError::VenueDown("INVALID".to_owned()), sf.stocks_on_a_venue("INVALID").unwrap_err());
    }

}
<|endoftext|>


<commit_before>#![feature(collections, core, libc)]
#![allow(raw_pointer_derive)]
#![crate_name = "neovim"]
#![crate_type = "lib"]
#![crate_type = "rlib"]

extern crate libc;

use std::ffi::CString;
use std::fmt;

#[cfg(target_os="macos")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "termkey", kind = "static")]
    #[link(name = "unibilium", kind = "static")]
    #[link(name = "util")]
    #[link(name = "intl")]
    #[link(name = "iconv")]
    extern{}
}

#[cfg(target_os="linux")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "termkey", kind = "static")]
    #[link(name = "unibilium", kind = "static")]
    #[link(name = "util")]
    extern{}
}

mod ffi;

pub enum Object {
    Buffer(ffi::C_Buffer),
    Window(ffi::C_Window),
    Tabpage(ffi::C_Tabpage),
    Boolean(ffi::C_Boolean),
    Integer(ffi::C_Integer),
    Float(ffi::C_Float),
    String(String),
    Array(Array),
    Dictionary(ffi::C_Dictionary)
}

impl fmt::Debug for Object {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Object::Buffer(ref obj) => write!(f, "Buffer({:?})", obj),
            Object::Window(ref obj) => write!(f, "Window({:?})", obj),
            Object::Tabpage(ref obj) => write!(f, "Tabpage({:?})", obj),
            Object::Boolean(ref obj) => write!(f, "Boolean({:?})", obj),
            Object::Integer(ref obj) => write!(f, "Integer({:?})", obj),
            Object::Float(ref obj) => write!(f, "Float({:?})", obj),
            Object::String(ref obj) => write!(f, "String({:?})", obj),
            Object::Array(ref arr) => {
                write!(f, "Array(").ok();
                let obj = arr.unwrap_value();
                for i in 0..obj.size {
                    let inner_obj_opt = unsafe { c_object_to_object(obj.items.offset(i as isize)) };
                    if let Some(inner_obj) = inner_obj_opt {
                        write!(f, "{:?}", inner_obj).ok();
                        if i + 1 < obj.size {
                            write!(f, ", ").ok();
                        }
                    } else {
                        write!(f, "Nil ").ok();
                    }
                }
                write!(f, ")")
            },
            Object::Dictionary(ref obj) => write!(f, "Dictionary(Length: {:?})", obj.size)
        }
    }
}

unsafe fn c_object_to_object(obj: *mut ffi::C_Object) -> Option<Object> {
    match (*obj).object_type {
        ffi::ObjectType::BufferType =>
            Some(Object::Buffer((*(obj as *mut ffi::C_Object_Buffer)).data)),
        ffi::ObjectType::WindowType =>
            Some(Object::Window((*(obj as *mut ffi::C_Object_Window)).data)),
        ffi::ObjectType::TabpageType =>
            Some(Object::Tabpage((*(obj as *mut ffi::C_Object_Tabpage)).data)),
        ffi::ObjectType::NilType =>
            None,
        ffi::ObjectType::BooleanType =>
            Some(Object::Boolean((*(obj as *mut ffi::C_Object_Boolean)).data)),
        ffi::ObjectType::IntegerType =>
            Some(Object::Integer((*(obj as *mut ffi::C_Object_Integer)).data)),
        ffi::ObjectType::FloatType =>
            Some(Object::Float((*(obj as *mut ffi::C_Object_Float)).data)),
        ffi::ObjectType::StringType => {
            let vim_str: ffi::C_String = (*(obj as *mut ffi::C_Object_String)).data;
            let v = Vec::from_raw_buf(vim_str.data as *const u8, vim_str.size as usize);
            Some(Object::String(String::from_utf8_unchecked(v)))
        },
        ffi::ObjectType::ArrayType =>
            Some(Object::Array(Array::wrap_value((*(obj as *mut ffi::C_Object_Array)).data))),
        ffi::ObjectType::DictionaryType =>
            Some(Object::Dictionary((*(obj as *mut ffi::C_Object_Dictionary)).data))
    }
}

pub fn main_setup(args: &Vec<String>) -> i32 {
    let args_vec_cstr: Vec<CString> = args.iter().map(|s| CString::new(s.as_slice()).unwrap()).collect();
    let args_vec_ptr: Vec<*const ffi::c_char> = args_vec_cstr.iter().map(|s| s.as_ptr()).collect();
    unsafe { ffi::nvim_main_setup(args_vec_ptr.len() as i32, args_vec_ptr.as_ptr()) }
}

pub fn main_loop() -> i32 {
    unsafe { ffi::nvim_main_loop() }
}

pub fn channel_from_fds(read_fd: i32, write_fd: i32) -> u64 {
    unsafe { ffi::channel_from_fds(read_fd, write_fd) }
}

pub fn serialize_message(id: u64, method: &'static str, args: &Array) -> String {
    unsafe {
        let buf = ffi::vim_msgpack_new();
        let vim_str = ffi::C_String {data: method.as_ptr() as *const i8, size: method.len() as u64};
        ffi::vim_serialize_request(id, vim_str, args.unwrap_value(), buf);
        let v = Vec::from_raw_buf((*buf).data as *const u8, (*buf).size as usize);
        ffi::vim_msgpack_free(buf);
        String::from_utf8_unchecked(v)
    }
}

pub fn deserialize_message(message: &String) -> Array {
    let s = ffi::C_String {
        data: message.as_slice().as_ptr() as *const i8,
        size: message.len() as u64
    };
    let mut arr_raw = ffi::C_Array {
        items: ::std::ptr::null_mut(),
        size: 0,
        capacity: 0
    };
    unsafe { ffi::vim_msgpack_parse(s, &mut arr_raw) };
    Array::wrap_value(arr_raw)
}

pub struct Array {
    value: ffi::C_Array,
    is_owned: bool,
}

impl Array {
    pub fn new() -> Array {
        Array {
            value: ffi::C_Array {
                items: ::std::ptr::null_mut(),
                size: 0,
                capacity: 0
            },
            is_owned: true
        }
    }

    pub fn add_buffer(&mut self, val: ffi::C_Buffer) {
        unsafe { ffi::vim_array_add_buffer(val, &mut self.value) }
    }

    pub fn add_window(&mut self, val: ffi::C_Window) {
        unsafe { ffi::vim_array_add_window(val, &mut self.value) }
    }

    pub fn add_tabpage(&mut self, val: ffi::C_Tabpage) {
        unsafe { ffi::vim_array_add_tabpage(val, &mut self.value) }
    }

    pub fn add_nil(&mut self) {
        unsafe { ffi::vim_array_add_nil(&mut self.value) }
    }

    pub fn add_boolean(&mut self, val: ffi::C_Boolean) {
        unsafe { ffi::vim_array_add_boolean(val, &mut self.value) }
    }

    pub fn add_integer(&mut self, val: ffi::C_Integer) {
        unsafe { ffi::vim_array_add_integer(val, &mut self.value) }
    }

    pub fn add_float(&mut self, val: ffi::C_Float) {
        unsafe { ffi::vim_array_add_float(val, &mut self.value) }
    }

    pub fn add_string(&mut self, val: &str) {
        unsafe {
            // we need to copy the string into memory not managed by Rust,
            // so api_free_array can clear it
            let ptr = ffi::malloc(val.len() as u64);
            ::std::ptr::copy(ptr, val.as_ptr() as *const ffi::c_void, val.len());
            let vim_str = ffi::C_String {data: ptr as *const i8, size: val.len() as u64};
            ffi::vim_array_add_string(vim_str, &mut self.value)
        }
    }

    pub fn add_array(&mut self, val: &Array) {
        unsafe { ffi::vim_array_add_array(val.unwrap_value(), &mut self.value) }
    }

    pub fn add_dictionary(&mut self, val: ffi::C_Dictionary) {
        unsafe { ffi::vim_array_add_dictionary(val, &mut self.value) }
    }

    pub fn get(&self, index: u64) -> Option<Object> {
        if index >= self.len() {
            return None;
        }
        unsafe { c_object_to_object(self.value.items.offset(index as isize)) }
    }

    pub fn len(&self) -> u64 {
        self.value.size
    }

    #[doc(hidden)]
    pub fn unwrap_value(&self) -> ffi::C_Array {
        self.value
    }

    #[doc(hidden)]
    pub fn wrap_value(c_array: ffi::C_Array) -> Array {
        Array {
            value: c_array,
            is_owned: false
        }
    }
}

impl Drop for Array {
    fn drop(&mut self) {
        if self.is_owned {
            unsafe { ffi::api_free_array(self.value) };
        }
    }
}

impl fmt::Debug for Array {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Array(").ok();
        for i in 0..self.len() {
            if let Some(obj) = self.get(i) {
                write!(f, "{:?}", obj).ok();
            } else {
                write!(f, "Nil").ok();
            }
            if i + 1 < self.len() {
                write!(f, ", ").ok();
            }
        }
        write!(f, ")")
    }
}

#[test]
fn test_request() {
    let mut args = Array::new();
    args.add_integer(80);
    args.add_integer(24);
    args.add_string("hello");

    let msg = serialize_message(1, "test", &args);
    let arr = deserialize_message(&msg);
    println!("LENGTH: {}", arr.len());
    for i in 0..arr.len() {
        println!("{:?}", arr.get(i));
    }
}
<commit_msg>Remove deprecation warnings<commit_after>#![feature(collections, convert, libc)]
#![allow(raw_pointer_derive)]
#![crate_name = "neovim"]
#![crate_type = "lib"]
#![crate_type = "rlib"]

extern crate libc;

use std::ffi::CString;
use std::fmt;

#[cfg(target_os="macos")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "termkey", kind = "static")]
    #[link(name = "unibilium", kind = "static")]
    #[link(name = "util")]
    #[link(name = "intl")]
    #[link(name = "iconv")]
    extern{}
}

#[cfg(target_os="linux")]
mod platform {
    #[link(name = "nvim")]
    #[link(name = "uv")]
    #[link(name = "msgpack")]
    #[link(name = "termkey", kind = "static")]
    #[link(name = "unibilium", kind = "static")]
    #[link(name = "util")]
    extern{}
}

mod ffi;

pub enum Object {
    Buffer(ffi::C_Buffer),
    Window(ffi::C_Window),
    Tabpage(ffi::C_Tabpage),
    Boolean(ffi::C_Boolean),
    Integer(ffi::C_Integer),
    Float(ffi::C_Float),
    String(String),
    Array(Array),
    Dictionary(ffi::C_Dictionary)
}

impl fmt::Debug for Object {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Object::Buffer(ref obj) => write!(f, "Buffer({:?})", obj),
            Object::Window(ref obj) => write!(f, "Window({:?})", obj),
            Object::Tabpage(ref obj) => write!(f, "Tabpage({:?})", obj),
            Object::Boolean(ref obj) => write!(f, "Boolean({:?})", obj),
            Object::Integer(ref obj) => write!(f, "Integer({:?})", obj),
            Object::Float(ref obj) => write!(f, "Float({:?})", obj),
            Object::String(ref obj) => write!(f, "String({:?})", obj),
            Object::Array(ref arr) => {
                write!(f, "Array(").ok();
                let obj = arr.unwrap_value();
                for i in 0..obj.size {
                    let inner_obj_opt = unsafe { c_object_to_object(obj.items.offset(i as isize)) };
                    if let Some(inner_obj) = inner_obj_opt {
                        write!(f, "{:?}", inner_obj).ok();
                        if i + 1 < obj.size {
                            write!(f, ", ").ok();
                        }
                    } else {
                        write!(f, "Nil ").ok();
                    }
                }
                write!(f, ")")
            },
            Object::Dictionary(ref obj) => write!(f, "Dictionary(Length: {:?})", obj.size)
        }
    }
}

unsafe fn c_object_to_object(obj: *mut ffi::C_Object) -> Option<Object> {
    match (*obj).object_type {
        ffi::ObjectType::BufferType =>
            Some(Object::Buffer((*(obj as *mut ffi::C_Object_Buffer)).data)),
        ffi::ObjectType::WindowType =>
            Some(Object::Window((*(obj as *mut ffi::C_Object_Window)).data)),
        ffi::ObjectType::TabpageType =>
            Some(Object::Tabpage((*(obj as *mut ffi::C_Object_Tabpage)).data)),
        ffi::ObjectType::NilType =>
            None,
        ffi::ObjectType::BooleanType =>
            Some(Object::Boolean((*(obj as *mut ffi::C_Object_Boolean)).data)),
        ffi::ObjectType::IntegerType =>
            Some(Object::Integer((*(obj as *mut ffi::C_Object_Integer)).data)),
        ffi::ObjectType::FloatType =>
            Some(Object::Float((*(obj as *mut ffi::C_Object_Float)).data)),
        ffi::ObjectType::StringType => {
            let vim_str: ffi::C_String = (*(obj as *mut ffi::C_Object_String)).data;
            let v = Vec::from_raw_buf(vim_str.data as *const u8, vim_str.size as usize);
            Some(Object::String(String::from_utf8_unchecked(v)))
        },
        ffi::ObjectType::ArrayType =>
            Some(Object::Array(Array::wrap_value((*(obj as *mut ffi::C_Object_Array)).data))),
        ffi::ObjectType::DictionaryType =>
            Some(Object::Dictionary((*(obj as *mut ffi::C_Object_Dictionary)).data))
    }
}

pub fn main_setup(args: &Vec<String>) -> i32 {
    let args_vec_cstr: Vec<CString> = args.iter().map(|s| {
        let s_ref: &str = s.as_ref();
        CString::new(s_ref).unwrap()
    }).collect();
    let args_vec_ptr: Vec<*const ffi::c_char> = args_vec_cstr.iter().map(|s| s.as_ptr()).collect();
    unsafe { ffi::nvim_main_setup(args_vec_ptr.len() as i32, args_vec_ptr.as_ptr()) }
}

pub fn main_loop() -> i32 {
    unsafe { ffi::nvim_main_loop() }
}

pub fn channel_from_fds(read_fd: i32, write_fd: i32) -> u64 {
    unsafe { ffi::channel_from_fds(read_fd, write_fd) }
}

pub fn serialize_message(id: u64, method: &'static str, args: &Array) -> String {
    unsafe {
        let buf = ffi::vim_msgpack_new();
        let vim_str = ffi::C_String {data: method.as_ptr() as *const i8, size: method.len() as u64};
        ffi::vim_serialize_request(id, vim_str, args.unwrap_value(), buf);
        let v = Vec::from_raw_buf((*buf).data as *const u8, (*buf).size as usize);
        ffi::vim_msgpack_free(buf);
        String::from_utf8_unchecked(v)
    }
}

pub fn deserialize_message(message: &String) -> Array {
    let message_ref: &str = message.as_ref();
    let s = ffi::C_String {
        data: message_ref.as_ptr() as *const i8,
        size: message.len() as u64
    };
    let mut arr_raw = ffi::C_Array {
        items: ::std::ptr::null_mut(),
        size: 0,
        capacity: 0
    };
    unsafe { ffi::vim_msgpack_parse(s, &mut arr_raw) };
    Array::wrap_value(arr_raw)
}

pub struct Array {
    value: ffi::C_Array,
    is_owned: bool,
}

impl Array {
    pub fn new() -> Array {
        Array {
            value: ffi::C_Array {
                items: ::std::ptr::null_mut(),
                size: 0,
                capacity: 0
            },
            is_owned: true
        }
    }

    pub fn add_buffer(&mut self, val: ffi::C_Buffer) {
        unsafe { ffi::vim_array_add_buffer(val, &mut self.value) }
    }

    pub fn add_window(&mut self, val: ffi::C_Window) {
        unsafe { ffi::vim_array_add_window(val, &mut self.value) }
    }

    pub fn add_tabpage(&mut self, val: ffi::C_Tabpage) {
        unsafe { ffi::vim_array_add_tabpage(val, &mut self.value) }
    }

    pub fn add_nil(&mut self) {
        unsafe { ffi::vim_array_add_nil(&mut self.value) }
    }

    pub fn add_boolean(&mut self, val: ffi::C_Boolean) {
        unsafe { ffi::vim_array_add_boolean(val, &mut self.value) }
    }

    pub fn add_integer(&mut self, val: ffi::C_Integer) {
        unsafe { ffi::vim_array_add_integer(val, &mut self.value) }
    }

    pub fn add_float(&mut self, val: ffi::C_Float) {
        unsafe { ffi::vim_array_add_float(val, &mut self.value) }
    }

    pub fn add_string(&mut self, val: &str) {
        unsafe {
            // we need to copy the string into memory not managed by Rust,
            // so api_free_array can clear it
            let ptr = ffi::malloc(val.len() as u64);
            ::std::ptr::copy(ptr, val.as_ptr() as *const ffi::c_void, val.len());
            let vim_str = ffi::C_String {data: ptr as *const i8, size: val.len() as u64};
            ffi::vim_array_add_string(vim_str, &mut self.value)
        }
    }

    pub fn add_array(&mut self, val: &Array) {
        unsafe { ffi::vim_array_add_array(val.unwrap_value(), &mut self.value) }
    }

    pub fn add_dictionary(&mut self, val: ffi::C_Dictionary) {
        unsafe { ffi::vim_array_add_dictionary(val, &mut self.value) }
    }

    pub fn get(&self, index: u64) -> Option<Object> {
        if index >= self.len() {
            return None;
        }
        unsafe { c_object_to_object(self.value.items.offset(index as isize)) }
    }

    pub fn len(&self) -> u64 {
        self.value.size
    }

    #[doc(hidden)]
    pub fn unwrap_value(&self) -> ffi::C_Array {
        self.value
    }

    #[doc(hidden)]
    pub fn wrap_value(c_array: ffi::C_Array) -> Array {
        Array {
            value: c_array,
            is_owned: false
        }
    }
}

impl Drop for Array {
    fn drop(&mut self) {
        if self.is_owned {
            unsafe { ffi::api_free_array(self.value) };
        }
    }
}

impl fmt::Debug for Array {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Array(").ok();
        for i in 0..self.len() {
            if let Some(obj) = self.get(i) {
                write!(f, "{:?}", obj).ok();
            } else {
                write!(f, "Nil").ok();
            }
            if i + 1 < self.len() {
                write!(f, ", ").ok();
            }
        }
        write!(f, ")")
    }
}

#[test]
fn test_request() {
    let mut args = Array::new();
    args.add_integer(80);
    args.add_integer(24);
    args.add_string("hello");

    let msg = serialize_message(1, "test", &args);
    let arr = deserialize_message(&msg);
    println!("LENGTH: {}", arr.len());
    for i in 0..arr.len() {
        println!("{:?}", arr.get(i));
    }
}
<|endoftext|>


<commit_before>#![feature(std_misc)]
use std::sync::Semaphore;
use std::thread;

pub struct ThreadPool {
    sem: std::sync::Semaphore,
}

impl ThreadPool {
    pub fn new(size: isize) -> ThreadPool {
       ThreadPool { sem: std::sync::Semaphore::new(size) }
    }

    pub fn scoped<'a, T, F>(&'a self, func: F) -> std::thread::JoinGuard<'a, T>
        where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
    {
       let guard = self.sem.access();
       thread::scoped(move || {
           let _guard = guard;
           func()
       })
    }
}

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

    #[test]
    // TODO find a better way to test than have someone pay attention to the commandline...
    fn it_works() {
        let pool = ThreadPool::new(2);

        let mut guards: Vec<thread::JoinGuard<()>> = Vec::new();

        for _ in (0..3) {
            guards.push(pool.scoped(move || {
                thread::sleep_ms(1000);
                println!("Things are happening!");
            }));
        }
    }
}
<commit_msg>chore(rename) clean up naming to make the pool's purpose clearer<commit_after>#![feature(std_misc)]
use std::sync::Semaphore;
use std::thread;

pub struct ScopedThreadPool {
    sem: std::sync::Semaphore,
}

impl ScopedThreadPool {
    pub fn new(size: isize) -> ScopedThreadPool {
       ScopedThreadPool { sem: std::sync::Semaphore::new(size) }
    }

    pub fn execute<'a, T, F>(&'a self, func: F) -> std::thread::JoinGuard<'a, T>
        where T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
    {
       let guard = self.sem.access();
       thread::scoped(move || {
           let _guard = guard;
           func()
       })
    }
}

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

    #[test]
    // TODO find a better way to test than have someone pay attention to the commandline...
    fn it_works() {
        let pool = ScopedThreadPool::new(2);

        let mut guards: Vec<thread::JoinGuard<()>> = Vec::new();

        for _ in (0..3) {
            guards.push(pool.execute(move || {
                thread::sleep_ms(1000);
                println!("Things are happening!");
            }));
        }
    }
}
<|endoftext|>