<commit_before>use std::cast;
use std::mem::size_of;
use std::raw::Slice;
use std::num::Zero;
use std::rc::Rc;
use sync::Mutex;

mod buffer;
mod schema;

static LEAF_MARKER: u8 = 0b111111111;
static BRANCH_MARKER: u8 = 0b0;

/* simple type alias to simplify signatures */
type ConcurrentManager = Rc<Mutex<buffer::BufferManager>>;

struct BTree<'a, K> {
	segment: u64,
	manager: ConcurrentManager,
	tree: LazyNode,
	next_free_page: u64,
}

impl<'a, K: TotalOrd + Zero> BTree<'a, K> {
	fn new<'b>(segment_id: u64, manager: ConcurrentManager) -> BTree<'b, K> {
		BTree {
			segment: segment_id,
			manager: manager,
			tree: LazyNode::new(1),
			next_free_page: 2,
		}
	}

	fn insert(&mut self, key: K, value: schema::TID) {
		let node = self.tree.load(self.manager.clone());
		// try insertion and see if the root was split
		let candidate = match node {
			Branch(mut n) => n.insert_value(self, key, value),
			Leaf(mut n) => n.insert_value(key, value),
		};
		// set new tree root if it was split
		match candidate {
			Some(new_node) => self.tree = new_node,
			None => (),
		}
	}

	fn next_page(&mut self) -> u64 {
		let n = self.next_free_page;
		self.next_free_page += 1;
		n
	}

	fn create_branch_page(&mut self) -> LazyNode {
		let next = self.next_page();
		let page_path = buffer::join_segment(self.segment, next);
		let mut manager = self.manager.lock();
		let pagelock = manager.fix_page(page_path).unwrap();
		let mut page = pagelock.write();
		let data = page.get_mut_data();
		data[0] = BRANCH_MARKER;
		LazyNode::new(page_path)
	}

	fn create_leaf_page(&mut self) -> LazyNode {
		let next = self.next_page();
		let page_path = buffer::join_segment(self.segment, next);
		let mut manager = self.manager.lock();
		let pagelock = manager.fix_page(page_path).unwrap();
		let mut page = pagelock.write();
		let data = page.get_mut_data();
		// marker to be a leaf page
		data[0] = LEAF_MARKER;
		LazyNode::new(page_path)

	}

	fn erase(&mut self, key: K) {
	}

	fn lookup(self, key: K) -> Option<schema::TID> {
		None
	}
}

/* a placeholder for the actual page */
struct LazyNode {
	page_id: u64,
}

// TODO implement Drop to unfix page
impl LazyNode {
	fn new(page_id: u64) -> LazyNode {
		LazyNode {page_id: page_id}
	}

	/*
	 * As this is just a placeholder, return the actual node that his is
	 * representing
	 */
	fn load<'a, K: TotalOrd + Zero>(&self, manager: ConcurrentManager) -> Node<'a, K> {
		let pagelock = {
			let mut managerlock = manager.lock();
			managerlock.fix_page(self.page_id).unwrap()
		};
		let mut is_leaf = false;

		{
			let page = pagelock.read();
			let page_data = page.get_data();
			if page_data[0] == LEAF_MARKER {
				is_leaf = true;
			} else if page_data[0] == BRANCH_MARKER {
				is_leaf = false;
			} else {
				fail!("Invalid page type");
			}
		}
		if is_leaf {
			Leaf(LeafNode::new(manager, pagelock))
		} else {
			//Branch(BranchNode::new(page_data))
			fail!("TODO, implement this")
		}
	}

}

/* a node might either be an inner node (branch node) or a leaf node (LeafNode) */
enum Node<'a, K> {
	Branch(BranchNode<'a, K>),
	Leaf(LeafNode<'a, K>),
}

/* leaf pages consist mainly of leaf entries which are (K, TID) pairs */
struct LeafEntry<K> {
	key: K,
	tid: schema::TID,
}

/* branch pages consist mainly of branch entries which are (K, page_id) pairs */
struct BranchEntry<K> {
	key: K,
	page_id: u64,
}

struct LeafNode<'a, K> {
	capacity: uint,
	entries: &'a mut [LeafEntry<K>],
	manager: ConcurrentManager,
	frame: buffer::ConcurrentFrame,
}

impl<'a, K: TotalOrd + Zero> LeafNode<'a, K> {
	fn new(manager: ConcurrentManager, frame: buffer::ConcurrentFrame) -> LeafNode<'a, K> {
		let mut r = {
			let framelock = frame.read();
			let page = framelock.get_data();
			// first byte is a Leaf/Branch marker
			let entry_size = size_of::<LeafEntry<K>>();
			let entry_num = (page.len() - size_of::<u8>()) / entry_size;

			let mut entries: &mut[LeafEntry<K>] = unsafe {
				cast::transmute(
					Slice::<LeafEntry<K>> {
						data: page.as_ptr() as *() as *LeafEntry<K>,
						len: entry_num,
					}
				)
			};
		entries
		};

		/* find slots that are used */
		let mut capacity = r.len();
		for i in range(0, r.len()) {
			if !r[i].key.is_zero() && !r[i].tid.is_invalid() {
				capacity -= 1;
			}
		}

		LeafNode {
			entries: r,
			capacity: capacity,
			manager: manager,
			frame: frame,
		}
	}

	fn insert_value(&mut self, key: K, tid: schema::TID) -> Option<LazyNode> {
		if self.capacity == 0 {
			// TODO split
			fail!("Not implemented");
			return None
		}

		// find place to insert
		let location = self.find_slot(&key);
		// free that spot
		self.shift_from(location);
		// and put it in
		self.entries[location].key = key;
		self.entries[location].tid = tid;

		// insertion went fine, done
		None
	}

	/* finds the location at which a key should be inserted */
	fn find_slot(&self, key: &K) -> uint {
		let mut found = 0;
		for i in range(0, self.entries.len()) {
			println!("Entry {:?}", self.entries[i]);
			if &self.entries[i].key > key {
				found = i - 1;
				break;
			}
		}
		found
	}

	/* moves all items from `index` one number back */
	fn shift_from(&mut self, index: uint) {
		// actually, this rotates right by 1 starting from index
		let last_elem = self.entries.len() - 1;
		for i in range(index, last_elem) {
			self.entries.swap(i, last_elem);
		}
	}
}

// TODO implement Drop for LeafNode
#[unsafe_destructor]
impl<'a, K> Drop for LeafNode<'a, K> {
	fn drop(&mut self) {
		let mut manager = self.manager.lock();
		println!("Ohai, unfixing page");
		// TODO: figure out if page was modified since loading
		manager.unfix_page(self.frame.clone(), true);
	}
}

struct BranchNode<'a, K> {
	capacity: uint,
	entries: &'a mut [BranchEntry<K>],
}

impl<'a, K: TotalOrd + Zero> BranchNode<'a, K> {
	fn new(page: &[u8]) -> BranchNode<'a, K> {
		let entry_size = size_of::<BranchEntry<K>>();
		let entry_num = (page.len() - size_of::<u8>()) / entry_size;
		let mut r: &mut [BranchEntry<K>] = unsafe {
			cast::transmute(
				Slice::<BranchEntry<K>> {
					data: page.as_ptr() as *() as *BranchEntry<K>,
					len: entry_num,
				}
			)
		};

		/* find slots that are used */
		let mut capacity = r.len();
		for i in range(0, r.len()) {
			if r[i].page_id != 0 {
				capacity -= 1;
			}
		}

		println!("BranchNode computed capacity: {}", capacity);

		BranchNode {
			entries: r,
			capacity: capacity
		}
	}

	/* might return a new branch node if this one was split */
	fn insert_value(&mut self, tree: &mut BTree<K>, key: K, value: schema::TID) -> Option<LazyNode> {
		let mut place = 0;
		// locate the place where to insert
		for i in range(0, self.entries.len()) {
			if self.entries[i].page_id == 0 {
				continue
			}
			println!("Entry i {:?}, key {:?}", self.entries[i], self.entries[i].key);
			// TODO find place
		}
		let go_to_page = self.entries[place].page_id;
		if go_to_page == 0 {
			let lazy_node = tree.create_leaf_page();
			let new_node = lazy_node.load(tree.manager.clone());
			let split_candidate = match new_node {
				Leaf(mut n) => n.insert_value(key, value),
				Branch(_) => fail!("Did not create a leaf page"),
			};
			self.entries[place].page_id = lazy_node.page_id;
			return split_candidate
		}

		// currently not caring about splitting branch pages
		None
	}
}

#[test]
fn simple_insert() {
	let p = Path::new(".");
	let manager = buffer::BufferManager::new(1024, p.clone());
	let mut bt = BTree::new(23, Rc::new(Mutex::new(manager)));
	bt.insert(42, schema::TID::new(0, 0));
	assert!(false);
}

#[test]
fn create_leaf_page() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let pagelock = manager.fix_page(10).unwrap();
	let page = pagelock.read();
	//let lp: LeafNode<u64> = LeafNode::new(page.get_data(), Rc::new(Mutex::new(manager)), pagelock);
	//println!("lp len: {}", lp.entries.len());
	assert!(false);
}
<commit_msg>Implemented destructor for BranchNode in the same way as LeafNode<commit_after>use std::cast;
use std::mem::size_of;
use std::raw::Slice;
use std::num::Zero;
use std::rc::Rc;
use sync::Mutex;

mod buffer;
mod schema;

static LEAF_MARKER: u8 = 0b111111111;
static BRANCH_MARKER: u8 = 0b0;

/* simple type alias to simplify signatures */
type ConcurrentManager = Rc<Mutex<buffer::BufferManager>>;

struct BTree<'a, K> {
	segment: u64,
	manager: ConcurrentManager,
	tree: LazyNode,
	next_free_page: u64,
}

impl<'a, K: TotalOrd + Zero> BTree<'a, K> {
	fn new<'b>(segment_id: u64, manager: ConcurrentManager) -> BTree<'b, K> {
		BTree {
			segment: segment_id,
			manager: manager,
			tree: LazyNode::new(1),
			next_free_page: 2,
		}
	}

	fn insert(&mut self, key: K, value: schema::TID) {
		let node = self.tree.load(self.manager.clone());
		// try insertion and see if the root was split
		let candidate = match node {
			Branch(mut n) => n.insert_value(self, key, value),
			Leaf(mut n) => n.insert_value(key, value),
		};
		// set new tree root if it was split
		match candidate {
			Some(new_node) => self.tree = new_node,
			None => (),
		}
	}

	fn next_page(&mut self) -> u64 {
		let n = self.next_free_page;
		self.next_free_page += 1;
		n
	}

	fn create_branch_page(&mut self) -> LazyNode {
		let next = self.next_page();
		let page_path = buffer::join_segment(self.segment, next);
		let mut manager = self.manager.lock();
		let pagelock = manager.fix_page(page_path).unwrap();
		let mut page = pagelock.write();
		let data = page.get_mut_data();
		data[0] = BRANCH_MARKER;
		LazyNode::new(page_path)
	}

	fn create_leaf_page(&mut self) -> LazyNode {
		let next = self.next_page();
		let page_path = buffer::join_segment(self.segment, next);
		let mut manager = self.manager.lock();
		let pagelock = manager.fix_page(page_path).unwrap();
		let mut page = pagelock.write();
		let data = page.get_mut_data();
		// marker to be a leaf page
		data[0] = LEAF_MARKER;
		LazyNode::new(page_path)

	}

	fn erase(&mut self, key: K) {
	}

	fn lookup(self, key: K) -> Option<schema::TID> {
		None
	}
}

/* a placeholder for the actual page */
struct LazyNode {
	page_id: u64,
}

impl LazyNode {
	fn new(page_id: u64) -> LazyNode {
		LazyNode {page_id: page_id}
	}

	/*
	 * As this is just a placeholder, return the actual node that his is
	 * representing
	 */
	fn load<'a, K: TotalOrd + Zero>(&self, manager: ConcurrentManager) -> Node<'a, K> {
		let pagelock = {
			let mut managerlock = manager.lock();
			managerlock.fix_page(self.page_id).unwrap()
		};

		let mut is_leaf = false;
		{
			let page = pagelock.read();
			let page_data = page.get_data();
			if page_data[0] == LEAF_MARKER {
				is_leaf = true;
			} else if page_data[0] == BRANCH_MARKER {
				is_leaf = false;
			} else {
				fail!("Invalid page type");
			}
		}
		if is_leaf {
			Leaf(LeafNode::new(manager, pagelock))
		} else {
			Branch(BranchNode::new(manager, pagelock))
		}
	}

}

/* a node might either be an inner node (branch node) or a leaf node (LeafNode) */
enum Node<'a, K> {
	Branch(BranchNode<'a, K>),
	Leaf(LeafNode<'a, K>),
}

/* leaf pages consist mainly of leaf entries which are (K, TID) pairs */
struct LeafEntry<K> {
	key: K,
	tid: schema::TID,
}

/* branch pages consist mainly of branch entries which are (K, page_id) pairs */
struct BranchEntry<K> {
	key: K,
	page_id: u64,
}

struct LeafNode<'a, K> {
	capacity: uint,
	entries: &'a mut [LeafEntry<K>],
	manager: ConcurrentManager,
	frame: buffer::ConcurrentFrame,
}

impl<'a, K: TotalOrd + Zero> LeafNode<'a, K> {
	fn new(manager: ConcurrentManager, frame: buffer::ConcurrentFrame) -> LeafNode<'a, K> {
		let mut r = {
			let framelock = frame.read();
			let page = framelock.get_data();
			// first byte is a Leaf/Branch marker
			let entry_size = size_of::<LeafEntry<K>>();
			let entry_num = (page.len() - size_of::<u8>()) / entry_size;

			let mut entries: &mut[LeafEntry<K>] = unsafe {
				cast::transmute(
					Slice::<LeafEntry<K>> {
						data: page.as_ptr() as *() as *LeafEntry<K>,
						len: entry_num,
					}
				)
			};
			entries
		};

		/* find slots that are used */
		let mut capacity = r.len();
		for i in range(0, r.len()) {
			if !r[i].key.is_zero() && !r[i].tid.is_invalid() {
				capacity -= 1;
			}
		}

		println!("Creating leaf node");
		LeafNode {
			entries: r,
			capacity: capacity,
			manager: manager,
			frame: frame,
		}
	}

	fn insert_value(&mut self, key: K, tid: schema::TID) -> Option<LazyNode> {
		if self.capacity == 0 {
			// TODO split
			fail!("Not implemented");
			return None
		}

		// find place to insert
		let location = self.find_slot(&key);
		// free that spot
		self.shift_from(location);
		// and put it in
		self.entries[location].key = key;
		self.entries[location].tid = tid;

		// insertion went fine, done
		None
	}

	/* finds the location at which a key should be inserted */
	fn find_slot(&self, key: &K) -> uint {
		let mut found = 0;
		for i in range(0, self.entries.len()) {
			println!("Entry {:?}", self.entries[i]);
			if &self.entries[i].key > key {
				found = i - 1;
				break;
			}
		}
		found
	}

	/* moves all items from `index` one number back */
	fn shift_from(&mut self, index: uint) {
		// actually, this rotates right by 1 starting from index
		let last_elem = self.entries.len() - 1;
		for i in range(index, last_elem) {
			self.entries.swap(i, last_elem);
		}
	}
}

#[unsafe_destructor]
impl<'a, K> Drop for LeafNode<'a, K> {
	fn drop(&mut self) {
		let mut manager = self.manager.lock();
		println!("Ohai, unfixing page");
		// TODO: figure out if page was modified since loading
		manager.unfix_page(self.frame.clone(), true);
	}
}

struct BranchNode<'a, K> {
	capacity: uint,
	entries: &'a mut [BranchEntry<K>],
	manager: ConcurrentManager,
	frame: buffer::ConcurrentFrame,
}

impl<'a, K: TotalOrd + Zero> BranchNode<'a, K> {
	fn new(manager: ConcurrentManager, frame: buffer::ConcurrentFrame) -> BranchNode<'a, K> {
		let mut r = {
			let framelock = frame.read();
			let page = framelock.get_data();

			let entry_size = size_of::<BranchEntry<K>>();
			let entry_num = (page.len() - size_of::<u8>()) / entry_size;
			let mut r: &mut [BranchEntry<K>] = unsafe {
				cast::transmute(
					Slice::<BranchEntry<K>> {
						data: page.as_ptr() as *() as *BranchEntry<K>,
						len: entry_num,
					}
				)
			};
			r
		};

		/* find slots that are used */
		let mut capacity = r.len();
		for i in range(0, r.len()) {
			if r[i].page_id != 0 {
				capacity -= 1;
			}
		}

		println!("BranchNode computed capacity: {}", capacity);

		BranchNode {
			entries: r,
			capacity: capacity,
			manager: manager,
			frame: frame,
		}
	}

	/* might return a new branch node if this one was split */
	fn insert_value(&mut self, tree: &mut BTree<K>, key: K, value: schema::TID) -> Option<LazyNode> {
		let mut place = 0;
		// locate the place where to insert
		for i in range(0, self.entries.len()) {
			if self.entries[i].page_id == 0 {
				continue
			}
			println!("Entry i {:?}, key {:?}", self.entries[i], self.entries[i].key);
			// TODO find place
		}
		let go_to_page = self.entries[place].page_id;
		if go_to_page == 0 {
			let lazy_node = tree.create_leaf_page();
			let new_node = lazy_node.load(tree.manager.clone());
			let split_candidate = match new_node {
				Leaf(mut n) => n.insert_value(key, value),
				Branch(_) => fail!("Did not create a leaf page"),
			};
			self.entries[place].page_id = lazy_node.page_id;
			return split_candidate
		}

		// currently not caring about splitting branch pages
		None
	}
}

#[unsafe_destructor]
impl<'a, K> Drop for BranchNode<'a, K> {
	fn drop(&mut self) {
		let mut manager = self.manager.lock();
		println!("Ohai, unfixing page");
		// TODO: figure out if page was modified since loading
		manager.unfix_page(self.frame.clone(), true);
	}
}

#[test]
fn simple_insert() {
	let p = Path::new(".");
	let manager = buffer::BufferManager::new(1024, p.clone());
	let mut bt = BTree::new(23, Rc::new(Mutex::new(manager)));
	bt.insert(42, schema::TID::new(0, 0));
	assert!(false);
}

#[test]
fn create_leaf_page() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let pagelock = manager.fix_page(10).unwrap();
	let page = pagelock.read();
	//let lp: LeafNode<u64> = LeafNode::new(page.get_data(), Rc::new(Mutex::new(manager)), pagelock);
	//println!("lp len: {}", lp.entries.len());
	assert!(false);
}
<|endoftext|>


<commit_before>use std::cast;
use std::mem::size_of;
use std::raw::Slice;
use std::num::Zero;

mod buffer;
mod schema;

struct BTree<'a, K> {
	segment: u64,
	manager: &'a mut buffer::BufferManager,
	tree: LazyNode,
	next_free_page: u64,
}

impl<'a, K: TotalOrd + Zero> BTree<'a, K> {
	fn new<'b>(segment_id: u64, dummy: K, manager: &'b mut buffer::BufferManager) -> BTree<'b, K> {
		BTree {
			segment: segment_id,
			manager: manager,
			tree: LazyNode::new(1),
			next_free_page: 2,
		}
	}

	//fn locate_page

	fn insert(&mut self, key: K, value: schema::TID) {
		let node = self.tree.load(self.manager);
		// try insertion and see if the root was split
		let candidate = match node {
			Inner(mut n) => n.insert_value(self, key, value),
			Leaf(mut n) => n.insert_value(key, value),
		};
		// set new tree root if it was split
		match candidate {
			Some(new_node) => self.tree = new_node,
			None => (),
		}
	}

	fn next_page(&mut self) -> u64 {
		let n = self.next_free_page;
		self.next_free_page += 1;
		n
	}

	fn create_branch_page(&mut self) -> LazyNode {
		let next = self.next_page();
		let page_path = buffer::join_segment(self.segment, next);
		let pagelock = self.manager.fix_page(page_path).unwrap();
		let mut page = pagelock.write();
		let data = page.get_mut_data();
		data[0] = 0;
		LazyNode::new(page_path)
	}

	fn create_leaf_page(&mut self) -> LazyNode {
		let next = self.next_page();
		let page_path = buffer::join_segment(self.segment, next);
		let pagelock = self.manager.fix_page(page_path).unwrap();
		let mut page = pagelock.write();
		let data = page.get_mut_data();
		// marker to be a leaf page
		data[0] = 255;
		LazyNode::new(page_path)

	}

	fn erase(&mut self, key: K) {
	}

	fn lookup(self, key: K) -> Option<schema::TID> {
		None
	}
}

/* a placeholder for the actual page */
struct LazyNode {
	page_id: u64,
}

// TODO implement Drop to unfix page
impl LazyNode {
	fn new(page_id: u64) -> LazyNode {
		LazyNode {page_id: page_id}
	}

	fn load<'a, K: TotalOrd + Zero>(&self, manager: &mut buffer::BufferManager) -> Node<'a, K> {
		let pagelock = manager.fix_page(self.page_id).unwrap();
		let page = pagelock.read();
		load_node(page.get_data())
	}
}

enum Node<'a, K> {
	Inner(BranchPage<'a, K>),
	Leaf(LeafPage<'a, K>),
}

struct LeafEntry<K> {
	key: K,
	tid: schema::TID,
}

struct BranchEntry<K> {
	key: K,
	page_id: u64,
}

struct LeafPage<'a, K> {
	capacity: uint,
	entries: &'a mut [LeafEntry<K>],
}

fn load_node<'a, K: TotalOrd + Zero>(page: &[u8]) -> Node<'a, K> {
	if page[0] == 255 {
		Leaf(LeafPage::new(page))
	} else {
		Inner(BranchPage::new(page))
	}
}

impl<'a, K: Zero> LeafPage<'a, K> {
	fn new(page: &[u8]) -> LeafPage<'a, K> {
		// first byte is a Leaf/Branch marker
		let entry_size = size_of::<LeafEntry<K>>();
		let entry_num = (page.len() - size_of::<u8>()) / entry_size;

		let mut r: &mut[LeafEntry<K>] = unsafe {
			cast::transmute(
				Slice::<LeafEntry<K>> {
					data: page.as_ptr() as *() as *LeafEntry<K>,
					len: entry_num,
				}
			)
		};

		/* find slots that are used */
		let mut capacity = r.len();
		for i in range(0, r.len()) {
			if !r[i].key.is_zero() && !r[i].tid.is_invalid() {
				capacity -= 1;
			}
		}

		LeafPage {
			entries: r,
			capacity: capacity
		}
	}

	fn insert_value(&mut self, key: K, tid: schema::TID) -> Option<LazyNode> {
		if self.capacity == 0 {
			// TODO split
			fail!("shit");
			return None
		}

		// find place to insert
		for i in range(0, self.entries.len()) {
			//let e = self.entries[i];
			println!("Entry {:?}", self.entries[i]);
		}
		// TODO insert

		// insertion went fine, done
		None
	}
}

struct BranchPage<'a, K> {
	capacity: uint,
	entries: &'a mut [BranchEntry<K>],
}

impl<'a, K: TotalOrd + Zero> BranchPage<'a, K> {
	fn new(page: &[u8]) -> BranchPage<'a, K> {
		let entry_size = size_of::<BranchEntry<K>>();
		let entry_num = (page.len() - size_of::<u8>()) / entry_size;
		let mut r: &mut [BranchEntry<K>] = unsafe {
			cast::transmute(
				Slice::<BranchEntry<K>> {
					data: page.as_ptr() as *() as *BranchEntry<K>,
					len: entry_num,
				}
			)
		};

		/* find slots that are used */
		let mut capacity = r.len();
		for i in range(0, r.len()) {
			if r[i].page_id != 0 {
				capacity -= 1;
			}
		}

		println!("BranchPage computed capacity: {}", capacity);

		BranchPage {
			entries: r,
			capacity: capacity
		}
	}

	/* might return a new branch node if this one was split */
	fn insert_value(&mut self, tree: &mut BTree<K>, key: K, value: schema::TID) -> Option<LazyNode> {
		let mut place = 0;
		// locate the place where to insert
		for i in range(0, self.entries.len()) {
			if self.entries[i].page_id == 0 {
				continue
			}
			println!("Entry i {:?}, key {:?}", self.entries[i], self.entries[i].key);
			// TODO find place
		}
		let go_to_page = self.entries[place].page_id;
		if go_to_page == 0 {
			let lazy_node = tree.create_leaf_page();
			let new_node = lazy_node.load(tree.manager);
			let split_candidate = match new_node {
				Leaf(mut n) => n.insert_value(key, value),
				Inner(_) => fail!("Did not create a leaf page"),
			};
			self.entries[place].page_id = lazy_node.page_id;
			return split_candidate
		}

		// currently not caring about splitting branch pages
		None
	}
}

#[test]
fn simple_insert() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let mut bt = BTree::new(23, 42, &mut manager);
	bt.insert(42, schema::TID::new(0, 0));
	assert!(false);
}

#[test]
fn create_leaf_page() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let pagelock = manager.fix_page(0).unwrap();
	let page = pagelock.read();
	let lp: LeafPage<u64> = LeafPage::new(page.get_data());
	println!("lp len: {}", lp.entries.len());
	assert!(false);
}
<commit_msg>Rename stuff to be more consistent<commit_after>use std::cast;
use std::mem::size_of;
use std::raw::Slice;
use std::num::Zero;

mod buffer;
mod schema;

static LEAF_MARKER: u8 = 0b111111111;
static BRANCH_MARKER: u8 = 0b0;

struct BTree<'a, K> {
	segment: u64,
	manager: &'a mut buffer::BufferManager,
	tree: LazyNode,
	next_free_page: u64,
}

impl<'a, K: TotalOrd + Zero> BTree<'a, K> {
	fn new<'b>(segment_id: u64, dummy: K, manager: &'b mut buffer::BufferManager) -> BTree<'b, K> {
		BTree {
			segment: segment_id,
			manager: manager,
			tree: LazyNode::new(1),
			next_free_page: 2,
		}
	}

	//fn locate_page

	fn insert(&mut self, key: K, value: schema::TID) {
		let node = self.tree.load(self.manager);
		// try insertion and see if the root was split
		let candidate = match node {
			Branch(mut n) => n.insert_value(self, key, value),
			Leaf(mut n) => n.insert_value(key, value),
		};
		// set new tree root if it was split
		match candidate {
			Some(new_node) => self.tree = new_node,
			None => (),
		}
	}

	fn next_page(&mut self) -> u64 {
		let n = self.next_free_page;
		self.next_free_page += 1;
		n
	}

	fn create_branch_page(&mut self) -> LazyNode {
		let next = self.next_page();
		let page_path = buffer::join_segment(self.segment, next);
		let pagelock = self.manager.fix_page(page_path).unwrap();
		let mut page = pagelock.write();
		let data = page.get_mut_data();
		data[0] = 0;
		LazyNode::new(page_path)
	}

	fn create_leaf_page(&mut self) -> LazyNode {
		let next = self.next_page();
		let page_path = buffer::join_segment(self.segment, next);
		let pagelock = self.manager.fix_page(page_path).unwrap();
		let mut page = pagelock.write();
		let data = page.get_mut_data();
		// marker to be a leaf page
		data[0] = 255;
		LazyNode::new(page_path)

	}

	fn erase(&mut self, key: K) {
	}

	fn lookup(self, key: K) -> Option<schema::TID> {
		None
	}
}

/* a placeholder for the actual page */
struct LazyNode {
	page_id: u64,
}

// TODO implement Drop to unfix page
impl LazyNode {
	fn new(page_id: u64) -> LazyNode {
		LazyNode {page_id: page_id}
	}

	/*
	 * As this is just a placeholder, return the actual node that his is
	 * representing
	 */
	fn load<'a, K: TotalOrd + Zero>(&self, manager: &mut buffer::BufferManager) -> Node<'a, K> {
		let pagelock = manager.fix_page(self.page_id).unwrap();
		let page = pagelock.read();
		LazyNode::load_node(page.get_data())
	}

	/* helper method to load a Node tepending on the page marker */
	fn load_node<'a, K: TotalOrd + Zero>(page: &[u8]) -> Node<'a, K> {
		if page[0] == 255 {
			Leaf(LeafNode::new(page))
		} else {
			Branch(BranchNode::new(page))
		}
	}
}

/* a node might either be an inner node (branch node) or a leaf node (LeafNode) */
enum Node<'a, K> {
	Branch(BranchNode<'a, K>),
	Leaf(LeafNode<'a, K>),
}

/* leaf pages consist mainly of leaf entries which are (K, TID) pairs */
struct LeafEntry<K> {
	key: K,
	tid: schema::TID,
}

/* branch pages consist mainly of branch entries which are (K, page_id) pairs */
struct BranchEntry<K> {
	key: K,
	page_id: u64,
}

struct LeafNode<'a, K> {
	capacity: uint,
	entries: &'a mut [LeafEntry<K>],
}

impl<'a, K: Zero> LeafNode<'a, K> {
	fn new(page: &[u8]) -> LeafNode<'a, K> {
		// first byte is a Leaf/Branch marker
		let entry_size = size_of::<LeafEntry<K>>();
		let entry_num = (page.len() - size_of::<u8>()) / entry_size;

		let mut r: &mut[LeafEntry<K>] = unsafe {
			cast::transmute(
				Slice::<LeafEntry<K>> {
					data: page.as_ptr() as *() as *LeafEntry<K>,
					len: entry_num,
				}
			)
		};

		/* find slots that are used */
		let mut capacity = r.len();
		for i in range(0, r.len()) {
			if !r[i].key.is_zero() && !r[i].tid.is_invalid() {
				capacity -= 1;
			}
		}

		LeafNode {
			entries: r,
			capacity: capacity
		}
	}

	fn insert_value(&mut self, key: K, tid: schema::TID) -> Option<LazyNode> {
		if self.capacity == 0 {
			// TODO split
			fail!("shit");
			return None
		}

		// find place to insert
		for i in range(0, self.entries.len()) {
			println!("Entry {:?}", self.entries[i]);
		}
		// TODO insert

		// insertion went fine, done
		None
	}
}

struct BranchNode<'a, K> {
	capacity: uint,
	entries: &'a mut [BranchEntry<K>],
}

impl<'a, K: TotalOrd + Zero> BranchNode<'a, K> {
	fn new(page: &[u8]) -> BranchNode<'a, K> {
		let entry_size = size_of::<BranchEntry<K>>();
		let entry_num = (page.len() - size_of::<u8>()) / entry_size;
		let mut r: &mut [BranchEntry<K>] = unsafe {
			cast::transmute(
				Slice::<BranchEntry<K>> {
					data: page.as_ptr() as *() as *BranchEntry<K>,
					len: entry_num,
				}
			)
		};

		/* find slots that are used */
		let mut capacity = r.len();
		for i in range(0, r.len()) {
			if r[i].page_id != 0 {
				capacity -= 1;
			}
		}

		println!("BranchNode computed capacity: {}", capacity);

		BranchNode {
			entries: r,
			capacity: capacity
		}
	}

	/* might return a new branch node if this one was split */
	fn insert_value(&mut self, tree: &mut BTree<K>, key: K, value: schema::TID) -> Option<LazyNode> {
		let mut place = 0;
		// locate the place where to insert
		for i in range(0, self.entries.len()) {
			if self.entries[i].page_id == 0 {
				continue
			}
			println!("Entry i {:?}, key {:?}", self.entries[i], self.entries[i].key);
			// TODO find place
		}
		let go_to_page = self.entries[place].page_id;
		if go_to_page == 0 {
			let lazy_node = tree.create_leaf_page();
			let new_node = lazy_node.load(tree.manager);
			let split_candidate = match new_node {
				Leaf(mut n) => n.insert_value(key, value),
				Branch(_) => fail!("Did not create a leaf page"),
			};
			self.entries[place].page_id = lazy_node.page_id;
			return split_candidate
		}

		// currently not caring about splitting branch pages
		None
	}
}

#[test]
fn simple_insert() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let mut bt = BTree::new(23, 42, &mut manager);
	bt.insert(42, schema::TID::new(0, 0));
	assert!(false);
}

#[test]
fn create_leaf_page() {
	let p = Path::new(".");
	let mut manager = buffer::BufferManager::new(1024, p.clone());
	let pagelock = manager.fix_page(0).unwrap();
	let page = pagelock.read();
	let lp: LeafNode<u64> = LeafNode::new(page.get_data());
	println!("lp len: {}", lp.entries.len());
	assert!(false);
}
<|endoftext|>


<commit_before>use std::fmt;
use world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS};
use super::{AxialType, DefaultFloat, Vector2f};
use math::cgmath::{VectorSpace, Zero};
use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Rem,
               RemAssign, Sub, SubAssign};
use math::cgmath::prelude::{Array, MetricSpace};
use std::cmp;

/// A 2-dimensional vector in axial coordinates. See [here][hex-blog] for more
/// information.
///
/// [hex-blog]: http://www.redblobgames.com/grids/hexagons/#coordinates
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, packed)]
pub struct AxialVector {
    pub q: AxialType,
    pub r: AxialType,
}
// TODO: implement cgmath::Zero
// TODO: implement cgmath::Array
// TODO: implement cgmath::MatricSpace
// TODO: implement cgmath::VectorSpace
// TODO: implement cgmath::InnerSpace
// TODO: implement ops::{ ... }
// TODO: Add `unit_q()` and `unit_r()` (see `Vector2::unit_x()` for reference)
// For all of the above, see
// http://bjz.github.io/cgmath/cgmath/struct.Vector2.html
//
/// AxialVector defines a vector specificly for Axial cordinate system.
impl AxialVector {
    pub fn new(q: AxialType, r: AxialType) -> Self {
        AxialVector { q: q, r: r }
    }
    /// Returns the position of the hexagons center in the standard coordinate
    /// system using `world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS}`.
    pub fn to_real(&self) -> Vector2f {
        Vector2f {
            x: ((2 * self.q + self.r) as DefaultFloat) * HEX_INNER_RADIUS,
            y: (self.r as DefaultFloat) * (3.0 / 2.0) * HEX_OUTER_RADIUS,
        }
    }
    /// Returns the `s` component of corresponding cube coordinates. In cube
    /// coordinates 'q + r + s = 0', so saving `s` is redundant and can be
    /// calculated on the fly when needed.
    pub fn s(&self) -> AxialType {
        -self.q - self.r
    }
    /// unit_q creates an default AxialVector with q:1 r:0.
    pub fn unit_q() -> AxialVector {
        AxialVector { q: 1, r: 0 }
    }
    /// unit_r creates an default AxialVector with q:0 r:1.
    pub fn unit_r() -> AxialVector {
        AxialVector { q: 0, r: 1 }
    }
}
impl fmt::Debug for AxialVector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("")
            .field(&self.q)
            .field(&self.r)
            .finish()
    }
}
// ********************* Basic Arithmetic (OPS) *********************
impl Neg for AxialVector {
    type Output = AxialVector;
    fn neg(self) -> Self::Output {
        AxialVector {
            q: -self.q,
            r: -self.r,
        }
    }
}
impl Add<AxialVector> for AxialVector {
    type Output = AxialVector;
    fn add(self, arg2: AxialVector) -> AxialVector {
        AxialVector {
            r: self.r + arg2.r,
            q: self.q + arg2.q,
        }
    }
}
impl AddAssign<AxialVector> for AxialVector {
    fn add_assign(&mut self, arg2: AxialVector) {
        self.r += arg2.r;
        self.q += arg2.q;

    }
}
impl Sub<AxialVector> for AxialVector {
    type Output = AxialVector;
    fn sub(self, arg2: AxialVector) -> AxialVector {
        AxialVector {
            r: self.r - arg2.r,
            q: self.q - arg2.q,
        }
    }
}
impl SubAssign<AxialVector> for AxialVector {
    fn sub_assign(&mut self, arg2: AxialVector) {
        self.r -= arg2.r;
        self.q -= arg2.q;
    }
}
impl Mul<AxialType> for AxialVector {
    type Output = AxialVector;
    fn mul(self, arg2: AxialType) -> AxialVector {
        AxialVector {
            r: self.r * arg2,
            q: self.q * arg2,
        }
    }
}
impl MulAssign<AxialType> for AxialVector {
    fn mul_assign(&mut self, arg2: AxialType) {
        self.r *= arg2;
        self.q *= arg2;

    }
}
impl Div<AxialType> for AxialVector {
    type Output = AxialVector;
    fn div(self, arg2: AxialType) -> AxialVector {
        AxialVector {
            r: self.r / arg2,
            q: self.q / arg2,
        }
    }
}
impl DivAssign<AxialType> for AxialVector {
    fn div_assign(&mut self, arg2: AxialType) {
        self.r /= arg2;
        self.q /= arg2;
    }
}
impl Rem<AxialType> for AxialVector {
    type Output = AxialVector;
    fn rem(self, arg2: AxialType) -> AxialVector {
        AxialVector {
            r: self.r % arg2,
            q: self.q % arg2,
        }
    }
}
impl RemAssign<AxialType> for AxialVector {
    fn rem_assign(&mut self, arg2: AxialType) {
        self.r %= arg2;
        self.q %= arg2;
    }
}
// ************ Metric Space ************
impl MetricSpace for AxialVector {
    type Metric = DefaultFloat;
    fn distance(self, other: AxialVector) -> DefaultFloat {
        self.distance2(other).sqrt()
    }
    fn distance2(self, other: AxialVector) -> DefaultFloat {
        ((self.q - other.q).pow(2) + (self.r - other.r).pow(2)) as DefaultFloat
    }
}
// ************ Vector Space ************
impl VectorSpace for AxialVector {
    type Scalar = AxialType;
}
// ************** Zero ****************
impl Zero for AxialVector {
    fn zero() -> AxialVector {
        AxialVector { q: 0, r: 0 }
    }
    fn is_zero(&self) -> bool {
        self.q == 0 && self.r == 0
    }
}
// *************** Array & Index *******************
impl Array for AxialVector {
    type Element = AxialType;
    fn from_value(value: Self::Element) -> Self {
        AxialVector::new(value, value)
    }
    fn sum(self) -> Self::Element {
        self.q + self.r
    }
    fn product(self) -> Self::Element {
        self.q * self.r
    }
    fn min(self) -> Self::Element {
        cmp::min(self.q, self.r)
    }
    fn max(self) -> Self::Element {
        cmp::max(self.q, self.r)
    }
}
impl Index<usize> for AxialVector {
    type Output = AxialType;
    fn index(&self, index: usize) -> &Self::Output {
        match index {
            0 => &self.q,
            1 => &self.r,
            _ => panic!("Illegal Index Argument: was {:?}", index),
        }
    }
}
impl IndexMut<usize> for AxialVector {
    fn index_mut(&mut self, index: usize) -> &mut AxialType {
        match index {
            0 => &mut self.q,
            1 => &mut self.r,
            _ => panic!("Illegal Index Argument: was {:?}", index),
        }
    }
}
#[test]
fn test_my_foo_feature() {
    // ***** Unit Vectors *****
    let uvq = AxialVector::unit_q();
    assert!(uvq.q == 1 && uvq.r == 0);
    let uvr = AxialVector::unit_r();
    assert!(uvq.r == 0 && uvr.r == 1);
    let test1 = AxialVector { q: -5, r: 2 };
    let test2 = AxialVector { q: 13, r: -4 };
    // ****** Arith. Operations ******
    assert_eq!(-uvq, AxialVector { q: -1, r: 0 });
    assert_eq!(-test1, AxialVector { q: 5, r: -2 });
    assert_eq!(test1 + uvq, AxialVector { q: -4, r: 2 });
    assert_eq!(test2 + test1, AxialVector { q: 8, r: -2 });
    let mut test3 = AxialVector { q: -9, r: 19 };
    test3 += test1;
    assert_eq!(test3, AxialVector { q: -14, r: 21 });
    assert_eq!(test2 - test1, AxialVector { q: 18, r: -6 });
    assert_eq!(test1 - uvr, AxialVector { q: -5, r: 1 });
    test3 -= test2;
    assert!(test3.q == -27 && test3.r == 25);
    test3 = test1 * 2;
    assert!(test3.q == -10, test3.r == 4);
    test3 = test1 * -4;
    assert!(test3.q == 20 && test3.r == -8);
    test3 *= -3;
    assert!(test3.q == -60 && test3.r == 24);
    test3 = test3 / 3;
    assert!(test3.q == -20 && test3.r == 8);
    test3 /= 5;
    assert!(test3.q == -4 && test3.r == 1);
    test3 = test2 % 2;
    assert!(test3.q == 1 && test3.r == 0);
    test3.q = 11;
    test3.r = 6;
    test3 %= 3;
    assert!(test3.q == 2 && test3.r == 0);
    // ********* metric space ************
    let mut f: f32 = 2.0;
    f = f.sqrt();
    assert_eq!(uvq.distance(uvr), f);
    assert_eq!(test1.distance2(test2), 360.0);
    // ********* zero *************
    test3 = AxialVector::zero();
    assert!(test3.q == 0 && test3.r == 0);
    assert!(test3.is_zero());
    assert!(!(test2.is_zero()));
    // ********** Index *********
    test3[0] = 12;
    test3[1] = 4;
    assert!(test3.q == 12 && test3.r == 4);
    assert!(test3[0] == 12 && test3[1] == 4);
    // ********** Array ***********
    test3 = AxialVector::from_value(3);
    assert!(test3.q == 3 && test3.r == 3);
    assert_eq!(test3.sum(), 6);
    assert_eq!(test3.product(), 9);
    assert_eq!(test1.min(), -5);
    assert_eq!(test2.max(), 13);
}
<commit_msg>Fixed spelling of 'specifically' in comments<commit_after>use std::fmt;
use world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS};
use super::{AxialType, DefaultFloat, Vector2f};
use math::cgmath::{VectorSpace, Zero};
use std::ops::{Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Rem,
               RemAssign, Sub, SubAssign};
use math::cgmath::prelude::{Array, MetricSpace};
use std::cmp;

/// A 2-dimensional vector in axial coordinates. See [here][hex-blog] for more
/// information.
///
/// [hex-blog]: http://www.redblobgames.com/grids/hexagons/#coordinates
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[repr(C, packed)]
pub struct AxialVector {
    pub q: AxialType,
    pub r: AxialType,
}
// TODO: implement cgmath::Zero
// TODO: implement cgmath::Array
// TODO: implement cgmath::MatricSpace
// TODO: implement cgmath::VectorSpace
// TODO: implement cgmath::InnerSpace
// TODO: implement ops::{ ... }
// TODO: Add `unit_q()` and `unit_r()` (see `Vector2::unit_x()` for reference)
// For all of the above, see
// http://bjz.github.io/cgmath/cgmath/struct.Vector2.html
//
/// AxialVector defines a vector specifically for Axial cordinate system.
impl AxialVector {
    pub fn new(q: AxialType, r: AxialType) -> Self {
        AxialVector { q: q, r: r }
    }
    /// Returns the position of the hexagons center in the standard coordinate
    /// system using `world::{HEX_INNER_RADIUS, HEX_OUTER_RADIUS}`.
    pub fn to_real(&self) -> Vector2f {
        Vector2f {
            x: ((2 * self.q + self.r) as DefaultFloat) * HEX_INNER_RADIUS,
            y: (self.r as DefaultFloat) * (3.0 / 2.0) * HEX_OUTER_RADIUS,
        }
    }
    /// Returns the `s` component of corresponding cube coordinates. In cube
    /// coordinates 'q + r + s = 0', so saving `s` is redundant and can be
    /// calculated on the fly when needed.
    pub fn s(&self) -> AxialType {
        -self.q - self.r
    }
    /// unit_q creates an default AxialVector with q:1 r:0.
    pub fn unit_q() -> AxialVector {
        AxialVector { q: 1, r: 0 }
    }
    /// unit_r creates an default AxialVector with q:0 r:1.
    pub fn unit_r() -> AxialVector {
        AxialVector { q: 0, r: 1 }
    }
}
impl fmt::Debug for AxialVector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("")
            .field(&self.q)
            .field(&self.r)
            .finish()
    }
}
// ********************* Basic Arithmetic (OPS) *********************
impl Neg for AxialVector {
    type Output = AxialVector;
    fn neg(self) -> Self::Output {
        AxialVector {
            q: -self.q,
            r: -self.r,
        }
    }
}
impl Add<AxialVector> for AxialVector {
    type Output = AxialVector;
    fn add(self, arg2: AxialVector) -> AxialVector {
        AxialVector {
            r: self.r + arg2.r,
            q: self.q + arg2.q,
        }
    }
}
impl AddAssign<AxialVector> for AxialVector {
    fn add_assign(&mut self, arg2: AxialVector) {
        self.r += arg2.r;
        self.q += arg2.q;

    }
}
impl Sub<AxialVector> for AxialVector {
    type Output = AxialVector;
    fn sub(self, arg2: AxialVector) -> AxialVector {
        AxialVector {
            r: self.r - arg2.r,
            q: self.q - arg2.q,
        }
    }
}
impl SubAssign<AxialVector> for AxialVector {
    fn sub_assign(&mut self, arg2: AxialVector) {
        self.r -= arg2.r;
        self.q -= arg2.q;
    }
}
impl Mul<AxialType> for AxialVector {
    type Output = AxialVector;
    fn mul(self, arg2: AxialType) -> AxialVector {
        AxialVector {
            r: self.r * arg2,
            q: self.q * arg2,
        }
    }
}
impl MulAssign<AxialType> for AxialVector {
    fn mul_assign(&mut self, arg2: AxialType) {
        self.r *= arg2;
        self.q *= arg2;

    }
}
impl Div<AxialType> for AxialVector {
    type Output = AxialVector;
    fn div(self, arg2: AxialType) -> AxialVector {
        AxialVector {
            r: self.r / arg2,
            q: self.q / arg2,
        }
    }
}
impl DivAssign<AxialType> for AxialVector {
    fn div_assign(&mut self, arg2: AxialType) {
        self.r /= arg2;
        self.q /= arg2;
    }
}
impl Rem<AxialType> for AxialVector {
    type Output = AxialVector;
    fn rem(self, arg2: AxialType) -> AxialVector {
        AxialVector {
            r: self.r % arg2,
            q: self.q % arg2,
        }
    }
}
impl RemAssign<AxialType> for AxialVector {
    fn rem_assign(&mut self, arg2: AxialType) {
        self.r %= arg2;
        self.q %= arg2;
    }
}
// ************ Metric Space ************
impl MetricSpace for AxialVector {
    type Metric = DefaultFloat;
    fn distance(self, other: AxialVector) -> DefaultFloat {
        self.distance2(other).sqrt()
    }
    fn distance2(self, other: AxialVector) -> DefaultFloat {
        ((self.q - other.q).pow(2) + (self.r - other.r).pow(2)) as DefaultFloat
    }
}
// ************ Vector Space ************
impl VectorSpace for AxialVector {
    type Scalar = AxialType;
}
// ************** Zero ****************
impl Zero for AxialVector {
    fn zero() -> AxialVector {
        AxialVector { q: 0, r: 0 }
    }
    fn is_zero(&self) -> bool {
        self.q == 0 && self.r == 0
    }
}
// *************** Array & Index *******************
impl Array for AxialVector {
    type Element = AxialType;
    fn from_value(value: Self::Element) -> Self {
        AxialVector::new(value, value)
    }
    fn sum(self) -> Self::Element {
        self.q + self.r
    }
    fn product(self) -> Self::Element {
        self.q * self.r
    }
    fn min(self) -> Self::Element {
        cmp::min(self.q, self.r)
    }
    fn max(self) -> Self::Element {
        cmp::max(self.q, self.r)
    }
}
impl Index<usize> for AxialVector {
    type Output = AxialType;
    fn index(&self, index: usize) -> &Self::Output {
        match index {
            0 => &self.q,
            1 => &self.r,
            _ => panic!("Illegal Index Argument: was {:?}", index),
        }
    }
}
impl IndexMut<usize> for AxialVector {
    fn index_mut(&mut self, index: usize) -> &mut AxialType {
        match index {
            0 => &mut self.q,
            1 => &mut self.r,
            _ => panic!("Illegal Index Argument: was {:?}", index),
        }
    }
}
#[test]
fn test_my_foo_feature() {
    // ***** Unit Vectors *****
    let uvq = AxialVector::unit_q();
    assert!(uvq.q == 1 && uvq.r == 0);
    let uvr = AxialVector::unit_r();
    assert!(uvq.r == 0 && uvr.r == 1);
    let test1 = AxialVector { q: -5, r: 2 };
    let test2 = AxialVector { q: 13, r: -4 };
    // ****** Arith. Operations ******
    assert_eq!(-uvq, AxialVector { q: -1, r: 0 });
    assert_eq!(-test1, AxialVector { q: 5, r: -2 });
    assert_eq!(test1 + uvq, AxialVector { q: -4, r: 2 });
    assert_eq!(test2 + test1, AxialVector { q: 8, r: -2 });
    let mut test3 = AxialVector { q: -9, r: 19 };
    test3 += test1;
    assert_eq!(test3, AxialVector { q: -14, r: 21 });
    assert_eq!(test2 - test1, AxialVector { q: 18, r: -6 });
    assert_eq!(test1 - uvr, AxialVector { q: -5, r: 1 });
    test3 -= test2;
    assert!(test3.q == -27 && test3.r == 25);
    test3 = test1 * 2;
    assert!(test3.q == -10, test3.r == 4);
    test3 = test1 * -4;
    assert!(test3.q == 20 && test3.r == -8);
    test3 *= -3;
    assert!(test3.q == -60 && test3.r == 24);
    test3 = test3 / 3;
    assert!(test3.q == -20 && test3.r == 8);
    test3 /= 5;
    assert!(test3.q == -4 && test3.r == 1);
    test3 = test2 % 2;
    assert!(test3.q == 1 && test3.r == 0);
    test3.q = 11;
    test3.r = 6;
    test3 %= 3;
    assert!(test3.q == 2 && test3.r == 0);
    // ********* metric space ************
    let mut f: f32 = 2.0;
    f = f.sqrt();
    assert_eq!(uvq.distance(uvr), f);
    assert_eq!(test1.distance2(test2), 360.0);
    // ********* zero *************
    test3 = AxialVector::zero();
    assert!(test3.q == 0 && test3.r == 0);
    assert!(test3.is_zero());
    assert!(!(test2.is_zero()));
    // ********** Index *********
    test3[0] = 12;
    test3[1] = 4;
    assert!(test3.q == 12 && test3.r == 4);
    assert!(test3[0] == 12 && test3[1] == 4);
    // ********** Array ***********
    test3 = AxialVector::from_value(3);
    assert!(test3.q == 3 && test3.r == 3);
    assert_eq!(test3.sum(), 6);
    assert_eq!(test3.product(), 9);
    assert_eq!(test1.min(), -5);
    assert_eq!(test2.max(), 13);
}
<|endoftext|>


<commit_before>use super::command;

// An item on the chain
#[derive(Clone)]
pub enum Item<'a> {
    FatalCommand(String),
    NonFatalCommand(String),
    ResultMappedCommand(&'a Fn(&command::Result, String) -> String, String, bool),
    ResultProcessor(&'a Fn(&command::Result) -> command::Result),
}

pub struct CommandChain<'a> {
    pub commands: Vec<Item<'a>>,
    pub old_commands: Vec<Item<'a>>,
    pub result: Option<command::Result>
}

impl<'a> CommandChain<'a> {

    pub fn new() -> Self {
        CommandChain {
            commands: Vec::new(),
            old_commands: Vec::new(),
            result: None
        }
    }

    pub fn result_proc(mut self, f: &'a Fn(&command::Result) -> command::Result) -> Self {
        self.commands.push(Item::ResultProcessor(f));
        self
    }

    pub fn result_mapped_cmd(mut self, f: &'a Fn(&command::Result, String) -> String, command_string: &str) -> Self {
        self.commands.push(Item::ResultMappedCommand(f, command_string.to_string(), true));
        self
    }

    pub fn result_mapped_cmd_nonfatal(mut self, f: &'a Fn(&command::Result, String) -> String, command_string: &str) -> Self {
        self.commands.push(Item::ResultMappedCommand(f, command_string.to_string(), false));
        self
    }

    pub fn cmd(mut self, command_string: &str) -> Self {
        self.commands.push(Item::FatalCommand(String::from(command_string)));
        self
    }

    pub fn cmd_nonfatal(mut self, command_string: &str) -> Self {
        self.commands.push(Item::NonFatalCommand(String::from(command_string)));
        self
    }

    fn run_command(cmd_str : &str) -> command::Result {
        let result = command::run_host_cmd(cmd_str);
        if result.success {
            info!("stdout:{}", result.stdout);
        } else {
            warn!("stderr:{}", result.stderr);
        }
        result
    }

    // Executes the chain and returns self, with vector reset
    pub fn execute(mut self) -> Self {
        for item in self.commands.iter() {
            match item {
                &Item::FatalCommand(ref s) => {
                    let result = CommandChain::run_command(s);
                    if !result.success {
                        self.result = Some(result);
                        break
                    }
                    self.result = Some(result);
                },
                &Item::NonFatalCommand(ref s) => {
                    let result = CommandChain::run_command(s);
                    self.result = Some(result);
                },
                &Item::ResultProcessor(f) => {
                    self.result = {
                        if let Some(ref mut curr_res) = self.result {
                            Some(f(&curr_res))
                        } else {
                            warn!("Executing ResultProcessor with no current result is a no-op!");
                            None
                        }
                    };
                },
                &Item::ResultMappedCommand(f, ref s, is_fatal) => {
                    let mapped_command : String = {
                        if let Some(ref mut curr_res) = self.result {
                            f(&curr_res, s.to_string())
                        } else {
                            warn!("Executing ResultMappedCommand with no current result is a no-op!");
                            s.to_string()
                        }
                    };
                    let result = CommandChain::run_command(&mapped_command);
                    if is_fatal && !result.success {
                        self.result = Some(result);
                        break
                    }
                    self.result = Some(result);
                }
            }
        }
        self.old_commands.extend(self.commands.clone());
        self.commands = Vec::new();
        self
    }
}
<commit_msg>better stderr, stdout output<commit_after>use super::command;

// An item on the chain
#[derive(Clone)]
pub enum Item<'a> {
    FatalCommand(String),
    NonFatalCommand(String),
    ResultMappedCommand(&'a Fn(&command::Result, String) -> String, String, bool),
    ResultProcessor(&'a Fn(&command::Result) -> command::Result),
}

pub struct CommandChain<'a> {
    pub commands: Vec<Item<'a>>,
    pub old_commands: Vec<Item<'a>>,
    pub result: Option<command::Result>
}

impl<'a> CommandChain<'a> {

    pub fn new() -> Self {
        CommandChain {
            commands: Vec::new(),
            old_commands: Vec::new(),
            result: None
        }
    }

    pub fn result_proc(mut self, f: &'a Fn(&command::Result) -> command::Result) -> Self {
        self.commands.push(Item::ResultProcessor(f));
        self
    }

    pub fn result_mapped_cmd(mut self, f: &'a Fn(&command::Result, String) -> String, command_string: &str) -> Self {
        self.commands.push(Item::ResultMappedCommand(f, command_string.to_string(), true));
        self
    }

    pub fn result_mapped_cmd_nonfatal(mut self, f: &'a Fn(&command::Result, String) -> String, command_string: &str) -> Self {
        self.commands.push(Item::ResultMappedCommand(f, command_string.to_string(), false));
        self
    }

    pub fn cmd(mut self, command_string: &str) -> Self {
        self.commands.push(Item::FatalCommand(String::from(command_string)));
        self
    }

    pub fn cmd_nonfatal(mut self, command_string: &str) -> Self {
        self.commands.push(Item::NonFatalCommand(String::from(command_string)));
        self
    }

    fn run_command(cmd_str : &str) -> command::Result {
        let result = command::run_host_cmd(cmd_str);
        info!("Running: {}", cmd_str);
        if result.success {
            info!("stdout: {}", result.stdout);
        } else {
            warn!("stderr: {}", result.stderr);
        }
        result
    }

    // Executes the chain and returns self, with vector reset
    pub fn execute(mut self) -> Self {
        for item in self.commands.iter() {
            match item {
                &Item::FatalCommand(ref s) => {
                    let result = CommandChain::run_command(s);
                    if !result.success {
                        self.result = Some(result);
                        break
                    }
                    self.result = Some(result);
                },
                &Item::NonFatalCommand(ref s) => {
                    let result = CommandChain::run_command(s);
                    self.result = Some(result);
                },
                &Item::ResultProcessor(f) => {
                    self.result = {
                        if let Some(ref mut curr_res) = self.result {
                            Some(f(&curr_res))
                        } else {
                            warn!("Executing ResultProcessor with no current result is a no-op!");
                            None
                        }
                    };
                },
                &Item::ResultMappedCommand(f, ref s, is_fatal) => {
                    let mapped_command : String = {
                        if let Some(ref mut curr_res) = self.result {
                            f(&curr_res, s.to_string())
                        } else {
                            warn!("Executing ResultMappedCommand with no current result is a no-op!");
                            s.to_string()
                        }
                    };
                    let result = CommandChain::run_command(&mapped_command);
                    if is_fatal && !result.success {
                        self.result = Some(result);
                        break
                    }
                    self.result = Some(result);
                }
            }
        }
        self.old_commands.extend(self.commands.clone());
        self.commands = Vec::new();
        self
    }
}
<|endoftext|>


<commit_before>use nalgebra;
use num::Num;
use std::cmp;
use std::convert::From;
use std::marker::PhantomData;
use std::ops;

use math::Clamp;

pub trait ClampedRange<T> {
    fn max_value() -> T;
    fn min_value() -> T;
}

pub struct Clamped<T, R>(T, PhantomData<R>)
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>;

impl<T, R> Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    pub fn new(value: T) -> Self {
        Clamped(nalgebra::clamp(value, R::min_value(), R::max_value()), PhantomData)
    }

    pub fn max_value() -> Self {
        Clamped(R::max_value(), PhantomData)
    }

    pub fn min_value() -> Self {
        Clamped(R::min_value(), PhantomData)
    }

    pub fn to_inner(&self) -> T {
        self.0
    }
}

impl<T, R> Clamp<Clamped<T, R>> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn clamp(&self, min: Self, max: Self) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

impl<T, R> Clone for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn clone(&self) -> Self {
        Clamped(self.0, PhantomData)
    }
}

impl<T, R> Copy for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T> {}

impl<T, R> From<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn from(value: T) -> Self {
        Self::new(value)
    }
}

impl<T, R> cmp::Eq for Clamped<T, R>
    where T: Copy + cmp::Eq + Num + cmp::PartialOrd,
          R: ClampedRange<T> {}

impl<T, R> cmp::Ord for Clamped<T, R>
    where T: Copy + Num + cmp::Ord + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.0.cmp(&other.0)
    }
}

impl<T, R> cmp::PartialEq for Clamped<T, R>
    where T: Copy + Num + cmp::PartialEq + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn eq(&self, other: &Self) -> bool {
        self.0.eq(&other.0)
    }
}

impl<T, R> cmp::PartialEq<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialEq + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn eq(&self, other: &T) -> bool {
        self.0.eq(other)
    }
}

impl<T, R> cmp::PartialOrd for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.0.partial_cmp(&other.0)
    }
}

impl<T, R> cmp::PartialOrd<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
        self.0.partial_cmp(other)
    }
}

impl<T, R> ops::Add for Clamped<T, R>
    where T: ops::Add<Output = T> + Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn add(self, other: Self) -> Self::Output {
        Self::new(self.0.add(other.0))
    }
}

impl<T, R> ops::Add<T> for Clamped<T, R>
    where T: ops::Add<Output = T> + Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn add(self, other: T) -> Self::Output {
        Self::new(self.0.add(other))
    }
}

impl<T, R> ops::Deref for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T, R> ops::Div for Clamped<T, R>
    where T: Copy + ops::Div<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn div(self, other: Self) -> Self::Output {
        Self::new(self.0.div(other.0))
    }
}

impl<T, R> ops::Div<T> for Clamped<T, R>
    where T: Copy + ops::Div<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn div(self, other: T) -> Self::Output {
        Self::new(self.0.div(other))
    }
}

impl<T, R> ops::Mul for Clamped<T, R>
    where T: Copy + ops::Mul<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn mul(self, other: Self) -> Self::Output {
        Self::new(self.0.mul(other.0))
    }
}

impl<T, R> ops::Mul<T> for Clamped<T, R>
    where T: Copy + ops::Mul<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn mul(self, other: T) -> Self::Output {
        Self::new(self.0.mul(other))
    }
}

impl<T, R> ops::Neg for Clamped<T, R>
    where T: Copy + ops::Neg<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn neg(self) -> Self::Output {
        Self::new(self.0.neg())
    }
}

impl<T, R> ops::Sub for Clamped<T, R>
    where T: Copy + Num + ops::Sub<Output = T> + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn sub(self, other: Self) -> Self::Output {
        Self::new(self.0.sub(other.0))
    }
}

impl<T, R> ops::Sub<T> for Clamped<T, R>
    where T: Copy + Num + ops::Sub<Output = T> + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn sub(self, other: T) -> Self::Output {
        Self::new(self.0.sub(other))
    }
}
<commit_msg>Expose min/max for inner type.<commit_after>use nalgebra;
use num::Num;
use std::cmp;
use std::convert::From;
use std::marker::PhantomData;
use std::ops;

use math::Clamp;

pub trait ClampedRange<T> {
    fn max_value() -> T;
    fn min_value() -> T;
}

pub struct Clamped<T, R>(T, PhantomData<R>)
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>;

impl<T, R> Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    pub fn new(value: T) -> Self {
        Clamped(nalgebra::clamp(value, R::min_value(), R::max_value()), PhantomData)
    }

    pub fn max_value() -> Self {
        Clamped(R::max_value(), PhantomData)
    }

    pub fn max_inner_value() -> T {
        R::max_value()
    }

    pub fn min_value() -> Self {
        Clamped(R::min_value(), PhantomData)
    }

    pub fn min_inner_value() -> T {
        R::min_value()
    }

    pub fn to_inner(&self) -> T {
        self.0
    }
}

impl<T, R> Clamp<Clamped<T, R>> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn clamp(&self, min: Self, max: Self) -> Self {
        nalgebra::clamp(*self, min, max)
    }
}

impl<T, R> Clone for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn clone(&self) -> Self {
        Clamped(self.0, PhantomData)
    }
}

impl<T, R> Copy for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T> {}

impl<T, R> From<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn from(value: T) -> Self {
        Self::new(value)
    }
}

impl<T, R> cmp::Eq for Clamped<T, R>
    where T: Copy + cmp::Eq + Num + cmp::PartialOrd,
          R: ClampedRange<T> {}

impl<T, R> cmp::Ord for Clamped<T, R>
    where T: Copy + Num + cmp::Ord + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn cmp(&self, other: &Self) -> cmp::Ordering {
        self.0.cmp(&other.0)
    }
}

impl<T, R> cmp::PartialEq for Clamped<T, R>
    where T: Copy + Num + cmp::PartialEq + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn eq(&self, other: &Self) -> bool {
        self.0.eq(&other.0)
    }
}

impl<T, R> cmp::PartialEq<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialEq + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn eq(&self, other: &T) -> bool {
        self.0.eq(other)
    }
}

impl<T, R> cmp::PartialOrd for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        self.0.partial_cmp(&other.0)
    }
}

impl<T, R> cmp::PartialOrd<T> for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    fn partial_cmp(&self, other: &T) -> Option<cmp::Ordering> {
        self.0.partial_cmp(other)
    }
}

impl<T, R> ops::Add for Clamped<T, R>
    where T: ops::Add<Output = T> + Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn add(self, other: Self) -> Self::Output {
        Self::new(self.0.add(other.0))
    }
}

impl<T, R> ops::Add<T> for Clamped<T, R>
    where T: ops::Add<Output = T> + Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn add(self, other: T) -> Self::Output {
        Self::new(self.0.add(other))
    }
}

impl<T, R> ops::Deref for Clamped<T, R>
    where T: Copy + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<T, R> ops::Div for Clamped<T, R>
    where T: Copy + ops::Div<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn div(self, other: Self) -> Self::Output {
        Self::new(self.0.div(other.0))
    }
}

impl<T, R> ops::Div<T> for Clamped<T, R>
    where T: Copy + ops::Div<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn div(self, other: T) -> Self::Output {
        Self::new(self.0.div(other))
    }
}

impl<T, R> ops::Mul for Clamped<T, R>
    where T: Copy + ops::Mul<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn mul(self, other: Self) -> Self::Output {
        Self::new(self.0.mul(other.0))
    }
}

impl<T, R> ops::Mul<T> for Clamped<T, R>
    where T: Copy + ops::Mul<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn mul(self, other: T) -> Self::Output {
        Self::new(self.0.mul(other))
    }
}

impl<T, R> ops::Neg for Clamped<T, R>
    where T: Copy + ops::Neg<Output = T> + Num + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn neg(self) -> Self::Output {
        Self::new(self.0.neg())
    }
}

impl<T, R> ops::Sub for Clamped<T, R>
    where T: Copy + Num + ops::Sub<Output = T> + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn sub(self, other: Self) -> Self::Output {
        Self::new(self.0.sub(other.0))
    }
}

impl<T, R> ops::Sub<T> for Clamped<T, R>
    where T: Copy + Num + ops::Sub<Output = T> + cmp::PartialOrd,
          R: ClampedRange<T>
{
    type Output = Self;

    fn sub(self, other: T) -> Self::Output {
        Self::new(self.0.sub(other))
    }
}
<|endoftext|>


<commit_before>extern crate bindgen;
extern crate cc;
extern crate glob;

use std::env;
use std::fs;
use std::path::PathBuf;

fn link(name: &str, bundled: bool) {
    use std::env::var;
    let target = var("TARGET").unwrap();
    let target: Vec<_> = target.split('-').collect();
    if target.get(2) == Some(&"windows") {
        println!("cargo:rustc-link-lib=dylib={}", name);
        if bundled && target.get(3) == Some(&"gnu") {
            let dir = var("CARGO_MANIFEST_DIR").unwrap();
            println!("cargo:rustc-link-search=native={}/{}", dir, target[0]);
        }
    }
}

fn fail_on_empty_directory(name: &str) {
    if fs::read_dir(name).unwrap().count() == 0 {
        println!(
            "The `{}` directory is empty, did you forget to pull the submodules?",
            name
        );
        println!("Try `git submodule update --init --recursive`");
        panic!();
    }
}

fn bindgen_rocksdb() {
    let bindings = bindgen::Builder::default()
        .header("rocksdb/include/rocksdb/c.h")
        .blacklist_type("max_align_t") // https://github.com/rust-lang-nursery/rust-bindgen/issues/550
        .ctypes_prefix("libc")
        .generate()
        .expect("unable to generate rocksdb bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("unable to write rocksdb bindings");
}

fn build_rocksdb() {
    let target = env::var("TARGET").unwrap();

    let mut config = cc::Build::new();
    config.include("rocksdb/include/");
    config.include("rocksdb/");
    config.include("rocksdb/third-party/gtest-1.7.0/fused-src/");

    if cfg!(feature = "snappy") {
        config.define("SNAPPY", Some("1"));
        config.include("snappy/");
    }

    if cfg!(feature = "lz4") {
        config.define("LZ4", Some("1"));
        config.include("lz4/lib/");
    }

    if cfg!(feature = "zstd") {
        config.define("ZSTD", Some("1"));
        config.include("zstd/lib/");
        config.include("zstd/lib/dictBuilder/");
    }

    if cfg!(feature = "zlib") {
        config.define("ZLIB", Some("1"));
        config.include("zlib/");
    }

    if cfg!(feature = "bzip2") {
        config.define("BZIP2", Some("1"));
        config.include("bzip2/");
    }

    config.include(".");
    config.define("NDEBUG", Some("1"));

    let mut lib_sources = include_str!("rocksdb_lib_sources.txt")
        .split("\n")
        .map(str::trim)
        .collect::<Vec<&'static str>>();

    // We have a pregenerated a version of build_version.cc in the local directory
    lib_sources = lib_sources
        .iter()
        .cloned()
        .filter(|file| *file != "util/build_version.cc")
        .collect::<Vec<&'static str>>();

    if target.contains("x86_64") {
        // This is needed to enable hardware CRC32C. Technically, SSE 4.2 is
        // only available since Intel Nehalem (about 2010) and AMD Bulldozer
        // (about 2011).
        config.define("HAVE_PCLMUL", Some("1"));
        config.define("HAVE_SSE42", Some("1"));
        config.flag_if_supported("-msse2");
        config.flag_if_supported("-msse4.1");
        config.flag_if_supported("-msse4.2");
        config.flag_if_supported("-mpclmul");
    }

    if target.contains("darwin") {
        config.define("OS_MACOSX", Some("1"));
        config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
        config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
    }
    if target.contains("linux") {
        config.define("OS_LINUX", Some("1"));
        config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
        config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
        // COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp"
    }
    if target.contains("freebsd") {
        config.define("OS_FREEBSD", Some("1"));
        config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
        config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
    }

    if target.contains("windows") {
        link("rpcrt4", false);
        link("shlwapi", false);
        config.define("OS_WIN", Some("1"));
        config.define("ROCKSDB_WINDOWS_UTF8_FILENAMES", Some("1"));

        // Remove POSIX-specific sources
        lib_sources = lib_sources
            .iter()
            .cloned()
            .filter(|file| match *file {
                "port/port_posix.cc" | "env/env_posix.cc" | "env/io_posix.cc" => false,
                _ => true,
            })
            .collect::<Vec<&'static str>>();

        // Add Windows-specific sources
        lib_sources.push("port/win/port_win.cc");
        lib_sources.push("port/win/env_win.cc");
        lib_sources.push("port/win/env_default.cc");
        lib_sources.push("port/win/win_logger.cc");
        lib_sources.push("port/win/io_win.cc");
        lib_sources.push("port/win/win_thread.cc");
    }

    if target.contains("msvc") {
        config.flag("-EHsc");
    } else {
        config.flag("-std=c++11");
        // this was breaking the build on travis due to
        // > 4mb of warnings emitted.
        config.flag("-Wno-unused-parameter");
    }

    for file in lib_sources {
        let file = "rocksdb/".to_string() + file;
        config.file(&file);
    }

    config.file("build_version.cc");

    config.cpp(true);
    config.compile("librocksdb.a");
}

fn build_snappy() {
    let target = env::var("TARGET").unwrap();

    let mut config = cc::Build::new();
    config.include("snappy/");
    config.include(".");

    config.define("NDEBUG", Some("1"));

    if target.contains("msvc") {
        config.flag("-EHsc");
    } else {
        config.flag("-std=c++11");
    }

    config.file("snappy/snappy.cc");
    config.file("snappy/snappy-sinksource.cc");
    config.file("snappy/snappy-c.cc");
    config.cpp(true);
    config.compile("libsnappy.a");
}

fn build_lz4() {
    let mut compiler = cc::Build::new();

    compiler
        .file("lz4/lib/lz4.c")
        .file("lz4/lib/lz4frame.c")
        .file("lz4/lib/lz4hc.c")
        .file("lz4/lib/xxhash.c");

    compiler.opt_level(3);

    match env::var("TARGET").unwrap().as_str() {
        "i686-pc-windows-gnu" => {
            compiler.flag("-fno-tree-vectorize");
        }
        _ => {}
    }

    compiler.compile("liblz4.a");
}

fn build_zstd() {
    let mut compiler = cc::Build::new();

    compiler.include("zstd/lib/");
    compiler.include("zstd/lib/common");
    compiler.include("zstd/lib/legacy");

    let globs = &[
        "zstd/lib/common/*.c",
        "zstd/lib/compress/*.c",
        "zstd/lib/decompress/*.c",
        "zstd/lib/dictBuilder/*.c",
        "zstd/lib/legacy/*.c",
    ];

    for pattern in globs {
        for path in glob::glob(pattern).unwrap() {
            let path = path.unwrap();
            compiler.file(path);
        }
    }

    compiler.opt_level(3);

    compiler.define("ZSTD_LIB_DEPRECATED", Some("0"));
    compiler.compile("libzstd.a");
}

fn build_zlib() {
    let mut compiler = cc::Build::new();

    let globs = &["zlib/*.c"];

    for pattern in globs {
        for path in glob::glob(pattern).unwrap() {
            let path = path.unwrap();
            compiler.file(path);
        }
    }

    compiler.flag_if_supported("-Wno-implicit-function-declaration");
    compiler.opt_level(3);
    compiler.compile("libz.a");
}

fn build_bzip2() {
    let mut compiler = cc::Build::new();

    compiler
        .file("bzip2/blocksort.c")
        .file("bzip2/bzlib.c")
        .file("bzip2/compress.c")
        .file("bzip2/crctable.c")
        .file("bzip2/decompress.c")
        .file("bzip2/huffman.c")
        .file("bzip2/randtable.c");

    compiler
        .define("_FILE_OFFSET_BITS", Some("64"))
        .define("BZ_NO_STDIO", None);

    compiler.extra_warnings(false);
    compiler.opt_level(3);
    compiler.compile("libbz2.a");
}

fn try_to_find_and_link_lib(lib_name: &str) -> bool {
    if let Ok(lib_dir) = env::var(&format!("{}_LIB_DIR", lib_name)) {
        println!("cargo:rustc-link-search=native={}", lib_dir);
        let mode = match env::var_os(&format!("{}_STATIC", lib_name)) {
            Some(_) => "static",
            None => "dylib",
        };
        println!("cargo:rustc-link-lib={}={}", mode, lib_name.to_lowercase());
        return true;
    }
    false
}

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=rocksdb/");
    println!("cargo:rerun-if-changed=snappy/");
    println!("cargo:rerun-if-changed=lz4/");
    println!("cargo:rerun-if-changed=zstd/");
    println!("cargo:rerun-if-changed=zlib/");
    println!("cargo:rerun-if-changed=bzip2/");

    fail_on_empty_directory("rocksdb");
    fail_on_empty_directory("snappy");
    fail_on_empty_directory("lz4");
    fail_on_empty_directory("zstd");
    fail_on_empty_directory("zlib");
    fail_on_empty_directory("bzip2");

    bindgen_rocksdb();

    if !try_to_find_and_link_lib("ROCKSDB") {
        build_rocksdb();
    }
    if cfg!(feature = "snappy") && !try_to_find_and_link_lib("SNAPPY") {
        build_snappy();
    }
    if cfg!(feature = "lz4") && !try_to_find_and_link_lib("LZ4") {
        build_lz4();
    }
    if cfg!(feature = "zstd") && !try_to_find_and_link_lib("ZSTD") {
        build_zstd();
    }
    if cfg!(feature = "zlib") && !try_to_find_and_link_lib("ZLIB") {
        build_zlib();
    }
    if cfg!(feature = "bzip2") && !try_to_find_and_link_lib("BZIP2") {
        build_bzip2();
    }
}
<commit_msg>Disable  trait derivation for librocksdb-sys (fixes #335)<commit_after>extern crate bindgen;
extern crate cc;
extern crate glob;

use std::env;
use std::fs;
use std::path::PathBuf;

fn link(name: &str, bundled: bool) {
    use std::env::var;
    let target = var("TARGET").unwrap();
    let target: Vec<_> = target.split('-').collect();
    if target.get(2) == Some(&"windows") {
        println!("cargo:rustc-link-lib=dylib={}", name);
        if bundled && target.get(3) == Some(&"gnu") {
            let dir = var("CARGO_MANIFEST_DIR").unwrap();
            println!("cargo:rustc-link-search=native={}/{}", dir, target[0]);
        }
    }
}

fn fail_on_empty_directory(name: &str) {
    if fs::read_dir(name).unwrap().count() == 0 {
        println!(
            "The `{}` directory is empty, did you forget to pull the submodules?",
            name
        );
        println!("Try `git submodule update --init --recursive`");
        panic!();
    }
}

fn bindgen_rocksdb() {
    let bindings = bindgen::Builder::default()
        .header("rocksdb/include/rocksdb/c.h")
        .derive_debug(false)
        .blacklist_type("max_align_t") // https://github.com/rust-lang-nursery/rust-bindgen/issues/550
        .ctypes_prefix("libc")
        .generate()
        .expect("unable to generate rocksdb bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings
        .write_to_file(out_path.join("bindings.rs"))
        .expect("unable to write rocksdb bindings");
}

fn build_rocksdb() {
    let target = env::var("TARGET").unwrap();

    let mut config = cc::Build::new();
    config.include("rocksdb/include/");
    config.include("rocksdb/");
    config.include("rocksdb/third-party/gtest-1.7.0/fused-src/");

    if cfg!(feature = "snappy") {
        config.define("SNAPPY", Some("1"));
        config.include("snappy/");
    }

    if cfg!(feature = "lz4") {
        config.define("LZ4", Some("1"));
        config.include("lz4/lib/");
    }

    if cfg!(feature = "zstd") {
        config.define("ZSTD", Some("1"));
        config.include("zstd/lib/");
        config.include("zstd/lib/dictBuilder/");
    }

    if cfg!(feature = "zlib") {
        config.define("ZLIB", Some("1"));
        config.include("zlib/");
    }

    if cfg!(feature = "bzip2") {
        config.define("BZIP2", Some("1"));
        config.include("bzip2/");
    }

    config.include(".");
    config.define("NDEBUG", Some("1"));

    let mut lib_sources = include_str!("rocksdb_lib_sources.txt")
        .split("\n")
        .map(str::trim)
        .collect::<Vec<&'static str>>();

    // We have a pregenerated a version of build_version.cc in the local directory
    lib_sources = lib_sources
        .iter()
        .cloned()
        .filter(|file| *file != "util/build_version.cc")
        .collect::<Vec<&'static str>>();

    if target.contains("x86_64") {
        // This is needed to enable hardware CRC32C. Technically, SSE 4.2 is
        // only available since Intel Nehalem (about 2010) and AMD Bulldozer
        // (about 2011).
        config.define("HAVE_PCLMUL", Some("1"));
        config.define("HAVE_SSE42", Some("1"));
        config.flag_if_supported("-msse2");
        config.flag_if_supported("-msse4.1");
        config.flag_if_supported("-msse4.2");
        config.flag_if_supported("-mpclmul");
    }

    if target.contains("darwin") {
        config.define("OS_MACOSX", Some("1"));
        config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
        config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
    }
    if target.contains("linux") {
        config.define("OS_LINUX", Some("1"));
        config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
        config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
        // COMMON_FLAGS="$COMMON_FLAGS -fno-builtin-memcmp"
    }
    if target.contains("freebsd") {
        config.define("OS_FREEBSD", Some("1"));
        config.define("ROCKSDB_PLATFORM_POSIX", Some("1"));
        config.define("ROCKSDB_LIB_IO_POSIX", Some("1"));
    }

    if target.contains("windows") {
        link("rpcrt4", false);
        link("shlwapi", false);
        config.define("OS_WIN", Some("1"));
        config.define("ROCKSDB_WINDOWS_UTF8_FILENAMES", Some("1"));

        // Remove POSIX-specific sources
        lib_sources = lib_sources
            .iter()
            .cloned()
            .filter(|file| match *file {
                "port/port_posix.cc" | "env/env_posix.cc" | "env/io_posix.cc" => false,
                _ => true,
            })
            .collect::<Vec<&'static str>>();

        // Add Windows-specific sources
        lib_sources.push("port/win/port_win.cc");
        lib_sources.push("port/win/env_win.cc");
        lib_sources.push("port/win/env_default.cc");
        lib_sources.push("port/win/win_logger.cc");
        lib_sources.push("port/win/io_win.cc");
        lib_sources.push("port/win/win_thread.cc");
    }

    if target.contains("msvc") {
        config.flag("-EHsc");
    } else {
        config.flag("-std=c++11");
        // this was breaking the build on travis due to
        // > 4mb of warnings emitted.
        config.flag("-Wno-unused-parameter");
    }

    for file in lib_sources {
        let file = "rocksdb/".to_string() + file;
        config.file(&file);
    }

    config.file("build_version.cc");

    config.cpp(true);
    config.compile("librocksdb.a");
}

fn build_snappy() {
    let target = env::var("TARGET").unwrap();

    let mut config = cc::Build::new();
    config.include("snappy/");
    config.include(".");

    config.define("NDEBUG", Some("1"));

    if target.contains("msvc") {
        config.flag("-EHsc");
    } else {
        config.flag("-std=c++11");
    }

    config.file("snappy/snappy.cc");
    config.file("snappy/snappy-sinksource.cc");
    config.file("snappy/snappy-c.cc");
    config.cpp(true);
    config.compile("libsnappy.a");
}

fn build_lz4() {
    let mut compiler = cc::Build::new();

    compiler
        .file("lz4/lib/lz4.c")
        .file("lz4/lib/lz4frame.c")
        .file("lz4/lib/lz4hc.c")
        .file("lz4/lib/xxhash.c");

    compiler.opt_level(3);

    match env::var("TARGET").unwrap().as_str() {
        "i686-pc-windows-gnu" => {
            compiler.flag("-fno-tree-vectorize");
        }
        _ => {}
    }

    compiler.compile("liblz4.a");
}

fn build_zstd() {
    let mut compiler = cc::Build::new();

    compiler.include("zstd/lib/");
    compiler.include("zstd/lib/common");
    compiler.include("zstd/lib/legacy");

    let globs = &[
        "zstd/lib/common/*.c",
        "zstd/lib/compress/*.c",
        "zstd/lib/decompress/*.c",
        "zstd/lib/dictBuilder/*.c",
        "zstd/lib/legacy/*.c",
    ];

    for pattern in globs {
        for path in glob::glob(pattern).unwrap() {
            let path = path.unwrap();
            compiler.file(path);
        }
    }

    compiler.opt_level(3);

    compiler.define("ZSTD_LIB_DEPRECATED", Some("0"));
    compiler.compile("libzstd.a");
}

fn build_zlib() {
    let mut compiler = cc::Build::new();

    let globs = &["zlib/*.c"];

    for pattern in globs {
        for path in glob::glob(pattern).unwrap() {
            let path = path.unwrap();
            compiler.file(path);
        }
    }

    compiler.flag_if_supported("-Wno-implicit-function-declaration");
    compiler.opt_level(3);
    compiler.compile("libz.a");
}

fn build_bzip2() {
    let mut compiler = cc::Build::new();

    compiler
        .file("bzip2/blocksort.c")
        .file("bzip2/bzlib.c")
        .file("bzip2/compress.c")
        .file("bzip2/crctable.c")
        .file("bzip2/decompress.c")
        .file("bzip2/huffman.c")
        .file("bzip2/randtable.c");

    compiler
        .define("_FILE_OFFSET_BITS", Some("64"))
        .define("BZ_NO_STDIO", None);

    compiler.extra_warnings(false);
    compiler.opt_level(3);
    compiler.compile("libbz2.a");
}

fn try_to_find_and_link_lib(lib_name: &str) -> bool {
    if let Ok(lib_dir) = env::var(&format!("{}_LIB_DIR", lib_name)) {
        println!("cargo:rustc-link-search=native={}", lib_dir);
        let mode = match env::var_os(&format!("{}_STATIC", lib_name)) {
            Some(_) => "static",
            None => "dylib",
        };
        println!("cargo:rustc-link-lib={}={}", mode, lib_name.to_lowercase());
        return true;
    }
    false
}

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=rocksdb/");
    println!("cargo:rerun-if-changed=snappy/");
    println!("cargo:rerun-if-changed=lz4/");
    println!("cargo:rerun-if-changed=zstd/");
    println!("cargo:rerun-if-changed=zlib/");
    println!("cargo:rerun-if-changed=bzip2/");

    fail_on_empty_directory("rocksdb");
    fail_on_empty_directory("snappy");
    fail_on_empty_directory("lz4");
    fail_on_empty_directory("zstd");
    fail_on_empty_directory("zlib");
    fail_on_empty_directory("bzip2");

    bindgen_rocksdb();

    if !try_to_find_and_link_lib("ROCKSDB") {
        build_rocksdb();
    }
    if cfg!(feature = "snappy") && !try_to_find_and_link_lib("SNAPPY") {
        build_snappy();
    }
    if cfg!(feature = "lz4") && !try_to_find_and_link_lib("LZ4") {
        build_lz4();
    }
    if cfg!(feature = "zstd") && !try_to_find_and_link_lib("ZSTD") {
        build_zstd();
    }
    if cfg!(feature = "zlib") && !try_to_find_and_link_lib("ZLIB") {
        build_zlib();
    }
    if cfg!(feature = "bzip2") && !try_to_find_and_link_lib("BZIP2") {
        build_bzip2();
    }
}
<|endoftext|>


<commit_before>/// Error types

error_chain! {
    types {
        Error, ErrorKind, ResultExt, Result;
    }

    errors {

        // Errors for tokenizer

        QueryParsingError(query: String) {
            description("parsing the query failed")
            display("Parsing the query '{}' failed", query)
        }

        EmptyQueryError {
            description("the query is empty")
            display("The query on the TOML is empty")
        }

        EmptyIdentifier {
            description("Query an empty identifier: ''")
            display("The passed query has an empty identifier")
        }

        ArrayAccessWithoutIndex {
            description("trying to access array without index")
            display("The passed query tries to access an array but does not specify the index")
        }

        ArrayAccessWithInvalidIndex {
            description("trying to pass an invalid index")
            display("The passed query tries to access an array but does not specify a valid index")
        }

        // Errors for Resolver

        IdentifierNotFoundInDocument(ident: String) {
            description("Identifier missing in document")
            display("The identfier '{}' is not present in the document", ident)
        }

    }
}
<commit_msg>Add error types for type failure<commit_after>/// Error types

error_chain! {
    types {
        Error, ErrorKind, ResultExt, Result;
    }

    errors {

        // Errors for tokenizer

        QueryParsingError(query: String) {
            description("parsing the query failed")
            display("Parsing the query '{}' failed", query)
        }

        EmptyQueryError {
            description("the query is empty")
            display("The query on the TOML is empty")
        }

        EmptyIdentifier {
            description("Query an empty identifier: ''")
            display("The passed query has an empty identifier")
        }

        ArrayAccessWithoutIndex {
            description("trying to access array without index")
            display("The passed query tries to access an array but does not specify the index")
        }

        ArrayAccessWithInvalidIndex {
            description("trying to pass an invalid index")
            display("The passed query tries to access an array but does not specify a valid index")
        }

        // Errors for Resolver

        IdentifierNotFoundInDocument(ident: String) {
            description("Identifier missing in document")
            display("The identfier '{}' is not present in the document", ident)
        }

        NoIndexInTable(i: usize) {
            description("Cannot deref index from table")
            display("Got an index query '[{}]' but have table", i)
        }

        NoIdentifierInArray(s: String) {
            description("Cannot query identifier in array")
            display("Got an identifier query '{}' but have array", s)
        }

    }
}
<|endoftext|>


<commit_before>use std::error;
use std::fmt;
use std::io;

use c_ares;

/// Error codes that the library might return.
#[derive(Debug)]
pub enum Error {
    /// An `io::Error`.
    Io(io::Error),

    /// A `c_ares::Error`.
    Ares(c_ares::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref err) => err.fmt(f),
            Error::Ares(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::Ares(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::Io(ref err) => Some(err),
            Error::Ares(ref err) => Some(err),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<c_ares::Error> for Error {
    fn from(err: c_ares::Error) -> Error {
        Error::Ares(err)
    }
}
<commit_msg>Explicit dyn<commit_after>use std::error;
use std::fmt;
use std::io;

use c_ares;

/// Error codes that the library might return.
#[derive(Debug)]
pub enum Error {
    /// An `io::Error`.
    Io(io::Error),

    /// A `c_ares::Error`.
    Ares(c_ares::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref err) => err.fmt(f),
            Error::Ares(ref err) => err.fmt(f),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::Ares(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&dyn error::Error> {
        match *self {
            Error::Io(ref err) => Some(err),
            Error::Ares(ref err) => Some(err),
        }
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl From<c_ares::Error> for Error {
    fn from(err: c_ares::Error) -> Error {
        Error::Ares(err)
    }
}
<|endoftext|>