<commit_before>pub mod socket;
pub mod reader;
pub mod test;

use std::io::{Error, ErrorKind};
use std::net::TcpStream;
use reader::{read_byte, read_bytes, read_line, read_u32};

static SSH_IDENTIFIER_MAX_LINE_LEN: usize = 255;
static SSH_MAX_LINES_BEFORE_IDENTIFIER: usize = 5;
static SSH_MSG_KEXINIT: u8 = 20;

/// Reads the SSH server identifier from the stream. Skips at most 5 lines
/// before giving up. RFC 4253, Section 4.2.
pub fn read_identifier(stream: &TcpStream) -> std::io::Result<String> {
  let mut line = try!(read_line(stream, SSH_IDENTIFIER_MAX_LINE_LEN));
  let mut lines = 0;
  while !line.starts_with("SSH-") {
    line = try!(read_line(stream, SSH_IDENTIFIER_MAX_LINE_LEN));
    lines += 1;

    if lines == SSH_MAX_LINES_BEFORE_IDENTIFIER {
      return Err(Error::new(ErrorKind::Other,
                            "Too many lines before the server identifier."));
    }
  }

  Ok(line)
}

/// Reads an SSH name-list from the stream.
fn read_name_list(stream: &TcpStream) -> std::io::Result<Vec<String>> {
  let len = try!(read_u32(stream));
  let raw = try!(read_bytes(stream, len as usize));
  let s = try!(String::from_utf8(raw)
    .map_err(|_| Error::new(ErrorKind::Other, "Invalid UTF-8.")));

  Ok(s.split(",").map(|v| v.to_string()).collect())
}

#[derive(Debug)]
pub struct KexData {
  pub key_exchange: Vec<String>,
  pub host_keys: Vec<String>,
  pub encryption_cts: Vec<String>,
  pub encryption_stc: Vec<String>,
  pub mac_cts: Vec<String>,
  pub mac_stc: Vec<String>,
  pub compression_cts: Vec<String>,
  pub compression_stc: Vec<String>,
}

/// Reads the SSH_MSG_KEXINIT from the socket and returns the payload.
pub fn read_kex_payload(stream: &TcpStream) -> std::io::Result<KexData> {
  // RFC 4253, section 6.
  let packet_len = try!(read_u32(stream)) as usize;

  if packet_len > 35000 {
    return Err(Error::new(ErrorKind::Other, "Packet too large."));
  }

  // TODO: Do bounds checking on payload length.

  // byte         SSH_MSG_KEXINIT
  let message_type = try!(read_byte(stream));
  if message_type != SSH_MSG_KEXINIT {
    return Err(Error::new(ErrorKind::Other, "Unexpected message."));
  }

  // byte[16]     cookie (random bytes)
  let _ = try!(read_bytes(stream, 16));

  // name-list    kex_algorithms
  // name-list    server_host_key_algorithms
  // name-list    encryption_algorithms_client_to_server
  // name-list    encryption_algorithms_server_to_client
  // name-list    mac_algorithms_client_to_server
  // name-list    mac_algorithms_server_to_client
  // name-list    compression_algorithms_client_to_server
  // name-list    compression_algorithms_server_to_client
  let key_exchange = try!(read_name_list(stream));
  let host_keys = try!(read_name_list(stream));
  let encryption_cts = try!(read_name_list(stream));
  let encryption_stc = try!(read_name_list(stream));
  let mac_cts = try!(read_name_list(stream));
  let mac_stc = try!(read_name_list(stream));
  let compression_cts = try!(read_name_list(stream));
  let compression_stc = try!(read_name_list(stream));

  Ok(KexData {
    key_exchange: key_exchange,
    host_keys: host_keys,
    encryption_cts: encryption_cts,
    encryption_stc: encryption_stc,
    mac_cts: mac_cts,
    mac_stc: mac_stc,
    compression_cts: compression_cts,
    compression_stc: compression_stc,
  })
}

#[cfg(test)]
mod tests {
  use super::{read_identifier, read_name_list};
  use super::test::create_tcp_stream;

  #[test]
  fn test_read_identifier_basic() {
    let stream = create_tcp_stream("SSH-2.0-foobar\r\n".as_bytes());
    assert_eq!(read_identifier(&stream).unwrap(), "SSH-2.0-foobar");
  }

  #[test]
  fn test_read_identifier_skip_extra_lines() {
    let stream = create_tcp_stream("foo\r\nbar\r\nSSH-2.0-foobar\r\n".as_bytes());
    assert_eq!(read_identifier(&stream).unwrap(), "SSH-2.0-foobar");
  }

  #[test]
  #[should_panic]
  fn test_read_identifier_missing() {
    let stream = create_tcp_stream("SHS-2.0-foobar\r\n".as_bytes());
    read_identifier(&stream).unwrap();
  }

  #[test]
  #[should_panic]
  fn test_read_identifier_too_many_extra_lines() {
    let stream = create_tcp_stream("1\r\n2\r\n3\r\n4\r\n5\r\nSSH-2.0-foobar\r\n".as_bytes());
    read_identifier(&stream).unwrap();
  }

  #[test]
  #[should_panic]
  fn test_read_identifier_unexpected_end() {
    let stream = create_tcp_stream("1\r\n2\r\n3\r\n".as_bytes());
    read_identifier(&stream).unwrap();
  }

  #[test]
  fn test_name_list_basic() {
    // From RFC 4251, Section 5 > name-list.
    let stream = create_tcp_stream(&[0, 0, 0, 0x09, 0x7a, 0x6c, 0x69, 0x62, 0x2c, 0x6e, 0x6f, 0x6e, 0x65]);
    assert_eq!(read_name_list(&stream).unwrap(), ["zlib", "none"]);
  }
}
<commit_msg>Restore the accidentally removed read for the padding_length byte.<commit_after>pub mod socket;
pub mod reader;
pub mod test;

use std::io::{Error, ErrorKind};
use std::net::TcpStream;
use reader::{read_byte, read_bytes, read_line, read_u32};

static SSH_IDENTIFIER_MAX_LINE_LEN: usize = 255;
static SSH_MAX_LINES_BEFORE_IDENTIFIER: usize = 5;
static SSH_MSG_KEXINIT: u8 = 20;

/// Reads the SSH server identifier from the stream. Skips at most 5 lines
/// before giving up. RFC 4253, Section 4.2.
pub fn read_identifier(stream: &TcpStream) -> std::io::Result<String> {
  let mut line = try!(read_line(stream, SSH_IDENTIFIER_MAX_LINE_LEN));
  let mut lines = 0;
  while !line.starts_with("SSH-") {
    line = try!(read_line(stream, SSH_IDENTIFIER_MAX_LINE_LEN));
    lines += 1;

    if lines == SSH_MAX_LINES_BEFORE_IDENTIFIER {
      return Err(Error::new(ErrorKind::Other,
                            "Too many lines before the server identifier."));
    }
  }

  Ok(line)
}

/// Reads an SSH name-list from the stream.
fn read_name_list(stream: &TcpStream) -> std::io::Result<Vec<String>> {
  let len = try!(read_u32(stream));
  let raw = try!(read_bytes(stream, len as usize));
  let s = try!(String::from_utf8(raw)
    .map_err(|_| Error::new(ErrorKind::Other, "Invalid UTF-8.")));

  Ok(s.split(",").map(|v| v.to_string()).collect())
}

#[derive(Debug)]
pub struct KexData {
  pub key_exchange: Vec<String>,
  pub host_keys: Vec<String>,
  pub encryption_cts: Vec<String>,
  pub encryption_stc: Vec<String>,
  pub mac_cts: Vec<String>,
  pub mac_stc: Vec<String>,
  pub compression_cts: Vec<String>,
  pub compression_stc: Vec<String>,
}

/// Reads the SSH_MSG_KEXINIT from the socket and returns the payload.
pub fn read_kex_payload(stream: &TcpStream) -> std::io::Result<KexData> {
  // RFC 4253, section 6.
  let packet_len = try!(read_u32(stream)) as usize;
  if packet_len > 35000 {
    return Err(Error::new(ErrorKind::Other, "Packet too large."));
  }

  // byte      padding_length
  let _ = try!(read_byte(stream));

  // TODO: Do bounds checking on payload length.

  // byte         SSH_MSG_KEXINIT
  let message_type = try!(read_byte(stream));
  if message_type != SSH_MSG_KEXINIT {
    return Err(Error::new(ErrorKind::Other, "Unexpected message."));
  }

  // byte[16]     cookie (random bytes)
  let _ = try!(read_bytes(stream, 16));

  // name-list    kex_algorithms
  // name-list    server_host_key_algorithms
  // name-list    encryption_algorithms_client_to_server
  // name-list    encryption_algorithms_server_to_client
  // name-list    mac_algorithms_client_to_server
  // name-list    mac_algorithms_server_to_client
  // name-list    compression_algorithms_client_to_server
  // name-list    compression_algorithms_server_to_client
  let key_exchange = try!(read_name_list(stream));
  let host_keys = try!(read_name_list(stream));
  let encryption_cts = try!(read_name_list(stream));
  let encryption_stc = try!(read_name_list(stream));
  let mac_cts = try!(read_name_list(stream));
  let mac_stc = try!(read_name_list(stream));
  let compression_cts = try!(read_name_list(stream));
  let compression_stc = try!(read_name_list(stream));

  Ok(KexData {
    key_exchange: key_exchange,
    host_keys: host_keys,
    encryption_cts: encryption_cts,
    encryption_stc: encryption_stc,
    mac_cts: mac_cts,
    mac_stc: mac_stc,
    compression_cts: compression_cts,
    compression_stc: compression_stc,
  })
}

#[cfg(test)]
mod tests {
  use super::{read_identifier, read_name_list};
  use super::test::create_tcp_stream;

  #[test]
  fn test_read_identifier_basic() {
    let stream = create_tcp_stream("SSH-2.0-foobar\r\n".as_bytes());
    assert_eq!(read_identifier(&stream).unwrap(), "SSH-2.0-foobar");
  }

  #[test]
  fn test_read_identifier_skip_extra_lines() {
    let stream = create_tcp_stream("foo\r\nbar\r\nSSH-2.0-foobar\r\n".as_bytes());
    assert_eq!(read_identifier(&stream).unwrap(), "SSH-2.0-foobar");
  }

  #[test]
  #[should_panic]
  fn test_read_identifier_missing() {
    let stream = create_tcp_stream("SHS-2.0-foobar\r\n".as_bytes());
    read_identifier(&stream).unwrap();
  }

  #[test]
  #[should_panic]
  fn test_read_identifier_too_many_extra_lines() {
    let stream = create_tcp_stream("1\r\n2\r\n3\r\n4\r\n5\r\nSSH-2.0-foobar\r\n".as_bytes());
    read_identifier(&stream).unwrap();
  }

  #[test]
  #[should_panic]
  fn test_read_identifier_unexpected_end() {
    let stream = create_tcp_stream("1\r\n2\r\n3\r\n".as_bytes());
    read_identifier(&stream).unwrap();
  }

  #[test]
  fn test_name_list_basic() {
    // From RFC 4251, Section 5 > name-list.
    let stream = create_tcp_stream(&[0, 0, 0, 0x09, 0x7a, 0x6c, 0x69, 0x62, 0x2c, 0x6e, 0x6f, 0x6e, 0x65]);
    assert_eq!(read_name_list(&stream).unwrap(), ["zlib", "none"]);
  }
}
<|endoftext|>


<commit_before>//! This library provides a convenient derive macro for the standard library's
//! [`std::error::Error`] trait.
//!
//! [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html
//!
//!

//!
//! # Example
//!
//! ```rust
//! # use std::io;
//! use thiserror::Error;
//!
//! #[derive(Error, Debug)]
//! pub enum DataStoreError {
//!     #[error("data store disconnected")]
//!     Disconnect(#[from] io::Error),
//!     #[error("the data for key `{0}` is not available")]
//!     Redaction(String),
//!     #[error("invalid header (expected {expected:?}, found {found:?})")]
//!     InvalidHeader {
//!         expected: String,
//!         found: String,
//!     },
//!     #[error("unknown data store error")]
//!     Unknown,
//! }
//! ```
//!
//!

//!
//! # Details
//!
//! - Thiserror deliberately does not appear in your public API. You get the
//!   same thing as if you had written an implementation of `std::error::Error`
//!   by hand, and switching from handwritten impls to thiserror or vice versa
//!   is not a breaking change.
//!
//! - Errors may be enums, structs with named fields, tuple structs, or unit
//!   structs.
//!
//! - A `Display` impl is generated for your error if you provide
//!   `#[error("...")]` messages on the struct or each variant of your enum, as
//!   shown above in the example.
//!
//!   The messages support a shorthand for interpolating fields from the error.
//!
//!     - `#[error("{var}")]` ⟶ `write!("{}", self.var)`
//!     - `#[error("{0}")]` ⟶ `write!("{}", self.0)`
//!     - `#[error("{var:?}")]` ⟶ `write!("{:?}", self.var)`
//!     - `#[error("{0:?}")]` ⟶ `write!("{:?}", self.0)`
//!
//!   These shorthands can be used together with any additional format args,
//!   which may be arbitrary expressions. For example:
//!
//!   ```rust
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum Error {
//!       #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::max_value())]
//!       InvalidLookahead(u32),
//!   }
//!   ```
//!
//!   If one of the additional expression arguments needs to refer to a field of
//!   the struct or enum, then refer to named fields as `.var` and tuple fields
//!   as `.0`.
//!
//!   ```rust
//!   # use thiserror::Error;
//!   #
//!   # fn first_char(s: &String) -> char {
//!   #     s.chars().next().unwrap()
//!   # }
//!   #
//!   # #[derive(Debug)]
//!   # struct Limits {
//!   #     lo: usize,
//!   #     hi: usize,
//!   # }
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum Error {
//!       #[error("first letter must be lowercase but was {:?}", first_char(.0))]
//!       WrongCase(String),
//!       #[error("invalid index {idx}, expected at least {} and at most {}", .limits.lo, .limits.hi)]
//!       OutOfBounds { idx: usize, limits: Limits },
//!   }
//!   ```
//!
//! - A `From` impl is generated for each variant containing a `#[from]`
//!   attribute.
//!
//!   Note that the variant must not contain any other fields beyond the source
//!   error and possibly a backtrace. A backtrace is captured from within the
//!   `From` impl if there is a field for it.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       Io {
//!           #[from]
//!           source: io::Error,
//!           backtrace: Backtrace,
//!       },
//!   }
//!   # };
//!   ```
//!
//! - The Error trait's `source()` method is implemented to return whichever
//!   field has a `#[source]` attribute or is named `source`, if any. This is
//!   for identifying the underlying lower level error that caused your error.
//!
//!   The `#[from]` attribute always implies that the same field is `#[source]`,
//!   so you don't ever need to specify both attributes.
//!
//!   Any error type that implements `std::error::Error` or dereferences to `dyn
//!   std::error::Error` will work as a source.
//!
//!   ```rust
//!   # use std::fmt::{self, Display};
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub struct MyError {
//!       msg: String,
//!       #[source]  // optional if field name is `source`
//!       source: anyhow::Error,
//!   }
//!   #
//!   # impl Display for MyError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   ```
//!
//! - The Error trait's `backtrace()` method is implemented to return whichever
//!   field has a type named `Backtrace`, if any.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   use std::backtrace::Backtrace;
//!
//!   #[derive(Error, Debug)]
//!   pub struct MyError {
//!       msg: String,
//!       backtrace: Backtrace,  // automatically detected
//!   }
//!   # };
//!   ```
//!
//! - Errors may use `error(transparent)` to forward the source and Display
//!   methods straight through to an underlying error without adding an
//!   additional message. This would be appropriate for enums that need an
//!   "anything else" variant.
//!
//!   ```
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       ...
//!
//!       #[error(transparent)]
//!       Other(#[from] anyhow::Error),  // source and Display delegate to anyhow::Error
//!   }
//!   ```
//!
//! - See also the [`anyhow`] library for a convenient single error type to use
//!   in application code.
//!
//!   [`anyhow`]: https://github.com/dtolnay/anyhow

mod aserror;
mod display;

pub use thiserror_impl::*;

// Not public API.
#[doc(hidden)]
pub mod private {
    pub use crate::aserror::AsDynError;
    pub use crate::display::{DisplayAsDisplay, PathAsDisplay};
}
<commit_msg>Make error(transparent) example doc test pass<commit_after>//! This library provides a convenient derive macro for the standard library's
//! [`std::error::Error`] trait.
//!
//! [`std::error::Error`]: https://doc.rust-lang.org/std/error/trait.Error.html
//!
//!

//!
//! # Example
//!
//! ```rust
//! # use std::io;
//! use thiserror::Error;
//!
//! #[derive(Error, Debug)]
//! pub enum DataStoreError {
//!     #[error("data store disconnected")]
//!     Disconnect(#[from] io::Error),
//!     #[error("the data for key `{0}` is not available")]
//!     Redaction(String),
//!     #[error("invalid header (expected {expected:?}, found {found:?})")]
//!     InvalidHeader {
//!         expected: String,
//!         found: String,
//!     },
//!     #[error("unknown data store error")]
//!     Unknown,
//! }
//! ```
//!
//!

//!
//! # Details
//!
//! - Thiserror deliberately does not appear in your public API. You get the
//!   same thing as if you had written an implementation of `std::error::Error`
//!   by hand, and switching from handwritten impls to thiserror or vice versa
//!   is not a breaking change.
//!
//! - Errors may be enums, structs with named fields, tuple structs, or unit
//!   structs.
//!
//! - A `Display` impl is generated for your error if you provide
//!   `#[error("...")]` messages on the struct or each variant of your enum, as
//!   shown above in the example.
//!
//!   The messages support a shorthand for interpolating fields from the error.
//!
//!     - `#[error("{var}")]` ⟶ `write!("{}", self.var)`
//!     - `#[error("{0}")]` ⟶ `write!("{}", self.0)`
//!     - `#[error("{var:?}")]` ⟶ `write!("{:?}", self.var)`
//!     - `#[error("{0:?}")]` ⟶ `write!("{:?}", self.0)`
//!
//!   These shorthands can be used together with any additional format args,
//!   which may be arbitrary expressions. For example:
//!
//!   ```rust
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum Error {
//!       #[error("invalid rdo_lookahead_frames {0} (expected < {})", i32::max_value())]
//!       InvalidLookahead(u32),
//!   }
//!   ```
//!
//!   If one of the additional expression arguments needs to refer to a field of
//!   the struct or enum, then refer to named fields as `.var` and tuple fields
//!   as `.0`.
//!
//!   ```rust
//!   # use thiserror::Error;
//!   #
//!   # fn first_char(s: &String) -> char {
//!   #     s.chars().next().unwrap()
//!   # }
//!   #
//!   # #[derive(Debug)]
//!   # struct Limits {
//!   #     lo: usize,
//!   #     hi: usize,
//!   # }
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum Error {
//!       #[error("first letter must be lowercase but was {:?}", first_char(.0))]
//!       WrongCase(String),
//!       #[error("invalid index {idx}, expected at least {} and at most {}", .limits.lo, .limits.hi)]
//!       OutOfBounds { idx: usize, limits: Limits },
//!   }
//!   ```
//!
//! - A `From` impl is generated for each variant containing a `#[from]`
//!   attribute.
//!
//!   Note that the variant must not contain any other fields beyond the source
//!   error and possibly a backtrace. A backtrace is captured from within the
//!   `From` impl if there is a field for it.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       Io {
//!           #[from]
//!           source: io::Error,
//!           backtrace: Backtrace,
//!       },
//!   }
//!   # };
//!   ```
//!
//! - The Error trait's `source()` method is implemented to return whichever
//!   field has a `#[source]` attribute or is named `source`, if any. This is
//!   for identifying the underlying lower level error that caused your error.
//!
//!   The `#[from]` attribute always implies that the same field is `#[source]`,
//!   so you don't ever need to specify both attributes.
//!
//!   Any error type that implements `std::error::Error` or dereferences to `dyn
//!   std::error::Error` will work as a source.
//!
//!   ```rust
//!   # use std::fmt::{self, Display};
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub struct MyError {
//!       msg: String,
//!       #[source]  // optional if field name is `source`
//!       source: anyhow::Error,
//!   }
//!   #
//!   # impl Display for MyError {
//!   #     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
//!   #         unimplemented!()
//!   #     }
//!   # }
//!   ```
//!
//! - The Error trait's `backtrace()` method is implemented to return whichever
//!   field has a type named `Backtrace`, if any.
//!
//!   ```rust
//!   # const IGNORE: &str = stringify! {
//!   use std::backtrace::Backtrace;
//!
//!   #[derive(Error, Debug)]
//!   pub struct MyError {
//!       msg: String,
//!       backtrace: Backtrace,  // automatically detected
//!   }
//!   # };
//!   ```
//!
//! - Errors may use `error(transparent)` to forward the source and Display
//!   methods straight through to an underlying error without adding an
//!   additional message. This would be appropriate for enums that need an
//!   "anything else" variant.
//!
//!   ```
//!   # use thiserror::Error;
//!   #
//!   #[derive(Error, Debug)]
//!   pub enum MyError {
//!       # /*
//!       ...
//!       # */
//!
//!       #[error(transparent)]
//!       Other(#[from] anyhow::Error),  // source and Display delegate to anyhow::Error
//!   }
//!   ```
//!
//! - See also the [`anyhow`] library for a convenient single error type to use
//!   in application code.
//!
//!   [`anyhow`]: https://github.com/dtolnay/anyhow

mod aserror;
mod display;

pub use thiserror_impl::*;

// Not public API.
#[doc(hidden)]
pub mod private {
    pub use crate::aserror::AsDynError;
    pub use crate::display::{DisplayAsDisplay, PathAsDisplay};
}
<|endoftext|>


<commit_before>#![feature(plugin,collections,core)]
#![plugin(regex_macros)]
extern crate rustc_serialize;
extern crate regex;
extern crate hyper;
extern crate chrono;
extern crate core;

use std::io::Read;
use hyper::Client;
use regex::Regex;
use chrono::offset::utc::UTC;
use chrono::Timelike;

#[cfg(test)]
mod test;

/// Interact with winds aloft data from NOAA

const URL: &'static str = "http://aviationweather.gov/products/nws/all";
static PATTERN: Regex = regex!(r"(?x)
    (?P<station>\w+)\s          # Airport code
    (?P<three_K>.{4})\s         # Winds aloft at 3,000'
    (?P<six_K>.{7})\s           # Winds aloft at 6,000'
    (?P<nine_K>.{7})\s          # Winds aloft at 9,000'
    (?P<twelve_K>.{7})\s        # Winds aloft at 12,000'
    (?P<eighteen_K>.{7})\s      # Winds aloft at 18,000'
    (?P<twenty_four_K>.{7})\s   # Winds aloft at 24,000'
    (?P<thirty_K>.{6})\s        # Winds aloft at 30,000'
    (?P<thirty_four_K>.{6})\s   # Winds aloft at 34,000'
    (?P<thirty_nine_K>.{6})\s   # Winds aloft at 39,000'
");
static WIND_PATTERN: Regex = regex!(r"(?x)
    \w+
");
static TIME_PATTERN: Regex = regex!(r"(?x)
    DATA\sBASED\sON\s(?P<date>\d{2})(?P<time>\d{4})Z
");

/// The wind data from one weather station at one altitude
#[derive(Debug,RustcEncodable,RustcDecodable)]
pub struct Wind {
    direction: u32,
    speed: u32,
    altitude: u32,
}

/// Weather data from one weather station at all altitudes
#[derive(Debug,RustcEncodable,RustcDecodable)]
pub struct StationForecast {
    station: String,
    winds: Vec<Wind>,
}

/// All information associated with winds aloft forecast
#[derive(Debug,RustcEncodable,RustcDecodable)]
pub struct WindsAloftForecast {
    /// The zulu time that this forecast was received as an unsigned 32-bit number. For example, if
    /// the report was downloaded at 2:45 PM (UTC + 1), this field will be 1345u32.
    time_retrieved: u32,

    /// The zulu time that this report was generated.
    forecast_time: u32,

    /// The list of `StationForecast` objects that are held in this report.
    forecasts: Vec<StationForecast>,
}

impl WindsAloftForecast {
    pub fn new() -> WindsAloftForecast {
        let mut forecast = WindsAloftForecast {
            time_retrieved: 0u32,
            forecast_time: 0u32,
            forecasts: vec![],
        };
        forecast.refresh();

        forecast
    }

    /// Re-downloads the forecast from NOAA. Returns None if there is a problem with the download,
    /// or `Some(())` if the operation completes successfully.
    pub fn refresh(&mut self) -> Option<()> {
        let mut client = Client::new();

        let mut res = match client.get(URL).send() {
            Ok(x) => x,
            Err(_) => return None,
        };

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

        self.forecasts = winds_from_body(&body);
        self.forecast_time = WindsAloftForecast::parse_time_from_body(&body);

        let now = UTC::now();
        let hour = now.hour();
        let minute = now.minute();

        self.time_retrieved = hour * 100 + minute;

        Some(())
    }

    /// Returns true if the data stored in this forecast is out of date, false otherwise. The
    /// winds aloft forecast is published at 00Z, 06Z, 12Z and 18Z
    pub fn needs_refresh(&self) -> bool {
        let now = UTC::now();
        let hour = now.hour();
        let minute = now.minute();

        self.needs_refresh_time_given(hour * 100 + minute)
    }

    fn needs_refresh_time_given(&self, time: u32) -> bool {
        let hour = time / 100u32;
        let forecast_hour = self.forecast_time / 100u32;

        if hour > forecast_hour + 6 {
            true
        } else if hour < forecast_hour {
            true
        } else {
            false
        }
    }

    /// Get the forecast for a specific station out of this complete forecast.
    pub fn get_station_forecast(&self, station: &str) -> Option<&StationForecast> {
        let upper_station = station.to_uppercase();
        for wind in self.forecasts.iter() {
            if wind.station == upper_station {
                return Some(wind);
            }
        }
        None
    }

    fn parse_time_from_body(body: &str) -> u32 {
        let mut time = 0u32;
        for group in TIME_PATTERN.captures_iter(body) {
            time = match group.name("time") {
                Some(x) => x.parse().unwrap(),
                None => continue,
            }
        }

        time
    }
}

impl Wind {
    pub fn new(direction: u32, speed: u32, altitude: u32) -> Wind {
        Wind {
            direction: direction,
            speed: speed,
            altitude: altitude,
        }
    }
}

impl StationForecast {
    pub fn new(station: &str, winds: Vec<Wind>) -> StationForecast {
        StationForecast { station: station.to_string(), winds: winds }
    }

    /// Search through the wind data from this station, return the wind data from the given
    /// altitude if it exists, otherwise return `None`.
    pub fn wind_at_altitude(&self, altitude: u32) -> Option<&Wind> {
        for wind in self.winds.iter() {
            if wind.altitude == altitude {
                return Some(wind);
            }
        }
        None
    }
}

fn winds_from_body(body: &str) -> Vec<StationForecast> {
    let mut wind_aloft: Vec<StationForecast> = vec![];

    for group in PATTERN.captures_iter(body) {
        let station = match group.name("station") {
            Some(x) => x,
            None => continue,
        };

        let mut winds: Vec<Wind> = vec![];

        match group.name("three_K") {
            Some(i) => {
                match parse_wind(i, 3000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("six_K") {
            Some(i) => {
                match parse_wind(i, 6000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("nine_K") {
            Some(i) => {
                match parse_wind(i, 9000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("twelve_K") {
            Some(i) => {
                match parse_wind(i, 12000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("eighteen_K") {
            Some(i) => {
                match parse_wind(i, 18000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("twenty_four_K") {
            Some(i) => {
                match parse_wind(i, 24000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("thirty_K") {
            Some(i) => {
                match parse_wind(i, 30000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("thirty_four_K") {
            Some(i) => {
                match parse_wind(i, 34000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("thirty_nine_K") {
            Some(i) => {
                match parse_wind(i, 39000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        wind_aloft.push(StationForecast::new(station, winds));
    }

    wind_aloft
}

fn parse_wind(wind: &str, altitude: u32) -> Option<Wind> {
    if WIND_PATTERN.is_match(wind) {
        let dir_str = wind.slice_chars(0, 2);
        let spd_str = wind.slice_chars(2, 4);

        let direction = match dir_str.parse::<u32>() {
            Ok(x) => x * 10,
            Err(_) => return None,
        };

        let speed = match spd_str.parse::<u32>() {
            Ok(x) => x,
            Err(_) => return None,
        };

        Some(Wind::new(direction, speed, altitude))
    } else {
        None
    }
}
<commit_msg>make forecast field public<commit_after>#![feature(plugin,collections,core)]
#![plugin(regex_macros)]
extern crate rustc_serialize;
extern crate regex;
extern crate hyper;
extern crate chrono;
extern crate core;

use std::io::Read;
use hyper::Client;
use regex::Regex;
use chrono::offset::utc::UTC;
use chrono::Timelike;

#[cfg(test)]
mod test;

/// Interact with winds aloft data from NOAA

const URL: &'static str = "http://aviationweather.gov/products/nws/all";
static PATTERN: Regex = regex!(r"(?x)
    (?P<station>\w+)\s          # Airport code
    (?P<three_K>.{4})\s         # Winds aloft at 3,000'
    (?P<six_K>.{7})\s           # Winds aloft at 6,000'
    (?P<nine_K>.{7})\s          # Winds aloft at 9,000'
    (?P<twelve_K>.{7})\s        # Winds aloft at 12,000'
    (?P<eighteen_K>.{7})\s      # Winds aloft at 18,000'
    (?P<twenty_four_K>.{7})\s   # Winds aloft at 24,000'
    (?P<thirty_K>.{6})\s        # Winds aloft at 30,000'
    (?P<thirty_four_K>.{6})\s   # Winds aloft at 34,000'
    (?P<thirty_nine_K>.{6})\s   # Winds aloft at 39,000'
");
static WIND_PATTERN: Regex = regex!(r"(?x)
    \w+
");
static TIME_PATTERN: Regex = regex!(r"(?x)
    DATA\sBASED\sON\s(?P<date>\d{2})(?P<time>\d{4})Z
");

/// The wind data from one weather station at one altitude
#[derive(Debug,RustcEncodable,RustcDecodable)]
pub struct Wind {
    direction: u32,
    speed: u32,
    altitude: u32,
}

/// Weather data from one weather station at all altitudes
#[derive(Debug,RustcEncodable,RustcDecodable)]
pub struct StationForecast {
    station: String,
    winds: Vec<Wind>,
}

/// All information associated with winds aloft forecast
#[derive(Debug,RustcEncodable,RustcDecodable)]
pub struct WindsAloftForecast {
    /// The zulu time that this forecast was received as an unsigned 32-bit number. For example, if
    /// the report was downloaded at 2:45 PM (UTC + 1), this field will be 1345u32.
    time_retrieved: u32,

    /// The zulu time that this report was generated.
    forecast_time: u32,

    /// The list of `StationForecast` objects that are held in this report.
    pub forecasts: Vec<StationForecast>,
}

impl WindsAloftForecast {
    pub fn new() -> WindsAloftForecast {
        let mut forecast = WindsAloftForecast {
            time_retrieved: 0u32,
            forecast_time: 0u32,
            forecasts: vec![],
        };
        forecast.refresh();

        forecast
    }

    /// Re-downloads the forecast from NOAA. Returns None if there is a problem with the download,
    /// or `Some(())` if the operation completes successfully.
    pub fn refresh(&mut self) -> Option<()> {
        let mut client = Client::new();

        let mut res = match client.get(URL).send() {
            Ok(x) => x,
            Err(_) => return None,
        };

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

        self.forecasts = winds_from_body(&body);
        self.forecast_time = WindsAloftForecast::parse_time_from_body(&body);

        let now = UTC::now();
        let hour = now.hour();
        let minute = now.minute();

        self.time_retrieved = hour * 100 + minute;

        Some(())
    }

    /// Returns true if the data stored in this forecast is out of date, false otherwise. The
    /// winds aloft forecast is published at 00Z, 06Z, 12Z and 18Z
    pub fn needs_refresh(&self) -> bool {
        let now = UTC::now();
        let hour = now.hour();
        let minute = now.minute();

        self.needs_refresh_time_given(hour * 100 + minute)
    }

    fn needs_refresh_time_given(&self, time: u32) -> bool {
        let hour = time / 100u32;
        let forecast_hour = self.forecast_time / 100u32;

        if hour > forecast_hour + 6 {
            true
        } else if hour < forecast_hour {
            true
        } else {
            false
        }
    }

    /// Get the forecast for a specific station out of this complete forecast.
    pub fn get_station_forecast(&self, station: &str) -> Option<&StationForecast> {
        let upper_station = station.to_uppercase();
        for wind in self.forecasts.iter() {
            if wind.station == upper_station {
                return Some(wind);
            }
        }
        None
    }

    fn parse_time_from_body(body: &str) -> u32 {
        let mut time = 0u32;
        for group in TIME_PATTERN.captures_iter(body) {
            time = match group.name("time") {
                Some(x) => x.parse().unwrap(),
                None => continue,
            }
        }

        time
    }
}

impl Wind {
    pub fn new(direction: u32, speed: u32, altitude: u32) -> Wind {
        Wind {
            direction: direction,
            speed: speed,
            altitude: altitude,
        }
    }
}

impl StationForecast {
    pub fn new(station: &str, winds: Vec<Wind>) -> StationForecast {
        StationForecast { station: station.to_string(), winds: winds }
    }

    /// Search through the wind data from this station, return the wind data from the given
    /// altitude if it exists, otherwise return `None`.
    pub fn wind_at_altitude(&self, altitude: u32) -> Option<&Wind> {
        for wind in self.winds.iter() {
            if wind.altitude == altitude {
                return Some(wind);
            }
        }
        None
    }
}

fn winds_from_body(body: &str) -> Vec<StationForecast> {
    let mut wind_aloft: Vec<StationForecast> = vec![];

    for group in PATTERN.captures_iter(body) {
        let station = match group.name("station") {
            Some(x) => x,
            None => continue,
        };

        let mut winds: Vec<Wind> = vec![];

        match group.name("three_K") {
            Some(i) => {
                match parse_wind(i, 3000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("six_K") {
            Some(i) => {
                match parse_wind(i, 6000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("nine_K") {
            Some(i) => {
                match parse_wind(i, 9000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("twelve_K") {
            Some(i) => {
                match parse_wind(i, 12000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("eighteen_K") {
            Some(i) => {
                match parse_wind(i, 18000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("twenty_four_K") {
            Some(i) => {
                match parse_wind(i, 24000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("thirty_K") {
            Some(i) => {
                match parse_wind(i, 30000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("thirty_four_K") {
            Some(i) => {
                match parse_wind(i, 34000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        match group.name("thirty_nine_K") {
            Some(i) => {
                match parse_wind(i, 39000u32) {
                    Some(x) => winds.push(x),
                    None => { }
                }
            }
            None => { }
        }

        wind_aloft.push(StationForecast::new(station, winds));
    }

    wind_aloft
}

fn parse_wind(wind: &str, altitude: u32) -> Option<Wind> {
    if WIND_PATTERN.is_match(wind) {
        let dir_str = wind.slice_chars(0, 2);
        let spd_str = wind.slice_chars(2, 4);

        let direction = match dir_str.parse::<u32>() {
            Ok(x) => x * 10,
            Err(_) => return None,
        };

        let speed = match spd_str.parse::<u32>() {
            Ok(x) => x,
            Err(_) => return None,
        };

        Some(Wind::new(direction, speed, altitude))
    } else {
        None
    }
}
<|endoftext|>


<commit_before>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }
}
<commit_msg>Make `to` public<commit_after>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }
}
<|endoftext|>


<commit_before>mod alias_dist;

use alias_dist::AliasDistribution;
use std::collections::HashMap;

#[derive(Debug)]
pub struct MarkovNode<T> {
    pub value: T,
    transitions: Vec<T>,
    dist: AliasDistribution,
}

impl<T> MarkovNode<T> {
    pub fn new(value: T, values: Vec<T>, weights: Vec<f64>) -> MarkovNode<T> {
        MarkovNode {
            value: value,
            transitions: values,
            dist: AliasDistribution::new(weights),
        }
    }

    pub fn next(&self) -> &T {
        &self.transitions[self.dist.choice().unwrap()]
    }

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

#[derive(Debug)]
pub struct PassphraseMarkovChain {
    nodes: HashMap<String, MarkovNode<String>>,
    starting_ngrams: Vec<String>,
    starting_dist: AliasDistribution,
}

impl PassphraseMarkovChain {
    pub fn new<U: Iterator<Item=String> + Clone>(ngrams: U)
            -> Result<PassphraseMarkovChain, &'static str> {

        let mut transition_map = HashMap::new();
        let mut starting_counts = HashMap::new();
        let mut ngrams_copy = ngrams.clone().cycle();
        ngrams_copy.next();
        for (a, b) in ngrams.zip(ngrams_copy).into_iter() {
            if b.starts_with(" ") {
                let count = starting_counts.entry(b.clone()).or_insert(0);
                *count += 1
            }
            let transitions = transition_map.entry(a).or_insert(HashMap::new());
            let count = transitions.entry(b).or_insert(0);
            *count += 1;
        };

        let mut nodes = HashMap::new();
        let mut total_entropy: f64 = 0.0;
        for (ngram, transition_counts) in transition_map.into_iter() {
            let mut values = Vec::with_capacity(transition_counts.len());
            let mut weights = Vec::with_capacity(transition_counts.len());
            for (value, weight) in transition_counts.into_iter() {
                values.push(value.clone());
                weights.push(weight as f64);
            }

            let node = MarkovNode::new(ngram.clone(), values, weights);
            total_entropy += node.entropy();
            nodes.insert(ngram, node);
        };

        let mut starting_ngrams = Vec::with_capacity(starting_counts.len());
        let mut weights = Vec::with_capacity(starting_counts.len());
        for (value, weight) in starting_counts.into_iter() {
            starting_ngrams.push(value);
            weights.push(weight as f64);
        }
        let starting_dist = AliasDistribution::new(weights);

        if total_entropy == 0.0 {
            return Err("No entropy found in input.");
        } else if starting_dist.entropy == 0.0 {
            return Err("No start of word entropy found in input.");
        };

        Ok(PassphraseMarkovChain {
            nodes: nodes,
            starting_ngrams: starting_ngrams,
            starting_dist: starting_dist,
        })
    }

    pub fn get_node(&self) -> &MarkovNode<String> {
        self.nodes.get(&self.starting_ngrams[self.starting_dist.choice().unwrap()]).unwrap()
    }

    pub fn passphrase(&self, min_entropy: f64) -> (String, f64) {
        let mut node = self.get_node();
        let mut entropy = self.starting_dist.entropy;
        let mut nodes = Vec::new();
        loop {
            nodes.push(node);
            entropy += node.entropy();
            if entropy >= min_entropy && node.value.ends_with(" ") { break };
            let ngram = node.next();
            node = self.nodes.get(ngram).unwrap();
        }
        let tail = nodes.last().unwrap().value.chars().skip(1);
        let chars = nodes.iter().map(|n| n.value.chars().next().unwrap()).chain(tail);
        let passphrase = chars.collect::<String>().trim().to_string();

        (passphrase, entropy)
    }
}
<commit_msg>Add comments and annotations for clarity.<commit_after>mod alias_dist;

use alias_dist::AliasDistribution;
use std::collections::HashMap;

#[derive(Debug)]
pub struct MarkovNode<T> {
    pub value: T,
    transitions: Vec<T>,
    dist: AliasDistribution,
}

impl<T> MarkovNode<T> {
    pub fn new(value: T, values: Vec<T>, weights: Vec<f64>) -> MarkovNode<T> {
        MarkovNode {
            value: value,
            transitions: values,
            dist: AliasDistribution::new(weights),
        }
    }

    pub fn next(&self) -> &T {
        &self.transitions[self.dist.choice().unwrap()]
    }

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

#[derive(Debug)]
pub struct PassphraseMarkovChain {
    nodes: HashMap<String, MarkovNode<String>>,
    starting_ngrams: Vec<String>,
    starting_dist: AliasDistribution,
}

impl PassphraseMarkovChain {
    pub fn new<U: Iterator<Item=String> + Clone>(ngrams: U)
            -> Result<PassphraseMarkovChain, &'static str> {

        // Count transitions and viable starting ngrams.
        // To get natural sounding words, only start with ngrams at the start of words.
        let mut transition_counters: HashMap<String, HashMap<String, usize>> = HashMap::new();
        let mut starting_ngram_counts: HashMap<String, usize> = HashMap::new();
        let mut ngrams_copy = ngrams.clone().cycle();
        ngrams_copy.next();
        for (a, b) in ngrams.zip(ngrams_copy).into_iter() {
            if b.starts_with(" ") {
                let count = starting_ngram_counts.entry(b.clone()).or_insert(0);
                *count += 1
            }
            let transitions = transition_counters.entry(a).or_insert(HashMap::new());
            let count = transitions.entry(b).or_insert(0);
            *count += 1;
        };

        // Build all the MarkovNodes from the tranition counts.
        let mut nodes: HashMap<String, MarkovNode<String>> = HashMap::new();
        let mut total_entropy: f64 = 0.0;
        for (ngram, transition_counts) in transition_counters.into_iter() {
            let mut values = Vec::with_capacity(transition_counts.len());
            let mut weights = Vec::with_capacity(transition_counts.len());
            for (value, weight) in transition_counts.into_iter() {
                values.push(value.clone());
                weights.push(weight as f64);
            }

            let node = MarkovNode::new(ngram.clone(), values, weights);
            total_entropy += node.entropy();
            nodes.insert(ngram, node);
        };

        // Generate the starting ngram probability distribution.
        let mut starting_ngrams = Vec::with_capacity(starting_ngram_counts.len());
        let mut weights = Vec::with_capacity(starting_ngram_counts.len());
        for (value, weight) in starting_ngram_counts.into_iter() {
            starting_ngrams.push(value);
            weights.push(weight as f64);
        }
        let starting_dist = AliasDistribution::new(weights);

        if total_entropy == 0.0 {
            return Err("No entropy found in input.");
        } else if starting_dist.entropy == 0.0 {
            return Err("No start of word entropy found in input.");
        };

        Ok(PassphraseMarkovChain {
            nodes: nodes,
            starting_ngrams: starting_ngrams,
            starting_dist: starting_dist,
        })
    }

    pub fn get_node(&self) -> &MarkovNode<String> {
        self.nodes.get(&self.starting_ngrams[self.starting_dist.choice().unwrap()]).unwrap()
    }

    pub fn passphrase(&self, min_entropy: f64) -> (String, f64) {
        let mut node = self.get_node();
        let mut entropy = self.starting_dist.entropy;
        let mut nodes = Vec::new();
        loop {
            nodes.push(node);
            entropy += node.entropy();
            // The passphrase is complete when we have enough entropy, and hit a word end.
            if entropy >= min_entropy && node.value.ends_with(" ") { break };
            let ngram = node.next();
            node = self.nodes.get(ngram).unwrap();
        }
        // We want to include the first character from each node, but the whole ngram from the
        // final node.
        let tail = nodes.last().unwrap().value.chars().skip(1);
        let chars = nodes.iter().map(|n| n.value.chars().next().unwrap()).chain(tail);
        let passphrase = chars.collect::<String>().trim().to_string();

        (passphrase, entropy)
    }
}
<|endoftext|>


<commit_before>extern crate lmdb;
extern crate lmdb_sys;

use std::{result, str};
use std::path::Path;
use lmdb::{Transaction, Cursor, DUP_SORT, INTEGER_KEY};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    ParseError,
    TransactionError,
    PathError,
    NotFoundError,
}

pub type Result<T> = result::Result<T, Error>;

struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

struct RwTransaction<'a> {
    lmdb_txn: lmdb::RwTransaction<'a>,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
struct Id(u64);

struct Node<'a> {
    id: Id,
    parent_id: Id,
    name: &'a str,
}

struct Entry<'a> {
    txn: &'a RwTransaction<'a>,
    node: Node<'a>,
    objectclass: &'a str,
}

// Ids are 64-bit integers in host-native byte order
// LMDB has special optimizations for host-native integers as keys
impl Id {
    fn root() -> Id {
        Id(0)
    }

    fn from_bytes(bytes: &[u8]) -> Result<Id> {
        if bytes.len() != 8 {
            return Err(Error::ParseError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        Ok(Id(unsafe { std::mem::transmute(id) }))
    }

    fn as_bytes(self) -> [u8; 8] {
        let Id(id) = self;
        unsafe { std::mem::transmute(id) }
    }

    fn next(self) -> Id {
        let Id(id) = self;
        Id(id + 1)
    }
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: Id::root(),
            parent_id: Id::root(),
            name: "/",
        }
    }

    fn from_parent_id_and_bytes(parent_id: Id, bytes: &[u8]) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let id = try!(Id::from_bytes(&bytes[0..8]));

        let name = match std::str::from_utf8(&bytes[8..]) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Node {
            id: id,
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&self.id.as_bytes());
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create_database(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new()
                            .set_max_dbs(8)
                            .open_with_permissions(&path, 0o600) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbCreateError),
        };

        let nodes = match env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        let entries = match env.create_db(Some("entries"), INTEGER_KEY) {
            Ok(db) => db,
            Err(_) => return Err(Error::DbCreateError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open_database(path: &Path) -> Result<LmdbAdapter> {
        let env = match lmdb::Environment::new().open(&path) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let nodes = match env.open_db(Some("nodes")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        let entries = match env.open_db(Some("entries")) {
            Ok(e) => e,
            Err(_) => return Err(Error::DbOpenError),
        };

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction { lmdb_txn: txn }),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id(&self, txn: &mut RwTransaction) -> Result<Id> {
        let cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
            Ok(c) => c,
            Err(_) => return Err(Error::TransactionError),
        };

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => Id::from_bytes(id.unwrap()).unwrap(),
            Err(_) => Id::root(),
        };

        Ok(last_id.next())
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &'a mut RwTransaction,
                            id: Id,
                            parent_id: Id,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        let node = Node {
            id: id,
            parent_id: parent_id,
            name: name,
        };

        {
            let ref mut lmdb_txn = txn.lmdb_txn;

            match lmdb_txn.put(self.nodes,
                               &parent_id.as_bytes(),
                               &node.to_bytes(),
                               lmdb::WriteFlags::empty()) {
                Ok(_) => (),
                Err(_) => return Err(Error::DbWriteError),
            }

            match lmdb_txn.put(self.entries,
                               &id.as_bytes(),
                               &objectclass,
                               lmdb::WriteFlags::empty()) {
                Ok(_) => (),
                Err(_) => return Err(Error::DbWriteError),
            }
        }

        Ok(Entry {
            txn: txn,
            node: node,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a>(&'a self, txn: &'a mut RwTransaction, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = match txn.lmdb_txn.get(self.entries, &node.id.as_bytes()) {
            Ok(bytes) => bytes,
            Err(_) => return Err(Error::DbCorruptError),
        };

        let objectclass = match std::str::from_utf8(&entry_bytes) {
            Ok(string) => string,
            _ => return Err(Error::DbCorruptError),
        };

        Ok(Entry {
            txn: txn,
            node: node,
            objectclass: objectclass,
        })
    }

    fn find_node(&self, txn: &mut RwTransaction, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        // Perform a hierarchical path lookup
        // TODO: since LMDB is ordered, we could e.g. perform a binary search
        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            let parent_id = try!(parent_node).id;

            let mut cursor = match txn.lmdb_txn.open_rw_cursor(self.nodes) {
                Ok(c) => c,
                Err(_) => return Err(Error::TransactionError),
            };

            let mut child_node = None;

            for (id, node_bytes) in cursor.iter_from(parent_id.as_bytes()) {
                if id != parent_id.as_bytes() {
                    return Err(Error::NotFoundError);
                }

                let node = try!(Node::from_parent_id_and_bytes(parent_id, node_bytes));

                if node.name == *component {
                    child_node = Some(node);
                    break;
                }
            }

            match child_node {
                Some(node) => Ok(node),
                None => return Err(Error::NotFoundError),
            }
        })
    }
}

impl<'a> RwTransaction<'a> {
    pub fn commit(self) -> Result<()> {
        match self.lmdb_txn.commit() {
            Ok(_) => Ok(()),
            Err(_) => return Err(Error::TransactionError),
        }
    }
}

#[test]
fn test_entry_lookup() {
    let path = Path::new("./tmp");
    let adapter = LmdbAdapter::create_database(path).unwrap();

    {
        let mut txn = adapter.rw_transaction().unwrap();

        let domain_id = adapter.next_available_id(&mut txn).unwrap();
        adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

        let hosts_id = domain_id.next();
        adapter.create_entry(&mut txn, hosts_id, domain_id, "hosts", "ou").unwrap();

        let host_id = hosts_id.next();
        adapter.create_entry(&mut txn, host_id, hosts_id, "master.example.com", "host").unwrap();

        txn.commit().unwrap();
    }

    {
        let mut txn = adapter.rw_transaction().unwrap();

        {
            let mut entry = adapter.find_entry(&mut txn, "/example.com/hosts/master.example.com")
                                   .unwrap();

            assert_eq!(entry.node.name, "master.example.com");
            assert_eq!(entry.objectclass, "host");
        }

        txn.commit().unwrap();
    }
}
<commit_msg>Idiomatic error handling<commit_after>extern crate lmdb;
extern crate lmdb_sys;

use std::{result, str};
use std::path::Path;
use lmdb::{Transaction, Cursor, DUP_SORT, INTEGER_KEY};

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    ParseError,
    TransactionError,
    PathError,
    NotFoundError,
}

pub type Result<T> = result::Result<T, Error>;

struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

struct RwTransaction<'a> {
    lmdb_txn: lmdb::RwTransaction<'a>,
}

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
struct Id(u64);

struct Node<'a> {
    id: Id,
    parent_id: Id,
    name: &'a str,
}

struct Entry<'a> {
    txn: &'a RwTransaction<'a>,
    node: Node<'a>,
    objectclass: &'a str,
}

// Ids are 64-bit integers in host-native byte order
// LMDB has special optimizations for host-native integers as keys
impl Id {
    fn root() -> Id {
        Id(0)
    }

    fn from_bytes(bytes: &[u8]) -> Result<Id> {
        if bytes.len() != 8 {
            return Err(Error::ParseError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        Ok(Id(unsafe { std::mem::transmute(id) }))
    }

    fn as_bytes(self) -> [u8; 8] {
        let Id(id) = self;
        unsafe { std::mem::transmute(id) }
    }

    fn next(self) -> Id {
        let Id(id) = self;
        Id(id + 1)
    }
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: Id::root(),
            parent_id: Id::root(),
            name: "/",
        }
    }

    fn from_parent_id_and_bytes(parent_id: Id, bytes: &[u8]) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let id = try!(Id::from_bytes(&bytes[0..8]));
        let name = try!(std::str::from_utf8(&bytes[8..]).map_err(|_err| Error::DbCorruptError));

        Ok(Node {
            id: id,
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&self.id.as_bytes());
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new()
                           .set_max_dbs(8)
                           .open_with_permissions(&path, 0o600)
                           .map_err(|_err| Error::DbCreateError));

        let nodes = try!(env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT)
                            .map_err(|_err| Error::DbCreateError));

        let entries = try!(env.create_db(Some("entries"), INTEGER_KEY)
                              .map_err(|_err| Error::DbCreateError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new().open(&path).map_err(|_err| Error::DbOpenError));

        let nodes = try!(env.open_db(Some("nodes")).map_err(|_err| Error::DbOpenError));

        let entries = try!(env.open_db(Some("entries")).map_err(|_err| Error::DbOpenError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction { lmdb_txn: txn }),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id(&self, txn: &mut RwTransaction) -> Result<Id> {
        let cursor = try!(txn.lmdb_txn
                             .open_rw_cursor(self.nodes)
                             .map_err(|_err| Error::TransactionError));

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => Id::from_bytes(id.unwrap()).unwrap(),
            Err(_) => Id::root(),
        };

        Ok(last_id.next())
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &'a mut RwTransaction,
                            id: Id,
                            parent_id: Id,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        let node = Node {
            id: id,
            parent_id: parent_id,
            name: name,
        };

        {
            let ref mut lmdb_txn = txn.lmdb_txn;

            try!(lmdb_txn.put(self.nodes,
                              &parent_id.as_bytes(),
                              &node.to_bytes(),
                              lmdb::WriteFlags::empty())
                         .map_err(|_err| Error::DbWriteError));

            try!(lmdb_txn.put(self.entries,
                              &id.as_bytes(),
                              &objectclass,
                              lmdb::WriteFlags::empty())
                         .map_err(|_err| Error::DbWriteError));
        }

        Ok(Entry {
            txn: txn,
            node: node,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a>(&'a self, txn: &'a mut RwTransaction, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = try!(txn.lmdb_txn
                                  .get(self.entries, &node.id.as_bytes())
                                  .map_err(|_err| Error::DbCorruptError));

        let objectclass = try!(std::str::from_utf8(&entry_bytes)
                                   .map_err(|_err| Error::DbCorruptError));

        Ok(Entry {
            txn: txn,
            node: node,
            objectclass: objectclass,
        })
    }

    fn find_node(&self, txn: &mut RwTransaction, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        // Perform a hierarchical path lookup
        // TODO: since LMDB is ordered, we could e.g. perform a binary search
        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            let parent_id = try!(parent_node).id;

            let mut cursor = try!(txn.lmdb_txn
                                     .open_rw_cursor(self.nodes)
                                     .map_err(|_err| Error::DbCorruptError));

            let mut child_node = None;

            for (id, node_bytes) in cursor.iter_from(parent_id.as_bytes()) {
                if id != parent_id.as_bytes() {
                    return Err(Error::NotFoundError);
                }

                let node = try!(Node::from_parent_id_and_bytes(parent_id, node_bytes));

                if node.name == *component {
                    child_node = Some(node);
                    break;
                }
            }

            match child_node {
                Some(node) => Ok(node),
                None => return Err(Error::NotFoundError),
            }
        })
    }
}

impl<'a> RwTransaction<'a> {
    pub fn commit(self) -> Result<()> {
        self.lmdb_txn.commit().map_err(|_err| Error::TransactionError)
    }
}

#[test]
fn test_entry_lookup() {
    let path = Path::new("./tmp");
    let adapter = LmdbAdapter::create_database(path).unwrap();

    {
        let mut txn = adapter.rw_transaction().unwrap();

        let domain_id = adapter.next_available_id(&mut txn).unwrap();
        adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

        let hosts_id = domain_id.next();
        adapter.create_entry(&mut txn, hosts_id, domain_id, "hosts", "ou").unwrap();

        let host_id = hosts_id.next();
        adapter.create_entry(&mut txn, host_id, hosts_id, "master.example.com", "host").unwrap();

        txn.commit().unwrap();
    }

    {
        let mut txn = adapter.rw_transaction().unwrap();

        {
            let mut entry = adapter.find_entry(&mut txn, "/example.com/hosts/master.example.com")
                                   .unwrap();

            assert_eq!(entry.node.name, "master.example.com");
            assert_eq!(entry.objectclass, "host");
        }

        txn.commit().unwrap();
    }
}
<|endoftext|>


<commit_before>#![feature(drop_types_in_const)]

use std::slice;

mod gameboy;
mod debugger;
use gameboy::joypad::Key;

pub const WIDTH: usize = 160;
pub const HEIGHT: usize = 144;

pub const KEY_UP: u32 = 0;
pub const KEY_DOWN: u32 = 1;
pub const KEY_LEFT: u32 = 2;
pub const KEY_RIGHT: u32 = 3;
pub const KEY_B: u32 = 4;
pub const KEY_A: u32 = 5;
pub const KEY_SELECT: u32 = 6;
pub const KEY_START: u32 = 7;

fn get_key(code: u32) -> Option<Key> {
	match code {
		KEY_UP => Some(Key::Up),
		KEY_DOWN => Some(Key::Down),
		KEY_LEFT => Some(Key::Left),
		KEY_RIGHT => Some(Key::Right),
		KEY_A => Some(Key::A),
		KEY_B => Some(Key::B),
		KEY_SELECT => Some(Key::Select),
		KEY_START => Some(Key::Start),
		_ => None,
	}
}

///Global gameboy object
static mut GAMEBOY: Option<Box<gameboy::GBC>> = None;

#[no_mangle]
///Create a new gameboy object (and store it as a global variable)
pub fn rustboy_init(rom_ptr: *const u8, rom_size: u32, ram_ptr: *const u8, ram_size: u32) {
	unsafe {
		/* Copy into a boxed array */
		let rom_slice: &[u8] = slice::from_raw_parts(rom_ptr, rom_size as usize);
		let ram_slice: &[u8] = slice::from_raw_parts(ram_ptr, ram_size as usize);

		let mut rom: Vec<u8> = Vec::with_capacity(rom_size as usize);
		let mut ram: Vec<u8> = Vec::with_capacity(ram_size as usize);

		rom.extend_from_slice(rom_slice);
		ram.extend_from_slice(ram_slice);

		GAMEBOY = Some(Box::new(gameboy::GBC::new(rom.into_boxed_slice(), ram.into_boxed_slice())));
	}
}

#[no_mangle]
//Create a new gameboy object from a path to a rom (and store it as a global variable)
//pub fn rustboy_init_from_path(rom_path: String, ram_path: String) {
//	unsafe {
//		GAMEBOY = Some(Box::new(gameboy::GBC::from_path(rom_path, ram_path)));
//	}
//}

#[no_mangle]
///Step to the next frame
pub fn rustboy_step_frame() {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.step_frame(),
			None => panic!("rustboy not initialized")
		}
	}
}

#[no_mangle]
///Get a pointer to the current front framebuffer
pub fn rustboy_get_framebuffer() -> *mut u32 {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.ppu.get_framebuffer_mut().as_mut_ptr(),
			None => panic!("rustboy not initialized"),	//return null?
		}
	}
}

#[no_mangle]
///Pass a keydown event to the gameboy
pub fn rustboy_keydown(code: u32) {
	let key: Option<Key> = get_key(code);
	if key.is_some() {
		unsafe {
			match GAMEBOY {
				Some(ref mut gameboy) => gameboy.keydown(key.unwrap()),
				None => panic!("rustboy not initialized")
			};
		}
	}
}

#[no_mangle]
///Pass a keyup event to the gameboy
pub fn rustboy_keyup(key: u32) {
	let key: Option<Key> = get_key(code);
	if key.is_some() {
		unsafe {
			match GAMEBOY {
				Some(ref mut gameboy) => gameboy.keyup(key.unwrap()),
				None => panic!("rustboy not initialized")
			};
		}
	}
}
<commit_msg>Fixed typo in rustboy_keyup.<commit_after>#![feature(drop_types_in_const)]

use std::slice;

mod gameboy;
mod debugger;
use gameboy::joypad::Key;

pub const WIDTH: usize = 160;
pub const HEIGHT: usize = 144;

pub const KEY_UP: u32 = 0;
pub const KEY_DOWN: u32 = 1;
pub const KEY_LEFT: u32 = 2;
pub const KEY_RIGHT: u32 = 3;
pub const KEY_B: u32 = 4;
pub const KEY_A: u32 = 5;
pub const KEY_SELECT: u32 = 6;
pub const KEY_START: u32 = 7;

fn get_key(code: u32) -> Option<Key> {
	match code {
		KEY_UP => Some(Key::Up),
		KEY_DOWN => Some(Key::Down),
		KEY_LEFT => Some(Key::Left),
		KEY_RIGHT => Some(Key::Right),
		KEY_A => Some(Key::A),
		KEY_B => Some(Key::B),
		KEY_SELECT => Some(Key::Select),
		KEY_START => Some(Key::Start),
		_ => None,
	}
}

///Global gameboy object
static mut GAMEBOY: Option<Box<gameboy::GBC>> = None;

#[no_mangle]
///Create a new gameboy object (and store it as a global variable)
pub fn rustboy_init(rom_ptr: *const u8, rom_size: u32, ram_ptr: *const u8, ram_size: u32) {
	unsafe {
		/* Copy into a boxed array */
		let rom_slice: &[u8] = slice::from_raw_parts(rom_ptr, rom_size as usize);
		let ram_slice: &[u8] = slice::from_raw_parts(ram_ptr, ram_size as usize);

		let mut rom: Vec<u8> = Vec::with_capacity(rom_size as usize);
		let mut ram: Vec<u8> = Vec::with_capacity(ram_size as usize);

		rom.extend_from_slice(rom_slice);
		ram.extend_from_slice(ram_slice);

		GAMEBOY = Some(Box::new(gameboy::GBC::new(rom.into_boxed_slice(), ram.into_boxed_slice())));
	}
}

#[no_mangle]
///Create a new gameboy object from a path to a rom (and store it as a global variable)
pub fn rustboy_init_from_path(rom_path: String, ram_path: String) {
	unsafe {
		GAMEBOY = Some(Box::new(gameboy::GBC::from_path(rom_path, ram_path)));
	}
}

#[no_mangle]
///Step to the next frame
pub fn rustboy_step_frame() {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.step_frame(),
			None => panic!("rustboy not initialized")
		}
	}
}

#[no_mangle]
///Get a pointer to the current front framebuffer
pub fn rustboy_get_framebuffer() -> *mut u32 {
	unsafe {
		match GAMEBOY {
			Some(ref mut gameboy) => gameboy.ppu.get_framebuffer_mut().as_mut_ptr(),
			None => panic!("rustboy not initialized"),	//return null?
		}
	}
}

#[no_mangle]
///Pass a keydown event to the gameboy
pub fn rustboy_keydown(code: u32) {
	let key: Option<Key> = get_key(code);
	if key.is_some() {
		unsafe {
			match GAMEBOY {
				Some(ref mut gameboy) => gameboy.keydown(key.unwrap()),
				None => panic!("rustboy not initialized")
			};
		}
	}
}

#[no_mangle]
///Pass a keyup event to the gameboy
pub fn rustboy_keyup(code: u32) {
	let key: Option<Key> = get_key(code);
	if key.is_some() {
		unsafe {
			match GAMEBOY {
				Some(ref mut gameboy) => gameboy.keyup(key.unwrap()),
				None => panic!("rustboy not initialized")
			};
		}
	}
}
<|endoftext|>


<commit_before>//! Rust friendly bindings to the various *nix system functions.
//!
//! Modules are structured according to the C header file that they would be
//! defined in.
#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
// warnings even though the macro expands into something with allow(dead_code)
#![allow(dead_code)]
#![deny(warnings)]

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate cfg_if;

pub extern crate libc;

#[cfg(test)]
extern crate nix_test as nixtest;

// Re-exports
pub use libc::{c_int, c_void};
pub use errno::Errno;

pub mod errno;
pub mod features;
pub mod fcntl;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod mount;

#[cfg(any(target_os = "linux"))]
pub mod mqueue;

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub mod poll;

pub mod net;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod sched;

pub mod sys;
pub mod unistd;

/*
 *
 * ===== Result / Error =====
 *
 */

use libc::c_char;
use std::{ptr, result};
use std::ffi::{CStr, OsStr};
use std::path::{Path, PathBuf};
use std::os::unix::ffi::OsStrExt;
use std::io;
use std::fmt;
use std::error;
use libc::PATH_MAX;

pub type Result<T> = result::Result<T, Error>;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
    Sys(errno::Errno),
    InvalidPath,
}

impl Error {
    pub fn from_errno(errno: errno::Errno) -> Error {
        Error::Sys(errno)
    }

    pub fn last() -> Error {
        Error::Sys(errno::Errno::last())
    }

    pub fn invalid_argument() -> Error {
        Error::Sys(errno::EINVAL)
    }

    pub fn errno(&self) -> errno::Errno {
        match *self {
            Error::Sys(errno) => errno,
            Error::InvalidPath => errno::Errno::EINVAL,
        }
    }
}

impl From<errno::Errno> for Error {
    fn from(errno: errno::Errno) -> Error { Error::from_errno(errno) }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::InvalidPath => "Invalid path",
            &Error::Sys(ref errno) => errno.desc(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::InvalidPath => write!(f, "Invalid path"),
            &Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
        }
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> Self {
        match err {
            Error::InvalidPath => io::Error::new(io::ErrorKind::InvalidInput, err),
            Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
        }
    }
}

pub trait NixPath {
    fn len(&self) -> usize;

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T;
}

impl NixPath for str {
    fn len(&self) -> usize {
        NixPath::len(OsStr::new(self))
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            OsStr::new(self).with_nix_path(f)
        }
}

impl NixPath for OsStr {
    fn len(&self) -> usize {
        self.as_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            self.as_bytes().with_nix_path(f)
        }
}

impl NixPath for CStr {
    fn len(&self) -> usize {
        self.to_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        // Equivalence with the [u8] impl.
        if self.len() >= PATH_MAX as usize {
            return Err(Error::InvalidPath);
        }

        Ok(f(self))
    }
}

impl NixPath for [u8] {
    fn len(&self) -> usize {
        self.len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        let mut buf = [0u8; PATH_MAX as usize];

        if self.len() >= PATH_MAX as usize {
            return Err(Error::InvalidPath);
        }

        match self.iter().position(|b| *b == 0) {
            Some(_) => Err(Error::InvalidPath),
            None => {
                unsafe {
                    // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
                    ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
                    Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
                }

            }
        }
    }
}

impl NixPath for Path {
    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

impl NixPath for PathBuf {
    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

/// Treats `None` as an empty string.
impl<'a, NP: ?Sized + NixPath>  NixPath for Option<&'a NP> {
    fn len(&self) -> usize {
        self.map_or(0, NixPath::len)
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        if let Some(nix_path) = *self {
            nix_path.with_nix_path(f)
        } else {
            unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
        }
    }
}
<commit_msg>libc: re-export libc properly<commit_after>//! Rust friendly bindings to the various *nix system functions.
//!
//! Modules are structured according to the C header file that they would be
//! defined in.
#![crate_name = "nix"]
#![cfg(unix)]
#![allow(non_camel_case_types)]
// latest bitflags triggers a rustc bug with cross-crate macro expansions causing dead_code
// warnings even though the macro expands into something with allow(dead_code)
#![allow(dead_code)]
#![deny(warnings)]

#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate cfg_if;

#[cfg(test)]
extern crate nix_test as nixtest;

// In rust 1.8+ this should be `pub extern crate libc` but prior
// to https://github.com/rust-lang/rust/issues/26775 being resolved
// it is necessary to get a little creative.
pub mod libc {
    extern crate libc;
    pub use self::libc::*;
}

pub use libc::{c_int, c_void};
pub use errno::Errno;

pub mod errno;
pub mod features;
pub mod fcntl;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod mount;

#[cfg(any(target_os = "linux"))]
pub mod mqueue;

#[cfg(any(target_os = "linux", target_os = "macos"))]
pub mod poll;

pub mod net;

#[cfg(any(target_os = "linux", target_os = "android"))]
pub mod sched;

pub mod sys;
pub mod unistd;

/*
 *
 * ===== Result / Error =====
 *
 */

use libc::c_char;
use std::{ptr, result};
use std::ffi::{CStr, OsStr};
use std::path::{Path, PathBuf};
use std::os::unix::ffi::OsStrExt;
use std::io;
use std::fmt;
use std::error;
use libc::PATH_MAX;

pub type Result<T> = result::Result<T, Error>;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
    Sys(errno::Errno),
    InvalidPath,
}

impl Error {
    pub fn from_errno(errno: errno::Errno) -> Error {
        Error::Sys(errno)
    }

    pub fn last() -> Error {
        Error::Sys(errno::Errno::last())
    }

    pub fn invalid_argument() -> Error {
        Error::Sys(errno::EINVAL)
    }

    pub fn errno(&self) -> errno::Errno {
        match *self {
            Error::Sys(errno) => errno,
            Error::InvalidPath => errno::Errno::EINVAL,
        }
    }
}

impl From<errno::Errno> for Error {
    fn from(errno: errno::Errno) -> Error { Error::from_errno(errno) }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::InvalidPath => "Invalid path",
            &Error::Sys(ref errno) => errno.desc(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error::InvalidPath => write!(f, "Invalid path"),
            &Error::Sys(errno) => write!(f, "{:?}: {}", errno, errno.desc()),
        }
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> Self {
        match err {
            Error::InvalidPath => io::Error::new(io::ErrorKind::InvalidInput, err),
            Error::Sys(errno) => io::Error::from_raw_os_error(errno as i32),
        }
    }
}

pub trait NixPath {
    fn len(&self) -> usize;

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T;
}

impl NixPath for str {
    fn len(&self) -> usize {
        NixPath::len(OsStr::new(self))
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            OsStr::new(self).with_nix_path(f)
        }
}

impl NixPath for OsStr {
    fn len(&self) -> usize {
        self.as_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
        where F: FnOnce(&CStr) -> T {
            self.as_bytes().with_nix_path(f)
        }
}

impl NixPath for CStr {
    fn len(&self) -> usize {
        self.to_bytes().len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        // Equivalence with the [u8] impl.
        if self.len() >= PATH_MAX as usize {
            return Err(Error::InvalidPath);
        }

        Ok(f(self))
    }
}

impl NixPath for [u8] {
    fn len(&self) -> usize {
        self.len()
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T>
            where F: FnOnce(&CStr) -> T {
        let mut buf = [0u8; PATH_MAX as usize];

        if self.len() >= PATH_MAX as usize {
            return Err(Error::InvalidPath);
        }

        match self.iter().position(|b| *b == 0) {
            Some(_) => Err(Error::InvalidPath),
            None => {
                unsafe {
                    // TODO: Replace with bytes::copy_memory. rust-lang/rust#24028
                    ptr::copy_nonoverlapping(self.as_ptr(), buf.as_mut_ptr(), self.len());
                    Ok(f(CStr::from_ptr(buf.as_ptr() as *const c_char)))
                }

            }
        }
    }
}

impl NixPath for Path {
    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

impl NixPath for PathBuf {
    fn len(&self) -> usize {
        NixPath::len(self.as_os_str())
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        self.as_os_str().with_nix_path(f)
    }
}

/// Treats `None` as an empty string.
impl<'a, NP: ?Sized + NixPath>  NixPath for Option<&'a NP> {
    fn len(&self) -> usize {
        self.map_or(0, NixPath::len)
    }

    fn with_nix_path<T, F>(&self, f: F) -> Result<T> where F: FnOnce(&CStr) -> T {
        if let Some(nix_path) = *self {
            nix_path.with_nix_path(f)
        } else {
            unsafe { CStr::from_ptr("\0".as_ptr() as *const _).with_nix_path(f) }
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Sub, Mul, Div};

#[macro_use]
extern crate nalgebra;
use nalgebra::ApproxEq;

extern crate num;
use num::{Float};

#[inline]
pub fn magic_number_1<T>() -> T
    where T: std::convert::From<f32>
{
    <T as std::convert::From<f32>>::from(700.)
}

#[inline]
pub fn magic_number_2<T>() -> T
    where T: std::convert::From<f32>
{
    <T as std::convert::From<f32>>::from(2595.)
}

pub fn hertz_from_mel<T>(mel: T) -> T
    where T: std::convert::From<f32> + Float + Div<T, Output=T> + Sub<T, Output=T>
{
    magic_number_1::<T>() *
        (<T as std::convert::From<f32>>::from(10.)
         .powf(mel / magic_number_2::<T>()) -
         <T as std::convert::From<f32>>::from(1.))
}

pub fn mel_from_hertz<T>(hertz: T) -> T
    where T: std::convert::From<f32> + Float + Mul<T, Output=T> + Add<T, Output=T>
{
    magic_number_2::<T>() *
        (<T as std::convert::From<f32>>::from(1.) +
         hertz / magic_number_1::<T>()).log10()
}

macro_rules! test_mel {
    ($float:ty) => {{
        assert_approx_eq_eps!(
            549.64 as $float, mel_from_hertz(440 as $float), 0.01);
        assert_approx_eq_eps!(
            440 as $float, hertz_from_mel(549.64 as $float), 0.01);

        let mel: $float = 0.;
        assert_approx_eq!(mel, mel_from_hertz(hertz_from_mel(mel)));
        let mel: $float = 100.;
        assert_approx_eq_eps!(
            mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);

        let hertz: $float = 0.;
        assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
        let hertz: $float = 44100. / 2.;
        assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
    }}
}

#[test]
fn test_mel_f32() {
    test_mel!(f32);
}

#[test]
fn test_mel_f64() {
    test_mel!(f64);
}
<commit_msg>make small functions that are likely called many times inlineable across crate boundary<commit_after>use std::ops::{Add, Sub, Mul, Div};

#[macro_use]
extern crate nalgebra;
use nalgebra::ApproxEq;

extern crate num;
use num::{Float};

#[inline]
pub fn magic_number_1<T>() -> T
    where T: std::convert::From<f32>
{
    <T as std::convert::From<f32>>::from(700.)
}

#[inline]
pub fn magic_number_2<T>() -> T
    where T: std::convert::From<f32>
{
    <T as std::convert::From<f32>>::from(2595.)
}

#[inline]
pub fn hertz_from_mel<T>(mel: T) -> T
    where T: std::convert::From<f32> + Float + Div<T, Output=T> + Sub<T, Output=T>
{
    magic_number_1::<T>() *
        (<T as std::convert::From<f32>>::from(10.)
         .powf(mel / magic_number_2::<T>()) -
         <T as std::convert::From<f32>>::from(1.))
}

#[inline]
pub fn mel_from_hertz<T>(hertz: T) -> T
    where T: std::convert::From<f32> + Float + Mul<T, Output=T> + Add<T, Output=T>
{
    magic_number_2::<T>() *
        (<T as std::convert::From<f32>>::from(1.) +
         hertz / magic_number_1::<T>()).log10()
}

macro_rules! test_mel {
    ($float:ty) => {{
        assert_approx_eq_eps!(
            549.64 as $float, mel_from_hertz(440 as $float), 0.01);
        assert_approx_eq_eps!(
            440 as $float, hertz_from_mel(549.64 as $float), 0.01);

        let mel: $float = 0.;
        assert_approx_eq!(mel, mel_from_hertz(hertz_from_mel(mel)));
        let mel: $float = 100.;
        assert_approx_eq_eps!(
            mel, mel_from_hertz(hertz_from_mel(mel)), 0.0001);

        let hertz: $float = 0.;
        assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
        let hertz: $float = 44100. / 2.;
        assert_approx_eq!(hertz, hertz_from_mel(mel_from_hertz(hertz)));
    }}
}

#[test]
fn test_mel_f32() {
    test_mel!(f32);
}

#[test]
fn test_mel_f64() {
    test_mel!(f64);
}
<|endoftext|>