<commit_before>use futures::sync::oneshot;
use futures::{future, Future};
use futures::sync::mpsc::{UnboundedReceiver, UnboundedSender, unbounded};
use std;
use std::borrow::Cow;
use std::io::{Read, Seek, SeekFrom, Result};
use std::mem;
use std::sync::mpsc::{RecvError, TryRecvError, RecvTimeoutError};
use std::thread;
use std::time::Duration;

use config::{Bitrate, PlayerConfig};
use core::session::Session;
use core::spotify_id::SpotifyId;

use audio_backend::Sink;
use audio::{AudioFile, AudioDecrypt};
use audio::{VorbisDecoder, VorbisPacket};
use metadata::{FileFormat, Track, Metadata};
use mixer::AudioFilter;

pub struct Player {
    commands: Option<std::sync::mpsc::Sender<PlayerCommand>>,
    thread_handle: Option<thread::JoinHandle<()>>,
}

struct PlayerInternal {
    session: Session,
    config: PlayerConfig,
    commands: std::sync::mpsc::Receiver<PlayerCommand>,

    state: PlayerState,
    sink: Box<Sink>,
    sink_running: bool,
    audio_filter: Option<Box<AudioFilter + Send>>,
    event_sender: UnboundedSender<PlayerEvent>,
}

enum PlayerCommand {
    Load(SpotifyId, bool, u32, oneshot::Sender<()>),
    Play,
    Pause,
    Stop,
    Seek(u32),
}

#[derive(Debug, Clone)]
pub enum PlayerEvent {
    Started {
        track_id: SpotifyId,
    },

    Changed {
        old_track_id: SpotifyId,
        new_track_id: SpotifyId,
    },

    Stopped {
        track_id: SpotifyId,
    }
}

type PlayerEventChannel = UnboundedReceiver<PlayerEvent>;
impl Player {
    pub fn new<F>(config: PlayerConfig, session: Session,
                  audio_filter: Option<Box<AudioFilter + Send>>,
                  sink_builder: F) -> (Player, PlayerEventChannel)
        where F: FnOnce() -> Box<Sink> + Send + 'static
    {
        let (cmd_tx, cmd_rx) = std::sync::mpsc::channel();
        let (event_sender, event_receiver) = unbounded();

        let handle = thread::spawn(move || {
            debug!("new Player[{}]", session.session_id());

            let internal = PlayerInternal {
                session: session,
                config: config,
                commands: cmd_rx,

                state: PlayerState::Stopped,
                sink: sink_builder(),
                sink_running: false,
                audio_filter: audio_filter,
                event_sender: event_sender,
            };

            internal.run();
        });

        (Player { commands: Some(cmd_tx), thread_handle: Some(handle) },
         event_receiver)
    }

    fn command(&self, cmd: PlayerCommand) {
        self.commands.as_ref().unwrap().send(cmd).unwrap();
    }

    pub fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32)
        -> oneshot::Receiver<()>
    {
        let (tx, rx) = oneshot::channel();
        self.command(PlayerCommand::Load(track, start_playing, position_ms, tx));

        rx
    }

    pub fn play(&self) {
        self.command(PlayerCommand::Play)
    }

    pub fn pause(&self) {
        self.command(PlayerCommand::Pause)
    }

    pub fn stop(&self) {
        self.command(PlayerCommand::Stop)
    }

    pub fn seek(&self, position_ms: u32) {
        self.command(PlayerCommand::Seek(position_ms));
    }
}

impl Drop for Player {
    fn drop(&mut self) {
        debug!("Shutting down player thread ...");
        self.commands = None;
        if let Some(handle) = self.thread_handle.take() {
            match handle.join() {
                Ok(_) => (),
                Err(_) => error!("Player thread panicked!")
            }
        }
    }
}

type Decoder = VorbisDecoder<Subfile<AudioDecrypt<AudioFile>>>;
enum PlayerState {
    Stopped,
    Paused {
        track_id: SpotifyId,
        decoder: Decoder,
        end_of_track: oneshot::Sender<()>,
    },
    Playing {
        track_id: SpotifyId,
        decoder: Decoder,
        end_of_track: oneshot::Sender<()>,
    },
    EndOfTrack { track_id: SpotifyId },
    Invalid,
}

impl PlayerState {
    fn is_playing(&self) -> bool {
        use self::PlayerState::*;
        match *self {
            Stopped | EndOfTrack { .. } | Paused { .. } => false,
            Playing { .. } => true,
            Invalid => panic!("invalid state"),
        }
    }

    fn decoder(&mut self) -> Option<&mut Decoder> {
        use self::PlayerState::*;
        match *self {
            Stopped | EndOfTrack { .. } => None,
            Paused { ref mut decoder, .. } |
            Playing { ref mut decoder, .. } => Some(decoder),
            Invalid => panic!("invalid state"),
        }
    }

    fn send_end_of_track(self) {
        use self::PlayerState::*;
        match self {
            Paused { end_of_track, .. } |
            Playing { end_of_track, .. } => {
                let _ = end_of_track.send(());
            },
            _ => ()
        }
    }

    fn playing_to_end_of_track(&mut self) {
        use self::PlayerState::*;
        match *self {
            Paused { track_id, .. } |
            Playing { track_id, .. } => {
                let old_state = mem::replace(self, EndOfTrack { track_id });
                old_state.send_end_of_track();
            },
            _ => panic!("Called playing_to_end_of_track in non-playing state.")
        }
    }

    fn paused_to_playing(&mut self) {
        use self::PlayerState::*;
        match ::std::mem::replace(self, Invalid) {
            Paused { decoder, end_of_track, track_id } => {
                *self = Playing {
                    decoder: decoder,
                    end_of_track: end_of_track,
                    track_id: track_id,
                };
            }
            _ => panic!("invalid state"),
        }
    }

    fn playing_to_paused(&mut self) {
        use self::PlayerState::*;
        match ::std::mem::replace(self, Invalid) {
            Playing { decoder, end_of_track, track_id } => {
                *self = Paused {
                    decoder: decoder,
                    end_of_track: end_of_track,
                    track_id: track_id,
                };
            }
            _ => panic!("invalid state"),
        }
    }
}

impl PlayerInternal {
    fn run(mut self) {
        loop {
            let cmd = if self.state.is_playing() {
                if self.sink_running
                {
                    match self.commands.try_recv() {
                        Ok(cmd) => Some(cmd),
                        Err(TryRecvError::Empty) => None,
                        Err(TryRecvError::Disconnected) => return,
                    }
                }
                else
                {
                    match self.commands.recv_timeout(Duration::from_secs(5)) {
                        Ok(cmd) => Some(cmd),
                        Err(RecvTimeoutError::Timeout) => None,
                        Err(RecvTimeoutError::Disconnected) => return,
                    }
                }
            } else {
                match self.commands.recv() {
                    Ok(cmd) => Some(cmd),
                    Err(RecvError) => return,
                }
            };

            if let Some(cmd) = cmd {
                self.handle_command(cmd);
            }

            if self.state.is_playing() && ! self.sink_running {
                self.start_sink();
            }

            if self.sink_running {
                let packet = if let PlayerState::Playing { ref mut decoder, .. } = self.state {
                    Some(decoder.next_packet().expect("Vorbis error"))
                } else {
                    None
                };

                if let Some(packet) = packet {
                    self.handle_packet(packet);
                }
            }
        }
    }

    fn start_sink(&mut self) {
        match self.sink.start() {
            Ok(()) => self.sink_running = true,
            Err(err) => error!("Could not start audio: {}", err),
        }
    }

    fn stop_sink_if_running(&mut self) {
        if self.sink_running {
            self.stop_sink();
        }
    }

    fn stop_sink(&mut self) {
        self.sink.stop().unwrap();
        self.sink_running = false;
    }

    fn handle_packet(&mut self, packet: Option<VorbisPacket>) {
        match packet {
            Some(mut packet) => {
                if let Some(ref editor) = self.audio_filter {
                    editor.modify_stream(&mut packet.data_mut())
                };

                if let Err(err) = self.sink.write(&packet.data()) {
                    error!("Could not write audio: {}", err);
                    self.stop_sink();
                }
            }

            None => {
                self.stop_sink();
                self.state.playing_to_end_of_track();
            }
        }
    }

    fn handle_command(&mut self, cmd: PlayerCommand) {
        debug!("command={:?}", cmd);
        match cmd {
            PlayerCommand::Load(track_id, play, position, end_of_track) => {
                if self.state.is_playing() {
                    self.stop_sink_if_running();
                }

                match self.load_track(track_id, position as i64) {
                    Some(decoder) => {
                        if play {
                            match self.state {
                                PlayerState::Playing { track_id: old_track_id, ..}
                                | PlayerState::EndOfTrack { track_id: old_track_id, .. } =>
                                    self.send_event(PlayerEvent::Changed {
                                        old_track_id: old_track_id,
                                        new_track_id: track_id
                                    }),
                                _ => self.send_event(PlayerEvent::Started { track_id }),
                            }

                            self.start_sink();

                            self.state = PlayerState::Playing {
                                track_id: track_id,
                                decoder: decoder,
                                end_of_track: end_of_track,
                            };
                        } else {
                            self.state = PlayerState::Paused {
                                track_id: track_id,
                                decoder: decoder,
                                end_of_track: end_of_track,
                            };
                            match self.state {
                                PlayerState::Playing { track_id: old_track_id, ..}
                                | PlayerState::EndOfTrack { track_id: old_track_id, .. } =>
                                    self.send_event(PlayerEvent::Changed {
                                        old_track_id: old_track_id,
                                        new_track_id: track_id
                                    }),
                                _ => (),
                            }
                            self.send_event(PlayerEvent::Stopped { track_id });
                        }
                    }

                    None => {
                        let _ = end_of_track.send(());
                    }
                }
            }

            PlayerCommand::Seek(position) => {
                if let Some(decoder) = self.state.decoder() {
                    match decoder.seek(position as i64) {
                        Ok(_) => (),
                        Err(err) => error!("Vorbis error: {:?}", err),
                    }
                } else {
                    warn!("Player::seek called from invalid state");
                }
            }

            PlayerCommand::Play => {
                if let PlayerState::Paused { track_id, .. } = self.state {
                    self.state.paused_to_playing();

                    self.send_event(PlayerEvent::Started { track_id });
                    self.start_sink();
                } else {
                    warn!("Player::play called from invalid state");
                }
            }

            PlayerCommand::Pause => {
                if let PlayerState::Playing { track_id, .. } = self.state {
                    self.state.playing_to_paused();

                    self.stop_sink_if_running();
                    self.send_event(PlayerEvent::Stopped { track_id });
                } else {
                    warn!("Player::pause called from invalid state");
                }
            }

            PlayerCommand::Stop => {
                match self.state {
                    PlayerState::Playing { track_id, .. }
                    | PlayerState::Paused { track_id, .. }
                    | PlayerState::EndOfTrack { track_id } => {
                        self.stop_sink_if_running();
                        self.send_event(PlayerEvent::Stopped { track_id });
                        self.state = PlayerState::Stopped;
                    },
                    PlayerState::Stopped => {
                        warn!("Player::stop called from invalid state");
                    }
                    PlayerState::Invalid => panic!("invalid state"),
                }
            }
        }
    }

    fn send_event(&mut self, event: PlayerEvent) {
        let _ = self.event_sender.unbounded_send(event.clone());
    }

    fn find_available_alternative<'a>(&self, track: &'a Track) -> Option<Cow<'a, Track>> {
        if track.available {
            Some(Cow::Borrowed(track))
        } else {
            let alternatives = track.alternatives
                .iter()
                .map(|alt_id| {
                    Track::get(&self.session, *alt_id)
                });
            let alternatives = future::join_all(alternatives).wait().unwrap();

            alternatives.into_iter().find(|alt| alt.available).map(Cow::Owned)
        }
    }

    fn load_track(&self, track_id: SpotifyId, position: i64) -> Option<Decoder> {
        let track = Track::get(&self.session, track_id).wait().unwrap();

        info!("Loading track \"{}\"", track.name);

        let track = match self.find_available_alternative(&track) {
            Some(track) => track,
            None => {
                warn!("Track \"{}\" is not available", track.name);
                return None;
            }
        };

        let format = match self.config.bitrate {
            Bitrate::Bitrate96 => FileFormat::OGG_VORBIS_96,
            Bitrate::Bitrate160 => FileFormat::OGG_VORBIS_160,
            Bitrate::Bitrate320 => FileFormat::OGG_VORBIS_320,
        };

        let file_id = match track.files.get(&format) {
            Some(&file_id) => file_id,
            None => {
                warn!("Track \"{}\" is not available in format {:?}", track.name, format);
                return None;
            }
        };

        let key = self.session.audio_key().request(track.id, file_id).wait().unwrap();

        let encrypted_file = AudioFile::open(&self.session, file_id).wait().unwrap();
        let audio_file = Subfile::new(AudioDecrypt::new(key, encrypted_file), 0xa7);

        let mut decoder = VorbisDecoder::new(audio_file).unwrap();

        match decoder.seek(position) {
            Ok(_) => (),
            Err(err) => error!("Vorbis error: {:?}", err),
        }

        info!("Track \"{}\" loaded", track.name);

        Some(decoder)
    }
}

impl Drop for PlayerInternal {
    fn drop(&mut self) {
        debug!("drop Player[{}]", self.session.session_id());
    }
}

impl ::std::fmt::Debug for PlayerCommand {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            PlayerCommand::Load(track, play, position, _) => {
                f.debug_tuple("Load")
                 .field(&track)
                 .field(&play)
                 .field(&position)
                 .finish()
            }
            PlayerCommand::Play => {
                f.debug_tuple("Play").finish()
            }
            PlayerCommand::Pause => {
                f.debug_tuple("Pause").finish()
            }
            PlayerCommand::Stop => {
                f.debug_tuple("Stop").finish()
            }
            PlayerCommand::Seek(position) => {
                f.debug_tuple("Seek")
                 .field(&position)
                 .finish()
            }
        }
    }
}

struct Subfile<T: Read + Seek> {
    stream: T,
    offset: u64,
}

impl<T: Read + Seek> Subfile<T> {
    pub fn new(mut stream: T, offset: u64) -> Subfile<T> {
        stream.seek(SeekFrom::Start(offset)).unwrap();
        Subfile {
            stream: stream,
            offset: offset,
        }
    }
}

impl<T: Read + Seek> Read for Subfile<T> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.stream.read(buf)
    }
}

impl<T: Read + Seek> Seek for Subfile<T> {
    fn seek(&mut self, mut pos: SeekFrom) -> Result<u64> {
        pos = match pos {
            SeekFrom::Start(offset) => SeekFrom::Start(offset + self.offset),
            x => x,
        };

        let newpos = try!(self.stream.seek(pos));
        if newpos > self.offset {
            Ok(newpos - self.offset)
        } else {
            Ok(0)
        }
    }
}
<commit_msg>Minor fixes after review.<commit_after>use futures::sync::oneshot;
use futures::{future, Future};
use futures;
use std;
use std::borrow::Cow;
use std::io::{Read, Seek, SeekFrom, Result};
use std::mem;
use std::sync::mpsc::{RecvError, TryRecvError, RecvTimeoutError};
use std::thread;
use std::time::Duration;

use config::{Bitrate, PlayerConfig};
use core::session::Session;
use core::spotify_id::SpotifyId;

use audio_backend::Sink;
use audio::{AudioFile, AudioDecrypt};
use audio::{VorbisDecoder, VorbisPacket};
use metadata::{FileFormat, Track, Metadata};
use mixer::AudioFilter;

pub struct Player {
    commands: Option<std::sync::mpsc::Sender<PlayerCommand>>,
    thread_handle: Option<thread::JoinHandle<()>>,
}

struct PlayerInternal {
    session: Session,
    config: PlayerConfig,
    commands: std::sync::mpsc::Receiver<PlayerCommand>,

    state: PlayerState,
    sink: Box<Sink>,
    sink_running: bool,
    audio_filter: Option<Box<AudioFilter + Send>>,
    event_sender: futures::sync::mpsc::UnboundedSender<PlayerEvent>,
}

enum PlayerCommand {
    Load(SpotifyId, bool, u32, oneshot::Sender<()>),
    Play,
    Pause,
    Stop,
    Seek(u32),
}

#[derive(Debug, Clone)]
pub enum PlayerEvent {
    Started {
        track_id: SpotifyId,
    },

    Changed {
        old_track_id: SpotifyId,
        new_track_id: SpotifyId,
    },

    Stopped {
        track_id: SpotifyId,
    }
}

type PlayerEventChannel = futures::sync::mpsc::UnboundedReceiver<PlayerEvent>;
impl Player {
    pub fn new<F>(config: PlayerConfig, session: Session,
                  audio_filter: Option<Box<AudioFilter + Send>>,
                  sink_builder: F) -> (Player, PlayerEventChannel)
        where F: FnOnce() -> Box<Sink> + Send + 'static
    {
        let (cmd_tx, cmd_rx) = std::sync::mpsc::channel();
        let (event_sender, event_receiver) = futures::sync::mpsc::unbounded();

        let handle = thread::spawn(move || {
            debug!("new Player[{}]", session.session_id());

            let internal = PlayerInternal {
                session: session,
                config: config,
                commands: cmd_rx,

                state: PlayerState::Stopped,
                sink: sink_builder(),
                sink_running: false,
                audio_filter: audio_filter,
                event_sender: event_sender,
            };

            internal.run();
        });

        (Player { commands: Some(cmd_tx), thread_handle: Some(handle) },
         event_receiver)
    }

    fn command(&self, cmd: PlayerCommand) {
        self.commands.as_ref().unwrap().send(cmd).unwrap();
    }

    pub fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32)
        -> oneshot::Receiver<()>
    {
        let (tx, rx) = oneshot::channel();
        self.command(PlayerCommand::Load(track, start_playing, position_ms, tx));

        rx
    }

    pub fn play(&self) {
        self.command(PlayerCommand::Play)
    }

    pub fn pause(&self) {
        self.command(PlayerCommand::Pause)
    }

    pub fn stop(&self) {
        self.command(PlayerCommand::Stop)
    }

    pub fn seek(&self, position_ms: u32) {
        self.command(PlayerCommand::Seek(position_ms));
    }
}

impl Drop for Player {
    fn drop(&mut self) {
        debug!("Shutting down player thread ...");
        self.commands = None;
        if let Some(handle) = self.thread_handle.take() {
            match handle.join() {
                Ok(_) => (),
                Err(_) => error!("Player thread panicked!")
            }
        }
    }
}

type Decoder = VorbisDecoder<Subfile<AudioDecrypt<AudioFile>>>;
enum PlayerState {
    Stopped,
    Paused {
        track_id: SpotifyId,
        decoder: Decoder,
        end_of_track: oneshot::Sender<()>,
    },
    Playing {
        track_id: SpotifyId,
        decoder: Decoder,
        end_of_track: oneshot::Sender<()>,
    },
    EndOfTrack { track_id: SpotifyId },
    Invalid,
}

impl PlayerState {
    fn is_playing(&self) -> bool {
        use self::PlayerState::*;
        match *self {
            Stopped | EndOfTrack { .. } | Paused { .. } => false,
            Playing { .. } => true,
            Invalid => panic!("invalid state"),
        }
    }

    fn decoder(&mut self) -> Option<&mut Decoder> {
        use self::PlayerState::*;
        match *self {
            Stopped | EndOfTrack { .. } => None,
            Paused { ref mut decoder, .. } |
            Playing { ref mut decoder, .. } => Some(decoder),
            Invalid => panic!("invalid state"),
        }
    }

    fn playing_to_end_of_track(&mut self) {
        use self::PlayerState::*;
        match mem::replace(self, Invalid) {
            Playing { track_id, end_of_track, ..} => {
                end_of_track.send(());
                let old_state = mem::replace(self, EndOfTrack { track_id });
            },
            _ => panic!("Called playing_to_end_of_track in non-playing state.")
        }
    }

    fn paused_to_playing(&mut self) {
        use self::PlayerState::*;
        match ::std::mem::replace(self, Invalid) {
            Paused { decoder, end_of_track, track_id } => {
                *self = Playing {
                    decoder: decoder,
                    end_of_track: end_of_track,
                    track_id: track_id,
                };
            }
            _ => panic!("invalid state"),
        }
    }

    fn playing_to_paused(&mut self) {
        use self::PlayerState::*;
        match ::std::mem::replace(self, Invalid) {
            Playing { decoder, end_of_track, track_id } => {
                *self = Paused {
                    decoder: decoder,
                    end_of_track: end_of_track,
                    track_id: track_id,
                };
            }
            _ => panic!("invalid state"),
        }
    }
}

impl PlayerInternal {
    fn run(mut self) {
        loop {
            let cmd = if self.state.is_playing() {
                if self.sink_running
                {
                    match self.commands.try_recv() {
                        Ok(cmd) => Some(cmd),
                        Err(TryRecvError::Empty) => None,
                        Err(TryRecvError::Disconnected) => return,
                    }
                }
                else
                {
                    match self.commands.recv_timeout(Duration::from_secs(5)) {
                        Ok(cmd) => Some(cmd),
                        Err(RecvTimeoutError::Timeout) => None,
                        Err(RecvTimeoutError::Disconnected) => return,
                    }
                }
            } else {
                match self.commands.recv() {
                    Ok(cmd) => Some(cmd),
                    Err(RecvError) => return,
                }
            };

            if let Some(cmd) = cmd {
                self.handle_command(cmd);
            }

            if self.state.is_playing() && ! self.sink_running {
                self.start_sink();
            }

            if self.sink_running {
                let packet = if let PlayerState::Playing { ref mut decoder, .. } = self.state {
                    Some(decoder.next_packet().expect("Vorbis error"))
                } else {
                    None
                };

                if let Some(packet) = packet {
                    self.handle_packet(packet);
                }
            }
        }
    }

    fn start_sink(&mut self) {
        match self.sink.start() {
            Ok(()) => self.sink_running = true,
            Err(err) => error!("Could not start audio: {}", err),
        }
    }

    fn stop_sink_if_running(&mut self) {
        if self.sink_running {
            self.stop_sink();
        }
    }

    fn stop_sink(&mut self) {
        self.sink.stop().unwrap();
        self.sink_running = false;
    }

    fn handle_packet(&mut self, packet: Option<VorbisPacket>) {
        match packet {
            Some(mut packet) => {
                if let Some(ref editor) = self.audio_filter {
                    editor.modify_stream(&mut packet.data_mut())
                };

                if let Err(err) = self.sink.write(&packet.data()) {
                    error!("Could not write audio: {}", err);
                    self.stop_sink();
                }
            }

            None => {
                self.stop_sink();
                self.state.playing_to_end_of_track();
            }
        }
    }

    fn handle_command(&mut self, cmd: PlayerCommand) {
        debug!("command={:?}", cmd);
        match cmd {
            PlayerCommand::Load(track_id, play, position, end_of_track) => {
                if self.state.is_playing() {
                    self.stop_sink_if_running();
                }

                match self.load_track(track_id, position as i64) {
                    Some(decoder) => {
                        if play {
                            match self.state {
                                PlayerState::Playing { track_id: old_track_id, ..}
                                | PlayerState::EndOfTrack { track_id: old_track_id, .. } =>
                                    self.send_event(PlayerEvent::Changed {
                                        old_track_id: old_track_id,
                                        new_track_id: track_id
                                    }),
                                _ => self.send_event(PlayerEvent::Started { track_id }),
                            }

                            self.start_sink();

                            self.state = PlayerState::Playing {
                                track_id: track_id,
                                decoder: decoder,
                                end_of_track: end_of_track,
                            };
                        } else {
                            self.state = PlayerState::Paused {
                                track_id: track_id,
                                decoder: decoder,
                                end_of_track: end_of_track,
                            };
                            match self.state {
                                PlayerState::Playing { track_id: old_track_id, ..}
                                | PlayerState::EndOfTrack { track_id: old_track_id, .. } =>
                                    self.send_event(PlayerEvent::Changed {
                                        old_track_id: old_track_id,
                                        new_track_id: track_id
                                    }),
                                _ => (),
                            }
                            self.send_event(PlayerEvent::Stopped { track_id });
                        }
                    }

                    None => {
                        let _ = end_of_track.send(());
                    }
                }
            }

            PlayerCommand::Seek(position) => {
                if let Some(decoder) = self.state.decoder() {
                    match decoder.seek(position as i64) {
                        Ok(_) => (),
                        Err(err) => error!("Vorbis error: {:?}", err),
                    }
                } else {
                    warn!("Player::seek called from invalid state");
                }
            }

            PlayerCommand::Play => {
                if let PlayerState::Paused { track_id, .. } = self.state {
                    self.state.paused_to_playing();

                    self.send_event(PlayerEvent::Started { track_id });
                    self.start_sink();
                } else {
                    warn!("Player::play called from invalid state");
                }
            }

            PlayerCommand::Pause => {
                if let PlayerState::Playing { track_id, .. } = self.state {
                    self.state.playing_to_paused();

                    self.stop_sink_if_running();
                    self.send_event(PlayerEvent::Stopped { track_id });
                } else {
                    warn!("Player::pause called from invalid state");
                }
            }

            PlayerCommand::Stop => {
                match self.state {
                    PlayerState::Playing { track_id, .. }
                    | PlayerState::Paused { track_id, .. }
                    | PlayerState::EndOfTrack { track_id } => {
                        self.stop_sink_if_running();
                        self.send_event(PlayerEvent::Stopped { track_id });
                        self.state = PlayerState::Stopped;
                    },
                    PlayerState::Stopped => {
                        warn!("Player::stop called from invalid state");
                    }
                    PlayerState::Invalid => panic!("invalid state"),
                }
            }
        }
    }

    fn send_event(&mut self, event: PlayerEvent) {
        let _ = self.event_sender.unbounded_send(event.clone());
    }

    fn find_available_alternative<'a>(&self, track: &'a Track) -> Option<Cow<'a, Track>> {
        if track.available {
            Some(Cow::Borrowed(track))
        } else {
            let alternatives = track.alternatives
                .iter()
                .map(|alt_id| {
                    Track::get(&self.session, *alt_id)
                });
            let alternatives = future::join_all(alternatives).wait().unwrap();

            alternatives.into_iter().find(|alt| alt.available).map(Cow::Owned)
        }
    }

    fn load_track(&self, track_id: SpotifyId, position: i64) -> Option<Decoder> {
        let track = Track::get(&self.session, track_id).wait().unwrap();

        info!("Loading track \"{}\"", track.name);

        let track = match self.find_available_alternative(&track) {
            Some(track) => track,
            None => {
                warn!("Track \"{}\" is not available", track.name);
                return None;
            }
        };

        let format = match self.config.bitrate {
            Bitrate::Bitrate96 => FileFormat::OGG_VORBIS_96,
            Bitrate::Bitrate160 => FileFormat::OGG_VORBIS_160,
            Bitrate::Bitrate320 => FileFormat::OGG_VORBIS_320,
        };

        let file_id = match track.files.get(&format) {
            Some(&file_id) => file_id,
            None => {
                warn!("Track \"{}\" is not available in format {:?}", track.name, format);
                return None;
            }
        };

        let key = self.session.audio_key().request(track.id, file_id).wait().unwrap();

        let encrypted_file = AudioFile::open(&self.session, file_id).wait().unwrap();
        let audio_file = Subfile::new(AudioDecrypt::new(key, encrypted_file), 0xa7);

        let mut decoder = VorbisDecoder::new(audio_file).unwrap();

        match decoder.seek(position) {
            Ok(_) => (),
            Err(err) => error!("Vorbis error: {:?}", err),
        }

        info!("Track \"{}\" loaded", track.name);

        Some(decoder)
    }
}

impl Drop for PlayerInternal {
    fn drop(&mut self) {
        debug!("drop Player[{}]", self.session.session_id());
    }
}

impl ::std::fmt::Debug for PlayerCommand {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            PlayerCommand::Load(track, play, position, _) => {
                f.debug_tuple("Load")
                 .field(&track)
                 .field(&play)
                 .field(&position)
                 .finish()
            }
            PlayerCommand::Play => {
                f.debug_tuple("Play").finish()
            }
            PlayerCommand::Pause => {
                f.debug_tuple("Pause").finish()
            }
            PlayerCommand::Stop => {
                f.debug_tuple("Stop").finish()
            }
            PlayerCommand::Seek(position) => {
                f.debug_tuple("Seek")
                 .field(&position)
                 .finish()
            }
        }
    }
}

struct Subfile<T: Read + Seek> {
    stream: T,
    offset: u64,
}

impl<T: Read + Seek> Subfile<T> {
    pub fn new(mut stream: T, offset: u64) -> Subfile<T> {
        stream.seek(SeekFrom::Start(offset)).unwrap();
        Subfile {
            stream: stream,
            offset: offset,
        }
    }
}

impl<T: Read + Seek> Read for Subfile<T> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
        self.stream.read(buf)
    }
}

impl<T: Read + Seek> Seek for Subfile<T> {
    fn seek(&mut self, mut pos: SeekFrom) -> Result<u64> {
        pos = match pos {
            SeekFrom::Start(offset) => SeekFrom::Start(offset + self.offset),
            x => x,
        };

        let newpos = try!(self.stream.seek(pos));
        if newpos > self.offset {
            Ok(newpos - self.offset)
        } else {
            Ok(0)
        }
    }
}
<|endoftext|>


<commit_before>//! utilities for convert array

use ndarray::*;

use super::error::*;
use super::lapack::UPLO;
use super::layout::*;
use super::types::*;

pub fn into_col<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
where
    S: Data,
{
    let n = a.len();
    a.into_shape((n, 1)).unwrap()
}

pub fn into_row<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
where
    S: Data,
{
    let n = a.len();
    a.into_shape((1, n)).unwrap()
}

pub fn flatten<S>(a: ArrayBase<S, Ix2>) -> ArrayBase<S, Ix1>
where
    S: Data,
{
    let n = a.len();
    a.into_shape(n).unwrap()
}

pub fn into_matrix<A, S>(l: MatrixLayout, a: Vec<A>) -> Result<ArrayBase<S, Ix2>>
where
    S: DataOwned<Elem = A>,
{
    match l {
        MatrixLayout::C { row, lda } => {
            Ok(ArrayBase::from_shape_vec((row as usize, lda as usize), a)?)
        }
        MatrixLayout::F { col, lda } => Ok(ArrayBase::from_shape_vec(
            (lda as usize, col as usize).f(),
            a,
        )?),
    }
}

fn uninitialized<A, S>(l: MatrixLayout) -> ArrayBase<S, Ix2>
where
    A: Copy,
    S: DataOwned<Elem = A>,
{
    match l {
        MatrixLayout::C { row, lda } => unsafe {
            ArrayBase::uninitialized((row as usize, lda as usize))
        },
        MatrixLayout::F { col, lda } => unsafe {
            ArrayBase::uninitialized((lda as usize, col as usize).f())
        },
    }
}

pub fn replicate<A, Sv, So, D>(a: &ArrayBase<Sv, D>) -> ArrayBase<So, D>
where
    A: Copy,
    Sv: Data<Elem = A>,
    So: DataOwned<Elem = A> + DataMut,
    D: Dimension,
{
    let mut b = unsafe { ArrayBase::uninitialized(a.dim()) };
    b.assign(a);
    b
}

fn clone_with_layout<A, Si, So>(l: MatrixLayout, a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2>
where
    A: Copy,
    Si: Data<Elem = A>,
    So: DataOwned<Elem = A> + DataMut,
{
    let mut b = uninitialized(l);
    b.assign(a);
    b
}

pub fn transpose_data<A, S>(a: &mut ArrayBase<S, Ix2>) -> Result<&mut ArrayBase<S, Ix2>>
where
    A: Copy,
    S: DataOwned<Elem = A> + DataMut,
{
    let l = a.layout()?.toggle_order();
    let new = clone_with_layout(l, a);
    ::std::mem::replace(a, new);
    Ok(a)
}

pub fn generalize<A, S, D>(a: Array<A, D>) -> ArrayBase<S, D>
where
    S: DataOwned<Elem = A>,
    D: Dimension,
{
    // FIXME
    // https://github.com/bluss/rust-ndarray/issues/325
    let strides: Vec<isize> = a.strides().to_vec();
    let new = if a.is_standard_layout() {
        ArrayBase::from_shape_vec(a.dim(), a.into_raw_vec()).unwrap()
    } else {
        ArrayBase::from_shape_vec(a.dim().f(), a.into_raw_vec()).unwrap()
    };
    assert_eq!(
        new.strides(),
        strides.as_slice(),
        "Custom stride is not supported"
    );
    new
}

/// Fills in the remainder of a Hermitian matrix that's represented by only one
/// triangle.
///
/// LAPACK methods on Hermitian matrices usually read/write only one triangular
/// portion of the matrix. This function fills in the other half based on the
/// data in the triangular portion corresponding to `uplo`.
///
/// ***Panics*** if `a` is not square.
pub(crate) fn triangular_fill_hermitian<A, S>(a: &mut ArrayBase<S, Ix2>, uplo: UPLO)
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    assert!(a.is_square());
    match uplo {
        UPLO::Upper => {
            for row in 0..a.nrows() {
                for col in 0..row {
                    a[(row, col)] = a[(col, row)].conj();
                }
            }
        }
        UPLO::Lower => {
            for col in 0..a.ncols() {
                for row in 0..col {
                    a[(row, col)] = a[(col, row)].conj();
                }
            }
        }
    }
}
<commit_msg>clippy mem::replace must_use warning<commit_after>//! utilities for convert array

use ndarray::*;

use super::error::*;
use super::lapack::UPLO;
use super::layout::*;
use super::types::*;

pub fn into_col<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
where
    S: Data,
{
    let n = a.len();
    a.into_shape((n, 1)).unwrap()
}

pub fn into_row<S>(a: ArrayBase<S, Ix1>) -> ArrayBase<S, Ix2>
where
    S: Data,
{
    let n = a.len();
    a.into_shape((1, n)).unwrap()
}

pub fn flatten<S>(a: ArrayBase<S, Ix2>) -> ArrayBase<S, Ix1>
where
    S: Data,
{
    let n = a.len();
    a.into_shape(n).unwrap()
}

pub fn into_matrix<A, S>(l: MatrixLayout, a: Vec<A>) -> Result<ArrayBase<S, Ix2>>
where
    S: DataOwned<Elem = A>,
{
    match l {
        MatrixLayout::C { row, lda } => {
            Ok(ArrayBase::from_shape_vec((row as usize, lda as usize), a)?)
        }
        MatrixLayout::F { col, lda } => Ok(ArrayBase::from_shape_vec(
            (lda as usize, col as usize).f(),
            a,
        )?),
    }
}

fn uninitialized<A, S>(l: MatrixLayout) -> ArrayBase<S, Ix2>
where
    A: Copy,
    S: DataOwned<Elem = A>,
{
    match l {
        MatrixLayout::C { row, lda } => unsafe {
            ArrayBase::uninitialized((row as usize, lda as usize))
        },
        MatrixLayout::F { col, lda } => unsafe {
            ArrayBase::uninitialized((lda as usize, col as usize).f())
        },
    }
}

pub fn replicate<A, Sv, So, D>(a: &ArrayBase<Sv, D>) -> ArrayBase<So, D>
where
    A: Copy,
    Sv: Data<Elem = A>,
    So: DataOwned<Elem = A> + DataMut,
    D: Dimension,
{
    let mut b = unsafe { ArrayBase::uninitialized(a.dim()) };
    b.assign(a);
    b
}

fn clone_with_layout<A, Si, So>(l: MatrixLayout, a: &ArrayBase<Si, Ix2>) -> ArrayBase<So, Ix2>
where
    A: Copy,
    Si: Data<Elem = A>,
    So: DataOwned<Elem = A> + DataMut,
{
    let mut b = uninitialized(l);
    b.assign(a);
    b
}

pub fn transpose_data<A, S>(a: &mut ArrayBase<S, Ix2>) -> Result<&mut ArrayBase<S, Ix2>>
where
    A: Copy,
    S: DataOwned<Elem = A> + DataMut,
{
    let l = a.layout()?.toggle_order();
    let new = clone_with_layout(l, a);
    *a = new;
    Ok(a)
}

pub fn generalize<A, S, D>(a: Array<A, D>) -> ArrayBase<S, D>
where
    S: DataOwned<Elem = A>,
    D: Dimension,
{
    // FIXME
    // https://github.com/bluss/rust-ndarray/issues/325
    let strides: Vec<isize> = a.strides().to_vec();
    let new = if a.is_standard_layout() {
        ArrayBase::from_shape_vec(a.dim(), a.into_raw_vec()).unwrap()
    } else {
        ArrayBase::from_shape_vec(a.dim().f(), a.into_raw_vec()).unwrap()
    };
    assert_eq!(
        new.strides(),
        strides.as_slice(),
        "Custom stride is not supported"
    );
    new
}

/// Fills in the remainder of a Hermitian matrix that's represented by only one
/// triangle.
///
/// LAPACK methods on Hermitian matrices usually read/write only one triangular
/// portion of the matrix. This function fills in the other half based on the
/// data in the triangular portion corresponding to `uplo`.
///
/// ***Panics*** if `a` is not square.
pub(crate) fn triangular_fill_hermitian<A, S>(a: &mut ArrayBase<S, Ix2>, uplo: UPLO)
where
    A: Scalar + Lapack,
    S: DataMut<Elem = A>,
{
    assert!(a.is_square());
    match uplo {
        UPLO::Upper => {
            for row in 0..a.nrows() {
                for col in 0..row {
                    a[(row, col)] = a[(col, row)].conj();
                }
            }
        }
        UPLO::Lower => {
            for col in 0..a.ncols() {
                for row in 0..col {
                    a[(row, col)] = a[(col, row)].conj();
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>state-res: Fix knocking support<commit_after><|endoftext|>


<commit_before>extern crate abra;
extern crate rocksdb;
extern crate rustc_serialize;

use std::sync::Arc;

use rocksdb::{DB, Writable, Options};
use abra::schema::{Schema, FieldType, FieldRef, AddFieldError};
use rustc_serialize::{json, Encodable};

pub struct RocksDBIndexStore {
    schema: Arc<Schema>,
    db: DB,
}

impl RocksDBIndexStore {
    pub fn create(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        let db = try!(DB::open(&opts, path));

        // Schema
        let schema = Schema::new();
        db.put(b"schema", json::encode(&schema).unwrap().as_bytes());

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn open(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        let db = try!(DB::open(&opts, path));

        let schema = match db.get(b"schema") {
            Ok(Some(schema)) => {
                let schema = schema.to_utf8().unwrap().to_string();
                json::decode(&schema).unwrap()
            }
            Ok(None) => Schema::new(),  // TODO: error
            Err(_) => Schema::new(),  // TODO: error
        };

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn add_field(&mut self, name: String, field_type: FieldType) -> Result<FieldRef, AddFieldError> {
        let mut schema_copy = (*self.schema).clone();
        let field_ref = try!(schema_copy.add_field(name, field_type));
        self.schema = Arc::new(schema_copy);

        self.db.put(b"schema", json::encode(&self.schema).unwrap().as_bytes());

        Ok(field_ref)
    }
}

#[cfg(test)]
mod tests {
    use rocksdb::{DB, Options};

    use super::RocksDBIndexStore;

    fn clean_test_indices() {
        use std::fs::remove_dir_all;

        remove_dir_all("test_indices");
    }

    #[test]
    fn test_create() {
        clean_test_indices();

        let store = RocksDBIndexStore::create("test_indices/test_create");
        assert!(store.is_ok());
    }

    #[test]
    fn test_open() {
        clean_test_indices();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_err());

        // Create DB
        let mut opts = Options::default();
        opts.create_if_missing(true);
        DB::open(&opts, "test_indices/test_open").unwrap();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_ok());
    }
}
<commit_msg>Implemented remove_field<commit_after>extern crate abra;
extern crate rocksdb;
extern crate rustc_serialize;

use std::sync::Arc;

use rocksdb::{DB, Writable, Options};
use abra::schema::{Schema, FieldType, FieldRef, AddFieldError};
use rustc_serialize::{json, Encodable};

pub struct RocksDBIndexStore {
    schema: Arc<Schema>,
    db: DB,
}

impl RocksDBIndexStore {
    pub fn create(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        let db = try!(DB::open(&opts, path));

        // Schema
        let schema = Schema::new();
        db.put(b"schema", json::encode(&schema).unwrap().as_bytes());

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn open(path: &str) -> Result<RocksDBIndexStore, String> {
        let mut opts = Options::default();
        let db = try!(DB::open(&opts, path));

        let schema = match db.get(b"schema") {
            Ok(Some(schema)) => {
                let schema = schema.to_utf8().unwrap().to_string();
                json::decode(&schema).unwrap()
            }
            Ok(None) => Schema::new(),  // TODO: error
            Err(_) => Schema::new(),  // TODO: error
        };

        Ok(RocksDBIndexStore {
            schema: Arc::new(schema),
            db: db,
        })
    }

    pub fn add_field(&mut self, name: String, field_type: FieldType) -> Result<FieldRef, AddFieldError> {
        let mut schema_copy = (*self.schema).clone();
        let field_ref = try!(schema_copy.add_field(name, field_type));
        self.schema = Arc::new(schema_copy);

        self.db.put(b"schema", json::encode(&self.schema).unwrap().as_bytes());

        Ok(field_ref)
    }

    pub fn remove_field(&mut self, field_ref: &FieldRef) -> bool {
        let mut schema_copy = (*self.schema).clone();
        let field_removed = schema_copy.remove_field(field_ref);

        if field_removed {
            self.schema = Arc::new(schema_copy);
            self.db.put(b"schema", json::encode(&self.schema).unwrap().as_bytes());
        }

        field_removed
    }
}

#[cfg(test)]
mod tests {
    use rocksdb::{DB, Options};

    use super::RocksDBIndexStore;

    fn clean_test_indices() {
        use std::fs::remove_dir_all;

        remove_dir_all("test_indices");
    }

    #[test]
    fn test_create() {
        clean_test_indices();

        let store = RocksDBIndexStore::create("test_indices/test_create");
        assert!(store.is_ok());
    }

    #[test]
    fn test_open() {
        clean_test_indices();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_err());

        // Create DB
        let mut opts = Options::default();
        opts.create_if_missing(true);
        DB::open(&opts, "test_indices/test_open").unwrap();

        let store = RocksDBIndexStore::open("test_indices/test_open");
        assert!(store.is_ok());
    }
}
<|endoftext|>


<commit_before>extern crate IOKit_sys;
extern crate CoreFoundation_sys as cf;
extern crate libc;
extern crate mach;

use std::mem;
use std::ptr;

use std::ffi::{CString,CStr};

use libc::{c_char,c_void};

use mach::port::{mach_port_t,MACH_PORT_NULL};
use mach::kern_return::KERN_SUCCESS;

use IOKit_sys::*;
use cf::*;

fn main() {
    unsafe {
        let mut master_port: mach_port_t = MACH_PORT_NULL;

        let classes_to_match = IOServiceMatching(kIOSerialBSDServiceValue());
        if classes_to_match.is_null() {
            panic!("IOServiceMatching returned a NULL dictionary.");
        }

        // build key
        let key = CFStringCreateWithCString(kCFAllocatorDefault, kIOSerialBSDTypeKey(), kCFStringEncodingUTF8);
        if key.is_null() {
            panic!("failed to allocate key string");
        }

        // verify key
        let mut buf = Vec::<c_char>::with_capacity(256);
        CFStringGetCString(key, buf.as_mut_ptr(), 256, kCFStringEncodingUTF8);
        println!("key: {:?}", CString::new(CStr::from_ptr(buf.as_ptr()).to_bytes()));

        // build value
        let val = CFStringCreateWithCString(kCFAllocatorDefault, kIOSerialBSDRS232Type(), kCFStringEncodingUTF8);
        if val.is_null() {
            panic!("failed to allocate value string");
        }

        // verify value
        CFStringGetCString(val, buf.as_mut_ptr(), 256, kCFStringEncodingUTF8);
        println!("val: {:?}", CString::new(CStr::from_ptr(buf.as_ptr()).to_bytes()));

        // set value in dictionary
        CFDictionarySetValue(classes_to_match, key as CFTypeRef, val as CFTypeRef);

        let cfstr = CFDictionaryGetValue(classes_to_match, key as CFTypeRef) as CFStringRef;
        CFStringGetCString(cfstr, buf.as_mut_ptr(), 256, kCFStringEncodingUTF8);
        println!("in dict: {:?}", CString::new(CStr::from_ptr(buf.as_ptr()).to_bytes()));

        let mut kern_result = IOMasterPort(MACH_PORT_NULL, &mut master_port);
        println!("IOMasterPort returned {}", kern_result);
        if kern_result != KERN_SUCCESS {
            panic!("ERROR");
        }

        let mut matching_services: io_iterator_t = mem::uninitialized();

        kern_result = IOServiceGetMatchingServices(kIOMasterPortDefault, classes_to_match, &mut matching_services);
        println!("IOServiceGetMatchingServices returned {}", kern_result);
        if kern_result != KERN_SUCCESS {
            panic!("ERROR");
        }

        loop {
            let modem_service = IOIteratorNext(matching_services);

            if modem_service == MACH_PORT_NULL {
                break;
            }

            println!("examining service");

            let mut props = mem::uninitialized();
            let result = IORegistryEntryCreateCFProperties(modem_service, &mut props, kCFAllocatorDefault, 0);

            if result == KERN_SUCCESS {
                CFDictionaryApplyFunction(props, print_property_entry, ptr::null());
            }

            IOObjectRelease(modem_service);
        }
    }
}

extern "C" fn print_property_entry(key: *const c_void, value: *const c_void, _context: *const c_void) {
    unsafe {
        let mut buf = Vec::<c_char>::with_capacity(256);

        CFStringGetCString(key as CFStringRef, buf.as_mut_ptr(), 256, kCFStringEncodingUTF8);
        println!("key: {:?}", CString::new(CStr::from_ptr(buf.as_ptr()).to_bytes()));

        print_object(value);
    }
}

unsafe fn print_object(obj: CFTypeRef) {
    let type_id = CFGetTypeID(obj);

    if type_id == CFStringGetTypeID() {
        let mut buf = Vec::<c_char>::with_capacity(256);

        CFStringGetCString(obj as CFStringRef, buf.as_mut_ptr(), 256, kCFStringEncodingUTF8);
        println!("value: {:?}", CString::new(CStr::from_ptr(buf.as_ptr()).to_bytes()));
    }
    else {
        println!("unhandled type ID: {}", type_id);
    }
}
<commit_msg>cleans up example<commit_after>extern crate IOKit_sys;
extern crate CoreFoundation_sys as cf;
extern crate libc;
extern crate mach;

use std::mem;
use std::ptr;

use std::ffi::{CString,CStr};

use libc::{c_char,c_void};

use mach::port::{mach_port_t,MACH_PORT_NULL};
use mach::kern_return::KERN_SUCCESS;

use IOKit_sys::*;
use cf::*;

fn main() {
    unsafe {
        let mut master_port: mach_port_t = MACH_PORT_NULL;

        let classes_to_match = IOServiceMatching(kIOSerialBSDServiceValue());
        if classes_to_match.is_null() {
            panic!("IOServiceMatching returned a NULL dictionary.");
        }

        // build key
        let key = CFStringCreateWithCString(kCFAllocatorDefault, kIOSerialBSDTypeKey(), kCFStringEncodingUTF8);
        if key.is_null() {
            panic!("failed to allocate key string");
        }

        // build value
        let val = CFStringCreateWithCString(kCFAllocatorDefault, kIOSerialBSDRS232Type(), kCFStringEncodingUTF8);
        if val.is_null() {
            panic!("failed to allocate value string");
        }

        // set value in dictionary
        CFDictionarySetValue(classes_to_match, key as CFTypeRef, val as CFTypeRef);

        let mut kern_result = IOMasterPort(MACH_PORT_NULL, &mut master_port);
        if kern_result != KERN_SUCCESS {
            panic!("ERROR: {}", kern_result);
        }

        let mut matching_services: io_iterator_t = mem::uninitialized();

        kern_result = IOServiceGetMatchingServices(kIOMasterPortDefault, classes_to_match, &mut matching_services);
        if kern_result != KERN_SUCCESS {
            panic!("ERROR: {}", kern_result);
        }

        loop {
            let modem_service = IOIteratorNext(matching_services);

            if modem_service == MACH_PORT_NULL {
                break;
            }

            let mut props = mem::uninitialized();

            let result = IORegistryEntryCreateCFProperties(modem_service, &mut props, kCFAllocatorDefault, 0);
            if result == KERN_SUCCESS {
                CFDictionaryApplyFunction(props, print_property_entry, ptr::null());
            }

            IOObjectRelease(modem_service);
        }
    }
}

extern "C" fn print_property_entry(key: CFTypeRef, value: CFTypeRef, _context: *const c_void) {
    unsafe {
        let mut buf = Vec::<c_char>::with_capacity(256);

        CFStringGetCString(key as CFStringRef, buf.as_mut_ptr(), 256, kCFStringEncodingUTF8);
        print!("{:?} => ", CString::new(CStr::from_ptr(buf.as_ptr()).to_bytes()).unwrap());

        print_object(value);
    }
}

unsafe fn print_object(obj: CFTypeRef) {
    let type_id = CFGetTypeID(obj);

    if type_id == CFStringGetTypeID() {
        let mut buf = Vec::<c_char>::with_capacity(256);

        CFStringGetCString(obj as CFStringRef, buf.as_mut_ptr(), 256, kCFStringEncodingUTF8);
        println!("{:?}", CString::new(CStr::from_ptr(buf.as_ptr()).to_bytes()).unwrap());
    }
    else {
        println!("unhandled type ID: {}", type_id);
    }
}
<|endoftext|>


<commit_before>// structs1.rs
// Address all the TODOs to make the tests pass!

struct ColorClassicStruct {
    // TODO: Something goes here
}

struct ColorTupleStruct(/* TODO: Something goes here */);

#[derive(Debug)]
struct UnitStruct;

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

    #[test]
    fn classic_c_structs() {
        // TODO: Instantiate a classic c struct!
        // let green =

        assert_eq!(green.name, "green");
        assert_eq!(green.hex, "#00FF00");
    }

    #[test]
    fn tuple_structs() {
        // TODO: Instantiate a tuple struct!
        // For more fun, use the field initialization shorthand.
        // let green =

        assert_eq!(green.0, "green");
        assert_eq!(green.1, "#00FF00");
    }

    #[test]
    fn unit_structs() {
        // TODO: Instantiate a unit struct!
        // let unit_struct =
        let message = format!("{:?}s are fun!", unit_struct);

        assert_eq!(message, "UnitStructs are fun!");
    }
}
<commit_msg>fix(structs1): Remove misleading comment<commit_after>// structs1.rs
// Address all the TODOs to make the tests pass!

struct ColorClassicStruct {
    // TODO: Something goes here
}

struct ColorTupleStruct(/* TODO: Something goes here */);

#[derive(Debug)]
struct UnitStruct;

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

    #[test]
    fn classic_c_structs() {
        // TODO: Instantiate a classic c struct!
        // let green =

        assert_eq!(green.name, "green");
        assert_eq!(green.hex, "#00FF00");
    }

    #[test]
    fn tuple_structs() {
        // TODO: Instantiate a tuple struct!
        // let green =

        assert_eq!(green.0, "green");
        assert_eq!(green.1, "#00FF00");
    }

    #[test]
    fn unit_structs() {
        // TODO: Instantiate a unit struct!
        // let unit_struct =
        let message = format!("{:?}s are fun!", unit_struct);

        assert_eq!(message, "UnitStructs are fun!");
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate nickel;
extern crate regex;
extern crate rustc_serialize;
extern crate hyper;

use std::io::Write;
use nickel::status::StatusCode::{self, NotFound};
use nickel::{
    Nickel, NickelError, Continue, Halt, Request, Response, MediaType,
    QueryString, JsonBody, StaticFilesHandler, MiddlewareResult, HttpRouter, Action
};
use regex::Regex;
use hyper::header::Location;

#[derive(RustcDecodable, RustcEncodable)]
struct Person {
    firstname: String,
    lastname:  String,
}

//this is an example middleware function that just logs each request
fn logger<'a>(request: &mut Request, response: Response<'a>) -> MiddlewareResult<'a> {
    println!("logging request: {:?}", request.origin.uri);
    Ok(Continue(response))
}

//this is how to overwrite the default error handler to handle 404 cases with a custom view
fn custom_404<'a>(err: &mut NickelError, _req: &mut Request) -> Action {
    if let Some(ref mut res) = err.stream {
        if res.status() == NotFound {
            let _ = res.write_all(b"
Call the police!
");
            return Halt(())
        }
    }

    Continue(())
}

fn main() {
    let mut server = Nickel::new();

    // middleware is optional and can be registered with `utilize`
    server.utilize(logger);

    // go to http://localhost:6767/thoughtram_logo_brain.png to see static file serving in action
    server.utilize(StaticFilesHandler::new("examples/assets/"));

    let hello_regex = Regex::new("/hello/(?P<name>[a-zA-Z]+)").unwrap();

    // The return type for a route can be anything that implements `Responder`
    server.utilize(router!(
        // go to http://localhost:6767/user/4711 to see this route in action
        get "/user/:userid" => |request| {
            // returning a String
            format!("This is user: {}", request.param("userid"))
        }

        // go to http://localhost:6767/no_alloc/4711 to see this route in action
        get "/no_alloc/:userid" => |request, response| {
            // returning a slice of T where T: Display
            &["This is user: ", request.param("userid")][..]
        }

        // go to http://localhost:6767/bar to see this route in action
        get "/bar" => {
            // returning a http status code and a static string
            (200u16, "This is the /bar handler")
        }

        // go to http://localhost:6767/content-type to see this route in action
        get "/content-type" => |_, mut response| {
            response.set(MediaType::Json);
            "{'foo':'bar'}"
        }

        // go to http://localhost:6767/hello/moomah to see this route in action
        get hello_regex => |request| {
            format!("Hello {}", request.param("name"))
        }

        // go to http://localhost:6767/redirect to see this route in action
        get "/redirect" => |_, mut response| {
            response.set(Location("http://nickel.rs".into()));

            StatusCode::PermanentRedirect
        }

        // go to http://localhost:6767/private to see this route in action
        get "/private" => {
            // returning a typed http status and a response body
            (StatusCode::Unauthorized, "This is a private place")
        }

        // go to http://localhost:6767/some/crazy/route to see this route in action
        get "/some/*/route" => {
            // returning a static string
            "This matches /some/crazy/route but not /some/super/crazy/route"
        }

        // go to http://localhost:6767/some/crazy/route to see this route in action
        get "/a/**/route" => {
            "This matches /a/crazy/route and also /a/super/crazy/route"
        }

        // try it with curl
        // curl 'http://localhost:6767/a/post/request' -H 'Content-Type: application/json;charset=UTF-8'  --data-binary $'{ "firstname": "John","lastname": "Connor" }'
        post "/a/post/request" => |request| {
            let person = request.json_as::<Person>().unwrap();
            format!("Hello {} {}", person.firstname, person.lastname)
        }

        // try calling http://localhost:6767/query?foo=bar
        get "/query" => |request| {
            let query = request.query();
            let foo = query.get("foo").unwrap_or("This is only a default value");
            let bar = query.get("bar").unwrap_or("This is only a default value");
            let text = format!("
Your foo values in the query string are: {:?}\

Your bar values are: {:?}",
                               foo, bar);
            text
        }
    ));

    // issue #20178
    let custom_handler: fn(&mut NickelError, &mut Request) -> Action = custom_404;

    server.handle_error(custom_handler);

    println!("Running server!");
    server.listen("127.0.0.1:6767");
}
<commit_msg>docs(example): Fixed missing url fragment on example's comment<commit_after>#[macro_use] extern crate nickel;
extern crate regex;
extern crate rustc_serialize;
extern crate hyper;

use std::io::Write;
use nickel::status::StatusCode::{self, NotFound};
use nickel::{
    Nickel, NickelError, Continue, Halt, Request, Response, MediaType,
    QueryString, JsonBody, StaticFilesHandler, MiddlewareResult, HttpRouter, Action
};
use regex::Regex;
use hyper::header::Location;

#[derive(RustcDecodable, RustcEncodable)]
struct Person {
    firstname: String,
    lastname:  String,
}

//this is an example middleware function that just logs each request
fn logger<'a>(request: &mut Request, response: Response<'a>) -> MiddlewareResult<'a> {
    println!("logging request: {:?}", request.origin.uri);
    Ok(Continue(response))
}

//this is how to overwrite the default error handler to handle 404 cases with a custom view
fn custom_404<'a>(err: &mut NickelError, _req: &mut Request) -> Action {
    if let Some(ref mut res) = err.stream {
        if res.status() == NotFound {
            let _ = res.write_all(b"
Call the police!
");
            return Halt(())
        }
    }

    Continue(())
}

fn main() {
    let mut server = Nickel::new();

    // middleware is optional and can be registered with `utilize`
    server.utilize(logger);

    // go to http://localhost:6767/thoughtram_logo_brain.png to see static file serving in action
    server.utilize(StaticFilesHandler::new("examples/assets/"));

    let hello_regex = Regex::new("/hello/(?P<name>[a-zA-Z]+)").unwrap();

    // The return type for a route can be anything that implements `Responder`
    server.utilize(router!(
        // go to http://localhost:6767/user/4711 to see this route in action
        get "/user/:userid" => |request| {
            // returning a String
            format!("This is user: {}", request.param("userid"))
        }

        // go to http://localhost:6767/no_alloc/4711 to see this route in action
        get "/no_alloc/:userid" => |request, response| {
            // returning a slice of T where T: Display
            &["This is user: ", request.param("userid")][..]
        }

        // go to http://localhost:6767/bar to see this route in action
        get "/bar" => {
            // returning a http status code and a static string
            (200u16, "This is the /bar handler")
        }

        // go to http://localhost:6767/content-type to see this route in action
        get "/content-type" => |_, mut response| {
            response.set(MediaType::Json);
            "{'foo':'bar'}"
        }

        // go to http://localhost:6767/hello/moomah to see this route in action
        get hello_regex => |request| {
            format!("Hello {}", request.param("name"))
        }

        // go to http://localhost:6767/redirect to see this route in action
        get "/redirect" => |_, mut response| {
            response.set(Location("http://nickel.rs".into()));

            StatusCode::PermanentRedirect
        }

        // go to http://localhost:6767/private to see this route in action
        get "/private" => {
            // returning a typed http status and a response body
            (StatusCode::Unauthorized, "This is a private place")
        }

        // go to http://localhost:6767/some/crazy/route to see this route in action
        get "/some/*/route" => {
            // returning a static string
            "This matches /some/crazy/route but not /some/super/crazy/route"
        }

        // go to http://localhost:6767/a/some/crazy/route to see this route in action
        get "/a/**/route" => {
            "This matches /a/crazy/route and also /a/super/crazy/route"
        }

        // try it with curl
        // curl 'http://localhost:6767/a/post/request' -H 'Content-Type: application/json;charset=UTF-8'  --data-binary $'{ "firstname": "John","lastname": "Connor" }'
        post "/a/post/request" => |request| {
            let person = request.json_as::<Person>().unwrap();
            format!("Hello {} {}", person.firstname, person.lastname)
        }

        // try calling http://localhost:6767/query?foo=bar
        get "/query" => |request| {
            let query = request.query();
            let foo = query.get("foo").unwrap_or("This is only a default value");
            let bar = query.get("bar").unwrap_or("This is only a default value");
            let text = format!("
Your foo values in the query string are: {:?}\

Your bar values are: {:?}",
                               foo, bar);
            text
        }
    ));

    // issue #20178
    let custom_handler: fn(&mut NickelError, &mut Request) -> Action = custom_404;

    server.handle_error(custom_handler);

    println!("Running server!");
    server.listen("127.0.0.1:6767");
}
<|endoftext|>


<commit_before>// from: https://github.com/Maktm/FLIRTDB/blob/1f5763535e02d7cccf2f90a96a8ebaa36e9b2495/cmt/windows/libcmt_15_msvc_x86.pat#L355
//
//    3B0D........F27502F2C3F2E9...................................... 00 0000 0011 :0000 @__security_check_cookie@4 :000B@ $failure$4 ^0002 ___security_cookie ^000D ___report_gsfailure
//    ^^^^        ^^^^^^^^^^^^^^   bytes
//        ^^^^^^^^                 relocations
//
//                                                                     00 0000 0011
//                                                                     ^^ number of bytes crc16'd
//                                                                        ^^^^ crc16
//                                                                             ^^^^ size of fn
//
//                                                                                :0000 @__security_check_cookie@4
//                                                                                ^^^^^ offset of match
//                                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^ name
//
//                                                                                :000B@ $failure$4
//                                                                                ^^^^^^ local offset
//                                                                                ^^^^^^^^^^ local name
//
//                                                                                ^0002 ___security_cookie
//                                                                                ^^^^^ reference offset
//                                                                                ^^^^^^^^^^^^^^^^^^ reference name

use log::{trace};
use nom::IResult;
use nom::multi::many0;
use nom::multi::many1;
use nom::bytes::complete::tag;
use nom::bytes::complete::take_till1;
use nom::bytes::complete::take_while;
use nom::bytes::complete::take_while_m_n;
use nom::branch::alt;
use nom::sequence::pair;
use nom::combinator::map;
use nom::combinator::map_res;
use nom::combinator::peek;
use nom::combinator::opt;
use failure::{Error, Fail};

use super::{SigElement, ByteSignature, Offset, Name, Symbol, FlirtSignature, TailByte};

#[derive(Debug, Fail)]
pub enum PatError {
    #[fail(display = "The pattern is not supported")]
    NotSupported,
    #[fail(display = "The .pat file is corrupt (or unsupported)")]
    CorruptPatFile,
}

fn whitespace(input: &str) -> IResult<&str, &str> {
    take_while(|c| c == ' ')(input)
}

fn is_hex_digit(c: char) -> bool {
  c.is_digit(16)
}

fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
  u8::from_str_radix(input, 16)
}

/// parse a single hex byte, like `AB`
fn hex(input: &str) -> IResult<&str, u8> {
    map_res(
        take_while_m_n(2, 2, is_hex_digit),
        from_hex
    )(input)
}

fn hex_byte(input: &str) -> IResult<&str, u8> {
    let (input, v) = hex(input)?;
    Ok((input, v))
}

fn hex_word(input: &str) -> IResult<&str, u16> {
    let (input, v1) = hex(input)?;
    let (input, v2) = hex(input)?;
    let v: u16 = ((v1 as u16) << 8) | (v2 as u16);
    Ok((input, v))
}

/// parse a single byte signature element, which is either a hex byte or a wildcard.
fn sig_element(input: &str) -> IResult<&str, SigElement> {
    alt((
        map(hex, |v| SigElement::Byte(v)),
        map(tag(".."), |_| SigElement::Wildcard)
    ))(input)
}

/// parse byte signature elements, hex or wildcard.
fn byte_signature(input: &str) -> IResult<&str, ByteSignature> {
    let (input, elems) = many1(sig_element)(input)?;
    Ok((input, ByteSignature(elems)))
}

/// parse a hex-encoded offset, like `0000`
/// max is 0x8000.
/// TODO: this can be negative.
fn hex_offset(input: &str) -> IResult<&str, u16> {
    hex_word(input)
}

/// parse a public offset, like `:0000`
fn public_offset(input: &str) -> IResult<&str, u16> {
    let (input, _) = tag(":")(input)?;
    let (input, offset) = hex_offset(input)?;
    let (input, _) = peek(tag(" "))(input)?;

    Ok((input, offset))
}

/// parse a local offset, like `:000B@`
fn local_offset(input: &str) -> IResult<&str, u16> {
    let (input, _) = tag(":")(input)?;
    let (input, offset) = hex_offset(input)?;
    let (input, _) = tag("@")(input)?;

    Ok((input, offset))
}

/// parse an external reference, like `^0002`
fn reference_offset(input: &str) -> IResult<&str, u16> {
    let (input, _) = tag("^")(input)?;
    let (input, offset) = hex_offset(input)?;

    Ok((input, offset))
}

fn offset(input: &str) -> IResult<&str, Offset> {
    alt((
        // this must go first, because it has trailing `@`,
        // otherwise, the same as public.
        map(local_offset, |v| Offset::Local(v)),
        map(public_offset, |v| Offset::Public(v)),
        map(reference_offset, |v| Offset::Reference(v))
    ))(input)
}

fn symbol_name(input: &str) -> IResult<&str, &str> {
    take_till1(|c| c == ' ' || c == '\n')(input)
}

/// parse a (offset, symbol) pair.
///
/// note: this also consumes trailing spaces so that a sequence of these can be easily parsed.
fn symbol(input: &str) -> IResult<&str, Symbol> {
    let (input, offset) = offset(input)?;
    let (input, _) = whitespace(input)?;
    let (input, name) = symbol_name(input)?;
    let (input, _) = opt(whitespace)(input)?;
    match offset {
        Offset::Public(v) => {
            Ok((input, Symbol::Public(Name {name: name.to_string(), offset: v as i64})))
        },
        Offset::Local(v) => {
            Ok((input, Symbol::Local(Name {name: name.to_string(), offset: v as i64})))
        },
        Offset::Reference(v) => {
            Ok((input, Symbol::Reference(Name {name: name.to_string(), offset: v as i64})))
        },
    }
}

fn symbols(input: &str) -> IResult<&str, Vec<Symbol>> {
    many1(symbol)(input)
}

fn tail_byte(input: &str) -> IResult<&str, TailByte> {
    let (input, _) = tag("(")(input)?;
    let (input, offset) = hex_offset(input)?;
    let (input, _) = whitespace(input)?;
    let (input, value) = hex_byte(input)?;
    let (input, _) = tag(")")(input)?;

    Ok((input, TailByte { offset: offset as u64, value }))
}

fn tail_bytes(input: &str) -> IResult<&str, Vec<TailByte>> {
    match opt(many1(tail_byte))(input)? {
        (input, Some(tail_bytes)) => Ok((input, tail_bytes)),
        (input, None) => Ok((input, vec![])),
    }
}

fn pat_signature(input: &str) -> IResult<&str, FlirtSignature> {
    let (input, byte_sig) = byte_signature(input)?;
    let (input, _) = whitespace(input)?;
    trace!("sig: {:?}", byte_sig);

    let (input, size_of_bytes_crc16) = hex_byte(input)?;
    let (input, _) = whitespace(input)?;
    trace!("crc16 len: {:02x}", size_of_bytes_crc16);

    let (input, crc16) = hex_word(input)?;
    let (input, _) = whitespace(input)?;
    trace!("crc16: {:04x}", crc16);

    let (input, size_of_function) = hex_word(input)?;
    let (input, _) = whitespace(input)?;
    trace!("function size: {:04x}", size_of_function);

    let (input, names) = symbols(input)?;
    trace!("names: {:?}", names);

    let (input, footer) = opt(byte_signature)(input)?;
    trace!("footer: {:?}", footer);

    let (input, tail_bytes) = tail_bytes(input)?;
    trace!("tail bytes: {:02x?}", tail_bytes);

    Ok((input, FlirtSignature {
        byte_sig,
        size_of_bytes_crc16,
        crc16,
        size_of_function: size_of_function as u64,
        names,
        footer,
        tail_bytes,
    }))
}

/// parse a .pat file into FLIRT signatures.
fn pat(input: &str) -> IResult<&str, Vec<FlirtSignature>> {
    // each signature is newline separated.
    // drop the newline after we've parsed it.
    let pat_sig_line = map(pair(pat_signature, alt((tag("\r\n"), tag("\n")))), |p| p.0);
    let (input, sigs) = many0(pat_sig_line)(input)?;

    // the file ends with `---`.
    let (input, _) = tag("---")(input)?;

    // TODO: assert there is nothing left in the file

    Ok((input, sigs))
}

/// ```
/// use flirt::pat;
/// let pat_buf = "3B0D........F27502F2C3F2E9...................................... 00 0000 0011 :0000 @__security_check_cookie@4 :000B@ $failure$4 ^0002 ___security_cookie ^000D ___report_gsfailure\n---";
/// assert_eq!(pat::parse(pat_buf).unwrap().len(), 1);
/// ```
pub fn parse(buf: &str) -> Result<Vec<FlirtSignature>, Error> {
    if let Ok((_, sigs)) = pat(buf) {
        Ok(sigs)
    } else {
        Err(PatError::CorruptPatFile.into())
    }
}
<commit_msg>flirt: pat: detect some whitespace<commit_after>// from: https://github.com/Maktm/FLIRTDB/blob/1f5763535e02d7cccf2f90a96a8ebaa36e9b2495/cmt/windows/libcmt_15_msvc_x86.pat#L355
//
//    3B0D........F27502F2C3F2E9...................................... 00 0000 0011 :0000 @__security_check_cookie@4 :000B@ $failure$4 ^0002 ___security_cookie ^000D ___report_gsfailure
//    ^^^^        ^^^^^^^^^^^^^^   bytes
//        ^^^^^^^^                 relocations
//
//                                                                     00 0000 0011
//                                                                     ^^ number of bytes crc16'd
//                                                                        ^^^^ crc16
//                                                                             ^^^^ size of fn
//
//                                                                                :0000 @__security_check_cookie@4
//                                                                                ^^^^^ offset of match
//                                                                                ^^^^^^^^^^^^^^^^^^^^^^^^^^ name
//
//                                                                                :000B@ $failure$4
//                                                                                ^^^^^^ local offset
//                                                                                ^^^^^^^^^^ local name
//
//                                                                                ^0002 ___security_cookie
//                                                                                ^^^^^ reference offset
//                                                                                ^^^^^^^^^^^^^^^^^^ reference name

use log::{trace};
use nom::IResult;
use nom::multi::many0;
use nom::multi::many1;
use nom::bytes::complete::tag;
use nom::bytes::complete::take_till1;
use nom::bytes::complete::take_while;
use nom::bytes::complete::take_while_m_n;
use nom::branch::alt;
use nom::sequence::pair;
use nom::combinator::map;
use nom::combinator::map_res;
use nom::combinator::peek;
use nom::combinator::opt;
use failure::{Error, Fail};

use super::{SigElement, ByteSignature, Offset, Name, Symbol, FlirtSignature, TailByte};

#[derive(Debug, Fail)]
pub enum PatError {
    #[fail(display = "The pattern is not supported")]
    NotSupported,
    #[fail(display = "The .pat file is corrupt (or unsupported)")]
    CorruptPatFile,
}

fn whitespace(input: &str) -> IResult<&str, &str> {
    take_while(|c| c == ' ')(input)
}

fn is_hex_digit(c: char) -> bool {
  c.is_digit(16)
}

fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
  u8::from_str_radix(input, 16)
}

/// parse a single hex byte, like `AB`
fn hex(input: &str) -> IResult<&str, u8> {
    map_res(
        take_while_m_n(2, 2, is_hex_digit),
        from_hex
    )(input)
}

fn hex_byte(input: &str) -> IResult<&str, u8> {
    let (input, v) = hex(input)?;
    Ok((input, v))
}

fn hex_word(input: &str) -> IResult<&str, u16> {
    let (input, v1) = hex(input)?;
    let (input, v2) = hex(input)?;
    let v: u16 = ((v1 as u16) << 8) | (v2 as u16);
    Ok((input, v))
}

/// parse a single byte signature element, which is either a hex byte or a wildcard.
fn sig_element(input: &str) -> IResult<&str, SigElement> {
    alt((
        map(hex, |v| SigElement::Byte(v)),
        map(tag(".."), |_| SigElement::Wildcard)
    ))(input)
}

/// parse byte signature elements, hex or wildcard.
fn byte_signature(input: &str) -> IResult<&str, ByteSignature> {
    let (input, elems) = many1(sig_element)(input)?;
    Ok((input, ByteSignature(elems)))
}

/// parse a hex-encoded offset, like `0000`
/// max is 0x8000.
/// TODO: this can be negative.
fn hex_offset(input: &str) -> IResult<&str, u16> {
    hex_word(input)
}

/// parse a public offset, like `:0000`
fn public_offset(input: &str) -> IResult<&str, u16> {
    let (input, _) = tag(":")(input)?;
    let (input, offset) = hex_offset(input)?;
    let (input, _) = peek(tag(" "))(input)?;

    Ok((input, offset))
}

/// parse a local offset, like `:000B@`
fn local_offset(input: &str) -> IResult<&str, u16> {
    let (input, _) = tag(":")(input)?;
    let (input, offset) = hex_offset(input)?;
    let (input, _) = tag("@")(input)?;

    Ok((input, offset))
}

/// parse an external reference, like `^0002`
fn reference_offset(input: &str) -> IResult<&str, u16> {
    let (input, _) = tag("^")(input)?;
    let (input, offset) = hex_offset(input)?;

    Ok((input, offset))
}

fn offset(input: &str) -> IResult<&str, Offset> {
    alt((
        // this must go first, because it has trailing `@`,
        // otherwise, the same as public.
        map(local_offset, |v| Offset::Local(v)),
        map(public_offset, |v| Offset::Public(v)),
        map(reference_offset, |v| Offset::Reference(v))
    ))(input)
}

fn symbol_name(input: &str) -> IResult<&str, &str> {
    take_till1(|c| c == ' ' || c == '\n')(input)
}

/// parse a (offset, symbol) pair.
///
/// note: this also consumes trailing spaces so that a sequence of these can be easily parsed.
fn symbol(input: &str) -> IResult<&str, Symbol> {
    let (input, offset) = offset(input)?;
    let (input, _) = whitespace(input)?;
    let (input, name) = symbol_name(input)?;
    let (input, _) = opt(whitespace)(input)?;
    match offset {
        Offset::Public(v) => {
            Ok((input, Symbol::Public(Name {name: name.to_string(), offset: v as i64})))
        },
        Offset::Local(v) => {
            Ok((input, Symbol::Local(Name {name: name.to_string(), offset: v as i64})))
        },
        Offset::Reference(v) => {
            Ok((input, Symbol::Reference(Name {name: name.to_string(), offset: v as i64})))
        },
    }
}

fn symbols(input: &str) -> IResult<&str, Vec<Symbol>> {
    many1(symbol)(input)
}

// like: `(0012: 87)`
fn tail_byte(input: &str) -> IResult<&str, TailByte> {
    let (input, _) = tag("(")(input)?;
    let (input, offset) = hex_offset(input)?;
    let (input, _) = whitespace(input)?;
    let (input, value) = hex_byte(input)?;
    let (input, _) = tag(")")(input)?;

    Ok((input, TailByte { offset: offset as u64, value }))
}

fn tail_bytes(input: &str) -> IResult<&str, Vec<TailByte>> {
    match opt(many1(tail_byte))(input)? {
        (input, Some(tail_bytes)) => Ok((input, tail_bytes)),
        (input, None) => Ok((input, vec![])),
    }
}

fn pat_signature(input: &str) -> IResult<&str, FlirtSignature> {
    let (input, byte_sig) = byte_signature(input)?;
    let (input, _) = whitespace(input)?;
    trace!("sig: {:?}", byte_sig);

    let (input, size_of_bytes_crc16) = hex_byte(input)?;
    let (input, _) = whitespace(input)?;
    trace!("crc16 len: {:02x}", size_of_bytes_crc16);

    let (input, crc16) = hex_word(input)?;
    let (input, _) = whitespace(input)?;
    trace!("crc16: {:04x}", crc16);

    let (input, size_of_function) = hex_word(input)?;
    let (input, _) = whitespace(input)?;
    trace!("function size: {:04x}", size_of_function);

    let (input, names) = symbols(input)?;
    trace!("names: {:?}", names);

    // i'm not sure which of these comes first, footer pattern or tail bytes.
    // are they both actually valid in a .pat file!?!
    // pat.txt only describes the footer pattern (which it calls "tail bytes").
    // whereas the .sig file format uses (offset, value) tuples for tail bytes,
    // and dumpsig.exe uses a format like `(AAAA: BB)` for these.

    let (input, _) = opt(whitespace)(input)?;
    let (input, footer) = opt(byte_signature)(input)?;
    trace!("footer: {:?}", footer);

    let (input, _) = opt(whitespace)(input)?;
    let (input, tail_bytes) = tail_bytes(input)?;
    trace!("tail bytes: {:02x?}", tail_bytes);

    Ok((input, FlirtSignature {
        byte_sig,
        size_of_bytes_crc16,
        crc16,
        size_of_function: size_of_function as u64,
        names,
        footer,
        tail_bytes,
    }))
}

/// parse a .pat file into FLIRT signatures.
fn pat(input: &str) -> IResult<&str, Vec<FlirtSignature>> {
    // each signature is newline separated.
    // drop the newline after we've parsed it.
    let pat_sig_line = map(pair(pat_signature, alt((tag("\r\n"), tag("\n")))), |p| p.0);
    let (input, sigs) = many0(pat_sig_line)(input)?;

    // the file ends with `---`.
    let (input, _) = tag("---")(input)?;

    // TODO: assert there is nothing left in the file

    Ok((input, sigs))
}

/// ```
/// use flirt::pat;
/// let pat_buf = "3B0D........F27502F2C3F2E9...................................... 00 0000 0011 :0000 @__security_check_cookie@4 :000B@ $failure$4 ^0002 ___security_cookie ^000D ___report_gsfailure\n---";
/// assert_eq!(pat::parse(pat_buf).unwrap().len(), 1);
/// ```
pub fn parse(buf: &str) -> Result<Vec<FlirtSignature>, Error> {
    if let Ok((_, sigs)) = pat(buf) {
        Ok(sigs)
    } else {
        Err(PatError::CorruptPatFile.into())
    }
}
<|endoftext|>


<commit_before>//
// Copyright 2014-2016 the slack-rs authors.
//
// 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.
//
//
// This is a simple example of using slack-rs.
// You can run it with `cargo run example -- <api_key>`
//

extern crate slack;

struct MyHandler;

#[allow(unused_variables)]
impl slack::EventHandler for MyHandler {
    fn on_event(&mut self, cli: &mut slack::RtmClient, event: Result<&slack::Event, slack::Error>, raw_json: &str) {
        println!("on_event(event: {:?}, raw_json: {:?})", event, raw_json);
    }

    fn on_ping(&mut self, cli: &mut slack::RtmClient) {
        println!("on_ping");
    }

    fn on_close(&mut self, cli: &mut slack::RtmClient) {
        println!("on_close");
    }

    fn on_connect(&mut self, cli: &mut slack::RtmClient) {
        println!("on_connect");
        // Do a few things using the api:
        // send a message over the real time api websocket
        let _ = cli.send_message("#general", "Hello world! (rtm)");
        // post a message as a user to the web api
        let _ = cli.post_message("#general", "hello world! (postMessage)", None);
        // set a channel topic via the web api
        // let _ = cli.set_topic("#general", "bots rule!");
    }
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let api_key = match args.len() {
        0 | 1 => panic!("No api-key in args! Usage: cargo run slack_example -- <api-key>"),
        x => {
            args[x - 1].clone()
        }
    };
    let mut handler = MyHandler;
    let mut cli = slack::RtmClient::new(&api_key);
    let r = cli.login_and_run::<MyHandler>(&mut handler);
    match r {
        Ok(_) => {}
        Err(err) => panic!("Error: {}", err),
    }
    println!("{}", cli.get_name().unwrap());
    println!("{}", cli.get_team().unwrap().name);
}
<commit_msg>Update usage information for example<commit_after>//
// Copyright 2014-2016 the slack-rs authors.
//
// 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.
//
//
// This is a simple example of using slack-rs.
// You can run it with `cargo run --example slack_example -- <api_key>`
//
// NOTE: This will post in the #general channel of the account you connect
// to.
//

extern crate slack;

struct MyHandler;

#[allow(unused_variables)]
impl slack::EventHandler for MyHandler {
    fn on_event(&mut self, cli: &mut slack::RtmClient, event: Result<&slack::Event, slack::Error>, raw_json: &str) {
        println!("on_event(event: {:?}, raw_json: {:?})", event, raw_json);
    }

    fn on_ping(&mut self, cli: &mut slack::RtmClient) {
        println!("on_ping");
    }

    fn on_close(&mut self, cli: &mut slack::RtmClient) {
        println!("on_close");
    }

    fn on_connect(&mut self, cli: &mut slack::RtmClient) {
        println!("on_connect");
        // Do a few things using the api:
        // send a message over the real time api websocket
        let _ = cli.send_message("#general", "Hello world! (rtm)");
        // post a message as a user to the web api
        let _ = cli.post_message("#general", "hello world! (postMessage)", None);
        // set a channel topic via the web api
        // let _ = cli.set_topic("#general", "bots rule!");
    }
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let api_key = match args.len() {
        0 | 1 => panic!("No api-key in args! Usage: cargo run --example slack_example -- <api-key>"),
        x => {
            args[x - 1].clone()
        }
    };
    let mut handler = MyHandler;
    let mut cli = slack::RtmClient::new(&api_key);
    let r = cli.login_and_run::<MyHandler>(&mut handler);
    match r {
        Ok(_) => {}
        Err(err) => panic!("Error: {}", err),
    }
    println!("{}", cli.get_name().unwrap());
    println!("{}", cli.get_team().unwrap().name);
}
<|endoftext|>


<commit_before>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use core_foundation::base::{CFRelease, CFTypeID, TCFType};

use libc::{c_void, size_t};
use std::cast;
use std::ptr;

pub type CGDataProviderGetBytesCallback = *u8;
pub type CGDataProviderReleaseInfoCallback = *u8;
pub type CGDataProviderRewindCallback = *u8;
pub type CGDataProviderSkipBytesCallback = *u8;
pub type CGDataProviderSkipForwardCallback = *u8;

pub type CGDataProviderGetBytePointerCallback = *u8;
pub type CGDataProviderGetBytesAtOffsetCallback = *u8;
pub type CGDataProviderReleaseBytePointerCallback = *u8;
pub type CGDataProviderReleaseDataCallback = *u8;
pub type CGDataProviderGetBytesAtPositionCallback = *u8;

struct __CGDataProvider;

pub type CGDataProviderRef = *__CGDataProvider;

pub struct CGDataProvider {
    obj: CGDataProviderRef,
}

impl Drop for CGDataProvider {
    fn drop(&mut self) {
        unsafe {
            CFRelease(self.as_CFTypeRef())
        }
    }
}

impl TCFType<CGDataProviderRef> for CGDataProvider {
    fn as_concrete_TypeRef(&self) -> CGDataProviderRef {
        self.obj
    }

    unsafe fn wrap_under_create_rule(obj: CGDataProviderRef) -> CGDataProvider {
        CGDataProvider {
            obj: obj,
        }
    }

    #[inline]
    fn type_id(_: Option<CGDataProvider>) -> CFTypeID {
        unsafe {
            CGDataProviderGetTypeID()
        }
    }
}

impl CGDataProvider {
    pub fn from_buffer(buffer: &[u8]) -> CGDataProvider {
        unsafe {
            let result = CGDataProviderCreateWithData(ptr::null(),
                                                      cast::transmute(buffer.as_ptr()),
                                                      buffer.len() as u64,
                                                      ptr::null());
            TCFType::wrap_under_create_rule(result)
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    //fn CGDataProviderCopyData
    //fn CGDataProviderCreateDirect
    //fn CGDataProviderCreateSequential
    //fn CGDataProviderCreateWithCFData
    fn CGDataProviderCreateWithData(info: *c_void,
                                    data: *c_void,
                                    size: size_t,
                                    releaseData: CGDataProviderReleaseDataCallback
                                   ) -> CGDataProviderRef;
    //fn CGDataProviderCreateWithFilename(filename: *c_char) -> CGDataProviderRef;
    //fn CGDataProviderCreateWithURL
    fn CGDataProviderGetTypeID() -> CFTypeID;
    //fn CGDataProviderRelease(provider: CGDataProviderRef);
    //fn CGDataProviderRetain(provider: CGDataProviderRef) -> CGDataProviderRef;
}
<commit_msg>Upgrade Rust.<commit_after>// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

use core_foundation::base::{CFRelease, CFTypeID, TCFType};

use libc::{c_void, size_t};
use std::mem;
use std::ptr;

pub type CGDataProviderGetBytesCallback = *u8;
pub type CGDataProviderReleaseInfoCallback = *u8;
pub type CGDataProviderRewindCallback = *u8;
pub type CGDataProviderSkipBytesCallback = *u8;
pub type CGDataProviderSkipForwardCallback = *u8;

pub type CGDataProviderGetBytePointerCallback = *u8;
pub type CGDataProviderGetBytesAtOffsetCallback = *u8;
pub type CGDataProviderReleaseBytePointerCallback = *u8;
pub type CGDataProviderReleaseDataCallback = *u8;
pub type CGDataProviderGetBytesAtPositionCallback = *u8;

struct __CGDataProvider;

pub type CGDataProviderRef = *__CGDataProvider;

pub struct CGDataProvider {
    obj: CGDataProviderRef,
}

impl Drop for CGDataProvider {
    fn drop(&mut self) {
        unsafe {
            CFRelease(self.as_CFTypeRef())
        }
    }
}

impl TCFType<CGDataProviderRef> for CGDataProvider {
    fn as_concrete_TypeRef(&self) -> CGDataProviderRef {
        self.obj
    }

    unsafe fn wrap_under_create_rule(obj: CGDataProviderRef) -> CGDataProvider {
        CGDataProvider {
            obj: obj,
        }
    }

    #[inline]
    fn type_id(_: Option<CGDataProvider>) -> CFTypeID {
        unsafe {
            CGDataProviderGetTypeID()
        }
    }
}

impl CGDataProvider {
    pub fn from_buffer(buffer: &[u8]) -> CGDataProvider {
        unsafe {
            let result = CGDataProviderCreateWithData(ptr::null(),
                                                      mem::transmute(buffer.as_ptr()),
                                                      buffer.len() as u64,
                                                      ptr::null());
            TCFType::wrap_under_create_rule(result)
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern {
    //fn CGDataProviderCopyData
    //fn CGDataProviderCreateDirect
    //fn CGDataProviderCreateSequential
    //fn CGDataProviderCreateWithCFData
    fn CGDataProviderCreateWithData(info: *c_void,
                                    data: *c_void,
                                    size: size_t,
                                    releaseData: CGDataProviderReleaseDataCallback
                                   ) -> CGDataProviderRef;
    //fn CGDataProviderCreateWithFilename(filename: *c_char) -> CGDataProviderRef;
    //fn CGDataProviderCreateWithURL
    fn CGDataProviderGetTypeID() -> CFTypeID;
    //fn CGDataProviderRelease(provider: CGDataProviderRef);
    //fn CGDataProviderRetain(provider: CGDataProviderRef) -> CGDataProviderRef;
}
<|endoftext|>