<commit_before>use std::fmt::{self, Write, Debug, Formatter};
use std::mem;
use std::ops::{Deref, DerefMut};

use gtk::signal::Inhibit;
use gdk::EventKey;

use logic::{Token, Tokens};
use logic::consts::ALLOWED_CHARS;

#[derive(Clone)]
pub struct Line {
	/// The line number of the proof, starting at 0. It is only visually where everything is incremented
	pub no: usize,
	/// A step of the proof. e.g. (P\^Q)->P. This is a vector of tokens that can be invalid.
	pub step: Tokens,
	/// A token string representing the method of the proof.
	pub method: Tokens,
	/// Line numbers that this depends on. Line numbers start at 0.
	pub deps: Vec<usize>,
}
impl Line {
	/// Constructs an empty line
	pub fn new(no: usize) -> Line {
		Line {
			no: no,
			step: Tokens::new(),
			method: Tokens::new(),
			deps: Vec::new(),
		}
	}
	/// Constructs a line with the specified tokens in the `step` field.
	pub fn with_step(no: usize, step: Tokens) -> Line {
		Line {
			no: no,
			step: step,
			method: Tokens::new(),
			deps: Vec::new(),
		}
	}
	pub fn full(no: usize, step: Tokens, method: Tokens, deps: Vec<usize>) -> Line {
		Line {
			no: no,
			step: step,
			method: method,
			deps: deps,
		}
	}

	pub fn fmt_cursor(&self, f: &mut Formatter, c: &Cursor) -> Result<(), fmt::Error> {
		let mut step_str = String::with_capacity(self.step.len() + 16);
		if !f.alternate() {
			for (i, t) in self.step.iter().enumerate() {
				if c.no == self.no && c.col == Col::Step && c.i == i {
					step_str.push('|');
				}
				try!(write!(step_str, "{}", t));
			}
		} else {
			for (i, t) in self.step.iter().enumerate() {
				if c.no == self.no && c.col == Col::Step && c.i == i {
					step_str.push('|');
				}
				try!(write!(step_str, "{:#}", t));
			}
		}
		if c.no == self.no && c.col == Col::Step && c.i == self.step.len() {
			step_str.push('|');
		}

		let mut dep_str = String::with_capacity(self.deps.len() * 2);
		for (i, dep) in self.deps.iter().enumerate() {
			try!(write!(dep_str, "{}", dep + 1));
			if i < self.deps.len() - 1 {
				dep_str.push_str(", ")
			}
		}

		let mut method_str = String::with_capacity(self.method.len() + 8);
		if c.no == self.no && c.col == Col::Method && (c.i <= self.method.len() || self.method.len() == 0) {
			let (a, b) = self.method.split_at(c.i);
			if !f.alternate() {
				for t in a {
					try!(write!(method_str, "{}", t));
				}
				method_str.push('|');
				for t in b {
					try!(write!(method_str, "{}", t));
				}
			} else {
				for t in a {
					try!(write!(method_str, "{:#}", t));
				}
				method_str.push('|');
				for t in b {
					try!(write!(method_str, "{:#}", t));
				}
			}
		} else {
			if !f.alternate() {
				for t in self.method.iter() {
					try!(write!(method_str, "{}", t));
				}
			} else {
				for t in self.method.iter() {
					try!(write!(method_str, "{:#}", t));
				}
			}
		}
		f.pad(&format!("{: >3}. {: <20} {: <10} {{{}}}", self.no + 1, step_str, method_str, dep_str))
	}

	/// True if `self.step` and `self.method` are empty
	pub fn is_empty(&self) -> bool {
		self.step.is_empty() && self.method.is_empty()
	}

	/// Simplifies all `Tokens` structs contained within this struct.
	pub fn simplify(&mut self) {
		self.step.simplify();
		self.method.simplify();
	}
}

#[derive(Clone)]
pub struct Lines {
	inner: Vec<Line>
}
impl Lines {
	/// Creates a lines object with one line.
	pub fn new() -> Lines {
		Lines {
			inner: vec![Line::new(0)]
		}
	}
	/// Creates a lines object from a vector.
	pub fn from_vec(v: Vec<Line>) -> Lines {
		Lines {
			inner: v
		}
	}

	/// Inserts `nl` at `nl.no` in `lines`, and updates all line numbers in `lines`
	pub fn insert_line(&mut self, nl: Line) {
		let no = nl.no;
		for l in self.iter_mut() {
			if l.no >= no {
				l.no += 1;
			}
		}
		self.insert(no, nl);
	}
	/// Deletes the line at `no` in `lines`, and updates all line numbers in `lines`
	pub fn delete_line(&mut self, no: usize) {
		self.inner.remove(no);
		for l in self.iter_mut() {
			if l.no >= no {
				l.no -= 1;
			}
		}
	}

	/// Simplifies all the lines that this structure holds.
	pub fn simplify(&mut self) {
		for l in self.iter_mut() {
			l.simplify();
		}
	}

	/// Inserts token `tok` at `cursor` pos.
	/// Returns Ok(n) with n being the number of tokens removed.
	pub fn insert_at(&mut self, cursor: &Cursor, tok: Token) -> Result<usize, ()> {
		let toks = match cursor.col {
			Col::Step   => &mut self[cursor.no].step,
			Col::Method => &mut self[cursor.no].method,
		};
		toks.insert(cursor.i, tok);
		let n = toks.simplify();
		Ok(n)
	}
}
impl Deref for Lines {
	type Target = Vec<Line>;
	fn deref(&self) -> &Vec<Line> {
		&self.inner
	}
}
impl DerefMut for Lines {
	fn deref_mut(&mut self) -> &mut Vec<Line> {
		&mut self.inner
	}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Col {
	Step,
	Method,
}
#[derive(Debug, PartialEq, Eq)]
pub struct Cursor {
	/// Line number
	no: usize,
	/// Column
	col: Col,
	/// Index of token/string
	i: usize,
}
impl Cursor {
	pub fn new() -> Cursor {
		Cursor {
			no: 0,
			col: Col::Step,
			i: 0,
		}
	}
	/// Move the cursor to the right. Wrap at end of line. Error at end of text.
	pub fn right(&mut self, lines: &Lines) -> Result<(), ()> {
		let l = match lines.get(self.no) {
			Some(l) => l,
			None    => { *self = Cursor::new(); return Err(()); },
		};
		self.i += 1;
		match self.col {
			Col::Step => {
				if self.i > l.step.len() {
					self.col = Col::Method;
					self.i = 0;
				}
				Ok(())
			}
			Col::Method => {
				if self.i > l.method.len() {
					if self.no < lines.len() - 1 {
						self.no += 1;
						self.col = Col::Step;
						self.i = 0;
						Ok(())
					} else {
						self.i -= 1;
						Err(())
					}
				} else {
					Ok(())
				}
			}
		}
	}
	/// Move the cursor to the left. Wrap at start of line. Error at start of text.
	pub fn left(&mut self, lines: &Lines) -> Result<(), ()> {
		let l = match lines.get(self.no) {
			Some(l) => l,
			None    => { *self = Cursor::new(); return Err(()); },
		};

		if self.i == 0 {
			match self.col {
				Col::Step => {
					if self.no > 0 {
						self.no -= 1;
						self.col = Col::Method;
						self.i = match lines.get(self.no) {
							Some(l) => l.method.len(),
							None    => { *self = Cursor::new(); return Err(()); },
						};
					}
				}
				Col::Method => {
					self.col = Col::Step;
					self.i = l.step.len();
				}
			}
		} else {
			self.i -= 1;
		}
		Ok(())
	}

	/// Is end of tokens
	/// Returns true if at the end of `Col::Step` or `Col::Method`
	fn is_eot(&self, lines: &Lines) -> bool {
		self.i == match self.col {
			Col::Step   => lines[self.no].step.len(),
			Col::Method => lines[self.no].method.len(),
		}
	}

	/// Delete the character in front of the cursor. If on an empty line && at the end, delete line. If no chars in front, returns `Err(())`.
	pub fn delete(&mut self, lines: &mut Lines) -> Result<(), ()> {
		if lines[self.no].is_empty() && self.col == Col::Method {
			if lines.len() == 1 {
				return Err(());
			}
			// Delete the line
			lines.delete_line(self.no);

			if self.no != 0 { self.no -= 1; };
			self.i = 0;

			Ok(())
		} else if self.is_eot(lines) {
			Err(())
		} else {
			// Delete char in front
			match self.col {
				Col::Step   => { let _ = lines[self.no].step.remove(self.i); },
				Col::Method => { let _ = lines[self.no].method.remove(self.i); },
			}
			Ok(())
		}
	}
	/// Delete the character behind the character. If on an empty line && at the start, delete line. If no chars behind, returns `Err(())`
	pub fn backspace(&mut self, lines: &mut Lines) -> Result<(), ()> {
		if lines[self.no].is_empty() && self.col == Col::Step {
			if lines.len() == 1 {
				return Err(());
			}
			// Delete the line
			lines.delete_line(self.no);

			if self.no != 0 { self.no -= 1; };
			self.i = 0;

			Ok(())
		} else if self.i == 0 {
			Err(())
		} else {
			// Delete char behind the cursor
			match self.col {
				Col::Step   => { let _ = lines[self.no].step.remove(self.i - 1); },
				Col::Method => { let _ = lines[self.no].method.remove(self.i - 1); },
			}
			self.i -= 1;
			Ok(())
		}
	}
	/// Add a newline to `lines` if the cursor is at the end of the line.
	pub fn newline(&mut self, lines: &mut Lines) -> Result<(), ()> {
		if !self.is_eot(lines) {
			// Don't place a newline if the cursor isn't at the end of the line.
			return Err(());
		}

		lines.insert_line(Line::new(self.no + 1));

		self.no += 1;
		self.i = 0;

		Ok(())
	}
	/// Inserts a token at the cursor pos in `lines`. Simplifies the line affected.
	pub fn insert(&mut self, lines: &mut Lines, c: Token) -> Result<(), ()> {
		let ret = lines.insert_at(self, c);
		if let Ok(n) = ret {
			self.i += 1;
			self.i -= n;
		}
		ret.map(|_| ())
	}
}

pub struct Editor {
	lines: Lines,
	cursor: Cursor,
}

impl<'a> Editor {
	/// Constructs a new editor
	pub fn new() -> Editor {
		Editor {
			lines: Lines::from_vec(vec![
			           Line::full(0, Tokens::from_str("P"), Tokens::from_str("Premise"), vec![0]),
			           Line::full(1, Tokens::from_str("¬¬P"), Tokens::from_str("¬I 1"), vec![0])
			       ]),
			cursor: Cursor::new(),
		}
	}
	/// Gets a ref to the line numbered `v` in the proof.
	pub fn line(&'a self, v: usize) -> Option<&'a Line> {
		self.lines.get(v - 1)
	}
	/// Gets the number of lines in the proof.
	pub fn lines(&self) -> usize {
		self.lines.len()
	}
	/// Handles the input given to it, and whether to pass the input on or not.
	pub fn handle_input(&mut self, e: &EventKey) -> Inhibit {
		use gdk::enums::key;
		use gdk::{keyval_to_unicode, keyval_name};

		let c = keyval_to_unicode(e.keyval).unwrap_or(' ');
		let name = keyval_name(e.keyval).unwrap_or(" ".to_string());
		println!("keypress: {0:#08x} : {1} : {2}", e.keyval, c, name);

		match unsafe { mem::transmute(e.keyval) } {
			key::Right => {
				let _ = self.cursor.right(&self.lines);
			},
			key::Left => {
				let _ = self.cursor.left(&self.lines);
			},
			key::Delete => {
				let _ = self.cursor.delete(&mut self.lines);
			},
			key::Return => {
				let _ = self.cursor.newline(&mut self.lines);
			},
			key::BackSpace => {
				let _ = self.cursor.backspace(&mut self.lines);
			},
			_ => {
				let _ = self.cursor.insert(&mut self.lines, match keyval_to_unicode(e.keyval) {
					Some(c) if c.is_alphabetic() || ALLOWED_CHARS.contains(c) => Token::Char(c),
					_ => { return Inhibit(false); },
				});
			}
		}
		println!(" *** Editor *** - Cursor: {:?} \n{:#?}", self.cursor, self);
		Inhibit(true)
	}
}
impl Debug for Editor {
	fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
		for l in self.lines.iter() {
			try!(l.fmt_cursor(f, &self.cursor));
			try!(writeln!(f, ""));
		}
		Ok(())
	}
}
<commit_msg>Fix backspace special cases<commit_after>use std::fmt::{self, Write, Debug, Formatter};
use std::mem;
use std::ops::{Deref, DerefMut};

use gtk::signal::Inhibit;
use gdk::EventKey;

use logic::{Token, Tokens};
use logic::consts::ALLOWED_CHARS;

#[derive(Clone)]
pub struct Line {
	/// The line number of the proof, starting at 0. It is only visually where everything is incremented
	pub no: usize,
	/// A step of the proof. e.g. (P\^Q)->P. This is a vector of tokens that can be invalid.
	pub step: Tokens,
	/// A token string representing the method of the proof.
	pub method: Tokens,
	/// Line numbers that this depends on. Line numbers start at 0.
	pub deps: Vec<usize>,
}
impl Line {
	/// Constructs an empty line
	pub fn new(no: usize) -> Line {
		Line {
			no: no,
			step: Tokens::new(),
			method: Tokens::new(),
			deps: Vec::new(),
		}
	}
	/// Constructs a line with the specified tokens in the `step` field.
	pub fn with_step(no: usize, step: Tokens) -> Line {
		Line {
			no: no,
			step: step,
			method: Tokens::new(),
			deps: Vec::new(),
		}
	}
	pub fn full(no: usize, step: Tokens, method: Tokens, deps: Vec<usize>) -> Line {
		Line {
			no: no,
			step: step,
			method: method,
			deps: deps,
		}
	}

	pub fn fmt_cursor(&self, f: &mut Formatter, c: &Cursor) -> Result<(), fmt::Error> {
		let mut step_str = String::with_capacity(self.step.len() + 16);
		if !f.alternate() {
			for (i, t) in self.step.iter().enumerate() {
				if c.no == self.no && c.col == Col::Step && c.i == i {
					step_str.push('|');
				}
				try!(write!(step_str, "{}", t));
			}
		} else {
			for (i, t) in self.step.iter().enumerate() {
				if c.no == self.no && c.col == Col::Step && c.i == i {
					step_str.push('|');
				}
				try!(write!(step_str, "{:#}", t));
			}
		}
		if c.no == self.no && c.col == Col::Step && c.i == self.step.len() {
			step_str.push('|');
		}

		let mut dep_str = String::with_capacity(self.deps.len() * 2);
		for (i, dep) in self.deps.iter().enumerate() {
			try!(write!(dep_str, "{}", dep + 1));
			if i < self.deps.len() - 1 {
				dep_str.push_str(", ")
			}
		}

		let mut method_str = String::with_capacity(self.method.len() + 8);
		if c.no == self.no && c.col == Col::Method && (c.i <= self.method.len() || self.method.len() == 0) {
			let (a, b) = self.method.split_at(c.i);
			if !f.alternate() {
				for t in a {
					try!(write!(method_str, "{}", t));
				}
				method_str.push('|');
				for t in b {
					try!(write!(method_str, "{}", t));
				}
			} else {
				for t in a {
					try!(write!(method_str, "{:#}", t));
				}
				method_str.push('|');
				for t in b {
					try!(write!(method_str, "{:#}", t));
				}
			}
		} else {
			if !f.alternate() {
				for t in self.method.iter() {
					try!(write!(method_str, "{}", t));
				}
			} else {
				for t in self.method.iter() {
					try!(write!(method_str, "{:#}", t));
				}
			}
		}
		f.pad(&format!("{: >3}. {: <20} {: <10} {{{}}}", self.no + 1, step_str, method_str, dep_str))
	}

	/// True if `self.step` and `self.method` are empty
	pub fn is_empty(&self) -> bool {
		self.step.is_empty() && self.method.is_empty()
	}

	/// Simplifies all `Tokens` structs contained within this struct.
	pub fn simplify(&mut self) {
		self.step.simplify();
		self.method.simplify();
	}
}

#[derive(Clone)]
pub struct Lines {
	inner: Vec<Line>
}
impl Lines {
	/// Creates a lines object with one line.
	pub fn new() -> Lines {
		Lines {
			inner: vec![Line::new(0)]
		}
	}
	/// Creates a lines object from a vector.
	pub fn from_vec(v: Vec<Line>) -> Lines {
		Lines {
			inner: v
		}
	}

	/// Inserts `nl` at `nl.no` in `lines`, and updates all line numbers in `lines`
	pub fn insert_line(&mut self, nl: Line) {
		let no = nl.no;
		for l in self.iter_mut() {
			if l.no >= no {
				l.no += 1;
			}
		}
		self.insert(no, nl);
	}
	/// Deletes the line at `no` in `lines`, and updates all line numbers in `lines`
	pub fn delete_line(&mut self, no: usize) {
		self.inner.remove(no);
		for l in self.iter_mut() {
			if l.no >= no {
				l.no -= 1;
			}
		}
	}

	/// Simplifies all the lines that this structure holds.
	pub fn simplify(&mut self) {
		for l in self.iter_mut() {
			l.simplify();
		}
	}

	/// Inserts token `tok` at `cursor` pos.
	/// Returns Ok(n) with n being the number of tokens removed.
	pub fn insert_at(&mut self, cursor: &Cursor, tok: Token) -> Result<usize, ()> {
		let toks = match cursor.col {
			Col::Step   => &mut self[cursor.no].step,
			Col::Method => &mut self[cursor.no].method,
		};
		toks.insert(cursor.i, tok);
		let n = toks.simplify();
		Ok(n)
	}
}
impl Deref for Lines {
	type Target = Vec<Line>;
	fn deref(&self) -> &Vec<Line> {
		&self.inner
	}
}
impl DerefMut for Lines {
	fn deref_mut(&mut self) -> &mut Vec<Line> {
		&mut self.inner
	}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Col {
	Step,
	Method,
}
#[derive(Debug, PartialEq, Eq)]
pub struct Cursor {
	/// Line number
	no: usize,
	/// Column
	col: Col,
	/// Index of token/string
	i: usize,
}
impl Cursor {
	pub fn new() -> Cursor {
		Cursor {
			no: 0,
			col: Col::Step,
			i: 0,
		}
	}
	/// Move the cursor to the right. Wrap at end of line. Error at end of text.
	pub fn right(&mut self, lines: &Lines) -> Result<(), ()> {
		let l = match lines.get(self.no) {
			Some(l) => l,
			None    => { *self = Cursor::new(); return Err(()); },
		};
		self.i += 1;
		match self.col {
			Col::Step => {
				if self.i > l.step.len() {
					self.col = Col::Method;
					self.i = 0;
				}
				Ok(())
			}
			Col::Method => {
				if self.i > l.method.len() {
					if self.no < lines.len() - 1 {
						self.no += 1;
						self.col = Col::Step;
						self.i = 0;
						Ok(())
					} else {
						self.i -= 1;
						Err(())
					}
				} else {
					Ok(())
				}
			}
		}
	}
	/// Move the cursor to the left. Wrap at start of line. Error at start of text.
	pub fn left(&mut self, lines: &Lines) -> Result<(), ()> {
		let l = match lines.get(self.no) {
			Some(l) => l,
			None    => { *self = Cursor::new(); return Err(()); },
		};

		if self.i == 0 {
			match self.col {
				Col::Step => {
					if self.no > 0 {
						self.no -= 1;
						self.col = Col::Method;
						self.i = match lines.get(self.no) {
							Some(l) => l.method.len(),
							None    => { *self = Cursor::new(); return Err(()); },
						};
					}
				}
				Col::Method => {
					self.col = Col::Step;
					self.i = l.step.len();
				}
			}
		} else {
			self.i -= 1;
		}
		Ok(())
	}

	/// Is end of tokens
	/// Returns true if at the end of `Col::Step` or `Col::Method`
	fn is_eot(&self, lines: &Lines) -> bool {
		self.i == match self.col {
			Col::Step   => lines[self.no].step.len(),
			Col::Method => lines[self.no].method.len(),
		}
	}

	/// Delete the character in front of the cursor. If on an empty line && at the end, delete line. If no chars in front, returns `Err(())`.
	pub fn delete(&mut self, lines: &mut Lines) -> Result<(), ()> {
		if lines[self.no].is_empty() && self.col == Col::Method {
			if lines.len() == 1 {
				return Err(());
			}
			// Delete the line
			lines.delete_line(self.no);

			if self.no != 0 { self.no -= 1; };
			self.i = 0;

			Ok(())
		} else if self.is_eot(lines) {
			Err(())
		} else {
			// Delete char in front
			match self.col {
				Col::Step   => { let _ = lines[self.no].step.remove(self.i); },
				Col::Method => { let _ = lines[self.no].method.remove(self.i); },
			}
			Ok(())
		}
	}
	/// Delete the character behind the character. If on an empty line && at the start, delete line. If no chars behind, returns `Err(())`
	pub fn backspace(&mut self, lines: &mut Lines) -> Result<(), ()> {
		if self.col == Col::Method && lines[self.no].method.is_empty() {
			self.left(lines)
		} else if lines[self.no].is_empty() && self.col == Col::Step {
			if lines.len() == 1 {
				return Err(());
			}
			// Delete the line
			lines.delete_line(self.no);

			if self.no != 0 { self.no -= 1; };
			self.i = 0;

			Ok(())
		} else if self.i == 0 {
			Err(())
		} else {
			// Delete char behind the cursor
			match self.col {
				Col::Step   => { let _ = lines[self.no].step.remove(self.i - 1); },
				Col::Method => { let _ = lines[self.no].method.remove(self.i - 1); },
			}
			self.i -= 1;
			Ok(())
		}
	}
	/// Add a newline to `lines` if the cursor is at the end of the line.
	pub fn newline(&mut self, lines: &mut Lines) -> Result<(), ()> {
		if !self.is_eot(lines) {
			// Don't place a newline if the cursor isn't at the end of the line.
			return Err(());
		}

		lines.insert_line(Line::new(self.no + 1));

		self.no += 1;
		self.i = 0;

		Ok(())
	}
	/// Inserts a token at the cursor pos in `lines`. Simplifies the line affected.
	pub fn insert(&mut self, lines: &mut Lines, c: Token) -> Result<(), ()> {
		let ret = lines.insert_at(self, c);
		if let Ok(n) = ret {
			self.i += 1;
			self.i -= n;
		}
		ret.map(|_| ())
	}
}

pub struct Editor {
	lines: Lines,
	cursor: Cursor,
}

impl<'a> Editor {
	/// Constructs a new editor
	pub fn new() -> Editor {
		Editor {
			lines: Lines::from_vec(vec![
			           Line::full(0, Tokens::from_str("P"), Tokens::from_str("Premise"), vec![0]),
			           Line::full(1, Tokens::from_str("¬¬P"), Tokens::from_str("¬I 1"), vec![0])
			       ]),
			cursor: Cursor::new(),
		}
	}
	/// Gets a ref to the line numbered `v` in the proof.
	pub fn line(&'a self, v: usize) -> Option<&'a Line> {
		self.lines.get(v - 1)
	}
	/// Gets the number of lines in the proof.
	pub fn lines(&self) -> usize {
		self.lines.len()
	}
	/// Handles the input given to it, and whether to pass the input on or not.
	pub fn handle_input(&mut self, e: &EventKey) -> Inhibit {
		use gdk::enums::key;
		use gdk::{keyval_to_unicode, keyval_name};

		let c = keyval_to_unicode(e.keyval).unwrap_or(' ');
		let name = keyval_name(e.keyval).unwrap_or(" ".to_string());
		println!("keypress: {0:#08x} : {1} : {2}", e.keyval, c, name);

		match unsafe { mem::transmute(e.keyval) } {
			key::Right => {
				let _ = self.cursor.right(&self.lines);
			},
			key::Left => {
				let _ = self.cursor.left(&self.lines);
			},
			key::Delete => {
				let _ = self.cursor.delete(&mut self.lines);
			},
			key::Return => {
				let _ = self.cursor.newline(&mut self.lines);
			},
			key::BackSpace => {
				let _ = self.cursor.backspace(&mut self.lines);
			},
			_ => {
				let _ = self.cursor.insert(&mut self.lines, match keyval_to_unicode(e.keyval) {
					Some(c) if c.is_alphabetic() || ALLOWED_CHARS.contains(c) => Token::Char(c),
					_ => { return Inhibit(false); },
				});
			}
		}
		println!(" *** Editor *** - Cursor: {:?} \n{:#?}", self.cursor, self);
		Inhibit(true)
	}
}
impl Debug for Editor {
	fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
		for l in self.lines.iter() {
			try!(l.fmt_cursor(f, &self.cursor));
			try!(writeln!(f, ""));
		}
		Ok(())
	}
}
<|endoftext|>


<commit_before>use luminance::{Dim2, Flat, RGBA32F, Texture};
use serde_json::from_reader;
use std::fs::File;
use std::path::Path;

use resource::{Load, LoadError, Result, ResCache};

/// Time.
pub type Time = f32;

/// A clip is an object that implements a visual sequence.
pub struct Clip<'a, 'b> where 'a: 'b {
  act: Box<Fn(Time) -> &'a Texture<Flat, Dim2, RGBA32F> + 'b>
}

impl<'a, 'b> Clip<'a, 'b> {
  pub fn new<F>(act: F) -> Self where F: 'b + Fn(Time) -> &'a Texture<Flat, Dim2, RGBA32F> {
    Clip {
      act: Box::new(act)
    }
  }
}

/// A cut is an object that slices a `Clip` at an *input time* and *output time*. It is instantiated
/// in a `Track` at a given *instance time*.
#[derive(Clone)]
pub struct Cut<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub in_time: Time,
  pub out_time: Time,
  pub inst_time: Time,
  pub clip: &'c Clip<'a, 'b>
}

impl<'a, 'b, 'c> Cut<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub fn new(in_time: Time, out_time: Time, inst_time: Time, clip: &'c Clip<'a, 'b>) -> Self {
    assert!(in_time <= out_time);

    Cut {
      in_time: in_time,
      out_time: out_time,
      inst_time: inst_time,
      clip: clip
    }
  }

  /// Duration of the cut.
  pub fn dur(&self) -> Time {
    self.out_time - self.in_time
  }
}

/// A track gathers `Cut`s and its purpose is to be used inside a `Timeline`.
#[derive(Clone)]
pub struct Track<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  cuts: Vec<Cut<'a, 'b, 'c>>
}

impl<'a, 'b, 'c> Track<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub fn new() -> Self {
    Track {
      cuts: Vec::new()
    }
  }

  pub fn add_cut(&mut self, cut: Cut<'a, 'b, 'c>) {
    self.cuts.push(cut);
  }
}

impl<'a, 'b, 'c, 'd> From<&'d [Cut<'a, 'b, 'c>]> for Track<'a, 'b, 'c> {
  fn from(cuts: &'d [Cut<'a, 'b, 'c>]) -> Self {
    Track {
      cuts: cuts.to_vec()
    }
  }
}

/// A timeline gathers tracks used to build up the visual aspect of the demo.
#[derive(Clone)]
pub struct Timeline<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  tracks: Vec<Track<'a, 'b, 'c>>,
}

impl<'a, 'b, 'c> Timeline<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub fn new() -> Self {
    Timeline {
      tracks: Vec::new(),
    }
  }

  pub fn add_track(&mut self, track: Track<'a, 'b, 'c>) {
    self.tracks.push(track);
  }

  // TODO: currently, we play the first track we find; add transition support
  pub fn play(&self, t: Time) -> Option<&'a Texture<Flat, Dim2, RGBA32F>> {
    for track in &self.tracks {
      for cut in &track.cuts {
        if cut.inst_time <= t && t <= cut.inst_time + cut.dur() {
          return Some((cut.clip.act)(t));
        }
      }
    }

    None
  }
}

impl<'a, 'b, 'c, 'd> From<&'d [Track<'a, 'b, 'c>]> for Timeline<'a, 'b, 'c> {
  fn from(tracks: &'d [Track<'a, 'b, 'c>]) -> Self {
    Timeline {
      tracks: tracks.to_vec(),
    }
  }
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct TimelineManifest {
  pub tracks: Vec<TrackManifest>
}

impl Load for TimelineManifest {
  type Args = ();

  const TY_STR: &'static str = "edit/timelines";

  fn load<P>(path: P, cache: &mut ResCache, args: Self::Args) -> Result<Self> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading timeline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let tracks = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(TimelineManifest {
      tracks: tracks
    })
  }
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct TrackManifest {
  pub cuts: Vec<CutManifest>
}

impl Load for TrackManifest {
  type Args = ();

  const TY_STR: &'static str = "edit/tracks";

  fn load<P>(path: P, cache: &mut ResCache, args: Self::Args) -> Result<Self> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading track: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    let cuts = from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))?;

    Ok(TrackManifest {
      cuts: cuts
    })
  }
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CutManifest {
  pub in_time: Time,
  pub out_time: Time,
  pub inst_time: Time,
  pub clip: String
}

impl Load for CutManifest {
  type Args = ();

  const TY_STR: &'static str = "edit/cuts";

  fn load<P>(path: P, cache: &mut ResCache, args: Self::Args) -> Result<Self> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading cut: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))
  }
}
<commit_msg>Fixed Load impls for *Manifest in edit.rs.<commit_after>use luminance::{Dim2, Flat, RGBA32F, Texture};
use serde_json::from_reader;
use std::fs::File;
use std::path::Path;

use resource::{Load, LoadError, Result, ResCache};

/// Time.
pub type Time = f32;

/// A clip is an object that implements a visual sequence.
pub struct Clip<'a, 'b> where 'a: 'b {
  act: Box<Fn(Time) -> &'a Texture<Flat, Dim2, RGBA32F> + 'b>
}

impl<'a, 'b> Clip<'a, 'b> {
  pub fn new<F>(act: F) -> Self where F: 'b + Fn(Time) -> &'a Texture<Flat, Dim2, RGBA32F> {
    Clip {
      act: Box::new(act)
    }
  }
}

/// A cut is an object that slices a `Clip` at an *input time* and *output time*. It is instantiated
/// in a `Track` at a given *instance time*.
#[derive(Clone)]
pub struct Cut<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub in_time: Time,
  pub out_time: Time,
  pub inst_time: Time,
  pub clip: &'c Clip<'a, 'b>
}

impl<'a, 'b, 'c> Cut<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub fn new(in_time: Time, out_time: Time, inst_time: Time, clip: &'c Clip<'a, 'b>) -> Self {
    assert!(in_time <= out_time);

    Cut {
      in_time: in_time,
      out_time: out_time,
      inst_time: inst_time,
      clip: clip
    }
  }

  /// Duration of the cut.
  pub fn dur(&self) -> Time {
    self.out_time - self.in_time
  }
}

/// A track gathers `Cut`s and its purpose is to be used inside a `Timeline`.
#[derive(Clone)]
pub struct Track<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  cuts: Vec<Cut<'a, 'b, 'c>>
}

impl<'a, 'b, 'c> Track<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub fn new() -> Self {
    Track {
      cuts: Vec::new()
    }
  }

  pub fn add_cut(&mut self, cut: Cut<'a, 'b, 'c>) {
    self.cuts.push(cut);
  }
}

impl<'a, 'b, 'c, 'd> From<&'d [Cut<'a, 'b, 'c>]> for Track<'a, 'b, 'c> {
  fn from(cuts: &'d [Cut<'a, 'b, 'c>]) -> Self {
    Track {
      cuts: cuts.to_vec()
    }
  }
}

/// A timeline gathers tracks used to build up the visual aspect of the demo.
#[derive(Clone)]
pub struct Timeline<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  tracks: Vec<Track<'a, 'b, 'c>>,
}

impl<'a, 'b, 'c> Timeline<'a, 'b, 'c> where 'a: 'b, 'b: 'c {
  pub fn new() -> Self {
    Timeline {
      tracks: Vec::new(),
    }
  }

  pub fn add_track(&mut self, track: Track<'a, 'b, 'c>) {
    self.tracks.push(track);
  }

  // TODO: currently, we play the first track we find; add transition support
  pub fn play(&self, t: Time) -> Option<&'a Texture<Flat, Dim2, RGBA32F>> {
    for track in &self.tracks {
      for cut in &track.cuts {
        if cut.inst_time <= t && t <= cut.inst_time + cut.dur() {
          return Some((cut.clip.act)(t));
        }
      }
    }

    None
  }
}

impl<'a, 'b, 'c, 'd> From<&'d [Track<'a, 'b, 'c>]> for Timeline<'a, 'b, 'c> {
  fn from(tracks: &'d [Track<'a, 'b, 'c>]) -> Self {
    Timeline {
      tracks: tracks.to_vec(),
    }
  }
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct TimelineManifest {
  pub tracks: Vec<TrackManifest>
}

impl Load for TimelineManifest {
  type Args = ();

  const TY_STR: &'static str = "edit/timelines";

  fn load<P>(path: P, cache: &mut ResCache, args: Self::Args) -> Result<Self> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading timeline: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))
  }
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct TrackManifest {
  pub cuts: Vec<CutManifest>
}

impl Load for TrackManifest {
  type Args = ();

  const TY_STR: &'static str = "edit/tracks";

  fn load<P>(path: P, cache: &mut ResCache, args: Self::Args) -> Result<Self> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading track: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))
  }
}

#[derive(Debug, Deserialize, PartialEq, Serialize)]
pub struct CutManifest {
  pub in_time: Time,
  pub out_time: Time,
  pub inst_time: Time,
  pub clip: String
}

impl Load for CutManifest {
  type Args = ();

  const TY_STR: &'static str = "edit/cuts";

  fn load<P>(path: P, cache: &mut ResCache, args: Self::Args) -> Result<Self> where P: AsRef<Path> {
    let path = path.as_ref();

    info!("loading cut: {:?}", path);

    let file = File::open(path).map_err(|e| LoadError::FileNotFound(path.to_path_buf(), format!("{:?}", e)))?;
    from_reader(file).map_err(|e| LoadError::ParseFailed(format!("{:?}", e)))
  }
}
<|endoftext|>


<commit_before>extern crate sdl2;

use sdl2::event::{Event};
use sdl2::rect::{Rect};

fn main() {
    // start sdl2 with everything
    let mut ctx = sdl2::init().everything().unwrap();

    // Create a window
    let window  = match ctx.window("eg03", 640, 480).position_centered().opengl().build() {
        Ok(window) => window,
        Err(err)   => panic!("failed to create window: {}", err)
    };

    // Create a rendering context
    let mut renderer = match window.renderer().build() {
        Ok(renderer) => renderer,
        Err(err) => panic!("failed to create renderer: {}", err)
    };

    // since the drawer changes, it should be borrowed as mutable
    let mut drawer = renderer.drawer();

    // Set the drawing color to a light blue.
    let _ = drawer.set_draw_color(sdl2::pixels::Color::RGB(101, 208, 246));

    // Clear the buffer, using the light blue color set above.
    let _ = drawer.clear();

    // Set the drawing color to a darker blue.
    let _ = drawer.set_draw_color(sdl2::pixels::Color::RGB(0, 153, 204));

    // Create centered Rect, draw the outline of the Rect in our dark blue color.
    let border_rect = Rect::new(320-64, 240-64, 128, 128);
    let _ = drawer.draw_rect(border_rect);

    // Create a smaller centered Rect, filling it in the same dark blue.
    let inner_rect = Rect::new(320-60, 240-60, 120, 120);
    let _ = drawer.fill_rect(inner_rect);

    // Swap our buffer for the present buffer, displaying it.
    let _ = drawer.present();

    let mut events = ctx.event_pump();

    // loop until we receive a QuitEvent
    'event : loop {
        for event in events.poll_iter() {
            match event {
                Event::Quit{..} => break 'event,
                _               => continue
            }
        }
    }
}

<commit_msg>Fix eg03<commit_after>extern crate sdl2;

use sdl2::event::{Event};
use sdl2::rect::{Rect};

fn main() {
    // start sdl2 with everything
    let ctx = sdl2::init().unwrap();
    let video_ctx = ctx.video().unwrap();

    // Create a window
    let window  = match video_ctx.window("eg03", 640, 480).position_centered().opengl().build() {
        Ok(window) => window,
        Err(err)   => panic!("failed to create window: {}", err)
    };

    // Create a rendering context
    let mut renderer = match window.renderer().build() {
        Ok(renderer) => renderer,
        Err(err) => panic!("failed to create renderer: {}", err)
    };

    // Set the drawing color to a light blue.
    let _ = renderer.set_draw_color(sdl2::pixels::Color::RGB(101, 208, 246));

    // Clear the buffer, using the light blue color set above.
    let _ = renderer.clear();

    // Set the drawing color to a darker blue.
    let _ = renderer.set_draw_color(sdl2::pixels::Color::RGB(0, 153, 204));

    // Create centered Rect, draw the outline of the Rect in our dark blue color.
    let border_rect = Rect::new(320-64, 240-64, 128, 128).unwrap().unwrap();
    let _ = renderer.draw_rect(border_rect);

    // Create a smaller centered Rect, filling it in the same dark blue.
    let inner_rect = Rect::new(320-60, 240-60, 120, 120).unwrap().unwrap();
    let _ = renderer.fill_rect(inner_rect);

    // Swap our buffer for the present buffer, displaying it.
    let _ = renderer.present();

    let mut events = ctx.event_pump().unwrap();

    // loop until we receive a QuitEvent
    'event : loop {
        for event in events.poll_iter() {
            match event {
                Event::Quit{..} => break 'event,
                _               => continue
            }
        }
    }
}

<|endoftext|>


<commit_before>use std::fmt;
use super::atom::Atom;
use super::parser;
use super::token::{Token, Tokenizer, CurlyAroundTokenizer};
use std::collections::BTreeMap;

#[derive(Debug, PartialEq)]
pub enum Expr {
    Atom(Atom),

    // ( ... )
    Tuple(Vec<Expr>),

    // [ ... ]
    Array(Vec<Expr>),

    // { key val ... }
    Map(Vec<(Expr, Expr)>),
}

impl Expr {
    /// Converts a Expr::Map into a BTreeMap<String, Expr> if possible.
    pub fn into_map(self) -> Result<BTreeMap<String, Expr>, &'static str> {
        match self {
            Expr::Map(pairs) => {
                let mut map = BTreeMap::new();
                for (key, val) in pairs {
                    match key {
                        Expr::Atom(Atom::Str(s)) => {
                            if map.insert(s, val).is_some() {
                                return Err("duplicate key");
                            }
                        }
                        _ => return Err("key has to be a string"),
                    }
                }
                return Ok(map);
            }
            _ => Err("expr is not a Expr::Map"),
        }
    }

    pub fn parse_iter<'a, I>(mut iter: I) -> Result<Expr, ()>
        where I: Iterator<Item = Token<'a>>
    {
        if let Ok(expr) = parser::parse_expr(&mut iter) {
            if parser::at_end(&mut iter) {
                return Ok(expr);
            }
        }
        Err(())
    }

    pub fn parse(s: &str) -> Result<Expr, ()> {
        Expr::parse_iter(Tokenizer::new(s, true))
    }

    pub fn parse_toplevel(s: &str) -> Result<Expr, ()> {
        Expr::parse_iter(CurlyAroundTokenizer::new(Tokenizer::new(s, true)))
    }
}

impl<T> From<T> for Expr where T: Into<Atom>
{
    fn from(t: T) -> Expr {
        Expr::Atom(t.into())
    }
}

impl From<()> for Expr {
    fn from(_e: ()) -> Expr {
        Expr::Tuple(vec![])
    }
}

impl<A> From<(A,)> for Expr where A: Into<Expr>
{
    fn from(e: (A,)) -> Expr {
        Expr::Tuple(vec![e.0.into()])
    }
}

impl<A, B> From<(A, B)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>
{
    fn from(e: (A, B)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into()])
    }
}

impl<A, B, C> From<(A, B, C)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>,
          C: Into<Expr>
{
    fn from(e: (A, B, C)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into(), e.2.into()])
    }
}

impl<A, B, C, D> From<(A, B, C, D)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>,
          C: Into<Expr>,
          D: Into<Expr>
{
    fn from(e: (A, B, C, D)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into(), e.2.into(), e.3.into()])
    }
}

impl<A> From<Vec<A>> for Expr where A: Into<Expr>
{
    fn from(arr: Vec<A>) -> Expr {
        Expr::Array(arr.into_iter().map(|e| e.into()).collect())
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Expr::Atom(ref a) => write!(f, "{}", a),
            Expr::Tuple(ref t) => {
                try!(write!(f, "("));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, ")")
            }
            Expr::Array(ref t) => {
                try!(write!(f, "["));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, "]")
            }
            Expr::Map(ref t) => {
                try!(write!(f, "{}", "{"));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{} {}", space, expr.0, expr.1));
                }
                write!(f, "{}", "}")
            }

        }
    }
}

#[test]
fn test_display() {
    assert_eq!("12345", &format!("{}", Expr::Atom(Atom::UInt(12345))));
    assert_eq!("1.0", &format!("{}", Expr::Atom(Atom::Float(1.0))));

    assert_eq!("(12345)",
               &format!("{}", Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345))])));
    assert_eq!("(12345 abc)",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Atom(Atom::Str("abc".to_string()))])));
    assert_eq!("(12345 (abc))",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Tuple(vec![
                                         Expr::Atom(Atom::Str("abc".to_string()))
                                         ])])));

}

#[test]
fn test_from() {
    assert_eq!(Expr::Atom(Atom::UInt(123)), Expr::from(123u64));
    assert_eq!(Expr::Atom(Atom::SInt(123)), Expr::from(123i64));
    assert_eq!(Expr::Atom(Atom::Str("test".to_string())),
               Expr::from("test"));
    assert_eq!(Expr::Atom(Atom::Float(123.45)), Expr::from(123.45));
    assert_eq!(Expr::Tuple(vec![Expr::Atom(Atom::Float(123.45))]),
               Expr::from((123.45,)));
    assert_eq!(Expr::Array(vec![Expr::Atom(Atom::Float(123.45))]),
               Expr::from(vec![123.45]));

}

#[test]
fn test_parse() {
    assert_eq!(Ok(Expr::from(("abc", 123u64, ("-", 123.43, 11.0)))),
               Expr::parse("(abc 123 (- 123.43 11.0))"));
}

#[test]
fn test_parse_toplevel() {
    assert_eq!(Expr::parse("{a 1 b 2}"), Expr::parse_toplevel("a 1 b 2"));
}

#[test]
fn test_map() {
    let map = Expr::parse("{a 1 b 2}").unwrap().into_map().unwrap();
    assert_eq!(true, map.contains_key("a"));
    assert_eq!(true, map.contains_key("b"));
    assert_eq!(false, map.contains_key("c"));

    assert_eq!(Err("duplicate key"),
               Expr::parse("{a 1 b 2 a 1}").unwrap().into_map());
    assert_eq!(Err("key has to be a string"),
               Expr::parse("{1 1 b 2 a 1}").unwrap().into_map());

}
<commit_msg>Add quick accessor methods (get_uint, get_int, get_float and get_str)<commit_after>use std::fmt;
use super::atom::Atom;
use super::parser;
use super::token::{Token, Tokenizer, CurlyAroundTokenizer};
use std::collections::BTreeMap;

#[derive(Debug, PartialEq)]
pub enum Expr {
    Atom(Atom),

    // ( ... )
    Tuple(Vec<Expr>),

    // [ ... ]
    Array(Vec<Expr>),

    // { key val ... }
    Map(Vec<(Expr, Expr)>),
}

impl Expr {
    /// Converts a Expr::Map into a BTreeMap<String, Expr> if possible.
    pub fn into_map(self) -> Result<BTreeMap<String, Expr>, &'static str> {
        match self {
            Expr::Map(pairs) => {
                let mut map = BTreeMap::new();
                for (key, val) in pairs {
                    match key {
                        Expr::Atom(Atom::Str(s)) => {
                            if map.insert(s, val).is_some() {
                                return Err("duplicate key");
                            }
                        }
                        _ => return Err("key has to be a string"),
                    }
                }
                return Ok(map);
            }
            _ => Err("expr is not a Expr::Map"),
        }
    }

    pub fn get_uint(&self) -> Option<u64> {
        match self {
            &Expr::Atom(Atom::UInt(u)) => Some(u),
            _ => None,
        }
    }

    pub fn get_int(&self) -> Option<i64> {
        match self {
            &Expr::Atom(Atom::SInt(s)) => Some(s),
            _ => None,
        }
    }

    pub fn get_float(&self) -> Option<f64> {
        match self {
            &Expr::Atom(Atom::Float(f)) => Some(f),
            _ => None,
        }
    }

    pub fn get_str(&self) -> Option<&str> {
        match self {
            &Expr::Atom(Atom::Str(ref s)) => Some(s),
            _ => None,
        }
    }

    pub fn parse_iter<'a, I>(mut iter: I) -> Result<Expr, ()>
        where I: Iterator<Item = Token<'a>>
    {
        if let Ok(expr) = parser::parse_expr(&mut iter) {
            if parser::at_end(&mut iter) {
                return Ok(expr);
            }
        }
        Err(())
    }

    pub fn parse(s: &str) -> Result<Expr, ()> {
        Expr::parse_iter(Tokenizer::new(s, true))
    }

    pub fn parse_toplevel(s: &str) -> Result<Expr, ()> {
        Expr::parse_iter(CurlyAroundTokenizer::new(Tokenizer::new(s, true)))
    }
}

impl<T> From<T> for Expr where T: Into<Atom>
{
    fn from(t: T) -> Expr {
        Expr::Atom(t.into())
    }
}

impl From<()> for Expr {
    fn from(_e: ()) -> Expr {
        Expr::Tuple(vec![])
    }
}

impl<A> From<(A,)> for Expr where A: Into<Expr>
{
    fn from(e: (A,)) -> Expr {
        Expr::Tuple(vec![e.0.into()])
    }
}

impl<A, B> From<(A, B)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>
{
    fn from(e: (A, B)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into()])
    }
}

impl<A, B, C> From<(A, B, C)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>,
          C: Into<Expr>
{
    fn from(e: (A, B, C)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into(), e.2.into()])
    }
}

impl<A, B, C, D> From<(A, B, C, D)> for Expr
    where A: Into<Expr>,
          B: Into<Expr>,
          C: Into<Expr>,
          D: Into<Expr>
{
    fn from(e: (A, B, C, D)) -> Expr {
        Expr::Tuple(vec![e.0.into(), e.1.into(), e.2.into(), e.3.into()])
    }
}

impl<A> From<Vec<A>> for Expr where A: Into<Expr>
{
    fn from(arr: Vec<A>) -> Expr {
        Expr::Array(arr.into_iter().map(|e| e.into()).collect())
    }
}

impl fmt::Display for Expr {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Expr::Atom(ref a) => write!(f, "{}", a),
            Expr::Tuple(ref t) => {
                try!(write!(f, "("));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, ")")
            }
            Expr::Array(ref t) => {
                try!(write!(f, "["));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{}", space, expr));
                }
                write!(f, "]")
            }
            Expr::Map(ref t) => {
                try!(write!(f, "{}", "{"));
                for (i, expr) in t.iter().enumerate() {
                    let space = if i > 0 {
                        " "
                    } else {
                        ""
                    };
                    try!(write!(f, "{}{} {}", space, expr.0, expr.1));
                }
                write!(f, "{}", "}")
            }

        }
    }
}

#[test]
fn test_display() {
    assert_eq!("12345", &format!("{}", Expr::Atom(Atom::UInt(12345))));
    assert_eq!("1.0", &format!("{}", Expr::Atom(Atom::Float(1.0))));

    assert_eq!("(12345)",
               &format!("{}", Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345))])));
    assert_eq!("(12345 abc)",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Atom(Atom::Str("abc".to_string()))])));
    assert_eq!("(12345 (abc))",
               &format!("{}",
                        Expr::Tuple(vec![Expr::Atom(Atom::UInt(12345)),
                                         Expr::Tuple(vec![
                                         Expr::Atom(Atom::Str("abc".to_string()))
                                         ])])));

}

#[test]
fn test_from() {
    assert_eq!(Expr::Atom(Atom::UInt(123)), Expr::from(123u64));
    assert_eq!(Expr::Atom(Atom::SInt(123)), Expr::from(123i64));
    assert_eq!(Expr::Atom(Atom::Str("test".to_string())),
               Expr::from("test"));
    assert_eq!(Expr::Atom(Atom::Float(123.45)), Expr::from(123.45));
    assert_eq!(Expr::Tuple(vec![Expr::Atom(Atom::Float(123.45))]),
               Expr::from((123.45,)));
    assert_eq!(Expr::Array(vec![Expr::Atom(Atom::Float(123.45))]),
               Expr::from(vec![123.45]));

}

#[test]
fn test_parse() {
    assert_eq!(Ok(Expr::from(("abc", 123u64, ("-", 123.43, 11.0)))),
               Expr::parse("(abc 123 (- 123.43 11.0))"));
}

#[test]
fn test_parse_toplevel() {
    assert_eq!(Expr::parse("{a 1 b 2}"), Expr::parse_toplevel("a 1 b 2"));
}

#[test]
fn test_map() {
    let map = Expr::parse("{a 1 b 2}").unwrap().into_map().unwrap();
    assert_eq!(true, map.contains_key("a"));
    assert_eq!(true, map.contains_key("b"));
    assert_eq!(false, map.contains_key("c"));

    assert_eq!(Err("duplicate key"),
               Expr::parse("{a 1 b 2 a 1}").unwrap().into_map());
    assert_eq!(Err("key has to be a string"),
               Expr::parse("{1 1 b 2 a 1}").unwrap().into_map());

}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::error;

use super::row::{Row, RowError, RowBuilder, RowReader};
use super::schema::{Schema, Type};
use super::value::Value;
use super::parser::Expression;
use std::ops::{Deref, DerefMut};

#[derive(Debug)]
pub enum StreamError {
    ValidationError(String),
    FieldNotFound(String),
    MissingRowId
}

impl From<RowError> for StreamError {
    fn from(err: RowError) -> StreamError {
        StreamError::MissingRowId
    }

}

#[derive(Debug)]
pub struct Stream {
    inserts: u64, // total number of inserts this Stream has seen
    lowest_id: Option<u64>,  // lowest id we still have in the Stream
    ttl: Option<u64>,
    rows: HashMap<u64, Row>,
    pub schema: Schema,

}

// Stream should deref schema since it's going to be used a lot
impl Deref for Stream {
    type Target = Schema;
    fn deref(&self) -> &Schema {
        &self.schema
    }
}
impl DerefMut for Stream {
    fn deref_mut(&mut self) -> &mut Schema {
        &mut self.schema
    }
}

/**
This is a weird DB.  There's no user defined primary key,
since everything is based off append only streaming
*/
impl Stream {
    pub fn new() -> Stream {
        let mut stream = Stream::new_empty();
        stream.schema.add_type("_id", Type::Int);
        stream.schema.add_type("_created", Type::Timestamp);
        stream
    }

    // used in temporary tables
    pub fn new_empty() -> Stream {
        let mut stream = Stream {
            inserts: 0,
            lowest_id: None,
            rows: HashMap::new(),
            schema: Schema::new(),
            ttl: None,
        };
        stream
    }

    /* we take a HashMap of String -> Field here
    * we're going to convert it to HashMap<u8, Field> for the Row struct
    */
    pub fn insert(&mut self, mut row_builder: RowBuilder) -> Result<u64, StreamError> {
        // validate the inserted data
        let mut row_map : HashMap<u16, Value> = HashMap::new();
        for (key, val) in row_builder.data.drain() {
            // get the field from the schema
            // TypeDef
            let tmp = try!(self.schema.get(&key)
                               .ok_or(StreamError::FieldNotFound(key.to_string())));
            row_map.insert(tmp.id, val);

        }
        let row_id = self.inserts;
        let row = try!(Row::new(row_map));
        self.rows.insert(self.inserts, row.clone());
        self.inserts += 1;
        Ok(row_id)
    }

    pub fn get(&self, position: u64) -> Option<RowReader> {
        if let Some(tmp) = self.rows.get(&position) {
            return Some(RowReader::new(&self.schema, &tmp));
        }
        None

    }
    pub fn select(&self, predicates: Box<Expression>) {

    }

}

impl<'a> IntoIterator for &'a Stream {
    type Item = RowReader<'a>;
    type IntoIter = StreamIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        // TODO fix the position
        StreamIterator{position:0,
                       stream: self}
    }
}

pub struct StreamIterator<'a> {
    position: u64,
    stream: &'a Stream,
}

impl<'a> StreamIterator<'a> {
    fn offset(&'a mut self, num: u64) -> &'a mut StreamIterator {
        self.position = num;
        self
    }
}

impl<'a> Iterator for StreamIterator<'a> {
    type Item = RowReader<'a>;
    fn next(&mut self) -> Option<RowReader<'a>> {
        let tmp = self.stream.get(self.position);
        self.position = self.position + 1;
        tmp
    }
}

#[cfg(test)]
mod tests {
    #![feature(test)]
    extern crate test;
    use super::{Stream};
    use db::row::RowBuilder;

    use db::schema::{Schema, Type};
    use db::value::{Value, ValueComparator};
    use std::collections::HashMap;
    use self::test::Bencher;

    fn get_stream() -> Stream {
        let mut s = Stream::new();
        s.schema.add_type("name", Type::String);
        s.schema.add_type("age", Type::Int);
        s.schema.add_type("created", Type::Timestamp);
        s
    }

    fn get_stream_with_data() -> Stream {
        let mut s = get_stream();

        let names = vec!["Jon", "Dani", "Pete", "Sammy", "Steph",
                         "Blake", "Mr. Robot", "Ted", "Rachel", "Gloria"];
        let ages = vec![35, 29, 45, 56, 100,
                        35, 78, 32, 32, 67];

        for x in 0..10 {
            let mut row = RowBuilder::new();
            row.set_string("name", names[x]);
            row.set_int("age", ages[x]);
            let result = s.insert(row).unwrap();
        }
        s
    }

    #[test]
    fn test_insert_works_normal_case() {
        let mut s = Stream::new();
        let name_id = s.schema.add_type("name", Type::String);

        let mut row = RowBuilder::new();
        row.set_string("name", "test");
        let result = s.insert(row).unwrap();
        assert_eq!(result, 0);
        assert_eq!(s.inserts, 1);
        let row2 = s.get(result).unwrap();
        let name = row2.get("name").unwrap();
        // was the data inserted?
        assert_eq!(*row2.get("name").unwrap(),
                   Value::from("test"));

    }

    #[test]
    fn test_equality() {
        assert_eq!(Value::from("jon"), Value::from("jon"));
    }

    #[test]
    fn test_builder_insertion() {
        let mut s = get_stream();
        let mut row = RowBuilder::new();

        row.set_string("name", "value")
           .set_int("age", 10);
        s.insert(row);

        let mut c = 0;
        for r in s.into_iter() {
            c += 1;
        }
        assert_eq!(c, 1);
    }

    #[test]
    fn test_iterator_offset() {
        let mut s = get_stream_with_data();
        let mut i = 0;
        for row in s.into_iter().offset(9) {
            i = i + 1;
        }
        assert_eq!(i, 1);
    }

    #[test]
    fn test_chaining() {
        let mut s = get_stream_with_data();
        // SELECT * from X where age > 25
        let c = Value::from(40);
        let mut i = 0;
        for row in s.into_iter().filter(|ref x| ValueComparator::new(x.get("age").unwrap(), Type::Int) >
                                                ValueComparator::new(&c, Type::Int) )  {
            i = i + 1;
        }
        assert_eq!(i, 5);

    }

    #[bench]
    fn bench_add_two(b: &mut Bencher) {
        let mut stream = get_stream();
        // benched original row builder at 318 ns/iter (+/- 52)
        b.iter(|| {
            let mut row = RowBuilder::new();
            row.set_string("name", "Dani");
            row.set_int("num_tacos", 4);
            stream.insert(row);
        });
    }

    #[test]
    fn test_table_scan() {
        let mut stream = get_stream_with_data();

    }

}<commit_msg>select can be called<commit_after>use std::collections::HashMap;
use std::error;

use super::row::{Row, RowError, RowBuilder, RowReader};
use super::schema::{Schema, Type};
use super::value::Value;
use super::parser::Expression;
use std::ops::{Deref, DerefMut};

#[derive(Debug)]
pub enum StreamError {
    ValidationError(String),
    FieldNotFound(String),
    MissingRowId,
    UnknownError,
}

impl From<RowError> for StreamError {
    fn from(err: RowError) -> StreamError {
        StreamError::MissingRowId
    }

}

#[derive(Debug)]
pub struct Stream {
    inserts: u64, // total number of inserts this Stream has seen
    lowest_id: Option<u64>,  // lowest id we still have in the Stream
    ttl: Option<u64>,
    rows: HashMap<u64, Row>,
    pub schema: Schema,

}

// Stream should deref schema since it's going to be used a lot
impl Deref for Stream {
    type Target = Schema;
    fn deref(&self) -> &Schema {
        &self.schema
    }
}
impl DerefMut for Stream {
    fn deref_mut(&mut self) -> &mut Schema {
        &mut self.schema
    }
}

/**
This is a weird DB.  There's no user defined primary key,
since everything is based off append only streaming
*/
impl Stream {
    pub fn new() -> Stream {
        let mut stream = Stream::new_empty();
        stream.schema.add_type("_id", Type::Int);
        stream.schema.add_type("_created", Type::Timestamp);
        stream
    }

    // used in temporary tables
    pub fn new_empty() -> Stream {
        let mut stream = Stream {
            inserts: 0,
            lowest_id: None,
            rows: HashMap::new(),
            schema: Schema::new(),
            ttl: None,
        };
        stream
    }

    /* we take a HashMap of String -> Field here
    * we're going to convert it to HashMap<u8, Field> for the Row struct
    */
    pub fn insert(&mut self, mut row_builder: RowBuilder) -> Result<u64, StreamError> {
        // validate the inserted data
        let mut row_map : HashMap<u16, Value> = HashMap::new();
        for (key, val) in row_builder.data.drain() {
            // get the field from the schema
            // TypeDef
            let tmp = try!(self.schema.get(&key)
                               .ok_or(StreamError::FieldNotFound(key.to_string())));
            row_map.insert(tmp.id, val);

        }
        let row_id = self.inserts;
        let row = try!(Row::new(row_map));
        self.rows.insert(self.inserts, row.clone());
        self.inserts += 1;
        Ok(row_id)
    }

    pub fn get(&self, position: u64) -> Option<RowReader> {
        if let Some(tmp) = self.rows.get(&position) {
            return Some(RowReader::new(&self.schema, &tmp));
        }
        None

    }
    pub fn select(&self, predicates: Box<Expression>) -> Result<(), StreamError> {
        Err(StreamError::UnknownError)
    }

}

impl<'a> IntoIterator for &'a Stream {
    type Item = RowReader<'a>;
    type IntoIter = StreamIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        // TODO fix the position
        StreamIterator{position:0,
                       stream: self}
    }
}

pub struct StreamIterator<'a> {
    position: u64,
    stream: &'a Stream,
}

impl<'a> StreamIterator<'a> {
    fn offset(&'a mut self, num: u64) -> &'a mut StreamIterator {
        self.position = num;
        self
    }
}

impl<'a> Iterator for StreamIterator<'a> {
    type Item = RowReader<'a>;
    fn next(&mut self) -> Option<RowReader<'a>> {
        let tmp = self.stream.get(self.position);
        self.position = self.position + 1;
        tmp
    }
}

#[cfg(test)]
mod tests {
    #![feature(test)]
    extern crate test;
    use super::{Stream};
    use db::row::RowBuilder;

    use db::schema::{Schema, Type};
    use db::value::{Value, ValueComparator};
    use std::collections::HashMap;
    use self::test::Bencher;

    fn get_stream() -> Stream {
        let mut s = Stream::new();
        s.schema.add_type("name", Type::String);
        s.schema.add_type("age", Type::Int);
        s.schema.add_type("created", Type::Timestamp);
        s
    }

    fn get_stream_with_data() -> Stream {
        let mut s = get_stream();

        let names = vec!["Jon", "Dani", "Pete", "Sammy", "Steph",
                         "Blake", "Mr. Robot", "Ted", "Rachel", "Gloria"];
        let ages = vec![35, 29, 45, 56, 100,
                        35, 78, 32, 32, 67];

        for x in 0..10 {
            let mut row = RowBuilder::new();
            row.set_string("name", names[x]);
            row.set_int("age", ages[x]);
            let result = s.insert(row).unwrap();
        }
        s
    }

    #[test]
    fn test_insert_works_normal_case() {
        let mut s = Stream::new();
        let name_id = s.schema.add_type("name", Type::String);

        let mut row = RowBuilder::new();
        row.set_string("name", "test");
        let result = s.insert(row).unwrap();
        assert_eq!(result, 0);
        assert_eq!(s.inserts, 1);
        let row2 = s.get(result).unwrap();
        let name = row2.get("name").unwrap();
        // was the data inserted?
        assert_eq!(*row2.get("name").unwrap(),
                   Value::from("test"));

    }

    #[test]
    fn test_equality() {
        assert_eq!(Value::from("jon"), Value::from("jon"));
    }

    #[test]
    fn test_builder_insertion() {
        let mut s = get_stream();
        let mut row = RowBuilder::new();

        row.set_string("name", "value")
           .set_int("age", 10);
        s.insert(row);

        let mut c = 0;
        for r in s.into_iter() {
            c += 1;
        }
        assert_eq!(c, 1);
    }

    #[test]
    fn test_iterator_offset() {
        let mut s = get_stream_with_data();
        let mut i = 0;
        for row in s.into_iter().offset(9) {
            i = i + 1;
        }
        assert_eq!(i, 1);
    }

    #[test]
    fn test_chaining() {
        let mut s = get_stream_with_data();
        // SELECT * from X where age > 25
        let c = Value::from(40);
        let mut i = 0;
        for row in s.into_iter().filter(|ref x| ValueComparator::new(x.get("age").unwrap(), Type::Int) >
                                                ValueComparator::new(&c, Type::Int) )  {
            i = i + 1;
        }
        assert_eq!(i, 5);

    }

    #[bench]
    fn bench_add_two(b: &mut Bencher) {
        let mut stream = get_stream();
        // benched original row builder at 318 ns/iter (+/- 52)
        b.iter(|| {
            let mut row = RowBuilder::new();
            row.set_string("name", "Dani");
            row.set_int("num_tacos", 4);
            stream.insert(row);
        });
    }

    #[test]
    fn test_table_scan() {
        let mut stream = get_stream_with_data();

    }

}<|endoftext|>


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

use crate::error::InvalidUuid;

#[inline]
pub const fn try_parse(input: &str) -> Result<[u8; 16], InvalidUuid> {
    let result = match (input.len(), input.as_bytes()) {
        // Inputs of 32 bytes must be a non-hyphenated UUID
        (32, s) => parse_simple(s),
        // Hyphenated UUIDs may be wrapped in various ways:
        // - `{UUID}` for braced UUIDs
        // - `urn:uuid:UUID` for URNs
        // - `UUID` for a regular hyphenated UUID
        (36, s)
        | (38, [b'{', s @ .., b'}'])
        | (
            45,
            [b'u', b'r', b'n', b':', b'u', b'u', b'i', b'd', b':', s @ ..],
        ) => parse_hyphenated(s),
        // Any other shaped input is immediately invalid
        _ => Err(()),
    };

    match result {
        Ok(b) => Ok(b),
        Err(()) => Err(InvalidUuid(input)),
    }
}

#[inline]
const fn parse_simple(s: &[u8]) -> Result<[u8; 16], ()> {
    // Should be optimized away as redundant
    if s.len() != 32 {
        return Err(());
    }

    let mut buf: [u8; 16] = [0; 16];
    let mut i = 0;

    while i < 16 {
        // Convert a two-char hex value (like `A8`)
        // into a byte (like `10101000`)
        let h1 = HEX_TABLE[s[i * 2] as usize];
        let h2 = HEX_TABLE[s[i * 2 + 1] as usize];

        // We use `0xff` as a sentinel value to indicate
        // an invalid hex character sequence (like the letter `G`)
        if h1 | h2 == 0xff {
            return Err(());
        }

        // The upper nibble needs to be shifted into position
        // to produce the final byte value
        buf[i] = SHL4_TABLE[h1 as usize] | h2;
        i += 1;
    }

    Ok(buf)
}

#[inline]
const fn parse_hyphenated(s: &[u8]) -> Result<[u8; 16], ()> {
    // Should be optimized away as redundant
    if s.len() != 36 {
        return Err(());
    }

    // First, ensure the hyphens appear in the right places
    match [s[8], s[13], s[18], s[23]] {
        [b'-', b'-', b'-', b'-'] => {}
        _ => return Err(()),
    }

    // We look at two hex-encoded values (4 chars) at a time because
    // that's the size of the smallest group in a hyphenated UUID:
    //
    // uuid     : 936da01f-9abd-4d9d-80c7-02af85c822a8
    //            |   |   ||   ||   ||   ||   |   |
    // hyphens  : |   |   8|  13|  18|  23|   |   |
    // positions: 0   4    9   14   19   24  28  32
    let positions: [u8; 8] = [0, 4, 9, 14, 19, 24, 28, 32];
    let mut buf: [u8; 16] = [0; 16];
    let mut j = 0;

    while j < 8 {
        let i = positions[j];

        // The decoding here is the same as the simple case
        // We're just dealing with two values instead of one
        let h1 = HEX_TABLE[s[i as usize] as usize];
        let h2 = HEX_TABLE[s[(i + 1) as usize] as usize];
        let h3 = HEX_TABLE[s[(i + 2) as usize] as usize];
        let h4 = HEX_TABLE[s[(i + 3) as usize] as usize];

        if h1 | h2 | h3 | h4 == 0xff {
            return Err(());
        }

        buf[j * 2] = SHL4_TABLE[h1 as usize] | h2;
        buf[j * 2 + 1] = SHL4_TABLE[h3 as usize] | h4;
        j += 1;
    }

    Ok(buf)
}

const HEX_TABLE: &[u8; 256] = &{
    let mut buf = [0; 256];
    let mut i: u8 = 0;

    loop {
        buf[i as usize] = match i {
            b'0'..=b'9' => i - b'0',
            b'a'..=b'f' => i - b'a' + 10,
            b'A'..=b'F' => i - b'A' + 10,
            _ => 0xff,
        };

        if i == 255 {
            break buf;
        }

        i += 1
    }
};

const SHL4_TABLE: &[u8; 256] = &{
    let mut buf = [0; 256];
    let mut i: u8 = 0;

    loop {
        buf[i as usize] = i.wrapping_shl(4);

        if i == 255 {
            break buf;
        }

        i += 1;
    }
};
<commit_msg>update comment on bounds checks<commit_after>// Copyright 2013-2014 The Rust Project Developers.
// Copyright 2018 The Uuid Project Developers.
//
// See the COPYRIGHT file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::error::InvalidUuid;

#[inline]
pub const fn try_parse(input: &str) -> Result<[u8; 16], InvalidUuid> {
    let result = match (input.len(), input.as_bytes()) {
        // Inputs of 32 bytes must be a non-hyphenated UUID
        (32, s) => parse_simple(s),
        // Hyphenated UUIDs may be wrapped in various ways:
        // - `{UUID}` for braced UUIDs
        // - `urn:uuid:UUID` for URNs
        // - `UUID` for a regular hyphenated UUID
        (36, s)
        | (38, [b'{', s @ .., b'}'])
        | (
            45,
            [b'u', b'r', b'n', b':', b'u', b'u', b'i', b'd', b':', s @ ..],
        ) => parse_hyphenated(s),
        // Any other shaped input is immediately invalid
        _ => Err(()),
    };

    match result {
        Ok(b) => Ok(b),
        Err(()) => Err(InvalidUuid(input)),
    }
}

#[inline]
const fn parse_simple(s: &[u8]) -> Result<[u8; 16], ()> {
    // This length check here removes all other bounds
    // checks in this function
    if s.len() != 32 {
        return Err(());
    }

    let mut buf: [u8; 16] = [0; 16];
    let mut i = 0;

    while i < 16 {
        // Convert a two-char hex value (like `A8`)
        // into a byte (like `10101000`)
        let h1 = HEX_TABLE[s[i * 2] as usize];
        let h2 = HEX_TABLE[s[i * 2 + 1] as usize];

        // We use `0xff` as a sentinel value to indicate
        // an invalid hex character sequence (like the letter `G`)
        if h1 | h2 == 0xff {
            return Err(());
        }

        // The upper nibble needs to be shifted into position
        // to produce the final byte value
        buf[i] = SHL4_TABLE[h1 as usize] | h2;
        i += 1;
    }

    Ok(buf)
}

#[inline]
const fn parse_hyphenated(s: &[u8]) -> Result<[u8; 16], ()> {
    // This length check here removes all other bounds
    // checks in this function
    if s.len() != 36 {
        return Err(());
    }

    // We look at two hex-encoded values (4 chars) at a time because
    // that's the size of the smallest group in a hyphenated UUID.
    // The indexes we're interested in are:
    //
    // uuid     : 936da01f-9abd-4d9d-80c7-02af85c822a8
    //            |   |   ||   ||   ||   ||   |   |
    // hyphens  : |   |   8|  13|  18|  23|   |   |
    // positions: 0   4    9   14   19   24  28  32

    // First, ensure the hyphens appear in the right places
    match [s[8], s[13], s[18], s[23]] {
        [b'-', b'-', b'-', b'-'] => {}
        _ => return Err(()),
    }

    let positions: [u8; 8] = [0, 4, 9, 14, 19, 24, 28, 32];
    let mut buf: [u8; 16] = [0; 16];
    let mut j = 0;

    while j < 8 {
        let i = positions[j];

        // The decoding here is the same as the simple case
        // We're just dealing with two values instead of one
        let h1 = HEX_TABLE[s[i as usize] as usize];
        let h2 = HEX_TABLE[s[(i + 1) as usize] as usize];
        let h3 = HEX_TABLE[s[(i + 2) as usize] as usize];
        let h4 = HEX_TABLE[s[(i + 3) as usize] as usize];

        if h1 | h2 | h3 | h4 == 0xff {
            return Err(());
        }

        buf[j * 2] = SHL4_TABLE[h1 as usize] | h2;
        buf[j * 2 + 1] = SHL4_TABLE[h3 as usize] | h4;
        j += 1;
    }

    Ok(buf)
}

const HEX_TABLE: &[u8; 256] = &{
    let mut buf = [0; 256];
    let mut i: u8 = 0;

    loop {
        buf[i as usize] = match i {
            b'0'..=b'9' => i - b'0',
            b'a'..=b'f' => i - b'a' + 10,
            b'A'..=b'F' => i - b'A' + 10,
            _ => 0xff,
        };

        if i == 255 {
            break buf;
        }

        i += 1
    }
};

const SHL4_TABLE: &[u8; 256] = &{
    let mut buf = [0; 256];
    let mut i: u8 = 0;

    loop {
        buf[i as usize] = i.wrapping_shl(4);

        if i == 255 {
            break buf;
        }

        i += 1;
    }
};
<|endoftext|>


<commit_before>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: crate::io::prelude
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
//!   marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{[`self`][`Option`], [`Some`], [`None`]}. A
//!   type which expresses the presence or absence of a value. This type is so
//!   commonly used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{[`self`][`Result`], [`Ok`], [`Err`]}. A type
//!   for functions that may succeed or fail. Like [`Option`], its variants are
//!   exported as well.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`], a growable, heap-allocated
//!   vector.
//!
//! [`mem::drop`]: crate::mem::drop
//! [`std::borrow`]: crate::borrow
//! [`std::boxed`]: crate::boxed
//! [`std::clone`]: crate::clone
//! [`std::cmp`]: crate::cmp
//! [`std::convert`]: crate::convert
//! [`std::default`]: crate::default
//! [`std::iter`]: crate::iter
//! [`std::marker`]: crate::marker
//! [`std::mem`]: crate::mem
//! [`std::ops`]: crate::ops
//! [`std::option`]: crate::option
//! [`std::prelude::v1`]: v1
//! [`std::result`]: crate::result
//! [`std::slice`]: crate::slice
//! [`std::string`]: crate::string
//! [`std::vec`]: module@crate::vec
//! [`to_owned`]: crate::borrow::ToOwned::to_owned
//! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html
//! [book-enums]: ../../book/ch06-01-defining-an-enum.html
//! [book-iter]: ../../book/ch13-02-iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<commit_msg>Move the std::vec link back to a path-based link to make it compile with --stage 0<commit_after>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: crate::io::prelude
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
//!   marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{[`self`][`Option`], [`Some`], [`None`]}. A
//!   type which expresses the presence or absence of a value. This type is so
//!   commonly used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{[`self`][`Result`], [`Ok`], [`Err`]}. A type
//!   for functions that may succeed or fail. Like [`Option`], its variants are
//!   exported as well.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`], a growable, heap-allocated
//!   vector.
//!
//! [`mem::drop`]: crate::mem::drop
//! [`std::borrow`]: crate::borrow
//! [`std::boxed`]: crate::boxed
//! [`std::clone`]: crate::clone
//! [`std::cmp`]: crate::cmp
//! [`std::convert`]: crate::convert
//! [`std::default`]: crate::default
//! [`std::iter`]: crate::iter
//! [`std::marker`]: crate::marker
//! [`std::mem`]: crate::mem
//! [`std::ops`]: crate::ops
//! [`std::option`]: crate::option
//! [`std::prelude::v1`]: v1
//! [`std::result`]: crate::result
//! [`std::slice`]: crate::slice
//! [`std::string`]: crate::string
//! [`std::vec`]: ../vec/index.html
//! [`to_owned`]: crate::borrow::ToOwned::to_owned
//! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html
//! [book-enums]: ../../book/ch06-01-defining-an-enum.html
//! [book-iter]: ../../book/ch13-02-iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<|endoftext|>


<commit_before>#![feature(async_await)]
#![deny(warnings)]
extern crate hyper;
extern crate pretty_env_logger;

use std::env;
use std::io::{self, Write};

use hyper::Client;
use hyper::rt;

fn main() {
    pretty_env_logger::init();

    // Some simple CLI args requirements...
    let url = match env::args().nth(1) {
        Some(url) => url,
        None => {
            println!("Usage: client <url>");
            return;
        }
    };

    // HTTPS requires picking a TLS implementation, so give a better
    // warning if the user tries to request an 'https' URL.
    let url = url.parse::<hyper::Uri>().unwrap();
    if url.scheme_part().map(|s| s.as_ref()) != Some("http") {
        println!("This example only works with 'http' URLs.");
        return;
    }

    // Run the runtime with the future trying to fetch and print this URL.
    //
    // Note that in more complicated use cases, the runtime should probably
    // run on its own, and futures should just be spawned into it.
    rt::run(fetch_url(url));
}

async fn fetch_url(url: hyper::Uri) {
    let client = Client::new();

    let res = match client.get(url).await {
        Ok(res) => res,
        Err(err) => {
            eprintln!("Response Error: {}", err);
            return;
        }
    };

    println!("Response: {}", res.status());
    println!("Headers: {:#?}\n", res.headers());

    let mut body = res.into_body();

    while let Some(next) = body.next().await {
        match next {
            Ok(chunk) => {
                io::stdout().write_all(&chunk)
                    .expect("example expects stdout is open");
            },
            Err(err) => {
                eprintln!("Body Error: {}", err);
                return;
            }
        }
    }

    println!("\n\nDone!");
}
<commit_msg>docs(examples): update client example to use rt::main<commit_after>#![feature(async_await)]
#![deny(warnings)]
extern crate hyper;
extern crate pretty_env_logger;

use std::env;
use std::io::{self, Write};

use hyper::Client;

// A simple type alias so as to DRY.
type Result<T> = std::result::Result<T, Box<dyn std::error::Error + Send + Sync>>;

#[hyper::rt::main]
async fn main() -> Result<()> {
    pretty_env_logger::init();

    // Some simple CLI args requirements...
    let url = match env::args().nth(1) {
        Some(url) => url,
        None => {
            println!("Usage: client <url>");
            return Ok(());
        }
    };

    // HTTPS requires picking a TLS implementation, so give a better
    // warning if the user tries to request an 'https' URL.
    let url = url.parse::<hyper::Uri>().unwrap();
    if url.scheme_part().map(|s| s.as_ref()) != Some("http") {
        println!("This example only works with 'http' URLs.");
        return Ok(());
    }

    fetch_url(url).await
}

async fn fetch_url(url: hyper::Uri) -> Result<()> {
    let client = Client::new();

    let res = client.get(url).await?;

    println!("Response: {}", res.status());
    println!("Headers: {:#?}\n", res.headers());

    let mut body = res.into_body();

    while let Some(next) = body.next().await {
        let chunk = next?;
        io::stdout().write_all(&chunk)?;
    }

    println!("\n\nDone!");

    Ok(())
}
<|endoftext|>


<commit_before>//! A simple example of hooking up stdin/stdout to a WebSocket stream.
//!
//! This example will connect to a server specified in the argument list and
//! then forward all data read on stdin to the server, printing out all data
//! received on stdout.
//!
//! Note that this is not currently optimized for performance, especially around
//! buffer management. Rather it's intended to show an example of working with a
//! client.
//!
//! You can use this example together with the `server` example.

use std::env;

use futures::{future, pin_mut, StreamExt};
use log::info;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio_tungstenite::connect_async;
use tungstenite::protocol::Message;

#[tokio::main]
async fn main() {
    let _ = env_logger::try_init();

    let connect_addr = env::args()
        .nth(1)
        .unwrap_or_else(|| panic!("this program requires at least one argument"));

    let url = url::Url::parse(&connect_addr).unwrap();

    let (stdin_tx, stdin_rx) = futures::channel::mpsc::unbounded();
    tokio::spawn(read_stdin(stdin_tx));

    let (ws_stream, _) = connect_async(url).await.expect("Failed to connect");
    info!("WebSocket handshake has been successfully completed");

    let (write, read) = ws_stream.split();

    let stdin_to_ws = stdin_rx.map(Ok).forward(write);
    let ws_to_stdout = {
        read.for_each(|message| {
            async {
                let data = message.unwrap().into_data();
                tokio::io::stdout().write_all(&data).await.unwrap();
            }
        })
    };

    pin_mut!(stdin_to_ws, ws_to_stdout);
    future::select(stdin_to_ws, ws_to_stdout).await;
}

// Our helper method which will read data from stdin and send it along the
// sender provided.
async fn read_stdin(tx: futures::channel::mpsc::UnboundedSender<Message>) {
    let mut stdin = tokio::io::stdin();
    loop {
        let mut buf = vec![0; 1024];
        let n = match stdin.read(&mut buf).await {
            Err(_) | Ok(0) => break,
            Ok(n) => n,
        };
        buf.truncate(n);
        tx.unbounded_send(Message::binary(buf)).unwrap();
    }
}
<commit_msg>examples: improve client example<commit_after>//! A simple example of hooking up stdin/stdout to a WebSocket stream.
//!
//! This example will connect to a server specified in the argument list and
//! then forward all data read on stdin to the server, printing out all data
//! received on stdout.
//!
//! Note that this is not currently optimized for performance, especially around
//! buffer management. Rather it's intended to show an example of working with a
//! client.
//!
//! You can use this example together with the `server` example.

use std::env;

use futures::{future, pin_mut, StreamExt};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio_tungstenite::connect_async;
use tungstenite::protocol::Message;

#[tokio::main]
async fn main() {
    let connect_addr = env::args()
        .nth(1)
        .unwrap_or_else(|| panic!("this program requires at least one argument"));

    let url = url::Url::parse(&connect_addr).unwrap();

    let (stdin_tx, stdin_rx) = futures::channel::mpsc::unbounded();
    tokio::spawn(read_stdin(stdin_tx));

    let (ws_stream, _) = connect_async(url).await.expect("Failed to connect");
    println!("WebSocket handshake has been successfully completed");

    let (write, read) = ws_stream.split();

    let stdin_to_ws = stdin_rx.map(Ok).forward(write);
    let ws_to_stdout = {
        read.for_each(|message| {
            async {
                let data = message.unwrap().into_data();
                tokio::io::stdout().write_all(&data).await.unwrap();
            }
        })
    };

    pin_mut!(stdin_to_ws, ws_to_stdout);
    future::select(stdin_to_ws, ws_to_stdout).await;
}

// Our helper method which will read data from stdin and send it along the
// sender provided.
async fn read_stdin(tx: futures::channel::mpsc::UnboundedSender<Message>) {
    let mut stdin = tokio::io::stdin();
    loop {
        let mut buf = vec![0; 1024];
        let n = match stdin.read(&mut buf).await {
            Err(_) | Ok(0) => break,
            Ok(n) => n,
        };
        buf.truncate(n);
        tx.unbounded_send(Message::binary(buf)).unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate docopt;
extern crate flac;
extern crate hound;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ErrorKind, StreamReader};

use std::env;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

const USAGE: &'static str = "
Usage: decode <input> <output>
       decode <input>... <dir>
       decode --help

Options:
  -h, --help   Show this message.
";

#[derive(RustcDecodable)]
struct Arguments {
  arg_input: Vec<String>,
  arg_output: Option<String>,
  arg_dir: Option<String>,
}

fn to_io_error(kind: ErrorKind) -> hound::Error {
  match kind {
    ErrorKind::IO(e) => {
      let io_error = io::Error::new(e, "io error");

      hound::Error::IoError(io_error)
    }
    _                => hound::Error::Unsupported,
  }
}

fn decode_file(input_file: &str, output_file: &str)
               -> Result<(), hound::Error> {
  let mut stream = try! {
    StreamReader::<fs::File>::from_file(input_file)
      .map_err(to_io_error)
  };

  let info = stream.info();
  let spec = hound::WavSpec {
    channels: info.channels as u16,
    sample_rate: info.sample_rate,
    bits_per_sample: info.bits_per_sample as u16,
  };

  let mut output = try!(hound::WavWriter::create(output_file, spec));

  if info.bits_per_sample <= 8 {
    for sample in stream.iter::<i16>() {
      try!(output.write_sample(sample));
    }
  } else if info.bits_per_sample <= 16 {
    for sample in stream.iter::<i32>() {
      try!(output.write_sample(sample));
    }
  }

  output.finalize()
}

fn to_output_file(buffer: &mut PathBuf, path: &Path, directory: &str)
                  -> Result<(), hound::Error> {
  buffer.push(directory);

  path.file_name().map(|name| {
    buffer.push(name);
    buffer.set_extension("wav");
  }).ok_or_else(|| {
    let kind    = io::ErrorKind::NotFound;
    let message = "no file name found";
    let error   = io::Error::new(kind, message);

    hound::Error::IoError(error)
  })
}

fn decode_all_files(input_files: &Vec<String>, directory: &str)
                    -> Result<(), hound::Error> {
  let dir_path = Path::new(directory);

  if !dir_path.exists() {
    try!(fs::create_dir(dir_path).map_err(hound::Error::IoError))
  }

  for ref input_file in input_files {
    let mut buffer = PathBuf::new();
    let path       = Path::new(input_file);

    try!(to_output_file(&mut buffer, path, directory));

    let output_file = try! {
      buffer.to_str().ok_or_else(|| {
        let kind    = io::ErrorKind::InvalidInput;
        let message = "invalid unicode with file path";
        let error   = io::Error::new(kind, message);

        hound::Error::IoError(error)
      })
    };

    let result = decode_file(input_file, output_file);

    if result.is_ok() {
      println!("decoded: {} -> {}", input_file, output_file);
    } else {
      return result;
    }
  }

  Ok(())
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  if let Some(ref output_file) = args.arg_output {
    let input_file = &args.arg_input[0];

    if let Err(e) = decode_file(input_file, output_file) {
      println!("{:?}", e);
    } else {
      println!("decoded: {} -> {}", input_file, output_file);
    }
  } else if let Some(ref directory) = args.arg_dir {
    if let Err(e) = decode_all_files(&args.arg_input, directory) {
      println!("{:?}", e);
    }
  }
}
<commit_msg>Add specific size for bits_per_sample 32 and lower<commit_after>extern crate docopt;
extern crate flac;
extern crate hound;
extern crate rustc_serialize;

use docopt::Docopt;
use flac::{ErrorKind, StreamReader};

use std::env;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

const USAGE: &'static str = "
Usage: decode <input> <output>
       decode <input>... <dir>
       decode --help

Options:
  -h, --help   Show this message.
";

#[derive(RustcDecodable)]
struct Arguments {
  arg_input: Vec<String>,
  arg_output: Option<String>,
  arg_dir: Option<String>,
}

fn to_io_error(kind: ErrorKind) -> hound::Error {
  match kind {
    ErrorKind::IO(e) => {
      let io_error = io::Error::new(e, "io error");

      hound::Error::IoError(io_error)
    }
    _                => hound::Error::Unsupported,
  }
}

fn decode_file(input_file: &str, output_file: &str)
               -> Result<(), hound::Error> {
  let mut stream = try! {
    StreamReader::<fs::File>::from_file(input_file)
      .map_err(to_io_error)
  };

  let info = stream.info();
  let spec = hound::WavSpec {
    channels: info.channels as u16,
    sample_rate: info.sample_rate,
    bits_per_sample: info.bits_per_sample as u16,
  };

  let mut output = try!(hound::WavWriter::create(output_file, spec));

  if info.bits_per_sample <= 8 {
    for sample in stream.iter::<i16>() {
      try!(output.write_sample(sample));
    }
  } else if info.bits_per_sample <= 16 {
    for sample in stream.iter::<i32>() {
      try!(output.write_sample(sample));
    }
  } else {
    for sample in stream.iter::<i64>() {
      try!(output.write_sample(sample));
    }
  }

  output.finalize()
}

fn to_output_file(buffer: &mut PathBuf, path: &Path, directory: &str)
                  -> Result<(), hound::Error> {
  buffer.push(directory);

  path.file_name().map(|name| {
    buffer.push(name);
    buffer.set_extension("wav");
  }).ok_or_else(|| {
    let kind    = io::ErrorKind::NotFound;
    let message = "no file name found";
    let error   = io::Error::new(kind, message);

    hound::Error::IoError(error)
  })
}

fn decode_all_files(input_files: &Vec<String>, directory: &str)
                    -> Result<(), hound::Error> {
  let dir_path = Path::new(directory);

  if !dir_path.exists() {
    try!(fs::create_dir(dir_path).map_err(hound::Error::IoError))
  }

  for ref input_file in input_files {
    let mut buffer = PathBuf::new();
    let path       = Path::new(input_file);

    try!(to_output_file(&mut buffer, path, directory));

    let output_file = try! {
      buffer.to_str().ok_or_else(|| {
        let kind    = io::ErrorKind::InvalidInput;
        let message = "invalid unicode with file path";
        let error   = io::Error::new(kind, message);

        hound::Error::IoError(error)
      })
    };

    let result = decode_file(input_file, output_file);

    if result.is_ok() {
      println!("decoded: {} -> {}", input_file, output_file);
    } else {
      return result;
    }
  }

  Ok(())
}

fn main() {
  let args: Arguments = Docopt::new(USAGE)
    .and_then(|d| d.argv(env::args()).decode())
    .unwrap_or_else(|e| e.exit());

  if let Some(ref output_file) = args.arg_output {
    let input_file = &args.arg_input[0];

    if let Err(e) = decode_file(input_file, output_file) {
      println!("{:?}", e);
    } else {
      println!("decoded: {} -> {}", input_file, output_file);
    }
  } else if let Some(ref directory) = args.arg_dir {
    if let Err(e) = decode_all_files(&args.arg_input, directory) {
      println!("{:?}", e);
    }
  }
}
<|endoftext|>