<commit_before>/*
 * chamkho - a word breaker written in Rust
 * Copyright (C) 2015  Vee Satayamas
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

pub extern crate wordcut_engine;

use self::wordcut_engine::Dict;
use std::io::Result;
use std::path::Path;

pub type Wordcut = self::wordcut_engine::Wordcut;

#[allow(dead_code)]
pub fn cargo_dir() -> &'static Path {
    Path::new(env!("CARGO_MANIFEST_DIR"))
}

pub fn default_path() -> &'static Path {
    Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/data/words_th.txt"))
}

pub fn lao_path() -> &'static Path {
    Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/data/laowords.txt"))
}

pub fn thai_cluster_path() -> Option<String> {
    Some(concat!(env!("CARGO_MANIFEST_DIR"), "/data/thai_cluster_rules.txt").to_owned())
}

pub fn lao_clusters_path() -> Option<String> {
    None
}

pub fn load_dict(path: &Path) -> Result<Dict> {
    self::wordcut_engine::load_dict(path)
}

#[cfg(test)]
mod tests {
    use super::wordcut_engine::TextRange;
    use super::Wordcut;
    use std::path::Path;

    #[test]
    fn test_default_dict() {
        let dict = super::load_dict(super::default_path());
        assert!(dict.is_ok());
    }

    #[test]
    fn test_segment_into_ranges() {
        let dict = super::load_dict(Path::new("data/thai.txt")).unwrap();
        let wordcut = Wordcut::new(dict);
        let ranges = wordcut.segment("กากกา");
        let expected = vec![TextRange { s: 0, e: 3 }, TextRange { s: 3, e: 5 }];
        assert_eq!(ranges, expected)
    }

    #[test]
    fn test_segment_into_strings() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("กากกา");
        let expected = vec!["กาก".to_string(), "กา".to_string()];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_punc() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("\"ฆกากา\"");
        let expected = &vec!["\"", "ฆ", "กา", "กา", "\""]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_parentheses() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings(&"(ฆกากา)".to_string());
        let expected = &vec!["(", "ฆ", "กา", "กา", ")"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_unicode_quote() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("“ฆกากา”");
        let expected = &vec!["“", "ฆ", "กา", "กา", "”"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_unknown_sandwich() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("ฮฮกาฮฮ");
        let expected = &vec!["ฮฮ", "กา", "ฮฮ"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_2spaces() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("กา  มา");
        let expected = &vec!["กา", "  ", "มา"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_2spaces_unk() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("ฮฮ  ญญ");
        let expected = &vec!["ฮฮ", "  ", "ญญ"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_one_word() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("มาตรา");
        let expected = &vec!["มาตรา"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_from_law() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("มาตรา 482 ผู้ขายไม่");
        let expected = &vec!["มาตรา", " ", "482", " ", "ผู้", "ขาย", "ไม่"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_space() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment("a cat");
        let expected = vec![
            TextRange { s: 0, e: 1 },
            TextRange { s: 1, e: 2 },
            TextRange { s: 2, e: 5 },
        ];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_lao() {
        let dict = super::load_dict(super::lao_path());
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment(&"ພາສາລາວມີ".to_string());
        let expected = vec![
            TextRange { s: 0, e: 4 },
            TextRange { s: 4, e: 7 },
            TextRange { s: 7, e: 9 },
        ];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_latin() {
        let dict = super::load_dict(super::lao_path());
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings(&"ฑฑACญญ".to_string());
        let expected = &vec!["ฑฑ", "AC", "ญญ"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_get_cargo_dir() {
        let cargo_dir = super::cargo_dir().to_str().unwrap();
        assert!(cargo_dir.len() > 0);
    }
}
<commit_msg>Remove LGPL term<commit_after>pub extern crate wordcut_engine;

use self::wordcut_engine::Dict;
use std::io::Result;
use std::path::Path;

pub type Wordcut = self::wordcut_engine::Wordcut;

#[allow(dead_code)]
pub fn cargo_dir() -> &'static Path {
    Path::new(env!("CARGO_MANIFEST_DIR"))
}

pub fn default_path() -> &'static Path {
    Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/data/words_th.txt"))
}

pub fn lao_path() -> &'static Path {
    Path::new(concat!(env!("CARGO_MANIFEST_DIR"), "/data/laowords.txt"))
}

pub fn thai_cluster_path() -> Option<String> {
    Some(concat!(env!("CARGO_MANIFEST_DIR"), "/data/thai_cluster_rules.txt").to_owned())
}

pub fn lao_clusters_path() -> Option<String> {
    None
}

pub fn load_dict(path: &Path) -> Result<Dict> {
    self::wordcut_engine::load_dict(path)
}

#[cfg(test)]
mod tests {
    use super::wordcut_engine::TextRange;
    use super::Wordcut;
    use std::path::Path;

    #[test]
    fn test_default_dict() {
        let dict = super::load_dict(super::default_path());
        assert!(dict.is_ok());
    }

    #[test]
    fn test_segment_into_ranges() {
        let dict = super::load_dict(Path::new("data/thai.txt")).unwrap();
        let wordcut = Wordcut::new(dict);
        let ranges = wordcut.segment("กากกา");
        let expected = vec![TextRange { s: 0, e: 3 }, TextRange { s: 3, e: 5 }];
        assert_eq!(ranges, expected)
    }

    #[test]
    fn test_segment_into_strings() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("กากกา");
        let expected = vec!["กาก".to_string(), "กา".to_string()];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_punc() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("\"ฆกากา\"");
        let expected = &vec!["\"", "ฆ", "กา", "กา", "\""]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_parentheses() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings(&"(ฆกากา)".to_string());
        let expected = &vec!["(", "ฆ", "กา", "กา", ")"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_with_unicode_quote() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("“ฆกากา”");
        let expected = &vec!["“", "ฆ", "กา", "กา", "”"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_unknown_sandwich() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("ฮฮกาฮฮ");
        let expected = &vec!["ฮฮ", "กา", "ฮฮ"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_2spaces() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("กา  มา");
        let expected = &vec!["กา", "  ", "มา"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_segment_2spaces_unk() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("ฮฮ  ญญ");
        let expected = &vec!["ฮฮ", "  ", "ญญ"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_one_word() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("มาตรา");
        let expected = &vec!["มาตรา"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_from_law() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings("มาตรา 482 ผู้ขายไม่");
        let expected = &vec!["มาตรา", " ", "482", " ", "ผู้", "ขาย", "ไม่"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_space() {
        let dict = super::load_dict(Path::new("data/thai.txt"));
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment("a cat");
        let expected = vec![
            TextRange { s: 0, e: 1 },
            TextRange { s: 1, e: 2 },
            TextRange { s: 2, e: 5 },
        ];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_lao() {
        let dict = super::load_dict(super::lao_path());
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment(&"ພາສາລາວມີ".to_string());
        let expected = vec![
            TextRange { s: 0, e: 4 },
            TextRange { s: 4, e: 7 },
            TextRange { s: 7, e: 9 },
        ];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_latin() {
        let dict = super::load_dict(super::lao_path());
        let wordcut = Wordcut::new(dict.unwrap());
        let words = wordcut.segment_into_strings(&"ฑฑACญญ".to_string());
        let expected = &vec!["ฑฑ", "AC", "ญญ"]
            .iter()
            .map(|&s| s.to_string())
            .collect::<Vec<String>>()[..];
        assert_eq!(words, expected)
    }

    #[test]
    fn test_get_cargo_dir() {
        let cargo_dir = super::cargo_dir().to_str().unwrap();
        assert!(cargo_dir.len() > 0);
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::c_str::CString;

mod ffi;

pub fn is_present() -> bool {
    unsafe {
        ffi::cpuid_present() == 1
    }
}

pub fn version() -> String {
    let version_string = unsafe {
        let ptr = ffi::cpuid_lib_version();
        CString::new(ptr, false)
    };
    version_string.as_str().unwrap().to_string()
}

pub fn error() -> String {
    let error_string = unsafe {
        let ptr = ffi::cpuid_error();
        CString::new(ptr, false)
    };
    error_string.as_str().unwrap().to_string()
}

#[test]
fn test_is_present() {
    assert!(is_present());
}
<commit_msg>Started work on identify() function.<commit_after>extern crate libc;

use std::c_str::CString;

mod ffi;

pub fn is_present() -> bool {
    unsafe {
        ffi::cpuid_present() == 1
    }
}

pub fn version() -> String {
    let version_string = unsafe {
        let ptr = ffi::cpuid_lib_version();
        CString::new(ptr, false)
    };
    version_string.as_str().unwrap().to_string()
}

pub fn error() -> String {
    let error_string = unsafe {
        let ptr = ffi::cpuid_error();
        CString::new(ptr, false)
    };
    error_string.as_str().unwrap().to_string()
}

pub fn identify() -> bool {
    let mut raw = ffi::cpu_raw_data_t {
        basic_cpuid: [0, ..ffi::MAX_CPUID_LEVEL * 4u],
        ext_cpuid: [0, ..ffi::MAX_EXT_CPUID_LEVEL * 4u],
        intel_fn4: [0, ..ffi::MAX_INTELFN4_LEVEL * 4u],
        intel_fn11: [0, ..ffi::MAX_INTELFN11_LEVEL * 4u],
    };
    let result = unsafe {
        ffi::cpuid_get_raw_data(&mut raw)
    };
    // TODO: use raw in the call to cpu_identify
    result == 0
}

#[test]
fn test_is_present() {
    assert!(is_present());
}
<|endoftext|>


<commit_before>//! [(Link to repository page.)](https://github.com/C4K3/Ozelot)
//!
//! This is a library made for interacting with the Minecraft protocl
//! (MCMODERN only, not MCPE.)
//!
//! It is mostly a low-level library, its goals are to
//! handle everything network related, but nothing beyond that. For example
//! this library does not support any types beyond ones found in standard Rust,
//! this results in certain packets that contain compound datatypes not having
//! their complex fields serialized by this library, but instead handing the
//! raw binary data to consumers of this library to parse however they wish.
//! One example of this is packets that contain NBT data, the packets are read
//! but the NBT data is not in any way parsed by this library.
//!
//! This library currently only supports the client side of the connection,
//! but servers may be supported in the future as well, since we already have
//! all the packet definitions.
//!
//! Currently the library is entirely synchronous, requiring consumers to handle
//! concurrency however they wish. It would be cool to add an asynchronous API
//! though, maybe using mio.
//!
//! The library nominally supports every packet used in MCMODERN, but the goal
//! is still to add lots more helper functions and other useful things.
//!
//! The library does not yet have any stable releases, not because it may
//! contain bugs (which it certainly does,) but because the API may be
//! significantly restructured without warning.
//!
//! # Examples
//!
//! Connecting to a remote server as an authenticated user, printing all chat
//! messages, and then echoing back messages that appear not to be written by us
//! (else we'd get into an infinite loop echoing our own messages.)
//!
//! ```rust,no_run
//! use ozelot::{mojang, Client, serverbound, utils};
//! use ozelot::clientbound::ClientboundPacket;
//!
//! let auth = mojang::Authenticate::new("my_email@example.com".to_string(),
//!                                      "my_password".to_string())
//!     .perform().unwrap();
//!
//!
//! /* By using connect_authenticated, auto_handle will be true and thus ozelot
//!  * will respond to keepalives automatically */
//! let mut client = Client::connect_authenticated("minecraft.example.com",
//!                                                25565, &auth).unwrap();
//!
//! let username = auth.selectedProfile.name;
//!
//! 'main: loop {
//!     let packets = client.read().unwrap();
//!     for packet in packets {
//!         match packet {
//!         ClientboundPacket::PlayDisconnect(ref p) => {
//!             println!("Disconnected, reason: {}",
//!                      utils::chat_to_str(p.get_reason()));
//!             break 'main;
//!         },
//!         ClientboundPacket::ChatMessage(ref p) => {
//!             let msg = utils::chat_to_str(p.get_chat());
//!             println!("{}", msg);
//!             if !msg.contains(&username) {
//!                 /* Since we don't want an infinite loop, we don't echo back
//!                  * our own messages. We say that a received message wasn't
//!                  * written by us if it doesn't contain our username
//!                  *
//!                  * Note that this echoes back the raw chat message, that is
//!                  * playername and everything, and also non-chat messages. */
//!                 let response = serverbound::ChatMessage::new(msg);
//!                 client.send(response).unwrap();
//!             }
//!         },
//!         /* We throw away all other packets */
//!         _ => (),
//!         }
//!     }
//! }
//! ```
extern crate byteorder;
extern crate flate2;
extern crate netbuf;
extern crate openssl;
extern crate reqwest; /* Holy fuck the dependencies needed just to make 2
                         HTTP POST requests ... */
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate derive_new;

#[macro_use]
mod macros;
mod client;
mod connection;
#[allow(non_snake_case)]
mod json;
mod yggdrasil;
pub mod clientbound;
#[allow(non_snake_case)]
pub mod mojang;
pub mod read;
pub mod serverbound;
pub mod utils;
pub mod write;
#[cfg(test)]
mod tests;

pub use client::Client;

use std::fmt;

use flate2::Compression;

const COMPRESSION_LEVEL: Compression = Compression::Default;
/// The protocol version supported by this version of ozelot
pub const PROTOCOL_VERSION: i32 = 316;

/// FIXME temporary struct until u128 lands in stable rust, used for uuids
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[allow(non_camel_case_types)]
pub struct u128(u64, u64);

/// This tracks which state of play the client is in. The value of this changes
/// the meaning of the different packet ids.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ClientState {
    Handshake,
    Status,
    Login,
    Play,
}
impl fmt::Display for ClientState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}",
               match self {
                   &ClientState::Handshake => "Handshake",
                   &ClientState::Status => "Status",
                   &ClientState::Login => "Login",
                   &ClientState::Play => "Play",
               })
    }
}
<commit_msg>Make u128 fields public<commit_after>//! [(Link to repository page.)](https://github.com/C4K3/Ozelot)
//!
//! This is a library made for interacting with the Minecraft protocl
//! (MCMODERN only, not MCPE.)
//!
//! It is mostly a low-level library, its goals are to
//! handle everything network related, but nothing beyond that. For example
//! this library does not support any types beyond ones found in standard Rust,
//! this results in certain packets that contain compound datatypes not having
//! their complex fields serialized by this library, but instead handing the
//! raw binary data to consumers of this library to parse however they wish.
//! One example of this is packets that contain NBT data, the packets are read
//! but the NBT data is not in any way parsed by this library.
//!
//! This library currently only supports the client side of the connection,
//! but servers may be supported in the future as well, since we already have
//! all the packet definitions.
//!
//! Currently the library is entirely synchronous, requiring consumers to handle
//! concurrency however they wish. It would be cool to add an asynchronous API
//! though, maybe using mio.
//!
//! The library nominally supports every packet used in MCMODERN, but the goal
//! is still to add lots more helper functions and other useful things.
//!
//! The library does not yet have any stable releases, not because it may
//! contain bugs (which it certainly does,) but because the API may be
//! significantly restructured without warning.
//!
//! # Examples
//!
//! Connecting to a remote server as an authenticated user, printing all chat
//! messages, and then echoing back messages that appear not to be written by us
//! (else we'd get into an infinite loop echoing our own messages.)
//!
//! ```rust,no_run
//! use ozelot::{mojang, Client, serverbound, utils};
//! use ozelot::clientbound::ClientboundPacket;
//!
//! let auth = mojang::Authenticate::new("my_email@example.com".to_string(),
//!                                      "my_password".to_string())
//!     .perform().unwrap();
//!
//!
//! /* By using connect_authenticated, auto_handle will be true and thus ozelot
//!  * will respond to keepalives automatically */
//! let mut client = Client::connect_authenticated("minecraft.example.com",
//!                                                25565, &auth).unwrap();
//!
//! let username = auth.selectedProfile.name;
//!
//! 'main: loop {
//!     let packets = client.read().unwrap();
//!     for packet in packets {
//!         match packet {
//!         ClientboundPacket::PlayDisconnect(ref p) => {
//!             println!("Disconnected, reason: {}",
//!                      utils::chat_to_str(p.get_reason()));
//!             break 'main;
//!         },
//!         ClientboundPacket::ChatMessage(ref p) => {
//!             let msg = utils::chat_to_str(p.get_chat());
//!             println!("{}", msg);
//!             if !msg.contains(&username) {
//!                 /* Since we don't want an infinite loop, we don't echo back
//!                  * our own messages. We say that a received message wasn't
//!                  * written by us if it doesn't contain our username
//!                  *
//!                  * Note that this echoes back the raw chat message, that is
//!                  * playername and everything, and also non-chat messages. */
//!                 let response = serverbound::ChatMessage::new(msg);
//!                 client.send(response).unwrap();
//!             }
//!         },
//!         /* We throw away all other packets */
//!         _ => (),
//!         }
//!     }
//! }
//! ```
extern crate byteorder;
extern crate flate2;
extern crate netbuf;
extern crate openssl;
extern crate reqwest; /* Holy fuck the dependencies needed just to make 2
                         HTTP POST requests ... */
extern crate rustc_serialize;
extern crate serde;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate serde_json;
#[macro_use]
extern crate derive_new;

#[macro_use]
mod macros;
mod client;
mod connection;
#[allow(non_snake_case)]
mod json;
mod yggdrasil;
pub mod clientbound;
#[allow(non_snake_case)]
pub mod mojang;
pub mod read;
pub mod serverbound;
pub mod utils;
pub mod write;
#[cfg(test)]
mod tests;

pub use client::Client;

use std::fmt;

use flate2::Compression;

const COMPRESSION_LEVEL: Compression = Compression::Default;
/// The protocol version supported by this version of ozelot
pub const PROTOCOL_VERSION: i32 = 316;

/// FIXME temporary struct until u128 lands in stable rust, used for uuids
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[allow(non_camel_case_types)]
pub struct u128(pub u64, pub u64);

/// This tracks which state of play the client is in. The value of this changes
/// the meaning of the different packet ids.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ClientState {
    Handshake,
    Status,
    Login,
    Play,
}
impl fmt::Display for ClientState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}",
               match self {
                   &ClientState::Handshake => "Handshake",
                   &ClientState::Status => "Status",
                   &ClientState::Login => "Login",
                   &ClientState::Play => "Play",
               })
    }
}
<|endoftext|>


<commit_before>//! # Plist
//!
//! A rusty plist parser.
//!
//! ## Usage
//!
//! Put this in your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! plist = "0.1"
//! ```
//!
//! And put this in your crate root:
//!
//! ```rust
//! extern crate plist;
//! ```
//!
//! ## Examples
//!
//! ```rust
//! use plist::Plist;
//! use std::fs::File;
//!
//! let file = File::open("tests/data/xml.plist").unwrap();
//! let plist = Plist::read(file).unwrap();
//!
//! match plist {
//!     Plist::Array(_array) => (),
//!     _ => ()
//! }
//! ```
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate serde_derive;
//!
//! use plist::serde::deserialize;
//! use std::fs::File;
//!
//! #[derive(Deserialize)]
//! struct Info {
//!     name: String,
//!     x: i32
//! }
//!
//! let file = File::open("tests/data/xml.plist").unwrap();
//! let info: Info = deserialize(file).unwrap();
//! ```

extern crate base64;
extern crate byteorder;
extern crate chrono;
extern crate xml as xml_rs;

pub mod binary;
pub mod xml;

mod builder;
mod date;
mod plist;

pub use date::Date;
pub use plist::Plist;

// Optional serde module
#[cfg(feature = "serde")]
#[macro_use]
extern crate serde as serde_base;
#[cfg(feature = "serde")]
pub mod serde;

use std::fmt;
use std::io::{Read, Seek, SeekFrom};
use std::io::Error as IoError;

/// An encoding of a plist as a flat structure.
///
/// Output by the event readers.
///
/// Dictionary keys and values are represented as pairs of values e.g.:
///
/// ```ignore rust
/// StartDictionary
/// StringValue("Height") // Key
/// RealValue(181.2)      // Value
/// StringValue("Age")    // Key
/// IntegerValue(28)      // Value
/// EndDictionary
/// ```
#[derive(Clone, Debug, PartialEq)]
pub enum PlistEvent {
    // While the length of an array or dict cannot be feasably greater than max(usize) this better
    // conveys the concept of an effectively unbounded event stream.
    StartArray(Option<u64>),
    EndArray,

    StartDictionary(Option<u64>),
    EndDictionary,

    BooleanValue(bool),
    DataValue(Vec<u8>),
    DateValue(Date),
    IntegerValue(i64),
    RealValue(f64),
    StringValue(String),
}

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

#[derive(Debug)]
pub enum Error {
    InvalidData,
    UnexpectedEof,
    Io(IoError),
    Serde(String),
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidData => "invalid data",
            Error::UnexpectedEof => "unexpected eof",
            Error::Io(ref err) => err.description(),
            Error::Serde(ref err) => &err,
        }
    }

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

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref err) => err.fmt(fmt),
            _ => <Self as ::std::error::Error>::description(self).fmt(fmt),
        }
    }
}

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

pub struct EventReader<R: Read + Seek>(EventReaderInner<R>);

enum EventReaderInner<R: Read + Seek> {
    Uninitialized(Option<R>),
    Xml(xml::EventReader<R>),
    Binary(binary::EventReader<R>),
}

impl<R: Read + Seek> EventReader<R> {
    pub fn new(reader: R) -> EventReader<R> {
        EventReader(EventReaderInner::Uninitialized(Some(reader)))
    }

    fn is_binary(reader: &mut R) -> Result<bool> {
        reader.seek(SeekFrom::Start(0))?;
        let mut magic = [0; 8];
        reader.read(&mut magic)?;
        reader.seek(SeekFrom::Start(0))?;

        Ok(if &magic == b"bplist00" { true } else { false })
    }
}

impl<R: Read + Seek> Iterator for EventReader<R> {
    type Item = Result<PlistEvent>;

    fn next(&mut self) -> Option<Result<PlistEvent>> {
        let mut reader = match self.0 {
            EventReaderInner::Xml(ref mut parser) => return parser.next(),
            EventReaderInner::Binary(ref mut parser) => return parser.next(),
            EventReaderInner::Uninitialized(ref mut reader) => reader.take().unwrap(),
        };

        let event_reader = match EventReader::is_binary(&mut reader) {
            Ok(true) => EventReaderInner::Binary(binary::EventReader::new(reader)),
            Ok(false) => EventReaderInner::Xml(xml::EventReader::new(reader)),
            Err(err) => {
                ::std::mem::replace(&mut self.0, EventReaderInner::Uninitialized(Some(reader)));
                return Some(Err(err));
            }
        };

        ::std::mem::replace(&mut self.0, event_reader);

        self.next()
    }
}

pub trait EventWriter {
    fn write(&mut self, event: &PlistEvent) -> Result<()>;
}

fn u64_to_usize(len_u64: u64) -> Result<usize> {
    let len = len_u64 as usize;
    if len as u64 != len_u64 {
        return Err(Error::InvalidData); // Too long
    }
    Ok(len)
}

fn u64_option_to_usize(len: Option<u64>) -> Result<Option<usize>> {
    match len {
        Some(len) => Ok(Some(u64_to_usize(len)?)),
        None => Ok(None),
    }
}
<commit_msg>Update usage example version.<commit_after>//! # Plist
//!
//! A rusty plist parser.
//!
//! ## Usage
//!
//! Put this in your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! plist = "0.2"
//! ```
//!
//! And put this in your crate root:
//!
//! ```rust
//! extern crate plist;
//! ```
//!
//! ## Examples
//!
//! ```rust
//! use plist::Plist;
//! use std::fs::File;
//!
//! let file = File::open("tests/data/xml.plist").unwrap();
//! let plist = Plist::read(file).unwrap();
//!
//! match plist {
//!     Plist::Array(_array) => (),
//!     _ => ()
//! }
//! ```
//!
//! ```rust,ignore
//! #[macro_use]
//! extern crate serde_derive;
//!
//! use plist::serde::deserialize;
//! use std::fs::File;
//!
//! #[derive(Deserialize)]
//! struct Info {
//!     name: String,
//!     x: i32
//! }
//!
//! let file = File::open("tests/data/xml.plist").unwrap();
//! let info: Info = deserialize(file).unwrap();
//! ```

extern crate base64;
extern crate byteorder;
extern crate chrono;
extern crate xml as xml_rs;

pub mod binary;
pub mod xml;

mod builder;
mod date;
mod plist;

pub use date::Date;
pub use plist::Plist;

// Optional serde module
#[cfg(feature = "serde")]
#[macro_use]
extern crate serde as serde_base;
#[cfg(feature = "serde")]
pub mod serde;

use std::fmt;
use std::io::{Read, Seek, SeekFrom};
use std::io::Error as IoError;

/// An encoding of a plist as a flat structure.
///
/// Output by the event readers.
///
/// Dictionary keys and values are represented as pairs of values e.g.:
///
/// ```ignore rust
/// StartDictionary
/// StringValue("Height") // Key
/// RealValue(181.2)      // Value
/// StringValue("Age")    // Key
/// IntegerValue(28)      // Value
/// EndDictionary
/// ```
#[derive(Clone, Debug, PartialEq)]
pub enum PlistEvent {
    // While the length of an array or dict cannot be feasably greater than max(usize) this better
    // conveys the concept of an effectively unbounded event stream.
    StartArray(Option<u64>),
    EndArray,

    StartDictionary(Option<u64>),
    EndDictionary,

    BooleanValue(bool),
    DataValue(Vec<u8>),
    DateValue(Date),
    IntegerValue(i64),
    RealValue(f64),
    StringValue(String),
}

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

#[derive(Debug)]
pub enum Error {
    InvalidData,
    UnexpectedEof,
    Io(IoError),
    Serde(String),
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidData => "invalid data",
            Error::UnexpectedEof => "unexpected eof",
            Error::Io(ref err) => err.description(),
            Error::Serde(ref err) => &err,
        }
    }

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

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref err) => err.fmt(fmt),
            _ => <Self as ::std::error::Error>::description(self).fmt(fmt),
        }
    }
}

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

pub struct EventReader<R: Read + Seek>(EventReaderInner<R>);

enum EventReaderInner<R: Read + Seek> {
    Uninitialized(Option<R>),
    Xml(xml::EventReader<R>),
    Binary(binary::EventReader<R>),
}

impl<R: Read + Seek> EventReader<R> {
    pub fn new(reader: R) -> EventReader<R> {
        EventReader(EventReaderInner::Uninitialized(Some(reader)))
    }

    fn is_binary(reader: &mut R) -> Result<bool> {
        reader.seek(SeekFrom::Start(0))?;
        let mut magic = [0; 8];
        reader.read(&mut magic)?;
        reader.seek(SeekFrom::Start(0))?;

        Ok(if &magic == b"bplist00" { true } else { false })
    }
}

impl<R: Read + Seek> Iterator for EventReader<R> {
    type Item = Result<PlistEvent>;

    fn next(&mut self) -> Option<Result<PlistEvent>> {
        let mut reader = match self.0 {
            EventReaderInner::Xml(ref mut parser) => return parser.next(),
            EventReaderInner::Binary(ref mut parser) => return parser.next(),
            EventReaderInner::Uninitialized(ref mut reader) => reader.take().unwrap(),
        };

        let event_reader = match EventReader::is_binary(&mut reader) {
            Ok(true) => EventReaderInner::Binary(binary::EventReader::new(reader)),
            Ok(false) => EventReaderInner::Xml(xml::EventReader::new(reader)),
            Err(err) => {
                ::std::mem::replace(&mut self.0, EventReaderInner::Uninitialized(Some(reader)));
                return Some(Err(err));
            }
        };

        ::std::mem::replace(&mut self.0, event_reader);

        self.next()
    }
}

pub trait EventWriter {
    fn write(&mut self, event: &PlistEvent) -> Result<()>;
}

fn u64_to_usize(len_u64: u64) -> Result<usize> {
    let len = len_u64 as usize;
    if len as u64 != len_u64 {
        return Err(Error::InvalidData); // Too long
    }
    Ok(len)
}

fn u64_option_to_usize(len: Option<u64>) -> Result<Option<usize>> {
    match len {
        Some(len) => Ok(Some(u64_to_usize(len)?)),
        None => Ok(None),
    }
}
<|endoftext|>


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

extern crate rustc_serialize;

mod macrogen;
mod lang;
mod error;
mod localizer;

pub use localizer::Localizer;
<commit_msg>Add crate documentation<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! A library to localize strings, translating them according to runtime options.
//!
//! Basically, this library allows your project to generate a `lformat!` macro, that behaves
//! similarly to `format!`, except the message string (the first argument) might get translated
//! (if you can find the appropriate string for the language).
//!
//! # Usage
//!
//! First, you'll need to add the following to your `Cargo.toml` file:
//!
//! ```toml, no_run
//! build = "build.rs"
//!
//! [build-dependencies]
//! crowbook-localize = "0.0.2"
//!
//! [dependencies]
//! lazy_static = "0.2" # the generated file needs `lazy_static!`
//! ```
//!
//! You'll then need to create the `build.rs` file, which can look like this:
//!
//! ```rust, no_run
//! extern crate crowbook_localize;
//! use crowbook_localize::Localizer;
//!
//! fn main() {
//!     let mut localizer = Localizer::new();
//!
//!     localizer.write_macro_file(concat!(env!("CARGO_MANIFEST_DIR"), "/src/lib/localize_macros.rs")).unwrap();
//! }
//! ```
//!
//! This way, a `localize_macros.rs` file will be created at build time in `src/lib`.
//! To use it, the last step is to modify your `src/lib/lib.rs` file:
//!
//! ```rust, no_run
//! #[macro_use] extern crate lazy_static;
//! #[macro_use] mod localize_macros;
//! ```
//!
//! Once this is done, you can start replacing your calls to `format!` with calls to `lformat!`.
//!
//! In order to get translation, you'll need to actually translate the strings in separate
//! files, and set your `build.rs` to load them.
//!
//! E.g., if you have the following code:
//!
//! ```rust, no_run
//! println!("{}", lformat!("Hello, world!"));
//! ```
//! and you want it translated in french, you'll have to create a `lang/fr.mo` file containing:
//!
//! ```text, no_run
//! msgid "Hello, world!";
//! msgstr "Bonjour le monde !";
//! ```
//!
//! And load it in your `build.rs` file:
//!
//! ```rust, no_run
//! let mut localizer = Localizer::new();
//! localizer.add_lang("fr", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/fr.mo"))).unwrap();
//! localizer.write_macro_file("...");
//! ```
//!
//! Once *this* is done, you can use the `localize_macros::set_lang` function
//! to switch the language at runtime:
//!
//! ```rust, no_run
//! use localize_macros::set_lang;
//! set_lang("en");
//! println!("{}", lformat!("Hello, world!")); // prints "Hello, world!"
//! set_lang("fr");
//! println!("{}", lformat!("Hello, world!")); // prints "Bonjour le monde !"
//! ```
//!
//! # Warning
//!
//! In case the complexity of the operation didn't discourage you, I should warn you
//! that this library is highly experimental at this time.

extern crate rustc_serialize;

mod macrogen;
mod lang;
mod error;
mod localizer;

pub use error::{Result, Error};
pub use localizer::Localizer;
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! Window abstraction

extern crate libc;
extern crate input;

use input::Input;

/// The type of an OpenGL function address.
pub type ProcAddress = *const libc::c_void;

/// Size in pixels.
#[derive(Copy, Clone)]
pub struct Size {
    /// The width in pixels.
    pub width: u32,
    /// The height in pixels.
    pub height: u32,
}

/// Required to use the event loop.
pub trait Window {
    /// The event type emitted by `poll_event`
    type Event;

    /// Returns true if window should close.
    fn should_close(&self) -> bool;

    /// Gets the size of the window in user coordinates.
    fn size(&self) -> Size;

    /// Swaps render buffers.
    fn swap_buffers(&mut self);

    /// Polls event from window.
    fn poll_event(&mut self) -> Option<Self::Event>;
}

/// Implemented by fully supported window back-ends.
pub trait AdvancedWindow: Window + Sized {
    /// Gets a copy of the title of the window.
    fn get_title(&self) -> String;

    /// Sets the title of the window.
    fn set_title(&mut self, value: String);

    /// Sets title on window.
    fn title(mut self, value: String) -> Self {
        self.set_title(value);
        self
    }

    /// Gets whether to exit when pressing esc.
    fn get_exit_on_esc(&self) -> bool;

    /// Sets whether to exit when pressing esc.
    fn set_exit_on_esc(&mut self, value: bool);

    /// Sets whether to exit when pressing esc.
    fn exit_on_esc(mut self, value: bool) -> Self {
        self.set_exit_on_esc(value);
        self
    }

    /// Sets whether to capture/grab cursor.
    /// This is used to lock and hide cursor to the window,
    /// for example in a first-person shooter game.
    fn set_capture_cursor(&mut self, value: bool);

    /// Sets whether to capture/grab cursor (see `set_capture_cursor`).
    fn capture_cursor(mut self, value: bool) -> Self {
        self.set_capture_cursor(value);
        self
    }

    /// Gets draw size of the window.
    /// This is equal to the size of the frame buffer of the inner window,
    /// excluding the title bar and borders.
    fn draw_size(&self) -> Size;
}

/// Trait for OpenGL specific operations.
pub trait OpenGLWindow: Window {
    /// Returns the address of an OpenGL function if it exist, else returns null pointer.
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress;

    /// Returns true if this context is the current context.
    fn is_current(&self) -> bool;

    /// Make this context current.
    fn make_current(&mut self);
}

/// Settings for window behavior.
pub struct WindowSettings {
    /// Title of the window.
    title: String,
    /// The size of the window.
    size: Size,
    /// Number samples per pixel (anti-aliasing).
    samples: u8,
    /// If true, the window is fullscreen.
    fullscreen: bool,
    /// If true, exit when pressing Esc.
    exit_on_esc: bool,
}

impl WindowSettings {
    /// Creates window settings with defaults.
    /// - samples: 0
    /// - fullscreen: false
    /// - exit_on_esc: false
    pub fn new(title: String, size: Size) -> WindowSettings {
        WindowSettings {
            title: title,
            size: size,
            samples: 0,
            fullscreen: false,
            exit_on_esc: false,
        }
    }

    /// Gets title.
    pub fn get_title(&self) -> String { self.title.clone() }

    /// Sets title.
    pub fn title(mut self, value: String) -> Self {
        self.title = value;
        self
    }

    /// Gets size.
    pub fn get_size(&self) -> Size { self.size }

    /// Sets size.
    pub fn size(mut self, value: Size) -> Self {
        self.size = value;
        self
    }

    /// Gets fullscreen.
    pub fn get_fullscreen(&self) -> bool { self.fullscreen }

    /// Sets fullscreen.
    pub fn fullscreen(mut self, value: bool) -> Self {
        self.fullscreen = value;
        self
    }

    /// Gets exit on esc.
    pub fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }

    /// Sets exit on esc.
    pub fn exit_on_esc(mut self, value: bool) -> Self {
        self.exit_on_esc = value;
        self
    }

    /// Gets samples.
    pub fn get_samples(&self) -> u8 { self.samples }

    /// Sets samples.
    pub fn samples(mut self, value: u8) -> Self {
        self.samples = value;
        self
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: WindowSettings) -> NoWindow {
        let title = settings.title.clone();
        NoWindow {
            should_close: false,
            title: title,
        }
    }
}

impl Window for NoWindow {
    type Event = Input;
    fn should_close(&self) -> bool { self.should_close }
    fn size(&self) -> Size { Size { width: 0, height: 0 } }
    fn swap_buffers(&mut self) {}
    fn poll_event(&mut self) -> Option<Input> { None }
}

impl AdvancedWindow for NoWindow {
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) { self.title = value; }
    fn get_exit_on_esc(&self) -> bool { false }
    fn set_exit_on_esc(&mut self, _value: bool) {}
    fn set_capture_cursor(&mut self, _value: bool) {}
    fn draw_size(&self) -> Size { self.size() }
}
<commit_msg>Moved `draw_size()` from `AdvancedWindow` trait to `Window` trait.<commit_after>#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! Window abstraction

extern crate libc;
extern crate input;

use input::Input;

/// The type of an OpenGL function address.
pub type ProcAddress = *const libc::c_void;

/// Size in pixels.
#[derive(Copy, Clone)]
pub struct Size {
    /// The width in pixels.
    pub width: u32,
    /// The height in pixels.
    pub height: u32,
}

/// Required to use the event loop.
pub trait Window {
    /// The event type emitted by `poll_event`
    type Event;

    /// Returns true if window should close.
    fn should_close(&self) -> bool;

    /// Gets the size of the window in user coordinates.
    fn size(&self) -> Size;

    /// Swaps render buffers.
    fn swap_buffers(&mut self);

    /// Polls event from window.
    fn poll_event(&mut self) -> Option<Self::Event>;

    /// Gets draw size of the window.
    /// This is equal to the size of the frame buffer of the inner window,
    /// excluding the title bar and borders.
    fn draw_size(&self) -> Size;
}

/// Implemented by fully supported window back-ends.
pub trait AdvancedWindow: Window + Sized {
    /// Gets a copy of the title of the window.
    fn get_title(&self) -> String;

    /// Sets the title of the window.
    fn set_title(&mut self, value: String);

    /// Sets title on window.
    fn title(mut self, value: String) -> Self {
        self.set_title(value);
        self
    }

    /// Gets whether to exit when pressing esc.
    fn get_exit_on_esc(&self) -> bool;

    /// Sets whether to exit when pressing esc.
    fn set_exit_on_esc(&mut self, value: bool);

    /// Sets whether to exit when pressing esc.
    fn exit_on_esc(mut self, value: bool) -> Self {
        self.set_exit_on_esc(value);
        self
    }

    /// Sets whether to capture/grab cursor.
    /// This is used to lock and hide cursor to the window,
    /// for example in a first-person shooter game.
    fn set_capture_cursor(&mut self, value: bool);

    /// Sets whether to capture/grab cursor (see `set_capture_cursor`).
    fn capture_cursor(mut self, value: bool) -> Self {
        self.set_capture_cursor(value);
        self
    }
}

/// Trait for OpenGL specific operations.
pub trait OpenGLWindow: Window {
    /// Returns the address of an OpenGL function if it exist, else returns null pointer.
    fn get_proc_address(&mut self, proc_name: &str) -> ProcAddress;

    /// Returns true if this context is the current context.
    fn is_current(&self) -> bool;

    /// Make this context current.
    fn make_current(&mut self);
}

/// Settings for window behavior.
pub struct WindowSettings {
    /// Title of the window.
    title: String,
    /// The size of the window.
    size: Size,
    /// Number samples per pixel (anti-aliasing).
    samples: u8,
    /// If true, the window is fullscreen.
    fullscreen: bool,
    /// If true, exit when pressing Esc.
    exit_on_esc: bool,
}

impl WindowSettings {
    /// Creates window settings with defaults.
    /// - samples: 0
    /// - fullscreen: false
    /// - exit_on_esc: false
    pub fn new(title: String, size: Size) -> WindowSettings {
        WindowSettings {
            title: title,
            size: size,
            samples: 0,
            fullscreen: false,
            exit_on_esc: false,
        }
    }

    /// Gets title.
    pub fn get_title(&self) -> String { self.title.clone() }

    /// Sets title.
    pub fn title(mut self, value: String) -> Self {
        self.title = value;
        self
    }

    /// Gets size.
    pub fn get_size(&self) -> Size { self.size }

    /// Sets size.
    pub fn size(mut self, value: Size) -> Self {
        self.size = value;
        self
    }

    /// Gets fullscreen.
    pub fn get_fullscreen(&self) -> bool { self.fullscreen }

    /// Sets fullscreen.
    pub fn fullscreen(mut self, value: bool) -> Self {
        self.fullscreen = value;
        self
    }

    /// Gets exit on esc.
    pub fn get_exit_on_esc(&self) -> bool { self.exit_on_esc }

    /// Sets exit on esc.
    pub fn exit_on_esc(mut self, value: bool) -> Self {
        self.exit_on_esc = value;
        self
    }

    /// Gets samples.
    pub fn get_samples(&self) -> u8 { self.samples }

    /// Sets samples.
    pub fn samples(mut self, value: u8) -> Self {
        self.samples = value;
        self
    }
}

/// An implementation of Window that runs without a window at all.
pub struct NoWindow {
    should_close: bool,
    title: String,
}

impl NoWindow {
    /// Returns a new `NoWindow`.
    pub fn new(settings: WindowSettings) -> NoWindow {
        let title = settings.title.clone();
        NoWindow {
            should_close: false,
            title: title,
        }
    }
}

impl Window for NoWindow {
    type Event = Input;
    fn should_close(&self) -> bool { self.should_close }
    fn size(&self) -> Size { Size { width: 0, height: 0 } }
    fn swap_buffers(&mut self) {}
    fn poll_event(&mut self) -> Option<Input> { None }
    fn draw_size(&self) -> Size { self.size() }
}

impl AdvancedWindow for NoWindow {
    fn get_title(&self) -> String { self.title.clone() }
    fn set_title(&mut self, value: String) { self.title = value; }
    fn get_exit_on_esc(&self) -> bool { false }
    fn set_exit_on_esc(&mut self, _value: bool) {}
    fn set_capture_cursor(&mut self, _value: bool) {}
}
<|endoftext|>


<commit_before>//! Access secure credentials at runtime with multiple backends.
//!
//! For more information, see [the
//! homepage](https://github.com/emk/credentials).
//!
//! ```
//! use credentials;
//! use std::env;
//!
//! env::set_var("PASSWORD", "secret");
//! assert_eq!("secret", credentials::var("PASSWORD").unwrap());
//! ```

#[macro_use]
extern crate hyper;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate regex;
extern crate rustc_serialize;
#[cfg(test)] #[macro_use]
extern crate yup_hyper_mock as hyper_mock;

use backend::Backend;
use errors::{BoxedError, CredentialErrorNew, err};
use std::convert::AsRef;
use std::ops::DerefMut;
use std::path::Path;
use std::sync::{Mutex, MutexGuard};

// Be very careful not to export any more of the Secretfile API than
// strictly necessary, because we don't want to stablize too much at this
// point.
pub use secretfile::Secretfile;
pub use errors::{CredentialError, SecretfileError};

#[macro_use]
mod errors;

mod backend;
mod chained;
mod envvar;
mod secretfile;
mod vault;

lazy_static! {
    // Our shared global client, initialized by `lazy_static!` and
    // protected by a Mutex.  There's no reason why we couldn't create a
    // per-thread client API for performance, but this will do for now.
    static ref BACKEND: Mutex<Result<chained::Client, BoxedError>> =
        Mutex::new(chained::Client::new_default());
}

/// Helper function for `var`, below.
fn var_inner(key: &str) -> Result<String, BoxedError> {
    // This is a bit subtle: First we need to lock our Mutex, and then--if
    // our Mutex was poisoned by a panic in another thread--we want to
    // propagate the panic in this thread using `unwrap()`.  See
    // https://doc.rust-lang.org/std/sync/struct.Mutex.html for details.
    let mut backend_result: MutexGuard<_> = BACKEND.lock().unwrap();

    // Deref our MutexGuard as a mutable reference, and then check to see
    // if it was initialized correctly.  I had to tweak the `mut` bits for
    // a few minutes to get this past the borrow checker.
    match backend_result.deref_mut() {
        &mut Ok(ref mut backend) => backend.var(key),
        &mut Err(ref e) => Err(err!("Could not initialize: {}", e)),
    }
}

/// Helper function for `file`, below.
fn file_inner(key: &str) -> Result<String, BoxedError> {
    let mut backend_result: MutexGuard<_> = BACKEND.lock().unwrap();
    match backend_result.deref_mut() {
        &mut Ok(ref mut backend) => backend.file(key),
        &mut Err(ref e) => Err(err!("Could not initialize: {}", e)),
    }
}

/// Fetch the value of an environment-variable-style credential.
pub fn var<S: AsRef<str>>(name: S) -> Result<String, CredentialError> {
    let name_ref = name.as_ref();
    trace!("getting secure credential {}", name_ref);
    var_inner(name.as_ref()).map_err(|e| {
        let err = CredentialError::new(name_ref.to_owned(), e);
        warn!("{}", err);
        err
    })
}

/// Fetch the value of a file-style credential.
pub fn file<S: AsRef<Path>>(path: S) -> Result<String, CredentialError> {
    let path_ref = path.as_ref();
    let path_str = try!(path_ref.to_str().ok_or_else(|| {
        CredentialError::new("(invalid path)".to_owned(),
                             err!("Path is not valid Unicode"))
    }));
    trace!("getting secure credential {}", path_str);
    file_inner(path_str).map_err(|e| {
        let err = CredentialError::new(path_str.to_owned(), e);
        warn!("{}", err);
        err
    })
}

#[cfg(test)]
mod test {
    use std::fs;
    use std::io::Read;
    use super::file;

    #[test]
    fn test_file() {
        // Some arbitrary file contents.
        let mut f = fs::File::open("Cargo.toml").unwrap();
        let mut expected = String::new();
        f.read_to_string(&mut expected).unwrap();

        assert_eq!(expected, file("Cargo.toml").unwrap());
        assert!(file("nosuchfile.txt").is_err());
    }
}
<commit_msg>Export SecretfileKeys iterator<commit_after>//! Access secure credentials at runtime with multiple backends.
//!
//! For more information, see [the
//! homepage](https://github.com/emk/credentials).
//!
//! ```
//! use credentials;
//! use std::env;
//!
//! env::set_var("PASSWORD", "secret");
//! assert_eq!("secret", credentials::var("PASSWORD").unwrap());
//! ```

#[macro_use]
extern crate hyper;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate regex;
extern crate rustc_serialize;
#[cfg(test)] #[macro_use]
extern crate yup_hyper_mock as hyper_mock;

use backend::Backend;
use errors::{BoxedError, CredentialErrorNew, err};
use std::convert::AsRef;
use std::ops::DerefMut;
use std::path::Path;
use std::sync::{Mutex, MutexGuard};

// Be very careful not to export any more of the Secretfile API than
// strictly necessary, because we don't want to stablize too much at this
// point.
pub use secretfile::{Secretfile, SecretfileKeys};
pub use errors::{CredentialError, SecretfileError};

#[macro_use]
mod errors;

mod backend;
mod chained;
mod envvar;
mod secretfile;
mod vault;

lazy_static! {
    // Our shared global client, initialized by `lazy_static!` and
    // protected by a Mutex.  There's no reason why we couldn't create a
    // per-thread client API for performance, but this will do for now.
    static ref BACKEND: Mutex<Result<chained::Client, BoxedError>> =
        Mutex::new(chained::Client::new_default());
}

/// Helper function for `var`, below.
fn var_inner(key: &str) -> Result<String, BoxedError> {
    // This is a bit subtle: First we need to lock our Mutex, and then--if
    // our Mutex was poisoned by a panic in another thread--we want to
    // propagate the panic in this thread using `unwrap()`.  See
    // https://doc.rust-lang.org/std/sync/struct.Mutex.html for details.
    let mut backend_result: MutexGuard<_> = BACKEND.lock().unwrap();

    // Deref our MutexGuard as a mutable reference, and then check to see
    // if it was initialized correctly.  I had to tweak the `mut` bits for
    // a few minutes to get this past the borrow checker.
    match backend_result.deref_mut() {
        &mut Ok(ref mut backend) => backend.var(key),
        &mut Err(ref e) => Err(err!("Could not initialize: {}", e)),
    }
}

/// Helper function for `file`, below.
fn file_inner(key: &str) -> Result<String, BoxedError> {
    let mut backend_result: MutexGuard<_> = BACKEND.lock().unwrap();
    match backend_result.deref_mut() {
        &mut Ok(ref mut backend) => backend.file(key),
        &mut Err(ref e) => Err(err!("Could not initialize: {}", e)),
    }
}

/// Fetch the value of an environment-variable-style credential.
pub fn var<S: AsRef<str>>(name: S) -> Result<String, CredentialError> {
    let name_ref = name.as_ref();
    trace!("getting secure credential {}", name_ref);
    var_inner(name.as_ref()).map_err(|e| {
        let err = CredentialError::new(name_ref.to_owned(), e);
        warn!("{}", err);
        err
    })
}

/// Fetch the value of a file-style credential.
pub fn file<S: AsRef<Path>>(path: S) -> Result<String, CredentialError> {
    let path_ref = path.as_ref();
    let path_str = try!(path_ref.to_str().ok_or_else(|| {
        CredentialError::new("(invalid path)".to_owned(),
                             err!("Path is not valid Unicode"))
    }));
    trace!("getting secure credential {}", path_str);
    file_inner(path_str).map_err(|e| {
        let err = CredentialError::new(path_str.to_owned(), e);
        warn!("{}", err);
        err
    })
}

#[cfg(test)]
mod test {
    use std::fs;
    use std::io::Read;
    use super::file;

    #[test]
    fn test_file() {
        // Some arbitrary file contents.
        let mut f = fs::File::open("Cargo.toml").unwrap();
        let mut expected = String::new();
        f.read_to_string(&mut expected).unwrap();

        assert_eq!(expected, file("Cargo.toml").unwrap());
        assert!(file("nosuchfile.txt").is_err());
    }
}
<|endoftext|>


<commit_before>#[crate_id = "rustful#0.1-pre"];

#[comment = "RESTful web framework"];
#[license = "MIT"];
#[crate_type = "lib"];
#[crate_type = "rlib"];

#[cfg(test)]
extern crate test;

extern crate collections;
extern crate url;
extern crate time;
extern crate http;

pub use router::Router;
pub use server::Server;
pub use request::Request;
pub use response::Response;

pub mod router;
pub mod server;
pub mod request;
pub mod response;<commit_msg>Made library announce its online documentation<commit_after>#[crate_id = "rustful#0.1-pre"];

#[comment = "RESTful web framework"];
#[license = "MIT"];
#[crate_type = "lib"];
#[crate_type = "rlib"];

#[doc(html_root_url = "http://www.rust-ci.org/Ogeon/rustful/doc/")];

#[cfg(test)]
extern crate test;

extern crate collections;
extern crate url;
extern crate time;
extern crate http;

pub use router::Router;
pub use server::Server;
pub use request::Request;
pub use response::Response;

pub mod router;
pub mod server;
pub mod request;
pub mod response;<|endoftext|>


<commit_before>//! Crate ruma_client_api contains serializable types for the requests and responses for each
//! endpoint in the [Matrix](https://matrix.org/) client API specification. These types can be
//! shared by client and server code.

#![deny(
    missing_copy_implementations,
    missing_debug_implementations,
    missing_docs,
    warnings
)]
#![warn(
    clippy::empty_line_after_outer_attr,
    clippy::expl_impl_clone_on_copy,
    clippy::if_not_else,
    clippy::items_after_statements,
    clippy::match_same_arms,
    clippy::mem_forget,
    clippy::missing_docs_in_private_items,
    clippy::multiple_inherent_impl,
    clippy::mut_mut,
    clippy::needless_borrow,
    clippy::needless_continue,
    clippy::single_match_else,
    clippy::unicode_not_nfc,
    clippy::use_self,
    clippy::used_underscore_binding,
    clippy::wrong_pub_self_convention,
    clippy::wrong_self_convention
)]
// Since we support Rust 1.34.2, we can't apply this suggestion yet
#![allow(clippy::use_self)]

pub mod r0;
pub mod unversioned;
<commit_msg>Remove #![deny(warnings)], #![warn(clippy::…)]<commit_after>//! Crate ruma_client_api contains serializable types for the requests and responses for each
//! endpoint in the [Matrix](https://matrix.org/) client API specification. These types can be
//! shared by client and server code.

#![deny(
    missing_copy_implementations,
    missing_debug_implementations,
    missing_docs
)]
// Since we support Rust 1.34.2, we can't apply this suggestion yet
#![allow(clippy::use_self)]

pub mod r0;
pub mod unversioned;
<|endoftext|>


<commit_before>#![feature(try_from)]
#![feature(test)]

extern crate test;
extern crate websocket;
extern crate futures;
extern crate tokio_core;
extern crate json;
extern crate time;
extern crate bus;

pub mod data;
pub mod actors;
pub mod push;
pub mod error;

#[cfg(test)]
mod tests;

<commit_msg>updating version, removing old stuff<commit_after>extern crate test;
extern crate websocket;
extern crate futures;
extern crate tokio_core;
extern crate json;
extern crate time;
extern crate bus;

pub mod data;
pub mod actors;
pub mod push;
pub mod error;

#[cfg(test)]
mod tests;

<|endoftext|>


<commit_before>extern crate libc;

use std::*;
use libc::*;

#[allow(dead_code, non_camel_case_types)]
mod bladerf;
use bladerf::*;

impl fmt::Debug for Struct_bladerf_devinfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "serial: UNIMPLEMENTED, bus: {}, address: {})", self.usb_bus, self.usb_addr)
    }
}

//#[link(name = "bladerf")]
//extern {
//	fn bladerf_get_device_list(devices: &*mut [Struct_bladerf_devinfo]) -> libc::c_int;
//	fn bladerf_free_device_list(devices: *mut [Struct_bladerf_devinfo]);
//    fn bladerf_set_usb_reset_on_open (enabled: bool);
//}

pub fn get_device_list() -> Result<isize, isize> {

	unsafe{
		let devices: *mut [Struct_bladerf_devinfo] = mem::uninitialized();

		let n = bladerf_get_device_list(&devices) as isize;

		for i in 0..n {
			let serial_ptr: *const i8 = &(*devices)[i as usize].serial[0] as *const i8;
			let serial_string = ffi::CStr::from_ptr(serial_ptr);
			println!("serial: {}, bus: {}, address: {}",
				str::from_utf8(serial_string.to_bytes()).unwrap(),
				(*devices)[i as usize].usb_bus as usize,
				(*devices)[i as usize].usb_addr as usize);
		}

		bladerf_free_device_list(devices);

		if n >= 0 {
			Ok(n)
		} else {
			Err(n)
		}
	}
}

pub fn set_usb_reset_on_open(enabled: bool) {
    unsafe{
    	bladerf_set_usb_reset_on_open(enabled as uint8_t);
    }
}

#[test]
fn discovery() {
	match get_device_list() {
		Ok(devices) => {
			println!("Discovered {} devices", devices);
		},
		Err(code) => {
			println!("Error {} listing devices", code);
			assert!(false);
		}
	}
}
<commit_msg>Playing with function wrappers Need to look into the correct way to create a type safe wrapper<commit_after>extern crate libc;

use std::*;
use libc::*;

#[allow(dead_code, non_camel_case_types)]
mod bladerf;
use bladerf::*;

impl fmt::Debug for Struct_bladerf_devinfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "serial: UNIMPLEMENTED, bus: {}, address: {})", self.usb_bus, self.usb_addr)
    }
}

//#[link(name = "bladerf")]
//extern {
//	fn bladerf_get_device_list(devices: &*mut [Struct_bladerf_devinfo]) -> libc::c_int;
//	fn bladerf_free_device_list(devices: *mut [Struct_bladerf_devinfo]);
//    fn bladerf_set_usb_reset_on_open (enabled: bool);
//}

pub fn get_device_list() -> Result<isize, isize> {

	unsafe{
		let devices: *mut [Struct_bladerf_devinfo] = mem::uninitialized();

		let n = bladerf_get_device_list(&devices) as isize;

		for i in 0..n {
			let serial_ptr: *const i8 = &(*devices)[i as usize].serial[0] as *const i8;
			let serial_string = ffi::CStr::from_ptr(serial_ptr);
			println!("serial: {}, bus: {}, address: {}",
				str::from_utf8(serial_string.to_bytes()).unwrap(),
				(*devices)[i as usize].usb_bus as usize,
				(*devices)[i as usize].usb_addr as usize);
		}

		bladerf_free_device_list(devices);

		if n >= 0 {
			Ok(n)
		} else {
			Err(n)
		}
	}
}

pub fn set_usb_reset_on_open(enabled: bool) {
    unsafe{
    	bladerf_set_usb_reset_on_open(enabled as uint8_t);
    }
}

pub fn open_with_devinfo(devinfo: *mut Struct_bladerf_devinfo) -> Result<isize, isize> {
	unsafe {
		let device: *mut *mut Struct_bladerf = mem::uninitialized();

		let res = bladerf_open_with_devinfo(device, devinfo) as isize;

		if res >= 0 {
			Ok(res)
		} else {
			Err(res)
		}
	}
}

pub fn close_device(device: *mut Struct_bladerf) {
	unsafe {
		bladerf_close(device)
	}
}

#[test]
fn discovery() {
	match get_device_list() {
		Ok(devices) => {
			println!("Discovered {} devices", devices);
		},
		Err(code) => {
			println!("Error {} listing devices", code);
			assert!(false);
		}
	}
}
<|endoftext|>


<commit_before>extern crate regex;

use regex::Regex;

pub fn puzzle(input: &str) -> u32 {
    0
}

pub struct Room {
    name: String,
    sector_id: u32,
    checksum: String,
}

impl Room {
    fn new(description: &str) -> Room {
        let regex = Regex::new(r"
(?P<name>[a-z-])
-
(?P<sector_id>[0-9]+)
\[(?P<checksum>[a-z]{5})\]
").unwrap();

        let caps = regex.captures(description).unwrap();

        Room {
            name: caps.name("name").unwrap().to_string(),
            sector_id: caps.name("sector_id").unwrap().parse().unwrap(),
            checksum: caps.name("checksum").unwrap().to_string(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_extraction() {
        let description = "aaaaa-bbb-z-y-x-123[abxyz]";
        let room = Room::new(description);

        assert_eq!(room.name, "aaaaa-bbb-z-y-x");
        assert_eq!(room.sector_id, 123);
        assert_eq!(room.checksum, "abxyz");
    }
}
<commit_msg>Ah, it's the capturing that's failing<commit_after>extern crate regex;

use regex::Regex;

pub fn puzzle(input: &str) -> u32 {
    0
}

pub struct Room {
    name: String,
    sector_id: u32,
    checksum: String,
}

impl Room {
    fn new(description: &str) -> Room {
        let regex = Regex::new(r"
(?P<name>[a-z-])
-
(?P<sector_id>[0-9]+)
\[(?P<checksum>[a-z]{5})\]
").expect("Regex is invalid");

        let caps = regex.captures(description).expect("Can't capture");

        Room {
            name: caps.name("name").expect("No name").to_string(),
            sector_id: caps.name("sector_id").expect("No sector id").parse().expect("Can't parse"),
            checksum: caps.name("checksum").expect("No checksum").to_string(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_extraction() {
        let description = "aaaaa-bbb-z-y-x-123[abxyz]";
        let room = Room::new(description);

        assert_eq!(room.name, "aaaaa-bbb-z-y-x");
        assert_eq!(room.sector_id, 123);
        assert_eq!(room.checksum, "abxyz");
    }
}
<|endoftext|>


<commit_before>//! A library for reading [SRT Subtitles][1].
//!
//! # Examples
//!
//! ## Reading from string
//!
//! ```
//! use srtparse::parse;
//! let subtitles = parse("1\n00:00:01,100 --> 00:00:02,120\nHello!").unwrap();
//! println!("{:?}", subtitles);
//! ```
//!
//! ## Reading from file
//!
//! ```
//! use srtparse::read_from_file;
//! let subtitles = read_from_file("./data/underworld.srt").unwrap();
//! println!("{:?}", subtitles[0]);
//! ```
//!
//! [1]: https://matroska.org/technical/specs/subtitles/srt.html
#![warn(missing_docs)]
use std::error::Error as StdError;
use std::fmt;
use std::fs::File;
use std::io::{Error as IoError, Read};
use std::path::Path;
use std::result::Result as StdResult;
use std::time::Duration;

const UTF8_BOM: &str = "\u{feff}";

#[derive(Debug)]
enum State {
    Pos,
    Time,
    Text,
}

/// A subtitle item
#[derive(Debug)]
pub struct Subtitle {
    /// A number indicating which subtitle it is in the sequence
    pub pos: usize,
    /// The time that the subtitle should appear
    pub start_time: Duration,
    /// The time that the subtitle should disappear
    pub end_time: Duration,
    /// The subtitle itself
    pub text: String,
}

/// Read subtitles from a string
pub fn parse(source: &str) -> Result<Vec<Subtitle>> {
    let source = source.trim_start_matches(UTF8_BOM).trim().lines();

    let mut result = Vec::new();

    let mut state = State::Pos;

    let mut pos: Option<usize> = None;
    let mut start_time: Option<Duration> = None;
    let mut end_time: Option<Duration> = None;
    let mut text: Option<String> = None;

    macro_rules! push_subtitle {
        ($pos:ident) => {
            result.push(Subtitle {
                pos: $pos,
                start_time: match start_time {
                    Some(val) => val,
                    None => return Err(Error::MissingStartTime),
                },
                end_time: match end_time {
                    Some(val) => val,
                    None => return Err(Error::MissingEndTime),
                },
                text: match text {
                    Some(val) => val,
                    None => return Err(Error::MissingText),
                },
            });
        };
    }

    for line in source {
        match state {
            State::Pos => {
                if let Some(ps) = pos {
                    push_subtitle!(ps);
                    start_time = None;
                    end_time = None;
                    text = None;
                }
                pos = Some(line.parse::<usize>().map_err(|_| Error::BadPosition)?);
                state = State::Time;
            }
            State::Time => {
                let mut parts = line.split("-->");
                start_time = match parts.next() {
                    Some(v) => Some(duration_from_str(v)?),
                    None => None,
                };
                end_time = match parts.next() {
                    Some(v) => Some(duration_from_str(v)?),
                    None => None,
                };
                if parts.next().is_some() {
                    return Err(Error::BadTime);
                }
                state = State::Text;
            }
            State::Text => {
                if line.is_empty() {
                    state = State::Pos;
                } else if let Some(ref mut txt) = text {
                    txt.push('\n');
                    txt.push_str(line);
                } else {
                    text = Some(line.to_string());
                }
            }
        }
    }
    if let Some(ps) = pos {
        push_subtitle!(ps);
    }

    Ok(result)
}

/// Read subtitles from a file
pub fn read_from_file<P: AsRef<Path>>(path: P) -> Result<Vec<Subtitle>> {
    let mut file = File::open(path).map_err(Error::OpenFile)?;
    let mut buf = String::new();
    file.read_to_string(&mut buf).map_err(Error::ReadFile)?;
    parse(&buf)
}

/// Alias for std result
pub type Result<T> = StdResult<T, Error>;

/// Describes all errors that may occur
#[derive(Debug)]
pub enum Error {
    /// An error when parsing subtitle position
    BadPosition,
    /// An error when parsing subtitle time
    BadTime,
    /// Unsupported subtitle time format
    BadTimeFormat,
    /// Subtitle start time is missing
    MissingStartTime,
    /// Subtitle end time is missing
    MissingEndTime,
    /// Subtitle text is missing
    MissingText,
    /// Unable to open a file
    OpenFile(IoError),
    /// Unable to read data from a file
    ReadFile(IoError),
}

impl StdError for Error {
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        match *self {
            Error::OpenFile(ref err) => Some(err),
            Error::ReadFile(ref err) => Some(err),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
        write!(
            out,
            "{}",
            match self {
                Error::BadPosition => "Invalid subtitle position",
                Error::BadTime => "Invalid subtitle time",
                Error::BadTimeFormat => "Invalid subtitle time format",
                Error::MissingStartTime => "Subtitle start time is missing",
                Error::MissingEndTime => "Subtitle end time is missing",
                Error::MissingText => "Subtitle text is missing",
                Error::OpenFile(ref err) => err.description(),
                Error::ReadFile(ref err) => err.description(),
            }
        )
    }
}

macro_rules! parse_time_part {
    ($part:expr) => {{
        match $part {
            Some(val) => val.trim().parse::<u64>().map_err(|_| Error::BadTime)?,
            None => {
                return Err(Error::BadTimeFormat);
            }
        }
    }};
}

fn duration_from_str(time: &str) -> Result<Duration> {
    let mut time = time.split(',');
    let (hours, mut minutes, mut seconds) = match time.next() {
        Some(val) => {
            let mut parts = val.split(':');
            let result = (
                parse_time_part!(parts.next()),
                parse_time_part!(parts.next()),
                parse_time_part!(parts.next()),
            );
            if parts.next().is_some() {
                return Err(Error::BadTimeFormat);
            }
            result
        }
        None => {
            return Err(Error::BadTimeFormat);
        }
    };
    let mut milliseconds = parse_time_part!(time.next());
    if time.next().is_some() {
        return Err(Error::BadTimeFormat);
    }
    minutes += hours * 60;
    seconds += minutes * 60;
    milliseconds += seconds * 1000;
    Ok(Duration::from_millis(milliseconds))
}

#[cfg(test)]
mod tests {
    use std::time::Duration;
    use {parse, read_from_file, Result, UTF8_BOM};

    #[test]
    fn it_works() {
        let source_without_bom = "1
00:00:58,392 --> 00:01:02,563
The war had all but ground to a halt
in the blink of an eye.

2
00:01:04,565 --> 00:01:08,986
Lucian, the most feared and ruthless
leader ever to rule the Lycan clan...

3
00:01:09,070 --> 00:01:11,656
...had finally been killed.

652
01:53:02,325 --> 01:53:06,162
Soon, Marcus will take the throne.
";
        let source_with_bom = format!("{}{}", UTF8_BOM, source_without_bom);

        fn assert_it_works(data: &str) -> Result<()> {
            let result = parse(&data)?;
            assert_eq!(result.len(), 4);
            assert_eq!(result[0].pos, 1);
            assert_eq!(result[0].start_time, Duration::from_millis(58392));
            assert_eq!(result[0].end_time, Duration::from_millis(62563));
            assert_eq!(
                result[0].text,
                "The war had all but ground to a halt\nin the blink of an eye."
            );
            assert_eq!(result[1].pos, 2);
            assert_eq!(result[1].start_time, Duration::from_millis(64565));
            assert_eq!(result[1].end_time, Duration::from_millis(68986));
            assert_eq!(
                result[1].text,
                "Lucian, the most feared and ruthless\nleader ever to rule the Lycan clan..."
            );
            assert_eq!(result[2].pos, 3);
            assert_eq!(result[2].start_time, Duration::from_millis(69070));
            assert_eq!(result[2].end_time, Duration::from_millis(71656));
            assert_eq!(result[2].text, "...had finally been killed.");
            assert_eq!(result[3].pos, 652);
            assert_eq!(result[3].start_time, Duration::from_millis(6_782_325));
            assert_eq!(result[3].end_time, Duration::from_millis(6_786_162));
            assert_eq!(result[3].text, "Soon, Marcus will take the throne.");
            Ok(())
        }

        assert_it_works(&source_without_bom).expect("Failed to parse UTF-8 source without BOM");
        assert_it_works(&source_with_bom).expect("Failed to parse UTF-8 source with BOM");
        let empty = parse("").unwrap();
        assert_eq!(empty.len(), 0);
    }

    #[test]
    fn it_fails_with_bad_position() {
        let err = parse("bad position").unwrap_err().to_string();
        assert_eq!(err, "Invalid subtitle position");
    }

    #[test]
    fn it_fails_with_bad_start_time() {
        let err = parse("1\nbad time").unwrap_err().to_string();
        assert_eq!(err, "Invalid subtitle time");
    }

    #[test]
    fn it_fails_with_bad_end_time() {
        let err = parse("1\n00:00:58,392 --> bad end time")
            .unwrap_err()
            .to_string();
        assert_eq!(err, "Invalid subtitle time");
    }

    #[test]
    fn it_fails_with_bad_time_format() {
        let err = parse("1\n00:00:00:00").unwrap_err().to_string();
        assert_eq!(err, "Invalid subtitle time format");
    }

    #[test]
    fn it_fails_with_extra_time() {
        let err = parse("1\n00:00:58,392 --> 00:01:02,563 -> 00:01:02,563")
            .unwrap_err()
            .to_string();
        assert_eq!(err, "Invalid subtitle time");
    }

    #[test]
    fn it_fails_with_missing_start_time() {
        let err = parse("1").unwrap_err().to_string();
        assert_eq!(err, "Subtitle start time is missing");
    }

    #[test]
    fn it_fails_with_missing_end_time() {
        let err = parse("1\n00:00:58,392").unwrap_err().to_string();
        assert_eq!(err, "Subtitle end time is missing");
    }

    #[test]
    fn it_fails_with_missing_text() {
        let err = parse("1\n00:00:58,392 --> 00:01:02,563")
            .unwrap_err()
            .to_string();
        assert_eq!(err, "Subtitle text is missing");
    }

    #[test]
    fn read_from_file_failed() {
        let err = read_from_file("/file/does/not/exist")
            .unwrap_err()
            .to_string();
        assert_eq!(err, "entity not found");
    }

    #[test]
    fn read_from_file_success() {
        let result = read_from_file("./data/underworld.srt").unwrap();
        assert_eq!(result.len(), 706);

        let first = result.first().unwrap();
        assert_eq!(first.pos, 1);
        assert_eq!(first.start_time, Duration::from_millis(58392));
        assert_eq!(first.end_time, Duration::from_millis(61478));
        assert_eq!(first.text, "Война закончилась в мгновение ока.");

        let last = result.last().unwrap();
        assert_eq!(last.pos, 706);
        assert_eq!(last.start_time, Duration::from_millis(6_801_628));
        assert_eq!(last.end_time, Duration::from_millis(6_804_381));
        assert_eq!(last.text, "... будет объявлена охота.");
    }
}
<commit_msg>Remove use of err.description()<commit_after>//! A library for reading [SRT Subtitles][1].
//!
//! # Examples
//!
//! ## Reading from string
//!
//! ```
//! use srtparse::parse;
//! let subtitles = parse("1\n00:00:01,100 --> 00:00:02,120\nHello!").unwrap();
//! println!("{:?}", subtitles);
//! ```
//!
//! ## Reading from file
//!
//! ```
//! use srtparse::read_from_file;
//! let subtitles = read_from_file("./data/underworld.srt").unwrap();
//! println!("{:?}", subtitles[0]);
//! ```
//!
//! [1]: https://matroska.org/technical/specs/subtitles/srt.html
#![warn(missing_docs)]
use std::error::Error as StdError;
use std::fmt;
use std::fs::File;
use std::io::{Error as IoError, Read};
use std::path::Path;
use std::result::Result as StdResult;
use std::time::Duration;

const UTF8_BOM: &str = "\u{feff}";

#[derive(Debug)]
enum State {
    Pos,
    Time,
    Text,
}

/// A subtitle item
#[derive(Debug)]
pub struct Subtitle {
    /// A number indicating which subtitle it is in the sequence
    pub pos: usize,
    /// The time that the subtitle should appear
    pub start_time: Duration,
    /// The time that the subtitle should disappear
    pub end_time: Duration,
    /// The subtitle itself
    pub text: String,
}

/// Read subtitles from a string
pub fn parse(source: &str) -> Result<Vec<Subtitle>> {
    let source = source.trim_start_matches(UTF8_BOM).trim().lines();

    let mut result = Vec::new();

    let mut state = State::Pos;

    let mut pos: Option<usize> = None;
    let mut start_time: Option<Duration> = None;
    let mut end_time: Option<Duration> = None;
    let mut text: Option<String> = None;

    macro_rules! push_subtitle {
        ($pos:ident) => {
            result.push(Subtitle {
                pos: $pos,
                start_time: match start_time {
                    Some(val) => val,
                    None => return Err(Error::MissingStartTime),
                },
                end_time: match end_time {
                    Some(val) => val,
                    None => return Err(Error::MissingEndTime),
                },
                text: match text {
                    Some(val) => val,
                    None => return Err(Error::MissingText),
                },
            });
        };
    }

    for line in source {
        match state {
            State::Pos => {
                if let Some(ps) = pos {
                    push_subtitle!(ps);
                    start_time = None;
                    end_time = None;
                    text = None;
                }
                pos = Some(line.parse::<usize>().map_err(|_| Error::BadPosition)?);
                state = State::Time;
            }
            State::Time => {
                let mut parts = line.split("-->");
                start_time = match parts.next() {
                    Some(v) => Some(duration_from_str(v)?),
                    None => None,
                };
                end_time = match parts.next() {
                    Some(v) => Some(duration_from_str(v)?),
                    None => None,
                };
                if parts.next().is_some() {
                    return Err(Error::BadTime);
                }
                state = State::Text;
            }
            State::Text => {
                if line.is_empty() {
                    state = State::Pos;
                } else if let Some(ref mut txt) = text {
                    txt.push('\n');
                    txt.push_str(line);
                } else {
                    text = Some(line.to_string());
                }
            }
        }
    }
    if let Some(ps) = pos {
        push_subtitle!(ps);
    }

    Ok(result)
}

/// Read subtitles from a file
pub fn read_from_file<P: AsRef<Path>>(path: P) -> Result<Vec<Subtitle>> {
    let mut file = File::open(path).map_err(Error::OpenFile)?;
    let mut buf = String::new();
    file.read_to_string(&mut buf).map_err(Error::ReadFile)?;
    parse(&buf)
}

/// Alias for std result
pub type Result<T> = StdResult<T, Error>;

/// Describes all errors that may occur
#[derive(Debug)]
pub enum Error {
    /// An error when parsing subtitle position
    BadPosition,
    /// An error when parsing subtitle time
    BadTime,
    /// Unsupported subtitle time format
    BadTimeFormat,
    /// Subtitle start time is missing
    MissingStartTime,
    /// Subtitle end time is missing
    MissingEndTime,
    /// Subtitle text is missing
    MissingText,
    /// Unable to open a file
    OpenFile(IoError),
    /// Unable to read data from a file
    ReadFile(IoError),
}

impl StdError for Error {
    fn source(&self) -> Option<&(dyn StdError + 'static)> {
        match *self {
            Error::OpenFile(ref err) => Some(err),
            Error::ReadFile(ref err) => Some(err),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, out: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::BadPosition => write!(out, "Invalid subtitle position"),
            Error::BadTime => write!(out, "Invalid subtitle time"),
            Error::BadTimeFormat => write!(out, "Invalid subtitle time format"),
            Error::MissingStartTime => write!(out, "Subtitle start time is missing"),
            Error::MissingEndTime => write!(out, "Subtitle end time is missing"),
            Error::MissingText => write!(out, "Subtitle text is missing"),
            Error::OpenFile(ref err) => write!(out, "{}", err),
            Error::ReadFile(ref err) => write!(out, "{}", err),
        }
    }
}

macro_rules! parse_time_part {
    ($part:expr) => {{
        match $part {
            Some(val) => val.trim().parse::<u64>().map_err(|_| Error::BadTime)?,
            None => {
                return Err(Error::BadTimeFormat);
            }
        }
    }};
}

fn duration_from_str(time: &str) -> Result<Duration> {
    let mut time = time.split(',');
    let (hours, mut minutes, mut seconds) = match time.next() {
        Some(val) => {
            let mut parts = val.split(':');
            let result = (
                parse_time_part!(parts.next()),
                parse_time_part!(parts.next()),
                parse_time_part!(parts.next()),
            );
            if parts.next().is_some() {
                return Err(Error::BadTimeFormat);
            }
            result
        }
        None => {
            return Err(Error::BadTimeFormat);
        }
    };
    let mut milliseconds = parse_time_part!(time.next());
    if time.next().is_some() {
        return Err(Error::BadTimeFormat);
    }
    minutes += hours * 60;
    seconds += minutes * 60;
    milliseconds += seconds * 1000;
    Ok(Duration::from_millis(milliseconds))
}

#[cfg(test)]
mod tests {
    use std::time::Duration;
    use {parse, read_from_file, Result, UTF8_BOM};

    #[test]
    fn it_works() {
        let source_without_bom = "1
00:00:58,392 --> 00:01:02,563
The war had all but ground to a halt
in the blink of an eye.

2
00:01:04,565 --> 00:01:08,986
Lucian, the most feared and ruthless
leader ever to rule the Lycan clan...

3
00:01:09,070 --> 00:01:11,656
...had finally been killed.

652
01:53:02,325 --> 01:53:06,162
Soon, Marcus will take the throne.
";
        let source_with_bom = format!("{}{}", UTF8_BOM, source_without_bom);

        fn assert_it_works(data: &str) -> Result<()> {
            let result = parse(&data)?;
            assert_eq!(result.len(), 4);
            assert_eq!(result[0].pos, 1);
            assert_eq!(result[0].start_time, Duration::from_millis(58392));
            assert_eq!(result[0].end_time, Duration::from_millis(62563));
            assert_eq!(
                result[0].text,
                "The war had all but ground to a halt\nin the blink of an eye."
            );
            assert_eq!(result[1].pos, 2);
            assert_eq!(result[1].start_time, Duration::from_millis(64565));
            assert_eq!(result[1].end_time, Duration::from_millis(68986));
            assert_eq!(
                result[1].text,
                "Lucian, the most feared and ruthless\nleader ever to rule the Lycan clan..."
            );
            assert_eq!(result[2].pos, 3);
            assert_eq!(result[2].start_time, Duration::from_millis(69070));
            assert_eq!(result[2].end_time, Duration::from_millis(71656));
            assert_eq!(result[2].text, "...had finally been killed.");
            assert_eq!(result[3].pos, 652);
            assert_eq!(result[3].start_time, Duration::from_millis(6_782_325));
            assert_eq!(result[3].end_time, Duration::from_millis(6_786_162));
            assert_eq!(result[3].text, "Soon, Marcus will take the throne.");
            Ok(())
        }

        assert_it_works(&source_without_bom).expect("Failed to parse UTF-8 source without BOM");
        assert_it_works(&source_with_bom).expect("Failed to parse UTF-8 source with BOM");
        let empty = parse("").unwrap();
        assert_eq!(empty.len(), 0);
    }

    #[test]
    fn it_fails_with_bad_position() {
        let err = parse("bad position").unwrap_err().to_string();
        assert_eq!(err, "Invalid subtitle position");
    }

    #[test]
    fn it_fails_with_bad_start_time() {
        let err = parse("1\nbad time").unwrap_err().to_string();
        assert_eq!(err, "Invalid subtitle time");
    }

    #[test]
    fn it_fails_with_bad_end_time() {
        let err = parse("1\n00:00:58,392 --> bad end time")
            .unwrap_err()
            .to_string();
        assert_eq!(err, "Invalid subtitle time");
    }

    #[test]
    fn it_fails_with_bad_time_format() {
        let err = parse("1\n00:00:00:00").unwrap_err().to_string();
        assert_eq!(err, "Invalid subtitle time format");
    }

    #[test]
    fn it_fails_with_extra_time() {
        let err = parse("1\n00:00:58,392 --> 00:01:02,563 -> 00:01:02,563")
            .unwrap_err()
            .to_string();
        assert_eq!(err, "Invalid subtitle time");
    }

    #[test]
    fn it_fails_with_missing_start_time() {
        let err = parse("1").unwrap_err().to_string();
        assert_eq!(err, "Subtitle start time is missing");
    }

    #[test]
    fn it_fails_with_missing_end_time() {
        let err = parse("1\n00:00:58,392").unwrap_err().to_string();
        assert_eq!(err, "Subtitle end time is missing");
    }

    #[test]
    fn it_fails_with_missing_text() {
        let err = parse("1\n00:00:58,392 --> 00:01:02,563")
            .unwrap_err()
            .to_string();
        assert_eq!(err, "Subtitle text is missing");
    }

    #[test]
    fn read_from_file_failed() {
        let err = read_from_file("/file/does/not/exist")
            .unwrap_err()
            .to_string();
        assert_eq!(err, "entity not found");
    }

    #[test]
    fn read_from_file_success() {
        let result = read_from_file("./data/underworld.srt").unwrap();
        assert_eq!(result.len(), 706);

        let first = result.first().unwrap();
        assert_eq!(first.pos, 1);
        assert_eq!(first.start_time, Duration::from_millis(58392));
        assert_eq!(first.end_time, Duration::from_millis(61478));
        assert_eq!(first.text, "Война закончилась в мгновение ока.");

        let last = result.last().unwrap();
        assert_eq!(last.pos, 706);
        assert_eq!(last.start_time, Duration::from_millis(6_801_628));
        assert_eq!(last.end_time, Duration::from_millis(6_804_381));
        assert_eq!(last.text, "... будет объявлена охота.");
    }
}
<|endoftext|>