<commit_before>use std::f32;
use glfw::{Key, Action, MouseButton};
use glfw;
use glfw::WindowEvent;
use na::{Point3, Vector2, Vector3, Matrix4, Isometry3, Perspective3};
use na;
use camera::Camera;

/// Arc-ball camera mode.
///
/// An arc-ball camera is a camera rotating around a fixed point (the focus point) and always
/// looking at it. The following inputs are handled:
///
/// * Left button press + drag - rotates the camera around the focus point
/// * Right button press + drag - translates the focus point on the plane orthogonal to the view
/// direction
/// * Scroll in/out - zoom in/out
/// * Enter key - set the focus point to the origin
#[derive(Clone, Debug)]
pub struct ArcBall {
    /// The focus point.
    at:    Point3<f32>,
    /// Yaw of the camera (rotation along the y axis).
    yaw:   f32,
    /// Pitch of the camera (rotation along the x axis).
    pitch: f32,
    /// Distance from the camera to the `at` focus point.
    dist:  f32,

    /// Increment of the yaw per unit mouse movement. The default value is 0.005.
    yaw_step:   f32,
    /// Increment of the pitch per unit mouse movement. The default value is 0.005.
    pitch_step: f32,
    /// Increment of the distance per unit scrolling. The default value is 40.0.
    dist_step:  f32,
    rotate_button: Option<MouseButton>,
    drag_button:   Option<MouseButton>,
    reset_key:     Option<Key>,

    projection:        Perspective3<f32>,
    proj_view:         Matrix4<f32>,
    inverse_proj_view: Matrix4<f32>,
    last_cursor_pos:   Vector2<f32>
}

impl ArcBall {
    /// Create a new arc-ball camera.
    pub fn new(eye: Point3<f32>, at: Point3<f32>) -> ArcBall {
        ArcBall::new_with_frustrum(f32::consts::PI / 4.0, 0.1, 1024.0, eye, at)
    }

    /// Creates a new arc ball camera with default sensitivity values.
    pub fn new_with_frustrum(fov:    f32,
                             znear:  f32,
                             zfar:   f32,
                             eye:    Point3<f32>,
                             at:     Point3<f32>) -> ArcBall {
        let mut res = ArcBall {
            at:              Point3::new(0.0, 0.0, 0.0),
            yaw:             0.0,
            pitch:           0.0,
            dist:            0.0,
            yaw_step:        0.005,
            pitch_step:      0.005,
            dist_step:       40.0,
            rotate_button:   Some(glfw::MouseButtonLeft),
            drag_button:     Some(glfw::MouseButtonRight),
            reset_key:       Some(Key::Enter),
            projection:      Perspective3::new(800.0 / 600.0, fov, znear, zfar),
            proj_view:       na::zero(),
            inverse_proj_view:   na::zero(),
            last_cursor_pos: na::zero()
        };

        res.look_at(eye, at);

        res
    }

    /// The point the arc-ball is looking at.
    pub fn at(&self) -> Point3<f32> {
        self.at
    }

    /// Get a mutable reference to the point the camera is looking at.
    pub fn set_at(&mut self, at: Point3<f32>) {
        self.at = at;
        self.update_projviews();
    }

    /// The arc-ball camera `yaw`.
    pub fn yaw(&self) -> f32 {
        self.yaw
    }

    /// Sets the camera `yaw`. Change this to modify the rotation along the `up` axis.
    pub fn set_yaw(&mut self, yaw: f32) {
        self.yaw = yaw;

        self.update_restrictions();
        self.update_projviews();
    }

    /// The arc-ball camera `pitch`.
    pub fn pitch(&self) -> f32 {
        self.pitch
    }

    /// Sets the camera `pitch`.
    pub fn set_pitch(&mut self, pitch: f32) {
        self.pitch = pitch;

        self.update_restrictions();
        self.update_projviews();
    }

    /// The distance from the camera position to its view point.
    pub fn dist(&self) -> f32 {
        self.dist
    }

    /// Move the camera such that it is at a given distance from the view point.
    pub fn set_dist(&mut self, dist: f32) {
        self.dist = dist;

        self.update_restrictions();
        self.update_projviews();
    }

    /// Move and orient the camera such that it looks at a specific point.
    pub fn look_at(&mut self, eye: Point3<f32>, at: Point3<f32>) {
        let dist  = na::norm(&(eye - at));
        let pitch = ((eye.y - at.y) / dist).acos();
        let yaw   = (eye.z - at.z).atan2(eye.x - at.x);

        self.at    = at;
        self.dist  = dist;
        self.yaw   = yaw;
        self.pitch = pitch;

        self.update_restrictions();
        self.update_projviews();
    }

    /// Transformation applied by the camera without perspective.
    fn update_restrictions(&mut self) {
        if self.dist < 0.00001 {
            self.dist = 0.00001
        }

        if self.pitch <= 0.01 {
            self.pitch = 0.01
        }

        let _pi: f32 = f32::consts::PI;
        if self.pitch > _pi - 0.01 {
            self.pitch = _pi - 0.01
        }
    }

    /// The button used to rotate the ArcBall camera.
    pub fn rotate_button(&self) -> Option<MouseButton> {
        self.rotate_button
    }

    /// Set the button used to rotate the ArcBall camera.
    /// Use None to disable rotation.
    pub fn rebind_rotate_button(&mut self, new_button: Option<MouseButton>) {
        self.rotate_button = new_button;
    }

    /// The button used to drag the ArcBall camera.
    pub fn drag_button(&self) -> Option<MouseButton> {
        self.drag_button
    }

    /// Set the button used to drag the ArcBall camera.
    /// Use None to disable dragging.
    pub fn rebind_drag_button(&mut self, new_button: Option<MouseButton>) {
        self.drag_button = new_button;
    }

    /// The key used to reset the ArcBall camera.
    pub fn reset_key(&self) -> Option<Key> {
        self.reset_key
    }

    /// Set the key used to reset the ArcBall camera.
    /// Use None to disable reset.
    pub fn rebind_reset_key(&mut self, new_key : Option<Key>) {
        self.reset_key = new_key;
    }

    fn handle_left_button_displacement(&mut self, dpos: &Vector2<f32>) {
        self.yaw   = self.yaw   + dpos.x * self.yaw_step;
        self.pitch = self.pitch - dpos.y * self.pitch_step;

        self.update_restrictions();
        self.update_projviews();
    }

    fn handle_right_button_displacement(&mut self, dpos: &Vector2<f32>) {
        let eye       = self.eye();
        let dir       = na::normalize(&(self.at - eye));
        let tangent   = na::normalize(&Vector3::y().cross(&dir));
        let bitangent = dir.cross(&tangent);
        let mult      = self.dist / 1000.0;

        self.at = self.at + tangent * (dpos.x * mult) + bitangent * (dpos.y * mult);
        self.update_projviews();
    }

    fn handle_scroll(&mut self, off: f32) {
        self.dist = self.dist + self.dist_step * (off) / 120.0;
        self.update_restrictions();
        self.update_projviews();
    }

    fn update_projviews(&mut self) {
        self.proj_view         = *self.projection.as_matrix() * self.view_transform().to_homogeneous();
        self.inverse_proj_view = self.proj_view.try_inverse().unwrap();
    }
}

impl Camera for ArcBall {
    fn clip_planes(&self) -> (f32, f32) {
        (self.projection.znear(), self.projection.zfar())
    }

    fn view_transform(&self) -> Isometry3<f32> {
        Isometry3::look_at_rh(&self.eye(), &self.at, &Vector3::y())
    }

    fn eye(&self) -> Point3<f32> {
        let px = self.at.x + self.dist * self.yaw.cos() * self.pitch.sin();
        let py = self.at.y + self.dist * self.pitch.cos();
        let pz = self.at.z + self.dist * self.yaw.sin() * self.pitch.sin();

        Point3::new(px, py, pz)
    }

    fn handle_event(&mut self, window: &glfw::Window, event: &WindowEvent) {
        match *event {
            WindowEvent::CursorPos(x, y) => {
                let curr_pos = Vector2::new(x as f32, y as f32);

                if let Some(rotate_button) = self.rotate_button {
                    if window.get_mouse_button(rotate_button) == Action::Press {
                        let dpos = curr_pos - self.last_cursor_pos;
                        self.handle_left_button_displacement(&dpos)
                    }
                }

                if let Some(drag_button) = self.drag_button {
                    if window.get_mouse_button(drag_button) == Action::Press {
                        let dpos = curr_pos - self.last_cursor_pos;
                        self.handle_right_button_displacement(&dpos)
                    }
                }

                self.last_cursor_pos = curr_pos;
            },
            WindowEvent::Key(key, _, Action::Press, _) if Some(key) == self.reset_key => {
                self.at = Point3::origin();
                self.update_projviews();
            },
            WindowEvent::Scroll(_, off) => self.handle_scroll(off as f32),
            WindowEvent::FramebufferSize(w, h) => {
                self.projection.set_aspect(w as f32 / h as f32);
                self.update_projviews();
            },
            _ => { }
        }
    }

    fn transformation(&self) -> Matrix4<f32> {
        self.proj_view
    }

    fn inverse_transformation(&self) -> Matrix4<f32> {
        self.inverse_proj_view
    }

    fn update(&mut self, _: &glfw::Window) { }
}
<commit_msg>Make z-up arc ball<commit_after>/*
 Copyright (c) 2013, Sébastien Crozet
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

1. Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

3. Neither the name of the author nor the names of its contributors may be used
   to endorse or promote products derived from this software without specific
   prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Edit Takashi Ogura <t.ogura@gmail.com>
 */

use std::f32;
use glfw::{Action, Key, MouseButton};
use glfw;
use glfw::WindowEvent;
use na::{Isometry3, Matrix4, Perspective3, Point3, Vector2, Vector3};
use na;
use kiss3d::camera::Camera;

/// Arc-ball camera mode.
///
/// An arc-ball camera is a camera rotating around a fixed point (the focus point) and always
/// looking at it. The following inputs are handled:
///
/// * Left button press + drag - rotates the camera around the focus point
/// * Right button press + drag - translates the focus point on the plane orthogonal to the view
/// direction
/// * Scroll in/out - zoom in/out
/// * Enter key - set the focus point to the origin
#[derive(Clone, Debug)]
pub struct ArcBall {
    /// The focus point.
    at: Point3<f32>,
    /// Yaw of the camera (rotation along the y axis).
    yaw: f32,
    /// Pitch of the camera (rotation along the x axis).
    pitch: f32,
    /// Distance from the camera to the `at` focus point.
    dist: f32,

    /// Increment of the yaw per unit mouse movement. The default value is 0.005.
    yaw_step: f32,
    /// Increment of the pitch per unit mouse movement. The default value is 0.005.
    pitch_step: f32,
    /// Increment of the distance per unit scrolling. The default value is 40.0.
    dist_step: f32,
    rotate_button: Option<MouseButton>,
    drag_button: Option<MouseButton>,
    reset_key: Option<Key>,

    projection: Perspective3<f32>,
    proj_view: Matrix4<f32>,
    inverse_proj_view: Matrix4<f32>,
    last_cursor_pos: Vector2<f32>,
}

impl ArcBall {
    /// Create a new arc-ball camera.
    pub fn new(eye: Point3<f32>, at: Point3<f32>) -> ArcBall {
        ArcBall::new_with_frustrum(f32::consts::PI / 4.0, 0.1, 1024.0, eye, at)
    }

    /// Creates a new arc ball camera with default sensitivity values.
    pub fn new_with_frustrum(
        fov: f32,
        znear: f32,
        zfar: f32,
        eye: Point3<f32>,
        at: Point3<f32>,
    ) -> ArcBall {
        let mut res = ArcBall {
            at: Point3::new(0.0, 0.0, 0.0),
            yaw: 0.0,
            pitch: 0.0,
            dist: 0.0,
            yaw_step: 0.005,
            pitch_step: 0.005,
            dist_step: 40.0,
            rotate_button: Some(glfw::MouseButtonLeft),
            drag_button: Some(glfw::MouseButtonRight),
            reset_key: Some(Key::Enter),
            projection: Perspective3::new(800.0 / 600.0, fov, znear, zfar),
            proj_view: na::zero(),
            inverse_proj_view: na::zero(),
            last_cursor_pos: na::zero(),
        };

        res.look_at(eye, at);

        res
    }

    /// The point the arc-ball is looking at.
    pub fn at(&self) -> Point3<f32> {
        self.at
    }

    /// Get a mutable reference to the point the camera is looking at.
    pub fn set_at(&mut self, at: Point3<f32>) {
        self.at = at;
        self.update_projviews();
    }

    /// The arc-ball camera `yaw`.
    pub fn yaw(&self) -> f32 {
        self.yaw
    }

    /// Sets the camera `yaw`. Change this to modify the rotation along the `up` axis.
    pub fn set_yaw(&mut self, yaw: f32) {
        self.yaw = yaw;

        self.update_restrictions();
        self.update_projviews();
    }

    /// The arc-ball camera `pitch`.
    pub fn pitch(&self) -> f32 {
        self.pitch
    }

    /// Sets the camera `pitch`.
    pub fn set_pitch(&mut self, pitch: f32) {
        self.pitch = pitch;

        self.update_restrictions();
        self.update_projviews();
    }

    /// The distance from the camera position to its view point.
    pub fn dist(&self) -> f32 {
        self.dist
    }

    /// Move the camera such that it is at a given distance from the view point.
    pub fn set_dist(&mut self, dist: f32) {
        self.dist = dist;

        self.update_restrictions();
        self.update_projviews();
    }

    /// Move and orient the camera such that it looks at a specific point.
    pub fn look_at(&mut self, eye: Point3<f32>, at: Point3<f32>) {
        let dist = na::norm(&(eye - at));
        let pitch = ((eye.z - at.z) / dist).acos();
        let yaw = (eye.x - at.x).atan2(eye.y - at.y);

        self.at = at;
        self.dist = dist;
        self.yaw = yaw;
        self.pitch = pitch;

        self.update_restrictions();
        self.update_projviews();
    }

    /// Transformation applied by the camera without perspective.
    fn update_restrictions(&mut self) {
        if self.dist < 0.00001 {
            self.dist = 0.00001
        }

        if self.pitch <= 0.01 {
            self.pitch = 0.01
        }

        let _pi: f32 = f32::consts::PI;
        if self.pitch > _pi - 0.01 {
            self.pitch = _pi - 0.01
        }
    }

    /// The button used to rotate the ArcBall camera.
    pub fn rotate_button(&self) -> Option<MouseButton> {
        self.rotate_button
    }

    /// Set the button used to rotate the ArcBall camera.
    /// Use None to disable rotation.
    pub fn rebind_rotate_button(&mut self, new_button: Option<MouseButton>) {
        self.rotate_button = new_button;
    }

    /// The button used to drag the ArcBall camera.
    pub fn drag_button(&self) -> Option<MouseButton> {
        self.drag_button
    }

    /// Set the button used to drag the ArcBall camera.
    /// Use None to disable dragging.
    pub fn rebind_drag_button(&mut self, new_button: Option<MouseButton>) {
        self.drag_button = new_button;
    }

    /// The key used to reset the ArcBall camera.
    pub fn reset_key(&self) -> Option<Key> {
        self.reset_key
    }

    /// Set the key used to reset the ArcBall camera.
    /// Use None to disable reset.
    pub fn rebind_reset_key(&mut self, new_key: Option<Key>) {
        self.reset_key = new_key;
    }

    fn handle_left_button_displacement(&mut self, dpos: &Vector2<f32>) {
        self.yaw = self.yaw + dpos.x * self.yaw_step;
        self.pitch = self.pitch - dpos.y * self.pitch_step;

        self.update_restrictions();
        self.update_projviews();
    }

    fn handle_right_button_displacement(&mut self, dpos: &Vector2<f32>) {
        let eye = self.eye();
        let dir = na::normalize(&(self.at - eye));
        let tangent = na::normalize(&Vector3::z().cross(&dir));
        let bitangent = dir.cross(&tangent);
        let mult = self.dist / 1000.0;

        self.at = self.at + tangent * (dpos.x * mult) + bitangent * (dpos.y * mult);
        self.update_projviews();
    }

    fn handle_scroll(&mut self, off: f32) {
        self.dist = self.dist + self.dist_step * (off) / 120.0;
        self.update_restrictions();
        self.update_projviews();
    }

    fn update_projviews(&mut self) {
        self.proj_view = *self.projection.as_matrix() * self.view_transform().to_homogeneous();
        self.inverse_proj_view = self.proj_view.try_inverse().unwrap();
    }
}

impl Camera for ArcBall {
    fn clip_planes(&self) -> (f32, f32) {
        (self.projection.znear(), self.projection.zfar())
    }

    fn view_transform(&self) -> Isometry3<f32> {
        Isometry3::look_at_rh(&self.eye(), &self.at, &Vector3::z())
    }

    fn eye(&self) -> Point3<f32> {
        let py = self.at.x + self.dist * self.yaw.cos() * self.pitch.sin();
        let pz = self.at.y + self.dist * self.pitch.cos();
        let px = self.at.z + self.dist * self.yaw.sin() * self.pitch.sin();

        Point3::new(px, py, pz)
    }

    fn handle_event(&mut self, window: &glfw::Window, event: &WindowEvent) {
        match *event {
            WindowEvent::CursorPos(x, y) => {
                let curr_pos = Vector2::new(x as f32, y as f32);

                if let Some(rotate_button) = self.rotate_button {
                    if window.get_mouse_button(rotate_button) == Action::Press {
                        let dpos = curr_pos - self.last_cursor_pos;
                        self.handle_left_button_displacement(&dpos)
                    }
                }

                if let Some(drag_button) = self.drag_button {
                    if window.get_mouse_button(drag_button) == Action::Press {
                        let dpos = curr_pos - self.last_cursor_pos;
                        self.handle_right_button_displacement(&dpos)
                    }
                }

                self.last_cursor_pos = curr_pos;
            }
            WindowEvent::Key(key, _, Action::Press, _) if Some(key) == self.reset_key => {
                self.at = Point3::origin();
                self.update_projviews();
            }
            WindowEvent::Scroll(_, off) => self.handle_scroll(off as f32),
            WindowEvent::FramebufferSize(w, h) => {
                self.projection.set_aspect(w as f32 / h as f32);
                self.update_projviews();
            }
            _ => {}
        }
    }

    fn transformation(&self) -> Matrix4<f32> {
        self.proj_view
    }

    fn inverse_transformation(&self) -> Matrix4<f32> {
        self.inverse_proj_view
    }

    fn update(&mut self, _: &glfw::Window) {}
}
<|endoftext|>


<commit_before>use clap::{Arg, ArgMatches, App};
use slog::Level;

use rt::Dim;

pub struct Config {
    pub output_file: String,
    pub log_level: Level,
    pub dim: Dim,
    pub integrator: SamplerIntegratorType,
    pub threads: u32,
}

arg_enum! {
  #[derive(Debug)]
  pub enum SamplerIntegratorType {
      Whitted,
      DirectLighting,
      PathTracing,
      Ao,
      Normal
  }
}

pub fn parse_args<'a>() -> ArgMatches<'a> {
    // TODO add block-size and ao-samples and whitted-max-ray? Or maybe not since eventually it
    // will be read from the scene file...
    App::new("rustracer")
        .version("0.1")
        .author("Antoine Büsch")
        .about("Toy raytracer in Rust based on PBRTv3")
        .arg(Arg::with_name("output")
                 .long("output")
                 .short("o")
                 .help("Output file name")
                 .default_value("image.png"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .help("Number of worker threads")
                 .takes_value(true))
        .arg(Arg::with_name("dim")
                 .long("dim")
                 .short("d")
                 .help("Dimension of the output image")
                 .default_value("800x600"))
        .arg(Arg::with_name("integrator")
                 .long("integrator")
                 .short("i")
                 .help("SamplerIntegrator to use")
                 .possible_values(&SamplerIntegratorType::variants())
                 .default_value("DirectLighting"))
        .arg(Arg::with_name("spp").long("spp").help("Sample per pixels").default_value("4"))
        .arg(Arg::with_name("verbose").short("v").help("log debug information"))
        .arg(Arg::with_name("display").short("p").help("Display image as it is rendered"))
        .get_matches()
}
<commit_msg>Remove unused struct<commit_after>use clap::{Arg, ArgMatches, App};

arg_enum! {
  #[derive(Debug)]
  pub enum SamplerIntegratorType {
      Whitted,
      DirectLighting,
      PathTracing,
      Ao,
      Normal
  }
}

pub fn parse_args<'a>() -> ArgMatches<'a> {
    // TODO add block-size and ao-samples and whitted-max-ray? Or maybe not since eventually it
    // will be read from the scene file...
    App::new("rustracer")
        .version("0.1")
        .author("Antoine Büsch")
        .about("Toy raytracer in Rust based on PBRTv3")
        .arg(Arg::with_name("output")
                 .long("output")
                 .short("o")
                 .help("Output file name")
                 .default_value("image.png"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .help("Number of worker threads")
                 .takes_value(true))
        .arg(Arg::with_name("dim")
                 .long("dim")
                 .short("d")
                 .help("Dimension of the output image")
                 .default_value("800x600"))
        .arg(Arg::with_name("integrator")
                 .long("integrator")
                 .short("i")
                 .help("SamplerIntegrator to use")
                 .possible_values(&SamplerIntegratorType::variants())
                 .default_value("DirectLighting"))
        .arg(Arg::with_name("spp").long("spp").help("Sample per pixels").default_value("4"))
        .arg(Arg::with_name("verbose").short("v").help("log debug information"))
        .arg(Arg::with_name("display").short("p").help("Display image as it is rendered"))
        .get_matches()
}
<|endoftext|>


<commit_before>use std::env;

use cargo::ops;
use cargo::util::{CliResult, Config};

#[derive(RustcDecodable)]
pub struct Options {
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_bin: bool,
    flag_lib: bool,
    arg_path: String,
    flag_name: Option<String>,
    flag_vcs: Option<ops::VersionControl>,
    flag_frozen: bool,
    flag_locked: bool,
}

pub const USAGE: &'static str = "
Create a new cargo package at <path>

Usage:
    cargo new [options] <path>
    cargo new -h | --help

Options:
    -h, --help          Print this message
    --vcs VCS           Initialize a new repository for the given version
                        control system (git or hg) or do not initialize any version
                        control at all (none) overriding a global configuration.
    --bin               Use a binary (application) template
    --lib               Use a library template
    --name NAME         Set the resulting package name
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
    debug!("executing; cmd=cargo-new; args={:?}", env::args().collect::<Vec<_>>());
    config.configure(options.flag_verbose,
                     options.flag_quiet,
                     &options.flag_color,
                     options.flag_frozen,
                     options.flag_locked)?;

    let Options { flag_bin, flag_lib, arg_path, flag_name, flag_vcs, .. } = options;

    let opts = ops::NewOptions::new(flag_vcs,
                                    flag_bin,
                                    flag_lib,
                                    &arg_path,
                                    flag_name.as_ref().map(|s| s.as_ref()));

    let opts_lib = opts.lib;
    ops::new(opts, config)?;

    config.shell().status("Created", format!("{} `{}` project",
                                             if opts_lib { "library" }
                                             else {"binary (application)"},
                                             arg_path))?;

    Ok(None)
}

<commit_msg>Auto merge of #3618 - sbeckeriv:3473-new-subcommand-doc-update, r=alexcrichton<commit_after>use std::env;

use cargo::ops;
use cargo::util::{CliResult, Config};

#[derive(RustcDecodable)]
pub struct Options {
    flag_verbose: u32,
    flag_quiet: Option<bool>,
    flag_color: Option<String>,
    flag_bin: bool,
    flag_lib: bool,
    arg_path: String,
    flag_name: Option<String>,
    flag_vcs: Option<ops::VersionControl>,
    flag_frozen: bool,
    flag_locked: bool,
}

pub const USAGE: &'static str = "
Create a new cargo package at <path>

Usage:
    cargo new [options] <path>
    cargo new -h | --help

Options:
    -h, --help          Print this message
    --vcs VCS           Initialize a new repository for the given version
                        control system (git or hg) or do not initialize any version
                        control at all (none) overriding a global configuration.
    --bin               Use a binary (application) template
    --lib               Use a library template
    --name NAME         Set the resulting package name, defaults to the value of <path>
    -v, --verbose ...   Use verbose output (-vv very verbose/build.rs output)
    -q, --quiet         No output printed to stdout
    --color WHEN        Coloring: auto, always, never
    --frozen            Require Cargo.lock and cache are up to date
    --locked            Require Cargo.lock is up to date
";

pub fn execute(options: Options, config: &Config) -> CliResult<Option<()>> {
    debug!("executing; cmd=cargo-new; args={:?}", env::args().collect::<Vec<_>>());
    config.configure(options.flag_verbose,
                     options.flag_quiet,
                     &options.flag_color,
                     options.flag_frozen,
                     options.flag_locked)?;

    let Options { flag_bin, flag_lib, arg_path, flag_name, flag_vcs, .. } = options;

    let opts = ops::NewOptions::new(flag_vcs,
                                    flag_bin,
                                    flag_lib,
                                    &arg_path,
                                    flag_name.as_ref().map(|s| s.as_ref()));

    let opts_lib = opts.lib;
    ops::new(opts, config)?;

    config.shell().status("Created", format!("{} `{}` project",
                                             if opts_lib { "library" }
                                             else {"binary (application)"},
                                             arg_path))?;

    Ok(None)
}

<|endoftext|>


<commit_before>use std::result;

use analysis::ref_mode::RefMode;
use env::Env;
use library::{self, Nullable};
use nameutil::crate_name;
use super::conversion_type::ConversionType;
use traits::*;

pub type Result = result::Result<String, String>;

impl AsStr for Result {
    #[inline]
    fn as_str(&self) -> &str {
        self.as_ref().unwrap_or_else(|s| s)
    }
}

pub fn rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::None)
}

fn rust_type_full(env: &Env, type_id: library::TypeId, nullable: Nullable, ref_mode: RefMode) -> Result {
    use library::Type::*;
    use library::Fundamental::*;
    let mut skip_option = false;
    let type_ = env.library.type_(type_id);
    let mut rust_type = match *type_ {
        Fundamental(fund) => {
            let ok = |s: &str| Ok(s.into());
            let err = |s: &str| Err(s.into());
            match fund {
                None => err("()"),
                Boolean => ok("bool"),
                Int8 => ok("i8"),
                UInt8 => ok("u8"),
                Int16 => ok("i16"),
                UInt16 => ok("u16"),
                Int32 => ok("i32"),
                UInt32 => ok("u32"),
                Int64 => ok("i64"),
                UInt64 => ok("u64"),

                Int => ok("i32"),      //maybe dependent on target system
                UInt => ok("u32"),     //maybe dependent on target system

                Float => ok("f32"),
                Double => ok("f64"),

                UniChar => ok("char"),
                Utf8 => if ref_mode.is_ref() { ok("str") } else { ok("String") },
                Filename => if ref_mode.is_ref() { ok("str") } else { ok("String") },

                Type => ok("glib::types::Type"),
                Unsupported => err("Unsupported"),
                _ => err(&format!("Fundamental: {:?}", fund)),
            }
        },
        Alias(ref alias) => rust_type_full(env, alias.typ, nullable, ref_mode)
                .map_any(|_| alias.name.clone()),

        Enumeration(ref enum_) => Ok(enum_.name.clone()),
        Bitfield(ref bitfield) => Ok(bitfield.name.clone()),
        Record(ref record) => Ok(record.name.clone()),
        Interface(ref interface) => Ok(interface.name.clone()),
        Class(ref klass) => Ok(klass.name.clone()),
        List(inner_tid) => {
            skip_option = true;
            rust_type(env, inner_tid)
                .map_any(|s| if ref_mode.is_ref() {
                    format!("[{}]", s)
                } else {
                    format!("Vec<{}>", s)
                })
        }
        _ => Err(format!("Unknown rust type: {:?}", type_.get_name())),
        //TODO: check usage library::Type::get_name() when no _ in this
    };

    if type_id.ns_id != library::MAIN_NAMESPACE && type_id.ns_id != library::INTERNAL_NAMESPACE
        && !implemented_in_main_namespace(&env.library, type_id) {
        let rust_type_with_prefix = rust_type.map(|s| format!("{}::{}",
            crate_name(&env.library.namespace(type_id.ns_id).name), s));
        if env.type_status(&type_id.full_name(&env.library)).ignored() {
            rust_type = Err(rust_type_with_prefix.as_str().into());
        } else {
            rust_type = rust_type_with_prefix;
        }
    }
    match ref_mode {
        RefMode::None => {}
        RefMode::ByRef | RefMode::ByRefImmut => rust_type = rust_type.map_any(|s| format!("&{}", s)),
        RefMode::ByRefMut => rust_type = rust_type.map_any(|s| format!("&mut {}", s)),
    }
    if *nullable && !skip_option {
        match ConversionType::of(&env.library, type_id) {
            ConversionType::Pointer => rust_type = rust_type.map_any(|s| format!("Option<{}>", s)),
            _ => (),
        }
    }

    rust_type
}

pub fn used_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    use library::Type::*;
    match *env.library.type_(type_id) {
        Fundamental(library::Fundamental::Type) |
            Alias(..) |
            Bitfield(..) |
            Record(..) |
            Class(..) |
            Enumeration(..) |
            Interface(..) => rust_type(env, type_id),
        List(inner_tid) => used_rust_type(env, inner_tid),
        _ => Err("Don't need use".into()),
    }
}

pub fn parameter_rust_type(env: &Env, type_id:library::TypeId,
                           direction: library::ParameterDirection, nullable: Nullable,
                           ref_mode: RefMode) -> Result {
    use library::Type::*;
    let type_ = env.library.type_(type_id);
    let rust_type = rust_type_full(env, type_id, nullable, ref_mode);
    match *type_ {
        Fundamental(fund) => {
            if fund == library::Fundamental::Utf8 || fund == library::Fundamental::Filename {
                match direction {
                    library::ParameterDirection::In |
                        library::ParameterDirection::Return => rust_type,
                    _ => Err(format!("/*Unimplemented*/{}", rust_type.as_str())),
                }
            } else {
                format_parameter(rust_type, direction)
            }
        }
        Alias(ref alias) => {
            let res = format_parameter(rust_type, direction);
            if parameter_rust_type(env, alias.typ, direction, nullable, ref_mode).is_ok() {
                res
            } else {
                res.and_then(|s| Err(s))
            }
        }

        Enumeration(..) |
            Bitfield(..) => format_parameter(rust_type, direction),

        Record(..) => {
            if env.type_status(&type_id.full_name(&env.library)).ignored() {
                Err(format!("/*Ignored*/{}", rust_type.as_str()))
            } else if direction == library::ParameterDirection::InOut {
                Err(format!("/*Unimplemented*/{}", rust_type.as_str()))
            } else {
                rust_type
            }
        }

        Class(..) |
            Interface (..) => {
            match direction {
                _ if env.type_status(&type_id.full_name(&env.library)).ignored() => {
                    Err(format!("/*Ignored*/{}", rust_type.as_str()))
                }
                library::ParameterDirection::In |
                    library::ParameterDirection::Return => rust_type,
                _ => Err(format!("/*Unimplemented*/{}", rust_type.as_str())),
            }
        }

        List(..) => {
            match direction {
                library::ParameterDirection::Return => rust_type,
                _ => Err(format!("/*Unimplemented*/{}", rust_type.as_str())),
            }
        }
        _ => Err(format!("Unknown rust type: {:?}", type_.get_name())),
        //TODO: check usage library::Type::get_name() when no _ in this
    }
}

#[inline]
fn format_parameter(rust_type: Result, direction: library::ParameterDirection) -> Result {
    if direction.is_out() {
        rust_type.map(|s| format!("&mut {}", s))
    } else {
        rust_type
    }
}

fn implemented_in_main_namespace(library: &library::Library, type_id: library::TypeId) -> bool {
    if library.namespace(library::MAIN_NAMESPACE).name != "Gtk" {
        return false;
    }
    match &*type_id.full_name(library) {
        "Gdk.Rectangle" => true,
        _ => false,
    }
}
<commit_msg>Support "nullability" for types with scalar conversion<commit_after>use std::result;

use analysis::ref_mode::RefMode;
use env::Env;
use library::{self, Nullable};
use nameutil::crate_name;
use super::conversion_type::ConversionType;
use traits::*;

pub type Result = result::Result<String, String>;

impl AsStr for Result {
    #[inline]
    fn as_str(&self) -> &str {
        self.as_ref().unwrap_or_else(|s| s)
    }
}

pub fn rust_type(env: &Env, type_id: library::TypeId) -> Result {
    rust_type_full(env, type_id, Nullable(false), RefMode::None)
}

fn rust_type_full(env: &Env, type_id: library::TypeId, nullable: Nullable, ref_mode: RefMode) -> Result {
    use library::Type::*;
    use library::Fundamental::*;
    let mut skip_option = false;
    let type_ = env.library.type_(type_id);
    let mut rust_type = match *type_ {
        Fundamental(fund) => {
            let ok = |s: &str| Ok(s.into());
            let err = |s: &str| Err(s.into());
            match fund {
                None => err("()"),
                Boolean => ok("bool"),
                Int8 => ok("i8"),
                UInt8 => ok("u8"),
                Int16 => ok("i16"),
                UInt16 => ok("u16"),
                Int32 => ok("i32"),
                UInt32 => ok("u32"),
                Int64 => ok("i64"),
                UInt64 => ok("u64"),

                Int => ok("i32"),      //maybe dependent on target system
                UInt => ok("u32"),     //maybe dependent on target system

                Float => ok("f32"),
                Double => ok("f64"),

                UniChar => ok("char"),
                Utf8 => if ref_mode.is_ref() { ok("str") } else { ok("String") },
                Filename => if ref_mode.is_ref() { ok("str") } else { ok("String") },

                Type => ok("glib::types::Type"),
                Unsupported => err("Unsupported"),
                _ => err(&format!("Fundamental: {:?}", fund)),
            }
        },
        Alias(ref alias) => rust_type_full(env, alias.typ, nullable, ref_mode)
                .map_any(|_| alias.name.clone()),

        Enumeration(ref enum_) => Ok(enum_.name.clone()),
        Bitfield(ref bitfield) => Ok(bitfield.name.clone()),
        Record(ref record) => Ok(record.name.clone()),
        Interface(ref interface) => Ok(interface.name.clone()),
        Class(ref klass) => Ok(klass.name.clone()),
        List(inner_tid) => {
            skip_option = true;
            rust_type(env, inner_tid)
                .map_any(|s| if ref_mode.is_ref() {
                    format!("[{}]", s)
                } else {
                    format!("Vec<{}>", s)
                })
        }
        _ => Err(format!("Unknown rust type: {:?}", type_.get_name())),
        //TODO: check usage library::Type::get_name() when no _ in this
    };

    if type_id.ns_id != library::MAIN_NAMESPACE && type_id.ns_id != library::INTERNAL_NAMESPACE
        && !implemented_in_main_namespace(&env.library, type_id) {
        let rust_type_with_prefix = rust_type.map(|s| format!("{}::{}",
            crate_name(&env.library.namespace(type_id.ns_id).name), s));
        if env.type_status(&type_id.full_name(&env.library)).ignored() {
            rust_type = Err(rust_type_with_prefix.as_str().into());
        } else {
            rust_type = rust_type_with_prefix;
        }
    }
    match ref_mode {
        RefMode::None => {}
        RefMode::ByRef | RefMode::ByRefImmut => rust_type = rust_type.map_any(|s| format!("&{}", s)),
        RefMode::ByRefMut => rust_type = rust_type.map_any(|s| format!("&mut {}", s)),
    }
    if *nullable && !skip_option {
        match ConversionType::of(&env.library, type_id) {
            ConversionType::Pointer
                | ConversionType::Scalar => {
                rust_type = rust_type.map_any(|s| format!("Option<{}>", s))
            }
            _ => (),
        }
    }

    rust_type
}

pub fn used_rust_type(env: &Env, type_id: library::TypeId) -> Result {
    use library::Type::*;
    match *env.library.type_(type_id) {
        Fundamental(library::Fundamental::Type) |
            Alias(..) |
            Bitfield(..) |
            Record(..) |
            Class(..) |
            Enumeration(..) |
            Interface(..) => rust_type(env, type_id),
        List(inner_tid) => used_rust_type(env, inner_tid),
        _ => Err("Don't need use".into()),
    }
}

pub fn parameter_rust_type(env: &Env, type_id:library::TypeId,
                           direction: library::ParameterDirection, nullable: Nullable,
                           ref_mode: RefMode) -> Result {
    use library::Type::*;
    let type_ = env.library.type_(type_id);
    let rust_type = rust_type_full(env, type_id, nullable, ref_mode);
    match *type_ {
        Fundamental(fund) => {
            if fund == library::Fundamental::Utf8 || fund == library::Fundamental::Filename {
                match direction {
                    library::ParameterDirection::In |
                        library::ParameterDirection::Return => rust_type,
                    _ => Err(format!("/*Unimplemented*/{}", rust_type.as_str())),
                }
            } else {
                format_parameter(rust_type, direction)
            }
        }
        Alias(ref alias) => {
            let res = format_parameter(rust_type, direction);
            if parameter_rust_type(env, alias.typ, direction, nullable, ref_mode).is_ok() {
                res
            } else {
                res.and_then(|s| Err(s))
            }
        }

        Enumeration(..) |
            Bitfield(..) => format_parameter(rust_type, direction),

        Record(..) => {
            if env.type_status(&type_id.full_name(&env.library)).ignored() {
                Err(format!("/*Ignored*/{}", rust_type.as_str()))
            } else if direction == library::ParameterDirection::InOut {
                Err(format!("/*Unimplemented*/{}", rust_type.as_str()))
            } else {
                rust_type
            }
        }

        Class(..) |
            Interface (..) => {
            match direction {
                _ if env.type_status(&type_id.full_name(&env.library)).ignored() => {
                    Err(format!("/*Ignored*/{}", rust_type.as_str()))
                }
                library::ParameterDirection::In |
                    library::ParameterDirection::Return => rust_type,
                _ => Err(format!("/*Unimplemented*/{}", rust_type.as_str())),
            }
        }

        List(..) => {
            match direction {
                library::ParameterDirection::Return => rust_type,
                _ => Err(format!("/*Unimplemented*/{}", rust_type.as_str())),
            }
        }
        _ => Err(format!("Unknown rust type: {:?}", type_.get_name())),
        //TODO: check usage library::Type::get_name() when no _ in this
    }
}

#[inline]
fn format_parameter(rust_type: Result, direction: library::ParameterDirection) -> Result {
    if direction.is_out() {
        rust_type.map(|s| format!("&mut {}", s))
    } else {
        rust_type
    }
}

fn implemented_in_main_namespace(library: &library::Library, type_id: library::TypeId) -> bool {
    if library.namespace(library::MAIN_NAMESPACE).name != "Gtk" {
        return false;
    }
    match &*type_id.full_name(library) {
        "Gdk.Rectangle" => true,
        _ => false,
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate extra;

use std::env;
use std::io::{stdout, stderr, Write};
use extra::option::OptionalExt;
use std::process::exit;

const MAN_PAGE: &'static str = /* @MANSTART{echo} */ r#"
NAME
    echo - display a line of text

SYNOPSIS
    echo [ -h | --help ] [-e] [-n] [-s] [STRING]...

DESCRIPTION
    Print the STRING(s) to standard output.

OPTIONS
    -e
        enable the interpretation of backslash escapes
    -n
        do not output the trailing newline
    -s
        do not separate arguments with spaces

    Escape Sequences
        When the -e argument is used, the following sequences will be interpreted:

        \\  backslash

        \a  alert (BEL)

        \b  backspace (BS)

        \c  produce no further output

        \e  escape (ESC)

        \f  form feed (FF)

        \n  new line

        \r  carriage return

        \t  horizontal tab (HT)

        \v  vertical tab (VT)

"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let stdout = &mut stdout.lock();
    let stderr = &mut stderr();
    let args = env::args().skip(1).collect::<Vec<String>>();

    let (mut no_newline, mut no_spaces, mut escape) = (false, false, false);

    // Check for specific flags
    for argument in args.iter().map(|x| x.as_bytes()) {
        if argument.len() == 2 && argument[0] == b'-' {
            match argument[1] {
                b'h' => {
                    stdout.write(MAN_PAGE.as_bytes()).try(stderr);
                    stdout.flush().try(stderr);
                    exit(0);
                }
                b'n' => no_newline = true,
                b's' => no_spaces = true,
                b'e' => escape = true,
                _   => ()
            }
        }
    }

    // Print to standard output
    for argument in args.iter().map(|x| x.as_bytes()) {
        if argument.len() == 2 && argument[0] == b'-' {
            match argument[1] {
                b'n' | b's' | b'e' => continue,
                _ => { stdout.write(argument).try(stderr); }
            }
        } else {
            if escape {
                let mut check = false;
                for &byte in argument {
                    match byte {
                        b'\\' if check => {
                            stdout.write(&[byte]).try(stderr);
                            check = false;
                        },
                        b'\\' => check = true,
                        b'a' if check => {
                            stdout.write(&[7u8]).try(stderr); // bell
                            check = false;
                        },
                        b'b' if check => {
                            stdout.write(&[8u8]).try(stderr); // backspace
                            check = false;
                        },
                        b'c' if check => {
                            exit(0);
                        },
                        b'e' if check => {
                            stdout.write(&[27u8]).try(stderr); // escape
                            check = false;
                        },
                        b'f' if check => {
                            stdout.write(&[12u8]).try(stderr); // form feed
                            check = false;
                        },
                        b'n' if check => {
                            stdout.write(&[b'\n']).try(stderr); // newline
                            check = false;
                        },
                        b'r' if check => {
                            stdout.write(&[b'\r']).try(stderr);
                            check = false;
                        },
                        b't' if check => {
                            stdout.write(&[b'\t']).try(stderr);
                            check = false;
                        },
                        b'v' if check => {
                            stdout.write(&[11u8]).try(stderr); // vertical tab
                            check = false;
                        },
                        _ if check => {
                            stdout.write(&[b'\\', byte]).try(stderr);
                            check = false;
                        },
                        _ => { stdout.write(&[byte]).try(stderr); }
                    }
                }
            } else {
                stdout.write(argument).try(stderr);
            }
        }
        if !no_spaces { stdout.write(&[b' ']).try(stderr); }
    }

    if !no_newline { stdout.write(&[b'\n']).try(stderr); }
}
<commit_msg>Adapt echo.rs with ArgParser<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::io::{stdout, stderr, Write};
use std::process::exit;
use coreutils::ArgParser;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{echo} */ r#"
NAME
    echo - display a line of text

SYNOPSIS
    echo [ -h | --help ] [-e] [-n] [-s] [STRING]...

DESCRIPTION
    Print the STRING(s) to standard output.

OPTIONS
    -e
        enable the interpretation of backslash escapes
    -n
        do not output the trailing newline
    -s
        do not separate arguments with spaces

    Escape Sequences
        When the -e argument is used, the following sequences will be interpreted:

        \\  backslash

        \a  alert (BEL)

        \b  backspace (BS)

        \c  produce no further output

        \e  escape (ESC)

        \f  form feed (FF)

        \n  new line

        \r  carriage return

        \t  horizontal tab (HT)

        \v  vertical tab (VT)

"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(4)
        .add_flag("e", "escape")
        .add_flag("n", "no-newline")
        .add_flag("s", "no-spaces")
        .add_flag("h", "help");
    parser.initialize(env::args());

    if parser.flagged(&'h') || parser.flagged("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    // Print to standard output
    for arg in parser.args.iter().map(|x| x.as_bytes()) {
        if parser.flagged(&'e') || parser.flagged("escape") {
            let mut check = false;
            for &byte in arg {
                match byte {
                    b'\\' if check => {
                        stdout.write(&[byte]).try(&mut stderr);
                        check = false;
                    },
                    b'\\' => check = true,
                    b'a' if check => {
                        stdout.write(&[7u8]).try(&mut stderr); // bell
                        check = false;
                    },
                    b'b' if check => {
                        stdout.write(&[8u8]).try(&mut stderr); // backspace
                        check = false;
                    },
                    b'c' if check => {
                        exit(0);
                    },
                    b'e' if check => {
                        stdout.write(&[27u8]).try(&mut stderr); // escape
                        check = false;
                    },
                    b'f' if check => {
                        stdout.write(&[12u8]).try(&mut stderr); // form feed
                        check = false;
                    },
                    b'n' if check => {
                        stdout.write(&[b'\n']).try(&mut stderr); // newline
                        check = false;
                    },
                    b'r' if check => {
                        stdout.write(&[b'\r']).try(&mut stderr);
                        check = false;
                    },
                    b't' if check => {
                        stdout.write(&[b'\t']).try(&mut stderr);
                        check = false;
                    },
                    b'v' if check => {
                        stdout.write(&[11u8]).try(&mut stderr); // vertical tab
                        check = false;
                    },
                    _ if check => {
                        stdout.write(&[b'\\', byte]).try(&mut stderr);
                        check = false;
                    },
                    _ => { stdout.write(&[byte]).try(&mut stderr); }
                }
            }
        }
        if !(parser.flagged(&'s') || parser.flagged("no-spaces")) {
            stdout.write(&[b' ']).try(&mut stderr);
        }
    }

    if !(parser.flagged(&'n') || parser.flagged("no-newline")) {
        stdout.write(&[b'\n']).try(&mut stderr);
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;

extern crate telegram_bot_raw;

use std::fs::File;
use std::io::prelude::*;

use telegram_bot_raw::types::message::MessageKind;
use telegram_bot_raw::types::update::{Update, UpdateKind};

macro_rules! make_test {
    ($asset: ident, $test: expr) => {
        #[test]
        fn $asset() {
            let data = {
                let filename = format!("tests/update_assets/{}.json", stringify!($asset));
                let mut data = Vec::new();
                let mut file = File::open(filename).unwrap();
                file.read_to_end(&mut data).unwrap();
                data
            };
            let update = serde_json::from_slice::<Update>(&data).unwrap();
            $test(update)
        }
    };
}

make_test!(migrate_from_chat_id, |update: Update| {
    if let UpdateKind::Message(message) = update.kind {
        if let MessageKind::MigrateFromChatId { .. } = message.kind {
            return ();
        }
    }
    assert!(false)
});

make_test!(migrate_to_chat_id, |update: Update| {
    if let UpdateKind::Message(message) = update.kind {
        if let MessageKind::MigrateToChatId { .. } = message.kind {
            return ();
        }
    }
    assert!(false)
});

make_test!(inline_query, |update: Update| {
    if let UpdateKind::InlineQuery(query) = update.kind {
        return ();
    }

    assert!(false)
});
<commit_msg>Fix unused variable warning<commit_after>use std::fs::File;
use std::io::prelude::*;

use telegram_bot_raw::types::message::MessageKind;
use telegram_bot_raw::types::update::{Update, UpdateKind};

macro_rules! make_test {
    ($asset: ident, $test: expr) => {
        #[test]
        fn $asset() {
            let data = {
                let filename = format!("tests/update_assets/{}.json", stringify!($asset));
                let mut data = Vec::new();
                let mut file = File::open(filename).unwrap();
                file.read_to_end(&mut data).unwrap();
                data
            };
            let update = serde_json::from_slice::<Update>(&data).unwrap();
            $test(update)
        }
    };
}

make_test!(migrate_from_chat_id, |update: Update| {
    if let UpdateKind::Message(message) = update.kind {
        if let MessageKind::MigrateFromChatId { .. } = message.kind {
            return ();
        }
    }
    assert!(false)
});

make_test!(migrate_to_chat_id, |update: Update| {
    if let UpdateKind::Message(message) = update.kind {
        if let MessageKind::MigrateToChatId { .. } = message.kind {
            return ();
        }
    }
    assert!(false)
});

make_test!(inline_query, |update: Update| {
    if let UpdateKind::InlineQuery(_query) = update.kind {
        return ();
    }

    assert!(false)
});
<|endoftext|>


<commit_before>extern crate rustyline;
extern crate combine;
extern crate telescope;

use rustyline::Editor;
use rustyline::error::ReadlineError as RLError;
use telescope::{lexer, parser};

fn main() {
    // Prompt constants
    let header = format!(r"telescope v{}", env!("CARGO_PKG_VERSION"));
    let prompt = "> ";

    let mut rl = Editor::<()>::new();

    println!("{}", header);

    loop {
        match rl.readline(prompt) {
            Ok(line) => {
                rl.add_history_entry(&line);
                if line == "exit" || line == "quit" {
                    break;
                }
                match lexer::lex(line.trim_right()) {
                    Ok((tokens, unlexed)) => {
                        match parser::parse(tokens.as_slice()) {
                            Ok((exprs, unparsed)) => {
                                for expr in exprs {
                                    print!("{} ", expr);
                                }
                                println!();
                                if !unparsed.is_empty() {
                                    println!("Unparsed: {:?}", unparsed);
                                }
                            }
                            Err(e) => println!("Error: {:?}", e),
                        };
                        if !unlexed.is_empty() {
                            println!("Unlexed: {}", unlexed)
                        }
                    }
                    Err(e) => println!("Error: {}", e),
                };
            }
            Err(RLError::Interrupted) |
            Err(RLError::Eof) => break,
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        };
    }
}
<commit_msg>Attempt to smoothen error handling in main<commit_after>extern crate rustyline;
extern crate combine;
extern crate telescope;

use rustyline::Editor;
use rustyline::error::ReadlineError as RLError;
use telescope::{lexer, parser};
// use telescope::error::*;

fn main() {
    // Prompt constants
    let header = format!(r"telescope v{}", env!("CARGO_PKG_VERSION"));
    let prompt = "> ";

    let mut rl = Editor::<()>::new();

    println!("{}", header);

    loop {
        match rl.readline(prompt) {
            Ok(line) => {
                rl.add_history_entry(&line);
                if line == "exit" || line == "quit" {
                    break;
                }

                let _ = lexer::lex(line.trim_right())
                    .map(|(tokens, _unlexed)| {
                        parser::parse(&*tokens)
                            .map(|(exprs, _unparsed)| {
                                for expr in exprs {
                                    match expr.eval() {
                                        Ok(value) => print!("{} ", value),
                                        Err(err) => { println!("Error: {}", err); continue }
                                    }
                                }
                                println!();
                            })
                            .map_err(|err| println!("Unparsed: {:?}", err))
                    })
                    .map_err(|err| println!("Error: {}", err));
            }
            Err(RLError::Interrupted) |
            Err(RLError::Eof) => break,
            Err(err) => {
                println!("Error: {:?}", err);
                break;
            }
        };
    }
}
<|endoftext|>


<commit_before>//! Utilities for working with buffers.
//!
//! A buffer is any structure that contains a sequence of bytes. The bytes may
//! or may not be stored in contiguous memory. This module contains traits used
//! to abstract over buffers as well as utilities for working with buffer types.
//!
//! # `Buf`, `BufMut`
//!
//! These are the two foundational traits for abstractly working with buffers.
//! They can be thought as iterators for byte structures. They offer additional
//! performance over `Iterator` by providing an API optimized for byte slices.
//!
//! See [`Buf`] and [`BufMut`] for more details.
//!
//! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure)
//! [`Buf`]: trait.Buf.html
//! [`BufMut`]: trait.BufMut.html

use std::{cmp, io, usize};

mod buf;
mod buf_mut;
mod from_buf;
mod into_buf;
mod reader;
mod source;
mod take;
mod writer;

pub use self::buf::Buf;
pub use self::buf_mut::BufMut;
pub use self::from_buf::FromBuf;
pub use self::into_buf::IntoBuf;
pub use self::reader::Reader;
pub use self::source::Source;
pub use self::take::Take;
pub use self::writer::Writer;

/*
 *
 * ===== Buf impls =====
 *
 */

impl<'a, T: Buf> Buf for &'a mut T {
    fn remaining(&self) -> usize {
        (**self).remaining()
    }

    fn bytes(&self) -> &[u8] {
        (**self).bytes()
    }

    fn advance(&mut self, cnt: usize) {
        (**self).advance(cnt)
    }
}

impl<'a, T: BufMut> BufMut for &'a mut T {
    fn remaining_mut(&self) -> usize {
        (**self).remaining_mut()
    }

    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        (**self).bytes_mut()
    }

    unsafe fn advance_mut(&mut self, cnt: usize) {
        (**self).advance_mut(cnt)
    }
}

impl<T: AsRef<[u8]>> Buf for io::Cursor<T> {
    fn remaining(&self) -> usize {
        let len = self.get_ref().as_ref().len();
        let pos = self.position();

        if pos >= len as u64 {
            return 0;
        }

        len - pos as usize
    }

    fn bytes(&self) -> &[u8] {
        let pos = self.position() as usize;
        &(self.get_ref().as_ref())[pos..]
    }

    fn advance(&mut self, cnt: usize) {
        let pos = self.position() as usize;
        let pos = cmp::min(self.get_ref().as_ref().len(), pos + cnt);
        self.set_position(pos as u64);
    }
}

impl<T: AsMut<[u8]> + AsRef<[u8]>> BufMut for io::Cursor<T> {
    fn remaining_mut(&self) -> usize {
        self.remaining()
    }

    /// Advance the internal cursor of the BufMut
    unsafe fn advance_mut(&mut self, cnt: usize) {
        let pos = self.position() as usize;
        let pos = cmp::min(self.get_mut().as_mut().len(), pos + cnt);
        self.set_position(pos as u64);
    }

    /// Returns a mutable slice starting at the current BufMut position and of
    /// length between 0 and `BufMut::remaining()`.
    ///
    /// The returned byte slice may represent uninitialized memory.
    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        let pos = self.position() as usize;
        &mut (self.get_mut().as_mut())[pos..]
    }
}

impl BufMut for Vec<u8> {
    fn remaining_mut(&self) -> usize {
        usize::MAX - self.len()
    }

    unsafe fn advance_mut(&mut self, cnt: usize) {
        let len = self.len() + cnt;

        if len > self.capacity() {
            // Reserve additional
            // TODO: Should this case panic?
            let cap = self.capacity();
            self.reserve(cap - len);
        }

        self.set_len(len);
    }

    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        use std::slice;

        if self.capacity() == self.len() {
            self.reserve(64); // Grow the vec
        }

        let cap = self.capacity();
        let len = self.len();

        let ptr = self.as_mut_ptr();
        &mut slice::from_raw_parts_mut(ptr, cap)[len..]
    }
}
<commit_msg>Expand object-safe impls slightly<commit_after>//! Utilities for working with buffers.
//!
//! A buffer is any structure that contains a sequence of bytes. The bytes may
//! or may not be stored in contiguous memory. This module contains traits used
//! to abstract over buffers as well as utilities for working with buffer types.
//!
//! # `Buf`, `BufMut`
//!
//! These are the two foundational traits for abstractly working with buffers.
//! They can be thought as iterators for byte structures. They offer additional
//! performance over `Iterator` by providing an API optimized for byte slices.
//!
//! See [`Buf`] and [`BufMut`] for more details.
//!
//! [rope]: https://en.wikipedia.org/wiki/Rope_(data_structure)
//! [`Buf`]: trait.Buf.html
//! [`BufMut`]: trait.BufMut.html

use std::{cmp, io, usize};

mod buf;
mod buf_mut;
mod from_buf;
mod into_buf;
mod reader;
mod source;
mod take;
mod writer;

pub use self::buf::Buf;
pub use self::buf_mut::BufMut;
pub use self::from_buf::FromBuf;
pub use self::into_buf::IntoBuf;
pub use self::reader::Reader;
pub use self::source::Source;
pub use self::take::Take;
pub use self::writer::Writer;

/*
 *
 * ===== Buf impls =====
 *
 */

impl<'a, T: Buf + ?Sized> Buf for &'a mut T {
    fn remaining(&self) -> usize {
        (**self).remaining()
    }

    fn bytes(&self) -> &[u8] {
        (**self).bytes()
    }

    fn advance(&mut self, cnt: usize) {
        (**self).advance(cnt)
    }
}

impl<'a, T: BufMut + ?Sized> BufMut for &'a mut T {
    fn remaining_mut(&self) -> usize {
        (**self).remaining_mut()
    }

    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        (**self).bytes_mut()
    }

    unsafe fn advance_mut(&mut self, cnt: usize) {
        (**self).advance_mut(cnt)
    }
}

impl<T: Buf + ?Sized> Buf for Box<T> {
    fn remaining(&self) -> usize {
        (**self).remaining()
    }

    fn bytes(&self) -> &[u8] {
        (**self).bytes()
    }

    fn advance(&mut self, cnt: usize) {
        (**self).advance(cnt)
    }
}

impl<T: BufMut + ?Sized> BufMut for Box<T> {
    fn remaining_mut(&self) -> usize {
        (**self).remaining_mut()
    }

    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        (**self).bytes_mut()
    }

    unsafe fn advance_mut(&mut self, cnt: usize) {
        (**self).advance_mut(cnt)
    }
}

impl<T: AsRef<[u8]>> Buf for io::Cursor<T> {
    fn remaining(&self) -> usize {
        let len = self.get_ref().as_ref().len();
        let pos = self.position();

        if pos >= len as u64 {
            return 0;
        }

        len - pos as usize
    }

    fn bytes(&self) -> &[u8] {
        let pos = self.position() as usize;
        &(self.get_ref().as_ref())[pos..]
    }

    fn advance(&mut self, cnt: usize) {
        let pos = self.position() as usize;
        let pos = cmp::min(self.get_ref().as_ref().len(), pos + cnt);
        self.set_position(pos as u64);
    }
}

impl<T: AsMut<[u8]> + AsRef<[u8]>> BufMut for io::Cursor<T> {
    fn remaining_mut(&self) -> usize {
        self.remaining()
    }

    /// Advance the internal cursor of the BufMut
    unsafe fn advance_mut(&mut self, cnt: usize) {
        let pos = self.position() as usize;
        let pos = cmp::min(self.get_mut().as_mut().len(), pos + cnt);
        self.set_position(pos as u64);
    }

    /// Returns a mutable slice starting at the current BufMut position and of
    /// length between 0 and `BufMut::remaining()`.
    ///
    /// The returned byte slice may represent uninitialized memory.
    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        let pos = self.position() as usize;
        &mut (self.get_mut().as_mut())[pos..]
    }
}

impl BufMut for Vec<u8> {
    fn remaining_mut(&self) -> usize {
        usize::MAX - self.len()
    }

    unsafe fn advance_mut(&mut self, cnt: usize) {
        let len = self.len() + cnt;

        if len > self.capacity() {
            // Reserve additional
            // TODO: Should this case panic?
            let cap = self.capacity();
            self.reserve(cap - len);
        }

        self.set_len(len);
    }

    unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        use std::slice;

        if self.capacity() == self.len() {
            self.reserve(64); // Grow the vec
        }

        let cap = self.capacity();
        let len = self.len();

        let ptr = self.as_mut_ptr();
        &mut slice::from_raw_parts_mut(ptr, cap)[len..]
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::path::Path;

use super::context::{Context};
use super::handler::Handler;
use super::config::{self, Config, Route, MethodHandler};

const STATUS_CODES: [(u16, &'static str); 62] = [
    (100, "Continue"),
    (101, "Switching Protocols"),
    (102, "Processing"),
    (200, "OK"),
    (201, "Created"),
    (202, "Accepted"),
    (203, "Non-authoritative Information"),
    (204, "No Content"),
    (205, "Reset Content"),
    (206, "Partial Content"),
    (207, "Multi-Status"),
    (208, "Already Reported"),
    (226, "IM Used"),
    (300, "Multiple Choices"),
    (301, "Moved Permanently"),
    (302, "Found"),
    (303, "See Other"),
    (304, "Not Modified"),
    (305, "Use Proxy"),
    (307, "Temporary Redirect"),
    (308, "Permanent Redirect"),
    (400, "Bad Request"),
    (401, "Unauthorized"),
    (402, "Payment Required"),
    (403, "Forbidden"),
    (404, "Not Found"),
    (405, "Method Not Allowed"),
    (406, "Not Acceptable"),
    (407, "Proxy Authentication Required"),
    (408, "Request Timeout"),
    (409, "Conflict"),
    (410, "Gone"),
    (411, "Length Required"),
    (412, "Precondition Failed"),
    (413, "Payload Too Large"),
    (414, "Request-URI Too Long"),
    (415, "Unsupported Media Type"),
    (416, "Requested Range Not Satisfiable"),
    (417, "Expectation Failed"),
    (418, "I'm a teapot"),
    (421, "Misdirected Request"),
    (422, "Unprocessable Entity"),
    (423, "Locked"),
    (424, "Failed Dependency"),
    (426, "Upgrade Required"),
    (428, "Precondition Required"),
    (429, "Too Many Requests"),
    (431, "Request Header Fields Too Large"),
    (451, "Unavailable For Legal Reasons"),
    (499, "Client Closed Request"),
    (500, "Internal Server Error"),
    (501, "Not Implemented"),
    (502, "Bad Gateway"),
    (503, "Service Unavailable"),
    (504, "Gateway Timeout"),
    (505, "HTTP Version Not Supported"),
    (506, "Variant Also Negotiates"),
    (507, "Insufficient Storage"),
    (508, "Loop Detected"),
    (510, "Not Extended"),
    (511, "Network Authentication Required"),
    (599, "Network Connect Timeout Error"),
];

pub fn build_context(context: &mut Context, configuration: Config) -> Result<(), String> {
    for (path, route) in configuration.routes.iter() {
        match route {
            &Route::Include(ref filename) =>
                try!(process_include(filename, path, &configuration, context)),
            &Route::Handler(ref route_handler) => {
                try!(process_handler(path, route_handler, &configuration, context));
            }
        }
    }

    process_notfound(&configuration, context);

    Ok(())
}

fn process_include(filename: &Path, root_path: &str, configuration: &Config, context: &mut Context)
    -> Result<(), String>
{
    let include_config = try!(config::read_config_include(filename));
    for (path, route) in include_config.iter() {
        let path = format!("{}/{}", root_path.trim_right_matches("/"),
                                    path.trim_left_matches("/"));

        match route {
            &Route::Include(ref filename) => try!(process_include(filename, &path, configuration, context)),
            &Route::Handler(ref route_handler) => {
                try!(process_handler(&path, route_handler, &configuration, context));
            }
        }
    }
    Ok(())
}

fn process_handler(path: &str,
                   route: &MethodHandler,
                   configuration: &Config,
                   context: &mut Context)
                   -> Result<(), String>
{
    for (method, handler_config) in route.handlers() {
        let status_code = handler_config.code;
        let status_text = handler_config.status.as_ref()
            .map(|x| x.clone())
            .unwrap_or(description(status_code).to_owned());

        let mut handler = Handler::new(status_code, status_text);
        handler.set_content(handler_config.content.clone());

        if handler_config.content.is_some() {
            let content_type = handler_config.contenttype.as_ref()
                .map(|x| &**x)
                .unwrap_or(configuration.settings.contenttype.as_ref())
                .as_bytes().iter().map(|b| *b).collect();

            handler.add_header("Content-Type".to_owned(), content_type);
        }

        process_headers(&mut handler,
                        &handler_config.headers,
                        &configuration.settings.headers,
                        configuration.settings.headers_replace);

        let path = if !path.ends_with("$") {
            format!("{}$", path)
        } else {
            path.to_owned()
        };
        try!(context.add_route(&path, method.to_owned(), handler)
            .map_err(|e| format!("Error adding route: {}", e)));
    }
    Ok(())
}

fn process_notfound(configuration: &Config, context: &mut Context) {
    match configuration.notfound {
        Some(ref not_found) => {
            let status_text = not_found.status
                .as_ref()
                .map(|x| x.clone())
                .unwrap_or(description(404).to_owned());

            let mut handler = Handler::new(404, status_text);
            handler.set_content(not_found.content.clone());

            if not_found.content.is_some() {
                let content_type = not_found.contenttype.as_ref()
                    .map(|x| &**x)
                    .unwrap_or(configuration.settings.contenttype.as_ref())
                    .as_bytes().iter().map(|b| *b).collect();

                handler.add_header("Content-Type".to_owned(), content_type);
            }

            for (k, v) in not_found.headers.iter() {
                handler.add_header(k.clone(), v.as_bytes().iter().map(|b| *b).collect());
            }

            let content_type = not_found.contenttype.clone().unwrap_or("application/json".to_owned());
            handler.add_header("Content-Type".to_owned(),
                               content_type.as_bytes().iter().map(|b| *b).collect());

            context.set_not_found_handler(handler);
        }
        None => {}
    }
}

fn description(status: u16) -> &'static str {
    for &(code, description) in STATUS_CODES.iter() {
        if status == code {
            return description
        }
    }
    "[Unknown HTTP Status]"
}

fn process_headers(handler: &mut Handler,
                   route_headers: &BTreeMap<String, String>,
                   settings_headers: &BTreeMap<String, String>,
                   replace: bool)
{
    if replace {
        let iter = route_headers.iter().filter(|&(ref k, _)| {
            !settings_headers.contains_key(k.to_owned())
        }).chain(settings_headers.iter());
        for (key, val) in iter {
            let header = val.as_bytes().iter().map(|b| *b).collect();
            handler.add_header(key.clone(), header);
        }
    } else {
        for (key, val) in route_headers.iter().chain(settings_headers.iter()) {
            let header = val.as_bytes().iter().map(|b| *b).collect();
            handler.add_header(key.clone(), header);
        }
    };
}
<commit_msg>Fix global headers replacing handler headers<commit_after>use std::collections::BTreeMap;
use std::path::Path;

use super::context::{Context};
use super::handler::Handler;
use super::config::{self, Config, Route, MethodHandler};

const STATUS_CODES: [(u16, &'static str); 62] = [
    (100, "Continue"),
    (101, "Switching Protocols"),
    (102, "Processing"),
    (200, "OK"),
    (201, "Created"),
    (202, "Accepted"),
    (203, "Non-authoritative Information"),
    (204, "No Content"),
    (205, "Reset Content"),
    (206, "Partial Content"),
    (207, "Multi-Status"),
    (208, "Already Reported"),
    (226, "IM Used"),
    (300, "Multiple Choices"),
    (301, "Moved Permanently"),
    (302, "Found"),
    (303, "See Other"),
    (304, "Not Modified"),
    (305, "Use Proxy"),
    (307, "Temporary Redirect"),
    (308, "Permanent Redirect"),
    (400, "Bad Request"),
    (401, "Unauthorized"),
    (402, "Payment Required"),
    (403, "Forbidden"),
    (404, "Not Found"),
    (405, "Method Not Allowed"),
    (406, "Not Acceptable"),
    (407, "Proxy Authentication Required"),
    (408, "Request Timeout"),
    (409, "Conflict"),
    (410, "Gone"),
    (411, "Length Required"),
    (412, "Precondition Failed"),
    (413, "Payload Too Large"),
    (414, "Request-URI Too Long"),
    (415, "Unsupported Media Type"),
    (416, "Requested Range Not Satisfiable"),
    (417, "Expectation Failed"),
    (418, "I'm a teapot"),
    (421, "Misdirected Request"),
    (422, "Unprocessable Entity"),
    (423, "Locked"),
    (424, "Failed Dependency"),
    (426, "Upgrade Required"),
    (428, "Precondition Required"),
    (429, "Too Many Requests"),
    (431, "Request Header Fields Too Large"),
    (451, "Unavailable For Legal Reasons"),
    (499, "Client Closed Request"),
    (500, "Internal Server Error"),
    (501, "Not Implemented"),
    (502, "Bad Gateway"),
    (503, "Service Unavailable"),
    (504, "Gateway Timeout"),
    (505, "HTTP Version Not Supported"),
    (506, "Variant Also Negotiates"),
    (507, "Insufficient Storage"),
    (508, "Loop Detected"),
    (510, "Not Extended"),
    (511, "Network Authentication Required"),
    (599, "Network Connect Timeout Error"),
];

pub fn build_context(context: &mut Context, configuration: Config) -> Result<(), String> {
    for (path, route) in configuration.routes.iter() {
        match route {
            &Route::Include(ref filename) =>
                try!(process_include(filename, path, &configuration, context)),
            &Route::Handler(ref route_handler) => {
                try!(process_handler(path, route_handler, &configuration, context));
            }
        }
    }

    process_notfound(&configuration, context);

    Ok(())
}

fn process_include(filename: &Path, root_path: &str, configuration: &Config, context: &mut Context)
    -> Result<(), String>
{
    let include_config = try!(config::read_config_include(filename));
    for (path, route) in include_config.iter() {
        let path = format!("{}/{}", root_path.trim_right_matches("/"),
                                    path.trim_left_matches("/"));

        match route {
            &Route::Include(ref filename) => try!(process_include(filename, &path, configuration, context)),
            &Route::Handler(ref route_handler) => {
                try!(process_handler(&path, route_handler, &configuration, context));
            }
        }
    }
    Ok(())
}

fn process_handler(path: &str,
                   route: &MethodHandler,
                   configuration: &Config,
                   context: &mut Context)
                   -> Result<(), String>
{
    for (method, handler_config) in route.handlers() {
        let status_code = handler_config.code;
        let status_text = handler_config.status.as_ref()
            .map(|x| x.clone())
            .unwrap_or(description(status_code).to_owned());

        let mut handler = Handler::new(status_code, status_text);
        handler.set_content(handler_config.content.clone());

        if handler_config.content.is_some() {
            let content_type = handler_config.contenttype.as_ref()
                .map(|x| &**x)
                .unwrap_or(configuration.settings.contenttype.as_ref())
                .as_bytes().iter().map(|b| *b).collect();

            handler.add_header("Content-Type".to_owned(), content_type);
        }

        process_headers(&mut handler,
                        &handler_config.headers,
                        &configuration.settings.headers,
                        configuration.settings.headers_replace);

        let path = if !path.ends_with("$") {
            format!("{}$", path)
        } else {
            path.to_owned()
        };
        try!(context.add_route(&path, method.to_owned(), handler)
            .map_err(|e| format!("Error adding route: {}", e)));
    }
    Ok(())
}

fn process_notfound(configuration: &Config, context: &mut Context) {
    match configuration.notfound {
        Some(ref not_found) => {
            let status_text = not_found.status
                .as_ref()
                .map(|x| x.clone())
                .unwrap_or(description(404).to_owned());

            let mut handler = Handler::new(404, status_text);
            handler.set_content(not_found.content.clone());

            if not_found.content.is_some() {
                let content_type = not_found.contenttype.as_ref()
                    .map(|x| &**x)
                    .unwrap_or(configuration.settings.contenttype.as_ref())
                    .as_bytes().iter().map(|b| *b).collect();

                handler.add_header("Content-Type".to_owned(), content_type);
            }

            for (k, v) in not_found.headers.iter() {
                handler.add_header(k.clone(), v.as_bytes().iter().map(|b| *b).collect());
            }

            let content_type = not_found.contenttype.clone().unwrap_or("application/json".to_owned());
            handler.add_header("Content-Type".to_owned(),
                               content_type.as_bytes().iter().map(|b| *b).collect());

            context.set_not_found_handler(handler);
        }
        None => {}
    }
}

fn description(status: u16) -> &'static str {
    for &(code, description) in STATUS_CODES.iter() {
        if status == code {
            return description
        }
    }
    "[Unknown HTTP Status]"
}

fn process_headers(handler: &mut Handler,
                   route_headers: &BTreeMap<String, String>,
                   settings_headers: &BTreeMap<String, String>,
                   replace: bool)
{
    if replace {
        let iter = settings_headers.iter().filter(|&(ref k, _)| {
            !route_headers.contains_key(k.to_owned())
        }).chain(route_headers.iter());
        for (key, val) in iter {
            let header = val.as_bytes().iter().map(|b| *b).collect();
            handler.add_header(key.clone(), header);
        }
    } else {
        for (key, val) in route_headers.iter().chain(settings_headers.iter()) {
            let header = val.as_bytes().iter().map(|b| *b).collect();
            handler.add_header(key.clone(), header);
        }
    };
}
<|endoftext|>