<commit_before>extern crate num;
extern crate nue;
use super::{Com, Core, SenderBus, Permission};
use std::sync::mpsc::{Receiver, SyncSender, sync_channel};
use std::io::Read;

struct Bus<W> {
    sender: SenderBus<W>,
    selected: bool,
}

#[derive(Default)]
struct DStack<W> {
    stack: Vec<W>,
}

impl<W> DStack<W> where W: Copy {
    fn rotate(&mut self, pos: u8) {
        let last = self.stack.len() - 1;
        // TODO: Introduce debug on out of range
        let v = self.stack.remove(last - pos as usize);
        self.stack.push(v);
    }

    fn copy(&mut self, pos: u8) {
        let last = self.stack.len() - 1;
        // TODO: Introduce debug on out of range
        let v = self.stack[last - pos as usize];
        self.stack.push(v);
    }

    fn replace<F>(&mut self, c: F) where F: FnOnce(W) -> W {
        let v = match self.stack.pop() {
            Some(v) => v,
            None => {
                // TODO: Add proper debugging here
                panic!("core0: Attempted to consume a value when none was available.");
            },
        };

        self.stack.push(c(v));
    }
}

pub struct Core0<W> {
    permission: Permission,
    running: bool,
    pc: W,
    dcs: [W; 4],
    carry: bool,
    overflow: bool,
    interrupt: bool,
    program: Vec<u8>,
    data: Vec<W>,

    // Buses including senders
    buses: Vec<Bus<W>>,

    // Incoming streams
    incoming_streams: Vec<Receiver<Com<Box<Read>>>>,

    // The channel that must be used to incept this core
    incept_channel: (SyncSender<Com<(Permission, Box<Read>)>>, Receiver<Com<(Permission, Box<Read>)>>),
    // The channel that must be used to send interrupts to this core
    send_channel: (SyncSender<Com<W>>, Receiver<Com<W>>),
    // The channel that must be used to kill this core
    kill_channel: (SyncSender<Com<()>>, Receiver<Com<()>>),

    // Set up stack
    dstack: DStack<W>,
}

impl Core0<u32> {
    fn new(memory: usize) -> Self {
        Core0{
            permission: Permission::default(),
            running: false,
            pc: 0,
            dcs: [0; 4],
            carry: false,
            overflow: false,
            interrupt: false,
            program: Vec::new(),
            data: vec![0; memory],

            incoming_streams: Vec::new(),
            buses: Vec::new(),

            incept_channel: sync_channel(0),
            send_channel: sync_channel(0),
            kill_channel: sync_channel(0),

            dstack: DStack::default(),
        }
    }
}

impl<W> Core<W> for Core0<W>
    where W: Copy + num::PrimInt + num::Signed + nue::Decode + nue::Encode, usize: From<W>
{
    fn append_sender(&mut self, sender: SenderBus<W>) {
        self.buses.push(Bus{
            sender: sender,
            selected: false,
        });
    }

    fn aquire_sender(&mut self) -> SenderBus<W> {
        let stream_channel = sync_channel(0);
        self.incoming_streams.push(stream_channel.1);
        SenderBus{
            bus: self.incoming_streams.len() - 1,
            stream: stream_channel.0,
            incept: self.incept_channel.0.clone(),
            send: self.send_channel.0.clone(),
            kill: self.kill_channel.0.clone(),
        }
    }

    fn begin(&mut self) {
        assert_eq!(self.incoming_streams.len(), self.buses.len());
        // Get disjoint references so borrows can occur simultaneously
        let dstack = &mut self.dstack;
        let data = &mut self.data;
        let prog = &mut self.program;
        let pc = &mut self.pc;
        let dcs = &mut self.dcs;
        let permission = &mut self.permission;
        let carry = &mut self.carry;
        let overflow = &mut self.overflow;

        // Repeat loop of reinception perpetually
        loop {
            // Accept inception
            // TODO: Implement
            {
                let com = match self.incept_channel.1.recv() {
                    Ok(v) => v,
                    Err(_) => panic!("core0: Inception channel broken"),
                };

                *permission = com.data.0;
                let mut receiver = com.data.1;
                // Clear any previous program before loading the new one
                prog.clear();
                receiver.read_to_end(prog).expect("core0: Inception stream failed");
            }

            // Run until core is killed
            loop {
                // Poll for any sort of communication
                // TODO: Implement

                // Execute instruction
                match prog[usize::from(*pc)] {
                    // rread#
                    x @ 0x00...0x03 => {
                        let select = x as usize;
                        dstack.replace(|v| {
                            data[usize::from(dcs[select] + v)]
                        });
                    },
                    // add#
                    x @ 0x04...0x07 => {
                        let select = x as usize - 0x04;
                        dstack.replace(|v| {
                            let dc_val = data[usize::from(dcs[select])];
                            let new = dc_val + v;
                            let old_signs = (v.is_negative(), dc_val.is_negative());
                            let new_sign = new < W::zero();
                            *overflow = if old_signs.0 != old_signs.1 {
                                false
                            } else {
                                new_sign != old_signs.0
                            };
                            *carry = old_signs.0 && old_signs.1 && !new_sign;
                            new
                        });
                    },
                    // inc
                    0x08 => {
                        dstack.replace(|v| {
                            let new = v + W::one();
                            let old_sign = v.is_negative();
                            let new_sign = new.is_negative();
                            // Going from positive to negative is overflow
                            *overflow = !old_sign && new_sign;
                            *carry = v == -W::one();
                            new
                        });
                    },
                    // TODO: Add all instructions
                    _ => {},
                }
            }
        }
    }
}
<commit_msg>finished up to 0x0F in c0 instruction space<commit_after>extern crate num;
extern crate nue;
use super::{Com, Core, SenderBus, Permission};
use std::sync::mpsc::{Receiver, SyncSender, sync_channel};
use std::io::Read;

struct Bus<W> {
    sender: SenderBus<W>,
    selected: bool,
}

#[derive(Default)]
struct DStack<W> {
    stack: Vec<W>,
}

impl<W> DStack<W> where W: Copy {
    fn rotate(&mut self, pos: u8) {
        let last = self.stack.len() - 1;
        // TODO: Introduce debug on out of range
        let v = self.stack.remove(last - pos as usize);
        self.stack.push(v);
    }

    fn copy(&mut self, pos: u8) {
        let last = self.stack.len() - 1;
        // TODO: Introduce debug on out of range
        let v = self.stack[last - pos as usize];
        self.stack.push(v);
    }

    fn replace<F>(&mut self, c: F) where F: FnOnce(W) -> W {
        let v = match self.stack.pop() {
            Some(v) => v,
            None => {
                // TODO: Add proper debugging here
                panic!("core0: Attempted to consume a value when none was available.");
            },
        };

        self.stack.push(c(v));
    }
}

struct CStackElement<W> {
    pc: W,
    dcs: [W; 4],
    interrupt: bool,
}

pub struct Core0<W> {
    permission: Permission,
    running: bool,
    pc: W,
    dcs: [W; 4],
    carry: bool,
    overflow: bool,
    interrupt: bool,
    program: Vec<u8>,
    data: Vec<W>,

    // Buses including senders
    buses: Vec<Bus<W>>,

    // Incoming streams
    incoming_streams: Vec<Receiver<Com<Box<Read>>>>,

    // The channel that must be used to incept this core
    incept_channel: (SyncSender<Com<(Permission, Box<Read>)>>, Receiver<Com<(Permission, Box<Read>)>>),
    // The channel that must be used to send interrupts to this core
    send_channel: (SyncSender<Com<W>>, Receiver<Com<W>>),
    // The channel that must be used to kill this core
    kill_channel: (SyncSender<Com<()>>, Receiver<Com<()>>),

    dstack: DStack<W>,
    cstack: Vec<CStackElement<W>>,
}

impl Core0<u32> {
    fn new(memory: usize) -> Self {
        Core0{
            permission: Permission::default(),
            running: false,
            pc: 0,
            dcs: [0; 4],
            carry: false,
            overflow: false,
            interrupt: false,
            program: Vec::new(),
            data: vec![0; memory],

            incoming_streams: Vec::new(),
            buses: Vec::new(),

            incept_channel: sync_channel(0),
            send_channel: sync_channel(0),
            kill_channel: sync_channel(0),

            dstack: DStack::default(),
            cstack: Vec::new(),
        }
    }
}

impl<W> Core<W> for Core0<W>
    where W: Copy + num::PrimInt + num::Signed + nue::Decode + nue::Encode, usize: From<W>
{
    fn append_sender(&mut self, sender: SenderBus<W>) {
        self.buses.push(Bus{
            sender: sender,
            selected: false,
        });
    }

    fn aquire_sender(&mut self) -> SenderBus<W> {
        let stream_channel = sync_channel(0);
        self.incoming_streams.push(stream_channel.1);
        SenderBus{
            bus: self.incoming_streams.len() - 1,
            stream: stream_channel.0,
            incept: self.incept_channel.0.clone(),
            send: self.send_channel.0.clone(),
            kill: self.kill_channel.0.clone(),
        }
    }

    fn begin(&mut self) {
        assert_eq!(self.incoming_streams.len(), self.buses.len());
        // Get disjoint references so borrows can occur simultaneously
        let dstack = &mut self.dstack;
        let cstack = &mut self.cstack;
        let data = &mut self.data;
        let prog = &mut self.program;
        let pc = &mut self.pc;
        let dcs = &mut self.dcs;
        let permission = &mut self.permission;
        let carry = &mut self.carry;
        let overflow = &mut self.overflow;
        let interrupt = &mut self.interrupt;

        // Repeat loop of reinception perpetually
        loop {
            // Accept inception
            // TODO: Implement
            {
                let com = match self.incept_channel.1.recv() {
                    Ok(v) => v,
                    Err(_) => panic!("core0: Inception channel broken"),
                };

                *permission = com.data.0;
                let mut receiver = com.data.1;
                // Clear any previous program before loading the new one
                prog.clear();
                receiver.read_to_end(prog).expect("core0: Inception stream failed");
            }

            // Run until core is killed
            loop {
                // Poll for any sort of communication
                // TODO: Implement

                // Execute instruction
                match prog[usize::from(*pc)] {
                    // rread#
                    x @ 0x00...0x03 => {
                        let select = x as usize;
                        dstack.replace(|v| {
                            data[usize::from(dcs[select] + v)]
                        });
                    },
                    // add#
                    x @ 0x04...0x07 => {
                        let select = x as usize - 0x04;
                        dstack.replace(|v| {
                            let dc_val = data[usize::from(dcs[select])];
                            let new = dc_val + v;
                            let old_signs = (v.is_negative(), dc_val.is_negative());
                            let new_sign = new < W::zero();
                            *overflow = if old_signs.0 != old_signs.1 {
                                false
                            } else {
                                new_sign != old_signs.0
                            };
                            *carry = old_signs.0 && old_signs.1 && !new_sign;
                            new
                        });
                    },
                    // inc
                    0x08 => {
                        dstack.replace(|v| {
                            let new = v + W::one();
                            let old_sign = v.is_negative();
                            let new_sign = new.is_negative();
                            // Going from positive to negative is overflow
                            *overflow = !old_sign && new_sign;
                            // If the new value wrapped back to zero we carry
                            *carry = new == W::zero();
                            new
                        });
                    },
                    // dec
                    0x09 => {
                        dstack.replace(|v| {
                            let new = v - W::one();
                            let old_sign = v.is_negative();
                            let new_sign = new.is_negative();
                            // Going from negative to positive is overflow
                            *overflow = old_sign && !new_sign;
                            // If the original value is zero, decrementing borrows
                            let borrow = v == W::zero();
                            *carry = !borrow;
                            new
                        });
                    },
                    // carry
                    0x0A => {
                        if *carry {
                            dstack.replace(|v| {
                                let new = v + W::one();
                                let old_sign = v.is_negative();
                                let new_sign = new.is_negative();
                                // Going from positive to negative is overflow
                                *overflow = !old_sign && new_sign;
                                // If the new value wrapped back to zero we carry
                                *carry = new == W::zero();
                                new
                            });
                        } else {
                            *overflow = false;
                            *carry = false;
                        }
                    },
                    // borrow
                    0x0B => {
                        if *carry {
                            *overflow = false;
                            *carry = true;
                        } else {
                            dstack.replace(|v| {
                                let new = v - W::one();
                                let old_sign = v.is_negative();
                                let new_sign = new.is_negative();
                                // Going from negative to positive is overflow
                                *overflow = old_sign && !new_sign;
                                // If the original value is zero, decrementing borrows
                                let borrow = v == W::zero();
                                *carry = !borrow;
                                new
                            });
                        }
                    },
                    // inv
                    0x0C => {
                        dstack.replace(|v| {
                            !v
                        });
                    },
                    // flush
                    0x0D => {},
                    // reads
                    0x0E => {
                        dstack.replace(|v| {
                            data[usize::from(v)]
                        });
                    },
                    // ret
                    0x0F => {
                        let elem = match cstack.pop() {
                            Some(v) => v,
                            None => panic!("core0: Tried to return with empty return stack"),
                        };
                        if elem.interrupt {
                            *interrupt = true;
                        }
                        *pc = elem.pc;
                        *dcs = elem.dcs;
                    },
                    // TODO: Add all instructions
                    _ => {},
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use clap::{App, Arg, AppSettings};

/// Representation of the application's of all configurable values
#[derive(Debug, Clone, Hash)]
pub struct Options {
    /// Host to connect to. Default: `"localhost"`
    pub host: String,
    /// Port on the host to connect to. Default: `8080`
    pub port: u16,
}

impl Options {
    /// Parse `env`-wide command-line arguments into an `Options` instance
    pub fn parse() -> Options {
        static USAGE: &'static str = "[host] 'Host to connect to. Default: localhost'";

        let matches = App::new("tatsoryk-server")
                          .setting(AppSettings::ColoredHelp)
                          .version(env!("CARGO_PKG_VERSION"))
                          .author("nabijaczleweli <nabijaczleweli@gmail.com>,\n\
                                   Cat Plus Plus <piotrlegnica@piotrl.pl>,\n\
                                   Lalaland <ethan.steinberg@gmail.com>")
                          .about("Implementation of the server for Tatsoryk")
                          .args_from_usage(USAGE)
                          .arg(Arg::from_usage("[port] 'Port on the host to connect to. \
                                                  Default: 8080'")
                                   .validator(Options::verify_u16))
                          .get_matches();

        Options {
            host: matches.value_of("host").unwrap_or("127.0.0.1").to_string(),
            port: matches.value_of("port").unwrap_or("8080").parse::<u16>().unwrap(), /* Verified earlier */
        }
    }

    fn verify_u16(arg: String) -> Result<(), String> {
        match arg[..].parse::<u16>() {
            Ok(_) => Ok(()),
            Err(err) => Err(format!("{:?} is not a 16-bit unsigned integer: {}", arg, err)),
        }
    }
}
<commit_msg>Fix typo in option.rs<commit_after>use clap::{App, Arg, AppSettings};

/// Representation of the application's all configurable values
#[derive(Debug, Clone, Hash)]
pub struct Options {
    /// Host to connect to. Default: `"localhost"`
    pub host: String,
    /// Port on the host to connect to. Default: `8080`
    pub port: u16,
}

impl Options {
    /// Parse `env`-wide command-line arguments into an `Options` instance
    pub fn parse() -> Options {
        static USAGE: &'static str = "[host] 'Host to connect to. Default: localhost'";

        let matches = App::new("tatsoryk-server")
                          .setting(AppSettings::ColoredHelp)
                          .version(env!("CARGO_PKG_VERSION"))
                          .author("nabijaczleweli <nabijaczleweli@gmail.com>,\n\
                                   Cat Plus Plus <piotrlegnica@piotrl.pl>,\n\
                                   Lalaland <ethan.steinberg@gmail.com>")
                          .about("Implementation of the server for Tatsoryk")
                          .args_from_usage(USAGE)
                          .arg(Arg::from_usage("[port] 'Port on the host to connect to. \
                                                  Default: 8080'")
                                   .validator(Options::verify_u16))
                          .get_matches();

        Options {
            host: matches.value_of("host").unwrap_or("127.0.0.1").to_string(),
            port: matches.value_of("port").unwrap_or("8080").parse::<u16>().unwrap(), /* Verified earlier */
        }
    }

    fn verify_u16(arg: String) -> Result<(), String> {
        match arg[..].parse::<u16>() {
            Ok(_) => Ok(()),
            Err(err) => Err(format!("{:?} is not a 16-bit unsigned integer: {}", arg, err)),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate dft;
extern crate test;

use std::mem;

use dft::{Operation, Plan, c64};
use test::{Bencher, black_box};

#[bench] fn complex_0004(bencher: &mut Bencher) { complex(   4, bencher); }
#[bench] fn complex_0008(bencher: &mut Bencher) { complex(   8, bencher); }
#[bench] fn complex_0016(bencher: &mut Bencher) { complex(  16, bencher); }
#[bench] fn complex_0032(bencher: &mut Bencher) { complex(  32, bencher); }
#[bench] fn complex_0064(bencher: &mut Bencher) { complex(  64, bencher); }
#[bench] fn complex_0128(bencher: &mut Bencher) { complex( 128, bencher); }
#[bench] fn complex_0256(bencher: &mut Bencher) { complex( 256, bencher); }
#[bench] fn complex_0512(bencher: &mut Bencher) { complex( 512, bencher); }
#[bench] fn complex_1024(bencher: &mut Bencher) { complex(1024, bencher); }
#[bench] fn complex_2048(bencher: &mut Bencher) { complex(2048, bencher); }
#[bench] fn complex_4096(bencher: &mut Bencher) { complex(4096, bencher); }
#[bench] fn complex_8192(bencher: &mut Bencher) { complex(8192, bencher); }

#[bench] fn real_0004(bencher: &mut Bencher) { real(   4, bencher); }
#[bench] fn real_0008(bencher: &mut Bencher) { real(   8, bencher); }
#[bench] fn real_0016(bencher: &mut Bencher) { real(  16, bencher); }
#[bench] fn real_0032(bencher: &mut Bencher) { real(  32, bencher); }
#[bench] fn real_0064(bencher: &mut Bencher) { real(  64, bencher); }
#[bench] fn real_0128(bencher: &mut Bencher) { real( 128, bencher); }
#[bench] fn real_0256(bencher: &mut Bencher) { real( 256, bencher); }
#[bench] fn real_0512(bencher: &mut Bencher) { real( 512, bencher); }
#[bench] fn real_1024(bencher: &mut Bencher) { real(1024, bencher); }
#[bench] fn real_2048(bencher: &mut Bencher) { real(2048, bencher); }
#[bench] fn real_4096(bencher: &mut Bencher) { real(4096, bencher); }
#[bench] fn real_8192(bencher: &mut Bencher) { real(8192, bencher); }

fn complex(size: usize, bencher: &mut Bencher) {
    let mut data = vec![c64::new(42.0, 69.0); size];
    let plan = Plan::new(Operation::Forward, size);
    bencher.bytes = (data.len() * mem::size_of::<c64>()) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}

fn real(size: usize, bencher: &mut Bencher) {
    let mut data = vec![42.0; 2 * size];
    let plan = Plan::new(Operation::Forward, 2 * size);
    bencher.bytes = (data.len() * mem::size_of::<f64>()) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}
<commit_msg>Inline a use<commit_after>#![feature(test)]

extern crate dft;
extern crate test;

use dft::{Operation, Plan, c64};
use test::{Bencher, black_box};

#[bench] fn complex_0004(bencher: &mut Bencher) { complex(   4, bencher); }
#[bench] fn complex_0008(bencher: &mut Bencher) { complex(   8, bencher); }
#[bench] fn complex_0016(bencher: &mut Bencher) { complex(  16, bencher); }
#[bench] fn complex_0032(bencher: &mut Bencher) { complex(  32, bencher); }
#[bench] fn complex_0064(bencher: &mut Bencher) { complex(  64, bencher); }
#[bench] fn complex_0128(bencher: &mut Bencher) { complex( 128, bencher); }
#[bench] fn complex_0256(bencher: &mut Bencher) { complex( 256, bencher); }
#[bench] fn complex_0512(bencher: &mut Bencher) { complex( 512, bencher); }
#[bench] fn complex_1024(bencher: &mut Bencher) { complex(1024, bencher); }
#[bench] fn complex_2048(bencher: &mut Bencher) { complex(2048, bencher); }
#[bench] fn complex_4096(bencher: &mut Bencher) { complex(4096, bencher); }
#[bench] fn complex_8192(bencher: &mut Bencher) { complex(8192, bencher); }

#[bench] fn real_0004(bencher: &mut Bencher) { real(   4, bencher); }
#[bench] fn real_0008(bencher: &mut Bencher) { real(   8, bencher); }
#[bench] fn real_0016(bencher: &mut Bencher) { real(  16, bencher); }
#[bench] fn real_0032(bencher: &mut Bencher) { real(  32, bencher); }
#[bench] fn real_0064(bencher: &mut Bencher) { real(  64, bencher); }
#[bench] fn real_0128(bencher: &mut Bencher) { real( 128, bencher); }
#[bench] fn real_0256(bencher: &mut Bencher) { real( 256, bencher); }
#[bench] fn real_0512(bencher: &mut Bencher) { real( 512, bencher); }
#[bench] fn real_1024(bencher: &mut Bencher) { real(1024, bencher); }
#[bench] fn real_2048(bencher: &mut Bencher) { real(2048, bencher); }
#[bench] fn real_4096(bencher: &mut Bencher) { real(4096, bencher); }
#[bench] fn real_8192(bencher: &mut Bencher) { real(8192, bencher); }

fn complex(size: usize, bencher: &mut Bencher) {
    let mut data = vec![c64::new(42.0, 69.0); size];
    let plan = Plan::new(Operation::Forward, size);
    bencher.bytes = (data.len() * std::mem::size_of::<c64>()) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}

fn real(size: usize, bencher: &mut Bencher) {
    let mut data = vec![42.0; 2 * size];
    let plan = Plan::new(Operation::Forward, 2 * size);
    bencher.bytes = (data.len() * std::mem::size_of::<f64>()) as u64;
    bencher.iter(|| black_box(dft::transform(&mut data, &plan)));
}
<|endoftext|>


<commit_before>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::sync::Arc;
use std::fmt::{self, Formatter, Display};

use uuid::Uuid;

use kvproto::metapb;
use kvproto::raftpb::ConfChangeType;
use kvproto::raft_cmdpb::{RaftCmdRequest, RaftCmdResponse, AdminRequest, AdminCmdType};
use kvproto::pdpb;

use util::worker::Runnable;
use util::escape;
use pd::PdClient;
use raftstore::store::{SendCh, Msg};
use raftstore::Result;

// Use an asynchronous thread to tell pd something.
pub enum Task {
    AskSplit {
        region: metapb::Region,
        split_key: Vec<u8>,
        peer: metapb::Peer,
    },
    Heartbeat {
        region: metapb::Region,
        peer: metapb::Peer,
    },
    StoreHeartbeat {
        stats: pdpb::StoreStats,
    },
}

impl Display for Task {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            Task::AskSplit { ref region, ref split_key, .. } => {
                write!(f,
                       "ask split region {} with key {}",
                       region.get_id(),
                       escape(&split_key))
            }
            Task::Heartbeat { ref region, ref peer } => {
                write!(f,
                       "heartbeat for region {:?}, leader {}",
                       region,
                       peer.get_id())
            }
            Task::StoreHeartbeat { ref stats } => write!(f, "store heartbeat stats: {:?}", stats),
        }
    }
}

pub struct Runner<T: PdClient> {
    pd_client: Arc<T>,
    ch: SendCh,
}

impl<T: PdClient> Runner<T> {
    pub fn new(pd_client: Arc<T>, ch: SendCh) -> Runner<T> {
        Runner {
            pd_client: pd_client,
            ch: ch,
        }
    }

    fn send_admin_request(&self,
                          mut region: metapb::Region,
                          peer: metapb::Peer,
                          request: AdminRequest) {
        let region_id = region.get_id();
        let cmd_type = request.get_cmd_type();

        let mut req = RaftCmdRequest::new();
        req.mut_header().set_region_id(region_id);
        req.mut_header().set_region_epoch(region.take_region_epoch());
        req.mut_header().set_peer(peer);
        req.mut_header().set_uuid(Uuid::new_v4().as_bytes().to_vec());

        req.set_admin_request(request);

        let cb = Box::new(move |_: RaftCmdResponse| -> Result<()> { Ok(()) });

        if let Err(e) = self.ch.send(Msg::RaftCmd {
            request: req,
            callback: cb,
        }) {
            error!("send {:?} request to region {} err {:?}",
                   cmd_type,
                   region_id,
                   e);
        }
    }
}

impl<T: PdClient> Runnable<Task> for Runner<T> {
    fn run(&mut self, task: Task) {
        debug!("executing task {}", task);

        match task {
            Task::AskSplit { region, split_key, peer } => {
                metric_incr!("pd.ask_split");
                if let Ok(mut resp) = self.pd_client.ask_split(region.clone()) {
                    metric_incr!("pd.ask_split.success");
                    info!("try to split with new region id {} for region {:?}",
                          resp.get_new_region_id(),
                          region);
                    let req = new_split_region_request(split_key,
                                                       resp.get_new_region_id(),
                                                       resp.take_new_peer_ids());
                    self.send_admin_request(region, peer, req);
                }
            }
            Task::Heartbeat { region, peer } => {
                metric_incr!("pd.heartbeat");
                // Now we use put region protocol for heartbeat.
                if let Ok(mut resp) = self.pd_client
                    .region_heartbeat(region.clone(), peer.clone()) {
                    metric_incr!("pd.heartbeat.success");
                    if resp.has_change_peer() {
                        metric_incr!("pd.heartbeat.change_peer");
                        let mut change_peer = resp.take_change_peer();
                        info!("try to change peer {:?} {:?} for region {:?}",
                              change_peer.get_change_type(),
                              change_peer.get_peer(),
                              region);
                        let req = new_change_peer_request(change_peer.get_change_type(),
                                                          change_peer.take_peer());
                        self.send_admin_request(region, peer, req);
                    } else if resp.has_transfer_leader() {
                        metric_incr!("pd.heartbeat.transfer_leader");
                        let mut transfer_leader = resp.take_transfer_leader();
                        info!("try to transfer leader from {:?} to {:?}",
                              peer,
                              transfer_leader.get_peer());
                        let req = new_transfer_leader_request(transfer_leader.take_peer());
                        self.send_admin_request(region, peer, req)
                    }
                }
            }
            Task::StoreHeartbeat { stats } => {
                if let Err(e) = self.pd_client.store_heartbeat(stats) {
                    error!("store heartbeat failed {:?}", e);
                }
            }
        };
    }
}

fn new_change_peer_request(change_type: ConfChangeType, peer: metapb::Peer) -> AdminRequest {
    let mut req = AdminRequest::new();
    req.set_cmd_type(AdminCmdType::ChangePeer);
    req.mut_change_peer().set_change_type(change_type);
    req.mut_change_peer().set_peer(peer);
    req
}

fn new_split_region_request(split_key: Vec<u8>,
                            new_region_id: u64,
                            peer_ids: Vec<u64>)
                            -> AdminRequest {
    let mut req = AdminRequest::new();
    req.set_cmd_type(AdminCmdType::Split);
    req.mut_split().set_split_key(split_key);
    req.mut_split().set_new_region_id(new_region_id);
    req.mut_split().set_new_peer_ids(peer_ids);
    req
}

fn new_transfer_leader_request(peer: metapb::Peer) -> AdminRequest {
    let mut req = AdminRequest::new();
    req.set_cmd_type(AdminCmdType::TransferLeader);
    req.mut_transfer_leader().set_peer(peer);
    req
}
<commit_msg>worker: make clippy happy. (#663)<commit_after>// Copyright 2016 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

use std::sync::Arc;
use std::fmt::{self, Formatter, Display};

use uuid::Uuid;

use kvproto::metapb;
use kvproto::raftpb::ConfChangeType;
use kvproto::raft_cmdpb::{RaftCmdRequest, RaftCmdResponse, AdminRequest, AdminCmdType};
use kvproto::pdpb;

use util::worker::Runnable;
use util::escape;
use pd::PdClient;
use raftstore::store::{SendCh, Msg};
use raftstore::Result;

// Use an asynchronous thread to tell pd something.
pub enum Task {
    AskSplit {
        region: metapb::Region,
        split_key: Vec<u8>,
        peer: metapb::Peer,
    },
    Heartbeat {
        region: metapb::Region,
        peer: metapb::Peer,
    },
    StoreHeartbeat {
        stats: pdpb::StoreStats,
    },
}

impl Display for Task {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            Task::AskSplit { ref region, ref split_key, .. } => {
                write!(f,
                       "ask split region {} with key {}",
                       region.get_id(),
                       escape(&split_key))
            }
            Task::Heartbeat { ref region, ref peer } => {
                write!(f,
                       "heartbeat for region {:?}, leader {}",
                       region,
                       peer.get_id())
            }
            Task::StoreHeartbeat { ref stats } => write!(f, "store heartbeat stats: {:?}", stats),
        }
    }
}

pub struct Runner<T: PdClient> {
    pd_client: Arc<T>,
    ch: SendCh,
}

impl<T: PdClient> Runner<T> {
    pub fn new(pd_client: Arc<T>, ch: SendCh) -> Runner<T> {
        Runner {
            pd_client: pd_client,
            ch: ch,
        }
    }

    fn send_admin_request(&self,
                          mut region: metapb::Region,
                          peer: metapb::Peer,
                          request: AdminRequest) {
        let region_id = region.get_id();
        let cmd_type = request.get_cmd_type();

        let mut req = RaftCmdRequest::new();
        req.mut_header().set_region_id(region_id);
        req.mut_header().set_region_epoch(region.take_region_epoch());
        req.mut_header().set_peer(peer);
        req.mut_header().set_uuid(Uuid::new_v4().as_bytes().to_vec());

        req.set_admin_request(request);

        let cb = Box::new(move |_: RaftCmdResponse| -> Result<()> { Ok(()) });

        if let Err(e) = self.ch.send(Msg::RaftCmd {
            request: req,
            callback: cb,
        }) {
            error!("send {:?} request to region {} err {:?}",
                   cmd_type,
                   region_id,
                   e);
        }
    }

    fn handle_ask_split(&self, region: metapb::Region, split_key: Vec<u8>, peer: metapb::Peer) {
        metric_incr!("pd.ask_split");
        if let Ok(mut resp) = self.pd_client.ask_split(region.clone()) {
            metric_incr!("pd.ask_split.success");
            info!("try to split with new region id {} for region {:?}",
                  resp.get_new_region_id(),
                  region);
            let req = new_split_region_request(split_key,
                                               resp.get_new_region_id(),
                                               resp.take_new_peer_ids());
            self.send_admin_request(region, peer, req);
        }
    }

    fn handle_heartbeat(&self, region: metapb::Region, peer: metapb::Peer) {
        metric_incr!("pd.heartbeat");
        // Now we use put region protocol for heartbeat.
        if let Ok(mut resp) = self.pd_client
            .region_heartbeat(region.clone(), peer.clone()) {
            metric_incr!("pd.heartbeat.success");
            if resp.has_change_peer() {
                metric_incr!("pd.heartbeat.change_peer");
                let mut change_peer = resp.take_change_peer();
                info!("try to change peer {:?} {:?} for region {:?}",
                      change_peer.get_change_type(),
                      change_peer.get_peer(),
                      region);
                let req = new_change_peer_request(change_peer.get_change_type(),
                                                  change_peer.take_peer());
                self.send_admin_request(region, peer, req);
            } else if resp.has_transfer_leader() {
                metric_incr!("pd.heartbeat.transfer_leader");
                let mut transfer_leader = resp.take_transfer_leader();
                info!("try to transfer leader from {:?} to {:?}",
                      peer,
                      transfer_leader.get_peer());
                let req = new_transfer_leader_request(transfer_leader.take_peer());
                self.send_admin_request(region, peer, req)
            }
        }
    }

    fn handle_store_heartbeat(&self, stats: pdpb::StoreStats) {
        if let Err(e) = self.pd_client.store_heartbeat(stats) {
            error!("store heartbeat failed {:?}", e);
        }
    }
}

impl<T: PdClient> Runnable<Task> for Runner<T> {
    fn run(&mut self, task: Task) {
        debug!("executing task {}", task);

        match task {
            Task::AskSplit { region, split_key, peer } => {
                self.handle_ask_split(region, split_key, peer)
            }
            Task::Heartbeat { region, peer } => self.handle_heartbeat(region, peer),
            Task::StoreHeartbeat { stats } => self.handle_store_heartbeat(stats),
        };
    }
}

fn new_change_peer_request(change_type: ConfChangeType, peer: metapb::Peer) -> AdminRequest {
    let mut req = AdminRequest::new();
    req.set_cmd_type(AdminCmdType::ChangePeer);
    req.mut_change_peer().set_change_type(change_type);
    req.mut_change_peer().set_peer(peer);
    req
}

fn new_split_region_request(split_key: Vec<u8>,
                            new_region_id: u64,
                            peer_ids: Vec<u64>)
                            -> AdminRequest {
    let mut req = AdminRequest::new();
    req.set_cmd_type(AdminCmdType::Split);
    req.mut_split().set_split_key(split_key);
    req.mut_split().set_new_region_id(new_region_id);
    req.mut_split().set_new_peer_ids(peer_ids);
    req
}

fn new_transfer_leader_request(peer: metapb::Peer) -> AdminRequest {
    let mut req = AdminRequest::new();
    req.set_cmd_type(AdminCmdType::TransferLeader);
    req.mut_transfer_leader().set_peer(peer);
    req
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-2018 Alex Maslakov, <gildedhonour.com>, <alexmaslakov.me>
 *
 * 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.
 *
 * For questions and comments about this product, please see the project page at:
 *
 * https://github.com/GildedHonour/frank_jwt
 *
 */

use std::io::Error as IoError;
use serde_json::Error as SJError;
use openssl::error::ErrorStack;
use base64::DecodeError as B64Error;

macro_rules! impl_error {
    ($from:ty, $to:path) => {
        impl From<$from> for Error {
            fn from(e: $from) -> Self {
                $to(format!("{:?}", e))
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Error {
    SignatureExpired,
    SignatureInvalid,
    JWTInvalid,
    IssuerInvalid,
    ExpirationInvalid,
    AudienceInvalid,
    FormatInvalid(String),
    IoError(String),
    OpenSslError(String),
    ProtocolError(String),
}

impl_error!{IoError, Error::IoError}
impl_error!{SJError, Error::FormatInvalid}
impl_error!{ErrorStack, Error::OpenSslError}
impl_error!{B64Error, Error::ProtocolError}
<commit_msg>Added std::error::Error impl for jwt error<commit_after>/**
 * Copyright (c) 2015-2018 Alex Maslakov, <gildedhonour.com>, <alexmaslakov.me>
 *
 * 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.
 *
 * For questions and comments about this product, please see the project page at:
 *
 * https://github.com/GildedHonour/frank_jwt
 *
 */

use std::io::Error as IoError;
use serde_json::Error as SJError;
use openssl::error::ErrorStack;
use base64::DecodeError as B64Error;
use std::error;
use std::fmt;

macro_rules! impl_error {
    ($from:ty, $to:path) => {
        impl From<$from> for Error {
            fn from(e: $from) -> Self {
                $to(format!("{:?}", e))
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Error {
    SignatureExpired,
    SignatureInvalid,
    JWTInvalid,
    IssuerInvalid,
    ExpirationInvalid,
    AudienceInvalid,
    FormatInvalid(String),
    IoError(String),
    OpenSslError(String),
    ProtocolError(String),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Error::SignatureExpired => write!(f, "Signature expired."),
            Error::SignatureInvalid => write!(f, "Signature invalid."),
            Error::JWTInvalid => write!(f, "JWT invalid."),
            Error::IssuerInvalid => write!(f, "Issuer invalid."),
            Error::ExpirationInvalid => write!(f, "Expiration invalid."),
            Error::AudienceInvalid => write!(f, "Audience invalid."),
            Error::FormatInvalid(msg) => write!(f, "Format invalid: {}.", msg),
            Error::IoError(msg) => write!(f, "Format invalid: {}.", msg),
            Error::OpenSslError(msg) => write!(f, "Format invalid: {}.", msg),
            Error::ProtocolError(msg) => write!(f, "Format invalid: {}.", msg),
        }
    }
}

impl error::Error for Error {}

impl_error!{IoError, Error::IoError}
impl_error!{SJError, Error::FormatInvalid}
impl_error!{ErrorStack, Error::OpenSslError}
impl_error!{B64Error, Error::ProtocolError}
<|endoftext|>


<commit_before>use ffi::h5::herr_t;
use ffi::h5e::{H5Ewalk2, H5Eget_msg, H5E_error2_t, H5Eset_auto2, H5Eget_current_stack,
               H5Eclose_stack, H5E_WALK_DOWNWARD, H5E_DEFAULT};

use util::{get_h5_str, string_from_cstr};

use std::ptr;
use std::fmt;
use std::ops::Index;
use std::error::Error as BaseError;

use libc::{c_uint, c_void};
use num::{Integer, Zero, Bounded};

pub struct ErrorFrame {
    desc: String,
    func: String,
    major: String,
    minor: String,
    description: String,
}

impl ErrorFrame {
    pub fn new<S1, S2, S3, S4>(desc: S1, func: S2, major: S3, minor: S4) -> ErrorFrame
              where S1: Into<String>, S2: Into<String>, S3: Into<String>, S4: Into<String> {
        let (s_func, s_desc) = (func.into(), desc.into());
        let description = format!("{}(): {}", s_func.clone(), s_desc.clone());
        ErrorFrame {
            desc: s_desc,
            func: s_func,
            major: major.into(),
            minor: minor.into(),
            description: description,
        }
    }

    pub fn description(&self) -> &str {
        self.description.as_ref()
    }

    pub fn detail(&self) -> Option<String> {
        Some(format!("Error in {}(): {} [{}: {}]",
             self.func, self.desc, self.major, self.minor).clone())
    }
}

pub fn silence_errors() {
    h5lock!(H5Eset_auto2(H5E_DEFAULT, None, ptr::null_mut()));
}

pub struct ErrorStack {
    frames: Vec<ErrorFrame>
}

impl Index<usize> for ErrorStack {
    type Output = ErrorFrame;

    fn index<'a>(&'a self, index: usize) -> &'a ErrorFrame {
        &self.frames[index]
    }
}

impl ErrorStack {
    // This low-level function is not thread-safe and has to be synchronized by the user
    pub fn query() -> Result<Option<ErrorStack>> {
        struct CallbackData {
            stack: ErrorStack,
            err: Option<Error>,
        }

        extern fn callback(_: c_uint, err_desc: *const H5E_error2_t, data: *mut c_void) -> herr_t {
            unsafe {
                let data = &mut *(data as *mut CallbackData);
                if data.err.is_some() {
                    return 0;
                }
                let closure = |e: H5E_error2_t| -> Result<ErrorFrame> {
                    let (desc, func) = (string_from_cstr(e.desc), string_from_cstr(e.func_name));
                    let major = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.maj_num, ptr::null_mut(), m, s)
                    }));
                    let minor = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.min_num, ptr::null_mut(), m, s)
                    }));
                    Ok(ErrorFrame::new(desc, func, major, minor))
                };
                match closure(*err_desc) {
                    Ok(frame) => { data.stack.push(frame); 0 },
                    Err(err)  => { data.err = Some(From::from(err)); 0 }
                }
            }
        }

        let mut data = CallbackData { stack: ErrorStack::new(), err: None };
        let data_ptr: *mut c_void = &mut data as *mut _ as *mut c_void;

        // known HDF5 bug: H5Eget_msg() may corrupt the current stack, so we copy it first
        unsafe {
            let stack_id = H5Eget_current_stack();
            ensure!(stack_id >= 0, "failed to copy the current error stack");
            H5Ewalk2(stack_id, H5E_WALK_DOWNWARD, Some(callback), data_ptr);
            H5Eclose_stack(stack_id)
        };

        match (data.err, data.stack.is_empty()) {
            (Some(err), _) => Err(err),
            (None, false)  => Ok(Some(data.stack)),
            (None, true)   => Ok(None),
        }
    }

    pub fn new() -> ErrorStack {
        ErrorStack { frames: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.frames.len()
    }

    pub fn push(&mut self, frame: ErrorFrame) {
        self.frames.push(frame)
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn top(&self) -> Option<&ErrorFrame> {
        match !self.is_empty() {
            false => None,
            true  => Some(&self.frames[0]),
        }
    }

    pub fn description(&self) -> &str {
        match self.top() {
            None        => "unknown library error",
            Some(frame) => frame.description(),
        }
    }

    pub fn detail(&self) -> Option<String> {
        match self.top() {
            None        => None,
            Some(frame) => frame.detail(),
        }
    }
}

pub enum Error {
    LibraryError(ErrorStack),
    InternalError(String),
}

pub type Result<T> = ::std::result::Result<T, Error>;

impl Error {
    pub fn query() -> Option<Error> {
        match ErrorStack::query() {
            Err(err)        => Some(From::from(err)),
            Ok(Some(stack)) => Some(Error::LibraryError(stack)),
            Ok(None)        => None,
        }
    }

    pub fn description(&self) -> &str {
        match *self {
            Error::InternalError(ref desc) => desc.as_ref(),
            Error::LibraryError(ref stack) => stack.description(),
        }
    }
}

impl<S> From<S> for Error where S: Into<String> {
    fn from(desc: S) -> Error {
        Error::InternalError(desc.into())
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            Error::InternalError(ref desc) => desc.fmt(formatter),
            Error::LibraryError(ref stack) => stack.detail().fmt(formatter),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        self.description().fmt(formatter)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        self.description()
    }
}

pub fn h5check<T>(value: T) -> Result<T> where T: Integer + Zero + Bounded,
{
    let min_value: T = Bounded::min_value();
    let zero:      T = Zero::zero();

    let maybe_error = if min_value < zero {
        value < zero
    } else {
        value == zero
    };

    match maybe_error {
        false => Ok(value),
        true  => match Error::query() {
            None       => Ok(value),
            Some(err)  => Err(From::from(err)),
        },
    }
}

#[cfg(test)]
mod tests {
    use ffi::h5::herr_t;
    use ffi::h5p::{H5Pcreate, H5Pclose};
    use globals::H5P_ROOT;
    use super::{ErrorStack, Result, silence_errors};

    #[test]
    pub fn test_error_stack() {
        silence_errors();

        let result_no_error = h5lock!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            ErrorStack::query()
        });
        assert!(result_no_error.ok().unwrap().is_none());

        let result_error = h5lock!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            H5Pclose(plist_id);
            ErrorStack::query()
        });
        let stack = result_error.ok().unwrap().unwrap();
        assert_eq!(stack.description(), "H5Pclose(): can't close");
        assert_eq!(&stack.detail().unwrap(),
                   "Error in H5Pclose(): can't close [Property lists: Unable to free object]");

        assert_eq!(stack.len(), 3);
        assert!(!stack.is_empty());

        assert_eq!(stack[0].description(), "H5Pclose(): can't close");
        assert_eq!(&stack[0].detail().unwrap(),
                   "Error in H5Pclose(): can't close \
                    [Property lists: Unable to free object]");

        assert_eq!(stack[1].description(), "H5I_dec_app_ref(): can't decrement ID ref count");
        assert_eq!(&stack[1].detail().unwrap(),
                   "Error in H5I_dec_app_ref(): can't decrement ID ref count \
                    [Object atom: Unable to decrement reference count]");

        assert_eq!(stack[2].description(), "H5I_dec_ref(): can't locate ID");
        assert_eq!(&stack[2].detail().unwrap(),
                   "Error in H5I_dec_ref(): can't locate ID \
                    [Object atom: Unable to find atom information (already closed?)]");

        let empty_stack = ErrorStack::new();
        assert!(empty_stack.is_empty());
        assert_eq!(empty_stack.len(), 0);
    }

    #[test]
    pub fn test_h5call() {
        silence_errors();

        let result_no_error = h5call!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id)
        });
        assert!(result_no_error.is_ok());

        let result_error = h5call!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            H5Pclose(plist_id)
        });
        assert!(result_error.is_err());
    }

    #[test]
    pub fn test_h5try() {
        silence_errors();

        fn f1() -> Result<herr_t> {
            let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
            h5try!(H5Pclose(plist_id));
            Ok(100)
        }

        let result1 = f1();
        assert!(result1.is_ok());
        assert_eq!(result1.ok().unwrap(), 100);

        fn f2() -> Result<herr_t> {
            let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
            h5try!(H5Pclose(plist_id));
            h5try!(H5Pclose(plist_id));
            Ok(100)
        }

        let result2 = f2();
        assert!(result2.is_err());
    }
}
<commit_msg>Fix a flaky error stack test (works differently on different HDF5 versions)<commit_after>use ffi::h5::herr_t;
use ffi::h5e::{H5Ewalk2, H5Eget_msg, H5E_error2_t, H5Eset_auto2, H5Eget_current_stack,
               H5Eclose_stack, H5E_WALK_DOWNWARD, H5E_DEFAULT};

use util::{get_h5_str, string_from_cstr};

use std::ptr;
use std::fmt;
use std::ops::Index;
use std::error::Error as BaseError;

use libc::{c_uint, c_void};
use num::{Integer, Zero, Bounded};

pub struct ErrorFrame {
    desc: String,
    func: String,
    major: String,
    minor: String,
    description: String,
}

impl ErrorFrame {
    pub fn new<S1, S2, S3, S4>(desc: S1, func: S2, major: S3, minor: S4) -> ErrorFrame
              where S1: Into<String>, S2: Into<String>, S3: Into<String>, S4: Into<String> {
        let (s_func, s_desc) = (func.into(), desc.into());
        let description = format!("{}(): {}", s_func.clone(), s_desc.clone());
        ErrorFrame {
            desc: s_desc,
            func: s_func,
            major: major.into(),
            minor: minor.into(),
            description: description,
        }
    }

    pub fn description(&self) -> &str {
        self.description.as_ref()
    }

    pub fn detail(&self) -> Option<String> {
        Some(format!("Error in {}(): {} [{}: {}]",
             self.func, self.desc, self.major, self.minor).clone())
    }
}

pub fn silence_errors() {
    h5lock!(H5Eset_auto2(H5E_DEFAULT, None, ptr::null_mut()));
}

pub struct ErrorStack {
    frames: Vec<ErrorFrame>
}

impl Index<usize> for ErrorStack {
    type Output = ErrorFrame;

    fn index<'a>(&'a self, index: usize) -> &'a ErrorFrame {
        &self.frames[index]
    }
}

impl ErrorStack {
    // This low-level function is not thread-safe and has to be synchronized by the user
    pub fn query() -> Result<Option<ErrorStack>> {
        struct CallbackData {
            stack: ErrorStack,
            err: Option<Error>,
        }

        extern fn callback(_: c_uint, err_desc: *const H5E_error2_t, data: *mut c_void) -> herr_t {
            unsafe {
                let data = &mut *(data as *mut CallbackData);
                if data.err.is_some() {
                    return 0;
                }
                let closure = |e: H5E_error2_t| -> Result<ErrorFrame> {
                    let (desc, func) = (string_from_cstr(e.desc), string_from_cstr(e.func_name));
                    let major = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.maj_num, ptr::null_mut(), m, s)
                    }));
                    let minor = try!(get_h5_str(|m, s| {
                        H5Eget_msg(e.min_num, ptr::null_mut(), m, s)
                    }));
                    Ok(ErrorFrame::new(desc, func, major, minor))
                };
                match closure(*err_desc) {
                    Ok(frame) => { data.stack.push(frame); 0 },
                    Err(err)  => { data.err = Some(From::from(err)); 0 }
                }
            }
        }

        let mut data = CallbackData { stack: ErrorStack::new(), err: None };
        let data_ptr: *mut c_void = &mut data as *mut _ as *mut c_void;

        // known HDF5 bug: H5Eget_msg() may corrupt the current stack, so we copy it first
        unsafe {
            let stack_id = H5Eget_current_stack();
            ensure!(stack_id >= 0, "failed to copy the current error stack");
            H5Ewalk2(stack_id, H5E_WALK_DOWNWARD, Some(callback), data_ptr);
            H5Eclose_stack(stack_id)
        };

        match (data.err, data.stack.is_empty()) {
            (Some(err), _) => Err(err),
            (None, false)  => Ok(Some(data.stack)),
            (None, true)   => Ok(None),
        }
    }

    pub fn new() -> ErrorStack {
        ErrorStack { frames: Vec::new() }
    }

    pub fn len(&self) -> usize {
        self.frames.len()
    }

    pub fn push(&mut self, frame: ErrorFrame) {
        self.frames.push(frame)
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn top(&self) -> Option<&ErrorFrame> {
        match !self.is_empty() {
            false => None,
            true  => Some(&self.frames[0]),
        }
    }

    pub fn description(&self) -> &str {
        match self.top() {
            None        => "unknown library error",
            Some(frame) => frame.description(),
        }
    }

    pub fn detail(&self) -> Option<String> {
        match self.top() {
            None        => None,
            Some(frame) => frame.detail(),
        }
    }
}

pub enum Error {
    LibraryError(ErrorStack),
    InternalError(String),
}

pub type Result<T> = ::std::result::Result<T, Error>;

impl Error {
    pub fn query() -> Option<Error> {
        match ErrorStack::query() {
            Err(err)        => Some(From::from(err)),
            Ok(Some(stack)) => Some(Error::LibraryError(stack)),
            Ok(None)        => None,
        }
    }

    pub fn description(&self) -> &str {
        match *self {
            Error::InternalError(ref desc) => desc.as_ref(),
            Error::LibraryError(ref stack) => stack.description(),
        }
    }
}

impl<S> From<S> for Error where S: Into<String> {
    fn from(desc: S) -> Error {
        Error::InternalError(desc.into())
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        match *self {
            Error::InternalError(ref desc) => desc.fmt(formatter),
            Error::LibraryError(ref stack) => stack.detail().fmt(formatter),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> ::std::result::Result<(), fmt::Error> {
        self.description().fmt(formatter)
    }
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        self.description()
    }
}

pub fn h5check<T>(value: T) -> Result<T> where T: Integer + Zero + Bounded,
{
    let min_value: T = Bounded::min_value();
    let zero:      T = Zero::zero();

    let maybe_error = if min_value < zero {
        value < zero
    } else {
        value == zero
    };

    match maybe_error {
        false => Ok(value),
        true  => match Error::query() {
            None       => Ok(value),
            Some(err)  => Err(From::from(err)),
        },
    }
}

#[cfg(test)]
mod tests {
    use ffi::h5::herr_t;
    use ffi::h5p::{H5Pcreate, H5Pclose};
    use globals::H5P_ROOT;
    use super::{ErrorStack, Result, silence_errors};

    #[test]
    pub fn test_error_stack() {
        silence_errors();

        let result_no_error = h5lock!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            ErrorStack::query()
        });
        assert!(result_no_error.ok().unwrap().is_none());

        let result_error = h5lock!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            H5Pclose(plist_id);
            ErrorStack::query()
        });
        let stack = result_error.ok().unwrap().unwrap();
        assert_eq!(stack.description(), "H5Pclose(): can't close");
        assert_eq!(&stack.detail().unwrap(),
                   "Error in H5Pclose(): can't close [Property lists: Unable to free object]");

        assert!(stack.len() >= 2 && stack.len() <= 3); // depending on HDF5 version
        assert!(!stack.is_empty());

        assert_eq!(stack[0].description(), "H5Pclose(): can't close");
        assert_eq!(&stack[0].detail().unwrap(),
                   "Error in H5Pclose(): can't close \
                    [Property lists: Unable to free object]");

        assert_eq!(stack[stack.len() - 1].description(), "H5I_dec_ref(): can't locate ID");
        assert_eq!(&stack[stack.len() - 1].detail().unwrap(),
                   "Error in H5I_dec_ref(): can't locate ID \
                    [Object atom: Unable to find atom information (already closed?)]");

        let empty_stack = ErrorStack::new();
        assert!(empty_stack.is_empty());
        assert_eq!(empty_stack.len(), 0);
    }

    #[test]
    pub fn test_h5call() {
        silence_errors();

        let result_no_error = h5call!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id)
        });
        assert!(result_no_error.is_ok());

        let result_error = h5call!({
            let plist_id = H5Pcreate(*H5P_ROOT);
            H5Pclose(plist_id);
            H5Pclose(plist_id)
        });
        assert!(result_error.is_err());
    }

    #[test]
    pub fn test_h5try() {
        silence_errors();

        fn f1() -> Result<herr_t> {
            let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
            h5try!(H5Pclose(plist_id));
            Ok(100)
        }

        let result1 = f1();
        assert!(result1.is_ok());
        assert_eq!(result1.ok().unwrap(), 100);

        fn f2() -> Result<herr_t> {
            let plist_id = h5try!(H5Pcreate(*H5P_ROOT));
            h5try!(H5Pclose(plist_id));
            h5try!(H5Pclose(plist_id));
            Ok(100)
        }

        let result2 = f2();
        assert!(result2.is_err());
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;

use std::io;
use std::string;

pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Debug)]
pub struct Error {
    pos: u64,
    kind: ErrorKind,
}

impl Error {
    pub fn new<K: Into<ErrorKind>>(pos: u64, kind: K) -> Self {
        Error {
            pos: pos,
            kind: kind.into(),
        }
    }
}

#[derive(Debug)]
pub enum ErrorKind {
    FromUtf8Error(string::FromUtf8Error),
    InvalidMagic,
    Io(io::Error),
    UnexpectedEof,
    Unimplemented(String),
}

impl From<string::FromUtf8Error> for ErrorKind {
    fn from(err: string::FromUtf8Error) -> ErrorKind {
        ErrorKind::FromUtf8Error(err)
    }
}

impl From<io::Error> for ErrorKind {
    fn from(err: io::Error) -> ErrorKind {
        ErrorKind::Io(err)
    }
}

impl From<byteorder::Error> for ErrorKind {
    fn from(err: byteorder::Error) -> ErrorKind {
        match err {
            byteorder::Error::UnexpectedEOF => ErrorKind::UnexpectedEof,
            byteorder::Error::Io(err) => ErrorKind::Io(err),
        }
    }
}
<commit_msg>Add error kind to represent "invalid data" error<commit_after>extern crate byteorder;

use std::io;
use std::string;

pub type Result<T> = ::std::result::Result<T, Error>;

#[derive(Debug)]
pub struct Error {
    pos: u64,
    kind: ErrorKind,
}

impl Error {
    pub fn new<K: Into<ErrorKind>>(pos: u64, kind: K) -> Self {
        Error {
            pos: pos,
            kind: kind.into(),
        }
    }
}

#[derive(Debug)]
pub enum ErrorKind {
    FromUtf8Error(string::FromUtf8Error),
    InvalidMagic,
    Io(io::Error),
    DataError(String),
    UnexpectedEof,
    Unimplemented(String),
}

impl From<string::FromUtf8Error> for ErrorKind {
    fn from(err: string::FromUtf8Error) -> ErrorKind {
        ErrorKind::FromUtf8Error(err)
    }
}

impl From<io::Error> for ErrorKind {
    fn from(err: io::Error) -> ErrorKind {
        ErrorKind::Io(err)
    }
}

impl From<byteorder::Error> for ErrorKind {
    fn from(err: byteorder::Error) -> ErrorKind {
        match err {
            byteorder::Error::UnexpectedEOF => ErrorKind::UnexpectedEof,
            byteorder::Error::Io(err) => ErrorKind::Io(err),
        }
    }
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]

use std::collections::HashMap;
use ast::{Atom, Expr, Env, Symbol};
use error::*;

type Form = Fn(&[Expr], &mut Env) -> Result<Expr> + Sync;

lazy_static! {
    static ref SPECIAL_FORMS: HashMap<String, Box<Form>> = {
        let mut forms = HashMap::<String, Box<Form>>::new();
        forms.insert("def".into(), Box::new(def_form));
        forms.insert("if".into(), Box::new(if_form));
        forms.insert("let".into(), Box::new(let_form));
        forms.insert("do".into(), Box::new(do_form));
        forms.insert("fn".into(), Box::new(fn_form));
        forms.insert("quote".into(), Box::new(quote_form));
        forms
    };
}

pub fn is_special_form(form: &Symbol) -> bool {
    SPECIAL_FORMS.contains_key(&form.0)
}

pub fn eval(form: &Symbol, args: &[Expr], env: &mut Env) -> Result<Expr> {
    assert!(is_special_form(form));
    (SPECIAL_FORMS.get(&form.0))
        .ok_or("did not find special form".into())
        .and_then(|f| (f)(args, env))
}

fn def_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    if args.len() != 2 {
        return Err("#[def] expected 2 arguments".into());
    }

    if let Expr::Atom(Atom::Sym(ref sym)) = args[0] {
        env.define(&sym.0, args[1].clone());
        Ok(Expr::Nil)
    } else {
        Err("#[def] expected symbol".into())
    }
}

fn if_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    if args.len() == 2 {
        if args[0].eval(env)?.truthiness() {
            args[1].eval(env)
        } else {
            Ok(Expr::Nil)
        }
    } else if args.len() == 3 {
        if args[0].eval(env)?.truthiness() {
            args[1].eval(env)
        } else {
            args[2].eval(env)
        }
    } else {
        Err("#[if] expected body clause".into())
    }
}

fn let_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    unimplemented!()
}

fn do_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    unimplemented!()
}

fn quote_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    unimplemented!()
}

fn fn_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    unimplemented!()
}
<commit_msg>Implement do form<commit_after>#![allow(unused_variables)]

use std::collections::HashMap;
use ast::{Atom, Expr, Env, Symbol};
use itertools::Itertools;
use error::*;

type Form = Fn(&[Expr], &mut Env) -> Result<Expr> + Sync;

lazy_static! {
    static ref SPECIAL_FORMS: HashMap<String, Box<Form>> = {
        let mut forms = HashMap::<String, Box<Form>>::new();
        forms.insert("def".into(), Box::new(def_form));
        forms.insert("if".into(), Box::new(if_form));
        forms.insert("let".into(), Box::new(let_form));
        forms.insert("do".into(), Box::new(do_form));
        forms.insert("fn".into(), Box::new(fn_form));
        forms.insert("quote".into(), Box::new(quote_form));
        forms
    };
}

pub fn is_special_form(form: &Symbol) -> bool {
    SPECIAL_FORMS.contains_key(&form.0)
}

pub fn eval(form: &Symbol, args: &[Expr], env: &mut Env) -> Result<Expr> {
    assert!(is_special_form(form));
    (SPECIAL_FORMS.get(&form.0))
        .ok_or("did not find special form".into())
        .and_then(|f| (f)(args, env))
}

fn def_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    if args.len() != 2 {
        return Err("#[def] expected 2 arguments".into());
    }

    if let Expr::Atom(Atom::Sym(ref sym)) = args[0] {
        env.define(&sym.0, args[1].clone());
        Ok(Expr::Nil)
    } else {
        Err("#[def] expected symbol".into())
    }
}

fn if_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    if args.len() == 2 {
        if args[0].eval(env)?.truthiness() {
            args[1].eval(env)
        } else {
            Ok(Expr::Nil)
        }
    } else if args.len() == 3 {
        if args[0].eval(env)?.truthiness() {
            args[1].eval(env)
        } else {
            args[2].eval(env)
        }
    } else {
        Err("#[if] expected body clause".into())
    }
}

fn let_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    unimplemented!()
}

fn do_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    match args.split_last() {
        Some((last, rest)) => {
            for arg in rest {
                arg.eval(env)?;
            }
            last.eval(env)
        }
        None => Ok(Expr::Nil),
    }
}

fn quote_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    unimplemented!()
}

fn fn_form(args: &[Expr], env: &mut Env) -> Result<Expr> {
    unimplemented!()
}
<|endoftext|>


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

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

#![cfg(not(test))]
#![deny(warnings)]

extern crate cargo_metadata;
extern crate getopts;
extern crate serde_json as json;

use std::env;
use std::fs;
use std::hash::{Hash, Hasher};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::str;
use std::collections::HashSet;
use std::iter::FromIterator;

use getopts::{Matches, Options};

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

const SUCCESS: i32 = 0;
const FAILURE: i32 = 1;

fn execute() -> i32 {
    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("q", "quiet", "no output printed to stdout");
    opts.optflag("v", "verbose", "use verbose output");
    opts.optmulti(
        "p",
        "package",
        "specify package to format (only usable in workspaces)",
        "<package>",
    );
    opts.optflag("", "version", "print rustfmt version and exit");
    opts.optflag("", "all", "format all packages (only usable in workspaces)");

    // If there is any invalid argument passed to `cargo fmt`, return without formatting.
    let mut is_package_arg = false;
    for arg in env::args().skip(2).take_while(|a| a != "--") {
        if arg.starts_with('-') {
            is_package_arg = arg.starts_with("--package");
        } else if !is_package_arg {
            print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg));
            return FAILURE;
        } else {
            is_package_arg = false;
        }
    }

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

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

    if matches.opt_present("h") {
        print_usage_to_stdout(&opts, "");
        return SUCCESS;
    }

    if matches.opt_present("version") {
        return handle_command_status(get_version(), &opts);
    }

    let strategy = CargoFmtStrategy::from_matches(&matches);

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

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

fn print_usage_to_stdout(opts: &Options, reason: &str) {
    print_usage!(println, opts, reason);
}

fn print_usage_to_stderr(opts: &Options, reason: &str) {
    print_usage!(eprintln, opts, reason);
}

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

fn handle_command_status(status: Result<ExitStatus, io::Error>, opts: &getopts::Options) -> i32 {
    match status {
        Err(e) => {
            print_usage_to_stderr(&opts, &e.to_string());
            FAILURE
        }
        Ok(status) => {
            if status.success() {
                SUCCESS
            } else {
                status.code().unwrap_or(FAILURE)
            }
        }
    }
}

fn get_version() -> Result<ExitStatus, io::Error> {
    let mut command = Command::new("rustfmt")
        .args(vec!["--version"])
        .spawn()
        .map_err(|e| match e.kind() {
            io::ErrorKind::NotFound => io::Error::new(
                io::ErrorKind::Other,
                "Could not run rustfmt, please make sure it is in your PATH.",
            ),
            _ => e,
        })?;

    command.wait()
}

fn format_crate(
    verbosity: Verbosity,
    strategy: &CargoFmtStrategy,
) -> Result<ExitStatus, io::Error> {
    let rustfmt_args = get_fmt_args();
    let targets = if rustfmt_args.iter().any(|s| s == "--dump-default-config") {
        HashSet::new()
    } else {
        get_targets(strategy)?
    };

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

    format_files(&files, &rustfmt_args, verbosity)
}

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

/// Target uses a `path` field for equality and hashing.
#[derive(Debug)]
pub struct Target {
    /// A path to the main source file of the target.
    path: PathBuf,
    /// A kind of target (e.g. lib, bin, example, ...).
    kind: String,
}

impl Target {
    pub fn from_target(target: &cargo_metadata::Target) -> Self {
        let path = PathBuf::from(&target.src_path);
        let canonicalized = fs::canonicalize(&path).unwrap_or(path);

        Target {
            path: canonicalized,
            kind: target.kind[0].clone(),
        }
    }
}

impl PartialEq for Target {
    fn eq(&self, other: &Target) -> bool {
        self.path == other.path
    }
}

impl Eq for Target {}

impl Hash for Target {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.path.hash(state);
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum CargoFmtStrategy {
    /// Format every packages and dependencies.
    All,
    /// Format pacakges that are specified by the command line argument.
    Some(Vec<String>),
    /// Format the root packages only.
    Root,
}

impl CargoFmtStrategy {
    pub fn from_matches(matches: &Matches) -> CargoFmtStrategy {
        match (matches.opt_present("all"), matches.opt_present("p")) {
            (false, false) => CargoFmtStrategy::Root,
            (true, _) => CargoFmtStrategy::All,
            (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")),
        }
    }
}

/// Based on the specified `CargoFmtStrategy`, returns a set of main source files.
fn get_targets(strategy: &CargoFmtStrategy) -> Result<HashSet<Target>, io::Error> {
    let mut targets = HashSet::new();

    match *strategy {
        CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?,
        CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?,
        CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?,
    }

    if targets.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "Failed to find targets".to_owned(),
        ))
    } else {
        Ok(targets)
    }
}

fn get_targets_root_only(targets: &mut HashSet<Target>) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    for package in metadata.packages {
        for target in package.targets {
            if target.name == package.name {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    Ok(())
}

fn get_targets_recursive(
    manifest_path: Option<&Path>,
    mut targets: &mut HashSet<Target>,
    visited: &mut HashSet<String>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(manifest_path)?;

    for package in metadata.packages {
        add_targets(&package.targets, &mut targets);

        // Look for local dependencies.
        for dependency in package.dependencies {
            if dependency.source.is_some() || visited.contains(&dependency.name) {
                continue;
            }

            let mut manifest_path = PathBuf::from(&package.manifest_path);

            manifest_path.pop();
            manifest_path.push(&dependency.name);
            manifest_path.push("Cargo.toml");

            if manifest_path.exists() {
                visited.insert(dependency.name);
                get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
            }
        }
    }

    Ok(())
}

fn get_targets_with_hitlist(
    hitlist: &[String],
    targets: &mut HashSet<Target>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist);

    for package in metadata.packages {
        if workspace_hitlist.remove(&package.name) {
            for target in package.targets {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    if workspace_hitlist.is_empty() {
        Ok(())
    } else {
        let package = workspace_hitlist.iter().next().unwrap();
        Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("package `{}` is not a member of the workspace", package),
        ))
    }
}

fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet<Target>) {
    for target in target_paths {
        targets.insert(Target::from_target(target));
    }
}

fn format_files(
    files: &[PathBuf],
    fmt_args: &[String],
    verbosity: Verbosity,
) -> Result<ExitStatus, io::Error> {
    let stdout = if verbosity == Verbosity::Quiet {
        std::process::Stdio::null()
    } else {
        std::process::Stdio::inherit()
    };

    if verbosity == Verbosity::Verbose {
        print!("rustfmt");
        for a in fmt_args {
            print!(" {}", a);
        }
        for f in files {
            print!(" {}", f.display());
        }
        println!();
    }

    let mut command = Command::new("rustfmt")
        .stdout(stdout)
        .args(files)
        .args(fmt_args)
        .spawn()
        .map_err(|e| match e.kind() {
            io::ErrorKind::NotFound => io::Error::new(
                io::ErrorKind::Other,
                "Could not run rustfmt, please make sure it is in your PATH.",
            ),
            _ => e,
        })?;

    command.wait()
}

fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> {
    match cargo_metadata::metadata(manifest_path) {
        Ok(metadata) => Ok(metadata),
        Err(..) => Err(io::Error::new(
            io::ErrorKind::Other,
            "`cargo manifest` failed.",
        )),
    }
}
<commit_msg>Reusing status-handling function<commit_after>// Copyright 2015-2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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

#![cfg(not(test))]
#![deny(warnings)]

extern crate cargo_metadata;
extern crate getopts;
extern crate serde_json as json;

use std::env;
use std::fs;
use std::hash::{Hash, Hasher};
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};
use std::str;
use std::collections::HashSet;
use std::iter::FromIterator;

use getopts::{Matches, Options};

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

const SUCCESS: i32 = 0;
const FAILURE: i32 = 1;

fn execute() -> i32 {
    let mut opts = getopts::Options::new();
    opts.optflag("h", "help", "show this message");
    opts.optflag("q", "quiet", "no output printed to stdout");
    opts.optflag("v", "verbose", "use verbose output");
    opts.optmulti(
        "p",
        "package",
        "specify package to format (only usable in workspaces)",
        "<package>",
    );
    opts.optflag("", "version", "print rustfmt version and exit");
    opts.optflag("", "all", "format all packages (only usable in workspaces)");

    // If there is any invalid argument passed to `cargo fmt`, return without formatting.
    let mut is_package_arg = false;
    for arg in env::args().skip(2).take_while(|a| a != "--") {
        if arg.starts_with('-') {
            is_package_arg = arg.starts_with("--package");
        } else if !is_package_arg {
            print_usage_to_stderr(&opts, &format!("Invalid argument: `{}`.", arg));
            return FAILURE;
        } else {
            is_package_arg = false;
        }
    }

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

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

    if matches.opt_present("h") {
        print_usage_to_stdout(&opts, "");
        return SUCCESS;
    }

    if matches.opt_present("version") {
        return handle_command_status(get_version(), &opts);
    }

    let strategy = CargoFmtStrategy::from_matches(&matches);
    handle_command_status(format_crate(verbosity, &strategy), &opts)
}

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

fn print_usage_to_stdout(opts: &Options, reason: &str) {
    print_usage!(println, opts, reason);
}

fn print_usage_to_stderr(opts: &Options, reason: &str) {
    print_usage!(eprintln, opts, reason);
}

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

fn handle_command_status(status: Result<ExitStatus, io::Error>, opts: &getopts::Options) -> i32 {
    match status {
        Err(e) => {
            print_usage_to_stderr(&opts, &e.to_string());
            FAILURE
        }
        Ok(status) => {
            if status.success() {
                SUCCESS
            } else {
                status.code().unwrap_or(FAILURE)
            }
        }
    }
}

fn get_version() -> Result<ExitStatus, io::Error> {
    let mut command = Command::new("rustfmt")
        .args(vec!["--version"])
        .spawn()
        .map_err(|e| match e.kind() {
            io::ErrorKind::NotFound => io::Error::new(
                io::ErrorKind::Other,
                "Could not run rustfmt, please make sure it is in your PATH.",
            ),
            _ => e,
        })?;

    command.wait()
}

fn format_crate(
    verbosity: Verbosity,
    strategy: &CargoFmtStrategy,
) -> Result<ExitStatus, io::Error> {
    let rustfmt_args = get_fmt_args();
    let targets = if rustfmt_args.iter().any(|s| s == "--dump-default-config") {
        HashSet::new()
    } else {
        get_targets(strategy)?
    };

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

    format_files(&files, &rustfmt_args, verbosity)
}

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

/// Target uses a `path` field for equality and hashing.
#[derive(Debug)]
pub struct Target {
    /// A path to the main source file of the target.
    path: PathBuf,
    /// A kind of target (e.g. lib, bin, example, ...).
    kind: String,
}

impl Target {
    pub fn from_target(target: &cargo_metadata::Target) -> Self {
        let path = PathBuf::from(&target.src_path);
        let canonicalized = fs::canonicalize(&path).unwrap_or(path);

        Target {
            path: canonicalized,
            kind: target.kind[0].clone(),
        }
    }
}

impl PartialEq for Target {
    fn eq(&self, other: &Target) -> bool {
        self.path == other.path
    }
}

impl Eq for Target {}

impl Hash for Target {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.path.hash(state);
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum CargoFmtStrategy {
    /// Format every packages and dependencies.
    All,
    /// Format pacakges that are specified by the command line argument.
    Some(Vec<String>),
    /// Format the root packages only.
    Root,
}

impl CargoFmtStrategy {
    pub fn from_matches(matches: &Matches) -> CargoFmtStrategy {
        match (matches.opt_present("all"), matches.opt_present("p")) {
            (false, false) => CargoFmtStrategy::Root,
            (true, _) => CargoFmtStrategy::All,
            (false, true) => CargoFmtStrategy::Some(matches.opt_strs("p")),
        }
    }
}

/// Based on the specified `CargoFmtStrategy`, returns a set of main source files.
fn get_targets(strategy: &CargoFmtStrategy) -> Result<HashSet<Target>, io::Error> {
    let mut targets = HashSet::new();

    match *strategy {
        CargoFmtStrategy::Root => get_targets_root_only(&mut targets)?,
        CargoFmtStrategy::All => get_targets_recursive(None, &mut targets, &mut HashSet::new())?,
        CargoFmtStrategy::Some(ref hitlist) => get_targets_with_hitlist(hitlist, &mut targets)?,
    }

    if targets.is_empty() {
        Err(io::Error::new(
            io::ErrorKind::Other,
            "Failed to find targets".to_owned(),
        ))
    } else {
        Ok(targets)
    }
}

fn get_targets_root_only(targets: &mut HashSet<Target>) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    for package in metadata.packages {
        for target in package.targets {
            if target.name == package.name {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    Ok(())
}

fn get_targets_recursive(
    manifest_path: Option<&Path>,
    mut targets: &mut HashSet<Target>,
    visited: &mut HashSet<String>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(manifest_path)?;

    for package in metadata.packages {
        add_targets(&package.targets, &mut targets);

        // Look for local dependencies.
        for dependency in package.dependencies {
            if dependency.source.is_some() || visited.contains(&dependency.name) {
                continue;
            }

            let mut manifest_path = PathBuf::from(&package.manifest_path);

            manifest_path.pop();
            manifest_path.push(&dependency.name);
            manifest_path.push("Cargo.toml");

            if manifest_path.exists() {
                visited.insert(dependency.name);
                get_targets_recursive(Some(&manifest_path), &mut targets, visited)?;
            }
        }
    }

    Ok(())
}

fn get_targets_with_hitlist(
    hitlist: &[String],
    targets: &mut HashSet<Target>,
) -> Result<(), io::Error> {
    let metadata = get_cargo_metadata(None)?;

    let mut workspace_hitlist: HashSet<&String> = HashSet::from_iter(hitlist);

    for package in metadata.packages {
        if workspace_hitlist.remove(&package.name) {
            for target in package.targets {
                targets.insert(Target::from_target(&target));
            }
        }
    }

    if workspace_hitlist.is_empty() {
        Ok(())
    } else {
        let package = workspace_hitlist.iter().next().unwrap();
        Err(io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("package `{}` is not a member of the workspace", package),
        ))
    }
}

fn add_targets(target_paths: &[cargo_metadata::Target], targets: &mut HashSet<Target>) {
    for target in target_paths {
        targets.insert(Target::from_target(target));
    }
}

fn format_files(
    files: &[PathBuf],
    fmt_args: &[String],
    verbosity: Verbosity,
) -> Result<ExitStatus, io::Error> {
    let stdout = if verbosity == Verbosity::Quiet {
        std::process::Stdio::null()
    } else {
        std::process::Stdio::inherit()
    };

    if verbosity == Verbosity::Verbose {
        print!("rustfmt");
        for a in fmt_args {
            print!(" {}", a);
        }
        for f in files {
            print!(" {}", f.display());
        }
        println!();
    }

    let mut command = Command::new("rustfmt")
        .stdout(stdout)
        .args(files)
        .args(fmt_args)
        .spawn()
        .map_err(|e| match e.kind() {
            io::ErrorKind::NotFound => io::Error::new(
                io::ErrorKind::Other,
                "Could not run rustfmt, please make sure it is in your PATH.",
            ),
            _ => e,
        })?;

    command.wait()
}

fn get_cargo_metadata(manifest_path: Option<&Path>) -> Result<cargo_metadata::Metadata, io::Error> {
    match cargo_metadata::metadata(manifest_path) {
        Ok(metadata) => Ok(metadata),
        Err(..) => Err(io::Error::new(
            io::ErrorKind::Other,
            "`cargo manifest` failed.",
        )),
    }
}
<|endoftext|>


<commit_before>use {Tokens, ToTokens};
use std::borrow::Cow;
use std::fmt;

#[derive(Debug, Clone, Eq, Hash)]
pub struct Ident(String);

impl Ident {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        t.into()
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident(s.to_owned())
    }
}

impl<'a> From<Cow<'a, str>> for Ident {
    fn from(s: Cow<'a, str>) -> Self {
        Ident(s.into_owned())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident(s)
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

impl fmt::Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
    where T: AsRef<str>
{
    fn eq(&self, other: &T) -> bool {
        self.0 == other.as_ref()
    }
}

impl ToTokens for Ident {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(self.as_ref())
    }
}
<commit_msg>Doc comment for Ident<commit_after>use {Tokens, ToTokens};
use std::borrow::Cow;
use std::fmt;

/// An identifier that should be interpolated without quotes.
#[derive(Debug, Clone, Eq, Hash)]
pub struct Ident(String);

impl Ident {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        t.into()
    }
}

impl<'a> From<&'a str> for Ident {
    fn from(s: &str) -> Self {
        Ident(s.to_owned())
    }
}

impl<'a> From<Cow<'a, str>> for Ident {
    fn from(s: Cow<'a, str>) -> Self {
        Ident(s.into_owned())
    }
}

impl From<String> for Ident {
    fn from(s: String) -> Self {
        Ident(s)
    }
}

impl AsRef<str> for Ident {
    fn as_ref(&self) -> &str {
        &self.0
    }
}

impl fmt::Display for Ident {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.0.fmt(formatter)
    }
}

impl<T: ?Sized> PartialEq<T> for Ident
    where T: AsRef<str>
{
    fn eq(&self, other: &T) -> bool {
        self.0 == other.as_ref()
    }
}

impl ToTokens for Ident {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(self.as_ref())
    }
}
<|endoftext|>


<commit_before>#[deriving(Show)]
struct Vec2<T> {
    x: T,
    y: T,
}

impl<
    // bound: T implements the Add trait
    T: Add<T, T>
> Add<Vec2<T>, Vec2<T>>
for Vec2<T> {
    fn add(&self, rhs: &Vec2<T>) -> Vec2<T> {
        Vec2 {
            // x and y are of type T, and implement the add() method
            x: self.x.add(&rhs.x),
            y: self.x.add(&rhs.y),
        }
    }
}

impl<
    // bound: T implements the Sub trait
    T: Sub<T, T>
> Sub<Vec2<T>, Vec2<T>>
for Vec2<T> {
    fn sub(&self, rhs: &Vec2<T>) -> Vec2<T> {
        Vec2 {
            // x and y are of type T, and implement the sub() method
            x: self.x.sub(&rhs.x),
            y: self.x.sub(&rhs.y),
        }
    }
}

impl<
    // bound: T implements *both* the Add trait and the Mul trait
    T: Add<T, T> + Mul<T, T>
> Vec2<T> {
    fn dot(&self, rhs: &Vec2<T>) -> T {
        // the sugary versions of mul() and add() can be used as well
        (self.x * rhs.x) + (self.y * rhs.y)
    }
}

fn main() {
    let v1 = Vec2 { x: 1.0, y: 2.0 };
    let v2 = Vec2 { x: 2.0, y: 1.0 };

    println!("{} + {} = {}", v1, v2, v1 + v2);
    println!("{} - {} = {}", v1, v2, v1 - v2);
    println!("{} . {} = {}", v1, v2, v1.dot(&v2));
}
<commit_msg>bounds: Rectify incorrect computations of the result vector y-component in the Vec2 add()/sub() implementations.<commit_after>#[deriving(Show)]
struct Vec2<T> {
    x: T,
    y: T,
}

impl<
    // bound: T implements the Add trait
    T: Add<T, T>
> Add<Vec2<T>, Vec2<T>>
for Vec2<T> {
    fn add(&self, rhs: &Vec2<T>) -> Vec2<T> {
        Vec2 {
            // x and y are of type T, and implement the add() method
            x: self.x.add(&rhs.x),
            y: self.y.add(&rhs.y),
        }
    }
}

impl<
    // bound: T implements the Sub trait
    T: Sub<T, T>
> Sub<Vec2<T>, Vec2<T>>
for Vec2<T> {
    fn sub(&self, rhs: &Vec2<T>) -> Vec2<T> {
        Vec2 {
            // x and y are of type T, and implement the sub() method
            x: self.x.sub(&rhs.x),
            y: self.y.sub(&rhs.y),
        }
    }
}

impl<
    // bound: T implements *both* the Add trait and the Mul trait
    T: Add<T, T> + Mul<T, T>
> Vec2<T> {
    fn dot(&self, rhs: &Vec2<T>) -> T {
        // the sugary versions of mul() and add() can be used as well
        (self.x * rhs.x) + (self.y * rhs.y)
    }
}

fn main() {
    let v1 = Vec2 { x: 1.0, y: 2.0 };
    let v2 = Vec2 { x: 2.0, y: 1.0 };

    println!("{} + {} = {}", v1, v2, v1 + v2);
    println!("{} - {} = {}", v1, v2, v1 - v2);
    println!("{} . {} = {}", v1, v2, v1.dot(&v2));
}
<|endoftext|>