<commit_before>use std::io::{TempDir, MemWriter};
use std::str::from_utf8;
use sync::{Arc, Mutex, RWLock};
use collections::hashmap::HashMap;
use schema;
use buffer;

#[deriving(Show, Eq, TotalEq, Hash, Clone)]
struct Register {
	record: schema::Record,
	datatype: schema::SqlType,
}

impl Register {
	fn new(rec: schema::Record, typ: schema::SqlType) -> Register {
		Register {
			record: rec,
			datatype: typ,
		}
	}

	fn set_int(&mut self, val: int) {
		// TODO
	}

	fn get_int(&self) -> int {
		self.record.to_int()
	}

	fn set_str(&mut self) {
		// TODO
	}

	fn get_str<'a>(&'a self) -> &'a str {
		let d = self.record.get_data();
		from_utf8(d).unwrap()
	}
}

impl Ord for Register {
	fn lt(&self, other: &Register) -> bool {
		// not the most robust implementation
		self.get_int() < other.get_int()
	}
}

trait Operatorish<T>: Iterator<T> {
	//fn open();
	//fn close(&self);
}

struct TableScan {
	relation: schema::Relation,
	segment: Arc<Mutex<schema::SPSegment>>,
	current: uint,
}

impl TableScan {
	fn new(rel: schema::Relation, seg: Arc<Mutex<schema::SPSegment>>) -> TableScan {
		TableScan {
			relation: rel,
			segment: seg,
			current: 0,
		}
	}
}

impl Operatorish<Vec<Register>> for TableScan {
}

impl Iterator<Vec<Register>> for TableScan {
	fn next(&mut self) -> Option<Vec<Register>> {
		if (self.current as u64) < self.relation.inserted {
			let mut seg = self.segment.lock();
			let tup = self.relation.get(seg.deref_mut(), self.current);
			let mut res = tup.move_iter().map(|(v, t)| Register::new(v, t)).
				collect::<Vec<Register>>();
			debug!("TS: {}", res);
			self.current += 1;
			Some(res)
		} else {
			None
		}
	}
}

struct Print<'a, T, V> {
	input: T,
	output: &'a mut V,
}

impl<'a, T: Operatorish<Vec<Register>>, V: Writer> Print<'a, T, V> {
	fn new(input: T, output: &'a mut V) -> Print<'a, T, V> {
		Print {
			input: input,
			output: output
		}
	}
}

impl<'a, T: Operatorish<Vec<Register>>, V: Writer> Iterator<Vec<Register>> for Print<'a, T, V> {
	fn next(&mut self) -> Option<Vec<Register>> {
		let cur = self.input.next();
		match cur {
			Some(reg) => {
				for item in reg.iter() {
					match item.datatype {
						schema::Varchar(_) => self.output.write(item.get_str().as_bytes()),
						schema::Integer => self.output.write(
							format!("{}", item.get_int()).as_bytes())
					};
					self.output.write(", ".as_bytes());
				}
				self.output.write("\n".as_bytes());
				Some(reg)
			},
			None => None,
		}
	}
}

struct Project<T> {
	input: T,
	registerids: Vec<uint>,
}

impl<T: Operatorish<Vec<Register>>> Project<T> {
	fn new(input: T, regs: Vec<uint>) -> Project<T> {
		Project {
			input: input,
			registerids: regs,
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Iterator<Vec<Register>> for Project<T> {
	fn next(&mut self) -> Option<Vec<Register>> {
		let cur = self.input.next();
		match cur {
			None => None,
			Some(mut reg) => {
				let mut res = Vec::with_capacity(self.registerids.len());
				let mut regids = self.registerids.clone();
				regids.reverse();
				for index in regids.move_iter() {
					let value = reg.remove(index);
					let v = match value {
						None => fail!("Projection doesn't have vield {}", index),
						Some(v) => v,
					};
					res.push(v);
				}
				Some(res)
			}
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Operatorish<Vec<Register>> for Project<T> {
}

#[deriving(Show)]
enum Selectable {
	Varchar(~str),
	Integer(int),
}

struct Select<T> {
	input: T,
	index: uint,
	value: Selectable,
}

impl<T: Operatorish<Vec<Register>>> Select<T> {
	fn new(input: T, index: uint, value: Selectable) -> Select<T> {
		Select {
			input: input,
			index: index,
			value: value,
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Iterator<Vec<Register>> for Select<T> {
	fn next(&mut self) -> Option<Vec<Register>> {
		// initial value
		let mut cur = self.input.next();
		while cur.is_some() {
			// we made sure cur is Some(…), so we can unwrap safely
			let reg = cur.unwrap();

			// check what we got to select for and retrieve values
			// accordingly
			match self.value {
				// comparing to a string
				Varchar(ref v) => {
					println!("Comparing {} with {}",
						reg.get(self.index).get_str(),
						v);
					// getting the register value as string
					if reg.get(self.index).get_str() == *v {
						return Some(reg)
					} else {
						// not equal, skip to next entry
						cur = self.input.next();
						continue
					}
				},
				// comparing to a number
				Integer(v) => {
					// compare against reg as integer
					if reg.get(self.index).get_int() == v {
						return Some(reg)
					} else {
						// not equal, skip to next entry
						cur = self.input.next();
						continue
					}
				}
			}
		}
		// no more entries, signal iterator exhaustion
		None
	}
}

impl<T: Operatorish<Vec<Register>>> Operatorish<Vec<Register>> for Select<T> {
}

struct HashJoin<T> {
	result: Vec<(Vec<Register>, Vec<Register>)>,
}

impl<T: Operatorish<Vec<Register>>> HashJoin<T> {
	fn new(mut left: T, mut right: T, on: (uint, uint)) -> HashJoin<T> {
		let mut map = HashMap::new();
		let (lindex, rindex) = on;
		for mut tuple in left {
			let element = tuple.get(lindex).clone();
			map.insert(element, tuple);
		}

		debug!("HashJoin map: {}", map);
		let mut res = Vec::new();
		for r in right {
			let element = r.get(rindex).clone();
			match map.find_copy(&element) {
				Some(s) => res.push((s, r)),
				None => continue,
			};
		}
		debug!("HashJon result: {}", res);

		HashJoin {
			result: res,
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Iterator<Vec<Register>> for HashJoin<T> {
	fn next(&mut self) -> Option<Vec<Register>> {
		match self.result.shift() {
			None => None,
			Some((mut s, r)) => {
				s.push_all_move(r);
				Some(s)
			}
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Operatorish<Vec<Register>> for HashJoin<T> {
}

fn construct_relation(prefix: ~str) -> (schema::Relation, Arc<Mutex<schema::SPSegment>>) {
	let dir = match TempDir::new(prefix) {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	//let p = dir.path();
	let p = Path::new(".");

	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let mut seg = schema::SPSegment::new(1, Arc::new(RWLock::new(manager)));

	let name = schema::Column::new(~"name", schema::Varchar(128), vec!(schema::NotNull));
	let age = schema::Column::new(~"age", schema::Integer, vec!(schema::NotNull));
	let mut relation = schema::Relation::new(~"Person");
	relation.add_column(name);
	relation.add_column(age);
	relation.insert(&mut seg, vec!(schema::Record::from_str(~"Alice"), schema::Record::from_int(20)));
	relation.insert(&mut seg, vec!(schema::Record::from_str(~"Bob"), schema::Record::from_int(40)));
	let segmut = Arc::new(Mutex::new(seg));
	(relation, segmut)
}

#[test]
fn simple_tablescan() {
	let (relation, segmut) = construct_relation(~"tablescan");

	let mut ts = TableScan::new(relation, segmut);
	let mut result = Vec::new();
	let expected = vec!((~"Alice", 20), (~"Bob", 40));
	for tuple in ts {
		println!("Got entry {}", tuple);
		let n = tuple.get(0).get_str().to_owned();
		let i = tuple.get(1).get_int();
		result.push((n, i));
	}
	assert_eq!(expected, result);
}

#[test]
fn simple_print() {
	let (relation, segmut) = construct_relation(~"print");
	let mut mw = MemWriter::new();
	{
		let mut ts = TableScan::new(relation.clone(), segmut.clone());
		let mut pr = Print::new(ts, &mut mw);
		// force write by iterating, strange API
		for _ in pr {}
	}
	let data = mw.unwrap();
	let printed = from_utf8(data).unwrap().to_owned();
	let expected = ~"Alice, 20, \nBob, 40, \n";

	println!("Printed:\n{}", printed);
	assert_eq!(expected, printed);
}

#[test]
fn simple_project() {
	let (relation, segmut) = construct_relation(~"project");
	{
		let mut mw = MemWriter::new();
		{
			let mut ts = TableScan::new(relation.clone(), segmut.clone());
			let mut pr = Project::new(ts, vec!(0));
			let mut pr = Print::new(pr, &mut mw);
			for _ in pr {}
		}
		println!("Saved: {}", from_utf8(mw.unwrap()).unwrap());
	}

	{
		let mut mw = MemWriter::new();
		{
			let mut ts = TableScan::new(relation.clone(), segmut.clone());
			let mut se = Select::new(ts, 1, Integer(20));
			let mut pr = Print::new(se, &mut mw);
			for _ in pr {}
		}
		println!("Saved: {}", from_utf8(mw.unwrap()).unwrap());
	}

	{
		let mut mw = MemWriter::new();
		{
			let mut ts = TableScan::new(relation.clone(), segmut.clone());
			let mut se = Select::new(ts, 0, Varchar(~"Bob"));
			let mut pr = Print::new(se, &mut mw);
			for _ in pr {}
		}
		println!("Saved: {}", from_utf8(mw.unwrap()).unwrap());
	}

	assert!(false);
}

#[test]
fn simple_hashjoin() {
	let dir = match TempDir::new("hashjoin") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	//let p = dir.path();
	let p = Path::new(".");

	let manager = buffer::BufferManager::new(1024, p.clone());
	let mut seg = schema::SPSegment::new(1, Arc::new(RWLock::new(manager)));

	/* first relation */
	let mut people = schema::Relation::new(~"Person");
	let id = schema::Column::new(~"id", schema::Integer, vec!(schema::NotNull));
	let name = schema::Column::new(~"name", schema::Varchar(128), vec!(schema::NotNull));
	people.add_column(id);
	people.add_column(name);
	people.insert(&mut seg, vec!(schema::Record::from_int(0), schema::Record::from_str(~"Alice")));
	people.insert(&mut seg, vec!(schema::Record::from_int(1), schema::Record::from_str(~"Bob")));
	people.insert(&mut seg, vec!(schema::Record::from_int(2), schema::Record::from_str(~"Eve")));
	people.insert(&mut seg, vec!(schema::Record::from_int(3), schema::Record::from_str(~"Mallory")));

	/* second relation */
	let mut oses = schema::Relation::new(~"OSes");
	let ident = schema::Column::new(~"ident", schema::Integer, vec!(schema::NotNull));
	let os = schema::Column::new(~"OS", schema::Varchar(128), vec!(schema::NotNull));
	oses.add_column(ident);
	oses.add_column(os);
	oses.insert(&mut seg, vec!(schema::Record::from_int(0), schema::Record::from_str(~"Plan 9")));
	oses.insert(&mut seg, vec!(schema::Record::from_int(1), schema::Record::from_str(~"NetBSD")));
	oses.insert(&mut seg, vec!(schema::Record::from_int(3), schema::Record::from_str(~"GNU/Linux")));

	let mut mw = MemWriter::new();
	let segmut = Arc::new(Mutex::new(seg));
	let ts_left = TableScan::new(oses, segmut.clone());
	let ts_right = TableScan::new(people, segmut.clone());
	let hj = HashJoin::new(ts_left, ts_right, (0,0));
	{
		let mut pr = Print::new(hj, &mut mw);
		for _ in pr {}
	}
	let expected = ~"0, Plan 9, 0, Alice, \n1, NetBSD, 1, Bob, \n3, GNU/Linux, 3, Mallory, \n";
	let data = mw.unwrap();
	let printed = from_utf8(data).unwrap().to_owned();

	assert_eq!(expected, printed);
}
<commit_msg>Refactored projection unit test<commit_after>use std::io::{TempDir, MemWriter};
use std::str::from_utf8;
use sync::{Arc, Mutex, RWLock};
use collections::hashmap::HashMap;
use schema;
use buffer;

#[deriving(Show, Eq, TotalEq, Hash, Clone)]
struct Register {
	record: schema::Record,
	datatype: schema::SqlType,
}

impl Register {
	fn new(rec: schema::Record, typ: schema::SqlType) -> Register {
		Register {
			record: rec,
			datatype: typ,
		}
	}

	fn set_int(&mut self, val: int) {
		// TODO
	}

	fn get_int(&self) -> int {
		self.record.to_int()
	}

	fn set_str(&mut self) {
		// TODO
	}

	fn get_str<'a>(&'a self) -> &'a str {
		let d = self.record.get_data();
		from_utf8(d).unwrap()
	}
}

impl Ord for Register {
	fn lt(&self, other: &Register) -> bool {
		// not the most robust implementation
		self.get_int() < other.get_int()
	}
}

trait Operatorish<T>: Iterator<T> {
	//fn open();
	//fn close(&self);
}

struct TableScan {
	relation: schema::Relation,
	segment: Arc<Mutex<schema::SPSegment>>,
	current: uint,
}

impl TableScan {
	fn new(rel: schema::Relation, seg: Arc<Mutex<schema::SPSegment>>) -> TableScan {
		TableScan {
			relation: rel,
			segment: seg,
			current: 0,
		}
	}
}

impl Operatorish<Vec<Register>> for TableScan {
}

impl Iterator<Vec<Register>> for TableScan {
	fn next(&mut self) -> Option<Vec<Register>> {
		if (self.current as u64) < self.relation.inserted {
			let mut seg = self.segment.lock();
			let tup = self.relation.get(seg.deref_mut(), self.current);
			let mut res = tup.move_iter().map(|(v, t)| Register::new(v, t)).
				collect::<Vec<Register>>();
			debug!("TS: {}", res);
			self.current += 1;
			Some(res)
		} else {
			None
		}
	}
}

struct Print<'a, T, V> {
	input: T,
	output: &'a mut V,
}

impl<'a, T: Operatorish<Vec<Register>>, V: Writer> Print<'a, T, V> {
	fn new(input: T, output: &'a mut V) -> Print<'a, T, V> {
		Print {
			input: input,
			output: output
		}
	}
}

impl<'a, T: Operatorish<Vec<Register>>, V: Writer> Iterator<Vec<Register>> for Print<'a, T, V> {
	fn next(&mut self) -> Option<Vec<Register>> {
		let cur = self.input.next();
		match cur {
			Some(reg) => {
				for item in reg.iter() {
					match item.datatype {
						schema::Varchar(_) => self.output.write(item.get_str().as_bytes()),
						schema::Integer => self.output.write(
							format!("{}", item.get_int()).as_bytes())
					};
					self.output.write(", ".as_bytes());
				}
				self.output.write("\n".as_bytes());
				Some(reg)
			},
			None => None,
		}
	}
}

struct Project<T> {
	input: T,
	registerids: Vec<uint>,
}

impl<T: Operatorish<Vec<Register>>> Project<T> {
	fn new(input: T, regs: Vec<uint>) -> Project<T> {
		Project {
			input: input,
			registerids: regs,
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Iterator<Vec<Register>> for Project<T> {
	fn next(&mut self) -> Option<Vec<Register>> {
		let cur = self.input.next();
		match cur {
			None => None,
			Some(mut reg) => {
				let mut res = Vec::with_capacity(self.registerids.len());
				let mut regids = self.registerids.clone();
				regids.reverse();
				for index in regids.move_iter() {
					let value = reg.remove(index);
					let v = match value {
						None => fail!("Projection doesn't have vield {}", index),
						Some(v) => v,
					};
					res.push(v);
				}
				Some(res)
			}
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Operatorish<Vec<Register>> for Project<T> {
}

#[deriving(Show)]
enum Selectable {
	Varchar(~str),
	Integer(int),
}

struct Select<T> {
	input: T,
	index: uint,
	value: Selectable,
}

impl<T: Operatorish<Vec<Register>>> Select<T> {
	fn new(input: T, index: uint, value: Selectable) -> Select<T> {
		Select {
			input: input,
			index: index,
			value: value,
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Iterator<Vec<Register>> for Select<T> {
	fn next(&mut self) -> Option<Vec<Register>> {
		// initial value
		let mut cur = self.input.next();
		while cur.is_some() {
			// we made sure cur is Some(…), so we can unwrap safely
			let reg = cur.unwrap();

			// check what we got to select for and retrieve values
			// accordingly
			match self.value {
				// comparing to a string
				Varchar(ref v) => {
					println!("Comparing {} with {}",
						reg.get(self.index).get_str(),
						v);
					// getting the register value as string
					if reg.get(self.index).get_str() == *v {
						return Some(reg)
					} else {
						// not equal, skip to next entry
						cur = self.input.next();
						continue
					}
				},
				// comparing to a number
				Integer(v) => {
					// compare against reg as integer
					if reg.get(self.index).get_int() == v {
						return Some(reg)
					} else {
						// not equal, skip to next entry
						cur = self.input.next();
						continue
					}
				}
			}
		}
		// no more entries, signal iterator exhaustion
		None
	}
}

impl<T: Operatorish<Vec<Register>>> Operatorish<Vec<Register>> for Select<T> {
}

struct HashJoin<T> {
	result: Vec<(Vec<Register>, Vec<Register>)>,
}

impl<T: Operatorish<Vec<Register>>> HashJoin<T> {
	fn new(mut left: T, mut right: T, on: (uint, uint)) -> HashJoin<T> {
		let mut map = HashMap::new();
		let (lindex, rindex) = on;
		for mut tuple in left {
			let element = tuple.get(lindex).clone();
			map.insert(element, tuple);
		}

		debug!("HashJoin map: {}", map);
		let mut res = Vec::new();
		for r in right {
			let element = r.get(rindex).clone();
			match map.find_copy(&element) {
				Some(s) => res.push((s, r)),
				None => continue,
			};
		}
		debug!("HashJon result: {}", res);

		HashJoin {
			result: res,
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Iterator<Vec<Register>> for HashJoin<T> {
	fn next(&mut self) -> Option<Vec<Register>> {
		match self.result.shift() {
			None => None,
			Some((mut s, r)) => {
				s.push_all_move(r);
				Some(s)
			}
		}
	}
}

impl<T: Operatorish<Vec<Register>>> Operatorish<Vec<Register>> for HashJoin<T> {
}

fn construct_relation(prefix: ~str) -> (schema::Relation, Arc<Mutex<schema::SPSegment>>) {
	let dir = match TempDir::new(prefix) {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	//let p = dir.path();
	let p = Path::new(".");

	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let mut seg = schema::SPSegment::new(1, Arc::new(RWLock::new(manager)));

	let name = schema::Column::new(~"name", schema::Varchar(128), vec!(schema::NotNull));
	let age = schema::Column::new(~"age", schema::Integer, vec!(schema::NotNull));
	let mut relation = schema::Relation::new(~"Person");
	relation.add_column(name);
	relation.add_column(age);
	relation.insert(&mut seg, vec!(schema::Record::from_str(~"Alice"), schema::Record::from_int(20)));
	relation.insert(&mut seg, vec!(schema::Record::from_str(~"Bob"), schema::Record::from_int(40)));
	let segmut = Arc::new(Mutex::new(seg));
	(relation, segmut)
}

#[test]
fn simple_tablescan() {
	let (relation, segmut) = construct_relation(~"tablescan");

	let mut ts = TableScan::new(relation, segmut);
	let mut result = Vec::new();
	let expected = vec!((~"Alice", 20), (~"Bob", 40));
	for tuple in ts {
		println!("Got entry {}", tuple);
		let n = tuple.get(0).get_str().to_owned();
		let i = tuple.get(1).get_int();
		result.push((n, i));
	}
	assert_eq!(expected, result);
}

#[test]
fn simple_print() {
	let (relation, segmut) = construct_relation(~"print");
	let mut mw = MemWriter::new();
	{
		let mut ts = TableScan::new(relation.clone(), segmut.clone());
		let mut pr = Print::new(ts, &mut mw);
		// force write by iterating, strange API
		for _ in pr {}
	}
	let data = mw.unwrap();
	let printed = from_utf8(data).unwrap().to_owned();
	let expected = ~"Alice, 20, \nBob, 40, \n";

	println!("Printed:\n{}", printed);
	assert_eq!(expected, printed);
}

#[test]
fn simple_project() {
	let (relation, segmut) = construct_relation(~"project");
	let mut mw = MemWriter::new();
	{
		let mut ts = TableScan::new(relation, segmut);
		let mut pr = Project::new(ts, vec!(0));
		let mut pr = Print::new(pr, &mut mw);
		for _ in pr {}
	}
	let data = mw.unwrap();
	let printed = from_utf8(data).unwrap().to_owned();
	let expected = ~"Alice, \nBob, \n";

	println!("Printed:\n{}", printed);
	assert_eq!(expected, printed);
}

#[test]
fn simple_select() {
	let (relation, segmut) = construct_relation(~"select");
	{
		let mut mw = MemWriter::new();
		{
			let mut ts = TableScan::new(relation.clone(), segmut.clone());
			let mut se = Select::new(ts, 1, Integer(20));
			let mut pr = Print::new(se, &mut mw);
			for _ in pr {}
		}
		println!("Saved: {}", from_utf8(mw.unwrap()).unwrap());
	}

	{
		let mut mw = MemWriter::new();
		{
			let mut ts = TableScan::new(relation.clone(), segmut.clone());
			let mut se = Select::new(ts, 0, Varchar(~"Bob"));
			let mut pr = Print::new(se, &mut mw);
			for _ in pr {}
		}
		println!("Saved: {}", from_utf8(mw.unwrap()).unwrap());
	}

	assert!(false);
}

#[test]
fn simple_hashjoin() {
	let dir = match TempDir::new("hashjoin") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	//let p = dir.path();
	let p = Path::new(".");

	let manager = buffer::BufferManager::new(1024, p.clone());
	let mut seg = schema::SPSegment::new(1, Arc::new(RWLock::new(manager)));

	/* first relation */
	let mut people = schema::Relation::new(~"Person");
	let id = schema::Column::new(~"id", schema::Integer, vec!(schema::NotNull));
	let name = schema::Column::new(~"name", schema::Varchar(128), vec!(schema::NotNull));
	people.add_column(id);
	people.add_column(name);
	people.insert(&mut seg, vec!(schema::Record::from_int(0), schema::Record::from_str(~"Alice")));
	people.insert(&mut seg, vec!(schema::Record::from_int(1), schema::Record::from_str(~"Bob")));
	people.insert(&mut seg, vec!(schema::Record::from_int(2), schema::Record::from_str(~"Eve")));
	people.insert(&mut seg, vec!(schema::Record::from_int(3), schema::Record::from_str(~"Mallory")));

	/* second relation */
	let mut oses = schema::Relation::new(~"OSes");
	let ident = schema::Column::new(~"ident", schema::Integer, vec!(schema::NotNull));
	let os = schema::Column::new(~"OS", schema::Varchar(128), vec!(schema::NotNull));
	oses.add_column(ident);
	oses.add_column(os);
	oses.insert(&mut seg, vec!(schema::Record::from_int(0), schema::Record::from_str(~"Plan 9")));
	oses.insert(&mut seg, vec!(schema::Record::from_int(1), schema::Record::from_str(~"NetBSD")));
	oses.insert(&mut seg, vec!(schema::Record::from_int(3), schema::Record::from_str(~"GNU/Linux")));

	let mut mw = MemWriter::new();
	let segmut = Arc::new(Mutex::new(seg));
	let ts_left = TableScan::new(oses, segmut.clone());
	let ts_right = TableScan::new(people, segmut.clone());
	let hj = HashJoin::new(ts_left, ts_right, (0,0));
	{
		let mut pr = Print::new(hj, &mut mw);
		for _ in pr {}
	}
	let expected = ~"0, Plan 9, 0, Alice, \n1, NetBSD, 1, Bob, \n3, GNU/Linux, 3, Mallory, \n";
	let data = mw.unwrap();
	let printed = from_utf8(data).unwrap().to_owned();

	assert_eq!(expected, printed);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Column", inherited=False) %>

${helpers.predefined_type("column-width",
                          "length::NonNegativeLengthOrAuto",
                          "Either::Second(Auto)",
                          initial_specified_value="Either::Second(Auto)",
                          extra_prefixes="moz",
                          animation_value_type="NonNegativeLengthOrAuto",
                          servo_pref="layout.column-width.enabled",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-width")}

${helpers.predefined_type("column-count",
                          "PositiveIntegerOrAuto",
                          "Either::Second(Auto)",
                          initial_specified_value="Either::Second(Auto)",
                          servo_pref="layout.column-count.enabled",
                          animation_value_type="PositiveIntegerOrAuto",
                          extra_prefixes="moz",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-count")}

${helpers.predefined_type("column-gap",
                          "length::NonNegativeLengthOrNormal",
                          "Either::Second(Normal)",
                          extra_prefixes="moz",
                          servo_pref="layout.column-gap.enabled",
                          animation_value_type="NonNegativeLengthOrNormal",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-gap")}

${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz",
                         products="gecko", animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill")}

${helpers.predefined_type("column-rule-width",
                          "BorderSideWidth",
                          "::values::computed::NonNegativeLength::new(3.)",
                          initial_specified_value="specified::BorderSideWidth::Medium",
                          computed_type="::values::computed::NonNegativeLength",
                          products="gecko",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width",
                          animation_value_type="NonNegativeLength",
                          extra_prefixes="moz")}

// https://drafts.csswg.org/css-multicol-1/#crc
${helpers.predefined_type(
    "column-rule-color",
    "Color",
    "computed_value::T::currentcolor()",
    initial_specified_value="specified::Color::currentcolor()",
    products="gecko",
    animation_value_type="AnimatedColor",
    extra_prefixes="moz",
    ignored_when_colors_disabled=True,
    spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color",
)}

${helpers.single_keyword("column-span", "none all",
                         products="gecko", animation_value_type="discrete",
                         gecko_pref="layout.css.column-span.enabled",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-span")}

${helpers.single_keyword("column-rule-style",
                         "none hidden dotted dashed solid double groove ridge inset outset",
                         products="gecko", extra_prefixes="moz",
                         gecko_constant_prefix="NS_STYLE_BORDER_STYLE",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style")}
<commit_msg>Bug 1417725 - (Servo) Add -moz-column-span alias for column-span property.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("Column", inherited=False) %>

${helpers.predefined_type("column-width",
                          "length::NonNegativeLengthOrAuto",
                          "Either::Second(Auto)",
                          initial_specified_value="Either::Second(Auto)",
                          extra_prefixes="moz",
                          animation_value_type="NonNegativeLengthOrAuto",
                          servo_pref="layout.column-width.enabled",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-width")}

${helpers.predefined_type("column-count",
                          "PositiveIntegerOrAuto",
                          "Either::Second(Auto)",
                          initial_specified_value="Either::Second(Auto)",
                          servo_pref="layout.column-count.enabled",
                          animation_value_type="PositiveIntegerOrAuto",
                          extra_prefixes="moz",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-count")}

${helpers.predefined_type("column-gap",
                          "length::NonNegativeLengthOrNormal",
                          "Either::Second(Normal)",
                          extra_prefixes="moz",
                          servo_pref="layout.column-gap.enabled",
                          animation_value_type="NonNegativeLengthOrNormal",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-gap")}

${helpers.single_keyword("column-fill", "balance auto", extra_prefixes="moz",
                         products="gecko", animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill")}

${helpers.predefined_type("column-rule-width",
                          "BorderSideWidth",
                          "::values::computed::NonNegativeLength::new(3.)",
                          initial_specified_value="specified::BorderSideWidth::Medium",
                          computed_type="::values::computed::NonNegativeLength",
                          products="gecko",
                          spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width",
                          animation_value_type="NonNegativeLength",
                          extra_prefixes="moz")}

// https://drafts.csswg.org/css-multicol-1/#crc
${helpers.predefined_type(
    "column-rule-color",
    "Color",
    "computed_value::T::currentcolor()",
    initial_specified_value="specified::Color::currentcolor()",
    products="gecko",
    animation_value_type="AnimatedColor",
    extra_prefixes="moz",
    ignored_when_colors_disabled=True,
    spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color",
)}

${helpers.single_keyword("column-span", "none all",
                         products="gecko", animation_value_type="discrete",
                         gecko_pref="layout.css.column-span.enabled",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-span",
                         extra_prefixes="moz")}

${helpers.single_keyword("column-rule-style",
                         "none hidden dotted dashed solid double groove ridge inset outset",
                         products="gecko", extra_prefixes="moz",
                         gecko_constant_prefix="NS_STYLE_BORDER_STYLE",
                         animation_value_type="discrete",
                         spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style")}
<|endoftext|>


<commit_before>//! SHM handling helpers
//!
//! This module provides helpers to handle SHM-based buffers from wayland clients.
//!
//! SHM (Shared Memory) is the most basic way wayland clients can send content to
//! the compositor: by sending a file descriptor to some (likely RAM-backed) storage
//! containing the actual data. This helper handles for you most of the logic for
//! handling these file descriptor and accessing their contents as simple `&[u8]` slices.
//!
//! This module is heavily inspired from
//! [the similar helpers](https://cgit.freedesktop.org/wayland/wayland/tree/src/wayland-shm.c)
//! of the wayland C libraries.
//!
//! To use it, first add a `ShmGlobal` to your event loop, specifying the formats
//! you want to support (ARGB8888 and XRGB8888 are always considered as supported,
//! as specified by the wayland protocol) and obtain its `ShmGlobalToken`.
//!
//! ```
//! extern crate wayland_server;
//! extern crate smithay;
//!
//! use smithay::shm::ShmGlobal;
//! use wayland_server::protocol::wl_shm;
//!
//! # fn main() {
//! # let (_, mut event_loop) = wayland_server::create_display();
//!
//! // Insert the ShmGlobal as a handler to your event loop
//! // Here, we specify that Yuyv and C8 format are supported
//! // additionnaly to the standart Argb8888 and Xrgb8888.
//! let handler_id = event_loop.add_handler_with_init(ShmGlobal::new(
//!     vec![wl_shm::Format::Yuyv, wl_shm::Format::C8],
//!     None // we don't provide a logger here
//! ));
//! // Register this handler to advertise a wl_shm global of version 1
//! let shm_global = event_loop.register_global::<wl_shm::WlShm,ShmGlobal>(handler_id, 1);
//! // Retrieve the shm token for later use to access the buffers
//! let shm_token = {
//!     let state = event_loop.state();
//!     state.get_handler::<ShmGlobal>(handler_id).get_token()
//! };
//!
//! # }
//! ```
//!
//! Then, when you have a `WlBuffer` and need to retrieve its contents, use the token method to
//! do it:
//!
//! ```ignore
//! shm_token.with_buffer_contents(&buffer,
//!     |slice: &[u8], buffer_metadata: &BufferData| {
//!         // do something to draw it on the screen
//!     }
//! );
//! ```
//!
//! **Note**
//!
//! This handler makes itself safe regading the client providing a wrong size for the memory pool
//! by using a SIGBUS handler.
//!
//! If you are already using an handler for this signal, you probably don't want to use this handler.

use self::pool::{Pool, ResizeError};

use std::os::unix::io::RawFd;
use std::sync::Arc;

use wayland_server::{Client, Destroy, EventLoopHandle, GlobalHandler, Init, Resource, resource_is_registered};
use wayland_server::protocol::{wl_buffer, wl_shm, wl_shm_pool};

mod pool;

/// A global for handling SHM pool and buffers
///
/// You must register it to an event loop using `register_with_init`, or it will
/// quickly panic.
pub struct ShmGlobal {
    formats: Vec<wl_shm::Format>,
    handler_id: Option<usize>,
    log: ::slog::Logger,
}

impl ShmGlobal {
    /// Create a new SHM global advertizing given supported formats.
    ///
    /// This global will always advertize `ARGB8888` and `XRGB8888` format
    /// as they are required by the protocol. Formats given as argument
    /// as additionnaly advertized.
    pub fn new<L>(mut formats: Vec<wl_shm::Format>, logger: L) -> ShmGlobal
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = ::slog_or_stdlog(logger);

        // always add the mandatory formats
        formats.push(wl_shm::Format::Argb8888);
        formats.push(wl_shm::Format::Xrgb8888);
        ShmGlobal {
            formats: formats,
            handler_id: None,
            log: log.new(o!("smithay_module" => "shm_handler")),
        }
    }

    /// Retreive a token from the SHM global.
    ///
    /// This can only be called once the `ShmGlobal` has been added to and event loop
    /// and has been initialized. If it is not the case, this method will panic.
    ///
    /// This is needed to retrieve the contents of the shm pools and buffers.
    pub fn get_token(&self) -> ShmGlobalToken {
        ShmGlobalToken { hid: self.handler_id.expect("ShmGlobal was not initialized.") }
    }
}

/// An SHM global token
///
/// It is needed to access the contents of the buffers & pools managed by the
/// associated `ShmGlobal`.
pub struct ShmGlobalToken {
    hid: usize,
}

/// Error that can occur when accessing an SHM buffer
pub enum BufferAccessError {
    /// This buffer is not managed by the SHM handler
    NotManaged,
    /// An error occured while accessing the memory map
    ///
    /// This can happen if the client advertized a wrong size
    /// for the memory map.
    ///
    /// If this error occurs, the client has been killed as a result.
    BadMap,
}

impl ShmGlobalToken {
    /// Call given closure with the contents of the given buffer
    ///
    /// If the buffer is managed by the associated ShmGlobal, its contents are
    /// extracted and the closure is extracted with them:
    ///
    /// - The first argument is a data slice of the contents of the pool
    /// - The second argument is the specification of this buffer is this pool
    ///
    /// If the buffer is not managed by the associated ShmGlobal, the closure is not called
    /// and this method will return `Err(())` (this will be the case for an EGL buffer for example).
    pub fn with_buffer_contents<F>(&self, buffer: &wl_buffer::WlBuffer, f: F) -> Result<(), BufferAccessError>
    where
        F: FnOnce(&[u8], BufferData),
    {
        if !resource_is_registered::<_, ShmHandler>(buffer, self.hid) {
            return Err(BufferAccessError::NotManaged);
        }
        let data = unsafe { &*(buffer.get_user_data() as *mut InternalBufferData) };

        if data.pool
            .with_data_slice(|slice| f(slice, data.data))
            .is_err()
        {
            // SIGBUS error occured
            buffer.post_error(wl_shm::Error::InvalidFd as u32, "Bad pool size.".into());
            return Err(BufferAccessError::BadMap);
        }
        Ok(())
    }
}

impl Init for ShmGlobal {
    fn init(&mut self, evqh: &mut EventLoopHandle, _index: usize) {
        let id = evqh.add_handler_with_init(ShmHandler {
            my_id: ::std::usize::MAX,
            valid_formats: self.formats.clone(),
            log: self.log.clone(),
        });
        self.handler_id = Some(id);
    }
}

impl GlobalHandler<wl_shm::WlShm> for ShmGlobal {
    fn bind(&mut self, evqh: &mut EventLoopHandle, _: &Client, global: wl_shm::WlShm) {
        let hid = self.handler_id.expect("ShmGlobal was not initialized.");
        // register an handler for this shm
        evqh.register::<_, ShmHandler>(&global, hid);
        // and then the custom formats
        for f in &self.formats {
            global.format(*f);
        }
    }
}

struct ShmHandler {
    my_id: usize,
    valid_formats: Vec<wl_shm::Format>,
    log: ::slog::Logger,
}

impl Init for ShmHandler {
    fn init(&mut self, _evqh: &mut EventLoopHandle, index: usize) {
        self.my_id = index;
        debug!(self.log, "Init finished")
    }
}

impl wl_shm::Handler for ShmHandler {
    fn create_pool(&mut self, evqh: &mut EventLoopHandle, _client: &Client, shm: &wl_shm::WlShm,
                   pool: wl_shm_pool::WlShmPool, fd: RawFd, size: i32) {
        if size <= 0 {
            shm.post_error(
                wl_shm::Error::InvalidFd as u32,
                "Invalid size for a new wl_shm_pool.".into(),
            );
            return;
        }
        let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) {
            Ok(p) => p,
            Err(()) => {
                shm.post_error(wl_shm::Error::InvalidFd as u32, format!("Failed mmap of fd {}.", fd));
                return
            }
        };
        let arc_pool = Box::new(Arc::new(mmap_pool));
        evqh.register_with_destructor::<_, ShmHandler, ShmHandler>(&pool, self.my_id);
        pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
    }
}

impl Destroy<wl_shm_pool::WlShmPool> for ShmHandler {
    fn destroy(pool: &wl_shm_pool::WlShmPool) {
        let arc_pool = unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) };
        drop(arc_pool)
    }
}

declare_handler!(ShmHandler, wl_shm::Handler, wl_shm::WlShm);

/// Details of the contents of a buffer relative to its pool
#[derive(Copy, Clone, Debug)]
pub struct BufferData {
    /// Offset of the start of the buffer relative to the beginning of the pool in bytes
    pub offset: i32,
    /// Wwidth of the buffer in bytes
    pub width: i32,
    /// Height of the buffer in bytes
    pub height: i32,
    /// Stride of the buffer in bytes
    pub stride: i32,
    /// Format used by this buffer
    pub format: wl_shm::Format,
}

struct InternalBufferData {
    pool: Arc<Pool>,
    data: BufferData,
}

impl wl_shm_pool::Handler for ShmHandler {
    fn create_buffer(&mut self, evqh: &mut EventLoopHandle, _client: &Client,
                     pool: &wl_shm_pool::WlShmPool, buffer: wl_buffer::WlBuffer, offset: i32, width: i32,
                     height: i32, stride: i32, format: wl_shm::Format) {
        if !self.valid_formats.contains(&format) {
            buffer.post_error(wl_shm::Error::InvalidFormat as u32, String::new());
            return;
        }
        let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
        let data = Box::into_raw(Box::new(InternalBufferData {
            pool: arc_pool.clone(),
            data: BufferData {
                offset: offset,
                width: width,
                height: height,
                stride: stride,
                format: format,
            },
        }));
        evqh.register_with_destructor::<_, ShmHandler, ShmHandler>(&buffer, self.my_id);
        buffer.set_user_data(data as *mut ());
    }

    fn resize(&mut self, _evqh: &mut EventLoopHandle, _client: &Client, pool: &wl_shm_pool::WlShmPool,
              size: i32) {
        let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
        match arc_pool.resize(size) {
            Ok(()) => {}
            Err(ResizeError::InvalidSize) => {
                pool.post_error(
                    wl_shm::Error::InvalidFd as u32,
                    "Invalid new size for a wl_shm_pool.".into(),
                );
            }
            Err(ResizeError::MremapFailed) => {
                pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into());
            }
        }
    }
}

impl Destroy<wl_buffer::WlBuffer> for ShmHandler {
    fn destroy(buffer: &wl_buffer::WlBuffer) {
        let buffer_data = unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) };
        drop(buffer_data)
    }
}

declare_handler!(ShmHandler, wl_shm_pool::Handler, wl_shm_pool::WlShmPool);

impl wl_buffer::Handler for ShmHandler {}

declare_handler!(ShmHandler, wl_buffer::Handler, wl_buffer::WlBuffer);
<commit_msg>shm: rename ShmGlobalToken to ShmToken<commit_after>//! SHM handling helpers
//!
//! This module provides helpers to handle SHM-based buffers from wayland clients.
//!
//! SHM (Shared Memory) is the most basic way wayland clients can send content to
//! the compositor: by sending a file descriptor to some (likely RAM-backed) storage
//! containing the actual data. This helper handles for you most of the logic for
//! handling these file descriptor and accessing their contents as simple `&[u8]` slices.
//!
//! This module is heavily inspired from
//! [the similar helpers](https://cgit.freedesktop.org/wayland/wayland/tree/src/wayland-shm.c)
//! of the wayland C libraries.
//!
//! To use it, first add a `ShmGlobal` to your event loop, specifying the formats
//! you want to support (ARGB8888 and XRGB8888 are always considered as supported,
//! as specified by the wayland protocol) and obtain its `ShmToken`.
//!
//! ```
//! extern crate wayland_server;
//! extern crate smithay;
//!
//! use smithay::shm::ShmGlobal;
//! use wayland_server::protocol::wl_shm;
//!
//! # fn main() {
//! # let (_, mut event_loop) = wayland_server::create_display();
//!
//! // Insert the ShmGlobal as a handler to your event loop
//! // Here, we specify that Yuyv and C8 format are supported
//! // additionnaly to the standart Argb8888 and Xrgb8888.
//! let handler_id = event_loop.add_handler_with_init(ShmGlobal::new(
//!     vec![wl_shm::Format::Yuyv, wl_shm::Format::C8],
//!     None // we don't provide a logger here
//! ));
//! // Register this handler to advertise a wl_shm global of version 1
//! let shm_global = event_loop.register_global::<wl_shm::WlShm,ShmGlobal>(handler_id, 1);
//! // Retrieve the shm token for later use to access the buffers
//! let shm_token = {
//!     let state = event_loop.state();
//!     state.get_handler::<ShmGlobal>(handler_id).get_token()
//! };
//!
//! # }
//! ```
//!
//! Then, when you have a `WlBuffer` and need to retrieve its contents, use the token method to
//! do it:
//!
//! ```ignore
//! shm_token.with_buffer_contents(&buffer,
//!     |slice: &[u8], buffer_metadata: &BufferData| {
//!         // do something to draw it on the screen
//!     }
//! );
//! ```
//!
//! **Note**
//!
//! This handler makes itself safe regading the client providing a wrong size for the memory pool
//! by using a SIGBUS handler.
//!
//! If you are already using an handler for this signal, you probably don't want to use this handler.

use self::pool::{Pool, ResizeError};

use std::os::unix::io::RawFd;
use std::sync::Arc;

use wayland_server::{Client, Destroy, EventLoopHandle, GlobalHandler, Init, Resource, resource_is_registered};
use wayland_server::protocol::{wl_buffer, wl_shm, wl_shm_pool};

mod pool;

/// A global for handling SHM pool and buffers
///
/// You must register it to an event loop using `register_with_init`, or it will
/// quickly panic.
pub struct ShmGlobal {
    formats: Vec<wl_shm::Format>,
    handler_id: Option<usize>,
    log: ::slog::Logger,
}

impl ShmGlobal {
    /// Create a new SHM global advertizing given supported formats.
    ///
    /// This global will always advertize `ARGB8888` and `XRGB8888` format
    /// as they are required by the protocol. Formats given as argument
    /// as additionnaly advertized.
    pub fn new<L>(mut formats: Vec<wl_shm::Format>, logger: L) -> ShmGlobal
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = ::slog_or_stdlog(logger);

        // always add the mandatory formats
        formats.push(wl_shm::Format::Argb8888);
        formats.push(wl_shm::Format::Xrgb8888);
        ShmGlobal {
            formats: formats,
            handler_id: None,
            log: log.new(o!("smithay_module" => "shm_handler")),
        }
    }

    /// Retreive a token from the SHM global.
    ///
    /// This can only be called once the `ShmGlobal` has been added to and event loop
    /// and has been initialized. If it is not the case, this method will panic.
    ///
    /// This is needed to retrieve the contents of the shm pools and buffers.
    pub fn get_token(&self) -> ShmToken {
        ShmToken { hid: self.handler_id.expect("ShmGlobal was not initialized.") }
    }
}

/// An SHM global token
///
/// It is needed to access the contents of the buffers & pools managed by the
/// associated `ShmGlobal`.
#[derive(Clone)]
pub struct ShmToken {
    hid: usize,
}

/// Error that can occur when accessing an SHM buffer
pub enum BufferAccessError {
    /// This buffer is not managed by the SHM handler
    NotManaged,
    /// An error occured while accessing the memory map
    ///
    /// This can happen if the client advertized a wrong size
    /// for the memory map.
    ///
    /// If this error occurs, the client has been killed as a result.
    BadMap,
}

impl ShmToken {
    /// Call given closure with the contents of the given buffer
    ///
    /// If the buffer is managed by the associated ShmGlobal, its contents are
    /// extracted and the closure is extracted with them:
    ///
    /// - The first argument is a data slice of the contents of the pool
    /// - The second argument is the specification of this buffer is this pool
    ///
    /// If the buffer is not managed by the associated ShmGlobal, the closure is not called
    /// and this method will return `Err(())` (this will be the case for an EGL buffer for example).
    pub fn with_buffer_contents<F>(&self, buffer: &wl_buffer::WlBuffer, f: F) -> Result<(), BufferAccessError>
    where
        F: FnOnce(&[u8], BufferData),
    {
        if !resource_is_registered::<_, ShmHandler>(buffer, self.hid) {
            return Err(BufferAccessError::NotManaged);
        }
        let data = unsafe { &*(buffer.get_user_data() as *mut InternalBufferData) };

        if data.pool
            .with_data_slice(|slice| f(slice, data.data))
            .is_err()
        {
            // SIGBUS error occured
            buffer.post_error(wl_shm::Error::InvalidFd as u32, "Bad pool size.".into());
            return Err(BufferAccessError::BadMap);
        }
        Ok(())
    }
}

impl Init for ShmGlobal {
    fn init(&mut self, evqh: &mut EventLoopHandle, _index: usize) {
        let id = evqh.add_handler_with_init(ShmHandler {
            my_id: ::std::usize::MAX,
            valid_formats: self.formats.clone(),
            log: self.log.clone(),
        });
        self.handler_id = Some(id);
    }
}

impl GlobalHandler<wl_shm::WlShm> for ShmGlobal {
    fn bind(&mut self, evqh: &mut EventLoopHandle, _: &Client, global: wl_shm::WlShm) {
        let hid = self.handler_id.expect("ShmGlobal was not initialized.");
        // register an handler for this shm
        evqh.register::<_, ShmHandler>(&global, hid);
        // and then the custom formats
        for f in &self.formats {
            global.format(*f);
        }
    }
}

struct ShmHandler {
    my_id: usize,
    valid_formats: Vec<wl_shm::Format>,
    log: ::slog::Logger,
}

impl Init for ShmHandler {
    fn init(&mut self, _evqh: &mut EventLoopHandle, index: usize) {
        self.my_id = index;
        debug!(self.log, "Init finished")
    }
}

impl wl_shm::Handler for ShmHandler {
    fn create_pool(&mut self, evqh: &mut EventLoopHandle, _client: &Client, shm: &wl_shm::WlShm,
                   pool: wl_shm_pool::WlShmPool, fd: RawFd, size: i32) {
        if size <= 0 {
            shm.post_error(
                wl_shm::Error::InvalidFd as u32,
                "Invalid size for a new wl_shm_pool.".into(),
            );
            return;
        }
        let mmap_pool = match Pool::new(fd, size as usize, self.log.clone()) {
            Ok(p) => p,
            Err(()) => {
                shm.post_error(wl_shm::Error::InvalidFd as u32, format!("Failed mmap of fd {}.", fd));
                return
            }
        };
        let arc_pool = Box::new(Arc::new(mmap_pool));
        evqh.register_with_destructor::<_, ShmHandler, ShmHandler>(&pool, self.my_id);
        pool.set_user_data(Box::into_raw(arc_pool) as *mut ());
    }
}

impl Destroy<wl_shm_pool::WlShmPool> for ShmHandler {
    fn destroy(pool: &wl_shm_pool::WlShmPool) {
        let arc_pool = unsafe { Box::from_raw(pool.get_user_data() as *mut Arc<Pool>) };
        drop(arc_pool)
    }
}

declare_handler!(ShmHandler, wl_shm::Handler, wl_shm::WlShm);

/// Details of the contents of a buffer relative to its pool
#[derive(Copy, Clone, Debug)]
pub struct BufferData {
    /// Offset of the start of the buffer relative to the beginning of the pool in bytes
    pub offset: i32,
    /// Wwidth of the buffer in bytes
    pub width: i32,
    /// Height of the buffer in bytes
    pub height: i32,
    /// Stride of the buffer in bytes
    pub stride: i32,
    /// Format used by this buffer
    pub format: wl_shm::Format,
}

struct InternalBufferData {
    pool: Arc<Pool>,
    data: BufferData,
}

impl wl_shm_pool::Handler for ShmHandler {
    fn create_buffer(&mut self, evqh: &mut EventLoopHandle, _client: &Client,
                     pool: &wl_shm_pool::WlShmPool, buffer: wl_buffer::WlBuffer, offset: i32, width: i32,
                     height: i32, stride: i32, format: wl_shm::Format) {
        if !self.valid_formats.contains(&format) {
            buffer.post_error(wl_shm::Error::InvalidFormat as u32, String::new());
            return;
        }
        let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
        let data = Box::into_raw(Box::new(InternalBufferData {
            pool: arc_pool.clone(),
            data: BufferData {
                offset: offset,
                width: width,
                height: height,
                stride: stride,
                format: format,
            },
        }));
        evqh.register_with_destructor::<_, ShmHandler, ShmHandler>(&buffer, self.my_id);
        buffer.set_user_data(data as *mut ());
    }

    fn resize(&mut self, _evqh: &mut EventLoopHandle, _client: &Client, pool: &wl_shm_pool::WlShmPool,
              size: i32) {
        let arc_pool = unsafe { &*(pool.get_user_data() as *mut Arc<Pool>) };
        match arc_pool.resize(size) {
            Ok(()) => {}
            Err(ResizeError::InvalidSize) => {
                pool.post_error(
                    wl_shm::Error::InvalidFd as u32,
                    "Invalid new size for a wl_shm_pool.".into(),
                );
            }
            Err(ResizeError::MremapFailed) => {
                pool.post_error(wl_shm::Error::InvalidFd as u32, "mremap failed.".into());
            }
        }
    }
}

impl Destroy<wl_buffer::WlBuffer> for ShmHandler {
    fn destroy(buffer: &wl_buffer::WlBuffer) {
        let buffer_data = unsafe { Box::from_raw(buffer.get_user_data() as *mut InternalBufferData) };
        drop(buffer_data)
    }
}

declare_handler!(ShmHandler, wl_shm_pool::Handler, wl_shm_pool::WlShmPool);

impl wl_buffer::Handler for ShmHandler {}

declare_handler!(ShmHandler, wl_buffer::Handler, wl_buffer::WlBuffer);
<|endoftext|>


<commit_before>//   Copyright 2014 Colin Sherratt
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

#![crate_name = "snowmew"]
#![feature(globs)]

extern crate "snowmew-core"         as _core;
extern crate "snowmew-graphics"     as _graphics;
extern crate "snowmew-loader"       as _loader;
extern crate "snowmew-physics"      as _physics;
extern crate "snowmew-position"     as _position;
extern crate "snowmew-render-mux"   as _render;
extern crate "snowmew-render-data"  as _render_data;

pub use _core::common::ObjectKey as ObjectKey;

pub mod render {
    pub use _render::RenderFactory as DefaultRender;
    pub use _render_data::{
        RenderData,
        Renderable
    };
    pub use _core::{
        RenderFactory,
        Render,
    };
}

pub mod graphics {
    pub use _graphics::{
        Drawable,
        Geometry,
        geometry,
        Graphics,
        GraphicsData,
        light,
        Light,
        material,
        Material,
        texture,
        Texture,
        texture_atlas,
        VertexBuffer,
        VertexBufferIter,
    };
}

pub mod position {
    pub use _position::{
        MatrixManager,
        Deltas,
        ComputedPositionGL,
        ComputedPosition,
        CalcPositionsCl,
        PositionData,
        Positions
    };
}

pub mod core {
    pub use _core::{
        DisplayConfig,
        Render,
        IOManager,
    };

    pub use _core::io::{
        InputHandle,
        Window,
    };

    pub use _core::game::Game;
}

pub mod common {
    pub use _core::common::{
        Common,
        CommonData,
        ObjectKey,
        Duplicate,
        Delete
    };
}

pub mod config  {
    pub use _core::SnowmewConfig as SnowmewConfig;
}

pub mod input {
    pub use _core::input::*;
    pub use _core::input_integrator::{
        InputIntegrator,
        InputIntegratorGameData,
        InputIntegratorState,
    };
    pub use _core::input_integrator::input_integrator as integrator;
}

pub mod debug {
    pub use _core::debugger::{
        Debugger,
        DebuggerGameData,
        debugger
    };
}<commit_msg>export table<commit_after>//   Copyright 2014 Colin Sherratt
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

#![crate_name = "snowmew"]
#![feature(globs)]

extern crate "snowmew-core"         as _core;
extern crate "snowmew-graphics"     as _graphics;
extern crate "snowmew-loader"       as _loader;
extern crate "snowmew-physics"      as _physics;
extern crate "snowmew-position"     as _position;
extern crate "snowmew-render-mux"   as _render;
extern crate "snowmew-render-data"  as _render_data;

pub use _core::table;
pub use _core::common::ObjectKey as ObjectKey;

pub mod render {
    pub use _render::RenderFactory as DefaultRender;
    pub use _render_data::{
        RenderData,
        Renderable
    };
    pub use _core::{
        RenderFactory,
        Render,
    };
}

pub mod graphics {
    pub use _graphics::{
        Drawable,
        Geometry,
        geometry,
        Graphics,
        GraphicsData,
        light,
        Light,
        material,
        Material,
        texture,
        Texture,
        texture_atlas,
        VertexBuffer,
        VertexBufferIter,
    };
}

pub mod position {
    pub use _position::{
        MatrixManager,
        Deltas,
        ComputedPositionGL,
        ComputedPosition,
        CalcPositionsCl,
        PositionData,
        Positions
    };
}

pub mod core {
    pub use _core::{
        DisplayConfig,
        Render,
        IOManager,
    };

    pub use _core::io::{
        InputHandle,
        Window,
    };

    pub use _core::game::Game;
}

pub mod common {
    pub use _core::common::{
        Common,
        CommonData,
        ObjectKey,
        Duplicate,
        Delete
    };
}

pub mod config  {
    pub use _core::SnowmewConfig as SnowmewConfig;
}

pub mod input {
    pub use _core::input::*;
    pub use _core::input_integrator::{
        InputIntegrator,
        InputIntegratorGameData,
        InputIntegratorState,
    };
    pub use _core::input_integrator::input_integrator as integrator;
}

pub mod debug {
    pub use _core::debugger::{
        Debugger,
        DebuggerGameData,
        debugger
    };
}<|endoftext|>


<commit_before>use rutorch::*;
use std::ops::{Index, IndexMut};
use std::slice;

macro_rules! impl_storage_impl {
    ($name:ident, $type:ident, $thname:ident) => {
        pub struct $name {
            pub t: *mut $thname,
        }
        impl Clone for $name {
            fn clone(&self) -> Self {
                unsafe { concat_idents!($thname, _retain)(self.t)};
                $name {t: self.t }
            }
        }
        impl $name {
            pub fn new() -> Self {
                unsafe { $name { t: concat_idents!($thname, _new)() } }
            }
            pub fn len(&self) -> usize {
                let t = unsafe {(*self.t).size };
                t as usize
            }
            pub fn with_capacity(size: usize) -> Self {
                unsafe { $name { t: concat_idents!($thname, _newWithSize)(size as isize) } }
            }
            pub fn with_data<D>(data: D) -> Self
                where D: AsRef<[$type]>
            {
                let data = data.as_ref();
                let mut store = unsafe { $name {
                    t: concat_idents!($thname, _newWithSize)(data.len() as isize)
                } };
                for i in 0..data.len() {
                    store[i as isize] = data[i];
                }
                store
            }
            pub fn into_slice(&self) -> &[$type] {
                unsafe { slice::from_raw_parts((*self.t).data, (*self.t).size as usize) }
            }
            pub fn into_slice_mut(&mut self) -> &mut [$type] {
                unsafe { slice::from_raw_parts_mut((*self.t).data, (*self.t).size as usize) }
            }
            pub fn iter(&self) -> slice::Iter<$type> {
                self.into_slice().iter()
            }
            pub fn iter_mut(&mut self) -> slice::IterMut<$type> {
                self.into_slice_mut().iter_mut()
            }
        }
        impl Drop for $name {
            fn drop(&mut self) {
                unsafe { concat_idents!($thname, _free)(self.t) }
            }
        }
        impl Index<isize> for $name {
            type Output = $type;
            fn index(&self, idx: isize) -> &Self::Output {
                unsafe { &*(*self.t).data.offset(idx) }
            }
        }
        impl IndexMut<isize> for $name {
            fn index_mut(&mut self, idx: isize) -> &mut Self::Output {
                unsafe { &mut *(*self.t).data.offset(idx) }
            }
        }
    }
}

impl_storage_impl!(FloatStorage, f32, THFloatStorage);
impl_storage_impl!(DoubleStorage, f64, THDoubleStorage);
impl_storage_impl!(LongStorage, i64, THLongStorage);
impl_storage_impl!(ByteStorage, u8, THByteStorage);
<commit_msg>implement range indexing and default to usize index<commit_after>use rutorch::*;
use std::ops::{Index, IndexMut};
use std::{slice, ops};

macro_rules! impl_storage_impl {
    ($name:ident, $type:ident, $thname:ident) => {
        pub struct $name {
            pub t: *mut $thname,
        }
        impl Clone for $name {
            fn clone(&self) -> Self {
                unsafe { concat_idents!($thname, _retain)(self.t)};
                $name {t: self.t }
            }
        }
        impl $name {
            pub fn new() -> Self {
                unsafe { $name { t: concat_idents!($thname, _new)() } }
            }
            pub fn len(&self) -> usize {
                let t = unsafe {(*self.t).size };
                t as usize
            }
            pub fn with_capacity(size: usize) -> Self {
                unsafe { $name { t: concat_idents!($thname, _newWithSize)(size as isize) } }
            }
            pub fn with_data<D>(data: D) -> Self
                where D: AsRef<[$type]>
            {
                let data = data.as_ref();
                let mut store = unsafe { $name {
                    t: concat_idents!($thname, _newWithSize)(data.len() as isize)
                } };
                for i in 0..data.len() {
                    store[i] = data[i];
                }
                store
            }
            pub fn into_slice(&self) -> &[$type] {
                unsafe { slice::from_raw_parts((*self.t).data, (*self.t).size as usize) }
            }
            pub fn into_slice_mut(&mut self) -> &mut [$type] {
                unsafe { slice::from_raw_parts_mut((*self.t).data, (*self.t).size as usize) }
            }
            pub fn iter(&self) -> slice::Iter<$type> {
                self.into_slice().iter()
            }
            pub fn iter_mut(&mut self) -> slice::IterMut<$type> {
                self.into_slice_mut().iter_mut()
            }
        }
        impl ops::Deref for $name {
            type Target = [$type];

            fn deref(&self) -> &Self::Target {
                self.into_slice()
            }
        }
        impl ops::DerefMut for $name {
            fn deref_mut (&mut self) -> &mut Self::Target {
                self.into_slice_mut()
            }
        }
        impl Drop for $name {
            fn drop(&mut self) {
                unsafe { concat_idents!($thname, _free)(self.t) }
            }
        }
        impl Index<usize> for $name {
            type Output = $type;
            fn index(&self, idx: usize) -> &Self::Output {
                &(**self)[idx]
            }
        }
        impl Index<ops::Range<usize>> for $name {
            type Output = [$type];
            fn index(&self, idx: ops::Range<usize>) -> &Self::Output {
                Index::index(&**self, idx)
            }
        }
        impl Index<ops::RangeTo<usize>> for $name {
            type Output = [$type];
            fn index(&self, idx: ops::RangeTo<usize>) -> &Self::Output {
                Index::index(&**self, idx)
            }
        }
        impl Index<ops::RangeFrom<usize>> for $name {
            type Output = [$type];
            fn index(&self, idx: ops::RangeFrom<usize>) -> &Self::Output {
                Index::index(&**self, idx)
            }
        }
        impl Index<ops::RangeFull> for $name {
            type Output = [$type];
            fn index(&self, _idx: ops::RangeFull) -> &Self::Output {
                self
            }
        }
        impl IndexMut<usize> for $name {
            fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
                &mut (**self)[idx]
            }
        }
    }
}

impl_storage_impl!(FloatStorage, f32, THFloatStorage);
impl_storage_impl!(DoubleStorage, f64, THDoubleStorage);
impl_storage_impl!(LongStorage, i64, THLongStorage);
impl_storage_impl!(ByteStorage, u8, THByteStorage);
<|endoftext|>


<commit_before>//! Utilities for the test suite.

use signal::Signal;

/// Trace equality of two signals.
pub fn signal_eq<T>(a: &Signal<T>, b: &Signal<T>) -> Signal<bool>
    where T: PartialEq + Clone + Send + Sync + 'static
{
    lift!(|a, b| a == b, a, b)
}

/// Self-tests.
mod test {
    use signal::Signal;
    use stream::{ Stream, Sink };
    use super::signal_eq;

    #[test]
    fn signal_eq_const() {
        let a = Signal::new(3);
        let eq = signal_eq(&a, &a);
        assert!(eq.sample());
    }

    #[test]
    fn signal_eq_piecewise_const() {
        let sink = Sink::new();
        let sig = sink.stream().hold(4);
        let eq = signal_eq(&sig, &sig);
        for &a in &[1, 2, 3] {
            sink.send(a);
            assert!(eq.sample());
        }
    }

    #[test]
    fn signal_eq_algebraic() {
        let eq = signal_eq(&Stream::never().hold(3), &Signal::new(3));
        assert!(eq.sample());
    }
}
<commit_msg>Shortcut for the identity function<commit_after>//! Utilities for the test suite.

use signal::Signal;

/// The identity function.
pub fn id<T>(t: T) -> T { t }

/// Trace equality of two signals.
pub fn signal_eq<T>(a: &Signal<T>, b: &Signal<T>) -> Signal<bool>
    where T: PartialEq + Clone + Send + Sync + 'static
{
    lift!(|a, b| a == b, a, b)
}

/// Self-tests.
mod test {
    use signal::Signal;
    use stream::{ Stream, Sink };
    use super::signal_eq;

    #[test]
    fn signal_eq_const() {
        let a = Signal::new(3);
        let eq = signal_eq(&a, &a);
        assert!(eq.sample());
    }

    #[test]
    fn signal_eq_piecewise_const() {
        let sink = Sink::new();
        let sig = sink.stream().hold(4);
        let eq = signal_eq(&sig, &sig);
        for &a in &[1, 2, 3] {
            sink.send(a);
            assert!(eq.sample());
        }
    }

    #[test]
    fn signal_eq_algebraic() {
        let eq = signal_eq(&Stream::never().hold(3), &Signal::new(3));
        assert!(eq.sample());
    }
}
<|endoftext|>


<commit_before>use std::cmp::Ordering;
use angle::Angle;
use point::Point;
use events::{Events, EventKind, Circle};
use beach::{Beach, Arc, ArcStart};
use diagram::{Diagram, Vertex, Face};

struct Builder {
    events: Events,
    beach: Beach,
    diagram: Diagram,
    scan_theta: Angle,
    temporary: Vec<Vertex>,
}

impl Builder {
    fn new(points: &[Point]) -> Result<Self, Error> {
        if points.len() < 2 {
            return Err(Error::FewPoints);
        }
        let mut builder = Builder {
            events: Events::default(),
            beach: Beach::default(),
            diagram: Diagram::default(),
            scan_theta: Angle::from(0.0),
            temporary: Vec::new(),
        };
        for &point in points {
            let face = builder.diagram.add_face(point);
            builder.events.add_site(face, point);
        }
        Ok(builder)
    }

    pub fn build(mut self, relaxations: usize) -> Result<Diagram, Error> {
        self.build_iter();
        for _ in 1..relaxations {
            self.reset();
            self.build_iter();
        }
        self.finish();
        Ok(self.diagram)
    }

    fn build_iter(&mut self) {
        while let Some(event) = self.events.pop() {
            //println!("{:#?}", event);
            let point = event.point;
            self.scan_theta = *point.theta();
            match event.kind {
                EventKind::Site(face) => self.handle_site_event(face, point),
                EventKind::Circle(event) => self.handle_circle_event(event),
            }
        }
    }

    fn reset(&mut self) {
        self.diagram.reset_faces();
        self.diagram.clear_vertices();
        self.diagram.clear_edges();
        for face in self.diagram.faces() {
            self.events.add_site(face, *self.diagram.face_point(face));
        }
        self.temporary.clear();
        self.events.clear();
        self.beach.clear();
        self.scan_theta = Angle::from(0.0);
    }

    fn arc_point(&self, arc: Arc) -> &Point {
        &self.diagram.face_point(self.beach.face(arc))
    }

    fn create_temporary(&mut self, arc0: Arc, arc1: Arc) {
        let index = self.temporary.len();
        self.temporary.push(Vertex::invalid());
        self.beach.set_start(arc0, ArcStart::Temporary(index));
        self.beach.set_start(arc1, ArcStart::Temporary(index));
    }

    fn handle_site_event(&mut self, face: Face, point: Point) {
        if let Some(mut arc) = self.beach.root() {
            if self.beach.len() == 1 {
                self.beach.insert_after(Some(arc), face);
                let arc0 = self.beach.first();
                let arc1 = self.beach.last();
                self.create_temporary(arc0, arc1);
                return;
            }
            let mut use_tree = true;
            loop {
                let prev_arc = self.beach.prev(arc);
                let next_arc = self.beach.next(arc);
                let phi_start = self.arcs_intersection(prev_arc, arc);
                let phi_end = self.arcs_intersection(arc, next_arc);
                match point.phi().is_in_range(phi_start, phi_end) {
                    Ordering::Less => {
                        if use_tree {
                            if let Some(left) = self.beach.left(arc) {
                                arc = left;
                            } else {
                                // the tree has failed us, do the linear search from now on.
                                arc = self.beach.last();
                                use_tree = false;
                            }
                        } else {
                            arc = self.beach.prev(arc);
                        }
                    },
                    Ordering::Greater => {
                        if use_tree {
                            if let Some(right) = self.beach.right(arc) {
                                arc = right;
                            } else {
                                // the tree has failed us, do the linear search from now on.
                                arc = self.beach.first();
                                use_tree = false;
                            }
                        } else {
                            arc = self.beach.next(arc);
                        }
                    },
                    Ordering::Equal => {
                        self.detach_circle(arc);
                        let twin = {
                            let face = self.beach.face(arc);
                            let a = if prev_arc == self.beach.last() {
                                None
                            } else {
                                Some(prev_arc)
                            };
                            self.beach.insert_after(a, face)
                        };
                        let new_arc = self.beach.insert_after(Some(twin), face);
                        self.create_temporary(twin, new_arc);
                        self.attach_circle(prev_arc, twin, new_arc, point.theta().value());
                        self.attach_circle(new_arc, arc, next_arc, point.theta().value());
                        if self.detach_circle(prev_arc) {
                            let prev_prev = self.beach.prev(prev_arc);
                            self.attach_circle(prev_prev, prev_arc, twin, ::std::f64::MIN);
                        }
                        break;
                    }
                }
            }
        } else {
            self.beach.insert_after(None, face);
        }
    }

    fn merge_arcs(&mut self, arc0: Arc, arc1: Arc, arc2: Arc, vertex: Option<Vertex>) {
        let (face0, face1, face2) = (self.beach.face(arc0), self.beach.face(arc1), self.beach.face(arc2));
        if face0 != face1 && face1 != face2 && face2 != face0 {
            let theta = self.scan_theta.value();
            if self.attach_circle(arc0, arc1, arc2, theta) {
                if let Some(vertex) = vertex {
                    self.beach.set_start(arc1, ArcStart::Vertex(vertex));
                }
            }
        }
    }

    fn edge_from_arc(&mut self, arc: Arc, end: Vertex) {
        match self.beach.start(arc) {
            ArcStart::Temporary(index) => {
                let start = self.temporary[index];
                if start.is_invalid() {
                    self.temporary[index] = end;
                } else {
                    self.diagram.add_edge(start, end);
                }
            },
            ArcStart::Vertex(start) => {
                self.diagram.add_edge(start, end);
            },
            ArcStart::None => {},
        };
    }

    fn handle_circle_event(&mut self, event: Circle) {
        if self.events.is_invalid(event) {
            return;
        }
        let arc = self.events.arc(event);
        assert_eq!(self.beach.circle(arc), Some(event));
        let prev = self.beach.prev(arc);
        let next = self.beach.next(arc);
        self.detach_circle(prev);
        self.detach_circle(next);
        let point = self.events.center(event);
        let vertex = self.diagram.add_vertex(point, &[self.beach.face(prev), self.beach.face(arc), self.beach.face(next)]);
        self.edge_from_arc(prev, vertex);
        self.edge_from_arc(arc, vertex);
        self.beach.remove(arc);
        if self.beach.prev(prev) == next {
            self.edge_from_arc(next, vertex);
            self.beach.remove(prev);
            self.beach.remove(next);
        } else {
            let prev_prev = self.beach.prev(prev);
            let next_next = self.beach.next(next);
            self.merge_arcs(prev_prev, prev, next, Some(vertex));
            self.merge_arcs(prev, next, next_next, None);
        }
    }

    fn arcs_intersection(&self, arc0: Arc, arc1: Arc) -> f64 {
        let point0 = self.arc_point(arc0);
        let theta0 = point0.theta();
        let phi0 = point0.phi();
        if theta0.value() >= self.scan_theta.value() {
            return phi0.value();
        }
        let point1 = self.arc_point(arc1);
        let theta1 = point1.theta();
        let phi1 = point1.phi();
        if theta1.value() >= self.scan_theta.value() {
            return phi1.value();
        }
        let u1 = (self.scan_theta.cos() - theta1.cos()) * theta0.sin();
        let u2 = (self.scan_theta.cos() - theta0.cos()) * theta1.sin();
        let a1 = u1 * phi0.cos();
        let a2 = u2 * phi1.cos();
        let a = a1 - a2;
        let b1 = u1 * phi0.sin();
        let b2 = u2 * phi1.sin();
        let b = b1 - b2;
        let c = (theta0.cos() - theta1.cos()) * self.scan_theta.sin();
        let length = (a * a + b * b).sqrt();
        if a.abs() > length || c.abs() > length {
            unreachable!()
        } else {
            let gamma = a.atan2(b);
            let phi_int_plus_gamma1 = (c / length).asin();
            Angle::wrap(phi_int_plus_gamma1 - gamma)
        }
    }

    fn attach_circle(&mut self, arc0: Arc, arc1: Arc, arc2: Arc, min_theta: f64) -> bool {
        let p1 = self.arc_point(arc1).position();
        let p01 = self.arc_point(arc0).position() - p1;
        let p21 = self.arc_point(arc2).position() - p1;
        let cross = p01.cross(p21);
        let center = Point::from_cartesian(cross.x, cross.y, cross.z);
        let radius = center.distance(&self.arc_point(arc0));
        let theta = center.theta().value() + radius;
        if theta >= min_theta {
            let point = Point::from_angles(Angle::from(theta), center.phi().clone());
            let circle = self.events.add_circle(arc1, center, point);
            self.beach.set_circle(arc1, Some(circle));
            true
        } else {
            false
        }
    }

    fn detach_circle(&mut self, arc: Arc) -> bool {
        if let Some(event) = self.beach.circle(arc) {
            self.events.set_invalid(event, true);
            self.beach.set_circle(arc, None);
            true
        } else {
            false
        }
    }

    fn finish(&mut self) {
        for edge in self.diagram.edges() {
            let mut common = Vec::new();
            let (vertex0, vertex1) = self.diagram.edge_vertices(edge);
            for &face0 in self.diagram.vertex_faces(vertex0) {
                for &face1 in self.diagram.vertex_faces(vertex1) {
                    if face0 == face1 {
                        common.push(face0);
                    }
                }
            }
            assert_eq!(common.len(), 2);
            self.diagram.set_edge_faces(edge, common[0], common[1]);
        }
    }
}

#[derive(PartialEq, Debug)]
pub enum Error {
    FewPoints,
}

pub fn build(points: &[Point], relaxations: usize) -> Result<Diagram, Error> {
    Builder::new(points)?.build(relaxations)
}

<commit_msg>Remove useless checks in arcs intersection<commit_after>use std::cmp::Ordering;
use angle::Angle;
use point::Point;
use events::{Events, EventKind, Circle};
use beach::{Beach, Arc, ArcStart};
use diagram::{Diagram, Vertex, Face};

struct Builder {
    events: Events,
    beach: Beach,
    diagram: Diagram,
    scan_theta: Angle,
    temporary: Vec<Vertex>,
}

impl Builder {
    fn new(points: &[Point]) -> Result<Self, Error> {
        if points.len() < 2 {
            return Err(Error::FewPoints);
        }
        let mut builder = Builder {
            events: Events::default(),
            beach: Beach::default(),
            diagram: Diagram::default(),
            scan_theta: Angle::from(0.0),
            temporary: Vec::new(),
        };
        for &point in points {
            let face = builder.diagram.add_face(point);
            builder.events.add_site(face, point);
        }
        Ok(builder)
    }

    pub fn build(mut self, relaxations: usize) -> Result<Diagram, Error> {
        self.build_iter();
        for _ in 1..relaxations {
            self.reset();
            self.build_iter();
        }
        self.finish();
        Ok(self.diagram)
    }

    fn build_iter(&mut self) {
        while let Some(event) = self.events.pop() {
            //println!("{:#?}", event);
            let point = event.point;
            self.scan_theta = *point.theta();
            match event.kind {
                EventKind::Site(face) => self.handle_site_event(face, point),
                EventKind::Circle(event) => self.handle_circle_event(event),
            }
        }
    }

    fn reset(&mut self) {
        self.diagram.reset_faces();
        self.diagram.clear_vertices();
        self.diagram.clear_edges();
        for face in self.diagram.faces() {
            self.events.add_site(face, *self.diagram.face_point(face));
        }
        self.temporary.clear();
        self.events.clear();
        self.beach.clear();
        self.scan_theta = Angle::from(0.0);
    }

    fn arc_point(&self, arc: Arc) -> &Point {
        &self.diagram.face_point(self.beach.face(arc))
    }

    fn create_temporary(&mut self, arc0: Arc, arc1: Arc) {
        let index = self.temporary.len();
        self.temporary.push(Vertex::invalid());
        self.beach.set_start(arc0, ArcStart::Temporary(index));
        self.beach.set_start(arc1, ArcStart::Temporary(index));
    }

    fn handle_site_event(&mut self, face: Face, point: Point) {
        if let Some(mut arc) = self.beach.root() {
            if self.beach.len() == 1 {
                self.beach.insert_after(Some(arc), face);
                let arc0 = self.beach.first();
                let arc1 = self.beach.last();
                self.create_temporary(arc0, arc1);
                return;
            }
            let mut use_tree = true;
            loop {
                let prev_arc = self.beach.prev(arc);
                let next_arc = self.beach.next(arc);
                let phi_start = self.arcs_intersection(prev_arc, arc);
                let phi_end = self.arcs_intersection(arc, next_arc);
                match point.phi().is_in_range(phi_start, phi_end) {
                    Ordering::Less => {
                        if use_tree {
                            if let Some(left) = self.beach.left(arc) {
                                arc = left;
                            } else {
                                // the tree has failed us, do the linear search from now on.
                                arc = self.beach.last();
                                use_tree = false;
                            }
                        } else {
                            arc = self.beach.prev(arc);
                        }
                    },
                    Ordering::Greater => {
                        if use_tree {
                            if let Some(right) = self.beach.right(arc) {
                                arc = right;
                            } else {
                                // the tree has failed us, do the linear search from now on.
                                arc = self.beach.first();
                                use_tree = false;
                            }
                        } else {
                            arc = self.beach.next(arc);
                        }
                    },
                    Ordering::Equal => {
                        self.detach_circle(arc);
                        let twin = {
                            let face = self.beach.face(arc);
                            let a = if prev_arc == self.beach.last() {
                                None
                            } else {
                                Some(prev_arc)
                            };
                            self.beach.insert_after(a, face)
                        };
                        let new_arc = self.beach.insert_after(Some(twin), face);
                        self.create_temporary(twin, new_arc);
                        self.attach_circle(prev_arc, twin, new_arc, point.theta().value());
                        self.attach_circle(new_arc, arc, next_arc, point.theta().value());
                        if self.detach_circle(prev_arc) {
                            let prev_prev = self.beach.prev(prev_arc);
                            self.attach_circle(prev_prev, prev_arc, twin, ::std::f64::MIN);
                        }
                        break;
                    }
                }
            }
        } else {
            self.beach.insert_after(None, face);
        }
    }

    fn merge_arcs(&mut self, arc0: Arc, arc1: Arc, arc2: Arc, vertex: Option<Vertex>) {
        let (face0, face1, face2) = (self.beach.face(arc0), self.beach.face(arc1), self.beach.face(arc2));
        if face0 != face1 && face1 != face2 && face2 != face0 {
            let theta = self.scan_theta.value();
            if self.attach_circle(arc0, arc1, arc2, theta) {
                if let Some(vertex) = vertex {
                    self.beach.set_start(arc1, ArcStart::Vertex(vertex));
                }
            }
        }
    }

    fn edge_from_arc(&mut self, arc: Arc, end: Vertex) {
        match self.beach.start(arc) {
            ArcStart::Temporary(index) => {
                let start = self.temporary[index];
                if start.is_invalid() {
                    self.temporary[index] = end;
                } else {
                    self.diagram.add_edge(start, end);
                }
            },
            ArcStart::Vertex(start) => {
                self.diagram.add_edge(start, end);
            },
            ArcStart::None => {},
        };
    }

    fn handle_circle_event(&mut self, event: Circle) {
        if self.events.is_invalid(event) {
            return;
        }
        let arc = self.events.arc(event);
        assert_eq!(self.beach.circle(arc), Some(event));
        let prev = self.beach.prev(arc);
        let next = self.beach.next(arc);
        self.detach_circle(prev);
        self.detach_circle(next);
        let point = self.events.center(event);
        let vertex = self.diagram.add_vertex(point, &[self.beach.face(prev), self.beach.face(arc), self.beach.face(next)]);
        self.edge_from_arc(prev, vertex);
        self.edge_from_arc(arc, vertex);
        self.beach.remove(arc);
        if self.beach.prev(prev) == next {
            self.edge_from_arc(next, vertex);
            self.beach.remove(prev);
            self.beach.remove(next);
        } else {
            let prev_prev = self.beach.prev(prev);
            let next_next = self.beach.next(next);
            self.merge_arcs(prev_prev, prev, next, Some(vertex));
            self.merge_arcs(prev, next, next_next, None);
        }
    }

    fn arcs_intersection(&self, arc0: Arc, arc1: Arc) -> f64 {
        let point0 = self.arc_point(arc0);
        let theta0 = point0.theta();
        let phi0 = point0.phi();
        let point1 = self.arc_point(arc1);
        let theta1 = point1.theta();
        let phi1 = point1.phi();
        let u1 = (self.scan_theta.cos() - theta1.cos()) * theta0.sin();
        let u2 = (self.scan_theta.cos() - theta0.cos()) * theta1.sin();
        let a1 = u1 * phi0.cos();
        let a2 = u2 * phi1.cos();
        let a = a1 - a2;
        let b1 = u1 * phi0.sin();
        let b2 = u2 * phi1.sin();
        let b = b1 - b2;
        let c = (theta0.cos() - theta1.cos()) * self.scan_theta.sin();
        let length = (a * a + b * b).sqrt();
        if a.abs() > length || c.abs() > length {
            unreachable!()
        } else {
            let gamma = a.atan2(b);
            let phi_int_plus_gamma1 = (c / length).asin();
            Angle::wrap(phi_int_plus_gamma1 - gamma)
        }
    }

    fn attach_circle(&mut self, arc0: Arc, arc1: Arc, arc2: Arc, min_theta: f64) -> bool {
        let p1 = self.arc_point(arc1).position();
        let p01 = self.arc_point(arc0).position() - p1;
        let p21 = self.arc_point(arc2).position() - p1;
        let cross = p01.cross(p21);
        let center = Point::from_cartesian(cross.x, cross.y, cross.z);
        let radius = center.distance(&self.arc_point(arc0));
        let theta = center.theta().value() + radius;
        if theta >= min_theta {
            let point = Point::from_angles(Angle::from(theta), center.phi().clone());
            let circle = self.events.add_circle(arc1, center, point);
            self.beach.set_circle(arc1, Some(circle));
            true
        } else {
            false
        }
    }

    fn detach_circle(&mut self, arc: Arc) -> bool {
        if let Some(event) = self.beach.circle(arc) {
            self.events.set_invalid(event, true);
            self.beach.set_circle(arc, None);
            true
        } else {
            false
        }
    }

    fn finish(&mut self) {
        for edge in self.diagram.edges() {
            let mut common = Vec::new();
            let (vertex0, vertex1) = self.diagram.edge_vertices(edge);
            for &face0 in self.diagram.vertex_faces(vertex0) {
                for &face1 in self.diagram.vertex_faces(vertex1) {
                    if face0 == face1 {
                        common.push(face0);
                    }
                }
            }
            assert_eq!(common.len(), 2);
            self.diagram.set_edge_faces(edge, common[0], common[1]);
        }
    }
}

#[derive(PartialEq, Debug)]
pub enum Error {
    FewPoints,
}

pub fn build(points: &[Point], relaxations: usize) -> Result<Diagram, Error> {
    Builder::new(points)?.build(relaxations)
}

<|endoftext|>


<commit_before>extern crate widestring;
extern crate winapi;

use crate::{Browser, Error, ErrorKind, Result};
pub use std::os::windows::process::ExitStatusExt;
use std::process::ExitStatus;
use std::ptr;
use widestring::U16CString;

/// Deal with opening of browsers on Windows, using [`ShellExecuteW`](
/// https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutew)
/// fucntion.
#[inline]
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<ExitStatus> {
    use winapi::shared::winerror::SUCCEEDED;
    use winapi::um::combaseapi::{CoInitializeEx, CoUninitialize};
    use winapi::um::objbase::{COINIT_APARTMENTTHREADED, COINIT_DISABLE_OLE1DDE};
    use winapi::um::shellapi::ShellExecuteW;
    use winapi::um::winuser::SW_SHOWNORMAL;
    match browser {
        Browser::Default => {
            static OPEN: &[u16] = &['o' as u16, 'p' as u16, 'e' as u16, 'n' as u16, 0x0000];
            let url =
                U16CString::from_str(url).map_err(|e| Error::new(ErrorKind::InvalidInput, e))?;
            let code = unsafe {
                let coinitializeex_result = CoInitializeEx(
                    ptr::null_mut(),
                    COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE,
                );
                let code = ShellExecuteW(
                    ptr::null_mut(),
                    OPEN.as_ptr(),
                    url.as_ptr(),
                    ptr::null(),
                    ptr::null(),
                    SW_SHOWNORMAL,
                ) as usize as i32;
                if SUCCEEDED(coinitializeex_result) {
                    CoUninitialize();
                }
                code
            };
            if code > 32 {
                Ok(ExitStatus::from_raw(0))
            } else {
                Err(Error::last_os_error())
            }
        }
        _ => Err(Error::new(
            ErrorKind::NotFound,
            "Only the default browser is supported on this platform right now",
        )),
    }
}

#[test]
fn test_open_internet_explorer() {
    assert!(open_browser_internal(Browser::InternetExplorer, "http://github.com").is_ok());
}
<commit_msg>Ignore IE test case for windows for now<commit_after>extern crate widestring;
extern crate winapi;

use crate::{Browser, Error, ErrorKind, Result};
pub use std::os::windows::process::ExitStatusExt;
use std::process::ExitStatus;
use std::ptr;
use widestring::U16CString;

/// Deal with opening of browsers on Windows, using [`ShellExecuteW`](
/// https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutew)
/// fucntion.
#[inline]
pub fn open_browser_internal(browser: Browser, url: &str) -> Result<ExitStatus> {
    use winapi::shared::winerror::SUCCEEDED;
    use winapi::um::combaseapi::{CoInitializeEx, CoUninitialize};
    use winapi::um::objbase::{COINIT_APARTMENTTHREADED, COINIT_DISABLE_OLE1DDE};
    use winapi::um::shellapi::ShellExecuteW;
    use winapi::um::winuser::SW_SHOWNORMAL;
    match browser {
        Browser::Default => {
            static OPEN: &[u16] = &['o' as u16, 'p' as u16, 'e' as u16, 'n' as u16, 0x0000];
            let url =
                U16CString::from_str(url).map_err(|e| Error::new(ErrorKind::InvalidInput, e))?;
            let code = unsafe {
                let coinitializeex_result = CoInitializeEx(
                    ptr::null_mut(),
                    COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE,
                );
                let code = ShellExecuteW(
                    ptr::null_mut(),
                    OPEN.as_ptr(),
                    url.as_ptr(),
                    ptr::null(),
                    ptr::null(),
                    SW_SHOWNORMAL,
                ) as usize as i32;
                if SUCCEEDED(coinitializeex_result) {
                    CoUninitialize();
                }
                code
            };
            if code > 32 {
                Ok(ExitStatus::from_raw(0))
            } else {
                Err(Error::last_os_error())
            }
        }
        _ => Err(Error::new(
            ErrorKind::NotFound,
            "Only the default browser is supported on this platform right now",
        )),
    }
}

#[test]
#[ignore]
fn test_open_internet_explorer() {
    assert!(open_browser_internal(Browser::InternetExplorer, "http://github.com").is_ok());
}
<|endoftext|>


<commit_before>use crate::backtrace::Backtrace;
use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};

#[repr(transparent)]
pub struct MessageError<M>(pub M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

#[repr(transparent)]
pub struct DisplayError<M>(pub M);

impl<M> Debug for DisplayError<M>
where
    M: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> Display for DisplayError<M>
where
    M: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for DisplayError<M> where M: Display + 'static {}

#[repr(transparent)]
pub struct BoxedError(pub Box<dyn StdError + Send + Sync>);

impl Debug for BoxedError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl Display for BoxedError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl StdError for BoxedError {
    #[cfg(backtrace)]
    fn backtrace(&self) -> Option<&Backtrace> {
        self.0.backtrace()
    }

    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        self.0.source()
    }
}
<commit_msg>Avoid unused import when building without backtrace<commit_after>use std::error::Error as StdError;
use std::fmt::{self, Debug, Display};

#[repr(transparent)]
pub struct MessageError<M>(pub M);

impl<M> Debug for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl<M> Display for MessageError<M>
where
    M: Display + Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for MessageError<M> where M: Display + Debug + 'static {}

#[repr(transparent)]
pub struct DisplayError<M>(pub M);

impl<M> Debug for DisplayError<M>
where
    M: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> Display for DisplayError<M>
where
    M: Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl<M> StdError for DisplayError<M> where M: Display + 'static {}

#[repr(transparent)]
pub struct BoxedError(pub Box<dyn StdError + Send + Sync>);

impl Debug for BoxedError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(&self.0, f)
    }
}

impl Display for BoxedError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Display::fmt(&self.0, f)
    }
}

impl StdError for BoxedError {
    #[cfg(backtrace)]
    fn backtrace(&self) -> Option<&crate::backtrace::Backtrace> {
        self.0.backtrace()
    }

    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        self.0.source()
    }
}
<|endoftext|>