<commit_before>use super::super::{Limiter, SteeringAcceleration, SteeringAccelerationCalculator, SteeringBehavior};
use nalgebra::{distance, Point3, Vector3};
use alga::general::Real;
use alga::general::AbstractModule;
use std::f32::MAX;
use num_traits::identities::Zero;
use Steerable;

#[derive(Builder)]
pub struct Face<'a, T>
where
    T: 'a + Real,
{
    /// Common behavior attributes
    pub behavior: SteeringBehavior<'a, T>,
    pub target: &'a Steerable<T>,
    pub allign_tolerance: T,
    pub deceleration_radius: T,
    pub time_to_target: T,
}

fn wrap_angle_around_zero<T: Real>(inp: T) -> T {
    if inp >= T::zero() {
        let mut rotation = inp % T::two_pi();
        if rotation > T::pi() {
            rotation -= T::two_pi();
        }
        rotation
    } else {
        let mut rotation = -inp % T::two_pi();
        if rotation > T::pi() {
            rotation -= T::two_pi();
        }
        -rotation
    }
}

impl<'a, T: 'a + Real> Face<'a, T> {
    fn reach_orientation<'b>(
        &self,
        steering_acceleration: &'b mut SteeringAcceleration<T>,
        owner: &'b Steerable<T>,
        target_orientation: T,
    ) -> &'b mut SteeringAcceleration<T> {
        let rotation = wrap_angle_around_zero(target_orientation - owner.get_orientation());
        let abs_rotation = Real::abs(rotation);
        if abs_rotation <= self.allign_tolerance {
            steering_acceleration.set_zero();
        }

        let mut target_rotation = match self.behavior.limiter {
            Some(lim) => lim.get_max_angular_speed(),
            None => T::from_f32(MAX).unwrap(),
        };
        if abs_rotation < self.deceleration_radius {
            target_rotation *= abs_rotation / self.deceleration_radius;
        }

        target_rotation *= rotation / abs_rotation;

        steering_acceleration.angular =
            (target_rotation - owner.get_angular_velocity()) / self.time_to_target;
        let angular_acceleration = Real::abs(steering_acceleration.angular);
        if let Some(lim) = self.behavior.limiter {
            if angular_acceleration > lim.get_max_angular_speed() {
                steering_acceleration.angular *= lim.get_max_angular_speed() / angular_acceleration;
            }
        }
        steering_acceleration.linear = Vector3::zero();
        steering_acceleration
    }
}

impl<'a, T: 'a + Real> SteeringAccelerationCalculator<T> for Face<'a, T> {
    fn calculate_real_steering<'b>(
        &self,
        steering_acceleration: &'b mut SteeringAcceleration<T>,
        owner: &'b Steerable<T>,
    ) -> &'b mut SteeringAcceleration<T> {
        steering_acceleration.linear = *self.target.get_position() - *owner.get_position();
        let to_target = distance(
            &Point3::from_coordinates(steering_acceleration.linear),
            &Point3::origin(),
        );

        if to_target <= self.allign_tolerance {
            steering_acceleration.set_zero();
        }
        let mut target_speed = match self.behavior.limiter {
            Some(lim) => lim.get_max_linear_speed(),
            None => T::from_f32(MAX).unwrap(),
        };
        if to_target <= self.deceleration_radius {
            target_speed *= to_target / self.deceleration_radius;
        }
        steering_acceleration.linear = steering_acceleration
            .linear
            .multiply_by(target_speed / to_target);
        steering_acceleration.linear -= *owner.get_linear_velocity();
        steering_acceleration.linear = steering_acceleration
            .linear
            .multiply_by(T::one() / self.time_to_target);
        steering_acceleration.angular = T::zero();
        steering_acceleration
    }

    fn is_enabled(self: &Self) -> bool {
        self.behavior.enabled
    }
}
<commit_msg>face behavior completed<commit_after>use super::super::{Limiter, SteeringAcceleration, SteeringAccelerationCalculator, SteeringBehavior};
use nalgebra::{angle, distance, Point3, Vector3};
use alga::general::Real;
use alga::general::AbstractModule;
use std::f32::MAX;
use num_traits::identities::Zero;
use Steerable;

#[derive(Builder)]
pub struct Face<'a, T>
where
    T: 'a + Real,
{
    /// Common behavior attributes
    pub behavior: SteeringBehavior<'a, T>,
    pub target: &'a Steerable<T>,
    pub allign_tolerance: T,
    pub deceleration_radius: T,
    pub time_to_target: T,
}

fn wrap_angle_around_zero<T: Real>(inp: T) -> T {
    if inp >= T::zero() {
        let mut rotation = inp % T::two_pi();
        if rotation > T::pi() {
            rotation -= T::two_pi();
        }
        rotation
    } else {
        let mut rotation = -inp % T::two_pi();
        if rotation > T::pi() {
            rotation -= T::two_pi();
        }
        -rotation
    }
}

impl<'a, T: 'a + Real> Face<'a, T> {
    fn reach_orientation<'b>(
        &self,
        steering_acceleration: &'b mut SteeringAcceleration<T>,
        owner: &'b Steerable<T>,
        target_orientation: T,
    ) -> &'b mut SteeringAcceleration<T> {
        let rotation = wrap_angle_around_zero(target_orientation - owner.get_orientation());
        let abs_rotation = Real::abs(rotation);
        if abs_rotation <= self.allign_tolerance {
            steering_acceleration.set_zero();
        }

        let mut target_rotation = match self.behavior.limiter {
            Some(lim) => lim.get_max_angular_speed(),
            None => T::from_f32(MAX).unwrap(),
        };
        if abs_rotation < self.deceleration_radius {
            target_rotation *= abs_rotation / self.deceleration_radius;
        }

        target_rotation *= rotation / abs_rotation;

        steering_acceleration.angular =
            (target_rotation - owner.get_angular_velocity()) / self.time_to_target;
        let angular_acceleration = Real::abs(steering_acceleration.angular);
        if let Some(lim) = self.behavior.limiter {
            if angular_acceleration > lim.get_max_angular_speed() {
                steering_acceleration.angular *= lim.get_max_angular_speed() / angular_acceleration;
            }
        }
        steering_acceleration.linear = Vector3::zero();
        steering_acceleration
    }
}

impl<'a, T: 'a + Real> SteeringAccelerationCalculator<T> for Face<'a, T> {
    fn calculate_real_steering<'b>(
        &self,
        steering_acceleration: &'b mut SteeringAcceleration<T>,
        owner: &'b Steerable<T>,
    ) -> &'b mut SteeringAcceleration<T> {
        steering_acceleration.linear = *self.target.get_position() - *owner.get_position();
        let to_target = distance(
            &Point3::from_coordinates(steering_acceleration.linear),
            &Point3::origin(),
        );

        if let Some(lim) = self.behavior.limiter {
            if to_target.powi(2) < lim.get_zero_linear_speed_threshold() {
                steering_acceleration.set_zero();
            }
        }

        let target_orientation = angle(
            &steering_acceleration.linear,
            &Vector3::new(T::zero(), T::one(), T::zero()),
        );
        self.reach_orientation(steering_acceleration, owner, target_orientation)
    }

    fn is_enabled(self: &Self) -> bool {
        self.behavior.enabled
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/)

#![cfg(not(test))]
#![cfg(feature="cargo-fmt")]
#![deny(warnings)]

extern crate getopts;
extern crate rustc_serialize;

use std::env;
use std::io::Write;
use std::path::PathBuf;
use std::process::{Command, ExitStatus};
use std::str;

use getopts::Options;
use rustc_serialize::json::Json;

fn main() {
    let exit_status = execute();
    std::io::stdout().flush().unwrap();
    std::process::exit(exit_status);
}

fn execute() -> i32 {
    let success = 0;
    let failure = 1;

    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("q", "quiet", "no output printed to stdout");
    opts.optflag("v", "verbose", "use verbose output");

    let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) {
        Ok(m) => m,
        Err(e) => {
            print_usage(&opts, &e.to_string());
            return failure;
        }
    };

    let (verbose, quiet) = (matches.opt_present("v"), matches.opt_present("q"));

    if verbose && quiet {
        print_usage(&opts, "quiet mode and verbose mode are not compatible");
        return failure;
    }

    if matches.opt_present("h") {
        print_usage(&opts, "");
        return success;
    }

    match format_crate(verbose, quiet) {
        Err(e) => {
            print_usage(&opts, &e.to_string());
            failure
        }
        Ok(status) => {
            if status.success() {
                success
            } else {
                status.code().unwrap_or(failure)
            }
        }
    }
}

fn print_usage(opts: &Options, reason: &str) {
    let msg = format!("{}\nusage: cargo fmt [options]", reason);
    println!("{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \
              Arguments after `--` are passed to rustfmt.",
             opts.usage(&msg));
}

fn format_crate(verbose: bool, quiet: bool) -> Result<ExitStatus, std::io::Error> {
    let targets = try!(get_targets());

    // Currently only bin and lib files get formatted
    let files: Vec<_> = targets.into_iter()
                               .filter(|t| t.kind.is_lib() | t.kind.is_bin())
                               .inspect(|t| {
                                   if verbose {
                                       println!("[{:?}] {:?}", t.kind, t.path)
                                   }
                               })
                               .map(|t| t.path)
                               .collect();

    format_files(&files, &get_fmt_args(), verbose, quiet)
}

fn get_fmt_args() -> Vec<String> {
    // All arguments after -- are passed to rustfmt
    env::args().skip_while(|a| a != "--").skip(1).collect()
}

#[derive(Debug)]
enum TargetKind {
    Lib, // dylib, staticlib, lib
    Bin, // bin
    Other, // test, plugin,...
}

impl TargetKind {
    fn is_lib(&self) -> bool {
        match self {
            &TargetKind::Lib => true,
            _ => false,
        }
    }

    fn is_bin(&self) -> bool {
        match self {
            &TargetKind::Bin => true,
            _ => false,
        }
    }
}

#[derive(Debug)]
pub struct Target {
    path: PathBuf,
    kind: TargetKind,
}

// Returns a vector of all compile targets of a crate
fn get_targets() -> Result<Vec<Target>, std::io::Error> {
    let mut targets: Vec<Target> = vec![];
    let output = try!(Command::new("cargo").arg("read-manifest").output());
    if output.status.success() {
        // None of the unwraps should fail if output of `cargo read-manifest` is correct
        let data = &String::from_utf8(output.stdout).unwrap();
        let json = Json::from_str(data).unwrap();
        let jtargets = json.find("targets").unwrap().as_array().unwrap();
        for jtarget in jtargets {
            targets.push(target_from_json(jtarget));
        }

        Ok(targets)
    } else {
        // This happens when cargo-fmt is not used inside a crate
        Err(std::io::Error::new(std::io::ErrorKind::NotFound,
                                str::from_utf8(&output.stderr).unwrap()))
    }
}

fn target_from_json(jtarget: &Json) -> Target {
    let jtarget = jtarget.as_object().unwrap();
    let path = PathBuf::from(jtarget.get("src_path").unwrap().as_string().unwrap());
    let kinds = jtarget.get("kind").unwrap().as_array().unwrap();
    let kind = match kinds[0].as_string().unwrap() {
        "bin" => TargetKind::Bin,
        "lib" | "dylib" | "staticlib" => TargetKind::Lib,
        _ => TargetKind::Other,
    };

    Target {
        path: path,
        kind: kind,
    }
}

fn format_files(files: &Vec<PathBuf>,
                fmt_args: &Vec<String>,
                verbose: bool,
                quiet: bool)
                -> Result<ExitStatus, std::io::Error> {
    let stdout = if quiet {
        std::process::Stdio::null()
    } else {
        std::process::Stdio::inherit()
    };
    if verbose {
        print!("rustfmt");
        for a in fmt_args.iter() {
            print!(" {}", a);
        }
        for f in files.iter() {
            print!(" {}", f.display());
        }
        println!("");
    }
    let mut command = try!(Command::new("rustfmt")
                               .stdout(stdout)
                               .args(files)
                               .args(fmt_args)
                               .spawn());
    command.wait()
}
<commit_msg>minor: use enum instead of pair of booleans<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Inspired by Paul Woolcock's cargo-fmt (https://github.com/pwoolcoc/cargo-fmt/)

#![cfg(not(test))]
#![cfg(feature="cargo-fmt")]
#![deny(warnings)]

extern crate getopts;
extern crate rustc_serialize;

use std::env;
use std::io::Write;
use std::path::PathBuf;
use std::process::{Command, ExitStatus};
use std::str;

use getopts::Options;
use rustc_serialize::json::Json;

fn main() {
    let exit_status = execute();
    std::io::stdout().flush().unwrap();
    std::process::exit(exit_status);
}

fn execute() -> i32 {
    let success = 0;
    let failure = 1;

    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("q", "quiet", "no output printed to stdout");
    opts.optflag("v", "verbose", "use verbose output");

    let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) {
        Ok(m) => m,
        Err(e) => {
            print_usage(&opts, &e.to_string());
            return failure;
        }
    };

    let verbosity = match (matches.opt_present("v"), matches.opt_present("q")) {
        (false, false) => Verbosity::Normal,
        (false, true) => Verbosity::Quiet,
        (true, false) => Verbosity::Verbose,
        (true, true) => {
            print_usage(&opts, "quiet mode and verbose mode are not compatible");
            return failure;
        }
    };

    if matches.opt_present("h") {
        print_usage(&opts, "");
        return success;
    }

    match format_crate(verbosity) {
        Err(e) => {
            print_usage(&opts, &e.to_string());
            failure
        }
        Ok(status) => {
            if status.success() {
                success
            } else {
                status.code().unwrap_or(failure)
            }
        }
    }
}

fn print_usage(opts: &Options, reason: &str) {
    let msg = format!("{}\nusage: cargo fmt [options]", reason);
    println!("{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \
              Arguments after `--` are passed to rustfmt.",
             opts.usage(&msg));
}

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Verbosity {
    Verbose,
    Normal,
    Quiet,
}

fn format_crate(verbosity: Verbosity) -> Result<ExitStatus, std::io::Error> {
    let targets = try!(get_targets());

    // Currently only bin and lib files get formatted
    let files: Vec<_> = targets.into_iter()
                               .filter(|t| t.kind.is_lib() | t.kind.is_bin())
                               .inspect(|t| {
                                   if verbosity == Verbosity::Verbose {
                                       println!("[{:?}] {:?}", t.kind, t.path)
                                   }
                               })
                               .map(|t| t.path)
                               .collect();

    format_files(&files, &get_fmt_args(), verbosity)
}

fn get_fmt_args() -> Vec<String> {
    // All arguments after -- are passed to rustfmt
    env::args().skip_while(|a| a != "--").skip(1).collect()
}

#[derive(Debug)]
enum TargetKind {
    Lib, // dylib, staticlib, lib
    Bin, // bin
    Other, // test, plugin,...
}

impl TargetKind {
    fn is_lib(&self) -> bool {
        match self {
            &TargetKind::Lib => true,
            _ => false,
        }
    }

    fn is_bin(&self) -> bool {
        match self {
            &TargetKind::Bin => true,
            _ => false,
        }
    }
}

#[derive(Debug)]
pub struct Target {
    path: PathBuf,
    kind: TargetKind,
}

// Returns a vector of all compile targets of a crate
fn get_targets() -> Result<Vec<Target>, std::io::Error> {
    let mut targets: Vec<Target> = vec![];
    let output = try!(Command::new("cargo").arg("read-manifest").output());
    if output.status.success() {
        // None of the unwraps should fail if output of `cargo read-manifest` is correct
        let data = &String::from_utf8(output.stdout).unwrap();
        let json = Json::from_str(data).unwrap();
        let jtargets = json.find("targets").unwrap().as_array().unwrap();
        for jtarget in jtargets {
            targets.push(target_from_json(jtarget));
        }

        Ok(targets)
    } else {
        // This happens when cargo-fmt is not used inside a crate
        Err(std::io::Error::new(std::io::ErrorKind::NotFound,
                                str::from_utf8(&output.stderr).unwrap()))
    }
}

fn target_from_json(jtarget: &Json) -> Target {
    let jtarget = jtarget.as_object().unwrap();
    let path = PathBuf::from(jtarget.get("src_path").unwrap().as_string().unwrap());
    let kinds = jtarget.get("kind").unwrap().as_array().unwrap();
    let kind = match kinds[0].as_string().unwrap() {
        "bin" => TargetKind::Bin,
        "lib" | "dylib" | "staticlib" => TargetKind::Lib,
        _ => TargetKind::Other,
    };

    Target {
        path: path,
        kind: kind,
    }
}

fn format_files(files: &Vec<PathBuf>,
                fmt_args: &Vec<String>,
                verbosity: Verbosity)
                -> Result<ExitStatus, std::io::Error> {
    let stdout = if verbosity == Verbosity::Quiet {
        std::process::Stdio::null()
    } else {
        std::process::Stdio::inherit()
    };
    if verbosity == Verbosity::Verbose {
        print!("rustfmt");
        for a in fmt_args.iter() {
            print!(" {}", a);
        }
        for f in files.iter() {
            print!(" {}", f.display());
        }
        println!("");
    }
    let mut command = try!(Command::new("rustfmt")
                               .stdout(stdout)
                               .args(files)
                               .args(fmt_args)
                               .spawn());
    command.wait()
}
<|endoftext|>


<commit_before>use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::iter;

// use failure::{err_msg, Error};
use ggez::nalgebra::{Point2, Vector2};
use ggez::{graphics, timer, Context, GameResult};
use ggez_goodies::scene::{Scene, SceneSwitch};
use serde_derive::{Deserialize, Serialize};
use specs::world::{Builder, Index};
use specs::{Dispatcher, DispatcherBuilder, Join, World, WorldExt};
use warmy::load::Load;
use warmy::{Res, SimpleKey, Store, StoreErrorOr};
// use warmy::ron::Ron;

use loadable_yaml_macro_derive::LoadableYaml;

use crate::animation::Image as SpriteImage;
use crate::animation::Sprite;
// TODO: move these components to common module out of combat
use crate::campaign::components::{HitBox, MapIntent, TimeSpentOnTerrain};
use crate::campaign::movement_cost::CampaignMap;
use crate::campaign::systems::map_boundary::Boundary;
use crate::campaign::systems::{
    HighlightPlayer, MapCommander, RestrictMovementToMapBoundary, SetMapVelocity, TerrainCost,
};
use crate::combat::components::{Controller, Draw, Facing, Palette, Position, Velocity};
use crate::combat::systems::Movement;
use crate::error::LoadError;
use crate::game::{Game, SceneState};
use crate::input;
use crate::input::{Axis, Button, InputEvent};
use crate::objects::TextureAtlas;
use crate::piv::{extract_palette, palette_swap, Colour, ColourOscillate, PivImage};
// use crate::ron::GameRon;
use crate::ron::{FromRon, GameRon};
use crate::scenes::world::draw_entities;
use crate::scenes::FSceneSwitch;
use crate::text::Image;

const MAP_ANIMATION_SPEED: u32 = 12;

#[derive(Debug)]
pub enum SceneError {
    Map(StoreErrorOr<MapData, Context, SimpleKey>),
    Piv(StoreErrorOr<PivImage, Context, SimpleKey>),
    // CampaignMap(StoreErrorOr<CampaignMap, Context, SimpleKey>),
    Ron(StoreErrorOr<GameRon<CampaignMap>, Context, SimpleKey, FromRon>),
    Ggez(ggez::error::GameError),
}

impl Error for SceneError {}

impl fmt::Display for SceneError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SceneError::Map(ref err) => err.fmt(f),
            SceneError::Piv(ref err) => err.fmt(f),
            // SceneError::CampaignMap(ref err) => err.fmt(f),
            SceneError::Ggez(ref err) => err.fmt(f),
            SceneError::Ron(ref err) => err.fmt(f),
        }
    }
}

impl From<StoreErrorOr<MapData, Context, SimpleKey>> for SceneError {
    fn from(err: StoreErrorOr<MapData, Context, SimpleKey>) -> SceneError {
        SceneError::Map(err)
    }
}

impl From<StoreErrorOr<GameRon<CampaignMap>, Context, SimpleKey, FromRon>> for SceneError {
    fn from(err: StoreErrorOr<GameRon<CampaignMap>, Context, SimpleKey, FromRon>) -> SceneError {
        SceneError::Ron(err)
    }
}

impl From<StoreErrorOr<PivImage, Context, SimpleKey>> for SceneError {
    fn from(err: StoreErrorOr<PivImage, Context, SimpleKey>) -> SceneError {
        SceneError::Piv(err)
    }
}

// impl From<StoreErrorOr<CampaignMap, Context, SimpleKey>> for SceneError {
//     fn from(err: StoreErrorOr<CampaignMap, Context, SimpleKey>) -> SceneError {
//         SceneError::CampaignMap(err)
//     }
// }

impl From<ggez::error::GameError> for SceneError {
    fn from(err: ggez::error::GameError) -> SceneError {
        SceneError::Ggez(err)
    }
}

pub struct FlashingPalettes {
    pub palettes: Vec<Vec<Colour>>,
}

#[derive(Debug, Default, Clone, Serialize, Deserialize, LoadableYaml)]
pub struct MapData {
    pub background: String,
    pub lairs: Vec<Image>,
    pub images: HashMap<String, Image>,
}

impl fmt::Display for MapData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MapData {}", self.background)
    }
}

pub struct MapScene<'a> {
    pub specs_world: World,
    pub dispatcher: Dispatcher<'a, 'a>,

    map_data: MapData,
    pub background: Vec<graphics::Image>,
    background_frame: u32,
    current_background_image: usize,

    pub palette: Vec<Colour>,
}

impl<'a> MapScene<'a> {
    fn build_world() -> World {
        let mut world = World::new();
        world.register::<Draw>();
        world.register::<HitBox>();
        world.register::<Palette>();
        world.register::<Position>();
        world.register::<Velocity>();
        world.register::<Controller>();
        world.register::<MapIntent>();
        world.register::<TimeSpentOnTerrain>();
        world
    }

    fn build_dispatcher() -> Dispatcher<'a, 'a> {
        DispatcherBuilder::new()
            .with(MapCommander, "map_commander", &[])
            .with(TerrainCost, "terrain_cost", &["map_commander"])
            .with(SetMapVelocity, "velocity", &["terrain_cost"])
            .with(
                RestrictMovementToMapBoundary,
                "restrict_movement",
                &["velocity"],
            )
            .with(Movement, "movement", &["restrict_movement"])
            .with(HighlightPlayer, "highlight_player", &[])
            .build()
    }

    pub fn new(
        ctx: &mut Context,
        store: &mut Store<Context, SimpleKey>,
        background_name: &str,
    ) -> Result<Self, SceneError> {
        let map_data = store
            .get::<MapData>(&warmy::SimpleKey::from("/map.yaml"), ctx)?
            .borrow()
            .clone();
        let piv_res = store.get::<PivImage>(&SimpleKey::from(map_data.background.clone()), ctx)?;
        let mut background: Vec<graphics::Image> = Vec::new();
        let mut piv = piv_res.borrow_mut();
        background.push(graphics::Image::from_rgba8(
            ctx,
            512,
            512,
            &piv.to_rgba8_512(),
        )?);

        piv.palette[21..24].rotate_right(1);
        background.push(graphics::Image::from_rgba8(
            ctx,
            512,
            512,
            &piv.to_rgba8_512(),
        )?);

        piv.palette[21..24].rotate_right(1);
        background.push(graphics::Image::from_rgba8(
            ctx,
            512,
            512,
            &piv.to_rgba8_512(),
        )?);

        piv.palette[21..24].rotate_right(1);

        let mut specs_world = Self::build_world();
        specs_world.insert(Boundary {
            x: 0,
            y: 0,
            w: 310,
            h: 190,
        });

        let atlas = store
            .get::<TextureAtlas>(&SimpleKey::from("mi.c"), ctx)
            .expect("error loading texture atlas when drawing");
        // the first image in mi.c is the blue knight head.
        let knight_rect = atlas.borrow().rects[0];
        let knight_width = atlas.borrow().visible_widths[0];

        let sprite_res = store
            .get::<Sprite>(&SimpleKey::from(format!("/{}.yaml", "mi")), ctx)
            // TODO fix error handling, make this ?
            .expect("error getting sprite in build entity");
        let sprite = sprite_res.borrow();
        specs_world
            .create_entity()
            .with(Position { x: 10, y: 10 })
            .with(Velocity {
                ..Default::default()
            })
            .with(Draw {
                frame: sprite.animations["blue_knight"].frames[0].clone(),
                animation: "blue_knight".to_string(),
                resource_name: "mi".to_string(),
                direction: Facing::default(),
            })
            .with(Palette {
                name: "0".to_string(),
                palette: piv.palette.clone(),
            })
            .with(HitBox {
                w: knight_width,
                h: knight_rect.h,
            })
            .with(Controller {
                x_axis: Axis::Horz1,
                y_axis: Axis::Vert1,
                button: Button::Fire1,
                ..Default::default()
            })
            .with(MapIntent {
                ..Default::default()
            })
            .with(TimeSpentOnTerrain {
                ..Default::default()
            })
            .build();

        let campaign_map_res = store.get_by::<GameRon<CampaignMap>, FromRon>(
            &SimpleKey::from("/campaign_map.ron"),
            ctx,
            FromRon,
        )?;
        specs_world.insert(campaign_map_res.borrow().0.clone());

        let mut swap_colour = extract_palette(&[0xff]).first().unwrap().clone();
        swap_colour.a = 255;
        let mut oscillate = ColourOscillate::new(piv.palette[31], swap_colour);
        let mut colours = (0..30)
            .map(|_| oscillate.next().unwrap())
            .collect::<Vec<_>>();
        colours.insert(0, piv.palette[31].clone());
        println!("{:?}", colours.len());

        let mut palettes = Vec::new();
        for c in &colours {
            let mut p = piv.palette.clone();
            p[31] = c.clone();
            palettes.push(p);
        }
        specs_world.insert(FlashingPalettes { palettes });

        Ok(Self {
            specs_world: specs_world,
            dispatcher: Self::build_dispatcher(),
            map_data,
            background,
            background_frame: 0,
            current_background_image: 0,
            palette: piv.palette.to_vec(),
        })
    }

    fn draw_background_map(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        // let draw_params = graphics::DrawParam::default().scale(game.screen_scale);
        graphics::draw(
            ctx,
            &self.background[self.current_background_image],
            // draw_params,
            graphics::DrawParam::default(),
        )?;
        Ok(())
    }

    fn update_controllers(&mut self, input: &input::InputState) {
        let entities = self.specs_world.entities();
        let mut controllers = self.specs_world.write_storage::<Controller>();
        for (e, controller) in (&*entities, &mut controllers).join() {
            controller.x = input.get_axis_raw(controller.x_axis) as i32;
            controller.y = input.get_axis_raw(controller.y_axis) as i32;
            controller.fire = input.get_button_down(controller.button);
        }
    }
}

impl<'a> Scene<Game, InputEvent> for MapScene<'a> {
    fn update(&mut self, game: &mut Game, _ctx: &mut Context) -> FSceneSwitch {
        self.update_controllers(&game.input);
        self.dispatcher.dispatch_par(&self.specs_world);
        self.specs_world.maintain();
        self.background_frame += 1;
        if self.background_frame == MAP_ANIMATION_SPEED {
            self.current_background_image += 1;
            self.current_background_image %= self.background.len();
        }
        self.background_frame %= MAP_ANIMATION_SPEED;
        SceneSwitch::None
    }

    fn draw(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        // since some of the campaign map is transparent, a sprite passing over
        // the transparent area would "colour in" that area, leaving behind the
        // ghost image of the sprite on those pixels, we clear the screen each
        // frame to get rid of these artifacts.
        graphics::clear(ctx, graphics::Color::new(0.0, 0.0, 0.0, 1.0));
        self.draw_background_map(game, ctx);
        draw_entities(&self.specs_world, &self.palette, None, game, ctx);
        Ok(())
    }

    fn name(&self) -> &str {
        "Map"
    }

    fn input(&mut self, gameworld: &mut Game, event: InputEvent, started: bool) {
        // let entities = self.specs_world.entities();
        // let mut controllers = self.specs_world.write_storage::<Controller>();
        // for (e, controller) in (&*entities, &mut controllers).join() {
        //     let x = gameworld.input.get_axis_raw(controller.x_axis);
        //     controller.x = gameworld.input.get_axis_raw(controller.x_axis) as i32;
        //     controller.y = gameworld.input.get_axis_raw(controller.y_axis) as i32;
        //     controller.fire = gameworld.input.get_button_down(controller.button);
        //     // println!("input {:?}", controller);
        // }
    }
}
<commit_msg>refactor campaign map scene into its own function.<commit_after>use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
use std::error::Error;
use std::fmt;
use std::iter;

// use failure::{err_msg, Error};
use ggez::nalgebra::{Point2, Vector2};
use ggez::{graphics, timer, Context, GameResult};
use ggez_goodies::scene::{Scene, SceneSwitch};
use serde_derive::{Deserialize, Serialize};
use specs::world::{Builder, Index};
use specs::{Dispatcher, DispatcherBuilder, Join, World, WorldExt};
use warmy::load::Load;
use warmy::{Res, SimpleKey, Store, StoreErrorOr};
// use warmy::ron::Ron;

use loadable_yaml_macro_derive::LoadableYaml;

use crate::animation::Image as SpriteImage;
use crate::animation::Sprite;
// TODO: move these components to common module out of combat
use crate::campaign::components::{HitBox, MapIntent, TimeSpentOnTerrain};
use crate::campaign::movement_cost::CampaignMap;
use crate::campaign::systems::map_boundary::Boundary;
use crate::campaign::systems::{
    HighlightPlayer, MapCommander, RestrictMovementToMapBoundary, SetMapVelocity, TerrainCost,
};
use crate::combat::components::{Controller, Draw, Facing, Palette, Position, Velocity};
use crate::combat::systems::Movement;
use crate::error::LoadError;
use crate::game::{Game, SceneState};
use crate::input;
use crate::input::{Axis, Button, InputEvent};
use crate::objects::TextureAtlas;
use crate::piv::{extract_palette, palette_swap, Colour, ColourOscillate, PivImage};
// use crate::ron::GameRon;
use crate::ron::{FromRon, GameRon};
use crate::scenes::world::draw_entities;
use crate::scenes::FSceneSwitch;
use crate::text::Image;

const MAP_ANIMATION_SPEED: u32 = 12;

#[derive(Debug)]
pub enum SceneError {
    Map(StoreErrorOr<MapData, Context, SimpleKey>),
    Piv(StoreErrorOr<PivImage, Context, SimpleKey>),
    // CampaignMap(StoreErrorOr<CampaignMap, Context, SimpleKey>),
    Ron(StoreErrorOr<GameRon<CampaignMap>, Context, SimpleKey, FromRon>),
    Ggez(ggez::error::GameError),
}

impl Error for SceneError {}

impl fmt::Display for SceneError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            SceneError::Map(ref err) => err.fmt(f),
            SceneError::Piv(ref err) => err.fmt(f),
            // SceneError::CampaignMap(ref err) => err.fmt(f),
            SceneError::Ggez(ref err) => err.fmt(f),
            SceneError::Ron(ref err) => err.fmt(f),
        }
    }
}

impl From<StoreErrorOr<MapData, Context, SimpleKey>> for SceneError {
    fn from(err: StoreErrorOr<MapData, Context, SimpleKey>) -> SceneError {
        SceneError::Map(err)
    }
}

impl From<StoreErrorOr<GameRon<CampaignMap>, Context, SimpleKey, FromRon>> for SceneError {
    fn from(err: StoreErrorOr<GameRon<CampaignMap>, Context, SimpleKey, FromRon>) -> SceneError {
        SceneError::Ron(err)
    }
}

impl From<StoreErrorOr<PivImage, Context, SimpleKey>> for SceneError {
    fn from(err: StoreErrorOr<PivImage, Context, SimpleKey>) -> SceneError {
        SceneError::Piv(err)
    }
}

// impl From<StoreErrorOr<CampaignMap, Context, SimpleKey>> for SceneError {
//     fn from(err: StoreErrorOr<CampaignMap, Context, SimpleKey>) -> SceneError {
//         SceneError::CampaignMap(err)
//     }
// }

impl From<ggez::error::GameError> for SceneError {
    fn from(err: ggez::error::GameError) -> SceneError {
        SceneError::Ggez(err)
    }
}

pub struct FlashingPalettes {
    pub palettes: Vec<Vec<Colour>>,
}

#[derive(Debug, Default, Clone, Serialize, Deserialize, LoadableYaml)]
pub struct MapData {
    pub background: String,
    pub lairs: Vec<Image>,
    pub images: HashMap<String, Image>,
}

impl fmt::Display for MapData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "MapData {}", self.background)
    }
}

pub struct MapScene<'a> {
    pub specs_world: World,
    pub dispatcher: Dispatcher<'a, 'a>,

    map_data: MapData,
    pub background: Vec<graphics::Image>,
    background_frame: u32,
    current_background_image: usize,

    pub palette: Vec<Colour>,
}

impl<'a> MapScene<'a> {
    fn build_world() -> World {
        let mut world = World::new();
        world.register::<Draw>();
        world.register::<HitBox>();
        world.register::<Palette>();
        world.register::<Position>();
        world.register::<Velocity>();
        world.register::<Controller>();
        world.register::<MapIntent>();
        world.register::<TimeSpentOnTerrain>();
        world
    }

    fn build_dispatcher() -> Dispatcher<'a, 'a> {
        DispatcherBuilder::new()
            .with(MapCommander, "map_commander", &[])
            .with(TerrainCost, "terrain_cost", &["map_commander"])
            .with(SetMapVelocity, "velocity", &["terrain_cost"])
            .with(
                RestrictMovementToMapBoundary,
                "restrict_movement",
                &["velocity"],
            )
            .with(Movement, "movement", &["restrict_movement"])
            .with(HighlightPlayer, "highlight_player", &[])
            .build()
    }

    fn setup_background_map(
        ctx: &mut Context,
        store: &mut Store<Context, SimpleKey>,
        background_name: &str,
    ) -> Result<Vec<graphics::Image>, SceneError> {
        let piv_res = store.get::<PivImage>(&SimpleKey::from(background_name), ctx)?;
        let mut background: Vec<graphics::Image> = Vec::new();
        let mut piv = piv_res.borrow_mut();
        background.push(graphics::Image::from_rgba8(
            ctx,
            512,
            512,
            &piv.to_rgba8_512(),
        )?);

        piv.palette[21..24].rotate_right(1);
        background.push(graphics::Image::from_rgba8(
            ctx,
            512,
            512,
            &piv.to_rgba8_512(),
        )?);

        piv.palette[21..24].rotate_right(1);
        background.push(graphics::Image::from_rgba8(
            ctx,
            512,
            512,
            &piv.to_rgba8_512(),
        )?);

        piv.palette[21..24].rotate_right(1);
        Ok(background)
    }

    pub fn new(
        ctx: &mut Context,
        store: &mut Store<Context, SimpleKey>,
        background_name: &str,
    ) -> Result<Self, SceneError> {
        let map_data = store
            .get::<MapData>(&warmy::SimpleKey::from("/map.yaml"), ctx)?
            .borrow()
            .clone();
        let background = MapScene::setup_background_map(ctx, store, &map_data.background)?;
        let piv_res = store.get::<PivImage>(&SimpleKey::from(map_data.background.clone()), ctx)?;
        let mut piv = piv_res.borrow_mut();

        let mut specs_world = Self::build_world();
        specs_world.insert(Boundary {
            x: 0,
            y: 0,
            w: 310,
            h: 190,
        });

        let atlas = store
            .get::<TextureAtlas>(&SimpleKey::from("mi.c"), ctx)
            .expect("error loading texture atlas when drawing");
        // the first image in mi.c is the blue knight head.
        let knight_rect = atlas.borrow().rects[0];
        let knight_width = atlas.borrow().visible_widths[0];

        let sprite_res = store
            .get::<Sprite>(&SimpleKey::from(format!("/{}.yaml", "mi")), ctx)
            // TODO fix error handling, make this ?
            .expect("error getting sprite in build entity");
        let sprite = sprite_res.borrow();
        specs_world
            .create_entity()
            .with(Position { x: 10, y: 10 })
            .with(Velocity {
                ..Default::default()
            })
            .with(Draw {
                frame: sprite.animations["blue_knight"].frames[0].clone(),
                animation: "blue_knight".to_string(),
                resource_name: "mi".to_string(),
                direction: Facing::default(),
            })
            .with(Palette {
                name: "0".to_string(),
                palette: piv.palette.clone(),
            })
            .with(HitBox {
                w: knight_width,
                h: knight_rect.h,
            })
            .with(Controller {
                x_axis: Axis::Horz1,
                y_axis: Axis::Vert1,
                button: Button::Fire1,
                ..Default::default()
            })
            .with(MapIntent {
                ..Default::default()
            })
            .with(TimeSpentOnTerrain {
                ..Default::default()
            })
            .build();

        let campaign_map_res = store.get_by::<GameRon<CampaignMap>, FromRon>(
            &SimpleKey::from("/campaign_map.ron"),
            ctx,
            FromRon,
        )?;
        specs_world.insert(campaign_map_res.borrow().0.clone());

        let mut swap_colour = extract_palette(&[0xff]).first().unwrap().clone();
        swap_colour.a = 255;
        let mut oscillate = ColourOscillate::new(piv.palette[31], swap_colour);
        let mut colours = (0..30)
            .map(|_| oscillate.next().unwrap())
            .collect::<Vec<_>>();
        colours.insert(0, piv.palette[31].clone());

        let mut palettes = Vec::new();
        for c in &colours {
            let mut p = piv.palette.clone();
            p[31] = c.clone();
            palettes.push(p);
        }
        specs_world.insert(FlashingPalettes { palettes });

        Ok(Self {
            specs_world: specs_world,
            dispatcher: Self::build_dispatcher(),
            map_data,
            background,
            background_frame: 0,
            current_background_image: 0,
            palette: piv.palette.to_vec(),
        })
    }

    fn draw_background_map(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        // let draw_params = graphics::DrawParam::default().scale(game.screen_scale);
        graphics::draw(
            ctx,
            &self.background[self.current_background_image],
            // draw_params,
            graphics::DrawParam::default(),
        )?;
        Ok(())
    }

    fn update_controllers(&mut self, input: &input::InputState) {
        let entities = self.specs_world.entities();
        let mut controllers = self.specs_world.write_storage::<Controller>();
        for (e, controller) in (&*entities, &mut controllers).join() {
            controller.x = input.get_axis_raw(controller.x_axis) as i32;
            controller.y = input.get_axis_raw(controller.y_axis) as i32;
            controller.fire = input.get_button_down(controller.button);
        }
    }
}

impl<'a> Scene<Game, InputEvent> for MapScene<'a> {
    fn update(&mut self, game: &mut Game, _ctx: &mut Context) -> FSceneSwitch {
        self.update_controllers(&game.input);
        self.dispatcher.dispatch_par(&self.specs_world);
        self.specs_world.maintain();
        self.background_frame += 1;
        if self.background_frame == MAP_ANIMATION_SPEED {
            self.current_background_image += 1;
            self.current_background_image %= self.background.len();
        }
        self.background_frame %= MAP_ANIMATION_SPEED;
        SceneSwitch::None
    }

    fn draw(&mut self, game: &mut Game, ctx: &mut Context) -> GameResult<()> {
        // since some of the campaign map is transparent, a sprite passing over
        // the transparent area would "colour in" that area, leaving behind the
        // ghost image of the sprite on those pixels, we clear the screen each
        // frame to get rid of these artifacts.
        graphics::clear(ctx, graphics::Color::new(0.0, 0.0, 0.0, 1.0));
        self.draw_background_map(game, ctx);
        draw_entities(&self.specs_world, &self.palette, None, game, ctx);
        Ok(())
    }

    fn name(&self) -> &str {
        "Map"
    }

    fn input(&mut self, gameworld: &mut Game, event: InputEvent, started: bool) {
        // let entities = self.specs_world.entities();
        // let mut controllers = self.specs_world.write_storage::<Controller>();
        // for (e, controller) in (&*entities, &mut controllers).join() {
        //     let x = gameworld.input.get_axis_raw(controller.x_axis);
        //     controller.x = gameworld.input.get_axis_raw(controller.x_axis) as i32;
        //     controller.y = gameworld.input.get_axis_raw(controller.y_axis) as i32;
        //     controller.fire = gameworld.input.get_button_down(controller.button);
        //     // println!("input {:?}", controller);
        // }
    }
}
<|endoftext|>


<commit_before>use std::fmt::Display;
use std::io::{Result, Write};

use analysis;
use analysis::general::StatusedTypeId;
use analysis::imports::Imports;
use analysis::namespaces;
use config::Config;
use config::derives::Derive;
use env::Env;
use gir_version::VERSION;
use version::Version;
use writer::primitives::tabs;

pub fn start_comments(w: &mut Write, conf: &Config) -> Result<()> {
    if conf.single_version_file.is_some() {
        return start_comments_no_version(w);
    }
    writeln!(
        w,
        "// This file was generated by gir (https://github.com/gtk-rs/gir @ {})
// from gir-files (https://github.com/gtk-rs/gir-files @ {})
// DO NOT EDIT",
        VERSION, conf.girs_version
    )
}

pub fn start_comments_no_version(w: &mut Write) -> Result<()> {
    writeln!(
        w,
        "// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files (https://github.com/gtk-rs/gir-files)
// DO NOT EDIT"
    )
}

pub fn single_version_file(w: &mut Write, conf: &Config) -> Result<()> {
    writeln!(
        w,
        "Generated by gir (https://github.com/gtk-rs/gir @ {})
from gir-files (https://github.com/gtk-rs/gir-files @ {})",
        VERSION, conf.girs_version
    )
}

pub fn uses(w: &mut Write, env: &Env, imports: &Imports) -> Result<()> {
    try!(writeln!(w));
    for (name, &(ref version, ref constraints)) in imports.iter() {
        if constraints.len() == 1 {
            try!(writeln!(w, "#[cfg(feature = \"{}\")]", constraints[0]));
        } else if !constraints.is_empty() {
            try!(writeln!(w, "#[cfg(any({}))]", constraints.iter().map(|c| format!("feature = \"{}\"", c)).collect::<Vec<_>>().join(", ")));
        }

        try!(version_condition(w, env, *version, false, 0));
        let mut default_use = true;
        if env.namespaces.is_glib_crate {
            if name == "glib_ffi" {
                try!(writeln!(w, "use ffi as {};", name));
                default_use = false;
            } else if env.namespaces.glib_ns_id != namespaces::MAIN && name == "ffi" {
                try!(writeln!(w, "use gobject_ffi as {};", name));
                default_use = false;
            }
        }
        if default_use {
            try!(writeln!(w, "use {};", name));
        }
    }

    Ok(())
}

pub fn define_object_type(
    w: &mut Write,
    env: &Env,
    type_name: &str,
    glib_name: &str,
    glib_class_name: &Option<&str>,
    rust_class_name: &Option<&str>,
    glib_func_name: &str,
    is_interface: bool,
    parents: &[StatusedTypeId],
) -> Result<()> {
    let mut external_parents = false;
    let parents: Vec<String> = parents
        .iter()
        .filter(|p| !p.status.ignored())
        .map(|p| if p.type_id.ns_id == namespaces::MAIN {
            p.name.clone()
        } else {
            external_parents = true;
            format!(
                "{krate}::{name} => {krate}_ffi::{ffi_name}",
                krate = env.namespaces[p.type_id.ns_id].crate_name,
                name = p.name,
                ffi_name = env.library.type_(p.type_id).get_glib_name().unwrap()
            )
        })
        .collect();

    let (separator, class_name) = {
        if let Some(s) = *glib_class_name {
            (", ".to_string(), format!("ffi::{}", s))
        } else {
            ("".to_string(), "".to_string())
        }
    };

    let rust_class_name = match rust_class_name {
        None => String::new(),
        Some(ref rust_class_name) => format!(", {}", rust_class_name),
    };

    let kind_name = if is_interface { "Interface" } else { "Object" };

    try!(writeln!(w));
    try!(writeln!(w, "glib_wrapper! {{"));
    if parents.is_empty() {
        try!(writeln!(
            w,
            "\tpub struct {}({}<ffi::{}{}{}{}>);",
            type_name,
            kind_name,
            glib_name,
            separator,
            class_name,
            rust_class_name
        ));
    } else if external_parents {
        try!(writeln!(
            w,
            "\tpub struct {}({}<ffi::{}{}{}{}>): [",
            type_name,
            kind_name,
            glib_name,
            separator,
            class_name,
            rust_class_name
        ));
        for parent in parents {
            try!(writeln!(w, "\t\t{},", parent));
        }
        try!(writeln!(w, "\t];"));
    } else {
        try!(writeln!(
            w,
            "\tpub struct {}({}<ffi::{}{}{}{}>): {};",
            type_name,
            kind_name,
            glib_name,
            separator,
            class_name,
            rust_class_name,
            parents.join(", ")
        ));
    }
    try!(writeln!(w));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(w, "\t\tget_type => || ffi::{}(),", glib_func_name));
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn define_boxed_type(
    w: &mut Write,
    type_name: &str,
    glib_name: &str,
    copy_fn: &str,
    free_fn: &str,
    get_type_fn: &Option<String>,
    derive: &[Derive],
) -> Result<()> {
    try!(writeln!(w));
    try!(writeln!(w, "glib_wrapper! {{"));

    try!(derives(w, derive, 1));
    try!(writeln!(
        w,
        "\tpub struct {}(Boxed<ffi::{}>);",
        type_name,
        glib_name
    ));
    try!(writeln!(w));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(
        w,
        "\t\tcopy => |ptr| ffi::{}(mut_override(ptr)),",
        copy_fn
    ));
    try!(writeln!(w, "\t\tfree => |ptr| ffi::{}(ptr),", free_fn));
    if let Some(ref get_type_fn) = *get_type_fn {
        try!(writeln!(w, "\t\tget_type => || ffi::{}(),", get_type_fn));
    }
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn define_auto_boxed_type(
    w: &mut Write,
    type_name: &str,
    glib_name: &str,
    get_type_fn: &str,
    derive: &[Derive],
) -> Result<()> {
    try!(writeln!(w));
    try!(writeln!(w, "glib_wrapper! {{"));
    try!(derives(w, derive, 1));
    try!(writeln!(
        w,
        "\tpub struct {}(Boxed<ffi::{}>);",
        type_name,
        glib_name
    ));
    try!(writeln!(w));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(
        w,
        "\t\tcopy => |ptr| gobject_ffi::g_boxed_copy(ffi::{}(), ptr as *mut _) as *mut ffi::{},",
        get_type_fn, glib_name
    ));
    try!(writeln!(
        w,
        "\t\tfree => |ptr| gobject_ffi::g_boxed_free(ffi::{}(), ptr as *mut _),",
        get_type_fn
    ));
    try!(writeln!(w, "\t\tget_type => || ffi::{}(),", get_type_fn));
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn define_shared_type(
    w: &mut Write,
    type_name: &str,
    glib_name: &str,
    ref_fn: &str,
    unref_fn: &str,
    get_type_fn: &Option<String>,
    derive: &[Derive],
) -> Result<()> {
    try!(writeln!(w));
    try!(writeln!(w, "glib_wrapper! {{"));
    try!(derives(w, derive, 1));
    try!(writeln!(
        w,
        "\tpub struct {}(Shared<ffi::{}>);",
        type_name,
        glib_name
    ));
    try!(writeln!(w));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(w, "\t\tref => |ptr| ffi::{}(ptr),", ref_fn));
    try!(writeln!(w, "\t\tunref => |ptr| ffi::{}(ptr),", unref_fn));
    if let Some(ref get_type_fn) = *get_type_fn {
        try!(writeln!(w, "\t\tget_type => || ffi::{}(),", get_type_fn));
    }
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn cfg_deprecated(
    w: &mut Write,
    env: &Env,
    deprecated: Option<Version>,
    commented: bool,
    indent: usize,
) -> Result<()> {
    if let Some(s) = cfg_deprecated_string(deprecated, env, commented, indent) {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn cfg_deprecated_string(
    deprecated: Option<Version>,
    env: &Env,
    commented: bool,
    indent: usize,
) -> Option<String> {
    let comment = if commented { "//" } else { "" };
    if env.is_too_low_version(deprecated) {
        Some(format!("{}{}#[deprecated]", tabs(indent), comment))
    } else if let Some(v) = deprecated {
        Some(format!(
            "{}{}#[cfg_attr({}, deprecated)]",
            tabs(indent),
            comment,
            v.to_cfg()
        ))
    } else {
        None
    }
}

pub fn version_condition(
    w: &mut Write,
    env: &Env,
    version: Option<Version>,
    commented: bool,
    indent: usize,
) -> Result<()> {
    if let Some(s) = version_condition_string(env, version, commented, indent) {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn version_condition_string(
    env: &Env,
    version: Option<Version>,
    commented: bool,
    indent: usize,
) -> Option<String> {
    match version {
        Some(v) if v > env.config.min_cfg_version => {
            let comment = if commented { "//" } else { "" };
            Some(format!(
                "{}{}#[cfg(any({}, feature = \"dox\"))]",
                tabs(indent),
                comment,
                v.to_cfg()
            ))
        }
        _ => None,
    }
}

pub fn not_version_condition(
    w: &mut Write,
    version: Option<Version>,
    commented: bool,
    indent: usize,
) -> Result<()> {
    if let Some(v) = version {
        let comment = if commented { "//" } else { "" };
        let s = format!(
            "{}{}#[cfg(any(not({}), feature = \"dox\"))]",
            tabs(indent),
            comment,
            v.to_cfg()
        );
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn cfg_condition(
    w: &mut Write,
    cfg_condition: &Option<String>,
    commented: bool,
    indent: usize,
) -> Result<()> {
    let s = cfg_condition_string(cfg_condition, commented, indent);
    if let Some(s) = s {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn cfg_condition_string(
    cfg_condition: &Option<String>,
    commented: bool,
    indent: usize,
) -> Option<String> {
    match cfg_condition.as_ref() {
        Some(v) => {
            let comment = if commented { "//" } else { "" };
            Some(format!(
                "{}{}#[cfg(any({}, feature = \"dox\"))]",
                tabs(indent),
                comment,
                v
            ))
        }
        None => None,
    }
}

pub fn derives(
    w: &mut Write,
    derives: &[Derive],
    indent: usize,
) -> Result<()> {
    for derive in derives {
        let s = match &derive.cfg_condition {
            Some(condition) => format!(
                "#[cfg_attr({}, derive({}))]",
                condition,
                derive.names.join(", ")
            ),
            None => format!("#[derive({})]", derive.names.join(", ")),
        };
        try!(writeln!(w, "{}{}", tabs(indent), s));
    }
    Ok(())
}

pub fn doc_hidden(
    w: &mut Write,
    doc_hidden: bool,
    comment_prefix: &str,
    indent: usize,
) -> Result<()> {
    if doc_hidden {
        writeln!(w, "{}{}#[doc(hidden)]", tabs(indent), comment_prefix)
    } else {
        Ok(())
    }
}

pub fn write_vec<T: Display>(w: &mut Write, v: &[T]) -> Result<()> {
    for s in v {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn declare_default_from_new(
    w: &mut Write,
    env: &Env,
    name: &str,
    functions: &[analysis::functions::Info],
) -> Result<()> {
    if let Some(func) = functions.iter().find(|f| {
        !f.visibility.hidden() && f.name == "new" && f.parameters.rust_parameters.is_empty()
    }) {
        try!(writeln!(w));
        try!(cfg_deprecated(w, env, func.deprecated_version, false, 0));
        try!(version_condition(w, env, func.version, false, 0));
        try!(writeln!(w, "impl Default for {} {{", name));
        try!(writeln!(w, "    fn default() -> Self {{"));
        try!(writeln!(w, "        Self::new()"));
        try!(writeln!(w, "    }}"));
        try!(writeln!(w, "}}"));
    }

    Ok(())
}

/// Escapes string in format suitable for placing inside double quotes.
pub fn escape_string(s: &str) -> String {
    let mut es = String::with_capacity(s.len() * 2);
    let _ = s.chars()
        .map(|c| match c {
            '\"' | '\\' => {
                es.push('\\');
                es.push(c)
            }
            _ => es.push(c),
        })
        .count();
    es
}

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

    #[test]
    fn test_escape_string() {
        assert_eq!(escape_string(""),
                   "");
        assert_eq!(escape_string("no escaping here"),
                   "no escaping here");
        assert_eq!(escape_string(r#"'"\"#),
                   r#"'\"\\"#);
    }
}
<commit_msg>Don't handle internal/external parent types different in glib_wrapper!()<commit_after>use std::fmt::Display;
use std::io::{Result, Write};

use analysis;
use analysis::general::StatusedTypeId;
use analysis::imports::Imports;
use analysis::namespaces;
use config::Config;
use config::derives::Derive;
use env::Env;
use gir_version::VERSION;
use version::Version;
use writer::primitives::tabs;

pub fn start_comments(w: &mut Write, conf: &Config) -> Result<()> {
    if conf.single_version_file.is_some() {
        return start_comments_no_version(w);
    }
    writeln!(
        w,
        "// This file was generated by gir (https://github.com/gtk-rs/gir @ {})
// from gir-files (https://github.com/gtk-rs/gir-files @ {})
// DO NOT EDIT",
        VERSION, conf.girs_version
    )
}

pub fn start_comments_no_version(w: &mut Write) -> Result<()> {
    writeln!(
        w,
        "// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files (https://github.com/gtk-rs/gir-files)
// DO NOT EDIT"
    )
}

pub fn single_version_file(w: &mut Write, conf: &Config) -> Result<()> {
    writeln!(
        w,
        "Generated by gir (https://github.com/gtk-rs/gir @ {})
from gir-files (https://github.com/gtk-rs/gir-files @ {})",
        VERSION, conf.girs_version
    )
}

pub fn uses(w: &mut Write, env: &Env, imports: &Imports) -> Result<()> {
    try!(writeln!(w));
    for (name, &(ref version, ref constraints)) in imports.iter() {
        if constraints.len() == 1 {
            try!(writeln!(w, "#[cfg(feature = \"{}\")]", constraints[0]));
        } else if !constraints.is_empty() {
            try!(writeln!(w, "#[cfg(any({}))]", constraints.iter().map(|c| format!("feature = \"{}\"", c)).collect::<Vec<_>>().join(", ")));
        }

        try!(version_condition(w, env, *version, false, 0));
        let mut default_use = true;
        if env.namespaces.is_glib_crate {
            if name == "glib_ffi" {
                try!(writeln!(w, "use ffi as {};", name));
                default_use = false;
            } else if env.namespaces.glib_ns_id != namespaces::MAIN && name == "ffi" {
                try!(writeln!(w, "use gobject_ffi as {};", name));
                default_use = false;
            }
        }
        if default_use {
            try!(writeln!(w, "use {};", name));
        }
    }

    Ok(())
}

pub fn define_object_type(
    w: &mut Write,
    _env: &Env,
    type_name: &str,
    glib_name: &str,
    glib_class_name: &Option<&str>,
    rust_class_name: &Option<&str>,
    glib_func_name: &str,
    is_interface: bool,
    parents: &[StatusedTypeId],
) -> Result<()> {
    let parents: Vec<String> = parents
        .iter()
        .filter(|p| !p.status.ignored())
        .map(|p| p.name.clone())
        .collect();

    let (separator, class_name) = {
        if let Some(s) = *glib_class_name {
            (", ".to_string(), format!("ffi::{}", s))
        } else {
            ("".to_string(), "".to_string())
        }
    };

    let rust_class_name = match rust_class_name {
        None => String::new(),
        Some(ref rust_class_name) => format!(", {}", rust_class_name),
    };

    let kind_name = if is_interface { "Interface" } else { "Object" };

    try!(writeln!(w));
    try!(writeln!(w, "glib_wrapper! {{"));
    if parents.is_empty() {
        try!(writeln!(
            w,
            "\tpub struct {}({}<ffi::{}{}{}{}>);",
            type_name,
            kind_name,
            glib_name,
            separator,
            class_name,
            rust_class_name
        ));
    } else {
        try!(writeln!(
            w,
            "\tpub struct {}({}<ffi::{}{}{}{}>): {};",
            type_name,
            kind_name,
            glib_name,
            separator,
            class_name,
            rust_class_name,
            parents.join(", ")
        ));
    }
    try!(writeln!(w));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(w, "\t\tget_type => || ffi::{}(),", glib_func_name));
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn define_boxed_type(
    w: &mut Write,
    type_name: &str,
    glib_name: &str,
    copy_fn: &str,
    free_fn: &str,
    get_type_fn: &Option<String>,
    derive: &[Derive],
) -> Result<()> {
    try!(writeln!(w));
    try!(writeln!(w, "glib_wrapper! {{"));

    try!(derives(w, derive, 1));
    try!(writeln!(
        w,
        "\tpub struct {}(Boxed<ffi::{}>);",
        type_name,
        glib_name
    ));
    try!(writeln!(w));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(
        w,
        "\t\tcopy => |ptr| ffi::{}(mut_override(ptr)),",
        copy_fn
    ));
    try!(writeln!(w, "\t\tfree => |ptr| ffi::{}(ptr),", free_fn));
    if let Some(ref get_type_fn) = *get_type_fn {
        try!(writeln!(w, "\t\tget_type => || ffi::{}(),", get_type_fn));
    }
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn define_auto_boxed_type(
    w: &mut Write,
    type_name: &str,
    glib_name: &str,
    get_type_fn: &str,
    derive: &[Derive],
) -> Result<()> {
    try!(writeln!(w));
    try!(writeln!(w, "glib_wrapper! {{"));
    try!(derives(w, derive, 1));
    try!(writeln!(
        w,
        "\tpub struct {}(Boxed<ffi::{}>);",
        type_name,
        glib_name
    ));
    try!(writeln!(w));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(
        w,
        "\t\tcopy => |ptr| gobject_ffi::g_boxed_copy(ffi::{}(), ptr as *mut _) as *mut ffi::{},",
        get_type_fn, glib_name
    ));
    try!(writeln!(
        w,
        "\t\tfree => |ptr| gobject_ffi::g_boxed_free(ffi::{}(), ptr as *mut _),",
        get_type_fn
    ));
    try!(writeln!(w, "\t\tget_type => || ffi::{}(),", get_type_fn));
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn define_shared_type(
    w: &mut Write,
    type_name: &str,
    glib_name: &str,
    ref_fn: &str,
    unref_fn: &str,
    get_type_fn: &Option<String>,
    derive: &[Derive],
) -> Result<()> {
    try!(writeln!(w));
    try!(writeln!(w, "glib_wrapper! {{"));
    try!(derives(w, derive, 1));
    try!(writeln!(
        w,
        "\tpub struct {}(Shared<ffi::{}>);",
        type_name,
        glib_name
    ));
    try!(writeln!(w));
    try!(writeln!(w, "\tmatch fn {{"));
    try!(writeln!(w, "\t\tref => |ptr| ffi::{}(ptr),", ref_fn));
    try!(writeln!(w, "\t\tunref => |ptr| ffi::{}(ptr),", unref_fn));
    if let Some(ref get_type_fn) = *get_type_fn {
        try!(writeln!(w, "\t\tget_type => || ffi::{}(),", get_type_fn));
    }
    try!(writeln!(w, "\t}}"));
    try!(writeln!(w, "}}"));

    Ok(())
}

pub fn cfg_deprecated(
    w: &mut Write,
    env: &Env,
    deprecated: Option<Version>,
    commented: bool,
    indent: usize,
) -> Result<()> {
    if let Some(s) = cfg_deprecated_string(deprecated, env, commented, indent) {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn cfg_deprecated_string(
    deprecated: Option<Version>,
    env: &Env,
    commented: bool,
    indent: usize,
) -> Option<String> {
    let comment = if commented { "//" } else { "" };
    if env.is_too_low_version(deprecated) {
        Some(format!("{}{}#[deprecated]", tabs(indent), comment))
    } else if let Some(v) = deprecated {
        Some(format!(
            "{}{}#[cfg_attr({}, deprecated)]",
            tabs(indent),
            comment,
            v.to_cfg()
        ))
    } else {
        None
    }
}

pub fn version_condition(
    w: &mut Write,
    env: &Env,
    version: Option<Version>,
    commented: bool,
    indent: usize,
) -> Result<()> {
    if let Some(s) = version_condition_string(env, version, commented, indent) {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn version_condition_string(
    env: &Env,
    version: Option<Version>,
    commented: bool,
    indent: usize,
) -> Option<String> {
    match version {
        Some(v) if v > env.config.min_cfg_version => {
            let comment = if commented { "//" } else { "" };
            Some(format!(
                "{}{}#[cfg(any({}, feature = \"dox\"))]",
                tabs(indent),
                comment,
                v.to_cfg()
            ))
        }
        _ => None,
    }
}

pub fn not_version_condition(
    w: &mut Write,
    version: Option<Version>,
    commented: bool,
    indent: usize,
) -> Result<()> {
    if let Some(v) = version {
        let comment = if commented { "//" } else { "" };
        let s = format!(
            "{}{}#[cfg(any(not({}), feature = \"dox\"))]",
            tabs(indent),
            comment,
            v.to_cfg()
        );
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn cfg_condition(
    w: &mut Write,
    cfg_condition: &Option<String>,
    commented: bool,
    indent: usize,
) -> Result<()> {
    let s = cfg_condition_string(cfg_condition, commented, indent);
    if let Some(s) = s {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn cfg_condition_string(
    cfg_condition: &Option<String>,
    commented: bool,
    indent: usize,
) -> Option<String> {
    match cfg_condition.as_ref() {
        Some(v) => {
            let comment = if commented { "//" } else { "" };
            Some(format!(
                "{}{}#[cfg(any({}, feature = \"dox\"))]",
                tabs(indent),
                comment,
                v
            ))
        }
        None => None,
    }
}

pub fn derives(
    w: &mut Write,
    derives: &[Derive],
    indent: usize,
) -> Result<()> {
    for derive in derives {
        let s = match &derive.cfg_condition {
            Some(condition) => format!(
                "#[cfg_attr({}, derive({}))]",
                condition,
                derive.names.join(", ")
            ),
            None => format!("#[derive({})]", derive.names.join(", ")),
        };
        try!(writeln!(w, "{}{}", tabs(indent), s));
    }
    Ok(())
}

pub fn doc_hidden(
    w: &mut Write,
    doc_hidden: bool,
    comment_prefix: &str,
    indent: usize,
) -> Result<()> {
    if doc_hidden {
        writeln!(w, "{}{}#[doc(hidden)]", tabs(indent), comment_prefix)
    } else {
        Ok(())
    }
}

pub fn write_vec<T: Display>(w: &mut Write, v: &[T]) -> Result<()> {
    for s in v {
        try!(writeln!(w, "{}", s));
    }
    Ok(())
}

pub fn declare_default_from_new(
    w: &mut Write,
    env: &Env,
    name: &str,
    functions: &[analysis::functions::Info],
) -> Result<()> {
    if let Some(func) = functions.iter().find(|f| {
        !f.visibility.hidden() && f.name == "new" && f.parameters.rust_parameters.is_empty()
    }) {
        try!(writeln!(w));
        try!(cfg_deprecated(w, env, func.deprecated_version, false, 0));
        try!(version_condition(w, env, func.version, false, 0));
        try!(writeln!(w, "impl Default for {} {{", name));
        try!(writeln!(w, "    fn default() -> Self {{"));
        try!(writeln!(w, "        Self::new()"));
        try!(writeln!(w, "    }}"));
        try!(writeln!(w, "}}"));
    }

    Ok(())
}

/// Escapes string in format suitable for placing inside double quotes.
pub fn escape_string(s: &str) -> String {
    let mut es = String::with_capacity(s.len() * 2);
    let _ = s.chars()
        .map(|c| match c {
            '\"' | '\\' => {
                es.push('\\');
                es.push(c)
            }
            _ => es.push(c),
        })
        .count();
    es
}

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

    #[test]
    fn test_escape_string() {
        assert_eq!(escape_string(""),
                   "");
        assert_eq!(escape_string("no escaping here"),
                   "no escaping here");
        assert_eq!(escape_string(r#"'"\"#),
                   r#"'\"\\"#);
    }
}
<|endoftext|>


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

use command::Command;
use objects::update::Update;
use bot::Bot;

pub struct CommandHandler {
    commands: HashMap<String, Box<Command>>,
}

impl CommandHandler {
    pub fn new() -> Self {
        CommandHandler { commands: HashMap::new() }
    }

    pub fn add<C: Command>(&mut self, command_name: &str, command: C) {
        self.commands.insert(command_name.to_string(), Box::new(command));
    }

    pub fn start_command_handling(&mut self, rx: mpsc::Receiver<Update>, bot: &Bot) {
        loop {
            let update = rx.recv().unwrap();

            if let Some(t) = update.clone().message.and_then(|t| t.text) {
                if t.starts_with("/") {
                    let (_, bot_command) = t.split_whitespace().next().unwrap().split_at(1);
                    let name_command: Vec<&str> = bot_command.split("@").collect();

                    if name_command.len() == 1 ||
                       name_command.len() == 2 && name_command[1] == bot.username {
                        let command = self.commands.get_mut(name_command[0]);

                        if let Some(c) = command {
                            c.execute(bot, update);
                        }
                    }
                }
            }
        }
    }
}
<commit_msg>Using the localkey static for starting and stopping the thread<commit_after>use std::collections::HashMap;
use std::sync::mpsc;

use command::Command;
use objects::update::Update;
use bot::Bot;
use updater::RUNNING;

pub struct CommandHandler {
    commands: HashMap<String, Box<Command>>,
}

impl CommandHandler {
    pub fn new() -> Self {
        CommandHandler { commands: HashMap::new() }
    }

    pub fn add<C: Command>(&mut self, command_name: &str, command: C) {
        self.commands.insert(command_name.to_string(), Box::new(command));
    }

    pub fn start_command_handling(&mut self, rx: mpsc::Receiver<Update>, bot: &Bot) {
        while RUNNING.with(|s| s.get()) {
            let update = rx.recv().unwrap();

            if let Some(t) = update.clone().message.and_then(|t| t.text) {
                if t.starts_with("/") {
                    let (_, bot_command) = t.split_whitespace().next().unwrap().split_at(1);
                    let name_command: Vec<&str> = bot_command.split("@").collect();

                    if name_command.len() == 1 ||
                       name_command.len() == 2 && name_command[1] == bot.username {
                        let command = self.commands.get_mut(name_command[0]);

                        if let Some(c) = command {
                            c.execute(bot, update);
                        }
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>
import std::vec;
import std::str;
import std::option;
import std::option::some;
import std::option::none;
import driver::session;
import front::parser::parser;
import front::parser::new_parser;
import front::parser::parse_inner_attrs_and_next;
import front::parser::parse_mod_items;

tag eval_mode { mode_depend; mode_parse; }

type ctx =
    @rec(parser p,
         eval_mode mode,
         mutable vec[str] deps,
         session::session sess,
         mutable uint chpos,
         mutable int next_id,
         ast::crate_cfg cfg);

fn eval_crate_directives(ctx cx, vec[@ast::crate_directive] cdirs,
                         str prefix, &mutable vec[@ast::view_item] view_items,
                         &mutable vec[@ast::item] items) {
    for (@ast::crate_directive sub_cdir in cdirs) {
        eval_crate_directive(cx, sub_cdir, prefix, view_items, items);
    }
}

fn eval_crate_directives_to_mod(ctx cx,
                                vec[@ast::crate_directive] cdirs, str prefix)
   -> ast::_mod {
    let vec[@ast::view_item] view_items = [];
    let vec[@ast::item] items = [];
    eval_crate_directives(cx, cdirs, prefix, view_items, items);
    ret rec(view_items=view_items, items=items);
}

fn eval_crate_directive_block(ctx cx, &ast::block blk, str prefix,
                              &mutable vec[@ast::view_item] view_items,
                              &mutable vec[@ast::item] items) {
    for (@ast::stmt s in blk.node.stmts) {
        alt (s.node) {
            case (ast::stmt_crate_directive(?cdir)) {
                eval_crate_directive(cx, cdir, prefix, view_items, items);
            }
            case (_) {
                cx.sess.span_fatal(s.span,
                                 "unsupported stmt in crate-directive block");
            }
        }
    }
}

fn eval_crate_directive(ctx cx, @ast::crate_directive cdir, str prefix,
                        &mutable vec[@ast::view_item] view_items,
                        &mutable vec[@ast::item] items) {
    alt (cdir.node) {
        case (ast::cdir_src_mod(?id, ?file_opt, ?attrs)) {
            auto file_path = id + ".rs";
            alt (file_opt) {
                case (some(?f)) { file_path = f; }
                case (none) { }
            }
            auto full_path = if (std::fs::path_is_absolute(file_path)) {
                file_path
            } else {
                prefix + std::fs::path_sep() + file_path
            };
            if (cx.mode == mode_depend) { cx.deps += [full_path]; ret; }
            auto p0 =
                new_parser(cx.sess, cx.cfg, full_path, cx.chpos,
                           cx.next_id);
            auto inner_attrs = parse_inner_attrs_and_next(p0);
            auto mod_attrs = attrs + inner_attrs._0;
            auto first_item_outer_attrs = inner_attrs._1;
            auto m0 = parse_mod_items(p0, token::EOF, first_item_outer_attrs);

            auto i = front::parser::mk_item(p0, cdir.span.lo, cdir.span.hi,
                                            id, ast::item_mod(m0),
                                            mod_attrs);
            // Thread defids and chpos through the parsers
            cx.chpos = p0.get_chpos();
            cx.next_id = p0.next_id();
            vec::push[@ast::item](items, i);
        }
        case (ast::cdir_dir_mod(?id, ?dir_opt, ?cdirs, ?attrs)) {
            auto path = id;
            alt (dir_opt) { case (some(?d)) { path = d; } case (none) { } }
            auto full_path = if (std::fs::path_is_absolute(path)) {
                path
            } else {
                prefix + std::fs::path_sep() + path
            };
            auto m0 = eval_crate_directives_to_mod(cx, cdirs, full_path);
            auto i = @rec(ident=id,
                          attrs=attrs,
                          id=cx.next_id,
                          node=ast::item_mod(m0),
                          span=cdir.span);
            cx.next_id += 1;
            vec::push[@ast::item](items, i);
        }
        case (ast::cdir_view_item(?vi)) {
            vec::push[@ast::view_item](view_items, vi);
        }
        case (ast::cdir_syntax(?pth)) { }
        case (ast::cdir_auth(?pth, ?eff)) { }
    }
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<commit_msg>Export only what's in use from front::eval. Issue #604<commit_after>
import std::vec;
import std::str;
import std::option;
import std::option::some;
import std::option::none;
import driver::session;
import front::parser::parser;
import front::parser::new_parser;
import front::parser::parse_inner_attrs_and_next;
import front::parser::parse_mod_items;

export eval_crate_directives_to_mod;
export mode_parse;

tag eval_mode { mode_depend; mode_parse; }

type ctx =
    @rec(parser p,
         eval_mode mode,
         mutable vec[str] deps,
         session::session sess,
         mutable uint chpos,
         mutable int next_id,
         ast::crate_cfg cfg);

fn eval_crate_directives(ctx cx, vec[@ast::crate_directive] cdirs,
                         str prefix, &mutable vec[@ast::view_item] view_items,
                         &mutable vec[@ast::item] items) {
    for (@ast::crate_directive sub_cdir in cdirs) {
        eval_crate_directive(cx, sub_cdir, prefix, view_items, items);
    }
}

fn eval_crate_directives_to_mod(ctx cx,
                                vec[@ast::crate_directive] cdirs, str prefix)
   -> ast::_mod {
    let vec[@ast::view_item] view_items = [];
    let vec[@ast::item] items = [];
    eval_crate_directives(cx, cdirs, prefix, view_items, items);
    ret rec(view_items=view_items, items=items);
}

fn eval_crate_directive_block(ctx cx, &ast::block blk, str prefix,
                              &mutable vec[@ast::view_item] view_items,
                              &mutable vec[@ast::item] items) {
    for (@ast::stmt s in blk.node.stmts) {
        alt (s.node) {
            case (ast::stmt_crate_directive(?cdir)) {
                eval_crate_directive(cx, cdir, prefix, view_items, items);
            }
            case (_) {
                cx.sess.span_fatal(s.span,
                                 "unsupported stmt in crate-directive block");
            }
        }
    }
}

fn eval_crate_directive(ctx cx, @ast::crate_directive cdir, str prefix,
                        &mutable vec[@ast::view_item] view_items,
                        &mutable vec[@ast::item] items) {
    alt (cdir.node) {
        case (ast::cdir_src_mod(?id, ?file_opt, ?attrs)) {
            auto file_path = id + ".rs";
            alt (file_opt) {
                case (some(?f)) { file_path = f; }
                case (none) { }
            }
            auto full_path = if (std::fs::path_is_absolute(file_path)) {
                file_path
            } else {
                prefix + std::fs::path_sep() + file_path
            };
            if (cx.mode == mode_depend) { cx.deps += [full_path]; ret; }
            auto p0 =
                new_parser(cx.sess, cx.cfg, full_path, cx.chpos,
                           cx.next_id);
            auto inner_attrs = parse_inner_attrs_and_next(p0);
            auto mod_attrs = attrs + inner_attrs._0;
            auto first_item_outer_attrs = inner_attrs._1;
            auto m0 = parse_mod_items(p0, token::EOF, first_item_outer_attrs);

            auto i = front::parser::mk_item(p0, cdir.span.lo, cdir.span.hi,
                                            id, ast::item_mod(m0),
                                            mod_attrs);
            // Thread defids and chpos through the parsers
            cx.chpos = p0.get_chpos();
            cx.next_id = p0.next_id();
            vec::push[@ast::item](items, i);
        }
        case (ast::cdir_dir_mod(?id, ?dir_opt, ?cdirs, ?attrs)) {
            auto path = id;
            alt (dir_opt) { case (some(?d)) { path = d; } case (none) { } }
            auto full_path = if (std::fs::path_is_absolute(path)) {
                path
            } else {
                prefix + std::fs::path_sep() + path
            };
            auto m0 = eval_crate_directives_to_mod(cx, cdirs, full_path);
            auto i = @rec(ident=id,
                          attrs=attrs,
                          id=cx.next_id,
                          node=ast::item_mod(m0),
                          span=cdir.span);
            cx.next_id += 1;
            vec::push[@ast::item](items, i);
        }
        case (ast::cdir_view_item(?vi)) {
            vec::push[@ast::view_item](view_items, vi);
        }
        case (ast::cdir_syntax(?pth)) { }
        case (ast::cdir_auth(?pth, ?eff)) { }
    }
}
//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
//
<|endoftext|>


<commit_before>use tokio::codec::{Encoder, Decoder};
use std::io::{Error, ErrorKind};
use bytes::{BufMut, BytesMut};

// 5 MiB limit
const MAX_PAYLOAD_LEN: u32 = 5_242_880;

#[derive(Debug)]
pub struct Payload {
    id: BytesMut,
    msg: BytesMut
}

#[derive(Default, Debug)]
pub struct Codec {
    id_len: u32,
    msg_len: u32
}

impl Codec {
    pub fn new() -> Codec {
        Codec::default()
    }
}

impl Encoder for Codec {
    type Item = Payload;
    type Error = Error;

    fn encode(&mut self, item: Self::Item, buf: &mut BytesMut) -> Result<(), Error> {
        {
            let total_len = item.id.len() + item.msg.len() + 8;
            assert!((total_len as u32) < MAX_PAYLOAD_LEN);
            buf.reserve(8 + total_len);
        }
        buf.put_u32_be(item.id.len() as u32);
        buf.put_u32_be(item.msg.len() as u32);
        buf.put(item.id);
        buf.put(item.msg);
        Ok(())
    }
}

impl Decoder for Codec {
    type Item = Payload;
    type Error = Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
        if self.id_len == 0 && self.msg_len == 0 && buf.len() >= 8 {
            let buf = buf.split_to(8);
            self.id_len = u32::from_be_bytes([buf[0], buf[1], buf[2], buf[3]]);
            self.msg_len = u32::from_be_bytes([buf[4], buf[5], buf[6], buf[7]]);
            if self.id_len + self.msg_len > MAX_PAYLOAD_LEN {
                return Err(Error::new(ErrorKind::Other, format!("payload must be <={} bytes", MAX_PAYLOAD_LEN)))
            }
        }
        if self.id_len != 0 && self.msg_len != 0
                && buf.len() >= (self.id_len + self.msg_len) as usize {
            let id_len = self.id_len;
            self.id_len = 0;

            let msg_len = self.msg_len;
            self.msg_len = 0;

            let id = buf.split_to(id_len as usize);
            let msg = buf.split_to(msg_len as usize);
            Ok(Some(Payload { id, msg }))
        } else {
            Ok(None)
        }
    }
}

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

    macro_rules! assert_decode {
        ($codec:expr, $bytes:expr, $id:expr, $msg:expr) => {
            {
                let res = $codec.decode(&mut $bytes).unwrap();
                assert!(res.is_some(), "decoding failure, expected Ok");
                let res = res.expect("decoding failure, expected payload");
                assert_eq!(res.id, $id, "id mismatch");
                assert_eq!(res.msg, $msg, "msg mismatch");
            }
        };
    }

    #[test]
    fn test_encode_full_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::new();
        codec.encode(Payload {
            id: vec![0, 1, 2, 3, 4, 5].into(),
            msg: vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245].into()
        }, &mut bytes).unwrap();
        assert_eq!(bytes, vec![
            0, 0, 0, 6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245 // Msg
        ]);
    }

    #[test]
    fn test_decode_full_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            0, 0, 0, 6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245 // Msg
        ]);

        assert_decode!(codec, bytes,
                        vec![0, 1, 2, 3, 4, 5],
                        vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);
    }

    #[test]
    fn test_decode_multipart_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            0, 0, 0, 6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248 // Msg
        ]);
        let res = codec.decode(&mut bytes).unwrap();
        assert!(res.is_none());

        bytes.reserve(3);
        bytes.put_slice(&vec![247, 246, 245]);
        assert_decode!(codec, bytes,
                        vec![0, 1, 2, 3, 4, 5],
                        vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);
    }

    #[test]
    fn test_decode_multiple_multipart_frames() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            0, 0, 0, 6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, // Msg
            0, 0, 0, 3 // ID len
        ]);
        assert_decode!(codec, bytes,
                vec![0, 1, 2, 3, 4, 5],
                vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);

        // Ensure the codec data is correct
        assert_eq!(bytes.len(), 4);
        assert_eq!(codec.id_len, 0);
        assert_eq!(codec.msg_len, 0);

        bytes.reserve(4);
        bytes.put_slice(&vec![0, 0, 0, 5]); // Write msg len
        let res = codec.decode(&mut bytes).unwrap();
        assert!(res.is_none());

        assert_eq!(bytes.len(), 0);
        assert_eq!(codec.id_len, 3);
        assert_eq!(codec.msg_len, 5);

        bytes.reserve(8);
        bytes.put_slice(&vec![
            1, 1, 1, // ID
            2, 2, 2, 2, 2 // Msg
        ]);
        assert_decode!(codec, bytes,
                vec![1, 1, 1],
                vec![2, 2, 2, 2, 2]);
    }

    #[test]
    fn test_decode_multiple_full_frames() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            // First payload
            0, 0, 0, 6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, // Msg
            // Second payload
            0, 0, 0, 3,
            0, 0, 0, 4,
            1, 1, 1,
            2, 2, 2, 2,
            // Third payload
            0, 0, 0, 4,
            0, 0, 0, 5,
            3, 3, 3, 3,
            4, 4, 4, 4, 4
        ]);

        assert_decode!(codec, bytes,
                vec![0, 1, 2, 3, 4, 5],
                vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);

        assert_decode!(codec, bytes,
                vec![1, 1, 1],
                vec![2, 2, 2, 2]);

        assert_decode!(codec, bytes,
                vec![3, 3, 3, 3],
                vec![4, 4, 4, 4, 4]);

        assert_eq!(bytes.len(), 0);
        assert_eq!(codec.id_len, 0);
        assert_eq!(codec.msg_len, 0);
    }
}
<commit_msg>Use u8 for message ID len<commit_after>use tokio::codec::{Encoder, Decoder};
use std::io::{Error, ErrorKind};
use bytes::{BufMut, BytesMut};

// 5 MiB limit
const MAX_MSG_LEN: u32 = 5_242_880;
// 512 bits should be way more than enough
const MAX_ID_LEN: u8 = 64;

#[derive(Debug)]
pub struct Payload {
    id: BytesMut,
    msg: BytesMut
}

#[derive(Default, Debug)]
pub struct Codec {
    id_len: u8,
    msg_len: u32
}

impl Codec {
    pub fn new() -> Codec {
        Codec::default()
    }
}

impl Encoder for Codec {
    type Item = Payload;
    type Error = Error;

    fn encode(&mut self, item: Self::Item, buf: &mut BytesMut) -> Result<(), Error> {
        assert!(item.id.len() < usize::from(MAX_ID_LEN));
        assert!((item.msg.len() as u32) < MAX_MSG_LEN);
        {
            let total_len = item.id.len() + item.msg.len() + 5;
            buf.reserve(total_len + 5);
        }
        buf.put_u8(item.id.len() as u8);
        buf.put_u32_be(item.msg.len() as u32);
        buf.put(item.id);
        buf.put(item.msg);
        Ok(())
    }
}

impl Decoder for Codec {
    type Item = Payload;
    type Error = Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
        if self.id_len == 0 && self.msg_len == 0 && buf.len() >= 5 {
            let buf = buf.split_to(5);
            self.id_len = buf[0];
            self.msg_len = u32::from_be_bytes([buf[1], buf[2], buf[3], buf[4]]);
            if self.id_len > MAX_ID_LEN {
                return Err(Error::new(ErrorKind::Other, format!("id must be <={} bytes", MAX_ID_LEN)))
            } else if self.msg_len > MAX_MSG_LEN {
                return Err(Error::new(ErrorKind::Other, format!("msg must be <={} bytes", MAX_MSG_LEN)))
            }
        }
        if self.id_len != 0 && self.msg_len != 0
                && buf.len() >= usize::from(self.id_len) + (self.msg_len as usize) {
            let id_len = self.id_len;
            self.id_len = 0;

            let msg_len = self.msg_len;
            self.msg_len = 0;

            let id = buf.split_to(id_len as usize);
            let msg = buf.split_to(msg_len as usize);
            Ok(Some(Payload { id, msg }))
        } else {
            Ok(None)
        }
    }
}

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

    macro_rules! assert_decode {
        ($codec:expr, $bytes:expr, $id:expr, $msg:expr) => {
            {
                let res = $codec.decode(&mut $bytes).unwrap();
                assert!(res.is_some(), "decoding failure, expected Ok");
                let res = res.expect("decoding failure, expected payload");
                assert_eq!(res.id, $id, "id mismatch");
                assert_eq!(res.msg, $msg, "msg mismatch");
            }
        };
    }

    #[test]
    fn test_encode_full_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::new();
        codec.encode(Payload {
            id: vec![0, 1, 2, 3, 4, 5].into(),
            msg: vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245].into()
        }, &mut bytes).unwrap();
        assert_eq!(bytes, vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245 // Msg
        ]);
    }

    #[test]
    fn test_decode_full_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245 // Msg
        ]);

        assert_decode!(codec, bytes,
                        vec![0, 1, 2, 3, 4, 5],
                        vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);
    }

    #[test]
    fn test_decode_multipart_frame() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248 // Msg
        ]);
        let res = codec.decode(&mut bytes).unwrap();
        assert!(res.is_none());

        bytes.reserve(3);
        bytes.put_slice(&vec![247, 246, 245]);
        assert_decode!(codec, bytes,
                        vec![0, 1, 2, 3, 4, 5],
                        vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);
    }

    #[test]
    fn test_decode_multiple_multipart_frames() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, // Msg
            3 // ID len
        ]);
        assert_decode!(codec, bytes,
                vec![0, 1, 2, 3, 4, 5],
                vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);

        // Ensure the codec data is correct
        assert_eq!(bytes.len(), 1);
        assert_eq!(codec.id_len, 0);
        assert_eq!(codec.msg_len, 0);

        bytes.reserve(4);
        bytes.put_slice(&vec![0, 0, 0, 5]); // Write msg len
        let res = codec.decode(&mut bytes).unwrap();
        assert!(res.is_none());

        assert_eq!(bytes.len(), 0);
        assert_eq!(codec.id_len, 3);
        assert_eq!(codec.msg_len, 5);

        bytes.reserve(8);
        bytes.put_slice(&vec![
            1, 1, 1, // ID
            2, 2, 2, 2, 2 // Msg
        ]);
        assert_decode!(codec, bytes,
                vec![1, 1, 1],
                vec![2, 2, 2, 2, 2]);
    }

    #[test]
    fn test_decode_multiple_full_frames() {
        let mut codec = Codec::new();
        let mut bytes = BytesMut::from(vec![
            // First payload
            6, // ID len
            0, 0, 0, 11, // Msg len
            0, 1, 2, 3, 4, 5, // ID
            255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, // Msg
            // Second payload
            3,
            0, 0, 0, 4,
            1, 1, 1,
            2, 2, 2, 2,
            // Third payload
            4,
            0, 0, 0, 5,
            3, 3, 3, 3,
            4, 4, 4, 4, 4
        ]);

        assert_decode!(codec, bytes,
                vec![0, 1, 2, 3, 4, 5],
                vec![255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245]);

        assert_decode!(codec, bytes,
                vec![1, 1, 1],
                vec![2, 2, 2, 2]);

        assert_decode!(codec, bytes,
                vec![3, 3, 3, 3],
                vec![4, 4, 4, 4, 4]);

        assert_eq!(bytes.len(), 0);
        assert_eq!(codec.id_len, 0);
        assert_eq!(codec.msg_len, 0);
    }
}
<|endoftext|>