<commit_before>use std::io;
use std::io::prelude::*;

fn main() {
    let mut stdin = io::stdin();

    //don't need it
    let count = stdin.lock().lines().next().unwrap().unwrap();

    for line in stdin.lock().lines() {
        let bytes: Vec<i8> = line.unwrap().as_bytes().iter().map(|x| *x as i8).collect();
        let mut result = 0;
        let mut iter = bytes.iter();
        while let(Some(&a), Some(&b)) = (iter.next(), iter.next_back()) {
            result += (b - a).abs();
        }
        println!("{}", result);
    }
}<commit_msg>the_love-letter_mystery<commit_after>use std::io;
use std::io::prelude::*;

fn main() {
    let mut stdin = io::stdin();

    //don't need it
    let count = stdin.lock().lines().next().unwrap().unwrap();

    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let mut result = 0;
        let mut iter = line.bytes().map(|x| x as i8);
        while let(Some(a), Some(b)) = (iter.next(), iter.next_back()) {
            result += (b - a).abs();
        }
        println!("{}", result);
    }
}<|endoftext|>


<commit_before>//! Library for manipulating Pokémon Gen3 (Fire Red/Leaf Green, Ruby/Emerald/Sapphire) save data.

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

mod util {
    mod lower_upper;
    pub use self::lower_upper::LowerUpper;
}
mod rw;

use crate::util::LowerUpper;
use std::error::Error;
use std::fs::File;
use std::path::Path;
use std::{fmt, io};

const UNKNOWN_SAVE_FOOTER_SIZE: usize = 16384;

/// Pokémon Gen3 save data.
pub struct Save {
    blocks: [SaveBlock; 2],
    unknown: [u8; UNKNOWN_SAVE_FOOTER_SIZE],
    most_recent_index: usize,
}

impl fmt::Debug for Save {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.blocks.fmt(f)
    }
}

impl Save {
    /// Load the save data from a file at the provided path.
    pub fn load_from_file<P: AsRef<Path>>(path: P) -> Result<Self, Box<Error>> {
        let mut file = File::open(path)?;
        Save::read(&mut file)
    }
    /// Save the save data to a file at the provided path.
    pub fn save_to_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), io::Error> {
        let mut file = File::create(path)?;
        self.write(&mut file)
    }
    pub fn sections_mut(&mut self) -> SaveSectionsMut {
        let block = &mut self.blocks[self.most_recent_index];
        let sections = &mut block.sections[..];
        let (team_items_sec, trainer_sec) = if block.team_and_items_index > block.trainer_info_index
        {
            let (lhs, rhs) = sections.split_at_mut(block.team_and_items_index);
            (&mut rhs[0], &mut lhs[block.trainer_info_index])
        } else {
            let (lhs, rhs) = sections.split_at_mut(block.trainer_info_index);
            (&mut lhs[block.team_and_items_index], &mut rhs[0])
        };
        let team_and_items = if let SectionData::TeamAndItems(ref mut data) = team_items_sec.data {
            data
        } else {
            panic!("Unexpected section data. Expected TeamAndItems");
        };
        let trainer_info = if let SectionData::TrainerInfo(ref mut data) = trainer_sec.data {
            data
        } else {
            panic!("Unexpected section data. Expected TrainerInfo");
        };
        SaveSectionsMut {
            team: &mut team_and_items.team,
            trainer: trainer_info,
            pc_boxes: &mut block.pokemon_storage.boxes,
        }
    }
}

pub struct SaveSectionsMut<'a> {
    pub trainer: &'a mut TrainerInfo,
    pub team: &'a mut Vec<Pokemon>,
    pub pc_boxes: &'a mut [PokeBox],
}

#[derive(Debug)]
struct SaveBlock {
    sections: Vec<Section>,
    trainer_info_index: usize,
    team_and_items_index: usize,
    // Does not exist yet, meaning the game has only been saved once, and this
    // block hasn't been written over yet.
    nonexistent: bool,
    pokemon_storage: PokemonStorage,
    box_indexes: [usize; N_BOXES],
}

#[allow(clippy::large_enum_variant)]
enum SectionData {
    Unimplemented {
        raw: [u8; DATA_SIZE as usize],
        id: u16,
        cksum: u16,
    },
    TrainerInfo(TrainerInfo),
    TeamAndItems(TeamAndItems),
    PcBuffer(PcBuffer),
}

impl fmt::Debug for SectionData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SectionData::Unimplemented { .. } => f.write_str("<Unimplemented section>"),
            SectionData::TrainerInfo(ref data) => data.fmt(f),
            SectionData::TeamAndItems(ref data) => data.fmt(f),
            SectionData::PcBuffer(ref data) => data.fmt(f),
        }
    }
}

#[derive(Debug)]
struct Section {
    data: SectionData,
    unknown_1: u32,
    save_idx: u32,
}

const DATA_SIZE: i64 = 0xFF4;

#[repr(u8)]
#[derive(Clone, Copy, Debug)]
enum Gender {
    Male = 0,
    Female = 1,
}

impl fmt::Display for Gender {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match *self {
            Gender::Male => "Male",
            Gender::Female => "Female",
        };
        f.write_str(str)
    }
}

#[derive(Debug)]
struct Time {
    hours: u16,
    minutes: u8,
    seconds: u8,
    frames: u8,
}

const TRAINER_INFO_UNKNOWN_3_SIZE: usize = 0x00AC - (0x0013 + 3);
const RS_EM_PLAYERINFO_TRAILING_DATA_SIZE: usize = DATA_SIZE as usize - (0x0AC + 4);
const FRLG_PLAYERINFO_UNKNOWN_CHUNK_SIZE: usize = 0x0AF8 - (0x00AC + 4);
const FRLG_PLAYERINFO_TRAILING_DATA_SIZE: usize = DATA_SIZE as usize - (0x0AF8 + 4);

enum Game {
    RubyOrSapphire {
        trailing_data: [u8; RS_EM_PLAYERINFO_TRAILING_DATA_SIZE],
    },
    FireredOrLeafgreen {
        unknown: [u8; FRLG_PLAYERINFO_UNKNOWN_CHUNK_SIZE],
        security_key: u32,
        trailing_data: [u8; FRLG_PLAYERINFO_TRAILING_DATA_SIZE],
    },
    Emerald {
        security_key: u32,
        trailing_data: [u8; RS_EM_PLAYERINFO_TRAILING_DATA_SIZE],
    },
}

#[derive(Clone, Copy)]
enum GameType {
    RubyOrSapphire,
    FireredOrLeafgreen,
    Emerald,
}

impl<'a> From<&'a Game> for GameType {
    fn from(src: &Game) -> Self {
        match *src {
            Game::RubyOrSapphire { .. } => GameType::RubyOrSapphire,
            Game::FireredOrLeafgreen { .. } => GameType::FireredOrLeafgreen,
            Game::Emerald { .. } => GameType::Emerald,
        }
    }
}

impl fmt::Debug for Game {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Game::RubyOrSapphire { .. } => write!(f, "Ruby/Sapphire"),
            Game::FireredOrLeafgreen { security_key, .. } => {
                write!(f, "Fire Red/Leaf Green (security key: {})", security_key)
            }
            Game::Emerald { security_key, .. } => {
                write!(f, "Emerald (security key: {})", security_key)
            }
        }
    }
}

const TRAINER_NAME_LEN: usize = 7;

pub struct TrainerInfo {
    pub name: TrainerName,
    unknown_1: u8,
    gender: Gender,
    unknown_2: u8,
    public_id: u16,
    secret_id: u16,
    time_played: Time,
    options_data: [u8; 3],
    unknown_3: [u8; TRAINER_INFO_UNKNOWN_3_SIZE],
    game: Game,
}

impl TrainerInfo {
    pub fn full_id(&self) -> u32 {
        u32::merge(self.public_id, self.secret_id)
    }
}

impl fmt::Debug for TrainerInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("== Trainer Info ==\n")?;
        writeln!(f, "name: {:?}", self.name)?;
        writeln!(f, "gender: {:?}", self.gender)?;
        writeln!(
            f,
            "id: public({:?}) secret({:?}) combined({:?})",
            self.public_id,
            self.secret_id,
            u32::merge(self.public_id, self.secret_id)
        )?;
        writeln!(f, "Time played: {:?}", self.time_played)?;
        writeln!(f, "GAME ID: {:?}", self.game)
    }
}

const EM_RU_SA_TEAMANDITEMS_UNK_LEN: usize = 0x0234;
const FR_LG_TEAMANDITEMS_UNK_LEN: usize = 0x0034;
const TEAMANDITEMS_POKE_LEN: usize = 600;
const EM_RU_SA_TEAMANDITEMS_REM_LEN: usize =
    DATA_SIZE as usize - (EM_RU_SA_TEAMANDITEMS_UNK_LEN + TEAMANDITEMS_POKE_LEN + 4);
const FR_LG_TEAMANDITEMS_REM_LEN: usize =
    DATA_SIZE as usize - (FR_LG_TEAMANDITEMS_UNK_LEN + TEAMANDITEMS_POKE_LEN + 4);

#[allow(clippy::large_enum_variant)]
enum TeamAndItemsUnknown {
    EmeraldOrRubyOrSapphire([u8; EM_RU_SA_TEAMANDITEMS_UNK_LEN]),
    FireRedOrLeafGreen([u8; FR_LG_TEAMANDITEMS_UNK_LEN]),
}

#[allow(clippy::large_enum_variant)]
enum TeamAndItemsRemaining {
    EmeraldOrRubyOrSapphire([u8; EM_RU_SA_TEAMANDITEMS_REM_LEN]),
    FireredOrLeafgreen([u8; FR_LG_TEAMANDITEMS_REM_LEN]),
}

struct TeamAndItems {
    unknown: TeamAndItemsUnknown,
    team: Vec<Pokemon>,
    orig_pokemon_data: [u8; TEAMANDITEMS_POKE_LEN],
    remaining_data: TeamAndItemsRemaining,
}

impl fmt::Debug for TeamAndItems {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("=== Team And Items ===\nTeam listing:\n")?;
        for pokemon in &self.team {
            pokemon.fmt(f)?
        }
        Ok(())
    }
}

const POKEMON_NICK_LEN: usize = 10;

#[derive(Default, Clone, Copy)]
pub struct PokemonNick(pub [u8; POKEMON_NICK_LEN]);
#[derive(Default, Clone, Copy)]
pub struct TrainerName(pub [u8; TRAINER_NAME_LEN]);
#[derive(Default, Clone, Copy)]
pub struct BoxName(pub [u8; BOX_NAME_LEN]);

const BOX_NAME_LEN: usize = 8;

macro_rules! debug_impl {
    ($target:ident) => {
        impl fmt::Debug for $target {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "{}", rgen3_string::decode_string(&self.0[..]))
            }
        }
    };
}

debug_impl!(PokemonNick);
debug_impl!(TrainerName);
debug_impl!(BoxName);

/// A Pokemon.
#[derive(Debug, Default)]
#[allow(missing_docs)]
pub struct Pokemon {
    pub personality: u32,
    pub ot_id: u32,
    pub nickname: PokemonNick,
    language: u16,
    pub ot_name: TrainerName,
    markings: u8,
    checksum: u16,
    unknown_1: u16,
    pub data: PokemonData,
    pub active_data: Option<PokemonActiveData>,
}

#[derive(Debug)]
pub struct InvalidSpecies;

impl Pokemon {
    pub fn set_species(&mut self, num: u16) -> Result<(), InvalidSpecies> {
        match num {
            1...251 | 277...411 => {
                self.data.growth.species = num;
                Ok(())
            }
            _ => Err(InvalidSpecies),
        }
    }
}

/// "Active" data that is not stored in the PC boxes.
#[derive(Debug, Default)]
pub struct PokemonActiveData {
    status_condition: u32,
    pub level: u8,
    pokerus_remaining: u8,
    pub current_hp: u16,
    pub total_hp: u16,
    pub attack: u16,
    pub defense: u16,
    pub speed: u16,
    pub sp_attack: u16,
    pub sp_defense: u16,
}

#[derive(Debug, Default)]
pub struct PokemonData {
    pub growth: PokemonGrowth,
    pub attacks: PokemonAttacks,
    pub evs_and_condition: PokemonEvsAndCondition,
    misc: PokemonMisc,
}

#[derive(Debug, Default)]
pub struct PokemonGrowth {
    pub species: u16,
    item_held: u16,
    pub experience: u32,
    pub pp_bonuses: u8,
    pub friendship: u8,
    unknown: u16,
}

#[derive(Debug, Default)]
pub struct PokemonAttacks {
    pub move1: u16,
    pub move2: u16,
    pub move3: u16,
    pub move4: u16,
    pub pp1: u8,
    pub pp2: u8,
    pub pp3: u8,
    pub pp4: u8,
}

#[derive(Debug, Default)]
pub struct PokemonEvsAndCondition {
    pub hp: u8,
    pub attack: u8,
    pub defense: u8,
    pub speed: u8,
    pub sp_attack: u8,
    pub sp_defense: u8,
    pub coolness: u8,
    pub beauty: u8,
    pub cuteness: u8,
    pub smartness: u8,
    pub toughness: u8,
    pub feel: u8,
}

#[derive(Debug, Default)]
struct PokemonMisc {
    pokerus_status: u8,
    met_location: u8,
    origins_info: u16,
    ivs_eggs_and_ability: u32,
    ribbons_and_obedience: u32,
}

struct PcBuffer {
    data: [u8; DATA_SIZE as usize],
    index: usize,
}

impl fmt::Debug for PcBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "PC Buffer {}", self.index)
    }
}

const N_BOXES: usize = 14;

#[derive(Default)]
pub struct PokemonStorage {
    current_box: usize,
    boxes: Vec<PokeBox>,
}

impl fmt::Debug for PokemonStorage {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Pokemon storage: (current box: {})", self.current_box)?;
        for b in &self.boxes {
            b.fmt(f)?;
        }
        Ok(())
    }
}

const N_POKEMON_PER_BOX: usize = 30;

#[derive(Debug, Default)]
pub struct PokeBox {
    name: BoxName,
    wallpaper: u8,
    pub pokemon: [Option<Pokemon>; N_POKEMON_PER_BOX],
}
<commit_msg>Add immutable sections() method<commit_after>//! Library for manipulating Pokémon Gen3 (Fire Red/Leaf Green, Ruby/Emerald/Sapphire) save data.

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

mod util {
    mod lower_upper;
    pub use self::lower_upper::LowerUpper;
}
mod rw;

use crate::util::LowerUpper;
use std::error::Error;
use std::fs::File;
use std::path::Path;
use std::{fmt, io};

const UNKNOWN_SAVE_FOOTER_SIZE: usize = 16384;

/// Pokémon Gen3 save data.
pub struct Save {
    blocks: [SaveBlock; 2],
    unknown: [u8; UNKNOWN_SAVE_FOOTER_SIZE],
    most_recent_index: usize,
}

impl fmt::Debug for Save {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.blocks.fmt(f)
    }
}

impl Save {
    /// Load the save data from a file at the provided path.
    pub fn load_from_file<P: AsRef<Path>>(path: P) -> Result<Self, Box<Error>> {
        let mut file = File::open(path)?;
        Save::read(&mut file)
    }
    /// Save the save data to a file at the provided path.
    pub fn save_to_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), io::Error> {
        let mut file = File::create(path)?;
        self.write(&mut file)
    }
    pub fn sections_mut(&mut self) -> SaveSectionsMut {
        let block = &mut self.blocks[self.most_recent_index];
        let sections = &mut block.sections[..];
        let (team_items_sec, trainer_sec) = if block.team_and_items_index > block.trainer_info_index
        {
            let (lhs, rhs) = sections.split_at_mut(block.team_and_items_index);
            (&mut rhs[0], &mut lhs[block.trainer_info_index])
        } else {
            let (lhs, rhs) = sections.split_at_mut(block.trainer_info_index);
            (&mut lhs[block.team_and_items_index], &mut rhs[0])
        };
        let team_and_items = if let SectionData::TeamAndItems(ref mut data) = team_items_sec.data {
            data
        } else {
            panic!("Unexpected section data. Expected TeamAndItems");
        };
        let trainer_info = if let SectionData::TrainerInfo(ref mut data) = trainer_sec.data {
            data
        } else {
            panic!("Unexpected section data. Expected TrainerInfo");
        };
        SaveSectionsMut {
            team: &mut team_and_items.team,
            trainer: trainer_info,
            pc_boxes: &mut block.pokemon_storage.boxes,
        }
    }
    pub fn sections(&self) -> SaveSections {
        let block = &self.blocks[self.most_recent_index];
        let sections = &block.sections[..];
        let (team_items_sec, trainer_sec) = (
            &sections[block.team_and_items_index],
            &sections[block.trainer_info_index],
        );
        let team_and_items = if let SectionData::TeamAndItems(ref data) = team_items_sec.data {
            data
        } else {
            panic!("Unexpected section data. Expected TeamAndItems");
        };
        let trainer_info = if let SectionData::TrainerInfo(ref data) = trainer_sec.data {
            data
        } else {
            panic!("Unexpected section data. Expected TrainerInfo");
        };
        SaveSections {
            team: &team_and_items.team,
            trainer: trainer_info,
            pc_boxes: &block.pokemon_storage.boxes,
        }
    }
}

pub struct SaveSectionsMut<'a> {
    pub trainer: &'a mut TrainerInfo,
    pub team: &'a mut Vec<Pokemon>,
    pub pc_boxes: &'a mut [PokeBox],
}

pub struct SaveSections<'a> {
    pub trainer: &'a TrainerInfo,
    pub team: &'a Vec<Pokemon>,
    pub pc_boxes: &'a [PokeBox],
}

#[derive(Debug)]
struct SaveBlock {
    sections: Vec<Section>,
    trainer_info_index: usize,
    team_and_items_index: usize,
    // Does not exist yet, meaning the game has only been saved once, and this
    // block hasn't been written over yet.
    nonexistent: bool,
    pokemon_storage: PokemonStorage,
    box_indexes: [usize; N_BOXES],
}

#[allow(clippy::large_enum_variant)]
enum SectionData {
    Unimplemented {
        raw: [u8; DATA_SIZE as usize],
        id: u16,
        cksum: u16,
    },
    TrainerInfo(TrainerInfo),
    TeamAndItems(TeamAndItems),
    PcBuffer(PcBuffer),
}

impl fmt::Debug for SectionData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SectionData::Unimplemented { .. } => f.write_str("<Unimplemented section>"),
            SectionData::TrainerInfo(ref data) => data.fmt(f),
            SectionData::TeamAndItems(ref data) => data.fmt(f),
            SectionData::PcBuffer(ref data) => data.fmt(f),
        }
    }
}

#[derive(Debug)]
struct Section {
    data: SectionData,
    unknown_1: u32,
    save_idx: u32,
}

const DATA_SIZE: i64 = 0xFF4;

#[repr(u8)]
#[derive(Clone, Copy, Debug)]
enum Gender {
    Male = 0,
    Female = 1,
}

impl fmt::Display for Gender {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let str = match *self {
            Gender::Male => "Male",
            Gender::Female => "Female",
        };
        f.write_str(str)
    }
}

#[derive(Debug)]
struct Time {
    hours: u16,
    minutes: u8,
    seconds: u8,
    frames: u8,
}

const TRAINER_INFO_UNKNOWN_3_SIZE: usize = 0x00AC - (0x0013 + 3);
const RS_EM_PLAYERINFO_TRAILING_DATA_SIZE: usize = DATA_SIZE as usize - (0x0AC + 4);
const FRLG_PLAYERINFO_UNKNOWN_CHUNK_SIZE: usize = 0x0AF8 - (0x00AC + 4);
const FRLG_PLAYERINFO_TRAILING_DATA_SIZE: usize = DATA_SIZE as usize - (0x0AF8 + 4);

enum Game {
    RubyOrSapphire {
        trailing_data: [u8; RS_EM_PLAYERINFO_TRAILING_DATA_SIZE],
    },
    FireredOrLeafgreen {
        unknown: [u8; FRLG_PLAYERINFO_UNKNOWN_CHUNK_SIZE],
        security_key: u32,
        trailing_data: [u8; FRLG_PLAYERINFO_TRAILING_DATA_SIZE],
    },
    Emerald {
        security_key: u32,
        trailing_data: [u8; RS_EM_PLAYERINFO_TRAILING_DATA_SIZE],
    },
}

#[derive(Clone, Copy)]
enum GameType {
    RubyOrSapphire,
    FireredOrLeafgreen,
    Emerald,
}

impl<'a> From<&'a Game> for GameType {
    fn from(src: &Game) -> Self {
        match *src {
            Game::RubyOrSapphire { .. } => GameType::RubyOrSapphire,
            Game::FireredOrLeafgreen { .. } => GameType::FireredOrLeafgreen,
            Game::Emerald { .. } => GameType::Emerald,
        }
    }
}

impl fmt::Debug for Game {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Game::RubyOrSapphire { .. } => write!(f, "Ruby/Sapphire"),
            Game::FireredOrLeafgreen { security_key, .. } => {
                write!(f, "Fire Red/Leaf Green (security key: {})", security_key)
            }
            Game::Emerald { security_key, .. } => {
                write!(f, "Emerald (security key: {})", security_key)
            }
        }
    }
}

const TRAINER_NAME_LEN: usize = 7;

pub struct TrainerInfo {
    pub name: TrainerName,
    unknown_1: u8,
    gender: Gender,
    unknown_2: u8,
    public_id: u16,
    secret_id: u16,
    time_played: Time,
    options_data: [u8; 3],
    unknown_3: [u8; TRAINER_INFO_UNKNOWN_3_SIZE],
    game: Game,
}

impl TrainerInfo {
    pub fn full_id(&self) -> u32 {
        u32::merge(self.public_id, self.secret_id)
    }
}

impl fmt::Debug for TrainerInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("== Trainer Info ==\n")?;
        writeln!(f, "name: {:?}", self.name)?;
        writeln!(f, "gender: {:?}", self.gender)?;
        writeln!(
            f,
            "id: public({:?}) secret({:?}) combined({:?})",
            self.public_id,
            self.secret_id,
            u32::merge(self.public_id, self.secret_id)
        )?;
        writeln!(f, "Time played: {:?}", self.time_played)?;
        writeln!(f, "GAME ID: {:?}", self.game)
    }
}

const EM_RU_SA_TEAMANDITEMS_UNK_LEN: usize = 0x0234;
const FR_LG_TEAMANDITEMS_UNK_LEN: usize = 0x0034;
const TEAMANDITEMS_POKE_LEN: usize = 600;
const EM_RU_SA_TEAMANDITEMS_REM_LEN: usize =
    DATA_SIZE as usize - (EM_RU_SA_TEAMANDITEMS_UNK_LEN + TEAMANDITEMS_POKE_LEN + 4);
const FR_LG_TEAMANDITEMS_REM_LEN: usize =
    DATA_SIZE as usize - (FR_LG_TEAMANDITEMS_UNK_LEN + TEAMANDITEMS_POKE_LEN + 4);

#[allow(clippy::large_enum_variant)]
enum TeamAndItemsUnknown {
    EmeraldOrRubyOrSapphire([u8; EM_RU_SA_TEAMANDITEMS_UNK_LEN]),
    FireRedOrLeafGreen([u8; FR_LG_TEAMANDITEMS_UNK_LEN]),
}

#[allow(clippy::large_enum_variant)]
enum TeamAndItemsRemaining {
    EmeraldOrRubyOrSapphire([u8; EM_RU_SA_TEAMANDITEMS_REM_LEN]),
    FireredOrLeafgreen([u8; FR_LG_TEAMANDITEMS_REM_LEN]),
}

struct TeamAndItems {
    unknown: TeamAndItemsUnknown,
    team: Vec<Pokemon>,
    orig_pokemon_data: [u8; TEAMANDITEMS_POKE_LEN],
    remaining_data: TeamAndItemsRemaining,
}

impl fmt::Debug for TeamAndItems {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("=== Team And Items ===\nTeam listing:\n")?;
        for pokemon in &self.team {
            pokemon.fmt(f)?
        }
        Ok(())
    }
}

const POKEMON_NICK_LEN: usize = 10;

#[derive(Default, Clone, Copy)]
pub struct PokemonNick(pub [u8; POKEMON_NICK_LEN]);
#[derive(Default, Clone, Copy)]
pub struct TrainerName(pub [u8; TRAINER_NAME_LEN]);
#[derive(Default, Clone, Copy)]
pub struct BoxName(pub [u8; BOX_NAME_LEN]);

const BOX_NAME_LEN: usize = 8;

macro_rules! debug_impl {
    ($target:ident) => {
        impl fmt::Debug for $target {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "{}", rgen3_string::decode_string(&self.0[..]))
            }
        }
    };
}

debug_impl!(PokemonNick);
debug_impl!(TrainerName);
debug_impl!(BoxName);

/// A Pokemon.
#[derive(Debug, Default)]
#[allow(missing_docs)]
pub struct Pokemon {
    pub personality: u32,
    pub ot_id: u32,
    pub nickname: PokemonNick,
    language: u16,
    pub ot_name: TrainerName,
    markings: u8,
    checksum: u16,
    unknown_1: u16,
    pub data: PokemonData,
    pub active_data: Option<PokemonActiveData>,
}

#[derive(Debug)]
pub struct InvalidSpecies;

impl Pokemon {
    pub fn set_species(&mut self, num: u16) -> Result<(), InvalidSpecies> {
        match num {
            1...251 | 277...411 => {
                self.data.growth.species = num;
                Ok(())
            }
            _ => Err(InvalidSpecies),
        }
    }
}

/// "Active" data that is not stored in the PC boxes.
#[derive(Debug, Default)]
pub struct PokemonActiveData {
    status_condition: u32,
    pub level: u8,
    pokerus_remaining: u8,
    pub current_hp: u16,
    pub total_hp: u16,
    pub attack: u16,
    pub defense: u16,
    pub speed: u16,
    pub sp_attack: u16,
    pub sp_defense: u16,
}

#[derive(Debug, Default)]
pub struct PokemonData {
    pub growth: PokemonGrowth,
    pub attacks: PokemonAttacks,
    pub evs_and_condition: PokemonEvsAndCondition,
    misc: PokemonMisc,
}

#[derive(Debug, Default)]
pub struct PokemonGrowth {
    pub species: u16,
    item_held: u16,
    pub experience: u32,
    pub pp_bonuses: u8,
    pub friendship: u8,
    unknown: u16,
}

#[derive(Debug, Default)]
pub struct PokemonAttacks {
    pub move1: u16,
    pub move2: u16,
    pub move3: u16,
    pub move4: u16,
    pub pp1: u8,
    pub pp2: u8,
    pub pp3: u8,
    pub pp4: u8,
}

#[derive(Debug, Default)]
pub struct PokemonEvsAndCondition {
    pub hp: u8,
    pub attack: u8,
    pub defense: u8,
    pub speed: u8,
    pub sp_attack: u8,
    pub sp_defense: u8,
    pub coolness: u8,
    pub beauty: u8,
    pub cuteness: u8,
    pub smartness: u8,
    pub toughness: u8,
    pub feel: u8,
}

#[derive(Debug, Default)]
struct PokemonMisc {
    pokerus_status: u8,
    met_location: u8,
    origins_info: u16,
    ivs_eggs_and_ability: u32,
    ribbons_and_obedience: u32,
}

struct PcBuffer {
    data: [u8; DATA_SIZE as usize],
    index: usize,
}

impl fmt::Debug for PcBuffer {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "PC Buffer {}", self.index)
    }
}

const N_BOXES: usize = 14;

#[derive(Default)]
pub struct PokemonStorage {
    current_box: usize,
    boxes: Vec<PokeBox>,
}

impl fmt::Debug for PokemonStorage {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Pokemon storage: (current box: {})", self.current_box)?;
        for b in &self.boxes {
            b.fmt(f)?;
        }
        Ok(())
    }
}

const N_POKEMON_PER_BOX: usize = 30;

#[derive(Debug, Default)]
pub struct PokeBox {
    name: BoxName,
    wallpaper: u8,
    pub pokemon: [Option<Pokemon>; N_POKEMON_PER_BOX],
}
<|endoftext|>


<commit_before>///! # Robin-CLI
///!
///! This module defines the CLI for Robin

#[macro_use]
extern crate clap;

extern crate rustyline;
extern crate robin_core;
extern crate itertools;

use std::process::{Command, Child, Stdio};
use std::io::{Read, Write};
use std::fs::File;

use rustyline::Editor;
use itertools::join;
use clap::{App, Arg, ArgMatches};

use robin_core::parser;
use robin_core::compiler::Compiler;

/// This struct handles the matches from the CLI
#[derive(Clone)]
struct CLI<'a> {
    args: ArgMatches<'a>
}

impl<'a> CLI<'a> {
    fn new() -> CLI<'a> {
        // Create a new handler for the user input
        let app = App::new("Robin CLI")
            .name(crate_name!())
            .about(crate_description!())
            .version(crate_version!())
            .author(crate_authors!())

            // Add an argument for the repl
            .arg(Arg::with_name("repl")
                    .short("r")
                    .long("repl")
                    .help("Start the repl")
                    .takes_value(false))

            // Add an argument for the input files
            .arg(Arg::with_name("input")
                    .short("i")
                    .long("input")
                    .value_name("input")
                    .multiple(true))

            // Add an argument for the output file
            .arg(Arg::with_name("output")
                    .short("o")
                    .long("output")
                    .value_name("output"));

        CLI{args: app.get_matches()}
    }

    fn handle_results(self) {
        // If repl has been given
        if self.args.is_present("repl") {
            Repl::new().repl()
        }

        // To compile, input and output arguments are required
        match (self.args.values_of("input"), self.args.value_of("output")) {
            // If both have been given
            (Some(file_names), Some(output)) => {
                // Open each file, read from the files, join them and compile them.
                // Then write the output

                let mut files = vec![];

                file_names.for_each(|file| files.push(file));

                let content = self.read_files(files);

                self.compile(&content, output);
            },
            (Some(_), _) => println!("Input given without output name"),
            (_, Some(_)) => println!("Output given without input name"),
            (None, None) => {}
        }
    }

    fn read_files(&self, filenames: Vec<&str>) -> String {
        // Open each of the files and join them with nothing
        join(filenames.into_iter().map(|file_name| {
            let mut file = File::open(file_name).expect(&format!("{} not found", file_name));

            let mut content = String::new();

            file.read_to_string(&mut content).expect(&format!("Cannot read from {}", file_name));

            content
        }), "")
    }

    fn compile(&self, content: &str, output: &str) {
        // Parse the input and compile the output
        let mut compiler = Compiler::new();

        match parser::ExprsParser::new().parse(content) {
            // TODO: Remove this unwrap
            Ok(mut expr) => {
                let result = compiler.compile(expr.as_mut_slice());

                // Show errors if they occur
                // TODO: Handle error stack here
                if !compiler.errors.0.is_empty() {
                    compiler.errors.0
                        .iter()
                        .for_each(|e| println!("{}", e));

                    // Clear the error stack on each input
                    compiler.errors.0.clear();

                } else {
                    // If no errors occur, then write the contents
                    self.write_files(&result, &output)
                }
            },

            Err(e) => {
                // TODO: Handle this error
                panic!("Error: {}", e);
            }
        }
    }

    fn write_files(&self, content: &str, output: &str) {
        // Create the file and write to it
        let mut new_file = File::create(output).expect(&format!("Unable to create file: {}", output));

        new_file.write_all(content.as_bytes()).expect(&format!("Unable to write to file: {}", output));
    }
}

/// Create a struct representing the repl
struct Repl<'a> {
    editor: Editor<()>,
    compiler: Compiler<'a>,

    // Node represents the background node.js process
    node: Child,
}

impl<'a> Repl<'a> {
    fn new() -> Repl<'a> {
        Repl {
            editor: Editor::<()>::new(),
            compiler: Compiler::new(),
            node: Command::new("node")
                        .stdin(Stdio::piped())
                        .stdout(Stdio::inherit())

                        // Use the --interactive flag to start the REPL despite stdin not
                        // being a terminal see node --help for more
                        .args(&["-i"])
                        .spawn()
                        .expect("Node.js not installed or found in path, please install from: https://nodejs.org/en/ and check if in path using the 'node' command")
        }
    }

    fn repl(&mut self) {
        println!("Welcome to Robin! Type code in below.");

        println!("Ignore the second prompt!");

        println!("When you run code in the REPL, you might find some Robin and some Node.js errors! Be careful");

        // Iterate for ever
        loop {
            let readline = self.editor.readline("robin> ");

            match readline {
                Ok(line) => {
                    self.parse(&line);

                    self.editor.add_history_entry(&line);
                }

                Err(_) => break,
            }
        }
    }

    // Clear the input
    fn handle_node_repl(&mut self, input: String) {
        if let Some(ref mut stdin) = self.node.stdin.as_mut() {
            write!(stdin, "{}\n", input).unwrap();

            stdin.flush().unwrap();
        }
    }

    // Parse the text
    fn parse(&mut self, line: &str) {
        match parser::ExprsParser::new().parse(line) {
            // TODO: Remove this unwrap
            Ok(mut expr) => {
                let output = self.compiler.compile(expr.as_mut_slice());

                // Print the errors
                // TODO: Handle error stack here
                if !self.compiler.errors.0.is_empty() {
                    self.compiler.errors.0
                        .iter()
                        .for_each(|e| println!("{}", e));

                    // Clear the error stack on each input
                    self.compiler.errors.0.clear();

                } else {
                    self.handle_node_repl(output);
                }
            },

            Err(e) => {
                // TODO: Handle this error
                panic!("Error: {}", e);
                //println!("Error");
            }
        }
    }
}

fn main() {
    let cli = CLI::new();

    cli.handle_results();
}
<commit_msg>Change prompt<commit_after>///! # Robin-CLI
///!
///! This module defines the CLI for Robin

#[macro_use]
extern crate clap;

extern crate rustyline;
extern crate robin_core;
extern crate itertools;

use std::process::{Command, Child, Stdio};
use std::io::{Read, Write};
use std::fs::File;

use rustyline::Editor;
use itertools::join;
use clap::{App, Arg, ArgMatches};

use robin_core::parser;
use robin_core::compiler::Compiler;

/// This struct handles the matches from the CLI
#[derive(Clone)]
struct CLI<'a> {
    args: ArgMatches<'a>
}

impl<'a> CLI<'a> {
    fn new() -> CLI<'a> {
        // Create a new handler for the user input
        let app = App::new("Robin CLI")
            .name(crate_name!())
            .about(crate_description!())
            .version(crate_version!())
            .author(crate_authors!())

            // Add an argument for the repl
            .arg(Arg::with_name("repl")
                    .short("r")
                    .long("repl")
                    .help("Start the repl")
                    .takes_value(false))

            // Add an argument for the input files
            .arg(Arg::with_name("input")
                    .short("i")
                    .long("input")
                    .value_name("input")
                    .multiple(true))

            // Add an argument for the output file
            .arg(Arg::with_name("output")
                    .short("o")
                    .long("output")
                    .value_name("output"));

        CLI{args: app.get_matches()}
    }

    fn handle_results(self) {
        // If repl has been given
        if self.args.is_present("repl") {
            Repl::new().repl()
        }

        // To compile, input and output arguments are required
        match (self.args.values_of("input"), self.args.value_of("output")) {
            // If both have been given
            (Some(file_names), Some(output)) => {
                // Open each file, read from the files, join them and compile them.
                // Then write the output

                let mut files = vec![];

                file_names.for_each(|file| files.push(file));

                let content = self.read_files(files);

                self.compile(&content, output);
            },
            (Some(_), _) => println!("Input given without output name"),
            (_, Some(_)) => println!("Output given without input name"),
            (None, None) => {}
        }
    }

    fn read_files(&self, filenames: Vec<&str>) -> String {
        // Open each of the files and join them with nothing
        join(filenames.into_iter().map(|file_name| {
            let mut file = File::open(file_name).expect(&format!("{} not found", file_name));

            let mut content = String::new();

            file.read_to_string(&mut content).expect(&format!("Cannot read from {}", file_name));

            content
        }), "")
    }

    fn compile(&self, content: &str, output: &str) {
        // Parse the input and compile the output
        let mut compiler = Compiler::new();

        match parser::ExprsParser::new().parse(content) {
            // TODO: Remove this unwrap
            Ok(mut expr) => {
                let result = compiler.compile(expr.as_mut_slice());

                // Show errors if they occur
                // TODO: Handle error stack here
                if !compiler.errors.0.is_empty() {
                    compiler.errors.0
                        .iter()
                        .for_each(|e| println!("{}", e));

                    // Clear the error stack on each input
                    compiler.errors.0.clear();

                } else {
                    // If no errors occur, then write the contents
                    self.write_files(&result, &output)
                }
            },

            Err(e) => {
                // TODO: Handle this error
                panic!("Error: {}", e);
            }
        }
    }

    fn write_files(&self, content: &str, output: &str) {
        // Create the file and write to it
        let mut new_file = File::create(output).expect(&format!("Unable to create file: {}", output));

        new_file.write_all(content.as_bytes()).expect(&format!("Unable to write to file: {}", output));
    }
}

/// Create a struct representing the repl
struct Repl<'a> {
    editor: Editor<()>,
    compiler: Compiler<'a>,

    // Node represents the background node.js process
    node: Child,
}

impl<'a> Repl<'a> {
    fn new() -> Repl<'a> {
        Repl {
            editor: Editor::<()>::new(),
            compiler: Compiler::new(),
            node: Command::new("node")
                        .stdin(Stdio::piped())
                        .stdout(Stdio::inherit())

                        // Use the --interactive flag to start the REPL despite stdin not
                        // being a terminal see node --help for more
                        .args(&["-i"])
                        .spawn()
                        .expect("Node.js not installed or found in path, please install from: https://nodejs.org/en/ and check if in path using the 'node' command")
        }
    }

    fn repl(&mut self) {
        println!("Welcome to Robin! Type code in below.");

        println!("Ignore the second prompt!");

        println!("When you run code in the REPL, you might find some Robin and some Node.js errors! Be careful");

        // Iterate for ever
        loop {
            let readline = self.editor.readline("> ");

            match readline {
                Ok(line) => {
                    self.parse(&line);

                    self.editor.add_history_entry(&line);
                }

                Err(_) => break,
            }
        }
    }

    // Clear the input
    fn handle_node_repl(&mut self, input: String) {
        if let Some(ref mut stdin) = self.node.stdin.as_mut() {
            write!(stdin, "{}\n", input).unwrap();

            stdin.flush().unwrap();
        }
    }

    // Parse the text
    fn parse(&mut self, line: &str) {
        match parser::ExprsParser::new().parse(line) {
            // TODO: Remove this unwrap
            Ok(mut expr) => {
                let output = self.compiler.compile(expr.as_mut_slice());

                // Print the errors
                // TODO: Handle error stack here
                if !self.compiler.errors.0.is_empty() {
                    self.compiler.errors.0
                        .iter()
                        .for_each(|e| println!("{}", e));

                    // Clear the error stack on each input
                    self.compiler.errors.0.clear();

                } else {
                    self.handle_node_repl(output);
                }
            },

            Err(e) => {
                // TODO: Handle this error
                panic!("Error: {}", e);
                //println!("Error");
            }
        }
    }
}

fn main() {
    let cli = CLI::new();

    cli.handle_results();
}
<|endoftext|>


<commit_before>#![allow(arithmetic_overflow)]

pub fn main() {
    // This tests that do (not) do sign extension properly when loading integers
    assert_eq!(u32::MAX as i64, 4294967295);
    assert_eq!(i32::MIN as i64, -2147483648);

    assert_eq!(i8::MAX, 127);
    assert_eq!(i8::MIN, -128);

    assert_eq!(i32::from_str_radix("A", 16), Ok(10));

    let n = -0b1000_0000i8;
    assert_eq!(n.count_ones(), 1);

    let n = -0b1000_0000i8;
    assert_eq!(n.count_zeros(), 7);

    let n = -1i16;
    assert_eq!(n.leading_zeros(), 0);

    let n = -4i8;
    assert_eq!(n.trailing_zeros(), 2);

    let n = 0x0123456789ABCDEFi64;
    let m = -0x76543210FEDCBA99i64;
    assert_eq!(n.rotate_left(32), m);

    let n = 0x0123456789ABCDEFi64;
    let m = -0xFEDCBA987654322i64;
    assert_eq!(n.rotate_right(4), m);

    let n =  0x0123456789ABCDEFi64;
    let m = -0x1032547698BADCFFi64;
    assert_eq!(n.swap_bytes(), m);

    let n = 0x0123456789ABCDEFi64;
    if cfg!(target_endian = "big") {
        assert_eq!(i64::from_be(n), n)
    } else {
        assert_eq!(i64::from_be(n), n.swap_bytes())
    }

    let n = 0x0123456789ABCDEFi64;
    if cfg!(target_endian = "little") {
        assert_eq!(i64::from_le(n), n)
    } else {
        assert_eq!(i64::from_le(n), n.swap_bytes())
    }

    let n = 0x0123456789ABCDEFi64;
    if cfg!(target_endian = "big") {
        assert_eq!(n.to_be(), n)
    } else {
        assert_eq!(n.to_be(), n.swap_bytes())
    }

    let n = 0x0123456789ABCDEFi64;
    if cfg!(target_endian = "little") {
        assert_eq!(n.to_le(), n)
    } else {
        assert_eq!(n.to_le(), n.swap_bytes())
    }

    assert_eq!(7i16.checked_add(32760), Some(32767));
    assert_eq!(8i16.checked_add(32760), None);

    assert_eq!((-127i8).checked_sub(1), Some(-128));
    assert_eq!((-128i8).checked_sub(1), None);

    assert_eq!(6i8.checked_mul(21), Some(126));
    assert_eq!(6i8.checked_mul(22), None);

    assert_eq!((-127i8).checked_div(-1), Some(127));
    assert_eq!((-128i8).checked_div(-1), None);
    assert_eq!((1i8).checked_div(0), None);

    assert_eq!(5i32.checked_rem(2), Some(1));
    assert_eq!(5i32.checked_rem(0), None);
    assert_eq!(i32::MIN.checked_rem(-1), None);

    assert_eq!(5i32.checked_neg(), Some(-5));
    assert_eq!(i32::MIN.checked_neg(), None);

    assert_eq!(0x10i32.checked_shl(4), Some(0x100));
    assert_eq!(0x10i32.checked_shl(33), None);

    assert_eq!(0x10i32.checked_shr(4), Some(0x1));
    assert_eq!(0x10i32.checked_shr(33), None);

    assert_eq!((-5i32).checked_abs(), Some(5));
    assert_eq!(i32::MIN.checked_abs(), None);

    assert_eq!(100i8.saturating_add(1), 101);
    assert_eq!(100i8.saturating_add(127), 127);

    assert_eq!(100i8.saturating_sub(127), -27);
    assert_eq!((-100i8).saturating_sub(127), -128);

    assert_eq!(100i32.saturating_mul(127), 12700);
    assert_eq!((1i32 << 23).saturating_mul(1 << 23), i32::MAX);
    assert_eq!((-1i32 << 23).saturating_mul(1 << 23), i32::MIN);

    assert_eq!(100i8.wrapping_add(27), 127);
    assert_eq!(100i8.wrapping_add(127), -29);

    assert_eq!(0i8.wrapping_sub(127), -127);
    assert_eq!((-2i8).wrapping_sub(127), 127);

    assert_eq!(10i8.wrapping_mul(12), 120);
    assert_eq!(11i8.wrapping_mul(12), -124);

    assert_eq!(100u8.wrapping_div(10), 10);
    assert_eq!((-128i8).wrapping_div(-1), -128);

    assert_eq!(100i8.wrapping_rem(10), 0);
    assert_eq!((-128i8).wrapping_rem(-1), 0);

    assert_eq!(i32::MIN.wrapping_div(-1), i32::MIN);
    assert_eq!(i32::MIN.wrapping_rem(-1), 0);

    assert_eq!(100i8.wrapping_neg(), -100);
    assert_eq!((-128i8).wrapping_neg(), -128);

    assert_eq!((-1i8).wrapping_shl(7), -128);
    assert_eq!((-1i8).wrapping_shl(8), -1);

    assert_eq!((-128i8).wrapping_shr(7), -1);
    assert_eq!((-128i8).wrapping_shr(8), -128);

    assert_eq!(100i8.wrapping_abs(), 100);
    assert_eq!((-100i8).wrapping_abs(), 100);
    assert_eq!((-128i8).wrapping_abs(), -128);
    assert_eq!((-128i8).wrapping_abs() as u8, 128);

    assert_eq!(5i32.overflowing_add(2), (7, false));
    assert_eq!(i32::MAX.overflowing_add(1), (i32::MIN, true));

    assert_eq!(5i32.overflowing_sub(2), (3, false));
    assert_eq!(i32::MIN.overflowing_sub(1), (i32::MAX, true));

    assert_eq!(5i32.overflowing_mul(2), (10, false));
    assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));

    assert_eq!(5i32.overflowing_div(2), (2, false));
    assert_eq!(i32::MIN.overflowing_div(-1), (i32::MIN, true));

    assert_eq!(5i32.overflowing_rem(2), (1, false));
    assert_eq!(i32::MIN.overflowing_rem(-1), (0, true));

    assert_eq!(2i32.overflowing_neg(), (-2, false));
    assert_eq!(i32::MIN.overflowing_neg(), (i32::MIN, true));

    assert_eq!(0x10i32.overflowing_shl(4), (0x100, false));
    assert_eq!(0x10i32.overflowing_shl(36), (0x100, true));

    assert_eq!(0x10i32.overflowing_shr(4), (0x1, false));
    assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));

    assert_eq!(10i8.overflowing_abs(), (10,false));
    assert_eq!((-10i8).overflowing_abs(), (10,false));
    assert_eq!((-128i8).overflowing_abs(), (-128,true));
}
<commit_msg>Auto merge of #2002 - RalfJung:negative-shifts, r=RalfJung<commit_after>// compile-flags: -Coverflow-checks=off
#![allow(arithmetic_overflow)]

pub fn main() {
    // This tests that we do (not) do sign extension properly when loading integers
    assert_eq!(u32::MAX as i64, 4294967295);
    assert_eq!(i32::MIN as i64, -2147483648);

    assert_eq!(i8::MAX, 127);
    assert_eq!(i8::MIN, -128);

    // Shifts with negative offsets are subtle.
    assert_eq!(13 << -2i8, 13 << 254);
    assert_eq!(13 << i8::MIN, 13);
    assert_eq!(13 << -1i16, 13 << u16::MAX);
    assert_eq!(13 << i16::MIN, 13);
    assert_eq!(13i128 << -2i8, 13i128 << 254);
    assert_eq!(13i128 << i8::MIN, 13);
    assert_eq!(13i128 << -1i16, 13i128 << u16::MAX);
    assert_eq!(13i128 << i16::MIN, 13);

    assert_eq!(i32::from_str_radix("A", 16), Ok(10));

    let n = -0b1000_0000i8;
    assert_eq!(n.count_ones(), 1);

    let n = -0b1000_0000i8;
    assert_eq!(n.count_zeros(), 7);

    let n = -1i16;
    assert_eq!(n.leading_zeros(), 0);

    let n = -4i8;
    assert_eq!(n.trailing_zeros(), 2);

    let n = 0x0123456789ABCDEFi64;
    let m = -0x76543210FEDCBA99i64;
    assert_eq!(n.rotate_left(32), m);

    let n = 0x0123456789ABCDEFi64;
    let m = -0xFEDCBA987654322i64;
    assert_eq!(n.rotate_right(4), m);

    let n =  0x0123456789ABCDEFi64;
    let m = -0x1032547698BADCFFi64;
    assert_eq!(n.swap_bytes(), m);

    let n = 0x0123456789ABCDEFi64;
    if cfg!(target_endian = "big") {
        assert_eq!(i64::from_be(n), n)
    } else {
        assert_eq!(i64::from_be(n), n.swap_bytes())
    }

    let n = 0x0123456789ABCDEFi64;
    if cfg!(target_endian = "little") {
        assert_eq!(i64::from_le(n), n)
    } else {
        assert_eq!(i64::from_le(n), n.swap_bytes())
    }

    let n = 0x0123456789ABCDEFi64;
    if cfg!(target_endian = "big") {
        assert_eq!(n.to_be(), n)
    } else {
        assert_eq!(n.to_be(), n.swap_bytes())
    }

    let n = 0x0123456789ABCDEFi64;
    if cfg!(target_endian = "little") {
        assert_eq!(n.to_le(), n)
    } else {
        assert_eq!(n.to_le(), n.swap_bytes())
    }

    assert_eq!(7i16.checked_add(32760), Some(32767));
    assert_eq!(8i16.checked_add(32760), None);

    assert_eq!((-127i8).checked_sub(1), Some(-128));
    assert_eq!((-128i8).checked_sub(1), None);

    assert_eq!(6i8.checked_mul(21), Some(126));
    assert_eq!(6i8.checked_mul(22), None);

    assert_eq!((-127i8).checked_div(-1), Some(127));
    assert_eq!((-128i8).checked_div(-1), None);
    assert_eq!((1i8).checked_div(0), None);

    assert_eq!(5i32.checked_rem(2), Some(1));
    assert_eq!(5i32.checked_rem(0), None);
    assert_eq!(i32::MIN.checked_rem(-1), None);

    assert_eq!(5i32.checked_neg(), Some(-5));
    assert_eq!(i32::MIN.checked_neg(), None);

    assert_eq!(0x10i32.checked_shl(4), Some(0x100));
    assert_eq!(0x10i32.checked_shl(33), None);

    assert_eq!(0x10i32.checked_shr(4), Some(0x1));
    assert_eq!(0x10i32.checked_shr(33), None);

    assert_eq!((-5i32).checked_abs(), Some(5));
    assert_eq!(i32::MIN.checked_abs(), None);

    assert_eq!(100i8.saturating_add(1), 101);
    assert_eq!(100i8.saturating_add(127), 127);

    assert_eq!(100i8.saturating_sub(127), -27);
    assert_eq!((-100i8).saturating_sub(127), -128);

    assert_eq!(100i32.saturating_mul(127), 12700);
    assert_eq!((1i32 << 23).saturating_mul(1 << 23), i32::MAX);
    assert_eq!((-1i32 << 23).saturating_mul(1 << 23), i32::MIN);

    assert_eq!(100i8.wrapping_add(27), 127);
    assert_eq!(100i8.wrapping_add(127), -29);

    assert_eq!(0i8.wrapping_sub(127), -127);
    assert_eq!((-2i8).wrapping_sub(127), 127);

    assert_eq!(10i8.wrapping_mul(12), 120);
    assert_eq!(11i8.wrapping_mul(12), -124);

    assert_eq!(100u8.wrapping_div(10), 10);
    assert_eq!((-128i8).wrapping_div(-1), -128);

    assert_eq!(100i8.wrapping_rem(10), 0);
    assert_eq!((-128i8).wrapping_rem(-1), 0);

    assert_eq!(i32::MIN.wrapping_div(-1), i32::MIN);
    assert_eq!(i32::MIN.wrapping_rem(-1), 0);

    assert_eq!(100i8.wrapping_neg(), -100);
    assert_eq!((-128i8).wrapping_neg(), -128);

    assert_eq!((-1i8).wrapping_shl(7), -128);
    assert_eq!((-1i8).wrapping_shl(8), -1);

    assert_eq!((-128i8).wrapping_shr(7), -1);
    assert_eq!((-128i8).wrapping_shr(8), -128);

    assert_eq!(100i8.wrapping_abs(), 100);
    assert_eq!((-100i8).wrapping_abs(), 100);
    assert_eq!((-128i8).wrapping_abs(), -128);
    assert_eq!((-128i8).wrapping_abs() as u8, 128);

    assert_eq!(5i32.overflowing_add(2), (7, false));
    assert_eq!(i32::MAX.overflowing_add(1), (i32::MIN, true));

    assert_eq!(5i32.overflowing_sub(2), (3, false));
    assert_eq!(i32::MIN.overflowing_sub(1), (i32::MAX, true));

    assert_eq!(5i32.overflowing_mul(2), (10, false));
    assert_eq!(1_000_000_000i32.overflowing_mul(10), (1410065408, true));

    assert_eq!(5i32.overflowing_div(2), (2, false));
    assert_eq!(i32::MIN.overflowing_div(-1), (i32::MIN, true));

    assert_eq!(5i32.overflowing_rem(2), (1, false));
    assert_eq!(i32::MIN.overflowing_rem(-1), (0, true));

    assert_eq!(2i32.overflowing_neg(), (-2, false));
    assert_eq!(i32::MIN.overflowing_neg(), (i32::MIN, true));

    assert_eq!(0x10i32.overflowing_shl(4), (0x100, false));
    assert_eq!(0x10i32.overflowing_shl(36), (0x100, true));

    assert_eq!(0x10i32.overflowing_shr(4), (0x1, false));
    assert_eq!(0x10i32.overflowing_shr(36), (0x1, true));

    assert_eq!(10i8.overflowing_abs(), (10,false));
    assert_eq!((-10i8).overflowing_abs(), (10,false));
    assert_eq!((-128i8).overflowing_abs(), (-128,true));
}
<|endoftext|>


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

use ggez::{filesystem, Context};
use serde_derive::{Deserialize, Serialize};
use serde_yaml::Value;
use warmy;

use loadable_yaml_macro_derive::LoadableYaml;
use crate::error::LoadError;
use crate::manager::GameYaml;

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct SpriteData {
    pub sprites: HashMap<String, Sprite>,
}

#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum ImageType {
    NonSolid,
    Collidee,
    Collider,
    Blood,
    BloodStain,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Image {
    pub sheet: String,
    pub image: usize,
    pub x: i32,
    pub y: i32,
    pub image_type: ImageType,
}

impl Image {
    pub fn is_collidee(&self) -> bool {
        self.image_type == ImageType::Collidee
    }

    pub fn is_collider(&self) -> bool {
        self.image_type == ImageType::Collider
    }

    pub fn is_blood(&self) -> bool {
        match self.image_type {
            ImageType::Blood | ImageType::BloodStain => true,
            _ => false,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Frame {
    pub images: Vec<Image>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Animation {
    pub frames: Vec<Frame>,
    #[serde(default)]
    pub order: Option<Vec<i32>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Sprite {
    pub animations: HashMap<String, Animation>,
}

impl warmy::Load<Context, warmy::SimpleKey> for Sprite {
    type Error = LoadError<GameYaml>;

    fn load(
        key: warmy::SimpleKey,
        _store: &mut warmy::Storage<ggez::Context, warmy::SimpleKey>,
        ctx: &mut ggez::Context,
    ) -> Result<warmy::Loaded<Self, warmy::SimpleKey>, Self::Error> {
        match key {
            warmy::SimpleKey::Logical(key) => {
                let file = filesystem::open(ctx, key)?;
                let yaml: Value = serde_yaml::from_reader(file)?;

                Ok(warmy::Loaded::from(Sprite {
                    animations: serde_yaml::from_value(yaml)?,
                }))
            }
            warmy::SimpleKey::Path(_) => return Err(LoadError::PathLoadNotImplemented),
        }
    }
}
<commit_msg>Make Sprite serde(transparent), simplifying loader.<commit_after>use std::collections::HashMap;

use ggez::{filesystem, Context};
use serde_derive::{Deserialize, Serialize};
use serde_yaml::Value;
use warmy;

use crate::error::LoadError;
use crate::manager::GameYaml;
use loadable_yaml_macro_derive::LoadableYaml;

#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct SpriteData {
    pub sprites: HashMap<String, Sprite>,
}

#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub enum ImageType {
    NonSolid,
    Collidee,
    Collider,
    Blood,
    BloodStain,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Image {
    pub sheet: String,
    pub image: usize,
    pub x: i32,
    pub y: i32,
    pub image_type: ImageType,
}

impl Image {
    pub fn is_collidee(&self) -> bool {
        self.image_type == ImageType::Collidee
    }

    pub fn is_collider(&self) -> bool {
        self.image_type == ImageType::Collider
    }

    pub fn is_blood(&self) -> bool {
        match self.image_type {
            ImageType::Blood | ImageType::BloodStain => true,
            _ => false,
        }
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Frame {
    pub images: Vec<Image>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Animation {
    pub frames: Vec<Frame>,
    #[serde(default)]
    pub order: Option<Vec<i32>>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Sprite {
    pub animations: HashMap<String, Animation>,
}

impl warmy::Load<Context, warmy::SimpleKey> for Sprite {
    type Error = LoadError<GameYaml>;

    fn load(
        key: warmy::SimpleKey,
        _store: &mut warmy::Storage<ggez::Context, warmy::SimpleKey>,
        ctx: &mut ggez::Context,
    ) -> Result<warmy::Loaded<Self, warmy::SimpleKey>, Self::Error> {
        match key {
            warmy::SimpleKey::Logical(key) => filesystem::open(ctx, key)
                .map(serde_yaml::from_reader::<filesystem::File, Sprite>)?
                .map(warmy::Loaded::from)
                .map_err(|e| e.into()),
            warmy::SimpleKey::Path(_) => return Err(LoadError::PathLoadNotImplemented),
        }
    }
}
<|endoftext|>


<commit_before>extern crate lalrpop_util;
extern crate glib;
extern crate libc;

extern crate cairo;
use self::cairo::MatrixTrait;
use self::glib::translate::*;

use std::f64::consts::*;

use parse_transform::*;

use error::*;
use parsers::ParseError;

pub fn parse_transform (s: &str) -> Result <cairo::Matrix, AttributeError> {
    let r = parse_TransformList (s);

    match r {
        Ok (m) => {
            m.try_invert ().map (|_| m)
                .map_err (|_| AttributeError::Value ("invalid transformation matrix".to_string ()))
        },

        Err (e) => {
            Err (AttributeError::Parse (ParseError::new (format! ("{:?}", e))))
        }
    }
}

fn make_rotation_matrix (angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
    let angle = angle_degrees * PI / 180.0;

    let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

    let mut r = cairo::Matrix::identity ();
    r.rotate (angle);
    m = cairo::Matrix::multiply (&r, &m);

    m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
    m
}

#[no_mangle]
pub fn rsvg_parse_transform (out_matrix: *mut cairo::Matrix, s: *const libc::c_char) -> bool {
    assert! (!out_matrix.is_null ());
    assert! (!s.is_null ());

    let string = unsafe { String::from_glib_none (s) };
    let matrix: &mut cairo::Matrix = unsafe { &mut *out_matrix };

    match parse_transform (&string) {
        Ok (m) => {
            *matrix = m;
            true
        },

        Err (_) => {
            *matrix = cairo::Matrix::identity ();
            false
        }
    }
}

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

    #[test]
    fn parses_valid_transform () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }

    #[test]
    fn syntax_error_yields_parse_error () {
        match parse_transform ("foo") {
            Err (AttributeError::Parse (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("matrix (1 2 3 4 5)") {
            Err (AttributeError::Parse (_)) => {},
            _ => { panic! (); }
        }
    }

    #[test]
    fn invalid_transform_yields_value_error () {
        match parse_transform ("matrix (0 0 0 0 0 0)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), translate (10, 10)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), skewX (90)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }
    }
}

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

    #[test]
    fn parses_numbers () {
        assert_eq! (parse_Num ("0"),          Ok (0.0));
        assert_eq! (parse_Num ("12345"),      Ok (12345.0));
        assert_eq! (parse_Num ("-123"),       Ok (-123.0));
        assert_eq! (parse_Num ("-123.25"),    Ok (-123.25));
        assert_eq! (parse_Num ("123.25"),     Ok (123.25));
        assert_eq! (parse_Num ("-.25"),       Ok (-0.25));
        assert_eq! (parse_Num (".25"),        Ok (0.25));
        assert_eq! (parse_Num ("-25."),       Ok (-25.0));
        assert_eq! (parse_Num ("25."),        Ok (25.0));
        assert_eq! (parse_Num ("22.5e1"),     Ok (225.0));
        assert_eq! (parse_Num ("-22.5e1"),    Ok (-225.0));
        assert_eq! (parse_Num ("-123.45e2"),  Ok (-12345.0));
        assert_eq! (parse_Num ("123.45E2"),   Ok (12345.0));
        assert_eq! (parse_Num ("-123.25e-2"), Ok (-1.2325));
        assert_eq! (parse_Num ("123.25E-2"),  Ok (1.2325));
    }

    #[test]
    fn parses_matrix () {
        assert_eq! (parse_Matrix ("matrix (1 2 3 4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_Matrix ("matrix (1,2,3,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_Matrix ("matrix (1,2.25,-3.25e2,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.25, -325.0, 4.0, 5.0, 6.0));
    }

    #[test]
    fn parses_translate () {
        assert_eq! (parse_Translate ("translate(-1 -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_Translate ("translate(-1, -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_Translate ("translate(-1)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, 0.0));
    }

    #[test]
    fn parses_scale () {
        assert_eq! (parse_Scale ("scale(-1 -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_Scale ("scale(-1, -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_Scale ("scale(-1)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
    }

    #[test]
    fn parses_rotate () {
        assert_eq! (parse_Rotate ("rotate (30)").unwrap (), make_rotation_matrix (30.0, 0.0, 0.0));
        assert_eq! (parse_Rotate ("rotate (30,-1,-2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
        assert_eq! (parse_Rotate ("rotate (30, -1, -2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
    }

    fn make_skew_x_matrix (angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new (1.0,      0.0,
                            a.tan (), 1.0,
                            0.0, 0.0)
    }

    fn make_skew_y_matrix (angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix (angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    fn parses_skew_x () {
        assert_eq! (parse_SkewX ("skewX (30)").unwrap (), make_skew_x_matrix (30.0));
    }

    #[test]
    fn parses_skew_y () {
        assert_eq! (parse_SkewY ("skewY (30)").unwrap (), make_skew_y_matrix (30.0));
    }

    #[test]
    fn parses_transform_list () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        assert_eq! (parse_TransformList ("scale(10)rotate(30, 10, 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &s));

        assert_eq! (parse_TransformList ("translate(20, 30), scale (10)").unwrap (),
                    cairo::Matrix::multiply (&s, &t));

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_TransformList ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }
}
<commit_msg>transform.rs: bool -> glib_sys::gboolean<commit_after>extern crate lalrpop_util;
extern crate glib_sys;
extern crate glib;
extern crate libc;

extern crate cairo;
use self::cairo::MatrixTrait;
use self::glib::translate::*;

use std::f64::consts::*;

use parse_transform::*;

use error::*;
use parsers::ParseError;

pub fn parse_transform (s: &str) -> Result <cairo::Matrix, AttributeError> {
    let r = parse_TransformList (s);

    match r {
        Ok (m) => {
            m.try_invert ().map (|_| m)
                .map_err (|_| AttributeError::Value ("invalid transformation matrix".to_string ()))
        },

        Err (e) => {
            Err (AttributeError::Parse (ParseError::new (format! ("{:?}", e))))
        }
    }
}

fn make_rotation_matrix (angle_degrees: f64, tx: f64, ty: f64) -> cairo::Matrix {
    let angle = angle_degrees * PI / 180.0;

    let mut m = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, tx, ty);

    let mut r = cairo::Matrix::identity ();
    r.rotate (angle);
    m = cairo::Matrix::multiply (&r, &m);

    m = cairo::Matrix::multiply (&cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -tx, -ty), &m);
    m
}

#[no_mangle]
pub fn rsvg_parse_transform (out_matrix: *mut cairo::Matrix, s: *const libc::c_char) -> glib_sys::gboolean {
    assert! (!out_matrix.is_null ());
    assert! (!s.is_null ());

    let string = unsafe { String::from_glib_none (s) };
    let matrix: &mut cairo::Matrix = unsafe { &mut *out_matrix };

    match parse_transform (&string) {
        Ok (m) => {
            *matrix = m;
            true.to_glib ()
        },

        Err (_) => {
            *matrix = cairo::Matrix::identity ();
            false.to_glib ()
        }
    }
}

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

    #[test]
    fn parses_valid_transform () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_transform ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }

    #[test]
    fn syntax_error_yields_parse_error () {
        match parse_transform ("foo") {
            Err (AttributeError::Parse (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("matrix (1 2 3 4 5)") {
            Err (AttributeError::Parse (_)) => {},
            _ => { panic! (); }
        }
    }

    #[test]
    fn invalid_transform_yields_value_error () {
        match parse_transform ("matrix (0 0 0 0 0 0)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), translate (10, 10)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }

        match parse_transform ("scale (0), skewX (90)") {
            Err (AttributeError::Value (_)) => {},
            _ => { panic! (); }
        }
    }
}

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

    #[test]
    fn parses_numbers () {
        assert_eq! (parse_Num ("0"),          Ok (0.0));
        assert_eq! (parse_Num ("12345"),      Ok (12345.0));
        assert_eq! (parse_Num ("-123"),       Ok (-123.0));
        assert_eq! (parse_Num ("-123.25"),    Ok (-123.25));
        assert_eq! (parse_Num ("123.25"),     Ok (123.25));
        assert_eq! (parse_Num ("-.25"),       Ok (-0.25));
        assert_eq! (parse_Num (".25"),        Ok (0.25));
        assert_eq! (parse_Num ("-25."),       Ok (-25.0));
        assert_eq! (parse_Num ("25."),        Ok (25.0));
        assert_eq! (parse_Num ("22.5e1"),     Ok (225.0));
        assert_eq! (parse_Num ("-22.5e1"),    Ok (-225.0));
        assert_eq! (parse_Num ("-123.45e2"),  Ok (-12345.0));
        assert_eq! (parse_Num ("123.45E2"),   Ok (12345.0));
        assert_eq! (parse_Num ("-123.25e-2"), Ok (-1.2325));
        assert_eq! (parse_Num ("123.25E-2"),  Ok (1.2325));
    }

    #[test]
    fn parses_matrix () {
        assert_eq! (parse_Matrix ("matrix (1 2 3 4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_Matrix ("matrix (1,2,3,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.0, 3.0, 4.0, 5.0, 6.0));

        assert_eq! (parse_Matrix ("matrix (1,2.25,-3.25e2,4 5 6)").unwrap (),
                    cairo::Matrix::new (1.0, 2.25, -325.0, 4.0, 5.0, 6.0));
    }

    #[test]
    fn parses_translate () {
        assert_eq! (parse_Translate ("translate(-1 -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_Translate ("translate(-1, -2)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, -2.0));

        assert_eq! (parse_Translate ("translate(-1)").unwrap (),
                    cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, -1.0, 0.0));
    }

    #[test]
    fn parses_scale () {
        assert_eq! (parse_Scale ("scale(-1 -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_Scale ("scale(-1, -2)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -2.0, 0.0, 0.0));

        assert_eq! (parse_Scale ("scale(-1)").unwrap (),
                    cairo::Matrix::new (-1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
    }

    #[test]
    fn parses_rotate () {
        assert_eq! (parse_Rotate ("rotate (30)").unwrap (), make_rotation_matrix (30.0, 0.0, 0.0));
        assert_eq! (parse_Rotate ("rotate (30,-1,-2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
        assert_eq! (parse_Rotate ("rotate (30, -1, -2)").unwrap (), make_rotation_matrix (30.0, -1.0, -2.0));
    }

    fn make_skew_x_matrix (angle_degrees: f64) -> cairo::Matrix {
        let a = angle_degrees * PI / 180.0;
        cairo::Matrix::new (1.0,      0.0,
                            a.tan (), 1.0,
                            0.0, 0.0)
    }

    fn make_skew_y_matrix (angle_degrees: f64) -> cairo::Matrix {
        let mut m = make_skew_x_matrix (angle_degrees);
        m.yx = m.xy;
        m.xy = 0.0;
        m
    }

    #[test]
    fn parses_skew_x () {
        assert_eq! (parse_SkewX ("skewX (30)").unwrap (), make_skew_x_matrix (30.0));
    }

    #[test]
    fn parses_skew_y () {
        assert_eq! (parse_SkewY ("skewY (30)").unwrap (), make_skew_y_matrix (30.0));
    }

    #[test]
    fn parses_transform_list () {
        let t = cairo::Matrix::new (1.0, 0.0, 0.0, 1.0, 20.0, 30.0);
        let s = cairo::Matrix::new (10.0, 0.0, 0.0, 10.0, 0.0, 0.0);
        let r = make_rotation_matrix (30.0, 10.0, 10.0);

        assert_eq! (parse_TransformList ("scale(10)rotate(30, 10, 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &s));

        assert_eq! (parse_TransformList ("translate(20, 30), scale (10)").unwrap (),
                    cairo::Matrix::multiply (&s, &t));

        let a = cairo::Matrix::multiply (&s, &t);
        assert_eq! (parse_TransformList ("translate(20, 30), scale (10) rotate (30 10 10)").unwrap (),
                    cairo::Matrix::multiply (&r, &a));
    }
}
<|endoftext|>


<commit_before>extern crate seax_svm;

use seax_svm::svm::cell::SVMCell;

/// Trait for AST nodes.
pub trait SyntaxTree {
    /// Compile this node to a list of SVM expressions
    fn compile(self)                    -> Vec<SVMCell>;

    /// Pretty-print this node at the desired indent level
    fn prettyprint(&self, level: usize) -> String;
}

/// Expression
///
/// All Seax Scheme expressions are one of the following
///  + Nested S-Expressions
///  + Identifiers
///  + Numbers
///     - signed int
///     - unsigned int
///     - float
///  + Characters
///  + Strings
pub enum Expr {
    SExpr(List<Expr>),
    Ident(String),
    SInt(isize),
    UInt(usize),
    Float(f64),
    Char(char),
    String(String)
}<commit_msg>Additional work on AST<commit_after>use seax_svm::svm::cell::SVMCell;
use seax_svm::slist::List;

/// Trait for AST nodes.
pub trait ASTNode {
    /// Compile this node to a list of SVM expressions
    fn compile(self)                        -> List<SVMCell>;

    /// Pretty-print this node
    fn prettyprint(&self)                   -> String {
        prettyprint_level(&self, 0usize)
    }

    /// Pretty-print this node at the desired indent level
    fn print_level(&self, level: usize)     -> String;
}

/// Expression
///
/// All Seax Scheme expressions are one of the following
///  + Nested S-Expressions
///  + Identifiers
///  + Lists
///  + Numbers
///     - signed int
///     - unsigned int
///     - floating-point
///  + Characters
///  + Strings
///  TODO: implement the entire Scheme 'numeric tower'
///  TODO: macros should happen
#[deriving(Clone, PartialEq)]
pub enum ExprNode {
    Root(RootNode),
    SExpr(SExprNode),
    Name(NameNode),
    List(ListNode),
    IntConst(IntNode),
    UIntConst(UIntNode),
    FloatConst(FloatNode),
    BoolConst(BoolNode),
    StringConst(StringNode),
    CharConst(CharNode),
}

/// AST node for the root of a program's AST
#[deriving(Clone, PartialEq)]
pub struct RootNode { pub exprs: Vec<ExprNode> }

/// AST node for an S-expression.
///
/// This includes function application, assignment,
/// function definition, et cetera...Scheme is not a complexl anguage.
#[deriving(Clone, PartialEq)]
pub struct SExprNode {
    pub operator: NameNode,
    pub operands: Vec<ExprNode>,
}

/// AST node for a list literal
#[deriving(Clone, PartialEq)]
pub struct ListNode { pub elements: Vec<ExprNode> }

/// AST node for an identifier
#[deriving(Clone, PartialEq)]
pub struct NameNode { pub name: String }

/// AST node for an integer constant
#[deriving(Clone, PartialEq)]
pub struct IntNode { pub value: isize }

/// AST node for an unsigned integer constant
#[deriving(Clone, PartialEq)]
pub struct UIntNode { pub value: usize }

/// AST node for a floating-point constant
#[deriving(Clone, PartialEq)]
pub struct FloatNode { pub value: f64 }

/// AST node for a boolean constant
#[deriving(Clone, PartialEq)]
pub struct BoolNode { pub value: bool }

/// AST node for a character constant
#[deriving(Clone, PartialEq)]
pub struct CharNode { pub value: char }

<|endoftext|>


<commit_before>use std::ops::DerefMut;

use runtime::Runtime;
use error::RuntimeError;
use error::RuntimeErrorKind;

use libimagstore::store::FileLockEntry;
use libimagstore::store::Entry;

pub type EditResult<T> = Result<T, RuntimeError>;

pub trait Edit {
    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()>;
}

impl Edit for Entry {

    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
        edit_in_tmpfile(rt, self.get_content_mut())
            .map(|_| ())
    }

}

impl<'a> Edit for FileLockEntry<'a> {

    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
        self.deref_mut().edit_content(rt)
    }

}

pub fn edit_in_tmpfile(rt: &Runtime, s: &mut String) -> EditResult<()> {
    use tempfile::NamedTempFile;
    use std::io::Seek;
    use std::io::Read;
    use std::io::SeekFrom;
    use std::io::Write;

    let file = NamedTempFile::new();
    if file.is_err() {
        return Err(RuntimeError::new(RuntimeErrorKind::Instantiate, None));
    }
    let file      = file.unwrap();
    let file_path = file.path();
    let file      = file.reopen();

    if file.is_err() {
        return Err(RuntimeError::new(RuntimeErrorKind::IOError, Some(Box::new(file.err().unwrap()))));
    }

    let mut file = file.unwrap();
    file.write_all(&s.clone().into_bytes()[..]);

    if let Err(e) = file.sync_data() {
        return Err(RuntimeError::new(RuntimeErrorKind::IOError, Some(Box::new(e))));
    }

    if let Some(mut editor) = rt.editor() {
        let exit_status = editor.arg(file_path).status();

        match exit_status.map(|s| s.success()) {
            Ok(true) => {
                file.sync_data()
                    .and_then(|_| file.seek(SeekFrom::Start(0)))
                    .and_then(|_| file.read_to_string(s))
                    .map(|_| ())
                    .map_err(|e| RuntimeError::new(RuntimeErrorKind::IOError, Some(Box::new(e))))
            },
            Ok(_)    => Err(RuntimeError::new(RuntimeErrorKind::ProcessExitFailure, None)),
            Err(e)   => Err(RuntimeError::new(RuntimeErrorKind::IOError, Some(Box::new(e)))),
        }
    } else {
        Err(RuntimeError::new(RuntimeErrorKind::Instantiate, None))
    }
}
<commit_msg>Remove unwraphell and replace by try!()<commit_after>use std::ops::DerefMut;

use runtime::Runtime;
use error::RuntimeError;
use error::RuntimeErrorKind;

use libimagstore::store::FileLockEntry;
use libimagstore::store::Entry;

pub type EditResult<T> = Result<T, RuntimeError>;

pub trait Edit {
    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()>;
}

impl Edit for Entry {

    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
        edit_in_tmpfile(rt, self.get_content_mut())
            .map(|_| ())
    }

}

impl<'a> Edit for FileLockEntry<'a> {

    fn edit_content(&mut self, rt: &Runtime) -> EditResult<()> {
        self.deref_mut().edit_content(rt)
    }

}

pub fn edit_in_tmpfile(rt: &Runtime, s: &mut String) -> EditResult<()> {
    use tempfile::NamedTempFile;
    use std::io::Seek;
    use std::io::Read;
    use std::io::SeekFrom;
    use std::io::Write;

    let file      = try!(NamedTempFile::new());
    let file_path = file.path();
    let mut file  = try!(file.reopen());

    file.write_all(&s.clone().into_bytes()[..]);

    try!(file.sync_data());

    if let Some(mut editor) = rt.editor() {
        let exit_status = editor.arg(file_path).status();

        match exit_status.map(|s| s.success()) {
            Ok(true) => {
                file.sync_data()
                    .and_then(|_| file.seek(SeekFrom::Start(0)))
                    .and_then(|_| file.read_to_string(s))
                    .map(|_| ())
                    .map_err(|e| RuntimeError::new(RuntimeErrorKind::IOError, Some(Box::new(e))))
            },
            Ok(_)    => Err(RuntimeError::new(RuntimeErrorKind::ProcessExitFailure, None)),
            Err(e)   => Err(RuntimeError::new(RuntimeErrorKind::IOError, Some(Box::new(e)))),
        }
    } else {
        Err(RuntimeError::new(RuntimeErrorKind::Instantiate, None))
    }
}
<|endoftext|>


<commit_before>use ahash::{AHasher, CallHasher, RandomState};
use criterion::*;
use fxhash::FxHasher;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher, BuildHasher};

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
fn aeshash<H: Hash>(b: &H) -> u64 {
    let hasher = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
    b.get_hash(hasher)
}
#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
fn aeshash<H: Hash>(_b: &H) -> u64 {
    panic!("aes must be enabled")
}

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
fn fallbackhash<H: Hash>(b: &H) -> u64 {
    let hasher = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
    b.get_hash(hasher)
}
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
fn fallbackhash<H: Hash>(_b: &H) -> u64 {
    panic!("aes must be disabled")
}

fn fnvhash<H: Hash>(b: &H) -> u64 {
    let mut hasher = fnv::FnvHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn siphash<H: Hash>(b: &H) -> u64 {
    let mut hasher = DefaultHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn fxhash<H: Hash>(b: &H) -> u64 {
    let mut hasher = FxHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn seahash<H: Hash>(b: &H) -> u64 {
    let mut hasher = seahash::SeaHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

const STRING_LENGTHS: [u32; 12] = [1, 3, 4, 7, 8, 15, 16, 24, 33, 68, 132, 1024];

fn gen_strings() -> Vec<String> {
    STRING_LENGTHS
        .iter()
        .map(|len| {
            let mut string = String::default();
            for pos in 1..=*len {
                let c = (48 + (pos % 10) as u8) as char;
                string.push(c);
            }
            string
        })
        .collect()
}

const U8_VALUES: [u8; 1] = [123];
const U16_VALUES: [u16; 1] = [1234];
const U32_VALUES: [u32; 1] = [12345678];
const U64_VALUES: [u64; 1] = [1234567890123456];
const U128_VALUES: [u128; 1] = [12345678901234567890123456789012];

fn bench_ahash(c: &mut Criterion) {
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(aeshash(s))), &U8_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(aeshash(s))), &U16_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(aeshash(s))), &U32_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(aeshash(s))), &U64_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(aeshash(s))), &U128_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(aeshash(s))), gen_strings()),
    );
}

fn bench_fallback(c: &mut Criterion) {
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U8_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U16_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U32_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U64_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U128_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fallbackhash(s))), gen_strings()),
    );
}

fn bench_fx(c: &mut Criterion) {
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fxhash(s))), &U8_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fxhash(s))), &U16_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fxhash(s))), &U32_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fxhash(s))), &U64_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fxhash(s))), &U128_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fxhash(s))), gen_strings()),
    );
}

fn bench_fnv(c: &mut Criterion) {
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fnvhash(s))), &U8_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fnvhash(s))), &U16_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fnvhash(s))), &U32_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fnvhash(s))), &U64_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fnvhash(s))), &U128_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fnvhash(s))), gen_strings()),
    );
}

fn bench_sea(c: &mut Criterion) {
    c.bench(
        "sea",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(seahash(s))), gen_strings()),
    );
}

fn bench_sip(c: &mut Criterion) {
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(siphash(s))), &U8_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(siphash(s))), &U16_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(siphash(s))), &U32_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(siphash(s))), &U64_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(siphash(s))), &U128_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(siphash(s))), gen_strings()),
    );
}

criterion_main!(benches);
criterion_group!(
    benches,
    bench_ahash,
    bench_fallback,
    bench_fx,
    bench_fnv,
    bench_sea,
    bench_sip
);
<commit_msg>Remove unused import<commit_after>use ahash::{CallHasher, RandomState};
use criterion::*;
use fxhash::FxHasher;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher, BuildHasher};

#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
fn aeshash<H: Hash>(b: &H) -> u64 {
    let hasher = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
    b.get_hash(hasher)
}
#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
fn aeshash<H: Hash>(_b: &H) -> u64 {
    panic!("aes must be enabled")
}

#[cfg(not(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes")))]
fn fallbackhash<H: Hash>(b: &H) -> u64 {
    let hasher = RandomState::with_seeds(1, 2, 3, 4).build_hasher();
    b.get_hash(hasher)
}
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "aes"))]
fn fallbackhash<H: Hash>(_b: &H) -> u64 {
    panic!("aes must be disabled")
}

fn fnvhash<H: Hash>(b: &H) -> u64 {
    let mut hasher = fnv::FnvHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn siphash<H: Hash>(b: &H) -> u64 {
    let mut hasher = DefaultHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn fxhash<H: Hash>(b: &H) -> u64 {
    let mut hasher = FxHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

fn seahash<H: Hash>(b: &H) -> u64 {
    let mut hasher = seahash::SeaHasher::default();
    b.hash(&mut hasher);
    hasher.finish()
}

const STRING_LENGTHS: [u32; 12] = [1, 3, 4, 7, 8, 15, 16, 24, 33, 68, 132, 1024];

fn gen_strings() -> Vec<String> {
    STRING_LENGTHS
        .iter()
        .map(|len| {
            let mut string = String::default();
            for pos in 1..=*len {
                let c = (48 + (pos % 10) as u8) as char;
                string.push(c);
            }
            string
        })
        .collect()
}

const U8_VALUES: [u8; 1] = [123];
const U16_VALUES: [u16; 1] = [1234];
const U32_VALUES: [u32; 1] = [12345678];
const U64_VALUES: [u64; 1] = [1234567890123456];
const U128_VALUES: [u128; 1] = [12345678901234567890123456789012];

fn bench_ahash(c: &mut Criterion) {
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(aeshash(s))), &U8_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(aeshash(s))), &U16_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(aeshash(s))), &U32_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(aeshash(s))), &U64_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(aeshash(s))), &U128_VALUES),
    );
    c.bench(
        "aeshash",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(aeshash(s))), gen_strings()),
    );
}

fn bench_fallback(c: &mut Criterion) {
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U8_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U16_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U32_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U64_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fallbackhash(s))), &U128_VALUES),
    );
    c.bench(
        "fallback",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fallbackhash(s))), gen_strings()),
    );
}

fn bench_fx(c: &mut Criterion) {
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fxhash(s))), &U8_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fxhash(s))), &U16_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fxhash(s))), &U32_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fxhash(s))), &U64_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fxhash(s))), &U128_VALUES),
    );
    c.bench(
        "fx",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fxhash(s))), gen_strings()),
    );
}

fn bench_fnv(c: &mut Criterion) {
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(fnvhash(s))), &U8_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(fnvhash(s))), &U16_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(fnvhash(s))), &U32_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(fnvhash(s))), &U64_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(fnvhash(s))), &U128_VALUES),
    );
    c.bench(
        "fnv",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(fnvhash(s))), gen_strings()),
    );
}

fn bench_sea(c: &mut Criterion) {
    c.bench(
        "sea",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(seahash(s))), gen_strings()),
    );
}

fn bench_sip(c: &mut Criterion) {
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u8", |b, &s| b.iter(|| black_box(siphash(s))), &U8_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u16", |b, &s| b.iter(|| black_box(siphash(s))), &U16_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u32", |b, &s| b.iter(|| black_box(siphash(s))), &U32_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u64", |b, &s| b.iter(|| black_box(siphash(s))), &U64_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("u128", |b, &s| b.iter(|| black_box(siphash(s))), &U128_VALUES),
    );
    c.bench(
        "sip",
        ParameterizedBenchmark::new("string", |b, s| b.iter(|| black_box(siphash(s))), gen_strings()),
    );
}

criterion_main!(benches);
criterion_group!(
    benches,
    bench_ahash,
    bench_fallback,
    bench_fx,
    bench_fnv,
    bench_sea,
    bench_sip
);
<|endoftext|>


<commit_before>use bifrost::vector_clock::{StandardVectorClock};
use std::collections::{HashSet, HashMap};
use chashmap::CHashMap;
use ram::types::{Id};
use ram::cell::{Cell, ReadError, WriteError};
use server::NebServer;
use super::*;

pub struct Timestamp {
    read: i64,
    write: i64,
    committed: bool
}

#[derive(Debug, Eq, PartialEq)]
enum TransactionState {
    Started,
    Aborted,
    Committing,
    Committed
}

struct Transaction {
    id: TransactionId,
    server: u64,
    state: TransactionState
}

pub struct DataManager {
    timestamps: CHashMap<Id, Timestamp>,
    prev_cells: CHashMap<Id, Cell>,
    status: CHashMap<TransactionId, Transaction>,
    server: Arc<NebServer>
}

service! {
    rpc read(server_id: u64, clock: StandardVectorClock, tid: TransactionId, id: Id) -> DataSiteResponse<TransactionExecResult<Cell, ReadError>>;
    rpc write(server_id: u64, clock: StandardVectorClock, tid: TransactionId, id: Id, cell: Cell) -> DataSiteResponse<TransactionExecResult<(), WriteError>>;
    rpc update(server_id: u64, clock: StandardVectorClock, tid: TransactionId, cell: Cell) -> DataSiteResponse<TransactionExecResult<(), WriteError>>;
    rpc remove(server_id: u64, clock: StandardVectorClock, tid: TransactionId, id: Id) -> DataSiteResponse<Result<(), WriteError>>;

    // two phase commit
    rpc prepare(clock :StandardVectorClock, tid: TransactionId) -> DataSiteResponse<bool>;
    rpc commit(clock :StandardVectorClock, tid: TransactionId, cells: Vec<Cell>) -> DataSiteResponse<bool>;

    rpc abort(clock :StandardVectorClock, tid: TransactionId) -> DataSiteResponse<()>;
}

dispatch_rpc_service_functions!(DataManager);

impl DataManager {
    fn local_clock(&self) -> StandardVectorClock {
        self.server.tnx_peer.clock.to_clock()
    }
    fn update_clock(&self, clock: &StandardVectorClock) {
        self.server.tnx_peer.clock.merge_with(clock);
    }
//    fn get_transaction(&self, tid: &TransactionId) -> &Transaction {
//
//    }
}

impl Service for DataManager {
    fn read(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, id: &Id)
        -> Result<DataSiteResponse<TransactionExecResult<Cell, ReadError>>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);

        unimplemented!()
    }
    fn write(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, id: &Id, cell: &Cell)
        -> Result<DataSiteResponse<TransactionExecResult<(), WriteError>>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn update(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, cell: &Cell)
        -> Result<DataSiteResponse<TransactionExecResult<(), WriteError>>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn remove(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, id: &Id)
        -> Result<DataSiteResponse<Result<(), WriteError>>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }

    fn prepare(&self, clock :&StandardVectorClock, tid: &TransactionId)
        -> Result<DataSiteResponse<bool>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn commit(&self, clock :&StandardVectorClock, tid: &TransactionId, cells: &Vec<Cell>)
        -> Result<DataSiteResponse<bool>, ()>  {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn abort(&self, clock :&StandardVectorClock, tid: &TransactionId)
        -> Result<DataSiteResponse<()>, ()>  {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
}<commit_msg>redesign data mamager data structure<commit_after>use bifrost::vector_clock::{StandardVectorClock};
use std::collections::{BTreeSet, HashMap};
use chashmap::{CHashMap, WriteGuard};
use ram::types::{Id};
use ram::cell::{Cell, ReadError, WriteError};
use server::NebServer;
use super::*;

pub struct CellMeta {
    read: i64,
    write: i64,
    committed: bool,
    owner: Option<TransactionId>, // transaction that owns the cell in Committing state
    waiting: BTreeSet<TransactionId>, // transactions that waiting for owner to finish
}

#[derive(Debug, Eq, PartialEq)]
enum TransactionState {
    Started,
    Aborted,
    Committing,
    Committed
}

struct Transaction {
    id: TransactionId,
    server: u64,
    state: TransactionState
}

pub struct DataManager {
    cells: CHashMap<Id, CellMeta>,
    status: CHashMap<TransactionId, Transaction>,
    server: Arc<NebServer>
}

service! {
    rpc read(server_id: u64, clock: StandardVectorClock, tid: TransactionId, id: Id) -> DataSiteResponse<TransactionExecResult<Cell, ReadError>>;
    rpc write(server_id: u64, clock: StandardVectorClock, tid: TransactionId, id: Id, cell: Cell) -> DataSiteResponse<TransactionExecResult<(), WriteError>>;
    rpc update(server_id: u64, clock: StandardVectorClock, tid: TransactionId, cell: Cell) -> DataSiteResponse<TransactionExecResult<(), WriteError>>;
    rpc remove(server_id: u64, clock: StandardVectorClock, tid: TransactionId, id: Id) -> DataSiteResponse<Result<(), WriteError>>;

    // two phase commit
    rpc prepare(clock :StandardVectorClock, tid: TransactionId) -> DataSiteResponse<bool>;
    rpc commit(clock :StandardVectorClock, tid: TransactionId, cells: Vec<Cell>) -> DataSiteResponse<bool>;

    rpc abort(clock :StandardVectorClock, tid: TransactionId) -> DataSiteResponse<()>;
}

dispatch_rpc_service_functions!(DataManager);

impl DataManager {
    fn local_clock(&self) -> StandardVectorClock {
        self.server.tnx_peer.clock.to_clock()
    }
    fn update_clock(&self, clock: &StandardVectorClock) {
        self.server.tnx_peer.clock.merge_with(clock);
    }
    fn get_transaction(&self, tid: &TransactionId, server: &u64) -> WriteGuard<TransactionId, Transaction> {
        if !self.status.contains_key(tid) {
            self.status.upsert(tid.clone(), ||{
                Transaction {
                    id: tid.clone(),
                    server: *server,
                    state: TransactionState::Started
                }
            }, |t|{});
        }
        self.status.get_mut(tid).unwrap()
    }
}

impl Service for DataManager {
    fn read(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, id: &Id)
        -> Result<DataSiteResponse<TransactionExecResult<Cell, ReadError>>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        let mut tnx = self.get_transaction(tid, server_id);
        unimplemented!()
    }
    fn write(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, id: &Id, cell: &Cell)
        -> Result<DataSiteResponse<TransactionExecResult<(), WriteError>>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn update(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, cell: &Cell)
        -> Result<DataSiteResponse<TransactionExecResult<(), WriteError>>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn remove(&self, server_id: &u64, clock: &StandardVectorClock, tid: &TransactionId, id: &Id)
        -> Result<DataSiteResponse<Result<(), WriteError>>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }

    fn prepare(&self, clock :&StandardVectorClock, tid: &TransactionId)
        -> Result<DataSiteResponse<bool>, ()> {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn commit(&self, clock :&StandardVectorClock, tid: &TransactionId, cells: &Vec<Cell>)
        -> Result<DataSiteResponse<bool>, ()>  {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
    fn abort(&self, clock :&StandardVectorClock, tid: &TransactionId)
        -> Result<DataSiteResponse<()>, ()>  {
        let local_clock = self.local_clock();
        self.update_clock(clock);
        unimplemented!()
    }
}<|endoftext|>