<commit_before>//!
//!  test.rs.rs
//!
//!  Created by Mitchell Nordine at 05:57PM on December 19, 2014.
//!
//!  Always remember to run high performance Rust code with the --release flag. `Synth`
//!

extern crate pitch_calc as pitch;
extern crate portaudio;
extern crate sample;
extern crate synth;

use portaudio as pa;
use pitch::{Letter, LetterOctave};
use synth::Synth;

// Currently supports i8, i32, f32.
pub type AudioSample = f32;
pub type Input = AudioSample;
pub type Output = AudioSample;

const CHANNELS: i32 = 2;
const FRAMES: u32 = 64;
const SAMPLE_HZ: f64 = 44_100.0;

fn main() {
    run().unwrap()
}

fn run() -> Result<(), pa::Error> {

    // Construct our fancy Synth!
    let mut synth = {
        use synth::{Point, Oscillator, oscillator, Envelope};

        // The following envelopes should create a downward pitching sine wave that gradually quietens.
        // Try messing around with the points and adding some of your own!
        let amp_env = Envelope::from(vec!(
            //         Time ,  Amp ,  Curve
            Point::new(0.0  ,  0.0 ,  0.0),
            Point::new(0.01 ,  1.0 ,  0.0),
            Point::new(0.45 ,  1.0 ,  0.0),
            Point::new(0.81 ,  0.8 ,  0.0),
            Point::new(1.0  ,  0.0 ,  0.0),
        ));
        let freq_env = Envelope::from(vec!(
            //         Time    , Freq   , Curve
            Point::new(0.0     , 0.0    , 0.0),
            Point::new(0.00136 , 1.0    , 0.0),
            Point::new(0.015   , 0.02   , 0.0),
            Point::new(0.045   , 0.005  , 0.0),
            Point::new(0.1     , 0.0022 , 0.0),
            Point::new(0.35    , 0.0011 , 0.0),
            Point::new(1.0     , 0.0    , 0.0),
        ));

        // Now we can create our oscillator from our envelopes.
        // There are also Sine, Noise, NoiseWalk, SawExp and Square waveforms.
        let oscillator = Oscillator::new(oscillator::waveform::Square, amp_env, freq_env, ());

        // Here we construct our Synth from our oscillator.
        Synth::retrigger(())
            .oscillator(oscillator) // Add as many different oscillators as desired.
            .duration(6000.0) // Milliseconds.
            .base_pitch(LetterOctave(Letter::C, 1).hz()) // Hz.
            .loop_points(0.49, 0.51) // Loop start and end points.
            .fade(500.0, 500.0) // Attack and Release in milliseconds.
            .num_voices(16) // By default Synth is monophonic but this gives it `n` voice polyphony.
            .volume(0.2)
            .detune(0.5)
            .spread(1.0)

        // Other methods include:
            // .loop_start(0.0)
            // .loop_end(1.0)
            // .attack(ms)
            // .release(ms)
            // .note_freq_generator(nfg)
            // .oscillators([oscA, oscB, oscC])
            // .volume(1.0)
    };

    // Construct a note for the synth to perform. Have a play around with the pitch and duration!
    let note = LetterOctave(Letter::C, 1);
    let note_velocity = 1.0;
    synth.note_on(note, note_velocity);

    // We'll call this to release the note after 4 seconds.
    let note_duration = 4.0;
    let mut is_note_off = false;

    // We'll use this to keep track of time and break from the loop after 6 seconds.
    let mut timer: f64 = 0.0;

    // This will be used to determine the delta time between calls to the callback.
    let mut prev_time = None;

    // The callback we'll use to pass to the Stream.
    let callback = move |pa::OutputStreamCallbackArgs { buffer, time, .. }| {
        let buffer: &mut [[f32; CHANNELS as usize]] = sample::slice::to_frame_slice_mut(buffer).unwrap();
        sample::slice::equilibrium(buffer);

        synth.fill_slice(buffer, SAMPLE_HZ as f64);
        if timer < 6.0 {

            let last_time = prev_time.unwrap_or(time.current);
            let dt = time.current - last_time;
            timer += dt;
            prev_time = Some(time.current);

            // Once the timer exceeds our note duration, send the note_off.
            if timer > note_duration {
                if !is_note_off {
                    synth.note_off(note);
                    is_note_off = true;
                }
            }
            pa::Continue
        } else {
            pa::Complete
        }
    };

    // Construct PortAudio and the stream.
    let pa = try!(pa::PortAudio::new());
    let settings = try!(pa.default_output_stream_settings::<f32>(CHANNELS, SAMPLE_HZ, FRAMES));
    let mut stream = try!(pa.open_non_blocking_stream(settings, callback));
    try!(stream.start());

    let ten_millis = std::time::Duration::from_millis(10);

    // Loop while the stream is active.
    while let Ok(true) = stream.is_active() {
        std::thread::sleep(std::time::Duration::from_millis(16));
    }

    Ok(())
}
<commit_msg>Removed unused var in example<commit_after>//!
//!  test.rs.rs
//!
//!  Created by Mitchell Nordine at 05:57PM on December 19, 2014.
//!
//!  Always remember to run high performance Rust code with the --release flag. `Synth`
//!

extern crate pitch_calc as pitch;
extern crate portaudio;
extern crate sample;
extern crate synth;

use portaudio as pa;
use pitch::{Letter, LetterOctave};
use synth::Synth;

// Currently supports i8, i32, f32.
pub type AudioSample = f32;
pub type Input = AudioSample;
pub type Output = AudioSample;

const CHANNELS: i32 = 2;
const FRAMES: u32 = 64;
const SAMPLE_HZ: f64 = 44_100.0;

fn main() {
    run().unwrap()
}

fn run() -> Result<(), pa::Error> {

    // Construct our fancy Synth!
    let mut synth = {
        use synth::{Point, Oscillator, oscillator, Envelope};

        // The following envelopes should create a downward pitching sine wave that gradually quietens.
        // Try messing around with the points and adding some of your own!
        let amp_env = Envelope::from(vec!(
            //         Time ,  Amp ,  Curve
            Point::new(0.0  ,  0.0 ,  0.0),
            Point::new(0.01 ,  1.0 ,  0.0),
            Point::new(0.45 ,  1.0 ,  0.0),
            Point::new(0.81 ,  0.8 ,  0.0),
            Point::new(1.0  ,  0.0 ,  0.0),
        ));
        let freq_env = Envelope::from(vec!(
            //         Time    , Freq   , Curve
            Point::new(0.0     , 0.0    , 0.0),
            Point::new(0.00136 , 1.0    , 0.0),
            Point::new(0.015   , 0.02   , 0.0),
            Point::new(0.045   , 0.005  , 0.0),
            Point::new(0.1     , 0.0022 , 0.0),
            Point::new(0.35    , 0.0011 , 0.0),
            Point::new(1.0     , 0.0    , 0.0),
        ));

        // Now we can create our oscillator from our envelopes.
        // There are also Sine, Noise, NoiseWalk, SawExp and Square waveforms.
        let oscillator = Oscillator::new(oscillator::waveform::Square, amp_env, freq_env, ());

        // Here we construct our Synth from our oscillator.
        Synth::retrigger(())
            .oscillator(oscillator) // Add as many different oscillators as desired.
            .duration(6000.0) // Milliseconds.
            .base_pitch(LetterOctave(Letter::C, 1).hz()) // Hz.
            .loop_points(0.49, 0.51) // Loop start and end points.
            .fade(500.0, 500.0) // Attack and Release in milliseconds.
            .num_voices(16) // By default Synth is monophonic but this gives it `n` voice polyphony.
            .volume(0.2)
            .detune(0.5)
            .spread(1.0)

        // Other methods include:
            // .loop_start(0.0)
            // .loop_end(1.0)
            // .attack(ms)
            // .release(ms)
            // .note_freq_generator(nfg)
            // .oscillators([oscA, oscB, oscC])
            // .volume(1.0)
    };

    // Construct a note for the synth to perform. Have a play around with the pitch and duration!
    let note = LetterOctave(Letter::C, 1);
    let note_velocity = 1.0;
    synth.note_on(note, note_velocity);

    // We'll call this to release the note after 4 seconds.
    let note_duration = 4.0;
    let mut is_note_off = false;

    // We'll use this to keep track of time and break from the loop after 6 seconds.
    let mut timer: f64 = 0.0;

    // This will be used to determine the delta time between calls to the callback.
    let mut prev_time = None;

    // The callback we'll use to pass to the Stream.
    let callback = move |pa::OutputStreamCallbackArgs { buffer, time, .. }| {
        let buffer: &mut [[f32; CHANNELS as usize]] = sample::slice::to_frame_slice_mut(buffer).unwrap();
        sample::slice::equilibrium(buffer);

        synth.fill_slice(buffer, SAMPLE_HZ as f64);
        if timer < 6.0 {

            let last_time = prev_time.unwrap_or(time.current);
            let dt = time.current - last_time;
            timer += dt;
            prev_time = Some(time.current);

            // Once the timer exceeds our note duration, send the note_off.
            if timer > note_duration {
                if !is_note_off {
                    synth.note_off(note);
                    is_note_off = true;
                }
            }
            pa::Continue
        } else {
            pa::Complete
        }
    };

    // Construct PortAudio and the stream.
    let pa = try!(pa::PortAudio::new());
    let settings = try!(pa.default_output_stream_settings::<f32>(CHANNELS, SAMPLE_HZ, FRAMES));
    let mut stream = try!(pa.open_non_blocking_stream(settings, callback));
    try!(stream.start());

    // Loop while the stream is active.
    while let Ok(true) = stream.is_active() {
        std::thread::sleep(std::time::Duration::from_millis(16));
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::mem;
use std::result::Result;
use math::variables::AbstVar;
use math::variables::new_const;
use math::relationships::Relationship;

pub struct Expression {
    left_hand_side: Vec<AbstVar>,
    relationship: Relationship,
    right_hand_side: Vec<AbstVar>,
}

impl Expression {
    pub fn new(l_h_s: Vec<AbstVar>, r: Relationship, r_h_s: Vec<AbstVar>) -> Expression {
        Expression {
            left_hand_side: l_h_s,
            relationship: r,
            right_hand_side: r_h_s,
        }
    }

    pub fn lhs(&self) -> &Vec<AbstVar> {
        &self.left_hand_side
    }

    pub fn rel(&self) -> &Relationship {
        &self.relationship
    }

    pub fn rhs(&self) -> &Vec<AbstVar> {
        &self.right_hand_side
    }

    pub fn set_rel(&mut self, new_rel: Relationship) {
        self.relationship = new_rel;
    }

    pub fn add_lhs(&mut self, to_add: AbstVar) {
        self.left_hand_side.push(to_add);
    }

    pub fn move_from_lhs_side(&mut self, index: usize, insert_at_start: bool) {
        let mut to_move = self.left_hand_side.remove(index);
        to_move.change_sign();
        if self.left_hand_side.is_empty() {
            self.left_hand_side.push(new_const("zero", 0.0));
        }
        insert_side(&mut self.right_hand_side, to_move, insert_at_start);
    }

    pub fn mul_both_sides(&mut self, by: f64) {
        mul_side(&mut self.left_hand_side, by);
        mul_side(&mut self.right_hand_side, by);

        // Change sign if required
        if by.is_sign_negative() && self.relationship != Relationship::EQ {
            if self.relationship == Relationship::GEQ {
                self.relationship = Relationship::LEQ;
            } else {
                self.relationship = Relationship::GEQ;
            }
        }
    }

    pub fn swap_sides(&mut self) -> Result<&str, &str> {
        if self.relationship == Relationship::EQ {
            mem::swap(&mut self.left_hand_side, &mut self.right_hand_side);
            Ok("Swapped!")
        } else {
            Err("Invalid state: relationship must be \"EQ\".")
        }
    }
}

fn insert_side(side: &mut Vec<AbstVar>, var: AbstVar, start: bool) {
    // Preserve order of basic followed by non basic
    if start {
        side.insert(0, var);
    } else {
        let mut insert_at = 0;
        while insert_at < side.len() {
            match &mut side[insert_at] {
                &mut AbstVar::SlackVar { .. } => break,
                _ => insert_at += 1,
            };
        }
        side.insert(insert_at, var);
    }
}

fn mul_side(side: &mut Vec<AbstVar>, by: f64) {
    for i in 0..side.len() {
        match &mut side[i] {
            &mut AbstVar::Variable { ref mut coefficient, .. } => *coefficient = *coefficient * by,
            &mut AbstVar::Constant { ref mut value, .. } => *value = *value * by,
            _ => panic!("Unexpected variant in this program logic."),
        };
    }
}
<commit_msg>Prevent 0.0 f64 to become negative.<commit_after>use std::mem;
use std::result::Result;
use math::variables::AbstVar;
use math::variables::new_const;
use math::relationships::Relationship;

pub struct Expression {
    left_hand_side: Vec<AbstVar>,
    relationship: Relationship,
    right_hand_side: Vec<AbstVar>,
}

impl Expression {
    pub fn new(l_h_s: Vec<AbstVar>, r: Relationship, r_h_s: Vec<AbstVar>) -> Expression {
        Expression {
            left_hand_side: l_h_s,
            relationship: r,
            right_hand_side: r_h_s,
        }
    }

    pub fn lhs(&self) -> &Vec<AbstVar> {
        &self.left_hand_side
    }

    pub fn rel(&self) -> &Relationship {
        &self.relationship
    }

    pub fn rhs(&self) -> &Vec<AbstVar> {
        &self.right_hand_side
    }

    pub fn set_rel(&mut self, new_rel: Relationship) {
        self.relationship = new_rel;
    }

    pub fn add_lhs(&mut self, to_add: AbstVar) {
        self.left_hand_side.push(to_add);
    }

    pub fn move_from_lhs_side(&mut self, index: usize, insert_at_start: bool) {
        let mut to_move = self.left_hand_side.remove(index);
        to_move.change_sign();
        if self.left_hand_side.is_empty() {
            self.left_hand_side.push(new_const("zero", 0.0));
        }
        insert_side(&mut self.right_hand_side, to_move, insert_at_start);
    }

    pub fn mul_both_sides(&mut self, by: f64) {
        mul_side(&mut self.left_hand_side, by);
        mul_side(&mut self.right_hand_side, by);

        // Change sign if required
        if by.is_sign_negative() && self.relationship != Relationship::EQ {
            if self.relationship == Relationship::GEQ {
                self.relationship = Relationship::LEQ;
            } else {
                self.relationship = Relationship::GEQ;
            }
        }
    }

    pub fn swap_sides(&mut self) -> Result<&str, &str> {
        if self.relationship == Relationship::EQ {
            mem::swap(&mut self.left_hand_side, &mut self.right_hand_side);
            Ok("Swapped!")
        } else {
            Err("Invalid state: relationship must be \"EQ\".")
        }
    }
}

fn insert_side(side: &mut Vec<AbstVar>, var: AbstVar, start: bool) {
    // Preserve order of basic followed by non basic
    if start {
        side.insert(0, var);
    } else {
        let mut insert_at = 0;
        while insert_at < side.len() {
            match &mut side[insert_at] {
                &mut AbstVar::SlackVar { .. } => break,
                _ => insert_at += 1,
            };
        }
        side.insert(insert_at, var);
    }
}

fn mul_side(side: &mut Vec<AbstVar>, by: f64) {
    for i in 0..side.len() {
        match &mut side[i] {
            &mut AbstVar::Variable { ref mut coefficient, .. } => {
                if *coefficient != 0.0 {
                    *coefficient = *coefficient * by;
                }
            }
            &mut AbstVar::Constant { ref mut value, .. } => {
                if *value != 0.0 {
                    *value = *value * by;
                }
            }
            _ => panic!("Unexpected variant in this program logic."),
        };
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove unsafe blocks in trie<commit_after><|endoftext|>


<commit_before>pub trait Color : Clone + Copy + PartialEq<Self> {
    fn from_byte(b: u8) -> Self;
    fn empty_color() -> Self;
    fn ojama_color() -> Self;
    fn wall_color() -> Self;

    fn all_colors() -> &'static [Self];
    fn all_normal_colors() -> &'static [Self];

    fn as_usize(&self) -> usize;
    fn to_char(&self) -> char;
    fn is_normal_color(&self) -> bool;

    fn as_str(&self) -> &'static str;
    // 2 byte string
    fn as_str_wide(&self) -> &'static str;
    // 2 byte string (with color escape sequence)
    fn as_colored_str_wide(&self) -> &'static str;
}
<commit_msg>Color should implement std::fmt::Display<commit_after>use std::fmt::Display;

pub trait Color : Clone + Copy + PartialEq<Self> + Display {
    fn from_byte(b: u8) -> Self;
    fn empty_color() -> Self;
    fn ojama_color() -> Self;
    fn wall_color() -> Self;

    fn all_colors() -> &'static [Self];
    fn all_normal_colors() -> &'static [Self];

    fn as_usize(&self) -> usize;
    fn to_char(&self) -> char;
    fn is_normal_color(&self) -> bool;

    fn as_str(&self) -> &'static str;
    // 2 byte string
    fn as_str_wide(&self) -> &'static str;
    // 2 byte string (with color escape sequence)
    fn as_colored_str_wide(&self) -> &'static str;
}
<|endoftext|>


<commit_before>#[derive(RustcDecodable, Debug)]
pub struct GcmResponse {
  pub message_id: Option<u64>,
  pub error: Option<String>,
  pub multicast_id: Option<u64>,
  pub success: Option<u64>,
  pub failure: Option<u64>,
  pub canonical_ids: Option<u64>,
  pub results: Option<Vec<MessageResult>>
}

#[derive(RustcDecodable, Debug)]
pub struct MessageResult {
  pub message_id: Option<u64>,
  pub registration_id: Option<u64>,
  pub error: Option<String>
}

#[derive(PartialEq, Debug)]
pub enum GcmError {
  Unauthorized, InvalidMessage(String), ServerError
}<commit_msg>fixed response::GcmResponse , multicast_id can actually be be negative ("-1"), so it has to be i64 instead of u64<commit_after>#[derive(RustcDecodable, Debug)]
pub struct GcmResponse {
  pub message_id: Option<u64>,
  pub error: Option<String>,
  pub multicast_id: Option<i64>,
  pub success: Option<u64>,
  pub failure: Option<u64>,
  pub canonical_ids: Option<u64>,
  pub results: Option<Vec<MessageResult>>
}

#[derive(RustcDecodable, Debug)]
pub struct MessageResult {
  pub message_id: Option<u64>,
  pub registration_id: Option<u64>,
  pub error: Option<String>
}

#[derive(PartialEq, Debug)]
pub enum GcmError {
  Unauthorized, InvalidMessage(String), ServerError
}
<|endoftext|>


<commit_before>/*================================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*================================================================================================*/

use Mathf;

use std::ops::*;
use std::cmp::PartialEq;

/*================================================================================================*/
/*------STRUCTS-----------------------------------------------------------------------------------*/
/*================================================================================================*/

/// The Vec2f struct
///
/// It is used mainly for 2D releated mathematics (e.g. texture and UV coordinates).
/// 32-bit floats are used for the values.
pub struct Vec2f {

    x : f32,
    y : f32
}

/*================================================================================================*/
/*------PUBLIC FUNCTIONS--------------------------------------------------------------------------*/
/*================================================================================================*/

impl Vec2f {

    /// Formats the vector as a string.
    ///
    /// # Examples
    /// ```
    /// let vec = Vec2f {x : 10.0, y : 5.0};
    /// println! ("Vector = {}", vec.to_string ());
    /// ```
    /// ```c
    /// Output : Vector = 10.0, 5.0
    pub fn to_string (&self) -> String {

        format! ("{}, {}", self.x, self.y)
    }

/*================================================================================================*/
/*------PUBLIC STATIC FUNCTIONS-------------------------------------------------------------------*/
/*================================================================================================*/

    /// Creates a vector with a default value of zero.
    ///
    /// # Examples
    /// ```
    /// let vec = Vec2f::new ();
    pub fn new () -> Vec2f {

        Vec2f {x : 0.0,
               y : 0.0}
    }
}

/*================================================================================================*/
/*------OPERATOR OVERLOADS------------------------------------------------------------------------*/
/*================================================================================================*/

impl Add for Vec2f {

    type Output = Vec2f;

    // Addition operator (vector)
    fn add (self, rhs : Vec2f) -> Vec2f {

        Vec2f {x : self.x + rhs.x,
               y : self.y + rhs.y}
    }
}

/*================================================================================================*/

impl Add <f32> for Vec2f {

    type Output = Vec2f;

    // Addition operator (f32)
    fn add (self, rhs : f32) -> Vec2f {

        Vec2f {x : self.x + rhs,
               y : self.y + rhs}
    }
}

/*================================================================================================*/

impl AddAssign for Vec2f {

    // Addition assignment operator (vector)
    fn add_assign (&mut self, rhs : Vec2f) {

        self.x += rhs.x;
        self.y += rhs.y;
    }
}

/*================================================================================================*/

impl AddAssign <f32> for Vec2f {

    // Addition assignment operator (f32)
    fn add_assign (&mut self, rhs : f32) {

        self.x += rhs;
        self.y += rhs;
    }
}
<commit_msg>Added sub, div, mul, eq, ne, and index operators to Vec2f<commit_after>/*================================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*================================================================================================*/

use Mathf;

use std::ops::*;
use std::cmp::PartialEq;

/*================================================================================================*/
/*------STRUCTS-----------------------------------------------------------------------------------*/
/*================================================================================================*/

/// The Vec2f struct
///
/// It is used mainly for 2D releated mathematics (e.g. texture and UV coordinates).
/// 32-bit floats are used for the values.
pub struct Vec2f {

    x : f32,
    y : f32
}

/*================================================================================================*/
/*------PUBLIC FUNCTIONS--------------------------------------------------------------------------*/
/*================================================================================================*/

impl Vec2f {

    /// Formats the vector as a string.
    ///
    /// # Examples
    /// ```
    /// let vec = Vec2f {x : 10.0, y : 5.0};
    /// println! ("Vector = {}", vec.to_string ());
    /// ```
    /// ```c
    /// Output : Vector = 10.0, 5.0
    pub fn to_string (&self) -> String {

        format! ("{}, {}", self.x, self.y)
    }

/*================================================================================================*/
/*------PUBLIC STATIC FUNCTIONS-------------------------------------------------------------------*/
/*================================================================================================*/

    /// Creates a vector with a default value of zero.
    ///
    /// # Examples
    /// ```
    /// let vec = Vec2f::new ();
    pub fn new () -> Vec2f {

        Vec2f {x : 0.0,
               y : 0.0}
    }
}

/*================================================================================================*/
/*------OPERATOR OVERLOADS------------------------------------------------------------------------*/
/*================================================================================================*/

impl Add for Vec2f {

    type Output = Vec2f;

    // Addition operator (vector)
    fn add (self, rhs : Vec2f) -> Vec2f {

        Vec2f {x : self.x + rhs.x,
               y : self.y + rhs.y}
    }
}

/*================================================================================================*/

impl Add <f32> for Vec2f {

    type Output = Vec2f;

    // Addition operator (f32)
    fn add (self, rhs : f32) -> Vec2f {

        Vec2f {x : self.x + rhs,
               y : self.y + rhs}
    }
}

/*================================================================================================*/

impl AddAssign for Vec2f {

    // Addition assignment operator (vector)
    fn add_assign (&mut self, rhs : Vec2f) {

        self.x += rhs.x;
        self.y += rhs.y;
    }
}

/*================================================================================================*/

impl AddAssign <f32> for Vec2f {

    // Addition assignment operator (f32)
    fn add_assign (&mut self, rhs : f32) {

        self.x += rhs;
        self.y += rhs;
    }
}

/*================================================================================================*/

impl Sub for Vec2f {

    type Output = Vec2f;

    // Subtraction operator (vector)
    fn sub (self, rhs : Vec2f) -> Vec2f {

        Vec2f {x : self.x - rhs.x,
               y : self.y - rhs.y}
    }
}

/*================================================================================================*/

impl Sub <f32> for Vec2f {

    type Output = Vec2f;

    // Subtraction operator (f32)
    fn sub (self, rhs : f32) -> Vec2f {

        Vec2f {x : self.x - rhs,
               y : self.y - rhs}
    }
}

/*================================================================================================*/

impl SubAssign for Vec2f {

    // Subtraction assignment operator (vector)
    fn sub_assign (&mut self, rhs : Vec2f) {

        self.x -= rhs.x;
        self.y -= rhs.y;
    }
}

/*================================================================================================*/

impl SubAssign <f32> for Vec2f {

    // Subtraction assignment operator (f32)
    fn sub_assign (&mut self, rhs : f32) {

        self.x += rhs;
        self.y += rhs;
    }
}

/*================================================================================================*/

impl Neg for Vec2f {

    type Output = Vec2f;

    // Unary minus operator
    fn neg (self) -> Vec2f {

        Vec2f {x : -self.x,
               y : -self.y}
    }
}

/*================================================================================================*/

impl Mul for Vec2f {

    type Output = Vec2f;

    // Multiplication operator (vector)
    fn mul (self, rhs : Vec2f) -> Vec2f {

        Vec2f {x : self.x * rhs.x,
               y : self.y * rhs.y}
    }
}

/*================================================================================================*/

impl Mul <f32> for Vec2f {

    type Output = Vec2f;

    // Multiplication operator (f32)
    fn mul (self, rhs : f32) -> Vec2f {

        Vec2f {x : self.x * rhs,
               y : self.y * rhs}
    }
}

/*================================================================================================*/

impl MulAssign for Vec2f {

    // Multiplication assignment operator (vector)
    fn mul_assign (&mut self, rhs : Vec2f) {

        self.x *= rhs.x;
        self.y *= rhs.y;
    }
}

/*================================================================================================*/

impl MulAssign <f32> for Vec2f {

    // Multiplication assignment operator (f32)
    fn mul_assign (&mut self, rhs : f32) {

        self.x *= rhs;
        self.y *= rhs;
    }
}

/*================================================================================================*/

impl Div for Vec2f {

    type Output = Vec2f;

    // Division operator (vector)
    fn div (self, rhs : Vec2f) -> Vec2f {

        Vec2f {x : self.x / rhs.x,
               y : self.y / rhs.y}
    }
}

/*================================================================================================*/

impl Div <f32> for Vec2f {

    type Output = Vec2f;

    // Division operator (f32)
    fn div (self, rhs : f32) -> Vec2f {

        Vec2f {x : self.x / rhs,
               y : self.y / rhs}
    }
}

/*================================================================================================*/

impl DivAssign for Vec2f {

    // Division assignment operator (vector)
    fn div_assign (&mut self, rhs : Vec2f) {

        self.x /= rhs.x;
        self.y /= rhs.y;
    }
}

/*================================================================================================*/

impl DivAssign <f32> for Vec2f {

    // Division assignment operator (f32)
    fn div_assign (&mut self, rhs : f32) {

        self.x /= rhs;
        self.y /= rhs;
    }
}

/*================================================================================================*/

impl PartialEq for Vec2f {

    // Equal to operator
    fn eq (&self, rhs : &Vec2f) -> bool {

        self.x == rhs.x &&
        self.y == rhs.y
    }

/*================================================================================================*/

    // Not equal to operator
    fn ne (&self, rhs : &Vec2f) -> bool {

        self.x != rhs.x ||
        self.y != rhs.y
    }
}

/*================================================================================================*/

impl Index <u8> for Vec2f {

    type Output = f32;

    // Index operator (immutable)
    fn index (&self, index : u8) -> &f32 {

        match index {

            0 => &self.x,
            1 => &self.y,
            _ => unreachable! ("Index out of range for Vec2f")
        }
    }
}

/*================================================================================================*/

impl IndexMut <u8> for Vec2f {

    // Index operator (mutable)
    fn index_mut (&mut self, index : u8) -> &mut f32 {

        match index {

            0 => &mut self.x,
            1 => &mut self.y,
            _ => unreachable! ("Index out of range for Vec2f")
        }
    }
}
<|endoftext|>


<commit_before>use std::convert::From;
use std::iter::{FromIterator, IntoIterator, Iterator};

use binding::array;
use types::{Value, ValueType};

use {AnyObject, RString, Object, VerifiedObject};

/// `Array`
#[derive(Debug, PartialEq)]
pub struct Array {
    value: Value,
}

impl Array {
    /// Creates a new instance of empty `Array`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, VM};
    /// # VM::init();
    ///
    /// Array::new();
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// []
    /// ```
    pub fn new() -> Self {
        Self::from(array::new())
    }

    /// Retrieves the length of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.length(), 1);
    ///
    /// array.push(Fixnum::new(2));
    ///
    /// assert_eq!(array.length(), 2);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array.length == 1
    ///
    /// array << 2
    /// array.length == 2
    /// ```
    pub fn length(&self) -> usize {
        array::len(self.value()) as usize
    }

    /// Retrieves an `AnyObject` from the element at `index` position.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    ///
    /// array[0] == 1
    /// ```
    pub fn at(&self, index: i64) -> AnyObject {
        let result = array::entry(self.value(), index);

        AnyObject::from(result)
    }

    /// Joins all elements of `Array` to Ruby `String`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, RString, VM};
    /// # VM::init();
    ///
    /// let array = Array::new()
    ///     .push(RString::new("Hello"))
    ///     .push(RString::new("World!"));
    ///
    /// let joined_string = array.join(RString::new(", ")).to_string();
    ///
    /// assert_eq!(joined_string, "Hello, World!".to_string());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = ['Hello', 'World!']
    ///
    /// joined_string = array.join(', ')
    ///
    /// joined_string == 'Hello, World!'
    /// ```
    pub fn join(&self, separator: RString) -> RString {
        let result = array::join(self.value(), separator.value());

        RString::from(result)
    }

    /// Pushes an object to `Array`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new();
    ///
    /// array.push(Fixnum::new(1));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = []
    /// array << 1
    ///
    /// array[0] == 1
    /// ```
    pub fn push<T: Object>(&mut self, item: T) -> Self {
        let result = array::push(self.value(), item.value());

        Array::from(result)
    }

    /// Stores an object at `index` position.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// array.store(0, Fixnum::new(2));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array[0] = 2
    ///
    /// array[0] == 2
    /// ```
    pub fn store<T: Object>(&mut self, index: i64, item: T) -> AnyObject {
        let result = array::store(self.value(), index, item.value());

        AnyObject::from(result)
    }

    /// Removes and returns the last element of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.pop().try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    ///
    /// array.pop == 1
    /// ```
    pub fn pop(&mut self) -> AnyObject {
        let result = array::pop(self.value());

        AnyObject::from(result)
    }

    /// Inserts `item` at the beggining of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// array.unshift(Fixnum::new(2));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array.unshift(2)
    ///
    /// array[0] == 2
    /// ```
    pub fn unshift<T: Object>(&mut self, item: T) -> AnyObject {
        let result = array::unshift(self.value(), item.value());

        AnyObject::from(result)
    }

    /// Removes the first item of the array and returns it.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// let item = array.shift();
    ///
    /// assert_eq!(item.try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    ///
    /// item = array.shift
    ///
    /// item == 1
    /// array[0] == 2
    /// ```
    pub fn shift(&mut self) -> AnyObject {
        let result = array::shift(self.value());

        AnyObject::from(result)
    }

    /// Creates a copy of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    /// let copy = array.dup();
    ///
    /// assert_eq!(array.at(0), copy.at(0));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// copy = array.dup
    ///
    /// array[0] == copy[0]
    /// ```
    pub fn dup(&mut self) -> Array {
        let result = array::dup(self.value());

        Array::from(result)
    }

    /// Creates a string representation of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// assert_eq!(array.to_s().to_string(), "[1, 2]".to_string());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    ///
    /// array.to_s == "[1, 2]"
    /// ```
    pub fn to_s(&mut self) -> RString {
        let result = array::to_s(self.value());

        RString::from(result)
    }

    /// Returns a new array containing array's elements in reverse order.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// array.reverse();
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    /// array.reverse!
    ///
    /// array[0] == 2
    /// array[1] == 1
    /// ```
    pub fn reverse(&mut self) -> Array {
        let result = array::reverse(self.value());
        Array::from(result)
    }

    /// Appends the elements of `other` array to `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    /// let other = Array::new().push(Fixnum::new(2));
    ///
    /// array.concat(other);
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// other = [2]
    ///
    /// array.concat(other)
    ///
    /// array[0] == 1
    /// array[1] == 2
    /// ```
    pub fn concat(&mut self, other: Array) -> Array {
        let result = array::concat(self.value(), other.value());

        Array::from(result)
    }

    /// Returns a new array created by sorting `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(2)).push(Fixnum::new(1));
    ///
    /// let sorted_array = array.sort();
    ///
    /// assert_eq!(sorted_array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(sorted_array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [2, 1]
    ///
    /// sorted_array = array.sort
    ///
    /// sorted_array[0] == 1
    /// sorted_array[1] == 2
    /// ```
    pub fn sort(&mut self) -> Array {
        let result = array::sort(self.value());
        Array::from(result)
    }

    /// Sorts the array in place.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(2)).push(Fixnum::new(1));
    ///
    /// array.sort_bang();
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [2, 1]
    ///
    /// array.sort!
    ///
    /// array[0] == 1
    /// array[1] == 2
    /// ```
    pub fn sort_bang(&mut self) -> Array {
        let result = array::sort_bang(self.value());
        Array::from(result)
    }
}

impl From<Value> for Array {
    fn from(value: Value) -> Self {
        Array { value: value }
    }
}

impl Object for Array {
    #[inline]
    fn value(&self) -> Value {
        self.value
    }
}

impl VerifiedObject for Array {
    fn is_correct_type<T: Object>(object: &T) -> bool {
        object.value().ty() == ValueType::Array
    }

    fn error_message() -> &'static str {
        "Error converting to Boolean"
    }
}

pub struct ArrayIterator {
    array: Array,
    current_index: i64,
}

impl ArrayIterator {
    fn new(array: Array) -> ArrayIterator {
        ArrayIterator {
            array: array,
            current_index: 0,
        }
    }
}

impl Iterator for ArrayIterator {
    type Item = AnyObject;

    fn next(&mut self) -> Option<AnyObject> {
        let item = if (self.current_index as usize) < self.len() {
            Some(self.array.at(self.current_index))
        } else {
            None
        };

        self.current_index += 1;

        item
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let total = self.len() as usize;
        (total, Some(total))
    }
}

impl ExactSizeIterator for ArrayIterator {
    fn len(&self) -> usize {
        self.array.length() as usize
    }
}

/// Allows Arrays to be iterable in Rust.
///
/// # Examples
///
/// ```
/// use ruru::{Array, Fixnum, Object, VM};
/// # VM::init();
///
/// let mut array = Array::new()
///     .push(Fixnum::new(1))
///     .push(Fixnum::new(2))
///     .push(Fixnum::new(3));
///
/// let mut sum: i64 = 0;
///
/// for item in array.into_iter() {
///     sum += item.try_convert_to::<Fixnum>().unwrap().to_i64();
/// }
///
/// assert_eq!(sum, 6);
/// ```
impl IntoIterator for Array {
    type Item = AnyObject;
    type IntoIter = ArrayIterator;

    fn into_iter(self) -> Self::IntoIter {
        ArrayIterator::new(self)
    }
}

/// Converts an iterator into `Array`.
///
/// # Examples
///
/// ```
/// use ruru::{Array, Fixnum, Object, VM};
/// # VM::init();
///
/// let array: Array = (1..6)
///     .map(|num| num * 2)
///     .map(|num| Fixnum::new(num).to_any_object())
///     .collect();
///
/// assert_eq!(array.length(), 5);
///
/// for i in 0..5 {
///     let expected_number = (i + 1) * 2;
///
///     assert_eq!(array.at(i).try_convert_to::<Fixnum>().unwrap().to_i64(), expected_number);
/// }
/// ```
impl FromIterator<AnyObject> for Array {
    fn from_iter<I: IntoIterator<Item = AnyObject>>(iter: I) -> Self {
        let mut array = Array::new();

        for i in iter {
            array.push(i);
        }

        array
    }
}
<commit_msg>Change Array::dup() to receive &self<commit_after>use std::convert::From;
use std::iter::{FromIterator, IntoIterator, Iterator};

use binding::array;
use types::{Value, ValueType};

use {AnyObject, RString, Object, VerifiedObject};

/// `Array`
#[derive(Debug, PartialEq)]
pub struct Array {
    value: Value,
}

impl Array {
    /// Creates a new instance of empty `Array`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, VM};
    /// # VM::init();
    ///
    /// Array::new();
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// []
    /// ```
    pub fn new() -> Self {
        Self::from(array::new())
    }

    /// Retrieves the length of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.length(), 1);
    ///
    /// array.push(Fixnum::new(2));
    ///
    /// assert_eq!(array.length(), 2);
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array.length == 1
    ///
    /// array << 2
    /// array.length == 2
    /// ```
    pub fn length(&self) -> usize {
        array::len(self.value()) as usize
    }

    /// Retrieves an `AnyObject` from the element at `index` position.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    ///
    /// array[0] == 1
    /// ```
    pub fn at(&self, index: i64) -> AnyObject {
        let result = array::entry(self.value(), index);

        AnyObject::from(result)
    }

    /// Joins all elements of `Array` to Ruby `String`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, RString, VM};
    /// # VM::init();
    ///
    /// let array = Array::new()
    ///     .push(RString::new("Hello"))
    ///     .push(RString::new("World!"));
    ///
    /// let joined_string = array.join(RString::new(", ")).to_string();
    ///
    /// assert_eq!(joined_string, "Hello, World!".to_string());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = ['Hello', 'World!']
    ///
    /// joined_string = array.join(', ')
    ///
    /// joined_string == 'Hello, World!'
    /// ```
    pub fn join(&self, separator: RString) -> RString {
        let result = array::join(self.value(), separator.value());

        RString::from(result)
    }

    /// Pushes an object to `Array`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new();
    ///
    /// array.push(Fixnum::new(1));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = []
    /// array << 1
    ///
    /// array[0] == 1
    /// ```
    pub fn push<T: Object>(&mut self, item: T) -> Self {
        let result = array::push(self.value(), item.value());

        Array::from(result)
    }

    /// Stores an object at `index` position.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// array.store(0, Fixnum::new(2));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array[0] = 2
    ///
    /// array[0] == 2
    /// ```
    pub fn store<T: Object>(&mut self, index: i64, item: T) -> AnyObject {
        let result = array::store(self.value(), index, item.value());

        AnyObject::from(result)
    }

    /// Removes and returns the last element of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// assert_eq!(array.pop().try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    ///
    /// array.pop == 1
    /// ```
    pub fn pop(&mut self) -> AnyObject {
        let result = array::pop(self.value());

        AnyObject::from(result)
    }

    /// Inserts `item` at the beggining of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    ///
    /// array.unshift(Fixnum::new(2));
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// array.unshift(2)
    ///
    /// array[0] == 2
    /// ```
    pub fn unshift<T: Object>(&mut self, item: T) -> AnyObject {
        let result = array::unshift(self.value(), item.value());

        AnyObject::from(result)
    }

    /// Removes the first item of the array and returns it.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// let item = array.shift();
    ///
    /// assert_eq!(item.try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    ///
    /// item = array.shift
    ///
    /// item == 1
    /// array[0] == 2
    /// ```
    pub fn shift(&mut self) -> AnyObject {
        let result = array::shift(self.value());

        AnyObject::from(result)
    }

    /// Creates a copy of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let array = Array::new().push(Fixnum::new(1));
    /// let copy = array.dup();
    ///
    /// assert_eq!(array.at(0), copy.at(0));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// copy = array.dup
    ///
    /// array[0] == copy[0]
    /// ```
    pub fn dup(&self) -> Array {
        let result = array::dup(self.value());

        Array::from(result)
    }

    /// Creates a string representation of the array.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// assert_eq!(array.to_s().to_string(), "[1, 2]".to_string());
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    ///
    /// array.to_s == "[1, 2]"
    /// ```
    pub fn to_s(&mut self) -> RString {
        let result = array::to_s(self.value());

        RString::from(result)
    }

    /// Returns a new array containing array's elements in reverse order.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1)).push(Fixnum::new(2));
    ///
    /// array.reverse();
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1, 2]
    /// array.reverse!
    ///
    /// array[0] == 2
    /// array[1] == 1
    /// ```
    pub fn reverse(&mut self) -> Array {
        let result = array::reverse(self.value());
        Array::from(result)
    }

    /// Appends the elements of `other` array to `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(1));
    /// let other = Array::new().push(Fixnum::new(2));
    ///
    /// array.concat(other);
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [1]
    /// other = [2]
    ///
    /// array.concat(other)
    ///
    /// array[0] == 1
    /// array[1] == 2
    /// ```
    pub fn concat(&mut self, other: Array) -> Array {
        let result = array::concat(self.value(), other.value());

        Array::from(result)
    }

    /// Returns a new array created by sorting `self`.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(2)).push(Fixnum::new(1));
    ///
    /// let sorted_array = array.sort();
    ///
    /// assert_eq!(sorted_array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(sorted_array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [2, 1]
    ///
    /// sorted_array = array.sort
    ///
    /// sorted_array[0] == 1
    /// sorted_array[1] == 2
    /// ```
    pub fn sort(&mut self) -> Array {
        let result = array::sort(self.value());
        Array::from(result)
    }

    /// Sorts the array in place.
    ///
    /// # Examples
    ///
    /// ```
    /// use ruru::{Array, Fixnum, Object, VM};
    /// # VM::init();
    ///
    /// let mut array = Array::new().push(Fixnum::new(2)).push(Fixnum::new(1));
    ///
    /// array.sort_bang();
    ///
    /// assert_eq!(array.at(0).try_convert_to::<Fixnum>(), Ok(Fixnum::new(1)));
    /// assert_eq!(array.at(1).try_convert_to::<Fixnum>(), Ok(Fixnum::new(2)));
    /// ```
    ///
    /// Ruby:
    ///
    /// ```ruby
    /// array = [2, 1]
    ///
    /// array.sort!
    ///
    /// array[0] == 1
    /// array[1] == 2
    /// ```
    pub fn sort_bang(&mut self) -> Array {
        let result = array::sort_bang(self.value());
        Array::from(result)
    }
}

impl From<Value> for Array {
    fn from(value: Value) -> Self {
        Array { value: value }
    }
}

impl Object for Array {
    #[inline]
    fn value(&self) -> Value {
        self.value
    }
}

impl VerifiedObject for Array {
    fn is_correct_type<T: Object>(object: &T) -> bool {
        object.value().ty() == ValueType::Array
    }

    fn error_message() -> &'static str {
        "Error converting to Boolean"
    }
}

pub struct ArrayIterator {
    array: Array,
    current_index: i64,
}

impl ArrayIterator {
    fn new(array: Array) -> ArrayIterator {
        ArrayIterator {
            array: array,
            current_index: 0,
        }
    }
}

impl Iterator for ArrayIterator {
    type Item = AnyObject;

    fn next(&mut self) -> Option<AnyObject> {
        let item = if (self.current_index as usize) < self.len() {
            Some(self.array.at(self.current_index))
        } else {
            None
        };

        self.current_index += 1;

        item
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let total = self.len() as usize;
        (total, Some(total))
    }
}

impl ExactSizeIterator for ArrayIterator {
    fn len(&self) -> usize {
        self.array.length() as usize
    }
}

/// Allows Arrays to be iterable in Rust.
///
/// # Examples
///
/// ```
/// use ruru::{Array, Fixnum, Object, VM};
/// # VM::init();
///
/// let mut array = Array::new()
///     .push(Fixnum::new(1))
///     .push(Fixnum::new(2))
///     .push(Fixnum::new(3));
///
/// let mut sum: i64 = 0;
///
/// for item in array.into_iter() {
///     sum += item.try_convert_to::<Fixnum>().unwrap().to_i64();
/// }
///
/// assert_eq!(sum, 6);
/// ```
impl IntoIterator for Array {
    type Item = AnyObject;
    type IntoIter = ArrayIterator;

    fn into_iter(self) -> Self::IntoIter {
        ArrayIterator::new(self)
    }
}

/// Converts an iterator into `Array`.
///
/// # Examples
///
/// ```
/// use ruru::{Array, Fixnum, Object, VM};
/// # VM::init();
///
/// let array: Array = (1..6)
///     .map(|num| num * 2)
///     .map(|num| Fixnum::new(num).to_any_object())
///     .collect();
///
/// assert_eq!(array.length(), 5);
///
/// for i in 0..5 {
///     let expected_number = (i + 1) * 2;
///
///     assert_eq!(array.at(i).try_convert_to::<Fixnum>().unwrap().to_i64(), expected_number);
/// }
/// ```
impl FromIterator<AnyObject> for Array {
    fn from_iter<I: IntoIterator<Item = AnyObject>>(iter: I) -> Self {
        let mut array = Array::new();

        for i in iter {
            array.push(i);
        }

        array
    }
}
<|endoftext|>


<commit_before>/*
Copyright ⓒ 2015-2017 cargo-script contributors.

Licensed under the MIT license (see LICENSE or <http://opensource.org
/licenses/MIT>) or the Apache License, Version 2.0 (see LICENSE of
<http://www.apache.org/licenses/LICENSE-2.0>), at your option. All
files in the project carrying such notice may not be copied, modified,
or distributed except according to those terms.
*/
/*!
This module just contains any big string literals I don't want cluttering up the rest of the code.
*/

/**
The message output when the user invokes `cargo script` with no further arguments.  We need to do this ourselves because `clap` doesn't provide any way to generate this message manually.
*/
pub const NO_ARGS_MESSAGE: &'static str = "\
The following required arguments were not supplied:
\t'<script>'

USAGE:
\tcargo script [FLAGS OPTIONS] [--] <script> <args>...

For more information try --help";

/*
What follows are the templates used to wrap script input.  The input provided by the user is inserted in place of `%b`.  *Proper* templates of some kind would be nice, but damnit, I'm lazy.
*/

/// The template used for script file inputs.
pub const FILE_TEMPLATE: &'static str = r#"%b"#;

/// The template used for `--expr` input.
pub const EXPR_TEMPLATE: &'static str = r#"
%p
fn main() {
    if let Err(e) = try_main() {
        println!("ERROR: script panicked: {:?}", e);
    }
}

fn try_main() -> Result<(), Box<std::error::Error>> {
    match {%b} {
        __cargo_script_expr => println!("{:?}", __cargo_script_expr)
    }
    Ok(())
}
"#;

/*
Regarding the loop templates: what I *want* is for the result of the closure to be printed to standard output *only* if it's not `()`.

* TODO: Just use TypeId, dumbass.
* TODO: Merge the `LOOP_*` templates so there isn't duplicated code.  It's icky.
*/

/// The template used for `--loop` input, assuming no `--count` flag is also given.
pub const LOOP_TEMPLATE: &'static str = r#"
%p
use std::any::Any;
use std::io::prelude::*;

fn main() {
    let mut closure = enforce_closure(
{%b}
    );
    let mut line_buffer = String::new();
    let mut stdin = std::io::stdin();
    loop {
        line_buffer.clear();
        let read_res = stdin.read_line(&mut line_buffer).unwrap_or(0);
        if read_res == 0 { break }
        let output = closure(&line_buffer);

        let display = {
            let output_any: &Any = &output;
            !output_any.is::<()>()
        };

        if display {
            println!("{:?}", output);
        }
    }
}

fn enforce_closure<F, T>(closure: F) -> F
where F: FnMut(&str) -> T, T: 'static {
    closure
}
"#;

/// The template used for `--count --loop` input.
pub const LOOP_COUNT_TEMPLATE: &'static str = r#"
%p
use std::any::Any;
use std::io::prelude::*;

fn main() {
    let mut closure = enforce_closure(
{%b}
    );
    let mut line_buffer = String::new();
    let mut stdin = std::io::stdin();
    let mut count = 0;
    loop {
        line_buffer.clear();
        let read_res = stdin.read_line(&mut line_buffer).unwrap_or(0);
        if read_res == 0 { break }
        count += 1;
        let output = closure(&line_buffer, count);

        let display = {
            let output_any: &Any = &output;
            !output_any.is::<()>()
        };

        if display {
            println!("{:?}", output);
        }
    }
}

fn enforce_closure<F, T>(closure: F) -> F
where F: FnMut(&str, usize) -> T, T: 'static {
    closure
}
"#;

/**
The default manifest used for packages.  `%n` is replaced with the "safe name" of the input, which *should* be safe to use as a file name.
*/
pub const DEFAULT_MANIFEST: &'static str = r#"
[package]
name = "%n"
version = "0.1.0"
authors = ["Anonymous"]

[[bin]]
name = "%n"
path = "%f.rs"
"#;

/**
The name of the package metadata file.
*/
pub const METADATA_FILE: &'static str = "metadata.json";

/**
Extensions to check when trying to find script input by name.
*/
pub const SEARCH_EXTS: &'static [&'static str] = &["crs", "rs"];

/**
When generating a package's unique ID, how many hex nibbles of the digest should be used *at most*?

The largest meaningful value is `40`.
*/
pub const ID_DIGEST_LEN_MAX: usize = 16;

/**
How old can stuff in the cache be before we automatically clear it out?

Measured in milliseconds.
*/
// It's been *one week* since you looked at me,
// cocked your head to the side and said "I'm angry."
pub const MAX_CACHE_AGE_MS: u64 = 1*7*24*60*60*1000;
<commit_msg>Modify how expr failures are reported.<commit_after>/*
Copyright ⓒ 2015-2017 cargo-script contributors.

Licensed under the MIT license (see LICENSE or <http://opensource.org
/licenses/MIT>) or the Apache License, Version 2.0 (see LICENSE of
<http://www.apache.org/licenses/LICENSE-2.0>), at your option. All
files in the project carrying such notice may not be copied, modified,
or distributed except according to those terms.
*/
/*!
This module just contains any big string literals I don't want cluttering up the rest of the code.
*/

/**
The message output when the user invokes `cargo script` with no further arguments.  We need to do this ourselves because `clap` doesn't provide any way to generate this message manually.
*/
pub const NO_ARGS_MESSAGE: &'static str = "\
The following required arguments were not supplied:
\t'<script>'

USAGE:
\tcargo script [FLAGS OPTIONS] [--] <script> <args>...

For more information try --help";

/*
What follows are the templates used to wrap script input.  The input provided by the user is inserted in place of `%b`.  *Proper* templates of some kind would be nice, but damnit, I'm lazy.
*/

/// The template used for script file inputs.
pub const FILE_TEMPLATE: &'static str = r#"%b"#;

/// The template used for `--expr` input.
pub const EXPR_TEMPLATE: &'static str = r#"
%p
fn main() {
    let exit_code = match try_main() {
        Ok(()) => None,
        Err(e) => {
            use std::io::{self, Write};
            writeln!(io::stderr(), "Error: {}", e);
            Some(1)
        },
    };
    if let Some(exit_code) = exit_code {
        std::process::exit(exit_code);
    }
}

fn try_main() -> Result<(), Box<std::error::Error>> {
    match {%b} {
        __cargo_script_expr => println!("{:?}", __cargo_script_expr)
    }
    Ok(())
}
"#;

/*
Regarding the loop templates: what I *want* is for the result of the closure to be printed to standard output *only* if it's not `()`.

* TODO: Just use TypeId, dumbass.
* TODO: Merge the `LOOP_*` templates so there isn't duplicated code.  It's icky.
*/

/// The template used for `--loop` input, assuming no `--count` flag is also given.
pub const LOOP_TEMPLATE: &'static str = r#"
%p
use std::any::Any;
use std::io::prelude::*;

fn main() {
    let mut closure = enforce_closure(
{%b}
    );
    let mut line_buffer = String::new();
    let mut stdin = std::io::stdin();
    loop {
        line_buffer.clear();
        let read_res = stdin.read_line(&mut line_buffer).unwrap_or(0);
        if read_res == 0 { break }
        let output = closure(&line_buffer);

        let display = {
            let output_any: &Any = &output;
            !output_any.is::<()>()
        };

        if display {
            println!("{:?}", output);
        }
    }
}

fn enforce_closure<F, T>(closure: F) -> F
where F: FnMut(&str) -> T, T: 'static {
    closure
}
"#;

/// The template used for `--count --loop` input.
pub const LOOP_COUNT_TEMPLATE: &'static str = r#"
%p
use std::any::Any;
use std::io::prelude::*;

fn main() {
    let mut closure = enforce_closure(
{%b}
    );
    let mut line_buffer = String::new();
    let mut stdin = std::io::stdin();
    let mut count = 0;
    loop {
        line_buffer.clear();
        let read_res = stdin.read_line(&mut line_buffer).unwrap_or(0);
        if read_res == 0 { break }
        count += 1;
        let output = closure(&line_buffer, count);

        let display = {
            let output_any: &Any = &output;
            !output_any.is::<()>()
        };

        if display {
            println!("{:?}", output);
        }
    }
}

fn enforce_closure<F, T>(closure: F) -> F
where F: FnMut(&str, usize) -> T, T: 'static {
    closure
}
"#;

/**
The default manifest used for packages.  `%n` is replaced with the "safe name" of the input, which *should* be safe to use as a file name.
*/
pub const DEFAULT_MANIFEST: &'static str = r#"
[package]
name = "%n"
version = "0.1.0"
authors = ["Anonymous"]

[[bin]]
name = "%n"
path = "%f.rs"
"#;

/**
The name of the package metadata file.
*/
pub const METADATA_FILE: &'static str = "metadata.json";

/**
Extensions to check when trying to find script input by name.
*/
pub const SEARCH_EXTS: &'static [&'static str] = &["crs", "rs"];

/**
When generating a package's unique ID, how many hex nibbles of the digest should be used *at most*?

The largest meaningful value is `40`.
*/
pub const ID_DIGEST_LEN_MAX: usize = 16;

/**
How old can stuff in the cache be before we automatically clear it out?

Measured in milliseconds.
*/
// It's been *one week* since you looked at me,
// cocked your head to the side and said "I'm angry."
pub const MAX_CACHE_AGE_MS: u64 = 1*7*24*60*60*1000;
<|endoftext|>


<commit_before>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use crate::cache::cache::Cache;
use rusoto_core::{Client, HttpClient, Region};
use rusoto_credential::StaticProvider;
use rusoto_s3::{GetObjectRequest, HeadObjectRequest, PutObjectRequest, S3Client, S3};
use std::io::{self, Read};
use std::path::Path;

#[derive(Clone)]
pub struct S3Cache {
    baseurl: Option<String>,
    client: S3Client,
    endpoint: String,
    bucket_name: String,
    key_prefix: Option<String>,
}

impl S3Cache {
    pub fn new(
        endpoint: &str,
        bucket_name: &str,
        access_key: &str,
        secret_key: &str,
        region: &str,
        baseurl: Option<String>,
        key_prefix: Option<String>,
    ) -> S3Cache {
        let region_object = Region::Custom {
            name: region.to_string(),
            endpoint: endpoint.to_string(),
        };
        let client = S3Client::new_with_client(
            Client::new_with(
                StaticProvider::new(access_key.to_string(), secret_key.to_string(), None, None),
                HttpClient::new().expect("Could not instantiate a new http client??"),
            ),
            region_object.clone(),
        );
        S3Cache {
            client: client,
            baseurl: baseurl,
            endpoint: endpoint.to_string(),
            bucket_name: bucket_name.to_string(),
            key_prefix: key_prefix,
        }
    }

    fn key_prefix(&self) -> String {
        self.key_prefix.clone().unwrap_or("".to_string())
    }

    fn full_path(&self, path: &str) -> String {
        let key_prefix = &self.key_prefix();
        match Path::new(key_prefix).join(path).to_str() {
            None => String::new(),
            Some(result) => result.to_string(),
        }
    }
}

impl Cache for S3Cache {
    fn info(&self) -> String {
        format!("Tile cache s3: {}/{}", self.endpoint, self.bucket_name)
    }

    fn baseurl(&self) -> String {
        self.baseurl
            .clone()
            .unwrap_or("http://localhost:6767".to_string())
    }

    fn read<F>(&self, path: &str, mut read: F) -> bool
    where
        F: FnMut(&mut dyn Read),
    {
        let key = self.full_path(path);
        if key.is_empty() {
            return false;
        }
        let request = GetObjectRequest {
            bucket: self.bucket_name.to_owned(),
            key: key.to_owned(),
            ..Default::default()
        };
        let client = self.client.clone();
        let response = client.get_object(request).sync();
        match response {
            Ok(mut result) => {
                let body = result.body.take().expect("The object has no body");
                read(&mut body.into_blocking_read());
                true
            }
            Err(_) => false,
        }
    }

    fn write(&self, path: &str, obj: &[u8]) -> Result<(), io::Error> {
        let key = self.full_path(path);
        if key.is_empty() {
            return Err(io::Error::new(
                io::ErrorKind::Other,
                "failed to join key_prefix with path",
            ));
        }
        let request = PutObjectRequest {
            bucket: self.bucket_name.to_owned(),
            key: key.to_owned(),
            body: Some(obj.to_vec().into()),
            ..Default::default()
        };
        let response = self.client.put_object(request).sync();
        match response {
            Ok(_) => Ok(()),
            Err(err) => Err(io::Error::new(io::ErrorKind::Other, err.to_string())),
        }
    }

    fn exists(&self, path: &str) -> bool {
        let key = self.full_path(path);
        if key.is_empty() {
            return false;
        }
        let request = HeadObjectRequest {
            bucket: self.bucket_name.to_owned(),
            key: key.to_owned(),
            ..Default::default()
        };
        let response = self.client.head_object(request).sync();
        match response {
            Ok(_) => true,
            Err(_) => false,
        }
    }
}
<commit_msg>set content-type on s3 objects<commit_after>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use crate::cache::cache::Cache;
use rusoto_core::{Client, HttpClient, Region};
use rusoto_credential::StaticProvider;
use rusoto_s3::{GetObjectRequest, HeadObjectRequest, PutObjectRequest, S3Client, S3};
use std::io::{self, Read};
use std::path::Path;

#[derive(Clone)]
pub struct S3Cache {
    baseurl: Option<String>,
    client: S3Client,
    endpoint: String,
    bucket_name: String,
    key_prefix: Option<String>,
}

impl S3Cache {
    pub fn new(
        endpoint: &str,
        bucket_name: &str,
        access_key: &str,
        secret_key: &str,
        region: &str,
        baseurl: Option<String>,
        key_prefix: Option<String>,
    ) -> S3Cache {
        let region_object = Region::Custom {
            name: region.to_string(),
            endpoint: endpoint.to_string(),
        };
        let client = S3Client::new_with_client(
            Client::new_with(
                StaticProvider::new(access_key.to_string(), secret_key.to_string(), None, None),
                HttpClient::new().expect("Could not instantiate a new http client??"),
            ),
            region_object.clone(),
        );
        S3Cache {
            client: client,
            baseurl: baseurl,
            endpoint: endpoint.to_string(),
            bucket_name: bucket_name.to_string(),
            key_prefix: key_prefix,
        }
    }

    fn key_prefix(&self) -> String {
        self.key_prefix.clone().unwrap_or("".to_string())
    }

    fn full_path(&self, path: &str) -> String {
        let key_prefix = &self.key_prefix();
        match Path::new(key_prefix).join(path).to_str() {
            None => String::new(),
            Some(result) => result.to_string(),
        }
    }
}

impl Cache for S3Cache {
    fn info(&self) -> String {
        format!("Tile cache s3: {}/{}", self.endpoint, self.bucket_name)
    }

    fn baseurl(&self) -> String {
        self.baseurl
            .clone()
            .unwrap_or("http://localhost:6767".to_string())
    }

    fn read<F>(&self, path: &str, mut read: F) -> bool
    where
        F: FnMut(&mut dyn Read),
    {
        let key = self.full_path(path);
        if key.is_empty() {
            return false;
        }
        let request = GetObjectRequest {
            bucket: self.bucket_name.to_owned(),
            key: key.to_owned(),
            ..Default::default()
        };
        let client = self.client.clone();
        let response = client.get_object(request).sync();
        match response {
            Ok(mut result) => {
                let body = result.body.take().expect("The object has no body");
                read(&mut body.into_blocking_read());
                true
            }
            Err(_) => false,
        }
    }

    fn write(&self, path: &str, obj: &[u8]) -> Result<(), io::Error> {
        let key = self.full_path(path);
        if key.is_empty() {
            return Err(io::Error::new(
                io::ErrorKind::Other,
                "failed to join key_prefix with path",
            ));
        }
        let extension = Path::new(path).extension().unwrap().to_str().unwrap();
        let content_type = match extension {
            "mvt" => Some("application/vnd.mapbox-vector-tile".to_string()),
            "pbf" => Some("application/vnd.mapbox-vector-tile".to_string()),
            "json" => Some("application/json".to_string()),
            _ => Some("application/octet-stream".to_string()),
        };
        let request = PutObjectRequest {
            bucket: self.bucket_name.to_owned(),
            key: key.to_owned(),
            content_type: content_type,
            body: Some(obj.to_vec().into()),
            ..Default::default()
        };
        let response = self.client.put_object(request).sync();
        match response {
            Ok(_) => Ok(()),
            Err(err) => Err(io::Error::new(io::ErrorKind::Other, err.to_string())),
        }
    }

    fn exists(&self, path: &str) -> bool {
        let key = self.full_path(path);
        if key.is_empty() {
            return false;
        }
        let request = HeadObjectRequest {
            bucket: self.bucket_name.to_owned(),
            key: key.to_owned(),
            ..Default::default()
        };
        let response = self.client.head_object(request).sync();
        match response {
            Ok(_) => true,
            Err(_) => false,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GtkPlacesSidebar — Sidebar that displays frequently-used places in the file system

use ffi;
use FFIWidget;
use cast::GTK_PLACES_SIDEBAR;
use glib::{to_bool, to_gboolean};

struct_Widget!(PlacesSidebar);

impl PlacesSidebar {
    pub fn new() -> Option<PlacesSidebar> {
        let tmp_pointer = unsafe { ffi::gtk_places_sidebar_new() };
        check_pointer!(tmp_pointer, PlacesSidebar)
    }

    pub fn set_open_flags(&self, flags: ::PlacesOpenFlags) {
        unsafe { ffi::gtk_places_sidebar_set_open_flags(GTK_PLACES_SIDEBAR(self.unwrap_widget()), flags) }
    }

    pub fn get_open_flags(&self) -> ::PlacesOpenFlags {
        unsafe { ffi::gtk_places_sidebar_get_open_flags(GTK_PLACES_SIDEBAR(self.unwrap_widget())) }
    }

    pub fn set_show_desktop(&self, show_desktop: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_desktop(GTK_PLACES_SIDEBAR(self.unwrap_widget()), to_gboolean(show_desktop)) }
    }

    pub fn get_show_desktop(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_desktop(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    pub fn set_show_connect_to_server(&self, show_connect_to_server: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_connect_to_server(GTK_PLACES_SIDEBAR(self.unwrap_widget()),
            to_gboolean(show_connect_to_server)) }
    }

    pub fn get_show_connect_to_server(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_connect_to_server(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    #[cfg(gtk_3_12)]
    pub fn set_local_only(&self, local_only: bool) {
        unsafe { ffi::gtk_places_sidebar_set_local_only(GTK_PLACES_SIDEBAR(self.unwrap_widget()), to_gboolean(local_only)) }
    }

    #[cfg(gtk_3_12)]
    pub fn get_local_only(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_local_only(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    #[cfg(gtk_3_12)]
    pub fn set_show_enter_location(&self, show_enter_location: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_enter_location(GTK_PLACES_SIDEBAR(self.unwrap_widget()),
            to_gboolean(show_enter_location)) }
    }

    #[cfg(gtk_3_12)]
    pub fn get_show_enter_location(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_enter_location(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }
}

impl_drop!(PlacesSidebar);
impl_TraitWidget!(PlacesSidebar);

impl ::ContainerTrait for PlacesSidebar {}
impl ::BinTrait for PlacesSidebar {}
impl ::ScrolledWindowTrait for PlacesSidebar {}
<commit_msg>Set good version<commit_after>// Copyright 2013-2015, The Rust-GNOME Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! GtkPlacesSidebar — Sidebar that displays frequently-used places in the file system

use ffi;
use FFIWidget;
use cast::GTK_PLACES_SIDEBAR;
use glib::{to_bool, to_gboolean};

struct_Widget!(PlacesSidebar);

impl PlacesSidebar {
    pub fn new() -> Option<PlacesSidebar> {
        let tmp_pointer = unsafe { ffi::gtk_places_sidebar_new() };
        check_pointer!(tmp_pointer, PlacesSidebar)
    }

    pub fn set_open_flags(&self, flags: ::PlacesOpenFlags) {
        unsafe { ffi::gtk_places_sidebar_set_open_flags(GTK_PLACES_SIDEBAR(self.unwrap_widget()), flags) }
    }

    pub fn get_open_flags(&self) -> ::PlacesOpenFlags {
        unsafe { ffi::gtk_places_sidebar_get_open_flags(GTK_PLACES_SIDEBAR(self.unwrap_widget())) }
    }

    pub fn set_show_desktop(&self, show_desktop: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_desktop(GTK_PLACES_SIDEBAR(self.unwrap_widget()), to_gboolean(show_desktop)) }
    }

    pub fn get_show_desktop(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_desktop(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    pub fn set_show_connect_to_server(&self, show_connect_to_server: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_connect_to_server(GTK_PLACES_SIDEBAR(self.unwrap_widget()),
            to_gboolean(show_connect_to_server)) }
    }

    pub fn get_show_connect_to_server(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_connect_to_server(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    #[cfg(gtk_3_12)]
    pub fn set_local_only(&self, local_only: bool) {
        unsafe { ffi::gtk_places_sidebar_set_local_only(GTK_PLACES_SIDEBAR(self.unwrap_widget()), to_gboolean(local_only)) }
    }

    #[cfg(gtk_3_12)]
    pub fn get_local_only(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_local_only(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }

    #[cfg(gtk_3_14)]
    pub fn set_show_enter_location(&self, show_enter_location: bool) {
        unsafe { ffi::gtk_places_sidebar_set_show_enter_location(GTK_PLACES_SIDEBAR(self.unwrap_widget()),
            to_gboolean(show_enter_location)) }
    }

    #[cfg(gtk_3_14)]
    pub fn get_show_enter_location(&self) -> bool {
        unsafe { to_bool(ffi::gtk_places_sidebar_get_show_enter_location(GTK_PLACES_SIDEBAR(self.unwrap_widget()))) }
    }
}

impl_drop!(PlacesSidebar);
impl_TraitWidget!(PlacesSidebar);

impl ::ContainerTrait for PlacesSidebar {}
impl ::BinTrait for PlacesSidebar {}
impl ::ScrolledWindowTrait for PlacesSidebar {}
<|endoftext|>


<commit_before>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

//! FFI interface for Command

use host::ffi::Ffi__Host;
use host::Host;
use libc::c_char;
use std::convert;
use std::ffi::CString;
use std::panic::catch_unwind;
use super::{Command, CommandResult};

#[repr(C)]
pub struct Ffi__Command {
    cmd: *const c_char,
}

impl convert::From<Command> for Ffi__Command {
    fn from(command: Command) -> Ffi__Command {
        Ffi__Command {
            cmd: CString::new(command.cmd).unwrap().into_raw(),
        }
    }
}

impl convert::Into<Command> for Ffi__Command {
    fn into(self) -> Command {
        let cmd = trypanic!(ptrtostr!(self.cmd, "Command.cmd string"));
        Command::new(cmd)
    }
}

#[repr(C)]
pub struct Ffi__CommandResult {
    pub exit_code: i32,
    pub stdout: *const c_char,
    pub stderr: *const c_char,
}

impl convert::From<CommandResult> for Ffi__CommandResult {
    fn from(result: CommandResult) -> Ffi__CommandResult {
        Ffi__CommandResult {
            exit_code: result.exit_code,
            stdout: CString::new(result.stdout).unwrap().into_raw(),
            stderr: CString::new(result.stderr).unwrap().into_raw(),
        }
    }
}

#[no_mangle]
pub extern "C" fn command_new(cmd_ptr: *const c_char) -> *mut Ffi__Command {
    let cmd = trynull!(ptrtostr!(cmd_ptr, "path string"));

    let ffi_command: Ffi__Command = trynull!(catch_unwind(|| Command::new(cmd).into()));
    Box::into_raw(Box::new(ffi_command))
}

#[no_mangle]
pub extern "C" fn command_exec(ffi_cmd_ptr: *mut Ffi__Command, ffi_host_ptr: *mut Ffi__Host) -> *mut Ffi__CommandResult {
    let cmd: Command = trynull!(readptr!(ffi_cmd_ptr, "Command struct"));
    let mut host: Host = trynull!(readptr!(ffi_host_ptr, "Host struct"));

    let result = trynull!(cmd.exec(&mut host));
    let ffi_result: Ffi__CommandResult = trynull!(catch_unwind(|| result.into()));
    Box::into_raw(Box::new(ffi_result))
}

#[cfg(test)]
mod tests {
    use {Command, CommandResult};
    #[cfg(feature = "remote-run")]
    use Host;
    #[cfg(feature = "remote-run")]
    use czmq::{ZMsg, ZSys};
    use error::ERRMSG;
    use host::ffi::Ffi__Host;
    #[cfg(feature = "remote-run")]
    use host::ffi::host_close;
    #[cfg(feature = "remote-run")]
    use std::{str, thread};
    use std::ffi::CStr;
    use std::ffi::CString;
    use std::ptr;
    use super::*;

    #[test]
    fn test_convert_command() {
        let command = Command {
            cmd: "whoami".to_string(),
        };
        Ffi__Command::from(command);
    }

    #[test]
    fn test_convert_ffi_command() {
        let ffi_command = Ffi__Command {
            cmd: CString::new("whoami").unwrap().as_ptr(),
        };
        let _: Command = ffi_command.into();
    }

    #[test]
    fn test_convert_command_result() {
        let result = CommandResult {
            exit_code: 0,
            stdout: "moo".to_string(),
            stderr: "cow".to_string(),
        };
        Ffi__CommandResult::from(result);
    }

    #[test]
    fn test_command_new() {
        let cmd_cstr = CString::new("moo").unwrap().as_ptr();
        let ffi_cmd = unsafe { ptr::read(command_new(cmd_cstr)) };
        assert_eq!(ffi_cmd.cmd, cmd_cstr);

        assert!(command_new(ptr::null()).is_null());
        assert_eq!(unsafe { CStr::from_ptr(ERRMSG).to_str().unwrap() }, "Received null when we expected a path string pointer");
    }

    #[cfg(feature = "local-run")]
    #[test]
    fn test_command_exec() {
        let mut host = Ffi__Host;
        let cmd = command_new(CString::new("whoami").unwrap().as_ptr());
        let result = unsafe { ptr::read(command_exec(cmd, &mut host)) };
        assert_eq!(result.exit_code, 0);
    }

    #[cfg(feature = "remote-run")]
    #[test]
    fn test_command_exec() {
        ZSys::init();

        let (client, mut server) = ZSys::create_pipe().unwrap();

        let agent_mock = thread::spawn(move || {
            let req = ZMsg::recv(&mut server).unwrap();
            assert_eq!("command::exec", req.popstr().unwrap().unwrap());
            assert_eq!("moo", req.popstr().unwrap().unwrap());

            let rep = ZMsg::new();
            rep.addstr("Ok").unwrap();
            rep.addstr("0").unwrap();
            rep.addstr("cow").unwrap();
            rep.addstr("err").unwrap();
            rep.send(&mut server).unwrap();
        });

        let mut ffi_host = Ffi__Host::from(Host::test_new(None, Some(client), None));

        let mut ffi_command = Ffi__Command {
            cmd: CString::new("moo").unwrap().as_ptr(),
        };

        let result = unsafe { ptr::read(command_exec(&mut ffi_command, &mut ffi_host)) };

        assert_eq!(host_close(&mut ffi_host), 0);

        assert_eq!(result.exit_code, 0);

        let stdout_slice = unsafe { CStr::from_ptr(result.stdout) };
        let stdout = str::from_utf8(stdout_slice.to_bytes()).unwrap();
        assert_eq!(stdout, "cow");

        let stderr_slice = unsafe { CStr::from_ptr(result.stderr) };
        let stderr = str::from_utf8(stderr_slice.to_bytes()).unwrap();
        assert_eq!(stderr, "err");

        agent_mock.join().unwrap();
    }
}
<commit_msg>Fix broken Command FFI test for Rust nightly<commit_after>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

//! FFI interface for Command

use host::ffi::Ffi__Host;
use host::Host;
use libc::c_char;
use std::convert;
use std::ffi::CString;
use std::panic::catch_unwind;
use super::{Command, CommandResult};

#[repr(C)]
pub struct Ffi__Command {
    cmd: *const c_char,
}

impl convert::From<Command> for Ffi__Command {
    fn from(command: Command) -> Ffi__Command {
        Ffi__Command {
            cmd: CString::new(command.cmd).unwrap().into_raw(),
        }
    }
}

impl convert::Into<Command> for Ffi__Command {
    fn into(self) -> Command {
        let cmd = trypanic!(ptrtostr!(self.cmd, "Command.cmd string"));
        Command::new(cmd)
    }
}

#[repr(C)]
pub struct Ffi__CommandResult {
    pub exit_code: i32,
    pub stdout: *const c_char,
    pub stderr: *const c_char,
}

impl convert::From<CommandResult> for Ffi__CommandResult {
    fn from(result: CommandResult) -> Ffi__CommandResult {
        Ffi__CommandResult {
            exit_code: result.exit_code,
            stdout: CString::new(result.stdout).unwrap().into_raw(),
            stderr: CString::new(result.stderr).unwrap().into_raw(),
        }
    }
}

#[no_mangle]
pub extern "C" fn command_new(cmd_ptr: *const c_char) -> *mut Ffi__Command {
    let cmd = trynull!(ptrtostr!(cmd_ptr, "path string"));

    let ffi_command: Ffi__Command = trynull!(catch_unwind(|| Command::new(cmd).into()));
    Box::into_raw(Box::new(ffi_command))
}

#[no_mangle]
pub extern "C" fn command_exec(ffi_cmd_ptr: *mut Ffi__Command, ffi_host_ptr: *mut Ffi__Host) -> *mut Ffi__CommandResult {
    let cmd: Command = trynull!(readptr!(ffi_cmd_ptr, "Command struct"));
    let mut host: Host = trynull!(readptr!(ffi_host_ptr, "Host struct"));

    let result = trynull!(cmd.exec(&mut host));
    let ffi_result: Ffi__CommandResult = trynull!(catch_unwind(|| result.into()));
    Box::into_raw(Box::new(ffi_result))
}

#[cfg(test)]
mod tests {
    use {Command, CommandResult};
    #[cfg(feature = "remote-run")]
    use Host;
    #[cfg(feature = "remote-run")]
    use czmq::{ZMsg, ZSys};
    use error::ERRMSG;
    use host::ffi::Ffi__Host;
    #[cfg(feature = "remote-run")]
    use host::ffi::host_close;
    #[cfg(feature = "remote-run")]
    use std::{str, thread};
    use std::ffi::CStr;
    use std::ffi::CString;
    use std::ptr;
    use super::*;

    #[test]
    fn test_convert_command() {
        let command = Command {
            cmd: "whoami".to_string(),
        };
        Ffi__Command::from(command);
    }

    #[test]
    fn test_convert_ffi_command() {
        let ffi_command = Ffi__Command {
            cmd: CString::new("whoami").unwrap().as_ptr(),
        };
        let _: Command = ffi_command.into();
    }

    #[test]
    fn test_convert_command_result() {
        let result = CommandResult {
            exit_code: 0,
            stdout: "moo".to_string(),
            stderr: "cow".to_string(),
        };
        Ffi__CommandResult::from(result);
    }

    #[test]
    fn test_command_new() {
        let cmd_cstr = CString::new("moo").unwrap().as_ptr();
        let ffi_cmd = unsafe { ptr::read(command_new(cmd_cstr)) };
        assert_eq!(ffi_cmd.cmd, cmd_cstr);

        assert!(command_new(ptr::null()).is_null());
        assert_eq!(unsafe { CStr::from_ptr(ERRMSG).to_str().unwrap() }, "Received null when we expected a path string pointer");
    }

    #[cfg(feature = "local-run")]
    #[test]
    fn test_command_exec() {
        let mut host = Ffi__Host;
        let cmd = command_new(CString::new("whoami").unwrap().as_ptr());
        let result = unsafe { ptr::read(command_exec(cmd, &mut host)) };
        assert_eq!(result.exit_code, 0);
    }

    #[cfg(feature = "remote-run")]
    #[test]
    fn test_command_exec() {
        ZSys::init();

        let (client, mut server) = ZSys::create_pipe().unwrap();
        client.set_sndtimeo(Some(500));
        server.set_rcvtimeo(Some(500));

        let agent_mock = thread::spawn(move || {
            let req = ZMsg::recv(&mut server).unwrap();
            assert_eq!("command::exec", req.popstr().unwrap().unwrap());
            assert_eq!("moo", req.popstr().unwrap().unwrap());

            let rep = ZMsg::new();
            rep.addstr("Ok").unwrap();
            rep.addstr("0").unwrap();
            rep.addstr("cow").unwrap();
            rep.addstr("err").unwrap();
            rep.send(&mut server).unwrap();
        });

        let mut ffi_host = Ffi__Host::from(Host::test_new(None, Some(client), None));
        let mut ffi_command = Ffi__Command {
            cmd: CString::new("moo").unwrap().into_raw(),
        };

        let result = unsafe { ptr::read(command_exec(&mut ffi_command, &mut ffi_host)) };

        assert_eq!(host_close(&mut ffi_host), 0);
        assert_eq!(result.exit_code, 0);

        let stdout = ptrtostr!(result.stdout, "stdout").unwrap();
        assert_eq!(stdout, "cow");

        let stderr = ptrtostr!(result.stderr, "stderr").unwrap();
        assert_eq!(stderr, "err");

        agent_mock.join().unwrap();
    }
}
<|endoftext|>


<commit_before>mod init;
mod config;
mod ignore;
mod sweep;
mod burn;
mod start;
mod end;
mod destroy;
mod patrol;

use self::init::Init;
use self::config::Config;
use self::ignore::Ignore;
use self::sweep::Sweep;
use self::burn::Burn;
use self::start::Start;
use self::end::End;
use self::destroy::Destroy;
use self::patrol::Patrol;

use constant::BANNED_DIRS;
use error::{CliError, EssentialLack, EssentialKind, RunningPlaceError, Usage, UsageKind};
use lib::io::*;
use lib::setting;
use std::env;
use std::fmt::Display;
use std::io::Error as IoError;

trait Command {
    fn allow_to_check_current_dir(&self) -> bool { true }
    fn check_current_dir(&self) -> Result<(), CliError> {
        let current_dir = try!(env::current_dir());

        match BANNED_DIRS.iter().find(|d| current_dir.ends_with(d)) {
            Some(d) => Err(From::from(RunningPlaceError::new(d.to_string()))),
            None    => Ok(()),
        }
    }

    fn allow_to_check_settings(&self) -> bool { true }
    fn check_settings(&self) -> Result<(), EssentialLack> {
        if !setting::working_dir_exists() {
            return Err(EssentialLack::new(EssentialKind::WorkingDir));
        }
        if !setting::Storage::exist() {
            return Err(EssentialLack::new(EssentialKind::StorageDir));
        }
        if !setting::Config::exist() {
            return Err(EssentialLack::new(EssentialKind::ConfigFile));
        }
        if !setting::Ignore::exist() {
            return Err(EssentialLack::new(EssentialKind::IgnoreFile));
        }

        Ok(())
    }

    fn usage(&self) -> Usage;

    fn main(&self) -> Result<(), CliError>;

    fn exec(&self, help: bool) -> Result<(), CliError> {
        if self.allow_to_check_current_dir() {
            try!(self.check_current_dir());
        }

        if self.allow_to_check_settings() {
            try!(self.check_settings());
        }

        if help {
            Err(From::from(self.usage()))
        } else {
            self.main()
        }
    }

    fn run_after_confirmation<D: Display, F>(message: D, danger_exec: F) -> Result<(), CliError>
        where Self: Sized, F: FnOnce() -> Result<(), IoError>
    {
        echo(format_with_tag(Tag::Caution, format!("{} [yes/no]: ", message)));

        let input = try!(read_line_from_stdin()).to_lowercase();
        match input.as_ref() {
            "y" | "yes" => try!(danger_exec()),
            _           => print_with_tag(Tag::Notice, "Interrupted by user"),
        };

        Ok(())
    }
}

pub fn execute() -> Result<(), CliError> {
    let args = env::args()
        .skip(1)
        .collect::<Vec<String>>();

    let help = args.iter().any(|a| *a == "-h" || *a == "--help");

    let mut args = args.into_iter();

    let command: Box<Command> = match args.next() {
        Some(first) => match first.as_ref() {
            "init"    => Box::new(Init                                                 ),
            "config"  => Box::new(Config::new(args.next(), args.next()   , args.next())),
            "ignore"  => Box::new(Ignore::new(args.next(), args.collect()             )),
            "sweep"   => Box::new(Sweep                                                ),
            "burn"    => Box::new(Burn                                                 ),
            "start"   => Box::new(Start                                                ),
            "end"     => Box::new(End                                                  ),
            "destroy" => Box::new(Destroy                                              ),
            "patrol"  => Box::new(Patrol                                               ),
            _         => return Err(From::from(Usage::new(UsageKind::Nothing))),
        },
        None => return Err(From::from(Usage::new(UsageKind::Nothing))),
    };

    command.exec(help)
}

pub fn clean_up_cron() -> Result<(), CliError> {
    if cfg!(unix) {
        End.main()
    } else {
        Ok(())
    }
}
<commit_msg>[Feature] Implement "help" command<commit_after>mod init;
mod config;
mod ignore;
mod sweep;
mod burn;
mod start;
mod end;
mod destroy;
mod patrol;

use self::init::Init;
use self::config::Config;
use self::ignore::Ignore;
use self::sweep::Sweep;
use self::burn::Burn;
use self::start::Start;
use self::end::End;
use self::destroy::Destroy;
use self::patrol::Patrol;

use constant::BANNED_DIRS;
use error::{CliError, EssentialLack, EssentialKind, RunningPlaceError, Usage, UsageKind};
use lib::io::*;
use lib::setting;
use std::env;
use std::fmt::Display;
use std::io::Error as IoError;

trait Command {
    fn allow_to_check_current_dir(&self) -> bool { true }
    fn check_current_dir(&self) -> Result<(), CliError> {
        let current_dir = try!(env::current_dir());

        match BANNED_DIRS.iter().find(|d| current_dir.ends_with(d)) {
            Some(d) => Err(From::from(RunningPlaceError::new(d.to_string()))),
            None    => Ok(()),
        }
    }

    fn allow_to_check_settings(&self) -> bool { true }
    fn check_settings(&self) -> Result<(), EssentialLack> {
        if !setting::working_dir_exists() {
            return Err(EssentialLack::new(EssentialKind::WorkingDir));
        }
        if !setting::Storage::exist() {
            return Err(EssentialLack::new(EssentialKind::StorageDir));
        }
        if !setting::Config::exist() {
            return Err(EssentialLack::new(EssentialKind::ConfigFile));
        }
        if !setting::Ignore::exist() {
            return Err(EssentialLack::new(EssentialKind::IgnoreFile));
        }

        Ok(())
    }

    fn usage(&self) -> Usage;

    fn main(&self) -> Result<(), CliError>;

    fn exec(&self, need_help: bool) -> Result<(), CliError> {
        if need_help {
            return Err(From::from(self.usage()));
        }

        if self.allow_to_check_current_dir() {
            try!(self.check_current_dir());
        }

        if self.allow_to_check_settings() {
            try!(self.check_settings());
        }

        self.main()
    }

    fn run_after_confirmation<D: Display, F>(message: D, danger_exec: F) -> Result<(), CliError>
        where Self: Sized, F: FnOnce() -> Result<(), IoError>
    {
        echo(format_with_tag(Tag::Caution, format!("{} [yes/no]: ", message)));

        let input = try!(read_line_from_stdin()).to_lowercase();
        match input.as_ref() {
            "y" | "yes" => try!(danger_exec()),
            _           => print_with_tag(Tag::Notice, "Interrupted by user"),
        };

        Ok(())
    }
}

pub fn execute() -> Result<(), CliError> {
    let args = env::args()
        .skip(1)
        .collect::<Vec<String>>();

    let mut args = args.into_iter();

    let command = try!(args.next().ok_or(Usage::new(UsageKind::Nothing)));

    let (command, need_help) = if &command == "help" {
        (try!(args.next().ok_or(Usage::new(UsageKind::Help))), true)
    } else {
        (command, false)
    };

    match command.as_ref() {
        "init"    => Init                                                 .exec(need_help),
        "config"  => Config::new(args.next(), args.next()   , args.next()).exec(need_help),
        "ignore"  => Ignore::new(args.next(), args.collect()             ).exec(need_help),
        "sweep"   => Sweep                                                .exec(need_help),
        "burn"    => Burn                                                 .exec(need_help),
        "start"   => Start                                                .exec(need_help),
        "end"     => End                                                  .exec(need_help),
        "destroy" => Destroy                                              .exec(need_help),
        "patrol"  => Patrol                                               .exec(need_help),
        _         => Err(From::from(Usage::new(UsageKind::Nothing))),
    }
}

pub fn clean_up_cron() -> Result<(), CliError> {
    if cfg!(unix) {
        End.main()
    } else {
        Ok(())
    }
}
<|endoftext|>