<commit_before>//! Library for manipulating Game Maker Studio's "data.win" (GEN8) data files.

#![feature(read_exact, associated_consts, associated_type_defaults)]
#![warn(missing_docs, trivial_casts, trivial_numeric_casts)]

#[macro_use]
extern crate quick_error;
extern crate byteorder;
#[macro_use]
extern crate log;

mod gamedata_io;

pub use gamedata_io::{ReadError, StringReadError};

use std::io::{self, Read, Write};
use std::path;

/// The data of a Game Maker Studio game.
///
/// This is the collective information acquired from "data.win".
pub struct GameData {
    metadata: MetaData,
    options: Options,
    extn: Extn,
    /// The sounds of the game.
    pub sounds: Sounds,
    audio_groups: Option<AudioGroups>,
    /// The sprites of the game.
    pub sprites: Sprites,
    backgrounds: Backgrounds,
    paths: Paths,
    scripts: Scripts,
    shaders: Shaders,
    /// The fonts of the game.
    pub fonts: Fonts,
    timelines: Timelines,
    objects: Objects,
    rooms: Rooms,
    dafl: Dafl,
    tpag: Tpag,
    code: Code,
    variables: Variables,
    functions: Functions,
    /// The strings of the game.
    pub strings: Strings,
    textures: Textures,
    audio: Audio,
}

/// A reader that satisfies the requirements for reading a GameData.
pub trait GameDataRead: Read + io::Seek {}
impl<T: Read + io::Seek> GameDataRead for T {}
/// A writer that satisfies the requirements for writing a GameData.
pub trait GameDataWrite: Write + io::Seek {}
impl<T: Write + io::Seek> GameDataWrite for T {}

impl GameData {
    /// Reads a GameData from a reader.
    pub fn from_reader<R: GameDataRead>(reader: &mut R) -> Result<GameData, ReadError> {
        gamedata_io::read(reader)
    }
    /// Reads a GameData from a file.
    pub fn from_file<P: AsRef<path::Path>>(path: &P) -> Result<GameData, ReadError> {
        use std::fs::File;
        use std::io::BufReader;
        let file = try!(File::open(path));
        GameData::from_reader(&mut BufReader::new(file))
    }
    /// Writes self to a writer.
    pub fn write_to_writer<W: GameDataWrite>(&self, writer: &mut W) -> io::Result<()> {
        gamedata_io::write(self, writer)
    }
    /// Writes self to a file.
    pub fn save_to_file<P: AsRef<path::Path>>(&self, path: &P) -> io::Result<()> {
        use std::fs::File;
        use std::io::BufWriter;
        let file = try!(File::create(path));
        self.write_to_writer(&mut BufWriter::new(file))
    }
    /// Returns the window width of the game.
    pub fn window_width(&self) -> u32 {
        self.metadata.window_width
    }
    /// Returns the window height of the game.
    pub fn window_height(&self) -> u32 {
        self.metadata.window_height
    }
    /// Sets the window dimensions of the game.
    pub fn set_window_dimensions(&mut self, width: u32, height: u32) {
        self.metadata.window_width = width;
        self.metadata.window_height = height;
    }
    /// Returns the window title of the game.
    pub fn window_title(&self) -> &str {
        &self.strings.strings[self.metadata.window_title_index]
    }
    /// Sets the window title of the game.
    pub fn set_window_title<S: Into<String>>(&mut self, new: S) {
        self.strings.strings[self.metadata.window_title_index] = new.into();
    }
}

/// Contains various metadata, for example, the window width/height/title.
struct MetaData {
    unk1: u32, // Purpose unknown
    game_id_1_index: usize, // Some kind of game id
    default_index: usize, // Points to "Default"
    unk2: u32,
    unk3: u32,
    unk4: u32,
    unk5: u32,
    unk6: u32,
    unk7: u32,
    unk8: u32,
    game_id_2_index: usize, // Some kind of game id, identical to game_id_1
    unk9: u32,
    unk10: u32,
    unk11: u32,
    unk12: u32,
    window_width: u32,
    window_height: u32,
    unk13: u32,
    unk14: u32,
    unk15: u32,
    unk16: u32,
    unk17: u32,
    unk18: u32,
    unk19: u32,
    unk20: u32,
    window_title_index: usize,
    unknown: Vec<u32>,
}

/// Game Maker project Options
struct Options {
    unk1: u32, // Unknown
    unk2: u32, // Unknown
    icon_offset: u32, // Points to texture data (icon?)
    unk3: u32,
    unk4: u32,
    unk5: u32,
    unk6: u32,
    unk7: u32,
    unk8: u32,
    unk9: u32,
    unk10: u32,
    unk11: u32,
    unk12: u32,
    unk13: u32,
    unk14: u32,
    unk15: u32,
    constant1_name_index: usize, // Offset of the name of this constant in the string table
    constant2_name_index: usize, // Offset of the name of this constant in the string table
    constant3_name_index: usize, // Offset of the name of this constant in the string table
    constant4_name_index: usize, // Offset of the name of this constant in the string table
    constant5_name_index: usize, // Offset of the name of this constant in the string table
    constant6_name_index: usize, // Offset of the name of this constant in the string table
    constant7_name_index: usize, // Offset of the name of this constant in the string table
    constant8_name_index: usize, // Offset of the name of this constant in the string table
    constant9_name_index: usize, // Offset of the name of this constant in the string table
    constant10_name_index: usize, // Offset of the name of this constant in the string table
    constant11_name_index: usize, // Offset of the name of this constant in the string table
    constant12_name_index: usize, // Offset of the name of this constant in the string table
    constant13_name_index: usize, // Offset of the name of this constant in the string table
    constant14_name_index: usize, // Offset of the name of this constant in the string table
}

/// Purpose unknown.
struct Extn {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A game maker sound.
#[derive(Clone, Copy)]
pub struct Sound {
    /// Index of the name in the string table.
    pub name_index: usize,
    unk1: u32,
    /// Index of the extension in the string table.
    pub ext_index: usize,
    /// Index of the filename in the string table.
    pub filename_index: usize,
    unk2: u32,
    unk3: u32,
    unk4: u32,
    unk5: u32,
    unk6: u32,
}

/// A collection of sounds.
pub struct Sounds {
    /// The sounds.
    pub sounds: Vec<Sound>,
}

/// Collection of audio groups. Not present in all games.
struct AudioGroups {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A game maker sprite.
pub struct Sprite {
    /// The index of the resource name in the string table.
    pub name_index: usize,
    /// The width of the sprite
    pub width: u32,
    /// The height of the sprite
    pub height: u32,
    unknown: Vec<u8>,
}

/// A collection of sprites.
pub struct Sprites {
    /// The sprites
    pub sprites: Vec<Sprite>,
}

/// A collection of backgrounds.
struct Backgrounds {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A collection of paths.
struct Paths {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A game maker script.
struct Script {
    /// Index of the name of the script in the string table
    pub name_index: usize,
    unknown: u32, // Unknown
}

/// A collection of scripts.
struct Scripts {
    pub scripts: Vec<Script>,
}

/// A collection of shaders.
struct Shaders {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A font.
#[derive(Clone)]
pub struct Font {
    /// Index of the font's resource name in the string table.
    pub name_index: usize,
    /// Index of the font's font name in the string table.
    pub font_name_index: usize,
    /// Point size of the font.
    pub point_size: u32,
    data: Vec<u8>,
}

/// A collection of fonts.
pub struct Fonts {
    /// The fonts.
    pub fonts: Vec<Font>,
    unknown: Vec<u8>, // Unknown trailing data
}

/// A collection of timelines.
struct Timelines {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A collection of objects.
struct Objects {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A collection of rooms.
struct Rooms {
    raw: Vec<u8>, // Data not analyzed yet
}

/// Purpose unknown.
struct Dafl {
    raw: Vec<u8>, // Data not analyzed yet
}

/// Purpose unknown.
struct Tpag {
    raw: Vec<u8>, // Data not analyzed yet
}

/// Something to do with code. Maybe code of scripts?
struct Code {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A game maker variable.
struct Variable {
    /// Index of the name of the variable in the strings section.
    pub name_index: usize,
    unknown: u32, // Purpose unknown. Ranges from 1 to a few thousand.
    code_offset: u32, // Points into the code section
}

/// A collection of variables.
struct Variables {
    pub variables: Vec<Variable>,
}

/// A game maker function.
struct Function {
    /// Index of the name of the function in the strings section.
    pub name_index: usize,
    unknown: u32, // Purpose unknown. Ranges from 1 to a few thousand.
    code_offset: u32, // Points into the code section.
}

/// A collection of functions.
struct Functions {
    pub functions: Vec<Function>,
}

/// A collection of strings.
///
/// All strings are assumed to be valid UTF-8.
pub struct Strings {
    /// The vector holding the strings.
    pub strings: Vec<String>,
}

struct Texture {
    unknown: u32, // Purpose unknown. Always seems to be 1.
    offset: u32, // Offset of data in the texture data
}

/// A collection of textures.
struct Textures {
    pub textures: Vec<Texture>,
    texture_data: Vec<u8>,
}

struct AudioData {
    data: Vec<u8>,
}

/// A collection of audio data.
struct Audio {
    audio: Vec<AudioData>,
    offsets: Vec<u32>, // Audio data is not contiguous, so we need to store relative offsets
    size: u32, // Fuck it
}
<commit_msg>Derive Clone for Sprite<commit_after>//! Library for manipulating Game Maker Studio's "data.win" (GEN8) data files.

#![feature(read_exact, associated_consts, associated_type_defaults)]
#![warn(missing_docs, trivial_casts, trivial_numeric_casts)]

#[macro_use]
extern crate quick_error;
extern crate byteorder;
#[macro_use]
extern crate log;

mod gamedata_io;

pub use gamedata_io::{ReadError, StringReadError};

use std::io::{self, Read, Write};
use std::path;

/// The data of a Game Maker Studio game.
///
/// This is the collective information acquired from "data.win".
pub struct GameData {
    metadata: MetaData,
    options: Options,
    extn: Extn,
    /// The sounds of the game.
    pub sounds: Sounds,
    audio_groups: Option<AudioGroups>,
    /// The sprites of the game.
    pub sprites: Sprites,
    backgrounds: Backgrounds,
    paths: Paths,
    scripts: Scripts,
    shaders: Shaders,
    /// The fonts of the game.
    pub fonts: Fonts,
    timelines: Timelines,
    objects: Objects,
    rooms: Rooms,
    dafl: Dafl,
    tpag: Tpag,
    code: Code,
    variables: Variables,
    functions: Functions,
    /// The strings of the game.
    pub strings: Strings,
    textures: Textures,
    audio: Audio,
}

/// A reader that satisfies the requirements for reading a GameData.
pub trait GameDataRead: Read + io::Seek {}
impl<T: Read + io::Seek> GameDataRead for T {}
/// A writer that satisfies the requirements for writing a GameData.
pub trait GameDataWrite: Write + io::Seek {}
impl<T: Write + io::Seek> GameDataWrite for T {}

impl GameData {
    /// Reads a GameData from a reader.
    pub fn from_reader<R: GameDataRead>(reader: &mut R) -> Result<GameData, ReadError> {
        gamedata_io::read(reader)
    }
    /// Reads a GameData from a file.
    pub fn from_file<P: AsRef<path::Path>>(path: &P) -> Result<GameData, ReadError> {
        use std::fs::File;
        use std::io::BufReader;
        let file = try!(File::open(path));
        GameData::from_reader(&mut BufReader::new(file))
    }
    /// Writes self to a writer.
    pub fn write_to_writer<W: GameDataWrite>(&self, writer: &mut W) -> io::Result<()> {
        gamedata_io::write(self, writer)
    }
    /// Writes self to a file.
    pub fn save_to_file<P: AsRef<path::Path>>(&self, path: &P) -> io::Result<()> {
        use std::fs::File;
        use std::io::BufWriter;
        let file = try!(File::create(path));
        self.write_to_writer(&mut BufWriter::new(file))
    }
    /// Returns the window width of the game.
    pub fn window_width(&self) -> u32 {
        self.metadata.window_width
    }
    /// Returns the window height of the game.
    pub fn window_height(&self) -> u32 {
        self.metadata.window_height
    }
    /// Sets the window dimensions of the game.
    pub fn set_window_dimensions(&mut self, width: u32, height: u32) {
        self.metadata.window_width = width;
        self.metadata.window_height = height;
    }
    /// Returns the window title of the game.
    pub fn window_title(&self) -> &str {
        &self.strings.strings[self.metadata.window_title_index]
    }
    /// Sets the window title of the game.
    pub fn set_window_title<S: Into<String>>(&mut self, new: S) {
        self.strings.strings[self.metadata.window_title_index] = new.into();
    }
}

/// Contains various metadata, for example, the window width/height/title.
struct MetaData {
    unk1: u32, // Purpose unknown
    game_id_1_index: usize, // Some kind of game id
    default_index: usize, // Points to "Default"
    unk2: u32,
    unk3: u32,
    unk4: u32,
    unk5: u32,
    unk6: u32,
    unk7: u32,
    unk8: u32,
    game_id_2_index: usize, // Some kind of game id, identical to game_id_1
    unk9: u32,
    unk10: u32,
    unk11: u32,
    unk12: u32,
    window_width: u32,
    window_height: u32,
    unk13: u32,
    unk14: u32,
    unk15: u32,
    unk16: u32,
    unk17: u32,
    unk18: u32,
    unk19: u32,
    unk20: u32,
    window_title_index: usize,
    unknown: Vec<u32>,
}

/// Game Maker project Options
struct Options {
    unk1: u32, // Unknown
    unk2: u32, // Unknown
    icon_offset: u32, // Points to texture data (icon?)
    unk3: u32,
    unk4: u32,
    unk5: u32,
    unk6: u32,
    unk7: u32,
    unk8: u32,
    unk9: u32,
    unk10: u32,
    unk11: u32,
    unk12: u32,
    unk13: u32,
    unk14: u32,
    unk15: u32,
    constant1_name_index: usize, // Offset of the name of this constant in the string table
    constant2_name_index: usize, // Offset of the name of this constant in the string table
    constant3_name_index: usize, // Offset of the name of this constant in the string table
    constant4_name_index: usize, // Offset of the name of this constant in the string table
    constant5_name_index: usize, // Offset of the name of this constant in the string table
    constant6_name_index: usize, // Offset of the name of this constant in the string table
    constant7_name_index: usize, // Offset of the name of this constant in the string table
    constant8_name_index: usize, // Offset of the name of this constant in the string table
    constant9_name_index: usize, // Offset of the name of this constant in the string table
    constant10_name_index: usize, // Offset of the name of this constant in the string table
    constant11_name_index: usize, // Offset of the name of this constant in the string table
    constant12_name_index: usize, // Offset of the name of this constant in the string table
    constant13_name_index: usize, // Offset of the name of this constant in the string table
    constant14_name_index: usize, // Offset of the name of this constant in the string table
}

/// Purpose unknown.
struct Extn {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A game maker sound.
#[derive(Clone, Copy)]
pub struct Sound {
    /// Index of the name in the string table.
    pub name_index: usize,
    unk1: u32,
    /// Index of the extension in the string table.
    pub ext_index: usize,
    /// Index of the filename in the string table.
    pub filename_index: usize,
    unk2: u32,
    unk3: u32,
    unk4: u32,
    unk5: u32,
    unk6: u32,
}

/// A collection of sounds.
pub struct Sounds {
    /// The sounds.
    pub sounds: Vec<Sound>,
}

/// Collection of audio groups. Not present in all games.
struct AudioGroups {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A game maker sprite.
#[derive(Clone)]
pub struct Sprite {
    /// The index of the resource name in the string table.
    pub name_index: usize,
    /// The width of the sprite
    pub width: u32,
    /// The height of the sprite
    pub height: u32,
    unknown: Vec<u8>,
}

/// A collection of sprites.
pub struct Sprites {
    /// The sprites
    pub sprites: Vec<Sprite>,
}

/// A collection of backgrounds.
struct Backgrounds {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A collection of paths.
struct Paths {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A game maker script.
struct Script {
    /// Index of the name of the script in the string table
    pub name_index: usize,
    unknown: u32, // Unknown
}

/// A collection of scripts.
struct Scripts {
    pub scripts: Vec<Script>,
}

/// A collection of shaders.
struct Shaders {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A font.
#[derive(Clone)]
pub struct Font {
    /// Index of the font's resource name in the string table.
    pub name_index: usize,
    /// Index of the font's font name in the string table.
    pub font_name_index: usize,
    /// Point size of the font.
    pub point_size: u32,
    data: Vec<u8>,
}

/// A collection of fonts.
pub struct Fonts {
    /// The fonts.
    pub fonts: Vec<Font>,
    unknown: Vec<u8>, // Unknown trailing data
}

/// A collection of timelines.
struct Timelines {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A collection of objects.
struct Objects {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A collection of rooms.
struct Rooms {
    raw: Vec<u8>, // Data not analyzed yet
}

/// Purpose unknown.
struct Dafl {
    raw: Vec<u8>, // Data not analyzed yet
}

/// Purpose unknown.
struct Tpag {
    raw: Vec<u8>, // Data not analyzed yet
}

/// Something to do with code. Maybe code of scripts?
struct Code {
    raw: Vec<u8>, // Data not analyzed yet
}

/// A game maker variable.
struct Variable {
    /// Index of the name of the variable in the strings section.
    pub name_index: usize,
    unknown: u32, // Purpose unknown. Ranges from 1 to a few thousand.
    code_offset: u32, // Points into the code section
}

/// A collection of variables.
struct Variables {
    pub variables: Vec<Variable>,
}

/// A game maker function.
struct Function {
    /// Index of the name of the function in the strings section.
    pub name_index: usize,
    unknown: u32, // Purpose unknown. Ranges from 1 to a few thousand.
    code_offset: u32, // Points into the code section.
}

/// A collection of functions.
struct Functions {
    pub functions: Vec<Function>,
}

/// A collection of strings.
///
/// All strings are assumed to be valid UTF-8.
pub struct Strings {
    /// The vector holding the strings.
    pub strings: Vec<String>,
}

struct Texture {
    unknown: u32, // Purpose unknown. Always seems to be 1.
    offset: u32, // Offset of data in the texture data
}

/// A collection of textures.
struct Textures {
    pub textures: Vec<Texture>,
    texture_data: Vec<u8>,
}

struct AudioData {
    data: Vec<u8>,
}

/// A collection of audio data.
struct Audio {
    audio: Vec<AudioData>,
    offsets: Vec<u32>, // Audio data is not contiguous, so we need to store relative offsets
    size: u32, // Fuck it
}
<|endoftext|>


<commit_before>#![feature(collections)]
#![feature(std_misc)]

#[macro_use] mod macros;
#[cfg(feature = "collect_impls")] mod collect_impls;
mod std_impls;

pub trait Collection {
    /// Removes all items from the collection.
    fn clear(&mut self);

    /// Checks if the collection is empty.
    fn is_empty(&self) -> bool { self.len() == 0 }

    /// Returns the number of items in the collection.
    fn len(&self) -> usize;
}

pub trait Map: Collection + MapLookup<<Self as Map>::Key, MapValue=<Self as Map>::Value> {
    /// The map's key type.
    type Key;
    /// The map's value type.
    type Value;

    /// Inserts the given key and value into the map, returning the previous value associated with
    /// the key, or `None` if the map did not already contain the key.
    fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value>;
}

pub trait MapLookup<Q: ?Sized> {
    type MapValue;

    /// Checks if the map contains the given key.
    fn contains_key(&self, key: &Q) -> bool { self.get(key).is_some() }

    /// Returns a reference to the value associated with the given key in the map, or `None` if
    /// the map does not contain the key.
    fn get(&self, key: &Q) -> Option<&Self::MapValue>;

    /// Returns a mutable reference to the value associated with the given key in the map, or
    /// `None` if the map does not contain the key.
    fn get_mut(&mut self, key: &Q) -> Option<&mut Self::MapValue>;

    /// Removes the given key from the map, returning the value associated with it, or `None` if
    /// the map did not contain the key.
    fn remove(&mut self, key: &Q) -> Option<Self::MapValue>;
}

pub trait EntryMap<'a>: Map {
    type Occupied: OccupiedEntry<'a, Value=Self::Value>;
    type Vacant: VacantEntry<'a, Value=Self::Value>;

    /// Returns the given key's corresponding entry in the map for in-place manipulation.
    fn entry(&'a mut self, key: Self::Key) -> Entry<Self::Occupied, Self::Vacant>;
}

pub enum Entry<O, V> {
    Occupied(O),
    Vacant(V),
}

impl<'a, O, V> Entry<O, V> where O: OccupiedEntry<'a>, V: VacantEntry<'a, Value=O::Value> {
    /// Returns a mutable reference to the entry's value if it is occupied, or the vacant entry if
    /// it is vacant.
    pub fn get(self) -> Result<&'a mut O::Value, V> {
        match self {
            Entry::Occupied(e) => Ok(e.into_mut()),
            Entry::Vacant(e) => Err(e),
        }
    }
}

pub trait OccupiedEntry<'a> {
    type Value: 'a;

    /// Returns a reference to the entry's value.
    fn get(&self) -> &Self::Value;

    /// Returns a mutable reference to the entry's value.
    fn get_mut(&mut self) -> &mut Self::Value;

    /// Sets the entry's value to the given one, returning the old value.
    fn insert(&mut self, value: Self::Value) -> Self::Value;

    /// Returns a mutable reference to the entry's value with the lifetime of the map.
    fn into_mut(self) -> &'a mut Self::Value;

    /// Removes the entry, returning its value.
    fn remove(self) -> Self::Value;
}

pub trait VacantEntry<'a> {
    type Value: 'a;

    /// Sets the entry's value to the given one, returning a mutable reference to the value with
    /// the lifetime of the map.
    fn insert(self, value: Self::Value) -> &'a mut Self::Value;
}

pub trait Set: Collection + SetLookup<<Self as Set>::Item> {
    type Item;

    /// Inserts the given item into the set, returning `true` if the set did not already contain
    /// the item.
    fn insert(&mut self, item: Self::Item) -> bool;
}

pub trait SetLookup<Q: ?Sized> {
    /// Checks if the set contains the given item.
    fn contains(&self, item: &Q) -> bool;

    /// Removes the given item from the map, returning `true` if the set contained the item.
    fn remove(&mut self, item: &Q) -> bool;
}
<commit_msg>fix `Set::remove` doc<commit_after>#![feature(collections)]
#![feature(std_misc)]

#[macro_use] mod macros;
#[cfg(feature = "collect_impls")] mod collect_impls;
mod std_impls;

pub trait Collection {
    /// Removes all items from the collection.
    fn clear(&mut self);

    /// Checks if the collection is empty.
    fn is_empty(&self) -> bool { self.len() == 0 }

    /// Returns the number of items in the collection.
    fn len(&self) -> usize;
}

pub trait Map: Collection + MapLookup<<Self as Map>::Key, MapValue=<Self as Map>::Value> {
    /// The map's key type.
    type Key;
    /// The map's value type.
    type Value;

    /// Inserts the given key and value into the map, returning the previous value associated with
    /// the key, or `None` if the map did not already contain the key.
    fn insert(&mut self, key: Self::Key, value: Self::Value) -> Option<Self::Value>;
}

pub trait MapLookup<Q: ?Sized> {
    type MapValue;

    /// Checks if the map contains the given key.
    fn contains_key(&self, key: &Q) -> bool { self.get(key).is_some() }

    /// Returns a reference to the value associated with the given key in the map, or `None` if
    /// the map does not contain the key.
    fn get(&self, key: &Q) -> Option<&Self::MapValue>;

    /// Returns a mutable reference to the value associated with the given key in the map, or
    /// `None` if the map does not contain the key.
    fn get_mut(&mut self, key: &Q) -> Option<&mut Self::MapValue>;

    /// Removes the given key from the map, returning the value associated with it, or `None` if
    /// the map did not contain the key.
    fn remove(&mut self, key: &Q) -> Option<Self::MapValue>;
}

pub trait EntryMap<'a>: Map {
    type Occupied: OccupiedEntry<'a, Value=Self::Value>;
    type Vacant: VacantEntry<'a, Value=Self::Value>;

    /// Returns the given key's corresponding entry in the map for in-place manipulation.
    fn entry(&'a mut self, key: Self::Key) -> Entry<Self::Occupied, Self::Vacant>;
}

pub enum Entry<O, V> {
    Occupied(O),
    Vacant(V),
}

impl<'a, O, V> Entry<O, V> where O: OccupiedEntry<'a>, V: VacantEntry<'a, Value=O::Value> {
    /// Returns a mutable reference to the entry's value if it is occupied, or the vacant entry if
    /// it is vacant.
    pub fn get(self) -> Result<&'a mut O::Value, V> {
        match self {
            Entry::Occupied(e) => Ok(e.into_mut()),
            Entry::Vacant(e) => Err(e),
        }
    }
}

pub trait OccupiedEntry<'a> {
    type Value: 'a;

    /// Returns a reference to the entry's value.
    fn get(&self) -> &Self::Value;

    /// Returns a mutable reference to the entry's value.
    fn get_mut(&mut self) -> &mut Self::Value;

    /// Sets the entry's value to the given one, returning the old value.
    fn insert(&mut self, value: Self::Value) -> Self::Value;

    /// Returns a mutable reference to the entry's value with the lifetime of the map.
    fn into_mut(self) -> &'a mut Self::Value;

    /// Removes the entry, returning its value.
    fn remove(self) -> Self::Value;
}

pub trait VacantEntry<'a> {
    type Value: 'a;

    /// Sets the entry's value to the given one, returning a mutable reference to the value with
    /// the lifetime of the map.
    fn insert(self, value: Self::Value) -> &'a mut Self::Value;
}

pub trait Set: Collection + SetLookup<<Self as Set>::Item> {
    type Item;

    /// Inserts the given item into the set, returning `true` if the set did not already contain
    /// the item.
    fn insert(&mut self, item: Self::Item) -> bool;
}

pub trait SetLookup<Q: ?Sized> {
    /// Checks if the set contains the given item.
    fn contains(&self, item: &Q) -> bool;

    /// Removes the given item from the set, returning `true` if the set contained the item.
    fn remove(&mut self, item: &Q) -> bool;
}
<|endoftext|>


<commit_before>#![allow(unstable)]

use std::ffi::{ CString, c_str_to_bytes};
use std::str::from_utf8;

mod dt;

pub fn dt_hello_world() {
    unsafe {
        let vm = dt::create_vm();
        let code = "(function () { return '12'; })()";
        let c_code = CString::from_slice(code.as_bytes());
        let c_result = dt::eval(vm, c_code.as_ptr());
        // FIXME: CESU-8 to UTF-8 conversion
        // TODO: handle error states
        let result = String::from_str(from_utf8(c_str_to_bytes(&c_result)).ok().unwrap());
        assert_eq!(result.as_slice(), "12");
        dt::destroy_vm(vm);
    }
}

#[test]
fn test_binding() {
    dt_hello_world();
}

#[test]
fn it_works() {
}
<commit_msg>remove dummy test<commit_after>#![allow(unstable)]

use std::ffi::{ CString, c_str_to_bytes};
use std::str::from_utf8;

mod dt;

pub fn dt_hello_world() {
    unsafe {
        let vm = dt::create_vm();
        let code = "(function () { return '12'; })()";
        let c_code = CString::from_slice(code.as_bytes());
        let c_result = dt::eval(vm, c_code.as_ptr());
        // FIXME: CESU-8 to UTF-8 conversion
        // TODO: handle error states
        let result = String::from_str(from_utf8(c_str_to_bytes(&c_result)).ok().unwrap());
        assert_eq!(result.as_slice(), "12");
        dt::destroy_vm(vm);
    }
}

#[test]
fn test_binding() {
    dt_hello_world();
}
<|endoftext|>


<commit_before>extern crate xmltree;
extern crate hyper;
extern crate url;

use hyper::Client;
use hyper::header::Connection;
use std::io::Read;

/// Turns "123" into 123
fn intify(instr: &str) -> u32{
    // TODO: Better error handling
    instr.to_owned().parse::<u32>().unwrap()
}

/// Errors in contacting TheTVDB
#[derive(Debug)]
pub enum TvdbError {
    SeriesNotFound,
    CommunicationError{reason: String},
    DataError{reason: String},
    Cancelled,
}

/// Series ID from TheTVDB.com, along with language
#[derive(Debug,Clone)]
pub struct EpisodeId{
    seriesid: u32,
    lang: String,
}

impl EpisodeId{
    pub fn new(seriesid: u32, lang: &str) -> EpisodeId{
        EpisodeId{
            seriesid: seriesid,
            lang: lang.to_owned(),
        }
    }
}

impl From<u32> for EpisodeId{
    fn from(x: u32) -> Self{
        EpisodeId{seriesid: x, lang: "en".to_owned()}
    }
}

impl From<SeriesSearchResult> for EpisodeId{
    fn from(x: SeriesSearchResult) -> Self{
        EpisodeId{seriesid: x.seriesid, lang: x.language}
    }
}

/// Series info as returned from TheTVDB's series search method:
/// http://www.thetvdb.com/wiki/index.php?title=API:GetSeries
#[derive(Debug,Clone)]
pub struct SeriesSearchResult{
    pub seriesid: u32, // seriesid is preferred over id according to TVDB wiki
    pub seriesname: String,
    pub language: String,
    pub overview: Option<String>,
    pub banner: Option<String>,
    pub imdb_id: Option<String>,
    //pub firstaired: Date,
    pub network: Option<String>,
    pub zap2it_id: Option<String>,
}

/// Base episode record,
/// http://www.thetvdb.com/wiki/index.php?title=API:Base_Episode_Record
#[derive(Debug,Clone)]
pub struct EpisodeInfo{
    pub id: u32, //id
    // Combined_episodenumber
    // Combined_season
    // DVD_chapter
    // DVD_discid
    // DVD_episodenumber
    // DVD_season
    // Director
    // EpImgFlag
    pub episodename: String, // EpisodeName
    // EpisodeNumber
    // FirstAired
    // GuestStars
    // IMDB_ID
    // Language
    // Overview
    // ProductionCode
    // Rating
    // RatingCount
    // SeasonNumber
    // Writer
    // absolute_number
    // airsafter_season
    // airsbefore_episode
    // airsbefore_season
    // filename
    // lastupdated
    // seasonid
    // seriesid
    // thumb_added
    // thumb_height
    // thumb_width
}

/// Main interface
#[derive(Debug,Clone)]
pub struct Tvdb{
    key: String,
}

impl Tvdb{
    /// Initalise API with the given API key. A key can be aquired via
    /// the [API Key Registration page](http://thetvdb.com/?tab=apiregister)
    pub fn new(key: String) -> Tvdb{
        Tvdb{key: key}
    }

    /// Searches for a given series name.
    pub fn search(&self, seriesname: String, lang: String) -> Result<Vec<SeriesSearchResult>, TvdbError>{
        let client = Client::new();

        let params = url::form_urlencoded::serialize([("seriesname", &seriesname), ("language", &lang)].iter());
        let formatted_url = format!("http://thetvdb.com/api/GetSeries.php?{}", params);
        let url = hyper::Url::parse(&formatted_url).ok().expect("invalid URL");
        println!("Getting {}", url);

        let res = client.get(url)
            .header(Connection::close())
            .send();

        let mut res = match res {
            Err(e) => return Err(TvdbError::CommunicationError{reason: "Error contacting TVDB".to_owned()}), // FIXME: http://stackoverflow.com/questions/28911833/error-handling-best-practices
            Ok(r) => r
        };

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        // Parse XML
        let tree = xmltree::Element::parse(body.as_bytes());

        // Convert XML into structs
        let mut results : Vec<SeriesSearchResult> = vec![];

        for child in tree.children.iter(){

            fn get_text(child: &xmltree::Element, x: &str) -> Option<String>{
                child.get_child(x).and_then(|id_child| id_child.text.clone())
            }

            let r = SeriesSearchResult{
                seriesid:   intify(&get_text(child, "seriesid").expect("Search result XML missing 'seriesid' element")),
                seriesname: get_text(child, "SeriesName").expect("Search result XML Missing 'SeriesName' element"),
                language:   get_text(child, "language").expect("Search result XML missing 'language' element"),
                overview:   get_text(child, "Overview"),
                banner:     get_text(child, "banner"),
                imdb_id:    get_text(child, "IMDB_ID"),
                //firstaired: Date,
                network:    get_text(child, "Network"),
                zap2it_id:  get_text(child, "zap2it_id"),
            };

            results.push(r);
        }

        if results.is_empty(){
            return Err(TvdbError::SeriesNotFound);
        }

        return Ok(results);
    }

    fn episode_inner(&self, epid: EpisodeId, season: u32, episode: u32) -> Result<EpisodeInfo, TvdbError>{
        // <mirrorpath>/api/<apikey>/series/{seriesid}/default/{season}/{episode}/{language}.xml

        let client = Client::new();

        let formatted_url = format!("http://thetvdb.com/api/{apikey}/series/{seriesid}/default/{season}/{episode}/{language}.xml",
                                    apikey=self.key,
                                    seriesid=epid.seriesid,
                                    language=epid.lang,
                                    season=season,
                                    episode=episode,
                                    );
        let url = hyper::Url::parse(&formatted_url).ok().expect("invalid URL");
        println!("Getting {}", url);

        // Perform request
        let res = client.get(url)
            .header(Connection::close())
            .send();

        let mut res = match res {
            Err(e) => return Err(TvdbError::CommunicationError{reason: "Error contacting TVDB".to_owned()}), // FIXME: http://stackoverflow.com/questions/28911833/error-handling-best-practices
            Ok(r) => r
        };

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        // Parse XML
        let tree = xmltree::Element::parse(body.as_bytes());
        let root = tree.children.first().unwrap();

        fn get_text(child: &xmltree::Element, x: &str) -> Option<String>{
            child.get_child(x).and_then(|id_child| id_child.text.clone())
        }

        // Convert XML into struct
        Ok(EpisodeInfo{
            id: intify(&get_text(root, "id").unwrap()),
            episodename: get_text(root, "EpisodeName").unwrap(),
        })
    }

    pub fn episode<T: Into<EpisodeId>>(&self, epid: T, season: u32, episode: u32) -> Result<EpisodeInfo, TvdbError>{
        self.episode_inner(epid.into(), season, episode)
    }
}

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

    const APIKEY: &'static str = "0629B785CE550C8D";

    #[test]
    fn search() {
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("scrubs".to_owned(), "en".to_owned());
        assert!(sr.ok().unwrap()[0].seriesname == "Scrubs");
    }

    #[test]
    fn nonexist() {
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("ladlkgdklfgsdfglk".to_owned(), "en".to_owned());
        assert!(sr.is_err());
    }

    #[test]
    fn lookup_by_epid(){
        let api = Tvdb::new(APIKEY.to_owned());
        let ep = api.episode(EpisodeId::new(76156, "en"), 1, 2).ok().unwrap();
        assert!(ep.episodename == "My Mentor");
    }

    #[test]
    fn lookup_by_u32(){
        let api = Tvdb::new(APIKEY.to_owned());
        let ep = api.episode(76156, 1, 2).ok().unwrap();
        assert!(ep.episodename == "My Mentor");
    }

    #[test]
    fn epinfo_default(){
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("scrubs".to_owned(), "en".to_owned()).ok().unwrap();
        let ep = api.episode(sr[0].clone(), 1, 2).ok().unwrap();
        assert!(ep.episodename == "My Mentor");
    }

}
<commit_msg>Unused error thing used.<commit_after>extern crate xmltree;
extern crate hyper;
extern crate url;

use hyper::Client;
use hyper::header::Connection;
use std::io::Read;

/// Turns "123" into 123
fn intify(instr: &str) -> u32{
    // TODO: Better error handling
    instr.to_owned().parse::<u32>().unwrap()
}

/// Errors in contacting TheTVDB
#[derive(Debug)]
pub enum TvdbError {
    SeriesNotFound,
    CommunicationError{reason: String},
    DataError{reason: String},
    Cancelled,
}

/// Series ID from TheTVDB.com, along with language
#[derive(Debug,Clone)]
pub struct EpisodeId{
    seriesid: u32,
    lang: String,
}

impl EpisodeId{
    pub fn new(seriesid: u32, lang: &str) -> EpisodeId{
        EpisodeId{
            seriesid: seriesid,
            lang: lang.to_owned(),
        }
    }
}

impl From<u32> for EpisodeId{
    fn from(x: u32) -> Self{
        EpisodeId{seriesid: x, lang: "en".to_owned()}
    }
}

impl From<SeriesSearchResult> for EpisodeId{
    fn from(x: SeriesSearchResult) -> Self{
        EpisodeId{seriesid: x.seriesid, lang: x.language}
    }
}

/// Series info as returned from TheTVDB's series search method:
/// http://www.thetvdb.com/wiki/index.php?title=API:GetSeries
#[derive(Debug,Clone)]
pub struct SeriesSearchResult{
    pub seriesid: u32, // seriesid is preferred over id according to TVDB wiki
    pub seriesname: String,
    pub language: String,
    pub overview: Option<String>,
    pub banner: Option<String>,
    pub imdb_id: Option<String>,
    //pub firstaired: Date,
    pub network: Option<String>,
    pub zap2it_id: Option<String>,
}

/// Base episode record,
/// http://www.thetvdb.com/wiki/index.php?title=API:Base_Episode_Record
#[derive(Debug,Clone)]
pub struct EpisodeInfo{
    pub id: u32, //id
    // Combined_episodenumber
    // Combined_season
    // DVD_chapter
    // DVD_discid
    // DVD_episodenumber
    // DVD_season
    // Director
    // EpImgFlag
    pub episodename: String, // EpisodeName
    // EpisodeNumber
    // FirstAired
    // GuestStars
    // IMDB_ID
    // Language
    // Overview
    // ProductionCode
    // Rating
    // RatingCount
    // SeasonNumber
    // Writer
    // absolute_number
    // airsafter_season
    // airsbefore_episode
    // airsbefore_season
    // filename
    // lastupdated
    // seasonid
    // seriesid
    // thumb_added
    // thumb_height
    // thumb_width
}

/// Main interface
#[derive(Debug,Clone)]
pub struct Tvdb{
    key: String,
}

impl Tvdb{
    /// Initalise API with the given API key. A key can be aquired via
    /// the [API Key Registration page](http://thetvdb.com/?tab=apiregister)
    pub fn new(key: String) -> Tvdb{
        Tvdb{key: key}
    }

    /// Searches for a given series name.
    pub fn search(&self, seriesname: String, lang: String) -> Result<Vec<SeriesSearchResult>, TvdbError>{
        let client = Client::new();

        let params = url::form_urlencoded::serialize([("seriesname", &seriesname), ("language", &lang)].iter());
        let formatted_url = format!("http://thetvdb.com/api/GetSeries.php?{}", params);
        let url = hyper::Url::parse(&formatted_url).ok().expect("invalid URL");
        println!("Getting {}", url);

        let res = client.get(url)
            .header(Connection::close())
            .send();

        let mut res = match res {
            Err(e) => return Err(TvdbError::CommunicationError{reason: format!("Error contacting TVDB: {}", e)}), // FIXME: http://stackoverflow.com/questions/28911833/error-handling-best-practices
            Ok(r) => r
        };

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        // Parse XML
        let tree = xmltree::Element::parse(body.as_bytes());

        // Convert XML into structs
        let mut results : Vec<SeriesSearchResult> = vec![];

        for child in tree.children.iter(){

            fn get_text(child: &xmltree::Element, x: &str) -> Option<String>{
                child.get_child(x).and_then(|id_child| id_child.text.clone())
            }

            let r = SeriesSearchResult{
                seriesid:   intify(&get_text(child, "seriesid").expect("Search result XML missing 'seriesid' element")),
                seriesname: get_text(child, "SeriesName").expect("Search result XML Missing 'SeriesName' element"),
                language:   get_text(child, "language").expect("Search result XML missing 'language' element"),
                overview:   get_text(child, "Overview"),
                banner:     get_text(child, "banner"),
                imdb_id:    get_text(child, "IMDB_ID"),
                //firstaired: Date,
                network:    get_text(child, "Network"),
                zap2it_id:  get_text(child, "zap2it_id"),
            };

            results.push(r);
        }

        if results.is_empty(){
            return Err(TvdbError::SeriesNotFound);
        }

        return Ok(results);
    }

    fn episode_inner(&self, epid: EpisodeId, season: u32, episode: u32) -> Result<EpisodeInfo, TvdbError>{
        // <mirrorpath>/api/<apikey>/series/{seriesid}/default/{season}/{episode}/{language}.xml

        let client = Client::new();

        let formatted_url = format!("http://thetvdb.com/api/{apikey}/series/{seriesid}/default/{season}/{episode}/{language}.xml",
                                    apikey=self.key,
                                    seriesid=epid.seriesid,
                                    language=epid.lang,
                                    season=season,
                                    episode=episode,
                                    );
        let url = hyper::Url::parse(&formatted_url).ok().expect("invalid URL");
        println!("Getting {}", url);

        // Perform request
        let res = client.get(url)
            .header(Connection::close())
            .send();

        let mut res = match res {
            Err(e) => return Err(TvdbError::CommunicationError{reason: format!("Error contacting TVDB: {}", e)}), // FIXME: http://stackoverflow.com/questions/28911833/error-handling-best-practices
            Ok(r) => r
        };

        // Read the Response.
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        // Parse XML
        let tree = xmltree::Element::parse(body.as_bytes());
        let root = tree.children.first().unwrap();

        fn get_text(child: &xmltree::Element, x: &str) -> Option<String>{
            child.get_child(x).and_then(|id_child| id_child.text.clone())
        }

        // Convert XML into struct
        Ok(EpisodeInfo{
            id: intify(&get_text(root, "id").unwrap()),
            episodename: get_text(root, "EpisodeName").unwrap(),
        })
    }

    pub fn episode<T: Into<EpisodeId>>(&self, epid: T, season: u32, episode: u32) -> Result<EpisodeInfo, TvdbError>{
        self.episode_inner(epid.into(), season, episode)
    }
}

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

    const APIKEY: &'static str = "0629B785CE550C8D";

    #[test]
    fn search() {
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("scrubs".to_owned(), "en".to_owned());
        assert!(sr.ok().unwrap()[0].seriesname == "Scrubs");
    }

    #[test]
    fn nonexist() {
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("ladlkgdklfgsdfglk".to_owned(), "en".to_owned());
        assert!(sr.is_err());
    }

    #[test]
    fn lookup_by_epid(){
        let api = Tvdb::new(APIKEY.to_owned());
        let ep = api.episode(EpisodeId::new(76156, "en"), 1, 2).ok().unwrap();
        assert!(ep.episodename == "My Mentor");
    }

    #[test]
    fn lookup_by_u32(){
        let api = Tvdb::new(APIKEY.to_owned());
        let ep = api.episode(76156, 1, 2).ok().unwrap();
        assert!(ep.episodename == "My Mentor");
    }

    #[test]
    fn epinfo_default(){
        let api = Tvdb::new(APIKEY.to_owned());
        let sr = api.search("scrubs".to_owned(), "en".to_owned()).ok().unwrap();
        let ep = api.episode(sr[0].clone(), 1, 2).ok().unwrap();
        assert!(ep.episodename == "My Mentor");
    }

}
<|endoftext|>


<commit_before>#![doc(html_root_url = "https://docs.rs/rayon/0.9")]
#![allow(non_camel_case_types)] // I prefer to use ALL_CAPS for type parameters
#![deny(missing_debug_implementations)]
#![cfg_attr(test, feature(conservative_impl_trait))]
#![cfg_attr(test, feature(i128_type))]

//! Data-parallelism library that is easy to convert sequential computations into parallel.
//!
//! Rayon is lightweight and convenient for application to existing code.  It guarantees
//! data-race free executions, and takes advantage of parallelism when sensible, based
//! on work-load at runtime.  There are two categories of rayon workloads: parallel
//! iterators and multi-branched recursion (`join` method).
//!
//! # Parallel Iterators
//!
//! Parallel iterators are formed using [`par_iter`], [`par_iter_mut`], and [`into_par_iter`]
//! functions to iterate by shared reference, mutable reference, or by value respectively.
//! These iterators are chained with computations that can take the
//! shape of `map` or `for_each` as an example.  This solves [embarrassingly]
//! parallel tasks that are completely independent of one another.
//!
//! [`par_iter`]: iter/trait.IntoParallelRefIterator.html#tymethod.par_iter
//! [`par_iter_mut`]: iter/trait.IntoParallelRefMutIterator.html#tymethod.par_iter_mut
//! [`into_par_iter`]: iter/trait.IntoParallelIterator.html#tymethod.into_par_iter
//! [embarrassingly]: https://en.wikipedia.org/wiki/Embarrassingly_parallel
//!
//! # Examples
//!
//! Here a string is encrypted using ROT13 leveraging parallelism.  Once all the
//! threads are complete, they are collected into a string.
//!
//! ```
//! extern crate rayon;
//! use rayon::prelude::*;
//! # fn main() {
//! let mut chars: Vec<char> = "A man, a plan, a canal - Panama!".chars().collect();
//! let encrypted: String = chars.into_par_iter().map(|c| {
//!        match c {
//!            'A' ... 'M' | 'a' ... 'm' => ((c as u8) + 13) as char,
//!            'N' ... 'Z' | 'n' ... 'z' => ((c as u8) - 13) as char,
//!            _ => c
//!        }
//!    }).collect();
//!    assert_eq!(encrypted, "N zna, n cyna, n pnany - Cnanzn!");
//! # }
//! ```
//!
//! # Divide and conquer with `join`
//!
//! [`join`] takes two closures and runs them in parallel if doing so will improve
//! execution time.  Parallel Iterators are implemented using [`join`] with
//! work-stealing.  Given two tasks that safely run in parallel, one task is queued
//! and another starts processing.  If idle threads exist, they begin execution on
//! the queued work.
//!
//! [`join`]: fn.join.html
//!
//! # Examples
//!
//! ```rust,ignore
//! join(|| do_something(), || do_something_else())
//! ```
//!
//! ```rust
//! fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
//!    if v.len() > 1 {
//!        let mid = partition(v);
//!        let (lo, hi) = v.split_at_mut(mid);
//!        rayon::join(|| quick_sort(lo),
//!                    || quick_sort(hi));
//!    }
//! }
//! # fn main() { }
//! # fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize { 0 }
//! ```
//!
//! # Rayon Types
//!
//! Rayon traits are bundled into [`rayon::prelude::*`].  To get access to parallel
//! implementations on various standard types include `use rayon::prelude::*;`
//!
//! These implementations will give you access to `par_iter` with parallel
//! implementations of iterative functions including [`map`], [`for_each`], [`filter`],
//! [`fold`], and [more].
//!
//! [`rayon::prelude::*`]: prelude/index.html
//! [`map`]: iter/trait.ParallelIterator.html#method.map
//! [`for_each`]: iter/trait.ParallelIterator.html#method.for_each
//! [`filter`]: iter/trait.ParallelIterator.html#method.filter
//! [`fold`]: iter/trait.ParallelIterator.html#method.fold
//! [more]: iter/trait.ParallelIterator.html#provided-methods
//!
//! # Crate Layout
//!
//! Rayon is modeled after [`std`].  Types are included in provided modules.
//!
//! [`std`]: https://doc.rust-lang.org/std/

extern crate rayon_core;
extern crate either;

#[cfg(test)]
extern crate rand;

#[macro_use]
mod delegate;

#[macro_use]
mod private;

mod split_producer;

pub mod collections;
pub mod iter;
pub mod option;
pub mod prelude;
pub mod range;
pub mod result;
pub mod slice;
pub mod str;
pub mod vec;

mod par_either;
mod test;

pub use rayon_core::current_num_threads;
pub use rayon_core::Configuration;
pub use rayon_core::initialize;
pub use rayon_core::ThreadPool;
pub use rayon_core::{join, join_context};
pub use rayon_core::FnContext;
pub use rayon_core::{scope, Scope};
pub use rayon_core::spawn;
<commit_msg>note that `collections` module does not contain actual collections<commit_after>#![doc(html_root_url = "https://docs.rs/rayon/0.9")]
#![allow(non_camel_case_types)] // I prefer to use ALL_CAPS for type parameters
#![deny(missing_debug_implementations)]
#![cfg_attr(test, feature(conservative_impl_trait))]
#![cfg_attr(test, feature(i128_type))]

//! Data-parallelism library that is easy to convert sequential computations into parallel.
//!
//! Rayon is lightweight and convenient for application to existing code.  It guarantees
//! data-race free executions, and takes advantage of parallelism when sensible, based
//! on work-load at runtime.  There are two categories of rayon workloads: parallel
//! iterators and multi-branched recursion (`join` method).
//!
//! # Parallel Iterators
//!
//! Parallel iterators are formed using [`par_iter`], [`par_iter_mut`], and [`into_par_iter`]
//! functions to iterate by shared reference, mutable reference, or by value respectively.
//! These iterators are chained with computations that can take the
//! shape of `map` or `for_each` as an example.  This solves [embarrassingly]
//! parallel tasks that are completely independent of one another.
//!
//! [`par_iter`]: iter/trait.IntoParallelRefIterator.html#tymethod.par_iter
//! [`par_iter_mut`]: iter/trait.IntoParallelRefMutIterator.html#tymethod.par_iter_mut
//! [`into_par_iter`]: iter/trait.IntoParallelIterator.html#tymethod.into_par_iter
//! [embarrassingly]: https://en.wikipedia.org/wiki/Embarrassingly_parallel
//!
//! # Examples
//!
//! Here a string is encrypted using ROT13 leveraging parallelism.  Once all the
//! threads are complete, they are collected into a string.
//!
//! ```
//! extern crate rayon;
//! use rayon::prelude::*;
//! # fn main() {
//! let mut chars: Vec<char> = "A man, a plan, a canal - Panama!".chars().collect();
//! let encrypted: String = chars.into_par_iter().map(|c| {
//!        match c {
//!            'A' ... 'M' | 'a' ... 'm' => ((c as u8) + 13) as char,
//!            'N' ... 'Z' | 'n' ... 'z' => ((c as u8) - 13) as char,
//!            _ => c
//!        }
//!    }).collect();
//!    assert_eq!(encrypted, "N zna, n cyna, n pnany - Cnanzn!");
//! # }
//! ```
//!
//! # Divide and conquer with `join`
//!
//! [`join`] takes two closures and runs them in parallel if doing so will improve
//! execution time.  Parallel Iterators are implemented using [`join`] with
//! work-stealing.  Given two tasks that safely run in parallel, one task is queued
//! and another starts processing.  If idle threads exist, they begin execution on
//! the queued work.
//!
//! [`join`]: fn.join.html
//!
//! # Examples
//!
//! ```rust,ignore
//! join(|| do_something(), || do_something_else())
//! ```
//!
//! ```rust
//! fn quick_sort<T:PartialOrd+Send>(v: &mut [T]) {
//!    if v.len() > 1 {
//!        let mid = partition(v);
//!        let (lo, hi) = v.split_at_mut(mid);
//!        rayon::join(|| quick_sort(lo),
//!                    || quick_sort(hi));
//!    }
//! }
//! # fn main() { }
//! # fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize { 0 }
//! ```
//!
//! # Rayon Types
//!
//! Rayon traits are bundled into [`rayon::prelude::*`].  To get access to parallel
//! implementations on various standard types include `use rayon::prelude::*;`
//!
//! These implementations will give you access to `par_iter` with parallel
//! implementations of iterative functions including [`map`], [`for_each`], [`filter`],
//! [`fold`], and [more].
//!
//! [`rayon::prelude::*`]: prelude/index.html
//! [`map`]: iter/trait.ParallelIterator.html#method.map
//! [`for_each`]: iter/trait.ParallelIterator.html#method.for_each
//! [`filter`]: iter/trait.ParallelIterator.html#method.filter
//! [`fold`]: iter/trait.ParallelIterator.html#method.fold
//! [more]: iter/trait.ParallelIterator.html#provided-methods
//!
//! # Crate Layout
//!
//! Rayon extends many of the types found in the standard library with
//! parallel iterator implementations. The modules in the `rayon`
//! crate mirror [`std`] itself: so, e.g., the `option` module in
//! Rayon contains parallel iterators for the `Option` type, which is
//! found in [the `option` module of `std`]. Similarly, the
//! `collections` module in Rayon offers parallel iterator types for
//! [the `collections` from `std`]. You will rarely need to access
//! these submodules unless you need to name iterator types
//! explicitly.
//!
//! [the `option` module of `std`]: https://doc.rust-lang.org/std/option/index.html
//! [the `collections` from `std`]: https://doc.rust-lang.org/std/collections/index.html
//! [`std`]: https://doc.rust-lang.org/std/

extern crate rayon_core;
extern crate either;

#[cfg(test)]
extern crate rand;

#[macro_use]
mod delegate;

#[macro_use]
mod private;

mod split_producer;

pub mod collections;
pub mod iter;
pub mod option;
pub mod prelude;
pub mod range;
pub mod result;
pub mod slice;
pub mod str;
pub mod vec;

mod par_either;
mod test;

pub use rayon_core::current_num_threads;
pub use rayon_core::Configuration;
pub use rayon_core::initialize;
pub use rayon_core::ThreadPool;
pub use rayon_core::{join, join_context};
pub use rayon_core::FnContext;
pub use rayon_core::{scope, Scope};
pub use rayon_core::spawn;
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A library for texture conventions.

use std::fmt::{ Display, Formatter, Error };

pub mod ops;

/// Implemented by all images to be used with generic algorithms.
pub trait ImageSize {
    /// Get the image size.
    fn get_size(&self) -> (u32, u32);

    /// Gets the image width.
    #[inline(always)]
    fn get_width(&self) -> u32 {
        let (w, _) = self.get_size();
        w
    }

    /// Gets the image height.
    #[inline(always)]
    fn get_height(&self) -> u32 {
        let (_, h) = self.get_size();
        h
    }
}

/// Texture creation parameters.
pub struct TextureSettings {
    flip_vertical: bool,
    convert_gamma: bool,
    /// Compress on GPU.
    compress: bool,
    /// Generate mipmap chain.
    generate_mipmap: bool,
}

impl TextureSettings {
    /// Create default settings.
    pub fn new() -> TextureSettings {
        TextureSettings {
            flip_vertical: false,
            convert_gamma: false,
            compress: false,
            generate_mipmap: false,
        }
    }

    /// Gets whether to flip vertical.
    pub fn get_flip_vertical(&self) -> bool { self.flip_vertical }
    /// Sets flip vertical.
    pub fn set_flip_vertical(&mut self, val: bool) { self.flip_vertical = val; }
    /// Sets flip vertical.
    pub fn flip_vertical(mut self, val: bool) -> Self {
        self.set_flip_vertical(val);
        self
    }

    /// Gets wheter to convert gamma, treated as sRGB color space.
    pub fn get_convert_gamma(&self) -> bool { self.convert_gamma }
    /// Sets convert gamma.
    pub fn set_convert_gamma(&mut self, val: bool) { self.convert_gamma = val; }
    /// Sets convert gamma.
    pub fn convert_gamma(mut self, val: bool) -> Self {
        self.set_convert_gamma(val);
        self
    }

    /// Gets wheter compress on the GPU.
    pub fn get_compress(&self) -> bool { self.compress }
    /// Sets compress.
    pub fn set_compress(&mut self, val: bool) { self.compress = val; }
    /// Sets compress.
    pub fn compress(mut self, val: bool) -> Self {
        self.set_compress(val);
        self
    }

    /// Gets generate mipmap.
    pub fn get_generate_mipmap(&self) -> bool { self.generate_mipmap }
    /// Sets generate mipmap.
    pub fn set_generate_mipmap(&mut self, val: bool) {
        self.generate_mipmap = val;
    }
    /// Sets generate mipmap.
    pub fn generate_mipmap(mut self, val: bool) -> Self {
        self.set_generate_mipmap(val);
        self
    }
}

/// Result of an texture creating/updating process.
pub type TextureResult<T> = Result<T, TextureError>;

/// An enumeration of Texture and TextureWithDevice errors.
#[derive(Debug)]
pub enum TextureError {
    /// The error in backend factory.
    FactoryError(String),
}

impl Display for TextureError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        match *self {
            TextureError::FactoryError(ref s) => s.fmt(f)
        }
    }
}

/// Unified interface creating/updating texture over backends.
pub trait TextureWithFactory<F>: ImageSize + Sized {
    /// Create texture from memory buffer. Supported only RGBA and alpha channels images.
    fn from_memory(
        device: &mut F,
        memory: &[u8],
        size: [u32; 2],
        channels: u8,
        settings: &TextureSettings
    ) -> TextureResult<Self>;

    /// Update texture from memory buffer. Supported only RGBA and alpha channels images.
    fn update_from_memory(
        &mut self,
        device: &mut F,
        memory: &[u8],
        size: [u32; 2],
        channels: u8
    ) -> TextureResult<()>;
}

/// Interface for device independent backends.
pub trait Texture: TextureWithFactory<()> + Sized {
    /// Create texture from memory buffer. Supported only RGBA and alpha channels images.
    #[inline(always)]
    fn from_memory(
        memory: &[u8],
        size: [u32; 2],
        channels: u8,
        settings: &TextureSettings
    ) -> TextureResult<Self> {
        TextureWithFactory::from_memory(&mut (), memory, size, channels, settings)
    }

    /// Update texture from memory buffer. Supports only RGBA and alpha channels images.
    #[inline(always)]
    fn update_from_memory(
        &mut self,
        memory: &[u8],
        size: [u32; 2],
        channels: u8
    ) -> TextureResult<()> {
        TextureWithFactory::update_from_memory(
            self, &mut (), memory, size, channels)
    }
}

impl<T: TextureWithFactory<()>> Texture for T {}
<commit_msg>Use `Into<[u32; 2]>`<commit_after>#![deny(missing_docs)]

//! A library for texture conventions.

use std::fmt::{ Display, Formatter, Error };

pub mod ops;

/// Implemented by all images to be used with generic algorithms.
pub trait ImageSize {
    /// Get the image size.
    fn get_size(&self) -> (u32, u32);

    /// Gets the image width.
    #[inline(always)]
    fn get_width(&self) -> u32 {
        let (w, _) = self.get_size();
        w
    }

    /// Gets the image height.
    #[inline(always)]
    fn get_height(&self) -> u32 {
        let (_, h) = self.get_size();
        h
    }
}

/// Texture creation parameters.
pub struct TextureSettings {
    flip_vertical: bool,
    convert_gamma: bool,
    /// Compress on GPU.
    compress: bool,
    /// Generate mipmap chain.
    generate_mipmap: bool,
}

impl TextureSettings {
    /// Create default settings.
    pub fn new() -> TextureSettings {
        TextureSettings {
            flip_vertical: false,
            convert_gamma: false,
            compress: false,
            generate_mipmap: false,
        }
    }

    /// Gets whether to flip vertical.
    pub fn get_flip_vertical(&self) -> bool { self.flip_vertical }
    /// Sets flip vertical.
    pub fn set_flip_vertical(&mut self, val: bool) { self.flip_vertical = val; }
    /// Sets flip vertical.
    pub fn flip_vertical(mut self, val: bool) -> Self {
        self.set_flip_vertical(val);
        self
    }

    /// Gets wheter to convert gamma, treated as sRGB color space.
    pub fn get_convert_gamma(&self) -> bool { self.convert_gamma }
    /// Sets convert gamma.
    pub fn set_convert_gamma(&mut self, val: bool) { self.convert_gamma = val; }
    /// Sets convert gamma.
    pub fn convert_gamma(mut self, val: bool) -> Self {
        self.set_convert_gamma(val);
        self
    }

    /// Gets wheter compress on the GPU.
    pub fn get_compress(&self) -> bool { self.compress }
    /// Sets compress.
    pub fn set_compress(&mut self, val: bool) { self.compress = val; }
    /// Sets compress.
    pub fn compress(mut self, val: bool) -> Self {
        self.set_compress(val);
        self
    }

    /// Gets generate mipmap.
    pub fn get_generate_mipmap(&self) -> bool { self.generate_mipmap }
    /// Sets generate mipmap.
    pub fn set_generate_mipmap(&mut self, val: bool) {
        self.generate_mipmap = val;
    }
    /// Sets generate mipmap.
    pub fn generate_mipmap(mut self, val: bool) -> Self {
        self.set_generate_mipmap(val);
        self
    }
}

/// Result of an texture creating/updating process.
pub type TextureResult<T> = Result<T, TextureError>;

/// An enumeration of Texture and TextureWithDevice errors.
#[derive(Debug)]
pub enum TextureError {
    /// The error in backend factory.
    FactoryError(String),
}

impl Display for TextureError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        match *self {
            TextureError::FactoryError(ref s) => s.fmt(f)
        }
    }
}

/// Unified interface creating/updating texture over backends.
pub trait TextureWithFactory<F>: ImageSize + Sized {
    /// Create texture from memory buffer. Supported only RGBA and alpha channels images.
    fn from_memory<S: Into<[u32; 2]>>(
        device: &mut F,
        memory: &[u8],
        size: S,
        channels: u8,
        settings: &TextureSettings
    ) -> TextureResult<Self>;

    /// Update texture from memory buffer. Supported only RGBA and alpha channels images.
    fn update_from_memory<S: Into<[u32; 2]>>(
        &mut self,
        device: &mut F,
        memory: &[u8],
        size: S,
        channels: u8
    ) -> TextureResult<()>;
}

/// Interface for device independent backends.
pub trait Texture: TextureWithFactory<()> + Sized {
    /// Create texture from memory buffer. Supported only RGBA and alpha channels images.
    #[inline(always)]
    fn from_memory<S: Into<[u32; 2]>>(
        memory: &[u8],
        size: S,
        channels: u8,
        settings: &TextureSettings
    ) -> TextureResult<Self> {
        TextureWithFactory::from_memory(&mut (), memory, size, channels, settings)
    }

    /// Update texture from memory buffer. Supports only RGBA and alpha channels images.
    #[inline(always)]
    fn update_from_memory<S: Into<[u32; 2]>>(
        &mut self,
        memory: &[u8],
        size: S,
        channels: u8
    ) -> TextureResult<()> {
        TextureWithFactory::update_from_memory(
            self, &mut (), memory, size, channels)
    }
}

impl<T: TextureWithFactory<()>> Texture for T {}
<|endoftext|>


<commit_before>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate "sha1-hasher" as sha1;
//! use std::io::Write;
//!
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.write("Hello World!".as_bytes());
//! assert_eq!(&*m.hexdigest(), "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(io)]

#![allow(unused_features)]
#![feature(test)]

#[cfg(test)] extern crate test;

use std::io::{Write, BufWriter};
use std::io::Result as IoResult;
use std::num::Int;
use std::num::wrapping::WrappingOps;
use std::default::Default;
use std::mem::transmute;

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&*format!("{:02x}", *b));
    }
    return s;
}

impl Default for Sha1 {
    #[inline]
    fn default() -> Sha1 {
        Sha1::new()
    }
}

impl Write for Sha1 {
    fn write(&mut self, bytes: &[u8]) -> IoResult<usize> {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(bytes);

        for chunk in d[..].chunks(64) {
            if chunk.len() == 64 {
                self.len += 64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }

        Ok(bytes.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        Ok(())
    }
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    pub fn finish(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut *buf);
        buf
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in range(16, 80) {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in range(0, 80) {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);

            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w = Vec::<u8>::with_capacity(137);
        w.push_all(&*self.data);
        w.push_all(&[0x80u8]);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in range(0, padding) {
            w.push(0u8);
        }
        w.push_all(unsafe { &transmute::<_, [u8; 8]>(((self.data.len() as u64 + self.len) * 8).to_be()) });
        for chunk in w[..].chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_all(unsafe { &transmute::<_, [u8; 4]>(n.to_be()) });
        }
    }

    pub fn hexdigest(&self) -> String {
        to_hex(&*self.finish())
    }
}

#[cfg(test)]
mod tests {
    use std::io::Write;
    use test::Bencher;
    use super::{Sha1, to_hex};

    #[test]
    fn test_simple() {
        let mut m = Sha1::new();

        let tests = [
            ("The quick brown fox jumps over the lazy dog",
            "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
            ("The quick brown fox jumps over the lazy cog",
            "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
            ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
            ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
            ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
        ];

        for &(s, ref h) in tests.iter() {
            let data = s.as_bytes();

            m.reset();
            m.write(data).unwrap();
            let hh = m.hexdigest();

            assert_eq!(hh.len(), h.len());
            assert_eq!(&*hh, *h);
        }
    }

    #[test]
    fn test_dirty_run() {
        let mut m = Sha1::new();

        m.write(b"123").unwrap();
        let out1 = m.finish();

        m.write_all(b"123").unwrap();
        let out2 = m.finish();

        assert!(out1 != out2);
        assert_eq!(&*to_hex(&*out1), "40bd001563085fc35165329ea1ff5c5ecbdbbeef");
        assert_eq!(&*to_hex(&*out2), "601f1889667efaebb33b8c12572835da3f027f78");
    }

    #[bench]
    fn test_sha1_speed(b: &mut Bencher) {
        let mut m = Sha1::new();
        let s = "The quick brown fox jumps over the lazy dog.";
        let n = 1000u64;

        b.bytes = n * s.len() as u64;
        b.iter(|| {
            m.reset();
            for _ in range(0, n) {
                m.write_all(s.as_bytes()).unwrap();
            }
            assert_eq!(m.hexdigest(), "7ca27655f67fceaa78ed2e645a81c7f1d6e249d2");
        });
    }
}
<commit_msg>explicit use of iter::range<commit_after>//! A minimal implementation of SHA1 for rust.
//!
//! Example:
//!
//! ```rust
//! extern crate "sha1-hasher" as sha1;
//! use std::io::Write;
//!
//! # fn main() {
//!
//! let mut m = sha1::Sha1::new();
//! m.write("Hello World!".as_bytes());
//! assert_eq!(&*m.hexdigest(), "2ef7bde608ce5404e97d5f042f95f89f1c232871");
//! # }
//! ```

#![feature(collections)]
#![feature(core)]
#![feature(hash)]
#![feature(io)]

#![allow(unused_features)]
#![feature(test)]

#[cfg(test)] extern crate test;

use std::io::{Write, BufWriter};
use std::io::Result as IoResult;
use std::num::Int;
use std::num::wrapping::WrappingOps;
use std::default::Default;
use std::mem::transmute;
use std::iter::range;

/// Represents a Sha1 hash object in memory.
#[derive(Clone)]
pub struct Sha1 {
    state: [u32; 5],
    data: Vec<u8>,
    len: u64,
}

const DEFAULT_STATE : [u32; 5] =
    [0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0];

fn to_hex(input: &[u8]) -> String {
    let mut s = String::new();
    for b in input.iter() {
        s.push_str(&*format!("{:02x}", *b));
    }
    return s;
}

impl Default for Sha1 {
    #[inline]
    fn default() -> Sha1 {
        Sha1::new()
    }
}

impl Write for Sha1 {
    fn write(&mut self, bytes: &[u8]) -> IoResult<usize> {
        let mut d = self.data.clone();
        self.data.clear();

        d.push_all(bytes);

        for chunk in d[..].chunks(64) {
            if chunk.len() == 64 {
                self.len += 64;
                self.process_block(chunk);
            } else {
                self.data.push_all(chunk);
            }
        }

        Ok(bytes.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        Ok(())
    }
}

impl Sha1 {

    /// Creates an fresh sha1 hash object.
    pub fn new() -> Sha1 {
        Sha1 {
            state: DEFAULT_STATE,
            data: Vec::new(),
            len: 0,
        }
    }

    pub fn reset(&mut self) {
        self.state = DEFAULT_STATE;
        self.data.clear();
        self.len = 0;
    }

    pub fn finish(&self) -> Vec<u8> {
        let mut buf = [0u8; 20].to_vec();
        self.output(&mut *buf);
        buf
    }

    fn process_block(&mut self, block: &[u8]) {
        assert_eq!(block.len(), 64);

        let mut words = [0u32; 80];
        for (i, chunk) in block.chunks(4).enumerate() {
            words[i] = (chunk[3] as u32) |
                       ((chunk[2] as u32) << 8) |
                       ((chunk[1] as u32) << 16) |
                       ((chunk[0] as u32) << 24);
        }

        fn ff(b: u32, c: u32, d: u32) -> u32 { d ^ (b & (c ^ d)) }
        fn gg(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }
        fn hh(b: u32, c: u32, d: u32) -> u32 { (b & c) | (d & (b | c)) }
        fn ii(b: u32, c: u32, d: u32) -> u32 { b ^ c ^ d }

        for i in range(16, 80) {
            let n = words[i - 3] ^ words[i - 8] ^ words[i - 14] ^ words[i - 16];
            words[i] = n.rotate_left(1);
        }

        let mut a = self.state[0];
        let mut b = self.state[1];
        let mut c = self.state[2];
        let mut d = self.state[3];
        let mut e = self.state[4];

        for i in range(0, 80) {
            let (f, k) = match i {
                0 ... 19 => (ff(b, c, d), 0x5a827999),
                20 ... 39 => (gg(b, c, d), 0x6ed9eba1),
                40 ... 59 => (hh(b, c, d), 0x8f1bbcdc),
                60 ... 79 => (ii(b, c, d), 0xca62c1d6),
                _ => (0, 0),
            };

            let tmp = a.rotate_left(5)
                .wrapping_add(f)
                .wrapping_add(e)
                .wrapping_add(k)
                .wrapping_add(words[i]);

            e = d;
            d = c;
            c = b.rotate_left(30);
            b = a;
            a = tmp;
        }

        self.state[0] = self.state[0].wrapping_add(a);
        self.state[1] = self.state[1].wrapping_add(b);
        self.state[2] = self.state[2].wrapping_add(c);
        self.state[3] = self.state[3].wrapping_add(d);
        self.state[4] = self.state[4].wrapping_add(e);
    }

    /// Retrieve digest result.  The output must be large enough to
    /// contain result (20 bytes).
    pub fn output(&self, out: &mut [u8]) {
        // these are unlikely to fail, since we're writing to memory
        #![allow(unused_must_use)]

        let mut m = Sha1 {
            state: self.state,
            data: Vec::new(),
            len: 0,
        };

        let mut w = Vec::<u8>::with_capacity(137);
        w.push_all(&*self.data);
        w.push_all(&[0x80u8]);
        let padding = 64 - ((self.data.len() + 9) % 64);
        for _ in range(0, padding) {
            w.push(0u8);
        }
        w.push_all(unsafe { &transmute::<_, [u8; 8]>(((self.data.len() as u64 + self.len) * 8).to_be()) });
        for chunk in w[..].chunks(64) {
            m.process_block(chunk);
        }

        let mut w = BufWriter::new(out);
        for &n in m.state.iter() {
            w.write_all(unsafe { &transmute::<_, [u8; 4]>(n.to_be()) });
        }
    }

    pub fn hexdigest(&self) -> String {
        to_hex(&*self.finish())
    }
}

#[cfg(test)]
mod tests {
    use std::io::Write;
    use test::Bencher;
    use super::{Sha1, to_hex};

    #[test]
    fn test_simple() {
        let mut m = Sha1::new();

        let tests = [
            ("The quick brown fox jumps over the lazy dog",
            "2fd4e1c67a2d28fced849ee1bb76e7391b93eb12"),
            ("The quick brown fox jumps over the lazy cog",
            "de9f2c7fd25e1b3afad3e85a0bd17d9b100db4b3"),
            ("", "da39a3ee5e6b4b0d3255bfef95601890afd80709"),
            ("testing\n", "9801739daae44ec5293d4e1f53d3f4d2d426d91c"),
            ("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
            "025ecbd5d70f8fb3c5457cd96bab13fda305dc59"),
        ];

        for &(s, ref h) in tests.iter() {
            let data = s.as_bytes();

            m.reset();
            m.write(data).unwrap();
            let hh = m.hexdigest();

            assert_eq!(hh.len(), h.len());
            assert_eq!(&*hh, *h);
        }
    }

    #[test]
    fn test_dirty_run() {
        let mut m = Sha1::new();

        m.write(b"123").unwrap();
        let out1 = m.finish();

        m.write_all(b"123").unwrap();
        let out2 = m.finish();

        assert!(out1 != out2);
        assert_eq!(&*to_hex(&*out1), "40bd001563085fc35165329ea1ff5c5ecbdbbeef");
        assert_eq!(&*to_hex(&*out2), "601f1889667efaebb33b8c12572835da3f027f78");
    }

    #[bench]
    fn test_sha1_speed(b: &mut Bencher) {
        let mut m = Sha1::new();
        let s = "The quick brown fox jumps over the lazy dog.";
        let n = 1000u64;

        b.bytes = n * s.len() as u64;
        b.iter(|| {
            m.reset();
            for _ in range(0, n) {
                m.write_all(s.as_bytes()).unwrap();
            }
            assert_eq!(m.hexdigest(), "7ca27655f67fceaa78ed2e645a81c7f1d6e249d2");
        });
    }
}
<|endoftext|>


<commit_before>//! RethinkDB protocol implementation in Rust

extern crate protobuf;

mod proto;

pub use proto::{
    VersionDummy_Version as Version,
    Term_TermType as TermType,
    Query_QueryType as QueryType,
    Response_ResponseType as ResponseType,
    Response_ErrorType as ErrorType,
};

use std::string::String as StdString;

use proto::{
    Term, Datum,
    Datum_DatumType as DatumType,
};

use protobuf::repeated::RepeatedField;

macro_rules! implement {
    (Selection<$dt:ident>) => {
        impl DataType for Selection<$dt> {}

        impl Selection<$dt> {
            pub fn new() -> Selection<$dt> {
                Selection::<$dt>($dt(Term::new()))
            }
        }

        impl From<Selection<$dt>> for Term {
            fn from(t: Selection<$dt>) -> Term {
                From::from(t.0)
            }
        }

        impl From<Term> for Selection<$dt> {
            fn from(t: Term) -> Selection<$dt> {
                Selection::<$dt>($dt(t))
            }
        }
    };

    ($dt:ident) => {
        #[derive(Debug, Clone)]
        pub struct $dt(Term);

        impl DataType for $dt {}

        impl $dt {
            pub fn new() -> $dt {
                $dt(Term::new())
            }
        }

        impl From<$dt> for Term {
            fn from(t: $dt) -> Term {
                t.0
            }
        }

        impl From<Term> for $dt {
            fn from(t: Term) -> $dt {
                $dt(t)
            }
        }
    };
}

/// *Arrays* are lists of zero or more elements.
///
/// ```json
/// [1, 2, 3]
/// []
/// [{user: 'Bob', posts: 23}, {user: 'Jason', posts: 10}]
/// ```
/// Anything valid in a JSON array is valid in RethinkDB.
/// The elements may be any of the basic values, objects,
/// or other arrays. Arrays in RethinkDB are loaded fully
/// into memory before they’re returned to the user, so
/// they’re inefficient at large sizes. RethinkDB defaults
/// to supporting arrays of up to 100,000 elements; this
/// may be set to a different value at runtime for reading
/// by using the `array_limit` option to run.
implement! { Array }

/// *Booleans* are `true` and `false`
implement! { Bool }

/// *Databases* are RethinkDB databases.
///
/// This is the return type of `db`.
implement! { Db }

/// *Functions* can be passed as parameters to certain ReQL
/// commands.
implement! { Function }

/// *Grouped data* is created by the `group` command.
///
/// The command partitions a stream into multiple groups
/// based on specified fields or functions. ReQL commands
/// called on GroupedData operate on each group
/// individually. For more details, read the group
/// documentation. Depending on the input to group,
/// grouped data may have the type of GroupedStream.
implement! { GroupedData }
implement! { GroupedStream }

/// *Minval* and *maxval* are used with some commands such
/// as `between` to specify absolute lower and upper bounds
/// (e.g., `between(r.minval, 1000)` would return all
/// documents in a table whose primary key is less than
/// 1000).
implement! { MaxVal }
implement! { MinVal }

/// *Null* is a value distinct from the number zero, an
/// empty set, or a zero-length string.
///
/// Natively this is
/// `None`. It is often used to explicitly denote the
/// absence of any other value. The root node of a tree
/// structure might have a parent of `null`, or a required
/// but as yet non-initialized key might be given a value
/// of `null`.
implement! { Null }

/// *Numbers* are any real number: `5`, `3.14159`, `-42`.
///
/// RethinkDB uses double precision (64-bit) floating point
/// numbers internally. Neither infinity nor NaN are allowed.
implement! { Number }

/// *Objects* are JSON data objects, standard key-value pairs.
///
/// ```json
/// {
///     username: 'bob',
///     posts: 23,
///     favorites: {
///         color: 'blue',
///         food: 'tacos'
///     },
///     friends: ['agatha', 'jason']
/// }
/// ```
///
/// Any valid JSON object is a valid RethinkDB object, so
/// values can be any of the basic values, arrays, or
/// other objects. Documents in a RethinkDB database are
/// objects. Like JSON, key names must be strings, not
/// integers.
implement! { Object }

/// *Binary* objects are similar to BLOBs in SQL databases:
/// files, images and other binary data.
///
/// See Storing binary objects for details.
implement! { Binary }

/// *Geometry* data types for geospatial support, including
/// points, lines, and polygons.
implement! { Geometry }

/// *Times* are RethinkDB’s native date/time type, stored
/// with millisecond precision.
///
/// You can use native date/time types in supported
/// languages, as the conversion will be done by the driver.
/// See Dates and times in RethinkDB for details.
implement! { Time }

/// *Streams* are lists like arrays, but they’re loaded in
/// a lazy fashion.
///
/// Operations that return streams return a `cursor`.
/// A cursor is a pointer into the result set. Instead of
/// reading the results all at once like an array, you
/// loop over the results, retrieving the next member of the
/// set with each iteration. This makes it possible to
/// efficiently work with large result sets.
///
/// (See “Working with Streams,” below, for some tips.)
/// Streams are read-only; you can’t pass one as an input
/// to an ReQL command meant to modify its input like
/// `update` or `delete`.
implement! { Stream }

/// *Strings* are any valid UTF-8 string: `"superhero"`,
/// `"ünnëcëssärÿ ümläüts"`. Strings may include the null
/// code point (U+0000).
implement! { String }

/// *Tables* are RethinkDB database tables.
///
/// They behave like selections—they’re writable, as you can
/// insert and delete documents in them. ReQL methods that
/// use an index, like `get_all`, are only available on
/// tables.
implement! { Table }
implement! { TableSlice }

/// *Selections* represent subsets of tables, for example,
/// the return values of `filter` or `get`.
///
/// There are three kinds of selections: *Selection<Object>*,
/// *Selection<Array>* and *Selection<Stream>*. The
/// difference between selections and their non-selection
/// counterparts is that selections are writable—their
/// return values can be passed as inputs to ReQL commands
/// that modify the database. For instance, the get command
/// will return a Selection<Object> that could then be
/// passed to an update or delete command.
///
/// (Note: *singleSelection* is an older term for
/// Selection<Object>; they mean the same thing.)
/// Some commands (`order_by` and `between`) return a data
/// type similar to a selection called a *table_slice*.
/// In most cases a table_slice behaves identically to a
/// selection, but `between` can only be called on a table
/// or a table_slice, not any other kind of selection.
#[derive(Debug, Clone)]
pub struct Selection<T>(T);
implement! { Selection<Object> }
implement! { Selection<Array> }
implement! { Selection<Stream> }

pub trait DataType : Sized + From<Term> + Into<Term> {}

#[derive(Debug, Clone)]
pub struct Command(Term);

impl Command {
    pub fn new<T>(cmd_type: TermType, prev_cmd: Option<T>) -> Command
        where T: DataType
        {
            let mut term = Term::new();
            term.set_field_type(cmd_type);
            if let Some(cmd) = prev_cmd {
                let args = RepeatedField::from_vec(vec![cmd.into()]);
                term.set_args(args);
            }
            Command(term)
        }

    pub fn set_args<T>(&mut self, args: T)
        where T: DataType
        {
            self.0.mut_args().push(args.into());
        }

    pub fn set_opts(&mut self, opts: Object)
        {
            let mut term: Term = opts.into();
            let opts = term.take_optargs().into_vec();
            for opt in opts.into_iter() {
                self.0.mut_optargs().push(opt);
            }
        }

    pub fn into<T>(self) -> T
        where T: From<Term>
        {
            From::from(self.0)
        }
}

impl<T> From<T> for String
    where T: Into<StdString>
{
    fn from(t: T) -> String {
        let mut datum = Datum::new();
        datum.set_field_type(DatumType::R_STR);
        datum.set_r_str(t.into());
        let mut output = String::new();
        output.0.set_field_type(TermType::DATUM);
        output.0.set_datum(datum);
        output
    }
}

<commit_msg>Add documentation in macros<commit_after>//! RethinkDB protocol implementation in Rust

extern crate protobuf;

mod proto;

pub use proto::{
    VersionDummy_Version as Version,
    Term_TermType as TermType,
    Query_QueryType as QueryType,
    Response_ResponseType as ResponseType,
    Response_ErrorType as ErrorType,
};

use std::string::String as StdString;

use proto::{
    Term, Datum,
    Datum_DatumType as DatumType,
};

use protobuf::repeated::RepeatedField;

macro_rules! implement {
    (Selection<$dt:ident>) => {
        impl DataType for Selection<$dt> {}

        impl Selection<$dt> {
            pub fn new() -> Selection<$dt> {
                Selection::<$dt>($dt(Term::new()))
            }
        }

        impl From<Selection<$dt>> for Term {
            fn from(t: Selection<$dt>) -> Term {
                From::from(t.0)
            }
        }

        impl From<Term> for Selection<$dt> {
            fn from(t: Term) -> Selection<$dt> {
                Selection::<$dt>($dt(t))
            }
        }
    };

    ($(#[$attr:meta])* pub struct $dt:ident) => {
        $(
            #[$attr]
        )*
        #[derive(Debug, Clone)]
        pub struct $dt(Term);

        impl DataType for $dt {}

        impl $dt {
            pub fn new() -> $dt {
                $dt(Term::new())
            }
        }

        impl From<$dt> for Term {
            fn from(t: $dt) -> Term {
                t.0
            }
        }

        impl From<Term> for $dt {
            fn from(t: Term) -> $dt {
                $dt(t)
            }
        }
    };
}

implement! {
    /// **Arrays** are lists of zero or more elements.
    ///
    /// ```json
    /// [1, 2, 3]
    /// []
    /// [{user: 'Bob', posts: 23}, {user: 'Jason', posts: 10}]
    /// ```
    /// Anything valid in a JSON array is valid in RethinkDB.
    /// The elements may be any of the basic values, objects,
    /// or other arrays. Arrays in RethinkDB are loaded fully
    /// into memory before they’re returned to the user, so
    /// they’re inefficient at large sizes. RethinkDB defaults
    /// to supporting arrays of up to 100,000 elements; this
    /// may be set to a different value at runtime for reading
    /// by using the `array_limit` option to run.
    pub struct Array
}

implement! {
    /// **Booleans** are `true` and `false`
    pub struct Bool
}

implement! {
    /// **Databases** are RethinkDB databases.
    ///
    /// This is the return type of `db`.
    pub struct Db
}

implement! {
    /// **Functions** can be passed as parameters to certain ReQL
    /// commands.
    pub struct Function
}

implement! {
    /// **Grouped data** is created by the `group` command.
    ///
    /// The command partitions a stream into multiple groups
    /// based on specified fields or functions. ReQL commands
    /// called on GroupedData operate on each group
    /// individually. For more details, read the group
    /// documentation. Depending on the input to group,
    /// grouped data may have the type of GroupedStream.
    pub struct GroupedData
}

implement! {
    pub struct GroupedStream
}

implement! {
    /// **Minval** and **maxval** are used with some commands such
    /// as `between` to specify absolute lower and upper bounds
    /// (e.g., `between(r.minval, 1000)` would return all
    /// documents in a table whose primary key is less than
    /// 1000).
    pub struct MaxVal
}

implement! {
    pub struct MinVal
}

implement! {
    /// **Null** is a value distinct from the number zero, an
    /// empty set, or a zero-length string.
    ///
    /// Natively this is
    /// `None`. It is often used to explicitly denote the
    /// absence of any other value. The root node of a tree
    /// structure might have a parent of `null`, or a required
    /// but as yet non-initialized key might be given a value
    /// of `null`.
    pub struct Null
}

implement! {
    /// **Numbers** are any real number: `5`, `3.14159`, `-42`.
    ///
    /// RethinkDB uses double precision (64-bit) floating point
    /// numbers internally. Neither infinity nor NaN are allowed.
    pub struct Number
}

implement! {
    /// **Objects** are JSON data objects, standard key-value pairs.
    ///
    /// ```json
    /// {
    ///     username: 'bob',
    ///     posts: 23,
    ///     favorites: {
    ///         color: 'blue',
    ///         food: 'tacos'
    ///     },
    ///     friends: ['agatha', 'jason']
    /// }
    /// ```
    ///
    /// Any valid JSON object is a valid RethinkDB object, so
    /// values can be any of the basic values, arrays, or
    /// other objects. Documents in a RethinkDB database are
    /// objects. Like JSON, key names must be strings, not
    /// integers.
    pub struct Object
}

implement! {
    /// **Binary** objects are similar to BLOBs in SQL databases:
    /// files, images and other binary data.
    ///
    /// See Storing binary objects for details.
    pub struct Binary
}

implement! {
    /// **Geometry** data types for geospatial support, including
    /// points, lines, and polygons.
    pub struct Geometry
}

implement! {
    /// **Times** are RethinkDB’s native date/time type, stored
    /// with millisecond precision.
    ///
    /// You can use native date/time types in supported
    /// languages, as the conversion will be done by the driver.
    /// See Dates and times in RethinkDB for details.
    pub struct Time
}

implement! {
    /// **Streams** are lists like arrays, but they’re loaded in
    /// a lazy fashion.
    ///
    /// Operations that return streams return a `cursor`.
    /// A cursor is a pointer into the result set. Instead of
    /// reading the results all at once like an array, you
    /// loop over the results, retrieving the next member of the
    /// set with each iteration. This makes it possible to
    /// efficiently work with large result sets.
    ///
    /// (See “Working with Streams,” below, for some tips.)
    /// Streams are read-only; you can’t pass one as an input
    /// to an ReQL command meant to modify its input like
    /// `update` or `delete`.
    pub struct Stream
}

implement! {
    /// **Strings** are any valid UTF-8 string: `"superhero"`,
    /// `"ünnëcëssärÿ ümläüts"`. Strings may include the null
    /// code point (U+0000).
    pub struct String
}

implement! {
    /// **Tables** are RethinkDB database tables.
    ///
    /// They behave like selections—they’re writable, as you can
    /// insert and delete documents in them. ReQL methods that
    /// use an index, like `get_all`, are only available on
    /// tables.
    pub struct Table
}

implement! {
    pub struct TableSlice
}

/// **Selections** represent subsets of tables, for example,
/// the return values of `filter` or `get`.
///
/// There are three kinds of selections: **Selection<Object>**,
/// **Selection<Array>** and **Selection<Stream>**. The
/// difference between selections and their non-selection
/// counterparts is that selections are writable—their
/// return values can be passed as inputs to ReQL commands
/// that modify the database. For instance, the get command
/// will return a Selection<Object> that could then be
/// passed to an update or delete command.
///
/// (Note: **singleSelection** is an older term for
/// Selection<Object>; they mean the same thing.)
/// Some commands (`order_by` and `between`) return a data
/// type similar to a selection called a **table**slice_.
/// In most cases a table_slice behaves identically to a
/// selection, but `between` can only be called on a table
/// or a table_slice, not any other kind of selection.
#[derive(Debug, Clone)]
pub struct Selection<T>(T);
implement! { Selection<Object> }
implement! { Selection<Array> }
implement! { Selection<Stream> }

pub trait DataType : Sized + From<Term> + Into<Term> {}

#[derive(Debug, Clone)]
pub struct Command(Term);

impl Command {
    pub fn new<T>(cmd_type: TermType, prev_cmd: Option<T>) -> Command
        where T: DataType
        {
            let mut term = Term::new();
            term.set_field_type(cmd_type);
            if let Some(cmd) = prev_cmd {
                let args = RepeatedField::from_vec(vec![cmd.into()]);
                term.set_args(args);
            }
            Command(term)
        }

    pub fn set_args<T>(&mut self, args: T)
        where T: DataType
        {
            self.0.mut_args().push(args.into());
        }

    pub fn set_opts(&mut self, opts: Object)
        {
            let mut term: Term = opts.into();
            let opts = term.take_optargs().into_vec();
            for opt in opts.into_iter() {
                self.0.mut_optargs().push(opt);
            }
        }

    pub fn into<T>(self) -> T
        where T: From<Term>
        {
            From::from(self.0)
        }
}

impl<T> From<T> for String
    where T: Into<StdString>
{
    fn from(t: T) -> String {
        let mut datum = Datum::new();
        datum.set_field_type(DatumType::R_STR);
        datum.set_r_str(t.into());
        let mut output = String::new();
        output.0.set_field_type(TermType::DATUM);
        output.0.set_datum(datum);
        output
    }
}

<|endoftext|>