<commit_before>use alto;
use alto::{Context, StaticSource, StreamingSource, Buffer, SourceTrait};
use alto::{Mono, Stereo};

use std::sync::Arc;
use std::path::{PathBuf};

use super::load::load_ogg;

use std::fs::File;
use lewton::inside_ogg::OggStreamReader;

use Vec3f;
use HashMap;
use JamResult;
use JamError;
use cgmath::Zero;

pub type SoundName = String;

pub type SoundEventId = u64;

pub type Gain = f32;

pub type DistanceModel = alto::DistanceModel;

pub struct SoundContext<'d> {
    pub context: &'d Context<'d>,
    pub path: String,
    pub extension: String,
    pub sources: Vec<SoundSource<'d>>,
    pub streaming_sources: Vec<StreamingSoundSource<'d>>,
    pub buffers: HashMap<SoundName, SoundBuffer<'d>>,
    pub stream_above_file_size: u64,
    pub next_event : SoundEventId,
    pub master_gain : Gain,
    pub distance_model : DistanceModel,
    pub listener : Listener,
}

pub struct SoundBuffer<'d> {
    pub inner : Arc<Buffer<'d, 'd>>,
    pub gain: Gain,
    pub duration: f32, // we could track last used .... could be interesting if nothing else
}

pub struct SoundSource<'d> {
    inner: StaticSource<'d, 'd>,
    pub current_binding: Option<SoundBinding>,
}

pub struct StreamingSoundSource<'d> {
    inner: StreamingSource<'d, 'd>,
    pub stream_reader : Option<OggStreamReader<File>>,
    pub current_binding: Option<SoundBinding>,
}

#[derive(Debug)]
pub struct SoundBinding {
    pub event_id: SoundEventId,
    pub sound_event: SoundEvent,
}

// an index to a source + binding
#[derive(Debug, Clone, Copy)]
pub struct SoundSourceLoan {
    pub source_id: usize,
    pub event_id: SoundEventId,
    pub streaming: bool,
}

#[derive(Clone, Debug)]
pub struct SoundEvent {
    pub name: String,
    pub position: Vec3f,
    pub gain: f32,
    pub pitch: f32,
    pub attenuation: f32,
    pub loop_sound: bool,
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Listener {
    pub position: Vec3f,
    pub velocity: Vec3f,
    pub orientation_up: Vec3f,
    pub orientation_forward: Vec3f,
}

impl Listener {
    pub fn default() -> Listener {
        Listener {
            position: Vec3f::zero(),
            velocity: Vec3f::zero(),
            orientation_up: Vec3f::new(0.0, 1.0, 0.0),
            orientation_forward: Vec3f::new(0.0, 0.0, -1.0),
        }
    }
}

pub fn create_sound_context<'d>(context: &'d Context<'d>, path:&str, extension: &str, stream_above_file_size: u64) -> SoundContext<'d> {
    // we should probably create our sources here
    SoundContext {
        context: context,
        path: String::from(path),
        extension: String::from(extension),
        sources: Vec::new(),
        streaming_sources: Vec::new(),
        buffers: HashMap::default(),
        stream_above_file_size: stream_above_file_size,
        next_event: 0,
        master_gain: 1.0,
        distance_model: alto::DistanceModel::None,
        listener: Listener::default() ,
    }
}

impl<'d> SoundContext<'d> {
      pub fn set_gain(&mut self, gain: Gain) -> JamResult<()> {
        try!(self.context.set_gain(gain));
        self.master_gain = gain;
        Ok(())
    }

    pub fn set_listener(&mut self, listener: Listener) -> JamResult<()> {
        try!(self.context.set_position(listener.position));
        try!(self.context.set_velocity(listener.velocity));
        try!(self.context.set_orientation::<[f32; 3]>((listener.orientation_forward.into(), listener.orientation_up.into())));

        self.listener = listener;

        Ok(())
    }

    pub fn create_sources(&mut self, static_sources: usize, streaming_sources: usize) -> JamResult<()> {
        for _ in 0..static_sources {
            let source = try!(self.context.new_static_source());
            self.sources.push(SoundSource { inner: source, current_binding: None});
        }
        for _ in 0..streaming_sources {
            let source = try!(self.context.new_streaming_source());
            self.streaming_sources.push(StreamingSoundSource { inner: source, stream_reader: None, current_binding: None });
        }
        Ok(())
    }

     pub fn purge(&mut self) -> JamResult<()> {
        for source in self.sources.iter_mut() {
            if source.current_binding.is_some() {
                try!(source.inner.stop());
                source.current_binding = None;
            }
        }
        for source in self.streaming_sources.iter_mut() {
            if source.current_binding.is_some() {
                try!(source.inner.stop());
                source.current_binding = None;
            }
        }
        self.buffers.clear();
        Ok(())
    }

    pub fn full_path(&self, name: &str) -> PathBuf {
        PathBuf::from(format!("{}/{}.{}", &self.path, name, &self.extension))
    }

    pub fn next_event_id(&mut self) -> SoundEventId {
        self.next_event += 1;
        self.next_event
    }

    pub fn clean_sources(&mut self) -> JamResult<(u32, u32)> {
        use alto::SourceState::*;

        let mut available_sources = 0;
        let mut available_streaming_sources = 0;

        for source in self.sources.iter_mut() {
            if source.current_binding.is_some() {
                let state = try!(source.inner.state());
                match state {
                    Initial | Playing | Paused => (),
                    Stopped => {
                        source.current_binding = None;
                        available_sources += 1;
                    },
                };
            } else {
                available_sources += 1;
            }
        }
        for streaming_source in self.streaming_sources.iter_mut() {
            if streaming_source.current_binding.is_some() {
                let state = try!(streaming_source.inner.state());
                match state {
                    Initial | Playing | Paused => (),
                    Stopped => {
                        streaming_source.current_binding = None;
                        available_streaming_sources += 1;
                    },
                };
            } else {
                available_streaming_sources += 1;
            }
        }

        Ok((available_sources, available_streaming_sources))
    }

    pub fn set_distace_model(&mut self, distance_model: DistanceModel) -> JamResult<()> {
        try!(self.context.set_distance_model(distance_model));
        self.distance_model = distance_model;
        Ok(())
    }

    // I don't really understand this 'a on the mut self :-(
    pub fn source_for_loan<'a>(&'a mut self, loan:SoundSourceLoan) -> Option<CombinedSource<'d, 'a>> {
        if loan.streaming {
            let mut source : &'a mut StreamingSoundSource<'d> = &mut self.streaming_sources[loan.source_id];
            let valid = source.current_binding.iter().any(|ss| ss.event_id == loan.event_id );
            if valid {
                Some(CombinedSource::Streaming(source))
            } else {
                None
            }
        } else {
            let mut source : &'a mut SoundSource<'d> = &mut self.sources[loan.source_id];
            let valid = source.current_binding.iter().any(|ss| ss.event_id == loan.event_id );
            if valid {
                Some(CombinedSource::Static(source))
            } else {
                None
            }
        }
    }

    // just convenience
    pub fn stop(&mut self, loan:SoundSourceLoan) -> JamResult<()> {
        if let Some(ref mut source) = self.source_for_loan(loan) {
            try!(source.stop());
        }
        Ok(())
    }
}

// used for retrieving loans
pub enum CombinedSource<'d: 'a, 'a> {
    Static(&'a mut SoundSource<'d>),
    Streaming(&'a mut StreamingSoundSource<'d>),
}

impl<'d: 'a, 'a> CombinedSource<'d, 'a> {
    fn assign_event(&mut self, event:&SoundEvent) -> JamResult<()> {
        use self::CombinedSource::*;
        match self {
            &mut Static( ref mut source) => {
                try!(assign_event(&mut source.inner, event));
            },
            &mut Streaming(ref mut source) => {
                try!(assign_event(&mut source.inner, event));
            },
        }
        Ok(())
    }

    fn stop(&mut self) -> JamResult<()> {
        use self::CombinedSource::*;
        match self {
            &mut Static(ref mut source) => {
                try!(source.inner.stop());
                try!(source.inner.clear_buffer());
                source.current_binding = None;
            },
            &mut Streaming(ref mut source) => {
                try!(source.inner.stop());
                source.stream_reader = None;
                source.current_binding = None;
                while try!(source.inner.buffers_processed()) > 0 {
                    println!("unqueing buffer for stream!!");
                    try!(source.inner.unqueue_buffer());
                }
            },
        }
        Ok(())
    }
}

fn assign_event<'d: 'c, 'c, ST : SourceTrait<'d,'c>>(source: &mut ST, sound_event:&SoundEvent) -> JamResult<()> {
    try!(source.set_pitch(sound_event.pitch));
    try!(source.set_position(sound_event.position));
    try!(source.set_gain(sound_event.gain));
    Ok(())
}

/*
pub position: Vec3f,
    pub gain: f32,
    pub pitch: f32,
    pub attenuation: f32,
    pub loop_sound: bool,*/<commit_msg>Building back up<commit_after>use alto;
use alto::{Context, StaticSource, StreamingSource, Buffer, SourceTrait};
use alto::{Mono, Stereo};

use std::sync::Arc;
use std::path::{PathBuf};

use super::load::load_ogg;

use std::fs::File;
use lewton::inside_ogg::OggStreamReader;

use Vec3f;
use HashMap;
use JamResult;
use JamError;
use cgmath::Zero;

pub type SoundName = String;

pub type SoundEventId = u64;

pub type Gain = f32;

pub type DistanceModel = alto::DistanceModel;

pub struct SoundContext<'d> {
    pub context: &'d Context<'d>,
    pub path: String,
    pub extension: String,
    pub sources: Sources<'d>,
    pub buffers: HashMap<SoundName, SoundBuffer<'d>>,
    pub stream_above_file_size: u64,
    pub master_gain : Gain,
    pub distance_model : DistanceModel,
    pub listener : Listener,
}

pub struct SoundBuffer<'d> {
    pub inner : Arc<Buffer<'d, 'd>>,
    pub gain: Gain,
    pub duration: f32, // we could track last used .... could be interesting if nothing else
}

pub struct SoundSource<'d> {
    inner: StaticSource<'d, 'd>,
    pub current_binding: Option<SoundBinding>,
}

pub struct StreamingSoundSource<'d> {
    inner: StreamingSource<'d, 'd>,
    pub stream_reader : Option<OggStreamReader<File>>,
    pub current_binding: Option<SoundBinding>,
}

#[derive(Debug)]
pub struct SoundBinding {
    pub event_id: SoundEventId,
    pub sound_event: SoundEvent,
}

// an index to a source + binding
#[derive(Debug, Clone, Copy)]
pub struct SoundSourceLoan {
    pub source_id: usize,
    pub event_id: SoundEventId,
    pub streaming: bool,
}

#[derive(Clone, Debug)]
pub struct SoundEvent {
    pub name: String,
    pub position: Vec3f,
    pub gain: f32,
    pub pitch: f32,
    pub attenuation: f32,
    pub loop_sound: bool,
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Listener {
    pub position: Vec3f,
    pub velocity: Vec3f,
    pub orientation_up: Vec3f,
    pub orientation_forward: Vec3f,
}

impl Listener {
    pub fn default() -> Listener {
        Listener {
            position: Vec3f::zero(),
            velocity: Vec3f::zero(),
            orientation_up: Vec3f::new(0.0, 1.0, 0.0),
            orientation_forward: Vec3f::new(0.0, 0.0, -1.0),
        }
    }
}

pub fn create_sound_context<'d>(context: &'d Context<'d>, path:&str, extension: &str, stream_above_file_size: u64) -> SoundContext<'d> {
    // we should probably create our sources here
    SoundContext {
        context: context,
        path: String::from(path),
        extension: String::from(extension),
        sources: Sources {
            next_event: 0,
            sources: Vec::new(),
            streaming: Vec::new(),
        },
        buffers: HashMap::default(),
        stream_above_file_size: stream_above_file_size,
        master_gain: 1.0,
        distance_model: alto::DistanceModel::None,
        listener: Listener::default() ,
    }
}

impl<'d> SoundContext<'d> {
    pub fn set_gain(&mut self, gain: Gain) -> JamResult<()> {
        try!(self.context.set_gain(gain));
        self.master_gain = gain;
        Ok(())
    }

    pub fn create(&mut self, static_count: usize, streaming_count: usize) -> JamResult<()> {
        for _ in 0..static_count {
            let source = try!(self.context.new_static_source());
            self.sources.sources.push(SoundSource { inner: source, current_binding: None});
        }
        for _ in 0..streaming_count {
            let source = try!(self.context.new_streaming_source());
            self.sources.streaming.push(StreamingSoundSource { inner: source, stream_reader: None, current_binding: None });
        }
        Ok(())
    }

    pub fn set_listener(&mut self, listener: Listener) -> JamResult<()> {
        try!(self.context.set_position(listener.position));
        try!(self.context.set_velocity(listener.velocity));
        try!(self.context.set_orientation::<[f32; 3]>((listener.orientation_forward.into(), listener.orientation_up.into())));

        self.listener = listener;

        Ok(())
    }

     pub fn purge(&mut self) -> JamResult<()> {
        try!(self.sources.purge());
        self.buffers.clear();
        Ok(())
    }

    pub fn full_path(&self, name: &str) -> PathBuf {
        PathBuf::from(format!("{}/{}.{}", &self.path, name, &self.extension))
    }

    pub fn set_distace_model(&mut self, distance_model: DistanceModel) -> JamResult<()> {
        try!(self.context.set_distance_model(distance_model));
        self.distance_model = distance_model;
        Ok(())
    }

    // just convenience
    pub fn stop(&mut self, loan:SoundSourceLoan) -> JamResult<()> {
        if let Some(ref mut source) = self.sources.for_loan(loan) {
            try!(source.stop());
        }
        Ok(())
    }

    pub fn play_event(&mut self, sound_event: SoundEvent, loan: Option<SoundSourceLoan>) -> JamResult<SoundSourceLoan> {
        if let Some(l) = loan {
            if let Some(mut s) = self.sources.for_loan(l) {
                try!(s.assign_event(&sound_event));
                return Ok(l)
            }
        }

        if let Some(buffer) = self.buffers.get(&sound_event.name) {
            // sound is loaded
            if let Some((source, loan)) = self.sources.loan_next_free_static() {
                // and there's a free source
                try!(source.inner.set_buffer(buffer.inner.clone()));
                try!(assign_event(&mut source.inner, &sound_event));
                try!(source.inner.play());

                Ok(loan)
            } else {
                Err(JamError::NoFreeSource)
            }
        } else {
            Ok(loan.unwrap())
        }
    }
}

pub struct Sources<'d> {
    pub next_event: SoundEventId,
    pub sources: Vec<SoundSource<'d>>,
    pub streaming: Vec<StreamingSoundSource<'d>>,
}

impl <'d> Sources<'d> {
    pub fn next_event_id(&mut self) -> SoundEventId {
        self.next_event += 1;
        self.next_event
    }

    pub fn next_free_static_idx(&self) -> Option<usize> {
        let len = self.sources.len();
        for i in 0..len {
            let source = &self.sources[i];
            if source.current_binding.is_none() {
                return Some(i);
            }
        }
        None
    }

    pub fn loan_next_free_static<'a>(&'a mut self) -> Option<(&'a mut SoundSource<'d>, SoundSourceLoan)> {
        let event_id = self.next_event_id();
        let len = self.sources.len();
        for i in 0..len {
            let source = &mut self.sources[i];
            let loan = SoundSourceLoan {
                source_id: i,
                event_id: event_id,
                streaming: false,
            };
            return Some((source, loan));
        }

        None
    }

    pub fn loan_next_free_streaming<'a>(&'a mut self) -> Option<(&'a mut StreamingSoundSource<'d>, SoundSourceLoan)> {
        let event_id = self.next_event_id();
        let len = self.streaming.len();
        for i in 0..len {
            let source = &mut self.streaming[i];
            let loan = SoundSourceLoan {
                source_id: i,
                event_id: event_id,
                streaming: true,
            };
            return Some((source, loan));
        }

        None
    }

    // I don't really understand this 'a on the mut self :-(
    pub fn for_loan<'a>(&'a mut self, loan:SoundSourceLoan) -> Option<CombinedSource<'d, 'a>> {
        use self::CombinedSource::*;
        if loan.streaming {
            let mut source : &'a mut StreamingSoundSource<'d> = &mut self.streaming[loan.source_id];
            let valid = source.current_binding.iter().any(|ss| ss.event_id == loan.event_id );
            if valid {
                Some(Streaming(source))
            } else {
                None
            }
        } else {
            let mut source : &'a mut SoundSource<'d> = &mut self.sources[loan.source_id];
            let valid = source.current_binding.iter().any(|ss| ss.event_id == loan.event_id );
            if valid {
                Some(Static(source))
            } else {
                None
            }
        }
    }

    pub fn purge(&mut self) -> JamResult<()> {
        for source in self.sources.iter_mut() {
            if source.current_binding.is_some() {
                try!(source.inner.stop());
                source.current_binding = None;
            }
        }
        for source in self.streaming.iter_mut() {
            if source.current_binding.is_some() {
                try!(source.inner.stop());
                source.current_binding = None;
            }
        }
        Ok(())
    }

    // just updates book keeping of sources that have stopped since we checked (so we can throw away the binding)
    pub fn clean(&mut self) -> JamResult<(u32, u32)> {
        use alto::SourceState::*;

        let mut available_sources = 0;
        let mut available_streaming_sources = 0;

        for source in self.sources.iter_mut() {
            if source.current_binding.is_some() {
                let state = try!(source.inner.state());
                match state {
                    Initial | Playing | Paused => (),
                    Stopped => {
                        source.current_binding = None;
                        available_sources += 1;
                    },
                };
            } else {
                available_sources += 1;
            }
        }
        for source in self.streaming.iter_mut() {
            if source.current_binding.is_some() {
                let state = try!(source.inner.state());
                match state {
                    Initial | Playing | Paused => (),
                    Stopped => {
                        source.current_binding = None;
                        available_streaming_sources += 1;
                    },
                };
            } else {
                available_streaming_sources += 1;
            }
        }

        Ok((available_sources, available_streaming_sources))
    }
}

// used for retrieving loans
pub enum CombinedSource<'d: 'a, 'a> {
    Static(&'a mut SoundSource<'d>),
    Streaming(&'a mut StreamingSoundSource<'d>),
}

impl<'d: 'a, 'a> CombinedSource<'d, 'a> {
    fn assign_event(&mut self, event:&SoundEvent) -> JamResult<()> {
        use self::CombinedSource::*;
        match self {
            &mut Static( ref mut source) => {
                try!(assign_event(&mut source.inner, event));
            },
            &mut Streaming(ref mut source) => {
                try!(assign_event(&mut source.inner, event));
            },
        }
        Ok(())
    }

    fn stop(&mut self) -> JamResult<()> {
        use self::CombinedSource::*;
        match self {
            &mut Static(ref mut source) => {
                try!(source.inner.stop());
                try!(source.inner.clear_buffer());
                source.current_binding = None;
            },
            &mut Streaming(ref mut source) => {
                try!(source.inner.stop());
                source.stream_reader = None;
                source.current_binding = None;
                while try!(source.inner.buffers_processed()) > 0 {
                    println!("unqueing buffer for stream!!");
                    try!(source.inner.unqueue_buffer());
                }
            },
        }
        Ok(())
    }
}

fn assign_event<'d: 'c, 'c, ST : SourceTrait<'d,'c>>(source: &mut ST, sound_event:&SoundEvent) -> JamResult<()> {
    try!(source.set_pitch(sound_event.pitch));
    try!(source.set_position(sound_event.position));
    try!(source.set_gain(sound_event.gain));
    Ok(())
}

/*
pub position: Vec3f,
    pub gain: f32,
    pub pitch: f32,
    pub attenuation: f32,
    pub loop_sound: bool,*/<|endoftext|>


<commit_before>use mio::*;
use mio::tcp::TcpStream;
use mio::channel::channel;
use mio::channel::{Sender, Receiver};
use std::collections::HashMap;
use std::net::IpAddr;
use std::net::SocketAddr;
use std::io::Read;

use metainfo::MetaInfo;
use metainfo::SHA1Hash20b;

use wire::handler::{BasicHandler, PeerHandler};
use wire::data::PeerMsg;

const OUTSIDE_MSG: Token = Token(0);
type StreamId = u32;

pub struct Protocol {
    streams: HashMap<StreamId, (TcpStream, PeerStream)>,
    poll: Poll,
    sender: Sender<ChanMsg>,
    receiver: Receiver<ChanMsg>,
    info: MetaInfo,
    info_hash: SHA1Hash20b,
}

struct PeerStream {
    id: StreamId,
    bytes_in: Vec<u8>,
    bytes_out: Vec<u8>,
}

impl PeerStream {
    fn write_in(&mut self, bytes: Vec<u8>) {
        unimplemented!();
    }

    fn write_out(&mut self, bytes: Vec<u8>) {
        unimplemented!();
    }

    fn message(&mut self) -> Option<PeerMsg> {
        unimplemented!();
    }

    fn take(&mut self, len: usize) -> Vec<u8> {
        unimplemented!();
    }
}

#[derive(Debug)]
pub enum ChanMsg {
    NewPeer(IpAddr, u16),
}

impl Protocol {
    pub fn new(info: &MetaInfo,
               hash: SHA1Hash20b)
               -> (Protocol, Sender<ChanMsg>, Receiver<ChanMsg>) {
        let poll = Poll::new().unwrap();

        match (channel(), channel()) {
            ((to_inside, from_outside), (to_outside, from_inside)) => {

                poll.register(&from_outside,
                              OUTSIDE_MSG,
                              Ready::readable(),
                              PollOpt::edge())
                    .unwrap();

                let proto = Protocol {
                    streams: HashMap::new(),
                    poll: poll,
                    sender: to_outside,
                    receiver: from_outside,
                    info: info.clone(),
                    info_hash: hash,
                };

                (proto, to_inside, from_inside)
            }
        }
    }

    pub fn run(&mut self) {
        let mut events = Events::with_capacity(1024);
        loop {
            self.poll.poll(&mut events, None).unwrap();
            for event in events.iter() {
                match event.token() {
                    OUTSIDE_MSG => {
                        match self.receiver.try_recv() {
                            Ok(msg) => self._handle_outside_msg(msg),
                            _ => (),
                        }
                    }
                    _ => self._handle_socket_event(event),
                }
            }
        }
    }

    fn _get_stream_id(&self, token: Token) -> Option<StreamId> {
        unimplemented!()
    }

    fn _handle_socket_event(&mut self, event: Event) {
        let kind = event.kind();
        let peer_id: StreamId = match self._get_stream_id(event.token()) {
            Some(p_id) => p_id,
            None => return,
        };

        if let Some((mut tcp_stream, mut peer_stream)) = self.streams.remove(&peer_id) {
            if kind.is_readable() {
                // read bytes of messages
                Protocol::_handle_read(&mut tcp_stream, &mut peer_stream);
            }
            if kind.is_writable() {
                // write pending messages
                Protocol::_handle_write(&mut tcp_stream, &mut peer_stream);
            }
            if kind.is_hup() {
                // remove socket and clean up
                Protocol::_handle_hup(&mut tcp_stream, &mut peer_stream);
            }
            self.streams.insert(peer_stream.id, (tcp_stream, peer_stream));
        }

    }

    fn _handle_read(socket: &mut TcpStream, peer: &mut PeerStream) {
        let mut buf = Vec::new();
        match socket.read(&mut buf) {
            Ok(bytes) => {
                peer.write_in(buf);
            }
            _ => (),
        }
        match peer.message() {
            Some(msg) => {
                //TODO: Take message and handle it
            },
            _ => ()
        }
    }

    fn _handle_write(socket: &mut TcpStream, peer: &mut PeerStream) {}

    fn _handle_hup(socket: &mut TcpStream, peer: &mut PeerStream) {}

    fn _handle_outside_msg(&mut self, msg: ChanMsg) {
        match msg {
            ChanMsg::NewPeer(ip, port) => self._connect_to_peer(ip, port),
        }
    }

    fn _connect_to_peer(&mut self, addr: IpAddr, port: u16) {
        let sock_addr = SocketAddr::new(addr, port);
        let sock = TcpStream::connect(&sock_addr).unwrap();
        self.poll
            .register(&sock,
                      Token(1),
                      Ready::readable() | Ready::writable(),
                      PollOpt::edge())
            .unwrap();
    }
}
<commit_msg>Make PeerServer a part of protocol<commit_after>use mio::*;
use mio::tcp::TcpStream;
use mio::channel::channel;
use mio::channel::{Sender, Receiver};
use std::collections::HashMap;
use std::net::IpAddr;
use std::net::SocketAddr;
use std::io::Read;

use metainfo::MetaInfo;
use metainfo::SHA1Hash20b;

use wire::handler::{BasicHandler, PeerHandler};
use wire::data::PeerMsg;
use wire::protocol_handler::PeerServer;

const OUTSIDE_MSG: Token = Token(0);
type StreamId = u32;

pub struct Protocol {
    streams: HashMap<StreamId, (TcpStream, PeerStream, PeerServer)>,
    poll: Poll,
    sender: Sender<ChanMsg>,
    receiver: Receiver<ChanMsg>,
    info: MetaInfo,
    info_hash: SHA1Hash20b,
}

struct PeerStream {
    id: StreamId,
    bytes_in: Vec<u8>,
    bytes_out: Vec<u8>,
}

impl PeerStream {
    fn write_in(&mut self, bytes: Vec<u8>) {
        unimplemented!();
    }

    fn write_out(&mut self, bytes: Vec<u8>) {
        unimplemented!();
    }

    fn message(&mut self) -> Option<PeerMsg> {
        unimplemented!();
    }

    fn take(&mut self, len: usize) -> Vec<u8> {
        unimplemented!();
    }
}

#[derive(Debug)]
pub enum ChanMsg {
    NewPeer(IpAddr, u16),
}

impl Protocol {
    pub fn new(info: &MetaInfo,
               hash: SHA1Hash20b)
               -> (Protocol, Sender<ChanMsg>, Receiver<ChanMsg>) {
        let poll = Poll::new().unwrap();

        match (channel(), channel()) {
            ((to_inside, from_outside), (to_outside, from_inside)) => {

                poll.register(&from_outside,
                              OUTSIDE_MSG,
                              Ready::readable(),
                              PollOpt::edge())
                    .unwrap();

                let proto = Protocol {
                    streams: HashMap::new(),
                    poll: poll,
                    sender: to_outside,
                    receiver: from_outside,
                    info: info.clone(),
                    info_hash: hash,
                };

                (proto, to_inside, from_inside)
            }
        }
    }

    pub fn run(&mut self) {
        let mut events = Events::with_capacity(1024);
        loop {
            self.poll.poll(&mut events, None).unwrap();
            for event in events.iter() {
                match event.token() {
                    OUTSIDE_MSG => {
                        match self.receiver.try_recv() {
                            Ok(msg) => self._handle_outside_msg(msg),
                            _ => (),
                        }
                    }
                    _ => self._handle_socket_event(event),
                }
            }
        }
    }

    fn _get_stream_id(&self, token: Token) -> Option<StreamId> {
        unimplemented!()
    }

    fn _handle_socket_event(&mut self, event: Event) {
        let kind = event.kind();
        let peer_id: StreamId = match self._get_stream_id(event.token()) {
            Some(p_id) => p_id,
            None => return,
        };

        if let Some((mut tcp_stream, mut peer_stream, mut handler)) = self.streams.remove(&peer_id) {
            if kind.is_readable() {
                // read bytes of messages
                Protocol::_handle_read(&mut tcp_stream, &mut peer_stream);
            }
            if kind.is_writable() {
                // write pending messages
                Protocol::_handle_write(&mut tcp_stream, &mut peer_stream);
            }
            if kind.is_hup() {
                // remove socket and clean up
                Protocol::_handle_hup(&mut tcp_stream, &mut peer_stream);
            }
            self.streams.insert(peer_stream.id, (tcp_stream, peer_stream, handler));
        }

    }

    fn _handle_read(socket: &mut TcpStream, peer: &mut PeerStream) {
        let mut buf = Vec::new();
        match socket.read(&mut buf) {
            Ok(bytes) => {
                peer.write_in(buf);
            }
            _ => (),
        }
        match peer.message() {
            Some(msg) => {
                //TODO: Take message and handle it
            },
            _ => ()
        }
    }

    fn _handle_write(socket: &mut TcpStream, peer: &mut PeerStream) {}

    fn _handle_hup(socket: &mut TcpStream, peer: &mut PeerStream) {}

    fn _handle_outside_msg(&mut self, msg: ChanMsg) {
        match msg {
            ChanMsg::NewPeer(ip, port) => self._connect_to_peer(ip, port),
        }
    }

    fn _connect_to_peer(&mut self, addr: IpAddr, port: u16) {
        let sock_addr = SocketAddr::new(addr, port);
        let sock = TcpStream::connect(&sock_addr).unwrap();
        self.poll
            .register(&sock,
                      Token(1),
                      Ready::readable() | Ready::writable(),
                      PollOpt::edge())
            .unwrap();
    }
}
<|endoftext|>


<commit_before>//! Code for representing cargo's release version number.

use std::fmt;

/// Information about the git repository where cargo was built from.
pub struct CommitInfo {
    pub short_commit_hash: String,
    pub commit_hash: String,
    pub commit_date: String,
}

/// Information provided by the outer build system (rustbuild aka bootstrap).
pub struct CfgInfo {
    /// Information about the Git repository we may have been built from.
    pub commit_info: Option<CommitInfo>,
    /// The release channel we were built for (stable/beta/nightly/dev).
    pub release_channel: String,
}

/// Cargo's version.
pub struct VersionInfo {
    pub major: u8,
    pub minor: u8,
    pub patch: u8,
    pub pre_release: Option<String>,
    /// Information that's only available when we were built with
    /// rustbuild, rather than Cargo itself.
    pub cfg_info: Option<CfgInfo>,
}

impl fmt::Display for VersionInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)?;
        if let Some(channel) = self.cfg_info.as_ref().map(|ci| &ci.release_channel) {
            if channel != "stable" {
                write!(f, "-{}", channel)?;
                let empty = String::new();
                write!(f, "{}", self.pre_release.as_ref().unwrap_or(&empty))?;
            }
        };

        if let Some(ref cfg) = self.cfg_info {
            if let Some(ref ci) = cfg.commit_info {
                write!(f, " ({} {})", ci.short_commit_hash, ci.commit_date)?;
            }
        };
        Ok(())
    }
}

/// Returns information about cargo's version.
pub fn version() -> VersionInfo {
    macro_rules! option_env_str {
        ($name:expr) => {
            option_env!($name).map(|s| s.to_string())
        };
    }

    // So this is pretty horrible...
    // There are two versions at play here:
    //   - version of cargo-the-binary, which you see when you type `cargo --version`
    //   - version of cargo-the-library, which you download from crates.io for use
    //     in your packages.
    //
    // We want to make the `binary` version the same as the corresponding Rust/rustc release.
    // At the same time, we want to keep the library version at `0.x`, because Cargo as
    // a library is (and probably will always be) unstable.
    //
    // Historically, Cargo used the same version number for both the binary and the library.
    // Specifically, rustc 1.x.z was paired with cargo 0.x+1.w.
    // We continue to use this scheme for the library, but transform it to 1.x.w for the purposes
    // of `cargo --version`.
    let major = 1;
    let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
    let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();

    match option_env!("CFG_RELEASE_CHANNEL") {
        // We have environment variables set up from configure/make.
        Some(_) => {
            let commit_info = option_env!("CFG_COMMIT_HASH").map(|s| CommitInfo {
                commit_hash: s.to_string(),
                short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
                commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
            });
            VersionInfo {
                major,
                minor,
                patch,
                pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
                cfg_info: Some(CfgInfo {
                    release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
                    commit_info,
                }),
            }
        }
        // We are being compiled by Cargo itself.
        None => VersionInfo {
            major,
            minor,
            patch,
            pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
            cfg_info: None,
        },
    }
}
<commit_msg>Remove pre_release in version info.<commit_after>//! Code for representing cargo's release version number.

use std::fmt;

/// Information about the git repository where cargo was built from.
pub struct CommitInfo {
    pub short_commit_hash: String,
    pub commit_hash: String,
    pub commit_date: String,
}

/// Information provided by the outer build system (rustbuild aka bootstrap).
pub struct CfgInfo {
    /// Information about the Git repository we may have been built from.
    pub commit_info: Option<CommitInfo>,
    /// The release channel we were built for (stable/beta/nightly/dev).
    pub release_channel: String,
}

/// Cargo's version.
pub struct VersionInfo {
    pub major: u8,
    pub minor: u8,
    pub patch: u8,
    /// Information that's only available when we were built with
    /// rustbuild, rather than Cargo itself.
    pub cfg_info: Option<CfgInfo>,
}

impl fmt::Display for VersionInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)?;
        if let Some(channel) = self.cfg_info.as_ref().map(|ci| &ci.release_channel) {
            if channel != "stable" {
                write!(f, "-{}", channel)?;
            }
        };

        if let Some(ref cfg) = self.cfg_info {
            if let Some(ref ci) = cfg.commit_info {
                write!(f, " ({} {})", ci.short_commit_hash, ci.commit_date)?;
            }
        };
        Ok(())
    }
}

/// Returns information about cargo's version.
pub fn version() -> VersionInfo {
    macro_rules! option_env_str {
        ($name:expr) => {
            option_env!($name).map(|s| s.to_string())
        };
    }

    // So this is pretty horrible...
    // There are two versions at play here:
    //   - version of cargo-the-binary, which you see when you type `cargo --version`
    //   - version of cargo-the-library, which you download from crates.io for use
    //     in your packages.
    //
    // We want to make the `binary` version the same as the corresponding Rust/rustc release.
    // At the same time, we want to keep the library version at `0.x`, because Cargo as
    // a library is (and probably will always be) unstable.
    //
    // Historically, Cargo used the same version number for both the binary and the library.
    // Specifically, rustc 1.x.z was paired with cargo 0.x+1.w.
    // We continue to use this scheme for the library, but transform it to 1.x.w for the purposes
    // of `cargo --version`.
    let major = 1;
    let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
    let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();

    match option_env!("CFG_RELEASE_CHANNEL") {
        // We have environment variables set up from configure/make.
        Some(_) => {
            let commit_info = option_env!("CFG_COMMIT_HASH").map(|s| CommitInfo {
                commit_hash: s.to_string(),
                short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
                commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
            });
            VersionInfo {
                major,
                minor,
                patch,
                cfg_info: Some(CfgInfo {
                    release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
                    commit_info,
                }),
            }
        }
        // We are being compiled by Cargo itself.
        None => VersionInfo {
            major,
            minor,
            patch,
            cfg_info: None,
        },
    }
}
<|endoftext|>


<commit_before>extern crate pancurses;

use backend;
use event::{Event, Key};

use self::super::find_closest;
use theme::{Color, ColorStyle, Effect};

pub struct Concrete {
    window: pancurses::Window,
}

impl backend::Backend for Concrete {
    fn init() -> Self {
        ::std::env::set_var("ESCDELAY", "25");
        let window = pancurses::initscr();
        window.keypad(true);
        pancurses::noecho();
        pancurses::cbreak();
        pancurses::start_color();
        pancurses::curs_set(0);
        window.bkgd(pancurses::COLOR_PAIR(ColorStyle::Background.id() as u64));

        Concrete { window: window }
    }

    fn screen_size(&self) -> (usize, usize) {
        let (y, x) = self.window.get_max_yx();
        (x as usize, y as usize)
    }

    fn has_colors(&self) -> bool {
        pancurses::has_colors()
    }

    fn finish(&mut self) {
        pancurses::endwin();
    }

    fn init_color_style(&mut self, style: ColorStyle, foreground: &Color,
                        background: &Color) {
        pancurses::init_pair(style.id(),
                             find_closest(foreground) as i16,
                             find_closest(background) as i16);
    }

    fn with_color<F: FnOnce()>(&self, color: ColorStyle, f: F) {
        // TODO: pancurses doesn't have an `attr_get` equivalent
        // let mut current_style: pancurses::attr_t = 0;
        // let mut current_color: i16 = 0;
        // pancurses::attr_get(&mut current_style, &mut current_color);

        let style = pancurses::COLOR_PAIR(color.id() as u64);
        self.window.attron(style);
        f();
        self.window.attroff(style);
        // pancurses::attron(current_style);
    }

    fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) {
        let style = match effect {
            // A_REVERSE, taken from ncurses
            Effect::Reverse => 1 << (10 + 8u32),
            Effect::Simple => pancurses::A_NORMAL,
        };
        self.window.attron(style);
        f();
        self.window.attroff(style);
    }

    fn clear(&self) {
        self.window.clear();
    }

    fn refresh(&mut self) {
        self.window.refresh();
    }

    fn print_at(&self, (x, y): (usize, usize), text: &str) {
        self.window.mvaddstr(y as i32, x as i32, text);
    }

    fn poll_event(&self) -> Event {
        // TODO: there seems to not be any indication
        // of Ctrl/Alt/Shift in these :v
        if let Some(ev) = self.window.getch() {
            match ev {
                pancurses::Input::Character('\n') => Event::Key(Key::Enter),
                pancurses::Input::Character(c) => Event::Char(c),
                pancurses::Input::Unknown(i) => Event::Unknown(i),
                // TODO: I honestly have no fucking idea what KeyCodeYes is
                pancurses::Input::KeyCodeYes => Event::Refresh,
                pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak),
                pancurses::Input::KeyDown => Event::Key(Key::Down),
                pancurses::Input::KeyUp => Event::Key(Key::Up),
                pancurses::Input::KeyLeft => Event::Key(Key::Left),
                pancurses::Input::KeyRight => Event::Key(Key::Right),
                pancurses::Input::KeyHome => Event::Key(Key::Home),
                pancurses::Input::KeyBackspace => Event::Key(Key::Backspace),
                pancurses::Input::KeyF0 => Event::Key(Key::F0),
                pancurses::Input::KeyF1 => Event::Key(Key::F1),
                pancurses::Input::KeyF2 => Event::Key(Key::F2),
                pancurses::Input::KeyF3 => Event::Key(Key::F3),
                pancurses::Input::KeyF4 => Event::Key(Key::F4),
                pancurses::Input::KeyF5 => Event::Key(Key::F5),
                pancurses::Input::KeyF6 => Event::Key(Key::F6),
                pancurses::Input::KeyF7 => Event::Key(Key::F7),
                pancurses::Input::KeyF8 => Event::Key(Key::F8),
                pancurses::Input::KeyF9 => Event::Key(Key::F9),
                pancurses::Input::KeyF10 => Event::Key(Key::F10),
                pancurses::Input::KeyF11 => Event::Key(Key::F11),
                pancurses::Input::KeyF12 => Event::Key(Key::F12),
                pancurses::Input::KeyF13 => Event::Shift(Key::F1),
                pancurses::Input::KeyF14 => Event::Shift(Key::F2),
                pancurses::Input::KeyF15 => Event::Shift(Key::F3),
                pancurses::Input::KeyDL => Event::Refresh,
                pancurses::Input::KeyIL => Event::Key(Key::Ins),
                pancurses::Input::KeyDC => Event::Key(Key::Del),
                pancurses::Input::KeyIC => Event::Refresh,
                pancurses::Input::KeyEIC => Event::Refresh,
                pancurses::Input::KeyClear => Event::Refresh,
                pancurses::Input::KeyEOS => Event::Refresh,
                pancurses::Input::KeyEOL => Event::Refresh,
                pancurses::Input::KeySF => Event::Refresh,
                pancurses::Input::KeySR => Event::Refresh,
                pancurses::Input::KeyNPage => Event::Key(Key::PageDown),
                pancurses::Input::KeyPPage => Event::Key(Key::PageUp),
                pancurses::Input::KeySTab => Event::Shift(Key::Tab),
                pancurses::Input::KeyCTab => Event::Ctrl(Key::Tab),
                pancurses::Input::KeyCATab => Event::CtrlAlt(Key::Tab),
                pancurses::Input::KeyEnter => Event::Key(Key::Enter),
                pancurses::Input::KeySReset => Event::Refresh,
                pancurses::Input::KeyReset => Event::Refresh,
                pancurses::Input::KeyPrint => Event::Refresh,
                pancurses::Input::KeyLL => Event::Refresh,
                pancurses::Input::KeyAbort => Event::Refresh,
                pancurses::Input::KeySHelp => Event::Refresh,
                pancurses::Input::KeyLHelp => Event::Refresh,
                pancurses::Input::KeyBTab => Event::Shift(Key::Tab),
                pancurses::Input::KeyBeg => Event::Refresh,
                pancurses::Input::KeyCancel => Event::Refresh,
                pancurses::Input::KeyClose => Event::Refresh,
                pancurses::Input::KeyCommand => Event::Refresh,
                pancurses::Input::KeyCopy => Event::Refresh,
                pancurses::Input::KeyCreate => Event::Refresh,
                pancurses::Input::KeyEnd => Event::Refresh,
                pancurses::Input::KeyExit => Event::Refresh,
                pancurses::Input::KeyFind => Event::Refresh,
                pancurses::Input::KeyHelp => Event::Refresh,
                pancurses::Input::KeyMark => Event::Refresh,
                pancurses::Input::KeyMessage => Event::Refresh,
                pancurses::Input::KeyMove => Event::Refresh,
                pancurses::Input::KeyNext => Event::Refresh,
                pancurses::Input::KeyOpen => Event::Refresh,
                pancurses::Input::KeyOptions => Event::Refresh,
                pancurses::Input::KeyPrevious => Event::Refresh,
                pancurses::Input::KeyRedo => Event::Refresh,
                pancurses::Input::KeyReference => Event::Refresh,
                pancurses::Input::KeyRefresh => Event::Refresh,
                pancurses::Input::KeyReplace => Event::Refresh,
                pancurses::Input::KeyRestart => Event::Refresh,
                pancurses::Input::KeyResume => Event::Refresh,
                pancurses::Input::KeySave => Event::Refresh,
                pancurses::Input::KeySBeg => Event::Refresh,
                pancurses::Input::KeySCancel => Event::Refresh,
                pancurses::Input::KeySCommand => Event::Refresh,
                pancurses::Input::KeySCopy => Event::Refresh,
                pancurses::Input::KeySCreate => Event::Refresh,
                pancurses::Input::KeySDC => Event::Shift(Key::Del),
                pancurses::Input::KeySDL => Event::Refresh,
                pancurses::Input::KeySelect => Event::Refresh,
                pancurses::Input::KeySEnd => Event::Shift(Key::End),
                pancurses::Input::KeySEOL => Event::Refresh,
                pancurses::Input::KeySExit => Event::Refresh,
                pancurses::Input::KeySFind => Event::Refresh,
                pancurses::Input::KeySHome => Event::Shift(Key::Home),
                pancurses::Input::KeySIC => Event::Shift(Key::Ins),
                pancurses::Input::KeySLeft => Event::Refresh,
                pancurses::Input::KeySMessage => Event::Refresh,
                pancurses::Input::KeySMove => Event::Refresh,
                pancurses::Input::KeySNext => Event::Shift(Key::PageDown),
                pancurses::Input::KeySOptions => Event::Refresh,
                pancurses::Input::KeySPrevious => Event::Shift(Key::PageUp),
                pancurses::Input::KeySPrint => Event::Refresh,
                pancurses::Input::KeySRedo => Event::Refresh,
                pancurses::Input::KeySReplace => Event::Refresh,
                pancurses::Input::KeySRight => Event::Refresh,
                pancurses::Input::KeySResume => Event::Refresh,
                pancurses::Input::KeySSave => Event::Refresh,
                pancurses::Input::KeySSuspend => Event::Refresh,
                pancurses::Input::KeySUndo => Event::Refresh,
                pancurses::Input::KeySuspend => Event::Refresh,
                pancurses::Input::KeyUndo => Event::Refresh,
                pancurses::Input::KeyResize => Event::Refresh,
                pancurses::Input::KeyEvent => Event::Refresh,
                // TODO: mouse support
                pancurses::Input::KeyMouse => Event::Refresh,
                pancurses::Input::KeyA1 => Event::Refresh,
                pancurses::Input::KeyA3 => Event::Refresh,
                pancurses::Input::KeyB2 => Event::Key(Key::NumpadCenter),
                pancurses::Input::KeyC1 => Event::Refresh,
                pancurses::Input::KeyC3 => Event::Refresh,
            }
        } else {
            Event::Refresh
        }
    }

    fn set_refresh_rate(&mut self, fps: u32) {
        if fps == 0 {
            self.window.timeout(-1);
        } else {
            self.window.timeout(1000 / fps as i32);
        }
    }
}
<commit_msg>Fix some input in pancurses backend<commit_after>extern crate pancurses;

use backend;
use event::{Event, Key};

use self::super::find_closest;
use theme::{Color, ColorStyle, Effect};

pub struct Concrete {
    window: pancurses::Window,
}

impl backend::Backend for Concrete {
    fn init() -> Self {
        ::std::env::set_var("ESCDELAY", "25");
        let window = pancurses::initscr();
        window.keypad(true);
        pancurses::noecho();
        pancurses::cbreak();
        pancurses::start_color();
        pancurses::curs_set(0);
        window.bkgd(pancurses::COLOR_PAIR(ColorStyle::Background.id() as u64));

        Concrete { window: window }
    }

    fn screen_size(&self) -> (usize, usize) {
        let (y, x) = self.window.get_max_yx();
        (x as usize, y as usize)
    }

    fn has_colors(&self) -> bool {
        pancurses::has_colors()
    }

    fn finish(&mut self) {
        pancurses::endwin();
    }

    fn init_color_style(&mut self, style: ColorStyle, foreground: &Color,
                        background: &Color) {
        pancurses::init_pair(style.id(),
                             find_closest(foreground) as i16,
                             find_closest(background) as i16);
    }

    fn with_color<F: FnOnce()>(&self, color: ColorStyle, f: F) {
        // TODO: pancurses doesn't have an `attr_get` equivalent
        // let mut current_style: pancurses::attr_t = 0;
        // let mut current_color: i16 = 0;
        // pancurses::attr_get(&mut current_style, &mut current_color);

        let style = pancurses::COLOR_PAIR(color.id() as u64);
        self.window.attron(style);
        f();
        self.window.attroff(style);
        // pancurses::attron(current_style);
    }

    fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) {
        let style = match effect {
            // A_REVERSE, taken from ncurses
            Effect::Reverse => 1 << (10 + 8u32),
            Effect::Simple => pancurses::A_NORMAL,
        };
        self.window.attron(style);
        f();
        self.window.attroff(style);
    }

    fn clear(&self) {
        self.window.clear();
    }

    fn refresh(&mut self) {
        self.window.refresh();
    }

    fn print_at(&self, (x, y): (usize, usize), text: &str) {
        self.window.mvaddstr(y as i32, x as i32, text);
    }

    fn poll_event(&self) -> Event {
        // TODO: there seems to not be any indication
        // of Ctrl/Alt/Shift in these :v
        if let Some(ev) = self.window.getch() {
            match ev {
                pancurses::Input::Character('\n') => Event::Key(Key::Enter),
                // TODO: wait for a very short delay. If more keys are
                // pipelined, it may be an escape sequence.
                pancurses::Input::Character('\u{1b}') => Event::Key(Key::Esc),
                pancurses::Input::Character('\u{7f}') => Event::Key(Key::Backspace),
                pancurses::Input::Character(c) => Event::Char(c),
                // TODO: Some key combos are not recognized by pancurses,
                // but are sent as Unknown. We could still parse them here.
                pancurses::Input::Unknown(i) => Event::Unknown(i),
                // TODO: I honestly have no fucking idea what KeyCodeYes is
                pancurses::Input::KeyCodeYes => Event::Refresh,
                pancurses::Input::KeyBreak => Event::Key(Key::PauseBreak),
                pancurses::Input::KeyDown => Event::Key(Key::Down),
                pancurses::Input::KeyUp => Event::Key(Key::Up),
                pancurses::Input::KeyLeft => Event::Key(Key::Left),
                pancurses::Input::KeyRight => Event::Key(Key::Right),
                pancurses::Input::KeyHome => Event::Key(Key::Home),
                pancurses::Input::KeyBackspace => Event::Key(Key::Backspace),
                pancurses::Input::KeyF0 => Event::Key(Key::F0),
                pancurses::Input::KeyF1 => Event::Key(Key::F1),
                pancurses::Input::KeyF2 => Event::Key(Key::F2),
                pancurses::Input::KeyF3 => Event::Key(Key::F3),
                pancurses::Input::KeyF4 => Event::Key(Key::F4),
                pancurses::Input::KeyF5 => Event::Key(Key::F5),
                pancurses::Input::KeyF6 => Event::Key(Key::F6),
                pancurses::Input::KeyF7 => Event::Key(Key::F7),
                pancurses::Input::KeyF8 => Event::Key(Key::F8),
                pancurses::Input::KeyF9 => Event::Key(Key::F9),
                pancurses::Input::KeyF10 => Event::Key(Key::F10),
                pancurses::Input::KeyF11 => Event::Key(Key::F11),
                pancurses::Input::KeyF12 => Event::Key(Key::F12),
                pancurses::Input::KeyF13 => Event::Shift(Key::F1),
                pancurses::Input::KeyF14 => Event::Shift(Key::F2),
                pancurses::Input::KeyF15 => Event::Shift(Key::F3),
                pancurses::Input::KeyDL => Event::Refresh,
                pancurses::Input::KeyIL => Event::Refresh,
                pancurses::Input::KeyDC => Event::Key(Key::Del),
                pancurses::Input::KeyIC => Event::Key(Key::Ins),
                pancurses::Input::KeyEIC => Event::Refresh,
                pancurses::Input::KeyClear => Event::Refresh,
                pancurses::Input::KeyEOS => Event::Refresh,
                pancurses::Input::KeyEOL => Event::Refresh,
                pancurses::Input::KeySF => Event::Shift(Key::Down),
                pancurses::Input::KeySR => Event::Shift(Key::Up),
                pancurses::Input::KeyNPage => Event::Key(Key::PageDown),
                pancurses::Input::KeyPPage => Event::Key(Key::PageUp),
                pancurses::Input::KeySTab => Event::Shift(Key::Tab),
                pancurses::Input::KeyCTab => Event::Ctrl(Key::Tab),
                pancurses::Input::KeyCATab => Event::CtrlAlt(Key::Tab),
                pancurses::Input::KeyEnter => Event::Key(Key::Enter),
                pancurses::Input::KeySReset => Event::Refresh,
                pancurses::Input::KeyReset => Event::Refresh,
                pancurses::Input::KeyPrint => Event::Refresh,
                pancurses::Input::KeyLL => Event::Refresh,
                pancurses::Input::KeyAbort => Event::Refresh,
                pancurses::Input::KeySHelp => Event::Refresh,
                pancurses::Input::KeyLHelp => Event::Refresh,
                pancurses::Input::KeyBTab => Event::Shift(Key::Tab),
                pancurses::Input::KeyBeg => Event::Refresh,
                pancurses::Input::KeyCancel => Event::Refresh,
                pancurses::Input::KeyClose => Event::Refresh,
                pancurses::Input::KeyCommand => Event::Refresh,
                pancurses::Input::KeyCopy => Event::Refresh,
                pancurses::Input::KeyCreate => Event::Refresh,
                pancurses::Input::KeyEnd => Event::Key(Key::End),
                pancurses::Input::KeyExit => Event::Refresh,
                pancurses::Input::KeyFind => Event::Refresh,
                pancurses::Input::KeyHelp => Event::Refresh,
                pancurses::Input::KeyMark => Event::Refresh,
                pancurses::Input::KeyMessage => Event::Refresh,
                pancurses::Input::KeyMove => Event::Refresh,
                pancurses::Input::KeyNext => Event::Refresh,
                pancurses::Input::KeyOpen => Event::Refresh,
                pancurses::Input::KeyOptions => Event::Refresh,
                pancurses::Input::KeyPrevious => Event::Refresh,
                pancurses::Input::KeyRedo => Event::Refresh,
                pancurses::Input::KeyReference => Event::Refresh,
                pancurses::Input::KeyRefresh => Event::Refresh,
                pancurses::Input::KeyReplace => Event::Refresh,
                pancurses::Input::KeyRestart => Event::Refresh,
                pancurses::Input::KeyResume => Event::Refresh,
                pancurses::Input::KeySave => Event::Refresh,
                pancurses::Input::KeySBeg => Event::Refresh,
                pancurses::Input::KeySCancel => Event::Refresh,
                pancurses::Input::KeySCommand => Event::Refresh,
                pancurses::Input::KeySCopy => Event::Refresh,
                pancurses::Input::KeySCreate => Event::Refresh,
                pancurses::Input::KeySDC => Event::Shift(Key::Del),
                pancurses::Input::KeySDL => Event::Refresh,
                pancurses::Input::KeySelect => Event::Refresh,
                pancurses::Input::KeySEnd => Event::Shift(Key::End),
                pancurses::Input::KeySEOL => Event::Refresh,
                pancurses::Input::KeySExit => Event::Refresh,
                pancurses::Input::KeySFind => Event::Refresh,
                pancurses::Input::KeySHome => Event::Shift(Key::Home),
                pancurses::Input::KeySIC => Event::Shift(Key::Ins),
                pancurses::Input::KeySLeft => Event::Shift(Key::Left),
                pancurses::Input::KeySMessage => Event::Refresh,
                pancurses::Input::KeySMove => Event::Refresh,
                pancurses::Input::KeySNext => Event::Shift(Key::PageDown),
                pancurses::Input::KeySOptions => Event::Refresh,
                pancurses::Input::KeySPrevious => Event::Shift(Key::PageUp),
                pancurses::Input::KeySPrint => Event::Refresh,
                pancurses::Input::KeySRedo => Event::Refresh,
                pancurses::Input::KeySReplace => Event::Refresh,
                pancurses::Input::KeySRight => Event::Shift(Key::Right),
                pancurses::Input::KeySResume => Event::Refresh,
                pancurses::Input::KeySSave => Event::Refresh,
                pancurses::Input::KeySSuspend => Event::Refresh,
                pancurses::Input::KeySUndo => Event::Refresh,
                pancurses::Input::KeySuspend => Event::Refresh,
                pancurses::Input::KeyUndo => Event::Refresh,
                pancurses::Input::KeyResize => Event::WindowResize,
                pancurses::Input::KeyEvent => Event::Refresh,
                // TODO: mouse support
                pancurses::Input::KeyMouse => Event::Refresh,
                pancurses::Input::KeyA1 => Event::Refresh,
                pancurses::Input::KeyA3 => Event::Refresh,
                pancurses::Input::KeyB2 => Event::Key(Key::NumpadCenter),
                pancurses::Input::KeyC1 => Event::Refresh,
                pancurses::Input::KeyC3 => Event::Refresh,
            }
        } else {
            Event::Refresh
        }
    }

    fn set_refresh_rate(&mut self, fps: u32) {
        if fps == 0 {
            self.window.timeout(-1);
        } else {
            self.window.timeout(1000 / fps as i32);
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate capnp;
extern crate libloading;

mod hierarchy_capnp;
mod vm_capnp;
mod test_capnp;

use std::fs::File;
use std::path::Path;
use std::io::BufReader;
use std::process;

use hierarchy_capnp::{directories};
use capnp::{serialize, message};

struct ExecuteTest<'a> {
    pub name: String,
    pub capnp: test_capnp::input_output::Reader<'a>,
}

fn main() {
    let matches = clap_app!(gaslighter =>
        (version: "0.1.0")
        (author: "Stewart Mackenzie <setori88@gmail.com>")
        (about: "Gaslighter - Ethereum Virtual Machine tester.")
        (@arg CAPNPROTO_TYPECHECKED_TEST_BIN: -t --capnp_test_bin +takes_value "Path to a type checked binary compiled by the capnp tool. The source of this artefact is in the tests directory. Please run `$ capnp eval -b tests/mod.capnp all > tests.bin` in the root directory to generate the binary.")
        (@arg TESTS_TO_RUN: -r --run_test +takes_value +required "The format is [directory]/[file]/[test] e.g. `--run_test arith/add/add1` will run the arith/add/add1 test, `--run_test arith/add/` will run every test in the tests/arith/add.capnp file. Likewise `--run_test arith//` will run every test in every file of the `arith` directory. Lastly `--run_test //` will run every single test available.")
        (@arg KEEP_GOING: -k --keep_going "Don't exit the program even if a test fails.")
    ).get_matches();
    let capnp_test_bin = match matches.value_of("CAPNPROTO_TYPECHECKED_TEST_BIN") {
        Some(c) => c,
        None => "",
    };
    let test_to_run = match matches.value_of("TESTS_TO_RUN") {
        Some(c) => c,
        None => "",
    };
    let keep_going = if matches.is_present("KEEP_GOING") { true } else { false };
    let path = Path::new(capnp_test_bin);
    let display = path.display();
    let file = match File::open(&path) {
        Err(_) => panic!("couldn't open {}", display),
        Ok(file) => file,
    };
    let (dir_to_run, file_to_run, test_to_run) = test_scope(test_to_run.into());
    let mut contents = BufReader::new(file);
    let tests_reader = serialize::read_message(&mut contents, message::ReaderOptions::new()).expect("read message failed.");
    let mut tests_to_execute :std::vec::Vec<ExecuteTest> = Vec::new();
    let top_level_tests = tests_reader.get_root::<directories::Reader>().expect("failed to get top level test root.");
    for dir in top_level_tests.get_dirs().expect("failed to directories.").iter() {
        let mut add_dir = false;
        let dirname = dir.get_name().expect("failed to get directory name.");
        if dirname == dir_to_run || dir_to_run == "" { add_dir = true; }
        for file in dir.get_files().expect("failed to files.").iter() {
            let mut add_file = false;
            let filename = file.get_name().expect("failed to get filename.");
            if filename == file_to_run || file_to_run == "" { add_file = true; }
            for test in file.get_tests().expect("failed to get tests.").iter() {
                let mut add_test = false;
                let testname = test.get_name().expect("failed to get test name.");
                if testname == test_to_run || test_to_run == "" {
                    add_test = true;
                    if add_dir && add_file && add_test {
                        let execute_test = ExecuteTest {
                            name: format!("{}::{}::{}", dirname, filename, testname),
                            capnp: test,
                        };
                        tests_to_execute.push(execute_test);
                    }
                }
            }
        }
    }
    if has_all_tests_passed(tests_to_execute, keep_going) {
        process::exit(0);
    } else {
        process::exit(1);
    }
}

fn test_scope(test_to_run: String) -> (String, String, String) {
    let vec: Vec<&str> = test_to_run.split("/").collect();
    (vec[0].into(), vec[1].into(), vec[2].into())
}

fn evaluate(msg: std::vec::Vec<capnp::Word>) -> libloading::Result<std::vec::Vec<capnp::Word>> {
    let lib = libloading::Library::new("libsputnikvm.so").expect("cannot load");
    unsafe {
        let func: libloading::Symbol<unsafe extern fn(std::vec::Vec<capnp::Word>) -> std::vec::Vec<capnp::Word>> = try!(lib.get(b"evaluate"));
        Ok(func(msg))
    }
}

fn has_all_tests_passed(tests_to_execute: std::vec::Vec<ExecuteTest>, keep_going: bool) -> bool {
    println!("running {} tests", tests_to_execute.len());
    let mut has_all_tests_passed = true;
    for test in tests_to_execute {
        print!("sputnikvm test {} ", test.name);
        let test = test.capnp;
        let eo = test.get_expected_output().expect("failed to get expected output");
        let io = test.get_input_output().expect("failed to get actual input output");
        let mut message = message::Builder::new_default();
        message.set_root(io);
        let mut vm_resp = serialize::write_message_to_words(&message);
        println!("\n\nbefore: {:?}\n\n", vm_resp);
        let vm_resp = evaluate(vm_resp).expect("failed to evaluate");
        println!("\n\nafter: {:?}\n\n", vm_resp);
        let io = serialize::read_message_from_words(vm_resp.as_slice(), message::ReaderOptions::new()).expect("failed to read vm response");
        let io = io.get_root::<vm_capnp::input_output::Reader>().expect("failed to get root");
        let ao_gas = io.get_output().expect("failed to get output").get_used_gas();
        let eo_gas = eo.get_used_gas();
        let ao_code = io.get_output().expect("").get_code().expect("").iter();
        let eo_code = eo.get_code().expect("").iter();
        let mut ao_vec = Vec::new();
        let mut eo_vec = Vec::new();
        let mut has_this_test_failed = false;
        for ao_char in ao_code {
            ao_vec.push(ao_char.expect("character expected")[0]);
        }
        for eo_char in eo_code {
            eo_vec.push(eo_char.expect("character expected")[0]);
        }
        let length = eo_vec.len();
        let matching = ao_vec.iter().zip(eo_vec.iter()).filter(|&(a, b)| a == b).count();
        if matching != length {
            has_this_test_failed = true;
            print!("\n\n code equality fail: only {} actual output opcodes matched the {} opcodes of the expected output.\n", matching, length);
            println!(" actual code output:\t{:?}", ao_vec);
            println!(" expected code output:\t{:?}", eo_vec);
        }
        if eo_gas != ao_gas {
            has_this_test_failed = true;
            print!("\n gas equality fail: actual output gas value of {} doesn't equal the expected output gas value of {}.", ao_gas, eo_gas);
            print!("\n actual gas output:\t{}", ao_gas);
            print!("\n expected gas output:\t{}\n", eo_gas);
        }
        if has_this_test_failed {
            print!("\n");
            has_all_tests_passed = false;
            if !keep_going {
                return has_all_tests_passed;
            }
        } else {
            print!("... ok\n")
        }
    }
    has_all_tests_passed
}
<commit_msg>Problem: code diverging is causing merge conflicts<commit_after>#[macro_use]
extern crate clap;
extern crate capnp;
extern crate libloading;

mod hierarchy_capnp;
mod vm_capnp;
mod test_capnp;

use std::fs::File;
use std::path::Path;
use std::io::BufReader;
use std::process;

use hierarchy_capnp::{directories};
use capnp::{serialize, message};

struct ExecuteTest<'a> {
    pub name: String,
    pub capnp: test_capnp::input_output::Reader<'a>,
}

fn main() {
    let matches = clap_app!(gaslighter =>
        (version: "0.1.0")
        (author: "Stewart Mackenzie <setori88@gmail.com>")
        (about: "Gaslighter - Ethereum Virtual Machine tester.")
        (@arg CAPNPROTO_TYPECHECKED_TEST_BIN: -t --capnp_test_bin +takes_value "Path to a type checked binary compiled by the capnp tool. The source of this artefact is in the tests directory. Please run `$ capnp eval -b tests/mod.capnp all > tests.bin` in the root directory to generate the binary.")
        (@arg TESTS_TO_RUN: -r --run_test +takes_value +required "The format is [directory]/[file]/[test] e.g. `--run_test arith/add/add1` will run the arith/add/add1 test, `--run_test arith/add/` will run every test in the tests/arith/add.capnp file. Likewise `--run_test arith//` will run every test in every file of the `arith` directory. Lastly `--run_test //` will run every single test available.")
        (@arg KEEP_GOING: -k --keep_going "Don't exit the program even if a test fails.")
    ).get_matches();
    let capnp_test_bin = match matches.value_of("CAPNPROTO_TYPECHECKED_TEST_BIN") {
        Some(c) => c,
        None => "",
    };
    let test_to_run = match matches.value_of("TESTS_TO_RUN") {
        Some(c) => c,
        None => "",
    };
    let keep_going = if matches.is_present("KEEP_GOING") { true } else { false };
    let path = Path::new(capnp_test_bin);
    let display = path.display();
    let file = match File::open(&path) {
        Err(_) => panic!("couldn't open {}", display),
        Ok(file) => file,
    };
    let (dir_to_run, file_to_run, test_to_run) = test_scope(test_to_run.into());
    let mut contents = BufReader::new(file);
    let tests_reader = serialize::read_message(&mut contents, message::ReaderOptions::new()).expect("read message failed.");
    let mut tests_to_execute :std::vec::Vec<ExecuteTest> = Vec::new();
    let top_level_tests = tests_reader.get_root::<directories::Reader>().expect("failed to get top level test root.");
    for dir in top_level_tests.get_dirs().expect("failed to directories.").iter() {
        let mut add_dir = false;
        let dirname = dir.get_name().expect("failed to get directory name.");
        if dirname == dir_to_run || dir_to_run == "" { add_dir = true; }
        for file in dir.get_files().expect("failed to files.").iter() {
            let mut add_file = false;
            let filename = file.get_name().expect("failed to get filename.");
            if filename == file_to_run || file_to_run == "" { add_file = true; }
            for test in file.get_tests().expect("failed to get tests.").iter() {
                let mut add_test = false;
                let testname = test.get_name().expect("failed to get test name.");
                if testname == test_to_run || test_to_run == "" {
                    add_test = true;
                    if add_dir && add_file && add_test {
                        let execute_test = ExecuteTest {
                            name: format!("{}::{}::{}", dirname, filename, testname),
                            capnp: test,
                        };
                        tests_to_execute.push(execute_test);
                    }
                }
            }
        }
    }
    if has_all_tests_passed(tests_to_execute, keep_going) {
        process::exit(0);
    } else {
        process::exit(1);
    }
}

fn test_scope(test_to_run: String) -> (String, String, String) {
    let vec: Vec<&str> = test_to_run.split("/").collect();
    (vec[0].into(), vec[1].into(), vec[2].into())
}

fn evaluate(msg: std::vec::Vec<capnp::Word>) -> libloading::Result<std::vec::Vec<capnp::Word>> {
    let lib = libloading::Library::new("libsputnikvm.so").expect("cannot load");
    unsafe {
        let func: libloading::Symbol<unsafe extern fn(std::vec::Vec<capnp::Word>) -> std::vec::Vec<capnp::Word>> = try!(lib.get(b"evaluate"));
        Ok(func(msg))
    }
}

fn has_all_tests_passed(tests_to_execute: std::vec::Vec<ExecuteTest>, keep_going: bool) -> bool {
    println!("running {} tests", tests_to_execute.len());
    let mut has_all_tests_passed = true;
    for test in tests_to_execute {
        print!("sputnikvm test {} ", test.name);
        let test = test.capnp;
        let eo = test.get_expected_output().expect("failed to get expected output");
        let io = test.get_input_output().expect("failed to get actual input output");
        let mut message = message::Builder::new_default();
        message.set_root(io);
        let mut vm_resp = serialize::write_message_to_words(&message);
        // println!("\n\nbefore: {:?}\n\n", vm_resp);
        // let vm_resp = evaluate(vm_resp).expect("failed to evaluate");
        // println!("\n\nafter: {:?}\n\n", vm_resp);
        let io = serialize::read_message_from_words(vm_resp.as_slice(), message::ReaderOptions::new()).expect("failed to read vm response");
        let io = io.get_root::<vm_capnp::input_output::Reader>().expect("failed to get root");
        let ao_gas = io.get_output().expect("failed to get output").get_used_gas();
        let eo_gas = eo.get_used_gas();
        let ao_code = io.get_output().expect("").get_code().expect("").iter();
        let eo_code = eo.get_code().expect("").iter();
        let mut ao_vec = Vec::new();
        let mut eo_vec = Vec::new();
        let mut has_this_test_failed = false;
        for ao_char in ao_code {
            ao_vec.push(ao_char.expect("character expected")[0]);
        }
        for eo_char in eo_code {
            eo_vec.push(eo_char.expect("character expected")[0]);
        }
        let length = eo_vec.len();
        let matching = ao_vec.iter().zip(eo_vec.iter()).filter(|&(a, b)| a == b).count();
        if matching != length {
            has_this_test_failed = true;
            print!("\n\n code equality fail: only {} actual output opcodes matched the {} opcodes of the expected output.\n", matching, length);
            println!(" actual code output:\t{:?}", ao_vec);
            println!(" expected code output:\t{:?}", eo_vec);
        }
        if eo_gas != ao_gas {
            has_this_test_failed = true;
            print!("\n gas equality fail: actual output gas value of {} doesn't equal the expected output gas value of {}.", ao_gas, eo_gas);
            print!("\n actual gas output:\t{}", ao_gas);
            print!("\n expected gas output:\t{}\n", eo_gas);
        }
        if has_this_test_failed {
            print!("\n");
            has_all_tests_passed = false;
            if !keep_going {
                return has_all_tests_passed;
            }
        } else {
            print!("... ok\n")
        }
    }
    has_all_tests_passed
}
<|endoftext|>


<commit_before>fn wants_box(x: @str) { }
fn wants_uniq(x: ~str) { }
fn wants_three(x: str/3) { }

fn has_box(x: @str) {
   wants_box(x);
   wants_uniq(x); //~ ERROR str storage differs: expected ~ but found @
   wants_three(x); //~ ERROR str storage differs: expected 3 but found @
}

fn has_uniq(x: ~str) {
   wants_box(x); //~ ERROR str storage differs: expected @ but found ~
   wants_uniq(x);
   wants_three(x); //~ ERROR str storage differs: expected 3 but found ~
}

fn has_three(x: str/3) {
   wants_box(x); //~ ERROR str storage differs: expected @ but found 3
   wants_uniq(x); //~ ERROR str storage differs: expected ~ but found 3
   wants_three(x);
}

fn has_four(x: str/4) {
   wants_box(x); //~ ERROR str storage differs: expected @ but found 4
   wants_uniq(x); //~ ERROR str storage differs: expected ~ but found 4
   wants_three(x); //~ ERROR str storage differs: expected 3 but found 4
}

fn main() {
}
<commit_msg>Remove obsolete fixed-length string test<commit_after>fn wants_box(x: @str) { }
fn wants_uniq(x: ~str) { }
fn wants_slice(x: &str) { }

fn has_box(x: @str) {
   wants_box(x);
   wants_uniq(x); //~ ERROR str storage differs: expected ~ but found @
   wants_slice(x);
}

fn has_uniq(x: ~str) {
   wants_box(x); //~ ERROR str storage differs: expected @ but found ~
   wants_uniq(x);
   wants_slice(x);
}

fn has_slice(x: &str) {
   wants_box(x); //~ ERROR str storage differs: expected @ but found &
   wants_uniq(x); //~ ERROR str storage differs: expected ~ but found &
   wants_slice(x);
}

fn main() {
}
<|endoftext|>


<commit_before>use crate::command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::ops;
use cargo::util::ToUrl;

pub fn cli() -> App {
    subcommand("install")
        .about("Install a Rust binary. Default location is $HOME/.cargo/bin")
        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
        .arg(
            opt("version", "Specify a version to install from crates.io")
                .alias("vers")
                .value_name("VERSION"),
        )
        .arg(opt("git", "Git URL to install the specified crate from").value_name("URL"))
        .arg(opt("branch", "Branch to use when installing from git").value_name("BRANCH"))
        .arg(opt("tag", "Tag to use when installing from git").value_name("TAG"))
        .arg(opt("rev", "Specific commit to use when installing from git").value_name("SHA"))
        .arg(opt("path", "Filesystem path to local crate to install").value_name("PATH"))
        .arg(opt(
            "list",
            "list all installed packages and their versions",
        ))
        .arg_jobs()
        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
        .arg_features()
        .arg(opt("debug", "Build in debug mode instead of release mode"))
        .arg_targets_bins_examples(
            "Install only the specified binary",
            "Install all binaries",
            "Install only the specified example",
            "Install all examples",
        )
        .arg_target_triple("Build for the target triple")
        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
        .after_help(
            "\
This command manages Cargo's local set of installed binary crates. Only packages
which have [[bin]] targets can be installed, and all binaries are installed into
the installation root's `bin` folder. The installation root is determined, in
order of precedence, by `--root`, `$CARGO_INSTALL_ROOT`, the `install.root`
configuration key, and finally the home directory (which is either
`$CARGO_HOME` if set or `$HOME/.cargo` by default).

There are multiple sources from which a crate can be installed. The default
location is crates.io but the `--git` and `--path` flags can change this source.
If the source contains more than one package (such as crates.io or a git
repository with multiple crates) the `<crate>` argument is required to indicate
which crate should be installed.

Crates from crates.io can optionally specify the version they wish to install
via the `--vers` flags, and similarly packages from git repositories can
optionally specify the branch, tag, or revision that should be installed. If a
crate has multiple binaries, the `--bin` argument can selectively install only
one of them, and if you'd rather install examples the `--example` argument can
be used as well.

By default cargo will refuse to overwrite existing binaries. The `--force` flag
enables overwriting existing binaries. Thus you can reinstall a crate with
`cargo install --force <crate>`.

Omitting the <crate> specification entirely will
install the crate in the current directory. That is, `install` is equivalent to
the more explicit `install --path .`.  This behaviour is deprecated, and no
longer supported as of the Rust 2018 edition.

If the source is crates.io or `--git` then by default the crate will be built
in a temporary target directory.  To avoid this, the target directory can be
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
path.  In particular, this can be useful for caching build artifacts on
continuous integration systems.",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let registry = args.registry(config)?;

    config.reload_rooted_at_cargo_home()?;
    let mut compile_opts = args.compile_options(config, CompileMode::Build)?;

    compile_opts.build_config.release = !args.is_present("debug");

    let krates = args
        .values_of("crate")
        .unwrap_or_default()
        .collect::<Vec<_>>();

    let mut from_cwd = false;

    let source = if let Some(url) = args.value_of("git") {
        let url = url.to_url()?;
        let gitref = if let Some(branch) = args.value_of("branch") {
            GitReference::Branch(branch.to_string())
        } else if let Some(tag) = args.value_of("tag") {
            GitReference::Tag(tag.to_string())
        } else if let Some(rev) = args.value_of("rev") {
            GitReference::Rev(rev.to_string())
        } else {
            GitReference::Branch("master".to_string())
        };
        SourceId::for_git(&url, gitref)?
    } else if let Some(path) = args.value_of_path("path", config) {
        SourceId::for_path(&path)?
    } else if krates.is_empty() {
        from_cwd = true;
        SourceId::for_path(config.cwd())?
    } else if let Some(registry) = registry {
        SourceId::alt_registry(config, &registry)?
    } else {
        SourceId::crates_io(config)?
    };

    let version = args.value_of("version");
    let root = args.value_of("root");

    if args.is_present("list") {
        ops::install_list(root, config)?;
    } else {
        ops::install(
            root,
            krates,
            source,
            from_cwd,
            version,
            &compile_opts,
            args.is_present("force"),
        )?;
    }
    Ok(())
}
<commit_msg>Fixup cargo install's help message<commit_after>use crate::command_prelude::*;

use cargo::core::{GitReference, SourceId};
use cargo::ops;
use cargo::util::ToUrl;

pub fn cli() -> App {
    subcommand("install")
        .about("Install a Rust binary. Default location is $HOME/.cargo/bin")
        .arg(Arg::with_name("crate").empty_values(false).multiple(true))
        .arg(
            opt("version", "Specify a version to install from crates.io")
                .alias("vers")
                .value_name("VERSION"),
        )
        .arg(opt("git", "Git URL to install the specified crate from").value_name("URL"))
        .arg(opt("branch", "Branch to use when installing from git").value_name("BRANCH"))
        .arg(opt("tag", "Tag to use when installing from git").value_name("TAG"))
        .arg(opt("rev", "Specific commit to use when installing from git").value_name("SHA"))
        .arg(opt("path", "Filesystem path to local crate to install").value_name("PATH"))
        .arg(opt(
            "list",
            "list all installed packages and their versions",
        ))
        .arg_jobs()
        .arg(opt("force", "Force overwriting existing crates or binaries").short("f"))
        .arg_features()
        .arg(opt("debug", "Build in debug mode instead of release mode"))
        .arg_targets_bins_examples(
            "Install only the specified binary",
            "Install all binaries",
            "Install only the specified example",
            "Install all examples",
        )
        .arg_target_triple("Build for the target triple")
        .arg(opt("root", "Directory to install packages into").value_name("DIR"))
        .arg(opt("registry", "Registry to use").value_name("REGISTRY"))
        .after_help(
            "\
This command manages Cargo's local set of installed binary crates. Only packages
which have [[bin]] targets can be installed, and all binaries are installed into
the installation root's `bin` folder. The installation root is determined, in
order of precedence, by `--root`, `$CARGO_INSTALL_ROOT`, the `install.root`
configuration key, and finally the home directory (which is either
`$CARGO_HOME` if set or `$HOME/.cargo` by default).

There are multiple sources from which a crate can be installed. The default
location is crates.io but the `--git` and `--path` flags can change this source.
If the source contains more than one package (such as crates.io or a git
repository with multiple crates) the `<crate>` argument is required to indicate
which crate should be installed.

Crates from crates.io can optionally specify the version they wish to install
via the `--version` flags, and similarly packages from git repositories can
optionally specify the branch, tag, or revision that should be installed. If a
crate has multiple binaries, the `--bin` argument can selectively install only
one of them, and if you'd rather install examples the `--example` argument can
be used as well.

By default cargo will refuse to overwrite existing binaries. The `--force` flag
enables overwriting existing binaries. Thus you can reinstall a crate with
`cargo install --force <crate>`.

Omitting the <crate> specification entirely will
install the crate in the current directory. That is, `install` is equivalent to
the more explicit `install --path .`.  This behaviour is deprecated, and no
longer supported as of the Rust 2018 edition.

If the source is crates.io or `--git` then by default the crate will be built
in a temporary target directory.  To avoid this, the target directory can be
specified by setting the `CARGO_TARGET_DIR` environment variable to a relative
path.  In particular, this can be useful for caching build artifacts on
continuous integration systems.",
        )
}

pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
    let registry = args.registry(config)?;

    config.reload_rooted_at_cargo_home()?;
    let mut compile_opts = args.compile_options(config, CompileMode::Build)?;

    compile_opts.build_config.release = !args.is_present("debug");

    let krates = args
        .values_of("crate")
        .unwrap_or_default()
        .collect::<Vec<_>>();

    let mut from_cwd = false;

    let source = if let Some(url) = args.value_of("git") {
        let url = url.to_url()?;
        let gitref = if let Some(branch) = args.value_of("branch") {
            GitReference::Branch(branch.to_string())
        } else if let Some(tag) = args.value_of("tag") {
            GitReference::Tag(tag.to_string())
        } else if let Some(rev) = args.value_of("rev") {
            GitReference::Rev(rev.to_string())
        } else {
            GitReference::Branch("master".to_string())
        };
        SourceId::for_git(&url, gitref)?
    } else if let Some(path) = args.value_of_path("path", config) {
        SourceId::for_path(&path)?
    } else if krates.is_empty() {
        from_cwd = true;
        SourceId::for_path(config.cwd())?
    } else if let Some(registry) = registry {
        SourceId::alt_registry(config, &registry)?
    } else {
        SourceId::crates_io(config)?
    };

    let version = args.value_of("version");
    let root = args.value_of("root");

    if args.is_present("list") {
        ops::install_list(root, config)?;
    } else {
        ops::install(
            root,
            krates,
            source,
            from_cwd,
            version,
            &compile_opts,
            args.is_present("force"),
        )?;
    }
    Ok(())
}
<|endoftext|>