<commit_before>use std::io::{BufReader, BufferedReader, Reader};
use std::str::{from_char, with_capacity};
use std::char::from_u32;
use std::num::FromStrRadix;
use ast::{TIdent, TNumber, TString, TSemicolon, TColon, TDot, TEqual, TOpenParen, TCloseParen, TComma, TOpenBlock, TCloseBlock, TOpenArray, TCloseArray, TQuestion, TNumOp, TBitOp};
use ast::{OpAdd, OpSub, OpMul, OpDiv, OpMod};
use ast::{BitAnd, BitOr, BitXor};
use ast::Token;
use std::io::{IoResult, EndOfFile};
use std::char::is_whitespace;
#[deriving(Clone)]
#[deriving(Eq)]
#[deriving(Show)]
/// The type of string used
pub enum StringType {
	/// Double-quoted
	DoubleQuote,
	/// Single-quoted
	SingleQuote
}
/// The Javascript Lexer
pub struct Lexer {
	/// The list of tokens generated so far
	pub tokens : Vec<Token>,
	/// The string buffer for identities
	ident_buffer : ~str,
	/// The string buffer for strings
	string_buffer : ~str,
	/// The string buffer for numbers
	num_buffer : ~str,
	/// The kind of string - i.e. double quote or single quote or none if it isn't in a string
	string_start : Option<StringType>,
	/// If the lexer is currently inside a number
	in_num : bool,
	/// If a backwards slash has just been read
	escaped : bool
}
impl Lexer {
	/// Creates a new lexer with empty buffers
	pub fn new() -> ~Lexer {
		return ~Lexer {
			tokens: Vec::new(),
			ident_buffer: with_capacity(32),
			string_buffer: with_capacity(256),
			num_buffer: with_capacity(16),
			string_start: None,
			in_num: false,
			escaped: false
		};
	}
	fn clear_buffer(&mut self) {
		if self.ident_buffer.len() > 0 {
			self.tokens.push(TIdent(self.ident_buffer.clone()));
			self.ident_buffer.clear();
		}
		if self.in_num {
			self.tokens.push(TNumber(from_str(self.num_buffer).unwrap()));
			self.num_buffer.clear();
			self.in_num = false;
		}
	}
	/// Processes an input stream from a string into an array of tokens
	pub fn lex_str(&mut self, script:~str) -> IoResult<()> {
		let script_bytes:&[u8] = script.as_bytes();
		let reader = BufReader::new(script_bytes);
		let buf_reader = BufferedReader::new(reader);
		self.lex(buf_reader)
	}
	/// Processes an input stream from a BufferedReader into an array of tokens
	pub fn lex<R : Reader>(&mut self, mut reader : BufferedReader<R>) -> IoResult<()> {
		loop {
			let ch = match reader.read_char() {
				Ok(c) => c,
				Err(ref e) if e.kind == EndOfFile => {
					self.clear_buffer();
					return Ok(())
				},
				Err(ref e) =>
					return Err(e.clone())
			};
			match ch {
				_ if self.escaped => {
					self.escaped = false;
					if ch != '\n' {
						self.string_buffer = self.string_buffer + from_char(match ch {
							'n' => '\n',
							'r' => '\r',
							't' => '\t',
							'b' => '\x08',
							'f' => '\x0c',
							'0' => '\0',
							'u' => {
								let mut nums = ~"";
								for _ in range(0, 4) {
									nums = format!("{}{}", nums, try!(reader.read_char()));
								}
								let as_num = match FromStrRadix::from_str_radix(nums, 16) {
									Some(v) => v,
									None => 0
								};
								match from_u32(as_num) {
									Some(v) => v,
									None => fail!("{} is not a valid unicode scalar value", as_num)
								}
							},
							'\'' if self.string_start == Some(SingleQuote) => '\'',
							'"' if self.string_start == Some(DoubleQuote) => '"',
							_ => fail!("Invalid escape `{}` after {}", ch, self.string_start)
						});
					}
				},
				'"' if self.string_start.is_some() && self.string_start.unwrap() == DoubleQuote => {
					self.string_start = None;
					self.tokens.push(TString(self.string_buffer.clone()));
					self.string_buffer.clear();
				},
				'\'' if self.string_start.is_some() && self.string_start.unwrap() == SingleQuote => {
					self.string_start = None;
					self.tokens.push(TString(self.string_buffer.clone()));
					self.string_buffer.clear();
				},
				'\\' if self.string_start.is_some() => self.escaped = true,
				_ if self.string_start.is_some() => self.string_buffer = format!("{}{}", self.string_buffer, ch),
				'"' if self.string_start.is_none() => self.string_start = Some(DoubleQuote),
				'0'.. '9' if self.string_start.is_none() && self.ident_buffer.len() == 0 => {
					self.num_buffer = format!("{}{}", self.num_buffer.clone(), ch);
					self.in_num = true;
				},
				'\'' if self.string_start.is_none() => self.string_start = Some(SingleQuote),
				'.' if self.in_num && !self.num_buffer.contains(".") => {
					self.num_buffer = format!("{}{}", self.num_buffer, ch);
				},
				';' => {
					self.clear_buffer();
					self.tokens.push(TSemicolon)
				},
				':' => {
					self.clear_buffer();
					self.tokens.push(TColon)
				},
				'.' => {
					self.clear_buffer();
					self.tokens.push(TDot)
				},
				'(' => {
					self.clear_buffer();
					self.tokens.push(TOpenParen)
				},
				')' => {
					self.clear_buffer();
					self.tokens.push(TCloseParen)
				},
				',' => {
					self.clear_buffer();
					self.tokens.push(TComma)
				},
				'{' => {
					self.clear_buffer();
					self.tokens.push(TOpenBlock)
				},
				'}' => {
					self.clear_buffer();
					self.tokens.push(TCloseBlock)
				},
				'[' => {
					self.clear_buffer();
					self.tokens.push(TOpenArray)
				},
				']' => {
					self.clear_buffer();
					self.tokens.push(TCloseArray)
				},
				'?' => {
					self.clear_buffer();
					self.tokens.push(TQuestion)
				},
				'/' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpDiv))
				},
				'*' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpMul))
				},
				'+' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpAdd))
				},
				'-' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpSub))
				},
				'%' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpMod))
				},
				'|' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitOr))
				},
				'&' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitAnd))
				},
				'^' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitXor))
				},
				'=' => {
					self.clear_buffer();
					self.tokens.push(TEqual)
				},
				_ if is_whitespace(ch) => self.clear_buffer(),
				_ => self.ident_buffer = format!("{}{}", self.ident_buffer, ch)
			};
		}
	}
}<commit_msg>Use StrBuf instead of ~str<commit_after>use std::io::{BufReader, BufferedReader, Reader};
use std::strbuf::StrBuf;
use std::char::from_u32;
use std::num::FromStrRadix;
use ast::{TIdent, TNumber, TString, TSemicolon, TColon, TDot, TEqual, TOpenParen, TCloseParen, TComma, TOpenBlock, TCloseBlock, TOpenArray, TCloseArray, TQuestion, TNumOp, TBitOp};
use ast::{OpAdd, OpSub, OpMul, OpDiv, OpMod};
use ast::{BitAnd, BitOr, BitXor};
use ast::Token;
use std::io::{IoResult, EndOfFile};
use std::char::is_whitespace;
#[deriving(Clone)]
#[deriving(Eq)]
#[deriving(Show)]
/// The type of string used
pub enum StringType {
	/// Double-quoted
	DoubleQuote,
	/// Single-quoted
	SingleQuote
}
/// The Javascript Lexer
pub struct Lexer {
	/// The list of tokens generated so far
	pub tokens : Vec<Token>,
	/// The string buffer for identities
	ident_buffer : StrBuf,
	/// The string buffer for strings
	string_buffer : StrBuf,
	/// The string buffer for numbers
	num_buffer : StrBuf,
	/// The kind of string - i.e. double quote or single quote or none if it isn't in a string
	string_start : Option<StringType>,
	/// If the lexer is currently inside a number
	in_num : bool,
	/// If a backwards slash has just been read
	escaped : bool
}
impl Lexer {
	/// Creates a new lexer with empty buffers
	pub fn new() -> ~Lexer {
		return ~Lexer {
			tokens: Vec::new(),
			ident_buffer: StrBuf::with_capacity(32),
			string_buffer: StrBuf::with_capacity(256),
			num_buffer: StrBuf::with_capacity(16),
			string_start: None,
			in_num: false,
			escaped: false
		};
	}
	fn clear_buffer(&mut self) {
		if self.ident_buffer.len() > 0 {
			self.tokens.push(TIdent(self.ident_buffer.clone().into_owned()));
			self.ident_buffer.truncate(0);
		}
		if self.in_num {
			self.tokens.push(TNumber(from_str(self.num_buffer.as_slice()).unwrap()));
			self.num_buffer.truncate(0);
			self.in_num = false;
		}
	}
	/// Processes an input stream from a string into an array of tokens
	pub fn lex_str(&mut self, script:~str) -> IoResult<()> {
		let script_bytes:&[u8] = script.as_bytes();
		let reader = BufReader::new(script_bytes);
		let buf_reader = BufferedReader::new(reader);
		self.lex(buf_reader)
	}
	/// Processes an input stream from a BufferedReader into an array of tokens
	pub fn lex<R : Reader>(&mut self, mut reader : BufferedReader<R>) -> IoResult<()> {
		loop {
			let ch = match reader.read_char() {
				Ok(c) => c,
				Err(ref e) if e.kind == EndOfFile => {
					self.clear_buffer();
					return Ok(())
				},
				Err(ref e) =>
					return Err(e.clone())
			};
			match ch {
				_ if self.escaped => {
					self.escaped = false;
					if ch != '\n' {
						self.string_buffer.push_char(match ch {
							'n' => '\n',
							'r' => '\r',
							't' => '\t',
							'b' => '\x08',
							'f' => '\x0c',
							'0' => '\0',
							'u' => {
								let mut nums = ~"";
								for _ in range(0, 4) {
									nums = format!("{}{}", nums, try!(reader.read_char()));
								}
								let as_num = match FromStrRadix::from_str_radix(nums, 16) {
									Some(v) => v,
									None => 0
								};
								match from_u32(as_num) {
									Some(v) => v,
									None => fail!("{} is not a valid unicode scalar value", as_num)
								}
							},
							'\'' if self.string_start == Some(SingleQuote) => '\'',
							'"' if self.string_start == Some(DoubleQuote) => '"',
							_ => fail!("Invalid escape `{}` after {}", ch, self.string_start)
						});
					}
				},
				'"' if self.string_start.is_some() && self.string_start.unwrap() == DoubleQuote => {
					self.string_start = None;
					self.tokens.push(TString(self.string_buffer.clone().into_owned()));
					self.string_buffer.truncate(0);
				},
				'\'' if self.string_start.is_some() && self.string_start.unwrap() == SingleQuote => {
					self.string_start = None;
					self.tokens.push(TString(self.string_buffer.clone().into_owned()));
					self.string_buffer.truncate(0);
				},
				'\\' if self.string_start.is_some() => self.escaped = true,
				_ if self.string_start.is_some() => self.string_buffer.push_char(ch),
				'"' if self.string_start.is_none() => self.string_start = Some(DoubleQuote),
				'0'.. '9' if self.string_start.is_none() && self.ident_buffer.len() == 0 => {
					self.num_buffer.push_char(ch);
					self.in_num = true;
				},
				'\'' if self.string_start.is_none() => self.string_start = Some(SingleQuote),
				'.' if self.in_num && !self.num_buffer.as_slice().contains(".") => {
					self.num_buffer.push_char(ch);
				},
				';' => {
					self.clear_buffer();
					self.tokens.push(TSemicolon)
				},
				':' => {
					self.clear_buffer();
					self.tokens.push(TColon)
				},
				'.' => {
					self.clear_buffer();
					self.tokens.push(TDot)
				},
				'(' => {
					self.clear_buffer();
					self.tokens.push(TOpenParen)
				},
				')' => {
					self.clear_buffer();
					self.tokens.push(TCloseParen)
				},
				',' => {
					self.clear_buffer();
					self.tokens.push(TComma)
				},
				'{' => {
					self.clear_buffer();
					self.tokens.push(TOpenBlock)
				},
				'}' => {
					self.clear_buffer();
					self.tokens.push(TCloseBlock)
				},
				'[' => {
					self.clear_buffer();
					self.tokens.push(TOpenArray)
				},
				']' => {
					self.clear_buffer();
					self.tokens.push(TCloseArray)
				},
				'?' => {
					self.clear_buffer();
					self.tokens.push(TQuestion)
				},
				'/' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpDiv))
				},
				'*' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpMul))
				},
				'+' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpAdd))
				},
				'-' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpSub))
				},
				'%' => {
					self.clear_buffer();
					self.tokens.push(TNumOp(OpMod))
				},
				'|' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitOr))
				},
				'&' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitAnd))
				},
				'^' => {
					self.clear_buffer();
					self.tokens.push(TBitOp(BitXor))
				},
				'=' => {
					self.clear_buffer();
					self.tokens.push(TEqual)
				},
				_ if is_whitespace(ch) => self.clear_buffer(),
				_ => self.ident_buffer.push_char(ch)
			};
		}
	}
}<|endoftext|>


<commit_before>use std::error::{self, FromError};

pub type SimplesResult<Msg> = Result<Msg, SimplesError>;

#[derive(Debug, Eq, PartialEq)]
pub struct SimplesError {
    pub description: String
}

impl<Error: ::std::error::Error> FromError<Error> for SimplesError {
    fn from_error(err: Error) -> SimplesError {
        SimplesError { description: String::from_str(err.description()) }
    }
}
<commit_msg>SimplesError type implements std::error::Error.<commit_after>use std::error::{Error, FromError};
use std::fmt::{self, Display, Formatter};

use nanomsg;
use protobuf;
use rustc_serialize;

pub type SimplesResult<Msg> = Result<Msg, SimplesError>;

#[derive(Debug, Eq, PartialEq)]
pub struct SimplesError {
    description: String
}

impl Display for SimplesError {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        formatter.write_str(&self.description[])
    }
}

impl Error for SimplesError {
    fn description(&self) -> &str { &self.description[] }

    fn cause(&self) -> Option<&Error> { None }
}

// TODO: Use something like below (albeit with a SimplesErrorTrait)
//       once Rust gets negative trait bounds
//
// impl<Error: ::std::error::Error + !SimplesError>
//     FromError<Error> for SimplesError {
//
//     fn from_error(err: Error) -> SimplesError {
//         SimplesError { description: String::from_str(err.description()) }
//     }
// }

trait ConvertToSimplesError: Error {}
impl ConvertToSimplesError for protobuf::error::ProtobufError {}
impl ConvertToSimplesError for ::std::old_io::IoError {}
impl ConvertToSimplesError for rustc_serialize::json::EncoderError {}

impl<Err: ConvertToSimplesError> FromError<Err> for SimplesError {
    fn from_error(err: Err) -> SimplesError {
        SimplesError { description: String::from_str(err.description()) }
    }
}

impl FromError<nanomsg::NanoError> for SimplesError {
    fn from_error(err: nanomsg::NanoError) -> SimplesError {
        SimplesError { description: String::from_str(err.description) }
    }
}

impl<'a> FromError<&'a str> for SimplesError {
    fn from_error(err: &'a str) -> SimplesError {
        SimplesError { description: String::from_str(err) }
    }
}
<|endoftext|>


<commit_before>//! Error and Result module.
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;
use std::str::Utf8Error;
use std::string::FromUtf8Error;

use httparse;
use url;

#[cfg(feature = "openssl")]
use openssl::ssl::error::SslError;

use self::Error::{
    Method,
    Uri,
    Version,
    Header,
    Status,
    Timeout,
    Io,
    Ssl,
    TooLarge,
    Incomplete,
    Utf8
};

/// Result type often returned from methods that can have hyper `Error`s.
pub type Result<T> = ::std::result::Result<T, Error>;

/// A set of errors that can occur parsing HTTP streams.
#[derive(Debug)]
pub enum Error {
    /// An invalid `Method`, such as `GE,T`.
    Method,
    /// An invalid `RequestUri`, such as `exam ple.domain`.
    Uri(url::ParseError),
    /// An invalid `HttpVersion`, such as `HTP/1.1`
    Version,
    /// An invalid `Header`.
    Header,
    /// A message head is too large to be reasonable.
    TooLarge,
    /// A message reached EOF, but is not complete.
    Incomplete,
    /// An invalid `Status`, such as `1337 ELITE`.
    Status,
    /// A timeout occurred waiting for an IO event.
    Timeout,
    /// Event loop is full and cannot process request
    Full,
    /// An `io::Error` that occurred while trying to read or write to a network stream.
    Io(IoError),
    /// An error from a SSL library.
    Ssl(Box<StdError + Send + Sync>),
    /// Parsing a field as string failed
    Utf8(Utf8Error),

    #[doc(hidden)]
    __Nonexhaustive(Void)
}

#[doc(hidden)]
pub enum Void {}

impl fmt::Debug for Void {
    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
        match *self {}
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Uri(ref e) => fmt::Display::fmt(e, f),
            Io(ref e) => fmt::Display::fmt(e, f),
            Ssl(ref e) => fmt::Display::fmt(e, f),
            Utf8(ref e) => fmt::Display::fmt(e, f),
            ref e => f.write_str(e.description()),
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Method => "Invalid Method specified",
            Version => "Invalid HTTP version specified",
            Header => "Invalid Header provided",
            TooLarge => "Message head is too large",
            Status => "Invalid Status provided",
            Incomplete => "Message is incomplete",
            Timeout => "Timeout",
            Error::Full => "Event loop is full",
            Uri(ref e) => e.description(),
            Io(ref e) => e.description(),
            Ssl(ref e) => e.description(),
            Utf8(ref e) => e.description(),
            Error::__Nonexhaustive(ref void) =>  match *void {}
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Io(ref error) => Some(error),
            Ssl(ref error) => Some(&**error),
            Uri(ref error) => Some(error),
            _ => None,
        }
    }
}

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

impl From<url::ParseError> for Error {
    fn from(err: url::ParseError) -> Error {
        Uri(err)
    }
}

#[cfg(feature = "openssl")]
impl From<SslError> for Error {
    fn from(err: SslError) -> Error {
        match err {
            SslError::StreamError(err) => Io(err),
            err => Ssl(Box::new(err)),
        }
    }
}

impl From<Utf8Error> for Error {
    fn from(err: Utf8Error) -> Error {
        Utf8(err)
    }
}

impl From<FromUtf8Error> for Error {
    fn from(err: FromUtf8Error) -> Error {
        Utf8(err.utf8_error())
    }
}

impl From<httparse::Error> for Error {
    fn from(err: httparse::Error) -> Error {
        match err {
            httparse::Error::HeaderName => Header,
            httparse::Error::HeaderValue => Header,
            httparse::Error::NewLine => Header,
            httparse::Error::Status => Status,
            httparse::Error::Token => Header,
            httparse::Error::TooManyHeaders => TooLarge,
            httparse::Error::Version => Version,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error as StdError;
    use std::io;
    use httparse;
    use url;
    use super::Error;
    use super::Error::*;

    #[test]
    fn test_cause() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = Io(orig);
        assert_eq!(e.cause().unwrap().description(), desc);
    }

    macro_rules! from {
        ($from:expr => $error:pat) => {
            match Error::from($from) {
                e @ $error => {
                    assert!(e.description().len() > 5);
                } ,
                _ => panic!("{:?}", $from)
            }
        }
    }

    macro_rules! from_and_cause {
        ($from:expr => $error:pat) => {
            match Error::from($from) {
                e @ $error => {
                    let desc = e.cause().unwrap().description();
                    assert_eq!(desc, $from.description().to_owned());
                    assert_eq!(desc, e.description());
                },
                _ => panic!("{:?}", $from)
            }
        }
    }

    #[test]
    fn test_from() {

        from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => Io(..));
        from_and_cause!(url::ParseError::EmptyHost => Uri(..));

        from!(httparse::Error::HeaderName => Header);
        from!(httparse::Error::HeaderName => Header);
        from!(httparse::Error::HeaderValue => Header);
        from!(httparse::Error::NewLine => Header);
        from!(httparse::Error::Status => Status);
        from!(httparse::Error::Token => Header);
        from!(httparse::Error::TooManyHeaders => TooLarge);
        from!(httparse::Error::Version => Version);
    }

    #[cfg(feature = "openssl")]
    #[test]
    fn test_from_ssl() {
        use openssl::ssl::error::SslError;

        from!(SslError::StreamError(
            io::Error::new(io::ErrorKind::Other, "ssl negotiation")) => Io(..));
        from_and_cause!(SslError::SslSessionClosed => Ssl(..));
    }
}
<commit_msg>refactor(error): export url::ParseError in hyper's error module<commit_after>//! Error and Result module.
use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;
use std::str::Utf8Error;
use std::string::FromUtf8Error;

use httparse;
use url;

#[cfg(feature = "openssl")]
use openssl::ssl::error::SslError;

use self::Error::{
    Method,
    Uri,
    Version,
    Header,
    Status,
    Timeout,
    Io,
    Ssl,
    TooLarge,
    Incomplete,
    Utf8
};

pub use url::ParseError;

/// Result type often returned from methods that can have hyper `Error`s.
pub type Result<T> = ::std::result::Result<T, Error>;

/// A set of errors that can occur parsing HTTP streams.
#[derive(Debug)]
pub enum Error {
    /// An invalid `Method`, such as `GE,T`.
    Method,
    /// An invalid `RequestUri`, such as `exam ple.domain`.
    Uri(url::ParseError),
    /// An invalid `HttpVersion`, such as `HTP/1.1`
    Version,
    /// An invalid `Header`.
    Header,
    /// A message head is too large to be reasonable.
    TooLarge,
    /// A message reached EOF, but is not complete.
    Incomplete,
    /// An invalid `Status`, such as `1337 ELITE`.
    Status,
    /// A timeout occurred waiting for an IO event.
    Timeout,
    /// Event loop is full and cannot process request
    Full,
    /// An `io::Error` that occurred while trying to read or write to a network stream.
    Io(IoError),
    /// An error from a SSL library.
    Ssl(Box<StdError + Send + Sync>),
    /// Parsing a field as string failed
    Utf8(Utf8Error),

    #[doc(hidden)]
    __Nonexhaustive(Void)
}

#[doc(hidden)]
pub enum Void {}

impl fmt::Debug for Void {
    fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
        match *self {}
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Uri(ref e) => fmt::Display::fmt(e, f),
            Io(ref e) => fmt::Display::fmt(e, f),
            Ssl(ref e) => fmt::Display::fmt(e, f),
            Utf8(ref e) => fmt::Display::fmt(e, f),
            ref e => f.write_str(e.description()),
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        match *self {
            Method => "Invalid Method specified",
            Version => "Invalid HTTP version specified",
            Header => "Invalid Header provided",
            TooLarge => "Message head is too large",
            Status => "Invalid Status provided",
            Incomplete => "Message is incomplete",
            Timeout => "Timeout",
            Error::Full => "Event loop is full",
            Uri(ref e) => e.description(),
            Io(ref e) => e.description(),
            Ssl(ref e) => e.description(),
            Utf8(ref e) => e.description(),
            Error::__Nonexhaustive(ref void) =>  match *void {}
        }
    }

    fn cause(&self) -> Option<&StdError> {
        match *self {
            Io(ref error) => Some(error),
            Ssl(ref error) => Some(&**error),
            Uri(ref error) => Some(error),
            _ => None,
        }
    }
}

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

impl From<url::ParseError> for Error {
    fn from(err: url::ParseError) -> Error {
        Uri(err)
    }
}

#[cfg(feature = "openssl")]
impl From<SslError> for Error {
    fn from(err: SslError) -> Error {
        match err {
            SslError::StreamError(err) => Io(err),
            err => Ssl(Box::new(err)),
        }
    }
}

impl From<Utf8Error> for Error {
    fn from(err: Utf8Error) -> Error {
        Utf8(err)
    }
}

impl From<FromUtf8Error> for Error {
    fn from(err: FromUtf8Error) -> Error {
        Utf8(err.utf8_error())
    }
}

impl From<httparse::Error> for Error {
    fn from(err: httparse::Error) -> Error {
        match err {
            httparse::Error::HeaderName => Header,
            httparse::Error::HeaderValue => Header,
            httparse::Error::NewLine => Header,
            httparse::Error::Status => Status,
            httparse::Error::Token => Header,
            httparse::Error::TooManyHeaders => TooLarge,
            httparse::Error::Version => Version,
        }
    }
}

#[cfg(test)]
mod tests {
    use std::error::Error as StdError;
    use std::io;
    use httparse;
    use url;
    use super::Error;
    use super::Error::*;

    #[test]
    fn test_cause() {
        let orig = io::Error::new(io::ErrorKind::Other, "other");
        let desc = orig.description().to_owned();
        let e = Io(orig);
        assert_eq!(e.cause().unwrap().description(), desc);
    }

    macro_rules! from {
        ($from:expr => $error:pat) => {
            match Error::from($from) {
                e @ $error => {
                    assert!(e.description().len() > 5);
                } ,
                _ => panic!("{:?}", $from)
            }
        }
    }

    macro_rules! from_and_cause {
        ($from:expr => $error:pat) => {
            match Error::from($from) {
                e @ $error => {
                    let desc = e.cause().unwrap().description();
                    assert_eq!(desc, $from.description().to_owned());
                    assert_eq!(desc, e.description());
                },
                _ => panic!("{:?}", $from)
            }
        }
    }

    #[test]
    fn test_from() {

        from_and_cause!(io::Error::new(io::ErrorKind::Other, "other") => Io(..));
        from_and_cause!(url::ParseError::EmptyHost => Uri(..));

        from!(httparse::Error::HeaderName => Header);
        from!(httparse::Error::HeaderName => Header);
        from!(httparse::Error::HeaderValue => Header);
        from!(httparse::Error::NewLine => Header);
        from!(httparse::Error::Status => Status);
        from!(httparse::Error::Token => Header);
        from!(httparse::Error::TooManyHeaders => TooLarge);
        from!(httparse::Error::Version => Version);
    }

    #[cfg(feature = "openssl")]
    #[test]
    fn test_from_ssl() {
        use openssl::ssl::error::SslError;

        from!(SslError::StreamError(
            io::Error::new(io::ErrorKind::Other, "ssl negotiation")) => Io(..));
        from_and_cause!(SslError::SslSessionClosed => Ssl(..));
    }
}
<|endoftext|>


<commit_before>extern crate config;
use self::config::error::ConfigError;

use std::fmt;
use std::error::Error;

use self::WrapConfigError::CError;

#[derive(Debug)]
pub enum WrapConfigError {
    CError(String),
}

impl fmt::Display for WrapConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }
}

impl Error for WrapConfigError {
    fn description(&self) -> &str {
        match *self {
            CError(ref desc) => &(*desc)[..],
        }
    }
}

impl From<ConfigError> for WrapConfigError {
    fn from(config: ConfigError) -> WrapConfigError {
        let default_desc = format!("unknown parse error");
        CError(format!("{}: {}", config.desc, config.detail.unwrap_or(default_desc)))
    }
}
<commit_msg>error: add the kind of error the the description<commit_after>extern crate config;
use self::config::error::ConfigError;

use std::fmt;
use std::error::Error;

use self::WrapConfigError::CError;

#[derive(Debug)]
pub enum WrapConfigError {
    CError(String),
}

impl fmt::Display for WrapConfigError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "{}", self.description()));
        Ok(())
    }
}

impl Error for WrapConfigError {
    fn description(&self) -> &str {
        match *self {
            CError(ref desc) => &(*desc)[..],
        }
    }
}

impl From<ConfigError> for WrapConfigError {
    fn from(config: ConfigError) -> WrapConfigError {
        let default_desc = format!("unknown parse error");
        CError(format!("{:?} {}: {}", config.kind, config.desc, config.detail.unwrap_or(default_desc)))
    }
}
<|endoftext|>


<commit_before>//! This module focuses on handling errors generated when using Ardite in a
//! graceful manner.

use std::io::Error as IOError;
use std::error::Error as ErrorTrait;
use std::fmt::{Display, Formatter, Result as FmtResult};

#[cfg(test)]
use regex::Regex;
use serde_json::error::Error as JSONError;
use serde_yaml::error::Error as YAMLError;

/// Any error generated by Ardite or it‘s drivers should be output using this
/// type. This allows for a comprehensive display of the error when a service
/// reports it to the user.
///
/// Information included with the error includes an `ErrorCode` (which maps to
/// an HTTP status code), a message, and an optional hint telling the user how
/// to fix the error.
///
/// Typically hints should be included for what would be considered the `4xx`
/// (in HTTP language) class of error codes.
///
/// # Tips For Writing Good Hint Messages
/// - Write in the second person (“You should…”).
/// - Always recommend a solution (“You should try…”, not “You must do…”).
/// - Be as specific as possible, if you have line numbers give them. If you
///   have file paths provide them.
/// - If it is a common error which generally confuses developers, provide a
///   link to a page which better explains the error and specific steps to
///   fix it.
#[derive(PartialEq, Debug)]
pub struct Error {
  /// A specific error code which describes the error.
  code: ErrorCode,
  /// A message providing more detail beyond the error code.
  message: String,
  /// A hint to the user on what to do next to try and avoid the error
  /// happening again. This is optional.
  hint: Option<String>
}

impl Error {
  /// Easily create a new error.
  pub fn new<S>(code: ErrorCode, message: S, hint: Option<S>) -> Self where S: Into<String> {
    Error {
      code: code,
      message: message.into(),
      hint: hint.map(|string| string.into())
    }
  }

  /// Get the code for the error.
  pub fn code(&self) -> &ErrorCode {
    &self.code
  }

  /// Get the message for the error.
  pub fn message(&self) -> &str {
    &self.message
  }

  /// Get the hint—for the error (see what I did there?).
  pub fn hint(&self) -> Option<&str> {
    self.hint.as_ref().map(|s| s.as_str())
  }

  /// Convenience function for saying a thing failed validation using
  /// `ErrorCode::BadRequest`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::validation("Failed validation.", "Try fixing your syntax!");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::BadRequest, "Failed validation.", Some("Try fixing your syntax!")));
  /// ```
  pub fn validation<S1, S2>(message: S1, hint: S2) -> Self where S1: Into<String>, S2: Into<String> {
    Error {
      code: ErrorCode::BadRequest,
      message: message.into(),
      hint: Some(hint.into())
    }
  }

  /// Convenience function for saying there was an internal error using
  /// `ErrorCode::Internal`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::internal("Something blew up.");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::Internal, "Something blew up.", None));
  /// ```
  pub fn internal<S>(message: S) -> Self where S: Into<String> {
    Error {
      code: ErrorCode::Internal,
      message: message.into(),
      hint: None
    }
  }

  /// Convenience function for creating an unimplemented error with a plain
  /// message describing what is unimplemented using
  /// `ErrorCode::NotImplemented`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::unimplemented("Cache invalidation is hard.");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::NotImplemented, "Cache invalidation is hard.", None));
  /// ```
  pub fn unimplemented<S>(message: S) -> Self where S: Into<String> {
    Error {
      code: ErrorCode::NotImplemented,
      message: message.into(),
      hint: None
    }
  }

  /// Special assertion for error messages. Takes a regular expression string
  /// argument which will automatically be constructed into a regualr
  /// expression. Only available in testing environments. Panics if the regular
  /// expression doesn’t match the error message string.
  #[cfg(test)]
  pub fn assert_message(&self, regex_str: &str) {
    if !Regex::new(regex_str).unwrap().is_match(&self.message) {
      panic!("Error message \"{}\" does not match regex /{}/", self.message, regex_str);
    }
  }
}

impl Display for Error {
  fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
    try!(write!(fmt, "\ncode: {}", self.code));
    try!(write!(fmt, "\nmessage: {}", self.message));

    if let Some(ref hint) = self.hint {
      try!(write!(fmt, "\nhint: {}", hint));
    }

    Ok(())
  }
}

impl ErrorTrait for Error {
  fn description(&self) -> &str {
    self.message.as_str()
  }
}

impl From<IOError> for Error {
  fn from(error: IOError) -> Self {
    Error {
      code: ErrorCode::Internal,
      message: error.description().to_owned(),
      hint: None
    }
  }
}

impl From<JSONError> for Error {
  fn from(error: JSONError) -> Self {
    match error {
      JSONError::Syntax(_, line, column) => {
        Error {
          code: ErrorCode::BadRequest,
          message: "Syntax error.".to_owned(),
          hint: Some(format!("Max sure your JSON syntax is correct around line {} column {}.", line, column))
        }
      },
      _ => {
        Error {
          code: ErrorCode::Internal,
          message: error.description().to_owned(),
          hint: None
        }
      }
    }
  }
}

impl From<YAMLError> for Error {
  fn from(error: YAMLError) -> Self {
    match error {
      YAMLError::Custom(ref message) => {
        Error {
          code: ErrorCode::BadRequest,
          message: message.to_owned(),
          hint: Some("Make sure your YAML syntax is correct.".to_owned())
        }
      },
      _ => {
        Error {
          code: ErrorCode::Internal,
          message: error.description().to_owned(),
          hint: None
        }
      }
    }
  }
}

/// The code of an error. Designed to easily map to [HTTP status codes][1],
/// however only a subset of these codes are supported and some custom codes
/// were added.
///
/// [1]: http://www.restapitutorial.com/httpstatuscodes.html
#[derive(PartialEq, Debug)]
pub enum ErrorCode {
  /// A bad syntax was used.
  BadRequest,
  /// Permissions do not allow this to happen.
  Forbidden,
  /// Resource was not found.
  NotFound,
  /// The requested resource is not acceptable.
  NotAcceptable,
  /// Present data made the request fail.
  Conflict,
  /// There was an invalid range.
  BadRange,
  /// Something bad happened inside a driver.
  Internal,
  /// The feature has not been implemented.
  NotImplemented
}

// Dump all the error codes into the export space.
pub use ErrorCode::*;

impl ErrorCode {
  pub fn code(&self) -> u16 {
    match *self {
      BadRequest => 400,
      Forbidden => 403,
      NotFound => 404,
      NotAcceptable => 406,
      Conflict => 409,
      BadRange => 416,
      Internal => 500,
      NotImplemented => 501
    }
  }

  pub fn reason(&self) -> &str {
    match *self {
      BadRequest => "Bad Request",
      Forbidden => "Forbidden",
      NotFound => "Not Found",
      NotAcceptable => "Not Acceptable",
      Conflict => "Conflict",
      BadRange => "Range Not Satisfiable",
      Internal => "Internal Error",
      NotImplemented => "Not Implemented"
    }
  }
}

impl Display for ErrorCode {
  fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
    try!(write!(fmt, "{} {}", self.code(), self.reason()));
    Ok(())
  }
}
<commit_msg>feat(error): add error to value method<commit_after>//! This module focuses on handling errors generated when using Ardite in a
//! graceful manner.

use std::io::Error as IOError;
use std::error::Error as ErrorTrait;
use std::fmt::{Display, Formatter, Result as FmtResult};

#[cfg(test)]
use regex::Regex;
use serde_json::error::Error as JSONError;
use serde_yaml::error::Error as YAMLError;

/// Any error generated by Ardite or it‘s drivers should be output using this
/// type. This allows for a comprehensive display of the error when a service
/// reports it to the user.
///
/// Information included with the error includes an `ErrorCode` (which maps to
/// an HTTP status code), a message, and an optional hint telling the user how
/// to fix the error.
///
/// Typically hints should be included for what would be considered the `4xx`
/// (in HTTP language) class of error codes.
///
/// # Tips For Writing Good Hint Messages
/// - Write in the second person (“You should…”).
/// - Always recommend a solution (“You should try…”, not “You must do…”).
/// - Be as specific as possible, if you have line numbers give them. If you
///   have file paths provide them.
/// - If it is a common error which generally confuses developers, provide a
///   link to a page which better explains the error and specific steps to
///   fix it.
#[derive(PartialEq, Debug)]
pub struct Error {
  /// A specific error code which describes the error.
  code: ErrorCode,
  /// A message providing more detail beyond the error code.
  message: String,
  /// A hint to the user on what to do next to try and avoid the error
  /// happening again. This is optional.
  hint: Option<String>
}

impl Error {
  /// Easily create a new error.
  pub fn new<S>(code: ErrorCode, message: S, hint: Option<S>) -> Self where S: Into<String> {
    Error {
      code: code,
      message: message.into(),
      hint: hint.map(|string| string.into())
    }
  }

  /// Get the code for the error.
  pub fn code(&self) -> &ErrorCode {
    &self.code
  }

  /// Get the message for the error.
  pub fn message(&self) -> &str {
    &self.message
  }

  /// Get the hint—for the error (see what I did there?).
  pub fn hint(&self) -> Option<&str> {
    self.hint.as_ref().map(|s| s.as_str())
  }

  /// Gets an object which represents the error.
  ///
  /// # Example
  /// ```rust
  /// #[macro_use(value)]
  /// extern crate ardite;
  ///
  /// use ardite::error::{Error, NotFound};
  ///
  /// # fn main() {
  ///
  /// let error = Error::new(NotFound, "Not found…", Some("Go to the light!"));
  ///
  /// let value = value!({
  ///   "error" => true,
  ///   "message" => "Not found…",
  ///   "hint" => "Go to the light!"
  /// });
  ///
  /// assert_eq!(error.to_value(), value);
  ///
  /// # }
  /// ```
  pub fn to_value(&self) -> Value {
    let mut object = Object::new();

    // TODO: implement an insert method which isn‘t as strict.
    object.insert("error".to_owned(), Value::Boolean(true));
    object.insert("message".to_owned(), Value::String(self.message.clone()));

    if let Some(ref hint) = self.hint {
      object.insert("hint".to_owned(), Value::String(hint.clone()));
    }

    Value::Object(object)
  }

  /// Convenience function for saying a thing failed validation using
  /// `ErrorCode::BadRequest`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::validation("Failed validation.", "Try fixing your syntax!");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::BadRequest, "Failed validation.", Some("Try fixing your syntax!")));
  /// ```
  pub fn validation<S1, S2>(message: S1, hint: S2) -> Self where S1: Into<String>, S2: Into<String> {
    Error {
      code: ErrorCode::BadRequest,
      message: message.into(),
      hint: Some(hint.into())
    }
  }

  /// Convenience function for saying there was an internal error using
  /// `ErrorCode::Internal`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::internal("Something blew up.");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::Internal, "Something blew up.", None));
  /// ```
  pub fn internal<S>(message: S) -> Self where S: Into<String> {
    Error {
      code: ErrorCode::Internal,
      message: message.into(),
      hint: None
    }
  }

  /// Convenience function for creating an unimplemented error with a plain
  /// message describing what is unimplemented using
  /// `ErrorCode::NotImplemented`.
  ///
  /// # Example
  /// ```rust
  /// use ardite::error::{Error, ErrorCode};
  ///
  /// let error = Error::unimplemented("Cache invalidation is hard.");
  ///
  /// assert_eq!(error, Error::new(ErrorCode::NotImplemented, "Cache invalidation is hard.", None));
  /// ```
  pub fn unimplemented<S>(message: S) -> Self where S: Into<String> {
    Error {
      code: ErrorCode::NotImplemented,
      message: message.into(),
      hint: None
    }
  }

  /// Special assertion for error messages. Takes a regular expression string
  /// argument which will automatically be constructed into a regualr
  /// expression. Only available in testing environments. Panics if the regular
  /// expression doesn’t match the error message string.
  #[cfg(test)]
  pub fn assert_message(&self, regex_str: &str) {
    if !Regex::new(regex_str).unwrap().is_match(&self.message) {
      panic!("Error message \"{}\" does not match regex /{}/", self.message, regex_str);
    }
  }
}

impl Display for Error {
  fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
    try!(write!(fmt, "\ncode: {}", self.code));
    try!(write!(fmt, "\nmessage: {}", self.message));

    if let Some(ref hint) = self.hint {
      try!(write!(fmt, "\nhint: {}", hint));
    }

    Ok(())
  }
}

impl ErrorTrait for Error {
  fn description(&self) -> &str {
    self.message.as_str()
  }
}

impl From<IOError> for Error {
  fn from(error: IOError) -> Self {
    Error {
      code: ErrorCode::Internal,
      message: error.description().to_owned(),
      hint: None
    }
  }
}

impl From<JSONError> for Error {
  fn from(error: JSONError) -> Self {
    match error {
      JSONError::Syntax(_, line, column) => {
        Error {
          code: ErrorCode::BadRequest,
          message: "Syntax error.".to_owned(),
          hint: Some(format!("Max sure your JSON syntax is correct around line {} column {}.", line, column))
        }
      },
      _ => {
        Error {
          code: ErrorCode::Internal,
          message: error.description().to_owned(),
          hint: None
        }
      }
    }
  }
}

impl From<YAMLError> for Error {
  fn from(error: YAMLError) -> Self {
    match error {
      YAMLError::Custom(ref message) => {
        Error {
          code: ErrorCode::BadRequest,
          message: message.to_owned(),
          hint: Some("Make sure your YAML syntax is correct.".to_owned())
        }
      },
      _ => {
        Error {
          code: ErrorCode::Internal,
          message: error.description().to_owned(),
          hint: None
        }
      }
    }
  }
}

/// The code of an error. Designed to easily map to [HTTP status codes][1],
/// however only a subset of these codes are supported and some custom codes
/// were added.
///
/// [1]: http://www.restapitutorial.com/httpstatuscodes.html
#[derive(PartialEq, Debug)]
pub enum ErrorCode {
  /// A bad syntax was used.
  BadRequest,
  /// Permissions do not allow this to happen.
  Forbidden,
  /// Resource was not found.
  NotFound,
  /// The requested resource is not acceptable.
  NotAcceptable,
  /// Present data made the request fail.
  Conflict,
  /// There was an invalid range.
  BadRange,
  /// Something bad happened inside a driver.
  Internal,
  /// The feature has not been implemented.
  NotImplemented
}

// Dump all the error codes into the export space.
pub use ErrorCode::*;

impl ErrorCode {
  pub fn code(&self) -> u16 {
    match *self {
      BadRequest => 400,
      Forbidden => 403,
      NotFound => 404,
      NotAcceptable => 406,
      Conflict => 409,
      BadRange => 416,
      Internal => 500,
      NotImplemented => 501
    }
  }

  pub fn reason(&self) -> &str {
    match *self {
      BadRequest => "Bad Request",
      Forbidden => "Forbidden",
      NotFound => "Not Found",
      NotAcceptable => "Not Acceptable",
      Conflict => "Conflict",
      BadRange => "Range Not Satisfiable",
      Internal => "Internal Error",
      NotImplemented => "Not Implemented"
    }
  }
}

impl Display for ErrorCode {
  fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
    try!(write!(fmt, "{} {}", self.code(), self.reason()));
    Ok(())
  }
}
<|endoftext|>


<commit_before>use std::convert::From;

use ::{Player, WIDTH, HEIGHT};
use unit::{Unit, PovUnit, GeneralUnit};
use move_conditions::{ALL_DIRECTIONS, Move, MoveCondition};

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Field<T: Unit> {
    pub rows: [[Option<T>; WIDTH]; HEIGHT],
}

impl<T: Unit> Field<T> {
    pub fn new() -> Field<T> {
        let rows = [[None; WIDTH]; HEIGHT];
        Field {
            rows: rows,
        }
    }

    pub fn possible_moves(&self, player: Player, move_condition: &MoveCondition) -> Vec<Move> {
        let mut res = Vec::new();

        for (j, row) in self.rows.iter().enumerate() {
            for (i, _) in row.iter().enumerate().filter(|&(_, x)| {if let &Some(x) = x {x.owner() == player} else {false} }) {
                for direction in ALL_DIRECTIONS {
                    let movement = Move {from: (i, j), direction: *direction};
                    if move_condition.is_valid(movement) { res.push(movement); }
                }
            }
        }

        res
    }
}

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct PovField {
    pub pov: Player,
    pub rows: [[Option<PovUnit>; WIDTH]; HEIGHT],
}

impl<'a> From<(&'a Field<GeneralUnit>, Player)> for PovField {
    fn from( data: (&Field<GeneralUnit>, Player) ) -> PovField {
        let (ref field, player) = data;
        let mut rows = [[None; WIDTH]; HEIGHT];

        for (i, ref row) in field.rows.iter().enumerate() {
            for (j, unit) in row.iter().enumerate() {
                if let Some(unit) = *unit {
                    rows[i][j] = Some( PovUnit::from( (unit, player) ) );
                }
            }
        }

        PovField {
            pov: player,
            rows: rows,
        }
    }
}
<commit_msg>Use Field struct in PovField<commit_after>use std::convert::From;

use ::{Player, WIDTH, HEIGHT};
use unit::{Unit, PovUnit, GeneralUnit};
use move_conditions::{ALL_DIRECTIONS, Move, MoveCondition};

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Field<T: Unit> {
    pub rows: [[Option<T>; WIDTH]; HEIGHT],
}

impl<T: Unit> Field<T> {
    pub fn new() -> Field<T> {
        let rows = [[None; WIDTH]; HEIGHT];
        Field {
            rows: rows,
        }
    }

    pub fn possible_moves(&self, player: Player, move_condition: &MoveCondition) -> Vec<Move> {
        let mut res = Vec::new();

        for (j, row) in self.rows.iter().enumerate() {
            for (i, _) in row.iter().enumerate().filter(|&(_, x)| {if let &Some(x) = x {x.owner() == player} else {false} }) {
                for direction in ALL_DIRECTIONS {
                    let movement = Move {from: (i, j), direction: *direction};
                    if move_condition.is_valid(movement) { res.push(movement); }
                }
            }
        }

        res
    }
}

#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct PovField {
    pub pov: Player,
    pub field: Field<PovUnit>,
}

impl<'a> From<(&'a Field<GeneralUnit>, Player)> for PovField {
    fn from( data: (&Field<GeneralUnit>, Player) ) -> PovField {
        let (ref field, player) = data;
        let mut rows = [[None; WIDTH]; HEIGHT];

        for (i, ref row) in field.rows.iter().enumerate() {
            for (j, unit) in row.iter().enumerate() {
                if let Some(unit) = *unit {
                    rows[i][j] = Some( PovUnit::from( (unit, player) ) );
                }
            }
        }

        PovField {
            pov: player,
            field: Field{ rows: rows },
        }
    }
}
<|endoftext|>


<commit_before>
use glium;
use glium::Surface;
use support;

pub struct Frame<'a, 'b> {
	color: [f32; 4],
	finished: bool,
	delta: f64,
	display: &'a glium::Display,
	target: glium::Frame,
	programs: &'b (glium::Program, glium::Program),
}

impl<'a, 'b> Frame<'a, 'b> {
	pub fn new(
		display: &'a glium::Display,
		programs: &'b (glium::Program, glium::Program),
		delta: f64,
	) -> Self {
		Frame {
			color: [0.0; 4],
			finished: false,
			delta: delta,
			display: display,
			target: display.draw(),
			programs: programs,
		}
	}

	pub fn delta(&self) -> f64 {
		self.delta
	}

	pub fn clear(&mut self) {
		self.target.clear_color(0.0, 0.0, 0.0, 1.0);
	}

	pub fn clear_to_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
		self.target.clear_color(red, green, blue, alpha);
	}

	pub fn set_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
		self.color = [red, green, blue, alpha];
	}

	pub fn set_color_html(&mut self, color: &str) {
		let mut bytes = color.as_bytes();
		if bytes[0] == b'#' {
			bytes = &bytes[1..];
		}

		use std::str::from_utf8;
		use std::u8;

		if bytes.len() == 3 {
			let r = u8::from_str_radix(from_utf8(&vec![bytes[0], bytes[0]]).unwrap(), 16).unwrap();
			let g = u8::from_str_radix(from_utf8(&vec![bytes[1], bytes[1]]).unwrap(), 16).unwrap();
			let b = u8::from_str_radix(from_utf8(&vec![bytes[2], bytes[2]]).unwrap(), 16).unwrap();
			self.set_color(
				(r as f32) / 255.0,
				(g as f32) / 255.0,
				(b as f32) / 255.0,
				1.0,
			);
		} else if bytes.len() == 6 {
			let r = u8::from_str_radix(from_utf8(&bytes[0..2]).unwrap(), 16).unwrap();
			let g = u8::from_str_radix(from_utf8(&bytes[2..4]).unwrap(), 16).unwrap();
			let b = u8::from_str_radix(from_utf8(&bytes[4..6]).unwrap(), 16).unwrap();
			self.set_color(
				(r as f32) / 255.0,
				(g as f32) / 255.0,
				(b as f32) / 255.0,
				1.0,
			);
		}
	}

	pub fn draw(&mut self, points: &[(f32, f32)]) {
		let vert_buff =
			support::buffer::poly_vert_buffer(self.display, &points, self.color).unwrap();
		let indices = glium::index::NoIndices(glium::index::PrimitiveType::TriangleFan);
		self.target
			.draw(
				&vert_buff,
				&indices,
				&self.programs.0,
				&glium::uniforms::EmptyUniforms,
				&glium::DrawParameters {
					blend: glium::draw_parameters::Blend::alpha_blending(),
					..Default::default()
				},
			)
			.unwrap();
	}

	pub fn draw_line(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
		let vert_buff =
			support::buffer::line_vert_buff(self.display, x1, y1, x2, y2, self.color).unwrap();
		let indices = glium::index::NoIndices(glium::index::PrimitiveType::LineStrip);
		self.target
			.draw(
				&vert_buff,
				&indices,
				&self.programs.0,
				&glium::uniforms::EmptyUniforms,
				&glium::DrawParameters {
					blend: glium::draw_parameters::Blend::alpha_blending(),
					..Default::default()
				},
			)
			.unwrap();
	}

	pub fn draw_rect(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
		self.draw(&vec![(x1, y1), (x1, y2), (x2, y2), (x2, y1)]);
	}

	pub fn draw_circle(&mut self, x: f32, y: f32, rx: f32, ry: f32, step_size: u32) {
		let circle: Vec<(f32, f32)> = (0u32..360)
			.filter(|d| d % step_size == 0)
			.map(|d| {
				let r = (d as f32).to_radians();
				(x + r.cos() * rx, y + r.sin() * ry)
			})
			.collect();
		self.draw(&circle);
	}

	pub fn draw_image(
		&mut self,
		image: &super::Image,
		position: (f32, f32),
		size: (f32, f32),
		parameters: Option<super::ImageParameters>,
	) {
		let vert_buff = support::buffer::image_vert_buffer(
			self.display,
			position.0,
			position.1,
			position.0 + size.0,
			position.1 + size.1,
			parameters.unwrap_or(Default::default()),
		).unwrap();
		let indices = glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip);
		self.target
			.draw(
				&vert_buff,
				&indices,
				&self.programs.1,
				&uniform! {
					tex: image.get_texture(),
				},
				&glium::DrawParameters {
					blend: glium::draw_parameters::Blend::alpha_blending(),
					..Default::default()
				},
			)
			.unwrap();
	}

	pub fn finish(mut self) {
		let ok = self.target.finish();
		self.finished = ok.is_ok();
	}
}
<commit_msg>Updated draw_rect to take with / height<commit_after>
use glium;
use glium::Surface;
use support;

pub struct Frame<'a, 'b> {
	color: [f32; 4],
	finished: bool,
	delta: f64,
	display: &'a glium::Display,
	target: glium::Frame,
	programs: &'b (glium::Program, glium::Program),
}

impl<'a, 'b> Frame<'a, 'b> {
	pub fn new(
		display: &'a glium::Display,
		programs: &'b (glium::Program, glium::Program),
		delta: f64,
	) -> Self {
		Frame {
			color: [0.0; 4],
			finished: false,
			delta: delta,
			display: display,
			target: display.draw(),
			programs: programs,
		}
	}

	pub fn delta(&self) -> f64 {
		self.delta
	}

	pub fn clear(&mut self) {
		self.target.clear_color(0.0, 0.0, 0.0, 1.0);
	}

	pub fn clear_to_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
		self.target.clear_color(red, green, blue, alpha);
	}

	pub fn set_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
		self.color = [red, green, blue, alpha];
	}

	pub fn set_color_html(&mut self, color: &str) {
		let mut bytes = color.as_bytes();
		if bytes[0] == b'#' {
			bytes = &bytes[1..];
		}

		use std::str::from_utf8;
		use std::u8;

		if bytes.len() == 3 {
			let r = u8::from_str_radix(from_utf8(&vec![bytes[0], bytes[0]]).unwrap(), 16).unwrap();
			let g = u8::from_str_radix(from_utf8(&vec![bytes[1], bytes[1]]).unwrap(), 16).unwrap();
			let b = u8::from_str_radix(from_utf8(&vec![bytes[2], bytes[2]]).unwrap(), 16).unwrap();
			self.set_color(
				(r as f32) / 255.0,
				(g as f32) / 255.0,
				(b as f32) / 255.0,
				1.0,
			);
		} else if bytes.len() == 6 {
			let r = u8::from_str_radix(from_utf8(&bytes[0..2]).unwrap(), 16).unwrap();
			let g = u8::from_str_radix(from_utf8(&bytes[2..4]).unwrap(), 16).unwrap();
			let b = u8::from_str_radix(from_utf8(&bytes[4..6]).unwrap(), 16).unwrap();
			self.set_color(
				(r as f32) / 255.0,
				(g as f32) / 255.0,
				(b as f32) / 255.0,
				1.0,
			);
		}
	}

	pub fn draw(&mut self, points: &[(f32, f32)]) {
		let vert_buff =
			support::buffer::poly_vert_buffer(self.display, &points, self.color).unwrap();
		let indices = glium::index::NoIndices(glium::index::PrimitiveType::TriangleFan);
		self.target
			.draw(
				&vert_buff,
				&indices,
				&self.programs.0,
				&glium::uniforms::EmptyUniforms,
				&glium::DrawParameters {
					blend: glium::draw_parameters::Blend::alpha_blending(),
					..Default::default()
				},
			)
			.unwrap();
	}

	pub fn draw_line(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
		let vert_buff =
			support::buffer::line_vert_buff(self.display, x1, y1, x2, y2, self.color).unwrap();
		let indices = glium::index::NoIndices(glium::index::PrimitiveType::LineStrip);
		self.target
			.draw(
				&vert_buff,
				&indices,
				&self.programs.0,
				&glium::uniforms::EmptyUniforms,
				&glium::DrawParameters {
					blend: glium::draw_parameters::Blend::alpha_blending(),
					..Default::default()
				},
			)
			.unwrap();
	}

	pub fn draw_rect(&mut self, x: f32, y: f32, w: f32, h: f32) {
		self.draw(&vec![(x, y), (x, y + h), (x + w, y + h), (x + w, y)]);
	}

	pub fn draw_circle(&mut self, x: f32, y: f32, rx: f32, ry: f32, step_size: u32) {
		let circle: Vec<(f32, f32)> = (0u32..360)
			.filter(|d| d % step_size == 0)
			.map(|d| {
				let r = (d as f32).to_radians();
				(x + r.cos() * rx, y + r.sin() * ry)
			})
			.collect();
		self.draw(&circle);
	}

	pub fn draw_image(
		&mut self,
		image: &super::Image,
		position: (f32, f32),
		size: (f32, f32),
		parameters: Option<super::ImageParameters>,
	) {
		let vert_buff = support::buffer::image_vert_buffer(
			self.display,
			position.0,
			position.1,
			position.0 + size.0,
			position.1 + size.1,
			parameters.unwrap_or(Default::default()),
		).unwrap();
		let indices = glium::index::NoIndices(glium::index::PrimitiveType::TriangleStrip);
		self.target
			.draw(
				&vert_buff,
				&indices,
				&self.programs.1,
				&uniform! {
					tex: image.get_texture(),
				},
				&glium::DrawParameters {
					blend: glium::draw_parameters::Blend::alpha_blending(),
					..Default::default()
				},
			)
			.unwrap();
	}

	pub fn finish(mut self) {
		let ok = self.target.finish();
		self.finished = ok.is_ok();
	}
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Anagrams

extern crate collections;

use collections::{HashMap, HashSet};
use std::str;

#[cfg(not(test))]
use std::io::{File, BufferedReader};
use std::cmp::max;

fn sort_string(string: &str) -> ~str {
	let mut chars: ~[char] = string.chars().collect();
	chars.sort();
	str::from_chars(chars)
}

// Returns groups of anagrams (each group consists of a set containing the words)
fn get_anagrams<T: Buffer>(mut reader: T) -> HashMap<~str, HashSet<~str>> {
    let mut groups: HashMap<~str, HashSet<~str>> = HashMap::new();

    // Make groups of words according to the letters they contain
	for line in reader.lines() {
		let s = line.unwrap().trim().to_owned();
		groups.insert_or_update_with(
            sort_string(s.clone()),                                       // The key
            { let mut set = HashSet::new(); set.insert(s.clone()); set }, // The value
			|_, group| { group.insert(s.clone()); }                       // The closure to update the value
		);
	}

    groups
}

// Returns the groups of anagrams that contain the most words in them
fn get_biggest_groups(groups: &HashMap<~str, HashSet<~str>>) -> HashMap<~str, HashSet<~str>> {
    let max_length = groups.iter().fold(0, |current_max, (_, group)| max(current_max, group.len()));
    groups.iter().filter(|&(_, group)| group.len() == max_length).map(|(x, y)| (x.clone(), y.clone())).collect()
}

#[cfg(not(test))]
fn main () {
	let path = Path::new("resources/unixdict.txt");
	let reader = BufferedReader::new(File::open(&path));

	let anagram_groups = get_anagrams(reader);
	let biggest_groups = get_biggest_groups(&anagram_groups);

    // Print the words in the biggest groups of anagrams
	for (_, group) in biggest_groups.iter() {
        for word in group.iter() {
            print!("{} ", *word)
        }
        println!("")
	}
}

#[test]
fn basic_test() {
    // Groups of anagrams
    let group1: HashSet<~str> = vec!("lane".to_owned(), "neal".to_owned(), "lean".to_owned()).move_iter().collect();
    let group2: HashSet<~str> = vec!("angel".to_owned(), "angle".to_owned(), "galen".to_owned()).move_iter().collect();
    let group3: HashSet<~str> = vec!("glare".to_owned(), "large".to_owned()).move_iter().collect();

    // Prepare the input for the program
    // We will get a string like "lane\nneal\nlean\nangel\nangle\ngalen\nglare\nlarge"
    let mut word_iter = group1.iter().chain(group2.iter().chain(group3.iter()));
    let mut words = StrBuf::new();

    words.push_str(word_iter.next().unwrap().as_slice());
    for word in word_iter {
        words.push_str("\n");
        words.push_str(word.as_slice());
    }

    // Here begins the real testing
    let all_groups = get_anagrams(std::io::MemReader::new(words.to_str().bytes().collect()));
    let biggest_groups = get_biggest_groups(&all_groups);

    // Groups 1, 2 and 3 are contained in "all_groups"
    assert!(all_groups.iter().any(|(_, group)| *group == group1));
    assert!(all_groups.iter().any(|(_, group)| *group == group2));
    assert!(all_groups.iter().any(|(_, group)| *group == group3));

    // Groups 1 and 2 are contained in "biggest_groups". Group 3 is not.
    assert!(biggest_groups.iter().any(|(_, group)| *group == group1));
    assert!(biggest_groups.iter().any(|(_, group)| *group == group2));
    assert!(biggest_groups.iter().all(|(_, group)| *group != group3));
}
<commit_msg>fix anagrams<commit_after>// Implements http://rosettacode.org/wiki/Anagrams

extern crate collections;

use collections::{HashMap, HashSet};
use std::str;

#[cfg(test)]
use std::io::MemReader;

#[cfg(not(test))]
use std::io::{File, BufferedReader};
use std::cmp::max;

fn sort_string(string: &str) -> ~str {
    let mut chars: Vec<char> = string.chars().collect();
    chars.sort();
    str::from_chars(chars.as_slice())
}

// Returns groups of anagrams where each group consists of a set
// containing the words
fn get_anagrams<T: Buffer>(mut reader: T) -> HashMap<~str, HashSet<~str>> {
    let mut groups: HashMap<~str, HashSet<~str>> = HashMap::new();

    // Make groups of words according to the letters they contain
    for line in reader.lines() {
	let s = line.unwrap().trim().to_owned();
	groups.insert_or_update_with(
            // The key
            sort_string(s.clone()),
            // The value
            {
                let mut set = HashSet::new();
                set.insert(s.clone());
                set
            },
            // The closure to update the value
	    |_, group| { group.insert(s.clone()); }
            );
    }

    groups
}

// Returns the groups of anagrams that contain the most words in them
fn get_biggest_groups(groups: &HashMap<~str, HashSet<~str>>)
                      -> HashMap<~str, HashSet<~str>> {
    let max_length = groups.iter()
        .fold(0, |current_max, (_, group)| max(current_max,
                                               group.len()));
    groups.iter()
        .filter(|&(_, group)| group.len() == max_length)
        .map(|(x, y)| (x.clone(), y.clone()))
        .collect()
}

#[cfg(not(test))]
fn main () {
    let path = Path::new("src/resources/unixdict.txt");
    let reader = BufferedReader::new(File::open(&path));

    let anagram_groups = get_anagrams(reader);
    let biggest_groups = get_biggest_groups(&anagram_groups);

    // Print the words in the biggest groups of anagrams
    for (_, group) in biggest_groups.iter() {
        for word in group.iter() {
            print!("{} ", *word)
        }
        println!("")
    }
}

#[test]
fn basic_test() {
    // Groups of anagrams
    let group1: HashSet<~str> = vec!("lane".to_owned(),
                                     "neal".to_owned(),
                                     "lean".to_owned()).move_iter().collect();
    let group2: HashSet<~str> = vec!("angel".to_owned(),
                                     "angle".to_owned(),
                                     "galen".to_owned()).move_iter().collect();
    let group3: HashSet<~str> = vec!("glare".to_owned(),
                                     "large".to_owned()).move_iter().collect();

    // Prepare the input for the program
    // We will get a string like "lane\nneal\nlean\nangel\nangle..."
    let mut word_iter = group1.iter().chain(group2.iter().chain(group3.iter()));
    let mut words = StrBuf::new();

    words.push_str(word_iter.next().unwrap().as_slice());
    for word in word_iter {
        words.push_str("\n");
        words.push_str(word.as_slice());
    }

    // Here begins the real testing
    let all_groups = get_anagrams(MemReader::new(words.to_str()
                                                 .bytes().collect()));
    let biggest_groups = get_biggest_groups(&all_groups);

    // Groups 1, 2 and 3 are contained in "all_groups"
    assert!(all_groups.iter().any(|(_, group)| *group == group1));
    assert!(all_groups.iter().any(|(_, group)| *group == group2));
    assert!(all_groups.iter().any(|(_, group)| *group == group3));

    // Groups 1 and 2 are contained in "biggest_groups". Group 3 is not.
    assert!(biggest_groups.iter().any(|(_, group)| *group == group1));
    assert!(biggest_groups.iter().any(|(_, group)| *group == group2));
    assert!(biggest_groups.iter().all(|(_, group)| *group != group3));
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#![feature(io)]

extern crate extra;

use std::ascii::AsciiExt;
use std::env::args;
use std::io::{self, Write, Read};
use std::process::exit;

use extra::option::OptionalExt;
use extra::io::{fail, WriteExt};

static HELP: &'static str = /* @MANSTART{mtxt} */ r#"
NAME
    mtxt - a simple tool to manipulate text from standard input.

SYNOPSIS
    mtxt [-h | --help | -u | --to-uppercase-w | -l | --to-lowercase | -a | --strip-non-ascii]

DESCRIPTION
    This utility will manipulate UTF-8 encoded text from the standard input. Unicode is supported.
    The flags are composable, unless otherwise stated.

OPTIONS
    -h
    --help
        Print this manual page.

    -u
    --to-uppercase
        Convert the input to UPPERCASE. Works correctly with Unicode. Incompatible with '-l'.

    -l
    --lowercase
        Convert the input to lowercase. Works correctly with Unicode.

    -a
    --strip-non-ascii
        Strip the input for non-ASCII bytes, outputting a valid ASCII string.

EXAMPLES
    $ echo Δ | mtxt -l
    > δ
    $ echo we got deltas Δ right | mtxt -a
    > we got deltas  right
    $ echo Japanese scripts do not have case thus 山will stay unchanged | mtxt -u
    > JAPANESE SCRIPTS DO NOT HAVE CASE THUS 山WILL STAY UNCHANGED

AUTHOR
    This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be
    reported in the Github repository, 'redox-os/extrautils'.

COPYRIGHT
    Copyright (c) 2016 Ticki

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and associated documentation files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or
    substantial portions of the Software.

    Do you actually read the license? wat?
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#; /* @MANEND */

fn main() {
    let stdin = io::stdin();
    let stdin = stdin.lock();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    // These are the options.
    let mut to_uppercase = false;
    let mut to_lowercase = false;
    let mut strip_non_ascii = false;

    for arg in args().skip(1) {
        match arg.as_str() {
            "-u" | "--to-uppercase" => to_uppercase = true,
            "-l" | "--to-lowercase" => to_lowercase = true,
            "-a" | "--strip-non-ascii" => strip_non_ascii = true,
            "-h" | "--help" => {
                // The help page.
                stdout.write(HELP.as_bytes()).try(&mut stderr);
            },
            a => {
                // The argument, a, is unknown.
                stderr.write(b"error: unknown argument, ").try(&mut stderr);
                stderr.write(a.as_bytes()).try(&mut stderr);
                stderr.write(b".\n").try(&mut stderr);
                stderr.flush().try(&mut stderr);
                exit(1);
            },
        }
    }

    if to_lowercase && to_uppercase {
        // Fail, since -u and -l are incompatible.
        fail("-u and -l are incompatible. Aborting.", &mut stderr);
    }

    // My eyes bleed.
    //
    // Anyone?
    // ...
    //
    // Silence.
    //
    // If you see this, rewrite the code below. Now, you can't say no. Too late.
    // Muhahahaha.
    for i in stdin.chars() {
        let i = i.try(&mut stderr);

        // TODO handle -a more efficient

        // If -u is set, convert to uppercase
        if to_uppercase {
            for uppercase in i.to_uppercase().filter(|x| !strip_non_ascii || x.is_ascii() ) {
                stdout.write_char(uppercase).try(&mut stderr);
            }
        // If -l is set, convert to lowercase
        } else if to_lowercase {
            for lowercase in i.to_lowercase().filter(|x| !strip_non_ascii || x.is_ascii()) {
                stdout.write_char(lowercase).try(&mut stderr);
            }
        // If -a is set, strip non-ASCII.
        } else if !strip_non_ascii || strip_non_ascii && i.is_ascii() {
            stdout.write_char(i).try(&mut stderr);
        }
    }
}
<commit_msg>Allow feature(io) warning as an indication to update our libstd<commit_after>//#![deny(warnings)]
#![feature(io)]

extern crate extra;

use std::ascii::AsciiExt;
use std::env::args;
use std::io::{self, Write, Read};
use std::process::exit;

use extra::option::OptionalExt;
use extra::io::{fail, WriteExt};

static HELP: &'static str = /* @MANSTART{mtxt} */ r#"
NAME
    mtxt - a simple tool to manipulate text from standard input.

SYNOPSIS
    mtxt [-h | --help | -u | --to-uppercase-w | -l | --to-lowercase | -a | --strip-non-ascii]

DESCRIPTION
    This utility will manipulate UTF-8 encoded text from the standard input. Unicode is supported.
    The flags are composable, unless otherwise stated.

OPTIONS
    -h
    --help
        Print this manual page.

    -u
    --to-uppercase
        Convert the input to UPPERCASE. Works correctly with Unicode. Incompatible with '-l'.

    -l
    --lowercase
        Convert the input to lowercase. Works correctly with Unicode.

    -a
    --strip-non-ascii
        Strip the input for non-ASCII bytes, outputting a valid ASCII string.

EXAMPLES
    $ echo Δ | mtxt -l
    > δ
    $ echo we got deltas Δ right | mtxt -a
    > we got deltas  right
    $ echo Japanese scripts do not have case thus 山will stay unchanged | mtxt -u
    > JAPANESE SCRIPTS DO NOT HAVE CASE THUS 山WILL STAY UNCHANGED

AUTHOR
    This program was written by Ticki for Redox OS. Bugs, issues, or feature requests should be
    reported in the Github repository, 'redox-os/extrautils'.

COPYRIGHT
    Copyright (c) 2016 Ticki

    Permission is hereby granted, free of charge, to any person obtaining a copy of this software
    and associated documentation files (the "Software"), to deal in the Software without
    restriction, including without limitation the rights to use, copy, modify, merge, publish,
    distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all copies or
    substantial portions of the Software.

    Do you actually read the license? wat?
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
    BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
    DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"#; /* @MANEND */

fn main() {
    let stdin = io::stdin();
    let stdin = stdin.lock();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();

    // These are the options.
    let mut to_uppercase = false;
    let mut to_lowercase = false;
    let mut strip_non_ascii = false;

    for arg in args().skip(1) {
        match arg.as_str() {
            "-u" | "--to-uppercase" => to_uppercase = true,
            "-l" | "--to-lowercase" => to_lowercase = true,
            "-a" | "--strip-non-ascii" => strip_non_ascii = true,
            "-h" | "--help" => {
                // The help page.
                stdout.write(HELP.as_bytes()).try(&mut stderr);
            },
            a => {
                // The argument, a, is unknown.
                stderr.write(b"error: unknown argument, ").try(&mut stderr);
                stderr.write(a.as_bytes()).try(&mut stderr);
                stderr.write(b".\n").try(&mut stderr);
                stderr.flush().try(&mut stderr);
                exit(1);
            },
        }
    }

    if to_lowercase && to_uppercase {
        // Fail, since -u and -l are incompatible.
        fail("-u and -l are incompatible. Aborting.", &mut stderr);
    }

    // My eyes bleed.
    //
    // Anyone?
    // ...
    //
    // Silence.
    //
    // If you see this, rewrite the code below. Now, you can't say no. Too late.
    // Muhahahaha.
    for i in stdin.chars() {
        let i = i.try(&mut stderr);

        // TODO handle -a more efficient

        // If -u is set, convert to uppercase
        if to_uppercase {
            for uppercase in i.to_uppercase().filter(|x| !strip_non_ascii || x.is_ascii() ) {
                stdout.write_char(uppercase).try(&mut stderr);
            }
        // If -l is set, convert to lowercase
        } else if to_lowercase {
            for lowercase in i.to_lowercase().filter(|x| !strip_non_ascii || x.is_ascii()) {
                stdout.write_char(lowercase).try(&mut stderr);
            }
        // If -a is set, strip non-ASCII.
        } else if !strip_non_ascii || strip_non_ascii && i.is_ascii() {
            stdout.write_char(i).try(&mut stderr);
        }
    }
}
<|endoftext|>


<commit_before>// TODO: use Impls https://github.com/iron/iron/blob/master/src/iron.rs

extern crate collections;

use collections::dlist::DList;
use collections::Deque;

use std::cmp;
use std::mem;

use std::rc::{mod, Rc};

static CHB_MIN_SIZE:uint = 32u;

// TODO: move to utils
fn blit<T:Clone>(src: &[T], dst: &mut [T], dst_ofs: uint) {
    let len = src.len();
    let sd = dst.slice_mut(dst_ofs, dst_ofs + len);
    if len > sd.len() {
        fail!("blit: source larger than destination");
    }

    let _ = sd.clone_from_slice(src);
}

/// Chained buffer of bytes.
/// Consists of linked list of nodes.
pub struct Chain {
    head: DList<Node>,
    length: uint
}

impl Chain {
    pub fn new() -> Chain {
        return Chain{
            head: DList::new(),
            length: 0
        }
    }

    pub fn from_foreign(src: Chain) -> Chain {
        let mut ch = Chain::new();
        ch.concat(src);
        ch
    }

    pub fn len(&self) -> uint {
        self.length
    }

    // XXX: maybe DEDUP append/prepend?
    pub fn append_bytes(&mut self, data: &[u8]) {
        let size = data.len();
        // XXX: Damn, https://github.com/rust-lang/rust/issues/6393
        let should_create = match self.head.back() {
            Some(nd) => {
                (nd.room() < size) || !rc::is_unique(&nd.dh)
            }
            None => {
                true
            }
        };
        // We either not the only owner of DH or don't have enough room
        if should_create {
            let nsize = if size < CHB_MIN_SIZE { size << 1 } else { size };
            let node = Node::new(DataHolder::new(nsize));
            self.add_node_tail(node);
        }
        // infailable: added node above
        let node = self.head.back_mut().unwrap();
        // XXX: Damn, https://github.com/rust-lang/rust/issues/6268
        // XXX: we need additional var and scope only to fight borrow checker
        {
            let node_end = node.end;
            // we should be sole owner of data holder inside node here
            let dh = rc::get_mut(&mut node.dh).unwrap();
            dh.copy_data_from(data, node_end);
        }
        node.end += size;
        self.length += size;
    }

    pub fn prepend_bytes(&mut self, data: &[u8]) {
        let size = data.len();
        // XXX: Damn, https://github.com/rust-lang/rust/issues/6393
        let should_create = match self.head.front() {
            Some(nd) => {
                (size > nd.start || !rc::is_unique(&nd.dh))
            }
            None => {
                true
            }
        };
        if should_create {
            let nsize = if size < CHB_MIN_SIZE { size << 1 } else { size };
            let mut node = Node::new(DataHolder::new(nsize)); // Box<Node>
            let r = node.room();
            node.start = r;
            node.end = r;
            self.add_node_head(node);
        }
        // See comments in `append_bytes`
        let node = self.head.front_mut().unwrap();
        {
            let node_start = node.start;
            let dh = rc::get_mut(&mut node.dh).unwrap();
            dh.copy_data_from(data, node_start - size);
        }
        node.start -= size;
        self.length += size;
    }

    pub fn pullup(&mut self, size: uint) -> Option<&[u8]> {
        if size == 0 || size > self.len() {
            return None
        }
        // could not fail, because self.size() > 0 => has node
        if self.head.front().unwrap().size() >= size {
            let node = self.head.front().unwrap();
            return Some(node.data(size));
        }

        let mut newn = Node::new(DataHolder::new(size));
        // XXX: we need this scope to be able to move newn inside our list
        {
            // we just created new data holder, so we have unique ownership
            let mut msize = size;
            while msize > 0 {
                {
                    let node = self.head.front_mut().unwrap();
                    let csize = cmp::min(node.size(), size);
                    // XXX: we need this scope only to beat borrow checker
                    {
                        let node_end = newn.end;
                        let dh = rc::get_mut(&mut newn.dh).unwrap();
                        dh.copy_data_from(node.data(csize), node_end);
                    }
                    newn.end += csize;

                    if node.size() > size {
                        node.start += size;
                        self.length -= size;
                        break
                    }
                }
                // infailable
                let n = self.head.pop_front().unwrap();
                msize -= n.size();
                // XXX: free node?
            }
        }
        self.add_node_head(newn);
        // Now first node.size >= size, so we recurse
        return self.pullup(size)
    }

    pub fn concat(&mut self, src: Chain) {
        self.length += src.length;
        self.head.append(src.head);
        // No need to cleanup `src`, because it has moved and cannot be used
    }

    // XXX: chb_drop; `drop` is the sole method of built-in Drop trait,
    // so use another name
    pub fn reset(&mut self) {
        self.head = DList::new();
        self.length = 0;
    }

    // XXX: deprecated & experimental

    // TODO: maybe we do not need this method?
    // TODO: `concat` better express move semantics
    // XXX: to delete...
    pub fn concat_ptr(&mut self, src: &mut Chain) {
        self.length += src.length;
        let sh = mem::replace(&mut src.head, DList::new());
        self.head.append(sh);
        src.length = 0;
    }

    // XXX: private
    fn add_node_tail(&mut self, node: Node) {
        self.length += node.size();
        self.head.push(node);
    }

    fn add_node_head(&mut self, node: Node) {
        self.length += node.size();
        self.head.push_front(node);
    }
}

/// Node of chain buffer.
/// Owned by Chain.
struct Node {
    dh: Rc<DataHolder>, // можно заменить на RC
    start: uint,
    end: uint
}

impl Node {
    fn new(dh: Rc<DataHolder>) -> Node {
        let n = Node {
            dh: dh.clone(),
            start: 0,
            end: 0
        };
        // TODO: ref dh ? auto, when using RC
        return n;
    }

    fn size(&self) -> uint {
        self.end - self.start
    }

    fn room(&self) -> uint {
        self.dh.size - self.end
    }

    fn data(&self, size:uint) -> &[u8] {
        self.dh.data.slice(self.start, self.start + size)
    }

}

/// Refcounted data holder
/// TODO: can be shared among different chains
/// TODO: implement other storages: shmem, mmap
struct DataHolder{
    size: uint,
    data: Vec<u8>
}

impl DataHolder {
    fn new(size: uint) -> Rc<DataHolder> {
        let dh = Rc::new(DataHolder {
            size: size,
            data: Vec::from_elem(size, 0)
        });
        return dh;
    }

    fn copy_data_from(&mut self, src: &[u8], dst_offs: uint) {
        blit(src,
             self.data.as_mut_slice(), dst_offs);
    }
}

#[cfg(test)]
mod test {
    use super::Chain;
    use std::rand::{task_rng, Rng};

    #[test]
    fn test_append_bytes_changes_length() {
        let mut chain = Chain::new();
        let s = "HelloWorld";
        let ls = s.len();
        chain.append_bytes(s.as_bytes());
        assert_eq!(chain.len(), ls);
    }

    #[test]
    fn test_prepend_bytes_changes_length() {
        let mut chain = Chain::new();
        let s = "HelloWorld".as_bytes();
        let ls = s.len();
        chain.prepend_bytes(s);
        assert_eq!(chain.len(), ls);
    }

    #[test]
    fn test_from_foreign_moves_all_data() {
        let mut orig = Chain::new();
        orig.append_bytes("HelloWorld".as_bytes());
        let sz = orig.len();
        let new = Chain::from_foreign(orig);
        assert_eq!(new.len(), sz);
    }

    #[test]
    fn test_pullup_return_none_on_empty_chain() {
        let mut chain = Chain::new();
        assert!(chain.pullup(1).is_none());
    }

    #[test]
    fn test_pullup_return_what_has_been_appended() {
        let mut chain = Chain::new();
        let s = "HelloWorld".as_bytes();
        let ls = s.len();
        chain.append_bytes(s);
        let res = chain.pullup(ls);
        assert!(res.is_some());
        assert_eq!(res.unwrap(), s);
    }

    #[test]
    fn test_pullup_does_not_change_length() {
        let mut chain = Chain::new();
        let s = "HelloWorld".as_bytes();
        let ls = s.len();
        chain.append_bytes(s);
        let olds = chain.len();
        chain.pullup(ls / 2);
        assert_eq!(chain.len(), olds);
    }

    #[test]
    fn test_pullup_works_on_large_sequences() {
        let mut chain = Chain::new();
        let total = 2048u;
        let mut t = total;
        let one_seq = 128u;
        let mut buf = Vec::new();
        while t > 0 {
            let s:String = task_rng().gen_ascii_chars().take(one_seq).collect();
            let b = s.as_bytes();
            buf = buf.append(b);
            chain.append_bytes(b);
            t -= one_seq;
        }
        let ret = chain.pullup(total);
        assert!(ret.is_some());
        assert_eq!(ret.unwrap(), buf.as_slice());
    }

    #[test]
    fn test_concat_increase_dst_length() {
        let mut chain1 = Chain::new();
        let mut chain2 = Chain::new();
        chain1.append_bytes("HelloWorld".as_bytes());
        let l1 = chain1.len();
        chain2.append_bytes("HelloWorld".as_bytes());
        let l2 = chain2.len();
        chain1.concat(chain2);
        assert_eq!(chain1.len(), l1+l2);
    }

    #[test]
    fn test_concat_appends_content() {
        let mut chain1 = Chain::new();
        let mut chain2 = Chain::new();
        let b = "HelloWorld".as_bytes();
        let bl = b.len();
        chain2.append_bytes(b);
        chain1.concat(chain2);
        let res = chain1.pullup(bl);

        assert!(res.is_some());
        assert_eq!(res.unwrap(), b);
    }

    #[test]
    fn test_reset_empties_chain() {
        let mut chain = Chain::new();
        chain.append_bytes("HelloWorld".as_bytes());
        chain.reset();
        assert!(chain.pullup(1).is_none());
        assert_eq!(chain.len(), 0);
    }

    // XXX: do not need to test it for `concat`, because it is done for us
    // XXX: by type-system.
    #[test]
    fn test_concat_ptr_destroy_src() {
        let mut chain1 = Chain::new();
        let mut chain2 = Chain::new();
        chain2.append_bytes("HelloWorld".as_bytes());
        chain1.concat_ptr(&mut chain2);
        assert_eq!(chain2.len(), 0);
    }

}
<commit_msg>[minor] cleanup<commit_after>// TODO: use Impls https://github.com/iron/iron/blob/master/src/iron.rs

extern crate collections;

use collections::dlist::DList;
use collections::Deque;

use std::cmp;
use std::mem;

use std::rc::{mod, Rc};

static CHB_MIN_SIZE:uint = 32u;

// TODO: move to utils
fn blit<T:Clone>(src: &[T], dst: &mut [T], dst_ofs: uint) {
    let len = src.len();
    let sd = dst.slice_mut(dst_ofs, dst_ofs + len);
    if len > sd.len() {
        fail!("blit: source larger than destination");
    }

    let _ = sd.clone_from_slice(src);
}

/// Chained buffer of bytes.
/// Consists of linked list of nodes.
pub struct Chain {
    head: DList<Node>,
    length: uint
}

impl Chain {
    pub fn new() -> Chain {
        return Chain{
            head: DList::new(),
            length: 0
        }
    }

    pub fn from_foreign(src: Chain) -> Chain {
        let mut ch = Chain::new();
        ch.concat(src);
        ch
    }

    pub fn len(&self) -> uint {
        self.length
    }

    // XXX: maybe DEDUP append/prepend?
    pub fn append_bytes(&mut self, data: &[u8]) {
        let size = data.len();
        // XXX: Damn, https://github.com/rust-lang/rust/issues/6393
        let should_create = match self.head.back() {
            Some(nd) => {
                (nd.room() < size) || !rc::is_unique(&nd.dh)
            }
            None => {
                true
            }
        };
        // We either not the only owner of DH or don't have enough room
        if should_create {
            let nsize = if size < CHB_MIN_SIZE { size << 1 } else { size };
            let node = Node::new(DataHolder::new(nsize));
            self.add_node_tail(node);
        }
        // infailable: added node above
        let node = self.head.back_mut().unwrap();
        // XXX: Damn, https://github.com/rust-lang/rust/issues/6268
        // XXX: we need additional var and scope only to fight borrow checker
        {
            let node_end = node.end;
            // we should be sole owner of data holder inside node here
            let dh = rc::get_mut(&mut node.dh).unwrap();
            dh.copy_data_from(data, node_end);
        }
        node.end += size;
        self.length += size;
    }

    pub fn prepend_bytes(&mut self, data: &[u8]) {
        let size = data.len();
        // XXX: Damn, https://github.com/rust-lang/rust/issues/6393
        let should_create = match self.head.front() {
            Some(nd) => {
                (size > nd.start || !rc::is_unique(&nd.dh))
            }
            None => {
                true
            }
        };
        if should_create {
            let nsize = if size < CHB_MIN_SIZE { size << 1 } else { size };
            let mut node = Node::new(DataHolder::new(nsize)); // Box<Node>
            let r = node.room();
            node.start = r;
            node.end = r;
            self.add_node_head(node);
        }
        // See comments in `append_bytes`
        let node = self.head.front_mut().unwrap();
        {
            let node_start = node.start;
            let dh = rc::get_mut(&mut node.dh).unwrap();
            dh.copy_data_from(data, node_start - size);
        }
        node.start -= size;
        self.length += size;
    }

    pub fn pullup(&mut self, size: uint) -> Option<&[u8]> {
        if size == 0 || size > self.len() {
            return None
        }
        // could not fail, because self.size() > 0 => has node
        if self.head.front().unwrap().size() >= size {
            let node = self.head.front().unwrap();
            return Some(node.data(size));
        }

        let mut newn = Node::new(DataHolder::new(size));
        // XXX: we need this scope to be able to move newn inside our list
        {
            // we just created new data holder, so we have unique ownership
            let mut msize = size;
            while msize > 0 {
                {
                    let node = self.head.front_mut().unwrap();
                    let csize = cmp::min(node.size(), size);
                    // XXX: we need this scope only to beat borrow checker
                    {
                        let node_end = newn.end;
                        let dh = rc::get_mut(&mut newn.dh).unwrap();
                        dh.copy_data_from(node.data(csize), node_end);
                    }
                    newn.end += csize;

                    if node.size() > size {
                        node.start += size;
                        self.length -= size;
                        break
                    }
                }
                // infailable
                let n = self.head.pop_front().unwrap();
                msize -= n.size();
                // XXX: free node?
            }
        }
        self.add_node_head(newn);
        // Now first node.size >= size, so we recurse
        return self.pullup(size)
    }

    pub fn concat(&mut self, src: Chain) {
        self.length += src.length;
        self.head.append(src.head);
        // No need to cleanup `src`, because it has moved and cannot be used
    }

    // XXX: chb_drop; `drop` is the sole method of built-in Drop trait,
    // so use another name
    pub fn reset(&mut self) {
        self.head = DList::new();
        self.length = 0;
    }

    // XXX: deprecated & experimental

    // TODO: maybe we do not need this method?
    // TODO: `concat` better express move semantics
    // XXX: to delete...
    pub fn concat_ptr(&mut self, src: &mut Chain) {
        self.length += src.length;
        let sh = mem::replace(&mut src.head, DList::new());
        self.head.append(sh);
        src.length = 0;
    }

    // XXX: private
    fn add_node_tail(&mut self, node: Node) {
        self.length += node.size();
        self.head.push(node);
    }

    fn add_node_head(&mut self, node: Node) {
        self.length += node.size();
        self.head.push_front(node);
    }
}

/// Node of chain buffer.
/// Owned by Chain.
struct Node {
    dh: Rc<DataHolder>,
    start: uint,
    end: uint
}

impl Node {
    fn new(dh: Rc<DataHolder>) -> Node {
        let n = Node {
            dh: dh.clone(),
            start: 0,
            end: 0
        };
        return n;
    }

    fn size(&self) -> uint {
        self.end - self.start
    }

    fn room(&self) -> uint {
        self.dh.size - self.end
    }

    fn data(&self, size:uint) -> &[u8] {
        self.dh.data.slice(self.start, self.start + size)
    }

}

/// Refcounted data holder
/// TODO: can be shared among different chains
/// TODO: implement other storages: shmem, mmap
struct DataHolder{
    size: uint,
    data: Vec<u8>
}

impl DataHolder {
    fn new(size: uint) -> Rc<DataHolder> {
        let dh = Rc::new(DataHolder {
            size: size,
            data: Vec::from_elem(size, 0)
        });
        return dh;
    }

    fn copy_data_from(&mut self, src: &[u8], dst_offs: uint) {
        blit(src,
             self.data.as_mut_slice(), dst_offs);
    }
}

#[cfg(test)]
mod test {
    use super::Chain;
    use std::rand::{task_rng, Rng};

    #[test]
    fn test_append_bytes_changes_length() {
        let mut chain = Chain::new();
        let s = "HelloWorld";
        let ls = s.len();
        chain.append_bytes(s.as_bytes());
        assert_eq!(chain.len(), ls);
    }

    #[test]
    fn test_prepend_bytes_changes_length() {
        let mut chain = Chain::new();
        let s = "HelloWorld".as_bytes();
        let ls = s.len();
        chain.prepend_bytes(s);
        assert_eq!(chain.len(), ls);
    }

    #[test]
    fn test_from_foreign_moves_all_data() {
        let mut orig = Chain::new();
        orig.append_bytes("HelloWorld".as_bytes());
        let sz = orig.len();
        let new = Chain::from_foreign(orig);
        assert_eq!(new.len(), sz);
    }

    #[test]
    fn test_pullup_return_none_on_empty_chain() {
        let mut chain = Chain::new();
        assert!(chain.pullup(1).is_none());
    }

    #[test]
    fn test_pullup_return_what_has_been_appended() {
        let mut chain = Chain::new();
        let s = "HelloWorld".as_bytes();
        let ls = s.len();
        chain.append_bytes(s);
        let res = chain.pullup(ls);
        assert!(res.is_some());
        assert_eq!(res.unwrap(), s);
    }

    #[test]
    fn test_pullup_does_not_change_length() {
        let mut chain = Chain::new();
        let s = "HelloWorld".as_bytes();
        let ls = s.len();
        chain.append_bytes(s);
        let olds = chain.len();
        chain.pullup(ls / 2);
        assert_eq!(chain.len(), olds);
    }

    #[test]
    fn test_pullup_works_on_large_sequences() {
        let mut chain = Chain::new();
        let total = 2048u;
        let mut t = total;
        let one_seq = 128u;
        let mut buf = Vec::new();
        while t > 0 {
            let s:String = task_rng().gen_ascii_chars().take(one_seq).collect();
            let b = s.as_bytes();
            buf = buf.append(b);
            chain.append_bytes(b);
            t -= one_seq;
        }
        let ret = chain.pullup(total);
        assert!(ret.is_some());
        assert_eq!(ret.unwrap(), buf.as_slice());
    }

    #[test]
    fn test_concat_increase_dst_length() {
        let mut chain1 = Chain::new();
        let mut chain2 = Chain::new();
        chain1.append_bytes("HelloWorld".as_bytes());
        let l1 = chain1.len();
        chain2.append_bytes("HelloWorld".as_bytes());
        let l2 = chain2.len();
        chain1.concat(chain2);
        assert_eq!(chain1.len(), l1+l2);
    }

    #[test]
    fn test_concat_appends_content() {
        let mut chain1 = Chain::new();
        let mut chain2 = Chain::new();
        let b = "HelloWorld".as_bytes();
        let bl = b.len();
        chain2.append_bytes(b);
        chain1.concat(chain2);
        let res = chain1.pullup(bl);

        assert!(res.is_some());
        assert_eq!(res.unwrap(), b);
    }

    #[test]
    fn test_reset_empties_chain() {
        let mut chain = Chain::new();
        chain.append_bytes("HelloWorld".as_bytes());
        chain.reset();
        assert!(chain.pullup(1).is_none());
        assert_eq!(chain.len(), 0);
    }

    // XXX: do not need to test it for `concat`, because it is done for us
    // XXX: by type-system.
    #[test]
    fn test_concat_ptr_destroy_src() {
        let mut chain1 = Chain::new();
        let mut chain2 = Chain::new();
        chain2.append_bytes("HelloWorld".as_bytes());
        chain1.concat_ptr(&mut chain2);
        assert_eq!(chain2.len(), 0);
    }

}
<|endoftext|>