<commit_before>use eventual::{self, Async};
use std::borrow::Cow;
use std::sync::{mpsc, Mutex, Arc, MutexGuard};
use std::thread;
use std::io::{Read, Seek};
use vorbis;

use audio_decrypt::AudioDecrypt;
use audio_backend::Sink;
use metadata::{FileFormat, Track, TrackRef};
use session::{Bitrate, Session};
use util::{self, ReadSeek, SpotifyId, Subfile};
pub use spirc::PlayStatus;

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms as f64 / 1000f64)
}

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell().map(|t| (t * 1000f64) as i64)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell()
}

pub type PlayerObserver = Box<Fn(&PlayerState) + Send>;

#[derive(Clone)]
pub struct Player {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    commands: mpsc::Sender<PlayerCommand>,
}

#[derive(Clone)]
pub struct PlayerState {
    pub status: PlayStatus,
    pub position_ms: u32,
    pub position_measured_at: i64,
    pub update_time: i64,
    pub volume: u16,
    pub track: Option<SpotifyId>,

    pub end_of_track: bool,
}

struct PlayerInternal {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    session: Session,
    commands: mpsc::Receiver<PlayerCommand>,
}

#[derive(Debug)]
enum PlayerCommand {
    Load(SpotifyId, bool, u32),
    Play,
    Pause,
    Volume(u16),
    Stop,
    Seek(u32),
    SeekAt(u32, i64),
}

impl Player {
    pub fn new<F>(session: Session, sink_builder: F) -> Player
        where F: FnOnce() -> Box<Sink> + Send + 'static {
        let (cmd_tx, cmd_rx) = mpsc::channel();

        let state = Arc::new(Mutex::new(PlayerState {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: util::now_ms(),
            volume: 0xFFFF,
            track: None,
            end_of_track: false,
        }));

        let observers = Arc::new(Mutex::new(Vec::new()));

        let internal = PlayerInternal {
            session: session,
            commands: cmd_rx,
            state: state.clone(),
            observers: observers.clone(),
        };

        thread::spawn(move || internal.run(sink_builder()));

        Player {
            commands: cmd_tx,
            state: state,
            observers: observers,
        }
    }

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

    pub fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32) {
        self.command(PlayerCommand::Load(track, start_playing, position_ms));
    }

    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));
    }

    pub fn seek_at(&self, position_ms: u32, measured_at: i64) {
        self.command(PlayerCommand::SeekAt(position_ms, measured_at));
    }

    pub fn state(&self) -> PlayerState {
        self.state.lock().unwrap().clone()
    }

    pub fn volume(&self, vol: u16) {
        self.command(PlayerCommand::Volume(vol));
    }

    pub fn add_observer(&self, observer: PlayerObserver) {
        self.observers.lock().unwrap().push(observer);
    }
}

fn apply_volume(volume: u16, data: &[i16]) -> Cow<[i16]> {
    // Fast path when volume is 100%
    if volume == 0xFFFF {
        Cow::Borrowed(data)
    } else {
        Cow::Owned(data.iter()
                       .map(|&x| {
                           (x as i32
                            * volume as i32
                            / 0xFFFF) as i16
                       })
                       .collect())
    }
}

fn find_available_alternative<'a>(session: &Session, track: &'a Track) -> Option<Cow<'a, Track>> {
    if track.available {
        Some(Cow::Borrowed(track))
    } else {
        let alternatives = track.alternatives
            .iter()
            .map(|alt_id| {
                session.metadata::<Track>(*alt_id)
            })
        .collect::<Vec<TrackRef>>();

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

fn load_track(session: &Session, track_id: SpotifyId) -> Option<vorbis::Decoder<Subfile<AudioDecrypt<Box<ReadSeek>>>>> {
    let track = session.metadata::<Track>(track_id).await().unwrap();

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

    let format = match session.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 = session.audio_key(track.id, file_id).await().unwrap();

    let audio_file = Subfile::new(AudioDecrypt::new(key, session.audio_file(file_id)), 0xa7);
    let decoder = vorbis::Decoder::new(audio_file).unwrap();

    Some(decoder)
}

fn run_onstart(session: &Session) {
    match session.config().onstart {
        Some(ref program) => util::run_program(program),
        None => {},
    };
}

fn run_onstop(session: &Session) {
    match session.config().onstop {
        Some(ref program) => util::run_program(program),
        None => {},
    };
}

impl PlayerInternal {
    fn run(self, mut sink: Box<Sink>) {
        let mut decoder = None;

        loop {
            let playing = self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay;
            let cmd = if playing {
                self.commands.try_recv().ok()
            } else {
                Some(self.commands.recv().unwrap())
            };

            match cmd {
                Some(PlayerCommand::Load(track_id, play, position)) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            sink.stop().unwrap();
                            run_onstop(&self.session);
                        }
                        state.end_of_track = false;
                        state.status = PlayStatus::kPlayStatusPause;
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();
                        state.track = Some(track_id);
                        true
                    });
                    drop(decoder);

                    decoder = match load_track(&self.session, track_id) {
                        Some(mut decoder) => {
                            vorbis_time_seek_ms(&mut decoder, position as i64).unwrap();

                            self.update(|state| {
                                state.status = if play {
                                    run_onstart(&self.session);
                                    sink.start().unwrap();
                                    PlayStatus::kPlayStatusPlay
                                } else {
                                    PlayStatus::kPlayStatusPause
                                };
                                state.position_ms = position;
                                state.position_measured_at = util::now_ms();

                                true
                            });

                            info!("Load Done");
                            Some(decoder)
                        }

                        None => {
                            self.update(|state| {
                                state.status = PlayStatus::kPlayStatusStop;
                                state.end_of_track = true;
                                true
                            });

                            None
                        }
                    }

                }
                Some(PlayerCommand::Seek(position)) => {
                    vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap();
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::SeekAt(position, measured_at)) => {
                    let position = (util::now_ms() - measured_at + position as i64) as u32;

                    vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap();
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::Play) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPlay;
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    run_onstart(&self.session);
                    sink.start().unwrap();
                }
                Some(PlayerCommand::Pause) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPause;
                        state.update_time = util::now_ms();
                        state.position_ms = decoder.as_mut().map(|d| vorbis_time_tell_ms(d).unwrap()).unwrap_or(0) as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    run_onstop(&self.session);
                }
                Some(PlayerCommand::Volume(vol)) => {
                    self.update(|state| {
                        state.volume = vol;
                        true
                    });
                }
                Some(PlayerCommand::Stop) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            state.status = PlayStatus::kPlayStatusPause;
                        }
                        state.position_ms = 0;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    run_onstop(&self.session);
                    decoder = None;
                }
                None => (),
            }

            if self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay {
                let packet = decoder.as_mut().unwrap().packets().next();

                match packet {
                    Some(Ok(packet)) => {
                        let buffer = apply_volume(self.state.lock().unwrap().volume,
                                                  &packet.data);
                        sink.write(&buffer).unwrap();

                        self.update(|state| {
                            state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                            state.position_measured_at = util::now_ms();

                            false
                        });
                    }
                    Some(Err(vorbis::VorbisError::Hole)) => (),
                    Some(Err(e)) => panic!("Vorbis error {:?}", e),
                    None => {
                        self.update(|state| {
                            state.status = PlayStatus::kPlayStatusStop;
                            state.end_of_track = true;
                            true
                        });

                        sink.stop().unwrap();
                        run_onstop(&self.session);
                        decoder = None;
                    }
                }
            }
        }
    }

    fn update<F>(&self, f: F)
        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool
    {
        let mut guard = self.state.lock().unwrap();
        let update = f(&mut guard);

        let observers = self.observers.lock().unwrap();
        if update {
            guard.update_time = util::now_ms();
            let state = guard.clone();
            drop(guard);

            for observer in observers.iter() {
                observer(&state);
            }
        }
    }
}

impl PlayerState {
    pub fn status(&self) -> PlayStatus {
        self.status
    }

    pub fn position(&self) -> (u32, i64) {
        (self.position_ms, self.position_measured_at)
    }

    pub fn volume(&self) -> u16 {
        self.volume
    }

    pub fn update_time(&self) -> i64 {
        self.update_time
    }

    pub fn end_of_track(&self) -> bool {
        self.end_of_track
    }
}
<commit_msg>Don't panic on error InitialFileHeadersCorrupt<commit_after>use eventual::{self, Async};
use std::borrow::Cow;
use std::sync::{mpsc, Mutex, Arc, MutexGuard};
use std::thread;
use std::io::{Read, Seek};
use vorbis;

use audio_decrypt::AudioDecrypt;
use audio_backend::Sink;
use metadata::{FileFormat, Track, TrackRef};
use session::{Bitrate, Session};
use util::{self, ReadSeek, SpotifyId, Subfile};
pub use spirc::PlayStatus;

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms as f64 / 1000f64)
}

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell().map(|t| (t * 1000f64) as i64)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell()
}

pub type PlayerObserver = Box<Fn(&PlayerState) + Send>;

#[derive(Clone)]
pub struct Player {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    commands: mpsc::Sender<PlayerCommand>,
}

#[derive(Clone)]
pub struct PlayerState {
    pub status: PlayStatus,
    pub position_ms: u32,
    pub position_measured_at: i64,
    pub update_time: i64,
    pub volume: u16,
    pub track: Option<SpotifyId>,

    pub end_of_track: bool,
}

struct PlayerInternal {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    session: Session,
    commands: mpsc::Receiver<PlayerCommand>,
}

#[derive(Debug)]
enum PlayerCommand {
    Load(SpotifyId, bool, u32),
    Play,
    Pause,
    Volume(u16),
    Stop,
    Seek(u32),
    SeekAt(u32, i64),
}

impl Player {
    pub fn new<F>(session: Session, sink_builder: F) -> Player
        where F: FnOnce() -> Box<Sink> + Send + 'static {
        let (cmd_tx, cmd_rx) = mpsc::channel();

        let state = Arc::new(Mutex::new(PlayerState {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: util::now_ms(),
            volume: 0xFFFF,
            track: None,
            end_of_track: false,
        }));

        let observers = Arc::new(Mutex::new(Vec::new()));

        let internal = PlayerInternal {
            session: session,
            commands: cmd_rx,
            state: state.clone(),
            observers: observers.clone(),
        };

        thread::spawn(move || internal.run(sink_builder()));

        Player {
            commands: cmd_tx,
            state: state,
            observers: observers,
        }
    }

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

    pub fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32) {
        self.command(PlayerCommand::Load(track, start_playing, position_ms));
    }

    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));
    }

    pub fn seek_at(&self, position_ms: u32, measured_at: i64) {
        self.command(PlayerCommand::SeekAt(position_ms, measured_at));
    }

    pub fn state(&self) -> PlayerState {
        self.state.lock().unwrap().clone()
    }

    pub fn volume(&self, vol: u16) {
        self.command(PlayerCommand::Volume(vol));
    }

    pub fn add_observer(&self, observer: PlayerObserver) {
        self.observers.lock().unwrap().push(observer);
    }
}

fn apply_volume(volume: u16, data: &[i16]) -> Cow<[i16]> {
    // Fast path when volume is 100%
    if volume == 0xFFFF {
        Cow::Borrowed(data)
    } else {
        Cow::Owned(data.iter()
                       .map(|&x| {
                           (x as i32
                            * volume as i32
                            / 0xFFFF) as i16
                       })
                       .collect())
    }
}

fn find_available_alternative<'a>(session: &Session, track: &'a Track) -> Option<Cow<'a, Track>> {
    if track.available {
        Some(Cow::Borrowed(track))
    } else {
        let alternatives = track.alternatives
            .iter()
            .map(|alt_id| {
                session.metadata::<Track>(*alt_id)
            })
        .collect::<Vec<TrackRef>>();

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

fn load_track(session: &Session, track_id: SpotifyId) -> Option<vorbis::Decoder<Subfile<AudioDecrypt<Box<ReadSeek>>>>> {
    let track = session.metadata::<Track>(track_id).await().unwrap();

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

    let format = match session.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 = session.audio_key(track.id, file_id).await().unwrap();

    let audio_file = Subfile::new(AudioDecrypt::new(key, session.audio_file(file_id)), 0xa7);
    let decoder = vorbis::Decoder::new(audio_file).unwrap();

    Some(decoder)
}

fn run_onstart(session: &Session) {
    match session.config().onstart {
        Some(ref program) => util::run_program(program),
        None => {},
    };
}

fn run_onstop(session: &Session) {
    match session.config().onstop {
        Some(ref program) => util::run_program(program),
        None => {},
    };
}

impl PlayerInternal {
    fn run(self, mut sink: Box<Sink>) {
        let mut decoder = None;

        loop {
            let playing = self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay;
            let cmd = if playing {
                self.commands.try_recv().ok()
            } else {
                Some(self.commands.recv().unwrap())
            };

            match cmd {
                Some(PlayerCommand::Load(track_id, play, position)) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            sink.stop().unwrap();
                            run_onstop(&self.session);
                        }
                        state.end_of_track = false;
                        state.status = PlayStatus::kPlayStatusPause;
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();
                        state.track = Some(track_id);
                        true
                    });
                    drop(decoder);

                    decoder = match load_track(&self.session, track_id) {
                        Some(mut decoder) => {
                            match vorbis_time_seek_ms(&mut decoder, position as i64) {
                                Ok(_) => (),
                                Err(err) => error!("Vorbis error: {:?}", err),
                            }

                            self.update(|state| {
                                state.status = if play {
                                    run_onstart(&self.session);
                                    sink.start().unwrap();
                                    PlayStatus::kPlayStatusPlay
                                } else {
                                    PlayStatus::kPlayStatusPause
                                };
                                state.position_ms = position;
                                state.position_measured_at = util::now_ms();

                                true
                            });

                            info!("Load Done");
                            Some(decoder)
                        }

                        None => {
                            self.update(|state| {
                                state.status = PlayStatus::kPlayStatusStop;
                                state.end_of_track = true;
                                true
                            });

                            None
                        }
                    }

                }
                Some(PlayerCommand::Seek(position)) => {
                    match vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64) {
                        Ok(_) => (),
                        Err(err) => error!("Vorbis error: {:?}", err),
                    }
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::SeekAt(position, measured_at)) => {
                    let position = (util::now_ms() - measured_at + position as i64) as u32;

                    match vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64) {
                        Ok(_) => (),
                        Err(err) => error!("Vorbis error: {:?}", err),
                    }
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::Play) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPlay;
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    run_onstart(&self.session);
                    sink.start().unwrap();
                }
                Some(PlayerCommand::Pause) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPause;
                        state.update_time = util::now_ms();
                        state.position_ms = decoder.as_mut().map(|d| vorbis_time_tell_ms(d).unwrap()).unwrap_or(0) as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    run_onstop(&self.session);
                }
                Some(PlayerCommand::Volume(vol)) => {
                    self.update(|state| {
                        state.volume = vol;
                        true
                    });
                }
                Some(PlayerCommand::Stop) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            state.status = PlayStatus::kPlayStatusPause;
                        }
                        state.position_ms = 0;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    run_onstop(&self.session);
                    decoder = None;
                }
                None => (),
            }

            if self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay {
                let packet = decoder.as_mut().unwrap().packets().next();

                match packet {
                    Some(Ok(packet)) => {
                        let buffer = apply_volume(self.state.lock().unwrap().volume,
                                                  &packet.data);
                        sink.write(&buffer).unwrap();

                        self.update(|state| {
                            state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                            state.position_measured_at = util::now_ms();

                            false
                        });
                    }
                    Some(Err(vorbis::VorbisError::Hole)) => (),
                    Some(Err(e)) => panic!("Vorbis error {:?}", e),
                    None => {
                        self.update(|state| {
                            state.status = PlayStatus::kPlayStatusStop;
                            state.end_of_track = true;
                            true
                        });

                        sink.stop().unwrap();
                        run_onstop(&self.session);
                        decoder = None;
                    }
                }
            }
        }
    }

    fn update<F>(&self, f: F)
        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool
    {
        let mut guard = self.state.lock().unwrap();
        let update = f(&mut guard);

        let observers = self.observers.lock().unwrap();
        if update {
            guard.update_time = util::now_ms();
            let state = guard.clone();
            drop(guard);

            for observer in observers.iter() {
                observer(&state);
            }
        }
    }
}

impl PlayerState {
    pub fn status(&self) -> PlayStatus {
        self.status
    }

    pub fn position(&self) -> (u32, i64) {
        (self.position_ms, self.position_measured_at)
    }

    pub fn volume(&self) -> u16 {
        self.volume
    }

    pub fn update_time(&self) -> i64 {
        self.update_time
    }

    pub fn end_of_track(&self) -> bool {
        self.end_of_track
    }
}
<|endoftext|>


<commit_before>use {osc_types as ot,
    errors as oe};

use std::{io, string, mem, error};
use std::io::{Read, BufRead};

use byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8], size: usize) -> ot::OscResult<ot::OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg, size)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(oe::OscError::BadOscPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8], size: usize) -> ot::OscResult<ot::OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);
    let mut pos: u64 = 0;

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            match read_osc_string(&mut cursor) {
                Ok(type_tags) => {
                    if type_tags.len() > 1 {
                        match read_osc_args(&mut cursor, type_tags) {
                            Ok(args) => println!("{}", args.len()),
                            Err(e) => ()
                        };
                    }
                },
                Err(e) => return Err(e)
            }
        }
        Err(e) => return Err(e)
    }

    Ok(ot::OscPacket::Message(ot::OscMessage))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> ot::OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => {
            pad_cursor(cursor);
            String::from_utf8(str_buf)
                .map_err(|e| oe::OscError::StringError(e))
                .map(|s| s.trim_matches(0u8 as char).to_string())
        },
        Err(e) => Err(oe::OscError::ReadError(e)),
    }
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>, raw_type_tags: String) -> ot::OscResult<Vec<ot::OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
        .skip(1)
        .map(|c| c as char)
        .collect();
    let mut args: Vec<ot::OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        match read_osc_arg(cursor, tag) {
            Ok(arg) => {
                args.push(arg);
            },
            Err(e) => return Err(e)
        }
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> ot::OscResult<ot::OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
            .map(|f| ot::OscType::OscFloat(f))
            .map_err(|e| oe::OscError::ByteOrderError(e))
        },
        'd' => {
            cursor.read_f64::<BigEndian>()
            .map(|d| ot::OscType::OscDouble(d))
            .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
            .map(|i| ot::OscType::OscInt(i))
            .map_err(|e| oe::OscError::ByteOrderError(e))
        },
        'h' => {
            cursor.read_i64::<BigEndian>()
            .map(|l| ot::OscType::OscLong(l))
            .map_err(|e| oe::OscError::ByteOrderError(e))
        },
        's' => {
            read_osc_string(cursor)
            .map(|s| ot::OscType::OscString(s))
        },
        't' => {
            // http://opensoundcontrol.org/node/3/#timetags
            read_time_tag(cursor)
        }
        'b' => {
            match cursor.read_u32::<BigEndian>() {
                Ok(size) => {
                    let mut buf: Vec<u8> = Vec::with_capacity(size as usize);
                    match cursor.take(size as u64).read(&mut buf) {
                        Ok(blob_size) => Ok(ot::OscType::OscBlob(buf)),
                        Err(e) => Err(oe::OscError::ReadError(e))
                    }
                },
                Err(e) => return Err(oe::OscError::BadOscBundle)
            }
        },
        _ => Err(oe::OscError::BadOscArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> ot::OscResult<ot::OscType> {
    match cursor.read_u32::<BigEndian>() {
        Ok(date) => {
            match cursor.read_u32::<BigEndian>() {
                Ok(frac) => Ok(ot::OscType::OscTime(date, frac)),
                Err(e) => Err(oe::OscError::ByteOrderError(e))
            }
        },
        Err(e) => Err(oe::OscError::ByteOrderError(e))
    }
}

fn decode_bundle(msg: &[u8]) -> ot::OscResult<ot::OscPacket> {
    Err(oe::OscError::BadOscBundle)
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    match pos % 4 {
        0 => (),
        d => cursor.set_position(pos + (4 - d)),
    }
}<commit_msg>Remove unused position variable<commit_after>use {osc_types as ot,
    errors as oe};

use std::{io, string, mem, error};
use std::io::{Read, BufRead};

use byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8], size: usize) -> ot::OscResult<ot::OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg, size)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(oe::OscError::BadOscPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8], size: usize) -> ot::OscResult<ot::OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            match read_osc_string(&mut cursor) {
                Ok(type_tags) => {
                    if type_tags.len() > 1 {
                        match read_osc_args(&mut cursor, type_tags) {
                            Ok(args) => println!("{}", args.len()),
                            Err(e) => ()
                        };
                    }
                },
                Err(e) => return Err(e)
            }
        }
        Err(e) => return Err(e)
    }

    Ok(ot::OscPacket::Message(ot::OscMessage))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> ot::OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => {
            pad_cursor(cursor);
            String::from_utf8(str_buf)
                .map_err(|e| oe::OscError::StringError(e))
                .map(|s| s.trim_matches(0u8 as char).to_string())
        },
        Err(e) => Err(oe::OscError::ReadError(e)),
    }
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>, raw_type_tags: String) -> ot::OscResult<Vec<ot::OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
        .skip(1)
        .map(|c| c as char)
        .collect();
    let mut args: Vec<ot::OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        match read_osc_arg(cursor, tag) {
            Ok(arg) => {
                args.push(arg);
            },
            Err(e) => return Err(e)
        }
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> ot::OscResult<ot::OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
            .map(|f| ot::OscType::OscFloat(f))
            .map_err(|e| oe::OscError::ByteOrderError(e))
        },
        'd' => {
            cursor.read_f64::<BigEndian>()
            .map(|d| ot::OscType::OscDouble(d))
            .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
            .map(|i| ot::OscType::OscInt(i))
            .map_err(|e| oe::OscError::ByteOrderError(e))
        },
        'h' => {
            cursor.read_i64::<BigEndian>()
            .map(|l| ot::OscType::OscLong(l))
            .map_err(|e| oe::OscError::ByteOrderError(e))
        },
        's' => {
            read_osc_string(cursor)
            .map(|s| ot::OscType::OscString(s))
        },
        't' => {
            // http://opensoundcontrol.org/node/3/#timetags
            read_time_tag(cursor)
        }
        'b' => {
            match cursor.read_u32::<BigEndian>() {
                Ok(size) => {
                    let mut buf: Vec<u8> = Vec::with_capacity(size as usize);
                    match cursor.take(size as u64).read(&mut buf) {
                        Ok(blob_size) => Ok(ot::OscType::OscBlob(buf)),
                        Err(e) => Err(oe::OscError::ReadError(e))
                    }
                },
                Err(e) => return Err(oe::OscError::BadOscBundle)
            }
        },
        _ => Err(oe::OscError::BadOscArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> ot::OscResult<ot::OscType> {
    match cursor.read_u32::<BigEndian>() {
        Ok(date) => {
            match cursor.read_u32::<BigEndian>() {
                Ok(frac) => Ok(ot::OscType::OscTime(date, frac)),
                Err(e) => Err(oe::OscError::ByteOrderError(e))
            }
        },
        Err(e) => Err(oe::OscError::ByteOrderError(e))
    }
}

fn decode_bundle(msg: &[u8]) -> ot::OscResult<ot::OscPacket> {
    Err(oe::OscError::BadOscBundle)
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    match pos % 4 {
        0 => (),
        d => cursor.set_position(pos + (4 - d)),
    }
}<|endoftext|>


<commit_before>use aabb::AABB;
use nalgebra::{Vector3, Point3, Norm};

/// A struct which defines a ray and some of its cached values.
#[derive(Debug)]
pub struct Ray {
    pub origin: Point3<f32>,
    pub direction: Vector3<f32>,
    inv_direction: Vector3<f32>,
    sign: Vector3<usize>,
}

impl Ray {
    /// Creates a new `Ray`.
    pub fn new(origin: Point3<f32>, direction: Vector3<f32>) -> Ray {
        let direction = direction.normalize();
        Ray {
            origin: origin,
            direction: direction,
            inv_direction: Vector3::new(1.0 / direction.x, 1.0 / direction.y, 1.0 / direction.z),
            sign: Vector3::new((direction.x < 0.0) as usize,
                               (direction.y < 0.0) as usize,
                               (direction.z < 0.0) as usize),
        }
    }

    /// Tests the intersection of a `Ray` with an `AABB` using the optimized algorithm
    /// from this paper: http://www.cs.utah.edu/~awilliam/box/box.pdf
    pub fn intersects_aabb(&self, aabb: &AABB) -> bool {
        let mut ray_min = (aabb[self.sign.x].x - self.origin.x) * self.inv_direction.x;
        let mut ray_max = (aabb[1 - self.sign.x].x - self.origin.x) * self.inv_direction.x;

        let y_min = (aabb[self.sign.y].y - self.origin.y) * self.inv_direction.y;
        let y_max = (aabb[1 - self.sign.y].y - self.origin.y) * self.inv_direction.y;

        if (ray_min > y_max) || (y_min > ray_max) {
            return false;
        }

        if y_min > ray_min {
            ray_min = y_min;
        }
        if y_max < ray_max {
            ray_max = y_max;
        }

        let z_min = (aabb[self.sign.z].z - self.origin.z) * self.inv_direction.z;
        let z_max = (aabb[1 - self.sign.z].z - self.origin.z) * self.inv_direction.z;

        if (ray_min > z_max) || (z_min > ray_max) {
            return false;
        }
        // if z_min > ray_min {
        // ray_min = z_min;
        // }
        if z_max < ray_max {
            ray_max = z_max;
        }

        ray_max > 0.0
    }

    /// Naive implementation of a `Ray`/`AABB` intersection algorithm.
    pub fn intersects_aabb_2(&self, aabb: &AABB) -> bool {
        let hit_min_x = (aabb.min.x - self.origin.x) * self.inv_direction.x;
        let hit_max_x = (aabb.max.x - self.origin.x) * self.inv_direction.x;

        let hit_min_y = (aabb.min.y - self.origin.y) * self.inv_direction.y;
        let hit_max_y = (aabb.max.y - self.origin.y) * self.inv_direction.y;

        let hit_min_z = (aabb.min.z - self.origin.z) * self.inv_direction.z;
        let hit_max_z = (aabb.max.z - self.origin.z) * self.inv_direction.z;

        let x_entry = hit_min_x.min(hit_max_x);
        let y_entry = hit_min_y.min(hit_max_y);
        let z_entry = hit_min_z.min(hit_max_z);
        let x_exit = hit_min_x.max(hit_max_x);
        let y_exit = hit_min_y.max(hit_max_y);
        let z_exit = hit_min_z.max(hit_max_z);

        let latest_entry = x_entry.max(y_entry).max(z_entry);
        let earliest_exit = x_exit.min(y_exit).min(z_exit);

        latest_entry < earliest_exit && earliest_exit > 0.0
    }
}

#[cfg(test)]
mod tests {
    use ray::Ray;
    use aabb::AABB;
    use nalgebra::{Point3, Vector3};
    use rand::{Rng, StdRng, SeedableRng};

    const EPSILON: f32 = 0.00001;

    type TupleVec = (f32, f32, f32);

    fn tuple_to_point(tpl: &TupleVec) -> Point3<f32> {
        Point3::new(tpl.0, tpl.1, tpl.2)
    }

    fn tuple_to_vector(tpl: &TupleVec) -> Vector3<f32> {
        Vector3::new(tpl.0, tpl.1, tpl.2)
    }

    /// Test whether a `Ray` which points at the center of an `AABB` intersects it.
    quickcheck!{
        fn test_ray_points_at_aabb_center(pos: TupleVec,
                                          point_a: TupleVec,
                                          point_b: TupleVec)
                                          -> bool {
            // Generate a random AABB
            let aabb = AABB::empty()
                .union_point(&tuple_to_point(&point_a))
                .union_point(&tuple_to_point(&point_b));

            // Get its center
            let center = aabb.center();

            // Generate random ray pointing at the center
            let pos = tuple_to_point(&pos);
            let ray = Ray::new(pos, center - pos);

            // It must always intersect the AABB
            ray.intersects_aabb(&aabb)
        }
    }

    /// Test whether a `Ray` which points at the center of an `AABB` intersects it.
    /// Uses the naive algorithm.
    quickcheck!{
        fn test_ray_points_at_aabb_center_2(pos: TupleVec,
                                            point_a: TupleVec,
                                            point_b: TupleVec)
                                            -> bool {
            // Generate a random AABB
            let aabb = AABB::empty()
                .union_point(&tuple_to_point(&point_a))
                .union_point(&tuple_to_point(&point_b));

            // Get its center
            let center = aabb.center();

            // Generate random ray pointing at the center
            let pos = tuple_to_point(&pos);
            let ray = Ray::new(pos, center - pos);

            // It must always intersect the AABB
            ray.intersects_aabb_2(&aabb)
        }
    }

    /// Test whether a `Ray` which points away from the center of an `AABB`
    /// does not intersect it, unless its origin is inside the `AABB`.
    quickcheck!{
        fn test_ray_points_from_aabb_center(pos: TupleVec,
                                            point_a: TupleVec,
                                            point_b: TupleVec)
                                            -> bool {
            let aabb = AABB::empty()
                .union_point(&tuple_to_point(&point_a))
                .union_point(&tuple_to_point(&point_b));
            let center = aabb.center();
            let pos = tuple_to_point(&pos);
            let ray = Ray::new(pos, -(center - pos));
            !ray.intersects_aabb(&aabb) || aabb.contains(&ray.origin)
        }
    }

    /// Test whether a `Ray` which points away from the center of an `AABB`
    /// does not intersect it, unless its origin is inside the `AABB`.
    /// Uses the naive algorithm.
    quickcheck!{
        fn test_ray_points_from_aabb_center_2(pos: TupleVec,
                                              point_a: TupleVec,
                                              point_b: TupleVec)
                                              -> bool {
            let aabb = AABB::empty()
                .union_point(&tuple_to_point(&point_a))
                .union_point(&tuple_to_point(&point_b));
            let center = aabb.center();
            let pos = tuple_to_point(&pos);
            let ray = Ray::new(pos, -(center - pos));
            !ray.intersects_aabb_2(&aabb) || aabb.contains(&ray.origin)
        }
    }

    #[bench]
    /// Benchmark for the optimized intersection algorithm.
    fn bench_intersects_aabb(b: &mut ::test::Bencher) {
        let seed = [0];
        let mut rng = StdRng::from_seed(&seed);

        b.iter(|| {
            let one_million = ::test::black_box(1000);
            for _ in 0..one_million {
                let a = tuple_to_point(&rng.gen::<TupleVec>());
                let b = tuple_to_point(&rng.gen::<TupleVec>());
                let c = tuple_to_point(&rng.gen::<TupleVec>());
                let d = tuple_to_vector(&rng.gen::<TupleVec>());

                let aabb = AABB::empty().union_point(&a).union_point(&b);
                let ray = Ray::new(c, d);
                ray.intersects_aabb(&aabb);
            }
        });
    }

    #[bench]
    /// Benchmark for the naive intersection algorithm.
    fn bench_intersects_aabb_2(b: &mut ::test::Bencher) {
        let seed = [0];
        let mut rng = StdRng::from_seed(&seed);

        b.iter(|| {
            let one_million = ::test::black_box(1000);
            for _ in 0..one_million {
                let a = tuple_to_point(&rng.gen::<TupleVec>());
                let b = tuple_to_point(&rng.gen::<TupleVec>());
                let c = tuple_to_point(&rng.gen::<TupleVec>());
                let d = tuple_to_vector(&rng.gen::<TupleVec>());

                let aabb = AABB::empty().union_point(&a).union_point(&b);
                let ray = Ray::new(c, d);
                ray.intersects_aabb_2(&aabb);
            }
        });
    }
}
<commit_msg>Add a branchles intersection algorithm<commit_after>use aabb::AABB;
use nalgebra::{Vector3, Point3, Norm};

/// A struct which defines a ray and some of its cached values.
#[derive(Debug)]
pub struct Ray {
    pub origin: Point3<f32>,
    pub direction: Vector3<f32>,
    inv_direction: Vector3<f32>,
    sign: Vector3<usize>,
}

impl Ray {
    /// Creates a new `Ray`.
    pub fn new(origin: Point3<f32>, direction: Vector3<f32>) -> Ray {
        let direction = direction.normalize();
        Ray {
            origin: origin,
            direction: direction,
            inv_direction: Vector3::new(1.0 / direction.x, 1.0 / direction.y, 1.0 / direction.z),
            sign: Vector3::new((direction.x < 0.0) as usize,
                               (direction.y < 0.0) as usize,
                               (direction.z < 0.0) as usize),
        }
    }

    /// Tests the intersection of a `Ray` with an `AABB` using the optimized algorithm
    /// from this paper: http://www.cs.utah.edu/~awilliam/box/box.pdf
    pub fn intersects_aabb(&self, aabb: &AABB) -> bool {
        let mut ray_min = (aabb[self.sign.x].x - self.origin.x) * self.inv_direction.x;
        let mut ray_max = (aabb[1 - self.sign.x].x - self.origin.x) * self.inv_direction.x;

        let y_min = (aabb[self.sign.y].y - self.origin.y) * self.inv_direction.y;
        let y_max = (aabb[1 - self.sign.y].y - self.origin.y) * self.inv_direction.y;

        if (ray_min > y_max) || (y_min > ray_max) {
            return false;
        }

        if y_min > ray_min {
            ray_min = y_min;
        }
        if y_max < ray_max {
            ray_max = y_max;
        }

        let z_min = (aabb[self.sign.z].z - self.origin.z) * self.inv_direction.z;
        let z_max = (aabb[1 - self.sign.z].z - self.origin.z) * self.inv_direction.z;

        if (ray_min > z_max) || (z_min > ray_max) {
            return false;
        }
        // if z_min > ray_min {
        // ray_min = z_min;
        // }
        if z_max < ray_max {
            ray_max = z_max;
        }

        ray_max > 0.0
    }

    /// Naive implementation of a `Ray`/`AABB` intersection algorithm.
    pub fn intersects_aabb_naive(&self, aabb: &AABB) -> bool {
        let hit_min_x = (aabb.min.x - self.origin.x) * self.inv_direction.x;
        let hit_max_x = (aabb.max.x - self.origin.x) * self.inv_direction.x;

        let hit_min_y = (aabb.min.y - self.origin.y) * self.inv_direction.y;
        let hit_max_y = (aabb.max.y - self.origin.y) * self.inv_direction.y;

        let hit_min_z = (aabb.min.z - self.origin.z) * self.inv_direction.z;
        let hit_max_z = (aabb.max.z - self.origin.z) * self.inv_direction.z;

        let x_entry = hit_min_x.min(hit_max_x);
        let y_entry = hit_min_y.min(hit_max_y);
        let z_entry = hit_min_z.min(hit_max_z);
        let x_exit = hit_min_x.max(hit_max_x);
        let y_exit = hit_min_y.max(hit_max_y);
        let z_exit = hit_min_z.max(hit_max_z);

        let latest_entry = x_entry.max(y_entry).max(z_entry);
        let earliest_exit = x_exit.min(y_exit).min(z_exit);

        latest_entry < earliest_exit && earliest_exit > 0.0
    }

    /// Implementation of the algorithm described here:
    /// https://tavianator.com/fast-branchless-raybounding-box-intersections/
    pub fn intersects_aabb_branchless(&self, aabb: &AABB) -> bool {
        let tx1 = (aabb.min.x - self.origin.x) * self.inv_direction.x;
        let tx2 = (aabb.max.x - self.origin.x) * self.inv_direction.x;

        let mut tmin = tx1.min(tx2);
        let mut tmax = tx1.max(tx2);

        let ty1 = (aabb.min.y - self.origin.y) * self.inv_direction.y;
        let ty2 = (aabb.max.y - self.origin.y) * self.inv_direction.y;

        tmin = tmin.max(ty1.min(ty2));
        tmax = tmax.min(ty1.max(ty2));

        let tz1 = (aabb.min.z - self.origin.z) * self.inv_direction.z;
        let tz2 = (aabb.max.z - self.origin.z) * self.inv_direction.z;

        tmin = tmin.max(tz1.min(tz2));
        tmax = tmax.min(tz1.max(tz2));

        tmax >= tmin && tmax >= 0.0
    }
}

#[cfg(test)]
mod tests {
    use ray::Ray;
    use aabb::AABB;
    use nalgebra::{Point3, Vector3};
    use rand::{Rng, StdRng, SeedableRng};

    type TupleVec = (f32, f32, f32);

    fn tuple_to_point(tpl: &TupleVec) -> Point3<f32> {
        Point3::new(tpl.0, tpl.1, tpl.2)
    }

    fn tuple_to_vector(tpl: &TupleVec) -> Vector3<f32> {
        Vector3::new(tpl.0, tpl.1, tpl.2)
    }

    fn gen_ray_to_aabb(data: (TupleVec, TupleVec, TupleVec)) -> (Ray, AABB) {
        // Generate a random AABB
        let aabb = AABB::empty()
            .union_point(&tuple_to_point(&data.0))
            .union_point(&tuple_to_point(&data.1));

        // Get its center
        let center = aabb.center();

        // Generate random ray pointing at the center
        let pos = tuple_to_point(&data.2);
        let ray = Ray::new(pos, center - pos);
        (ray, aabb)
    }

    /// Test whether a `Ray` which points at the center of an `AABB` intersects it.
    /// Uses the optimized algorithm.
    quickcheck!{
        fn test_ray_points_at_aabb_center(data: (TupleVec, TupleVec, TupleVec)) -> bool {
            let (ray, aabb) = gen_ray_to_aabb(data);
            ray.intersects_aabb(&aabb)
        }
    }

    /// Test whether a `Ray` which points at the center of an `AABB` intersects it.
    /// Uses the naive algorithm.
    quickcheck!{
        fn test_ray_points_at_aabb_center_naive(data: (TupleVec, TupleVec, TupleVec)) -> bool {
            let (ray, aabb) = gen_ray_to_aabb(data);
            ray.intersects_aabb_naive(&aabb)
        }
    }

    /// Test whether a `Ray` which points at the center of an `AABB` intersects it.
    /// Uses the branchless algorithm.
    quickcheck!{
        fn test_ray_points_at_aabb_center_branchless(data: (TupleVec, TupleVec, TupleVec)) -> bool {
            let (ray, aabb) = gen_ray_to_aabb(data);
            ray.intersects_aabb_branchless(&aabb)
        }
    }

    /// Test whether a `Ray` which points away from the center of an `AABB`
    /// does not intersect it, unless its origin is inside the `AABB`.
    /// Uses the optimized algorithm.
    quickcheck!{
        fn test_ray_points_from_aabb_center(data: (TupleVec, TupleVec, TupleVec)) -> bool {
            let (mut ray, aabb) = gen_ray_to_aabb(data);
            ray.direction = -ray.direction;
            ray.inv_direction = -ray.inv_direction;
            !ray.intersects_aabb(&aabb) || aabb.contains(&ray.origin)
        }
    }

    /// Test whether a `Ray` which points away from the center of an `AABB`
    /// does not intersect it, unless its origin is inside the `AABB`.
    /// Uses the naive algorithm.
    quickcheck!{
        fn test_ray_points_from_aabb_center_naive(data: (TupleVec, TupleVec, TupleVec)) -> bool {
            let (mut ray, aabb) = gen_ray_to_aabb(data);
            ray.direction = -ray.direction;
            ray.inv_direction = -ray.inv_direction;
            !ray.intersects_aabb_naive(&aabb) || aabb.contains(&ray.origin)
        }
    }

    /// Test whether a `Ray` which points away from the center of an `AABB`
    /// does not intersect it, unless its origin is inside the `AABB`.
    /// Uses the branchless algorithm.
    quickcheck!{
        fn test_ray_points_from_aabb_center_branchless(data: (TupleVec, TupleVec, TupleVec)) -> bool {
            let (mut ray, aabb) = gen_ray_to_aabb(data);
            ray.direction = -ray.direction;
            ray.inv_direction = -ray.inv_direction;
            !ray.intersects_aabb_branchless(&aabb) || aabb.contains(&ray.origin)
        }
    }

    fn gen_random_ray_aabb(rng: &mut StdRng) -> (Ray, AABB) {
        let a = tuple_to_point(&rng.gen::<TupleVec>());
        let b = tuple_to_point(&rng.gen::<TupleVec>());
        let c = tuple_to_point(&rng.gen::<TupleVec>());
        let d = tuple_to_vector(&rng.gen::<TupleVec>());

        let aabb = AABB::empty().union_point(&a).union_point(&b);
        let ray = Ray::new(c, d);
        (ray, aabb)
    }

    #[bench]
    /// Benchmark for the optimized intersection algorithm.
    fn bench_intersects_aabb(b: &mut ::test::Bencher) {
        let seed = [0];
        let mut rng = StdRng::from_seed(&seed);

        b.iter(|| {
            let one_thousand = ::test::black_box(1000);
            for _ in 0..one_thousand {
                let (ray, aabb) = gen_random_ray_aabb(&mut rng);
                ray.intersects_aabb(&aabb);
            }
        });
    }

    #[bench]
    /// Benchmark for the naive intersection algorithm.
    fn bench_intersects_aabb_naive(b: &mut ::test::Bencher) {
        let seed = [0];
        let mut rng = StdRng::from_seed(&seed);

        b.iter(|| {
            let one_thousand = ::test::black_box(1000);
            for _ in 0..one_thousand {
                let (ray, aabb) = gen_random_ray_aabb(&mut rng);
                ray.intersects_aabb_naive(&aabb);
            }
        });
    }

    #[bench]
    /// Benchmark for the branchless intersection algorithm.
    fn bench_intersects_aabb_branchless(b: &mut ::test::Bencher) {
        let seed = [0];
        let mut rng = StdRng::from_seed(&seed);

        b.iter(|| {
            let one_thousand = ::test::black_box(1000);
            for _ in 0..one_thousand {
                let (ray, aabb) = gen_random_ray_aabb(&mut rng);
                ray.intersects_aabb_branchless(&aabb);
            }
        });
    }
}
<|endoftext|>


<commit_before>//! Rust representations of docker json structures

use std::collections::HashMap;

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SearchResult {
    pub description: String,
    pub is_official: bool,
    pub is_trusted: bool,
    pub name: String,
    pub star_count: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Image {
    pub Created: u64,
    pub Id: String,
    pub ParentId: String,
    pub Labels: Option<HashMap<String, String>>,
    pub RepoTags: Vec<String>,
    pub RepoDigests: Option<Vec<String>>,
    pub Size: u64,
    pub VirtualSize: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ImageDetails {
    pub Architecture: String,
    pub Author: String,
    pub Comment: String,
    pub Config: Config,
    pub Created: String,
    pub DockerVersion: String,
    pub Id: String,
    pub Os: String,
    pub Parent: String,
    pub Size: u64,
    pub VirtualSize: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Container {
    pub Created: u64,
    pub Command: String,
    pub Id: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    pub Names: Vec<String>,
    pub Ports: Vec<Port>,
    pub Status: String,
    pub SizeRw: Option<u64>,
    pub SizeRootFs: Option<u64>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerDetails {
    pub AppArmorProfile: String,
    pub Args: Vec<String>,
    pub Config: Config,
    pub Created: String,
    pub Driver: String,
    pub ExecDriver: String,
    // pub ExecIDs: ??
    pub HostConfig: HostConfig,
    pub HostnamePath: String,
    pub HostsPath: String,
    pub LogPath: String,
    pub Id: String,
    pub Image: String,
    pub MountLabel: String,
    pub NetworkSettings: NetworkSettings,
    pub Path: String,
    pub ProcessLabel: String,
    pub ResolvConfPath: String,
    pub RestartCount: u64,
    pub State: State,
    pub Mounts: Vec<Mount>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Mount {
    pub Source: String,
    pub Destination: String,
    pub Mode: String,
    pub RW: bool,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct State {
    pub Error: String,
    pub ExitCode: u64,
    pub FinishedAt: String,
    pub OOMKilled: bool,
    pub Paused: bool,
    pub Pid: u64,
    pub Restarting: bool,
    pub Running: bool,
    pub StartedAt: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkSettings {
    pub Bridge: String,
    pub Gateway: String,
    pub IPAddress: String,
    pub IPPrefixLen: u64,
    pub MacAddress: String, /*    pub PortMapping: Option<???>,
                             *   pub Ports: Option<???> */
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct HostConfig {
    pub CgroupParent: Option<String>,
    pub ContainerIDFile: String,
    pub CpuShares: Option<u64>,
    pub CpusetCpus: Option<String>,
    pub Memory: Option<u64>,
    pub MemorySwap: Option<u64>,
    pub NetworkMode: String,
    pub PidMode: Option<String>,
    // pub PortBindings: ???
    pub Privileged: bool,
    pub PublishAllPorts: bool,
    pub ReadonlyRootfs: Option<bool>, /* pub RestartPolicy: ???
                                       * pub SecurityOpt: Option<???>,
                                       * pub Ulimits: Option<???>
                                       * pub VolumesFrom: Option<??/> */
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Config {
    pub AttachStderr: bool,
    pub AttachStdin: bool,
    pub AttachStdout: bool,
    pub Cmd: Option<Vec<String>>,
    pub Domainname: String,
    pub Entrypoint: Option<Vec<String>>,
    pub Env: Option<Vec<String>>,
    // ExposedPorts
    pub Hostname: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    // pub MacAddress: String,
    pub OnBuild: Option<String>,
    // pub NetworkDisabled: bool,
    pub OpenStdin: bool,
    pub StdinOnce: bool,
    pub Tty: bool,
    pub User: String,
    pub WorkingDir: String,
}

impl Config {
    pub fn env(&self) -> HashMap<String, String> {
        let mut map = HashMap::new();
        match self.Env {
            Some(ref vars) => {
                for e in vars {
                    let pair: Vec<&str> = e.split("=").collect();
                    map.insert(pair[0].to_owned(), pair[1].to_owned());
                }
            }
            _ => (),
        };
        map
    }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Port {
    pub IP: Option<String>,
    pub PrivatePort: u64,
    pub PublicPort: Option<u64>,
    pub Type: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Stats {
    pub read: String,
    pub networks: HashMap<String, Network>,
    pub memory_stats: MemoryStats,
    pub blkio_stats: BlkioStats,
    pub cpu_stats: CpuStats,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Network {
    pub rx_dropped: u64,
    pub rx_bytes: u64,
    pub rx_errors: u64,
    pub tx_packets: u64,
    pub tx_dropped: u64,
    pub rx_packets: u64,
    pub tx_errors: u64,
    pub tx_bytes: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStats {
    pub max_usage: u64,
    pub usage: u64,
    pub failcnt: u64,
    pub limit: u64,
    pub stats: MemoryStat,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStat {
    pub total_pgmajfault: u64,
    pub cache: u64,
    pub mapped_file: u64,
    pub total_inactive_file: u64,
    pub pgpgout: u64,
    pub rss: u64,
    pub total_mapped_file: u64,
    pub writeback: u64,
    pub unevictable: u64,
    pub pgpgin: u64,
    pub total_unevictable: u64,
    pub pgmajfault: u64,
    pub total_rss: u64,
    pub total_rss_huge: u64,
    pub total_writeback: u64,
    pub total_inactive_anon: u64,
    pub rss_huge: u64,
    pub hierarchical_memory_limit: u64,
    pub hierarchical_memsw_limit: u64,
    pub total_pgfault: u64,
    pub total_active_file: u64,
    pub active_anon: u64,
    pub total_active_anon: u64,
    pub total_pgpgout: u64,
    pub total_cache: u64,
    pub inactive_anon: u64,
    pub active_file: u64,
    pub pgfault: u64,
    pub inactive_file: u64,
    pub total_pgpgin: u64,
    pub swap: u64,
    pub total_swap: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct CpuStats {
    pub cpu_usage: CpuUsage,
    pub system_cpu_usage: u64,
    pub throttling_data: ThrottlingData,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct CpuUsage {
    pub percpu_usage: Vec<u64>,
    pub usage_in_usermode: u64,
    pub total_usage: u64,
    pub usage_in_kernelmode: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct ThrottlingData {
    pub periods: u64,
    pub throttled_periods: u64,
    pub throttled_time: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStats {
    pub io_service_bytes_recursive: Vec<BlkioStat>,
    pub io_serviced_recursive: Vec<BlkioStat>,
    pub io_queue_recursive: Vec<BlkioStat>,
    pub io_service_time_recursive: Vec<BlkioStat>,
    pub io_wait_time_recursive: Vec<BlkioStat>,
    pub io_merged_recursive: Vec<BlkioStat>,
    pub io_time_recursive: Vec<BlkioStat>,
    pub sectors_recursive: Vec<BlkioStat>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStat {
    pub major: u64,
    pub minor: u64,
    pub op: String,
    pub value: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Change {
    pub Kind: u64,
    pub Path: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Top {
    pub Titles: Vec<String>,
    pub Processes: Vec<Vec<String>>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Version {
    pub ApiVersion: String,
    pub Version: String,
    pub GitCommit: String,
    pub GoVersion: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Info {
    pub Containers: u64,
    pub Images: u64,
    pub Driver: String,
    pub DockerRootDir: String,
    pub DriverStatus: Vec<Vec<String>>,
    pub ExecutionDriver: String,
    pub ID: String,
    pub KernelVersion: String,
    // pub Labels: Option<???>,
    pub MemTotal: u64,
    pub MemoryLimit: bool,
    pub NCPU: u64,
    pub NEventsListener: u64,
    pub NGoroutines: u64,
    pub Name: String,
    pub OperatingSystem: String,
    // pub RegistryConfig:???
    pub SwapLimit: bool,
    pub SystemTime: Option<String>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerCreateInfo {
    pub Id: String,
    pub Warnings: Option<Vec<String>>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct History {
    pub Id: String,
    pub Created: u64,
    pub CreatedBy: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Exit {
    pub StatusCode: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Event {
    pub status: String,
    pub id: String,
    pub from: Option<String>,
    pub time: u64,
    pub timeNano: u64,
}

#[derive(Debug)]
pub enum BuildOutput {
    Stream(String),
    Err(String),
}

// fixme: all fields are options because PullInfo.progressDefault is sometimes an empty object instead of a null/absent value
#[derive(Clone, Debug, RustcDecodable)]
pub struct ProgressDetail {
    current: Option<u64>,
    total: Option<u64>,
    status: Option<String>, // fixme: it looks like this field isn't deserializing properly
}

#[derive(Clone, Debug, RustcDecodable)]
#[allow(non_snake_case)]
pub struct PullInfo {
    pub id: Option<String>,
    pub status: String,
    pub progress: Option<String>,
    pub progressDetail: Option<ProgressDetail>,
}

#[derive(Debug)]
pub enum PullOutput {
    Status {
        id: Option<String>,
        status: String,
        progress: Option<String>,
        progress_detail: Option<ProgressDetail>,
    },
    Err(String),
}

#[derive(Debug)]
pub enum Status {
    Untagged(String),
    Deleted(String),
}
<commit_msg>Fix: execDriver is not return by the api.<commit_after>//! Rust representations of docker json structures

use std::collections::HashMap;

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SearchResult {
    pub description: String,
    pub is_official: bool,
    pub is_trusted: bool,
    pub name: String,
    pub star_count: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Image {
    pub Created: u64,
    pub Id: String,
    pub ParentId: String,
    pub Labels: Option<HashMap<String, String>>,
    pub RepoTags: Vec<String>,
    pub RepoDigests: Option<Vec<String>>,
    pub Size: u64,
    pub VirtualSize: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ImageDetails {
    pub Architecture: String,
    pub Author: String,
    pub Comment: String,
    pub Config: Config,
    pub Created: String,
    pub DockerVersion: String,
    pub Id: String,
    pub Os: String,
    pub Parent: String,
    pub Size: u64,
    pub VirtualSize: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Container {
    pub Created: u64,
    pub Command: String,
    pub Id: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    pub Names: Vec<String>,
    pub Ports: Vec<Port>,
    pub Status: String,
    pub SizeRw: Option<u64>,
    pub SizeRootFs: Option<u64>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerDetails {
    pub AppArmorProfile: String,
    pub Args: Vec<String>,
    pub Config: Config,
    pub Created: String,
    pub Driver: String,
    // pub ExecIDs: ??
    pub HostConfig: HostConfig,
    pub HostnamePath: String,
    pub HostsPath: String,
    pub LogPath: String,
    pub Id: String,
    pub Image: String,
    pub MountLabel: String,
    pub NetworkSettings: NetworkSettings,
    pub Path: String,
    pub ProcessLabel: String,
    pub ResolvConfPath: String,
    pub RestartCount: u64,
    pub State: State,
    pub Mounts: Vec<Mount>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Mount {
    pub Source: String,
    pub Destination: String,
    pub Mode: String,
    pub RW: bool,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct State {
    pub Error: String,
    pub ExitCode: u64,
    pub FinishedAt: String,
    pub OOMKilled: bool,
    pub Paused: bool,
    pub Pid: u64,
    pub Restarting: bool,
    pub Running: bool,
    pub StartedAt: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct NetworkSettings {
    pub Bridge: String,
    pub Gateway: String,
    pub IPAddress: String,
    pub IPPrefixLen: u64,
    pub MacAddress: String, /*    pub PortMapping: Option<???>,
                             *   pub Ports: Option<???> */
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct HostConfig {
    pub CgroupParent: Option<String>,
    pub ContainerIDFile: String,
    pub CpuShares: Option<u64>,
    pub CpusetCpus: Option<String>,
    pub Memory: Option<u64>,
    pub MemorySwap: Option<u64>,
    pub NetworkMode: String,
    pub PidMode: Option<String>,
    // pub PortBindings: ???
    pub Privileged: bool,
    pub PublishAllPorts: bool,
    pub ReadonlyRootfs: Option<bool>, /* pub RestartPolicy: ???
                                       * pub SecurityOpt: Option<???>,
                                       * pub Ulimits: Option<???>
                                       * pub VolumesFrom: Option<??/> */
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Config {
    pub AttachStderr: bool,
    pub AttachStdin: bool,
    pub AttachStdout: bool,
    pub Cmd: Option<Vec<String>>,
    pub Domainname: String,
    pub Entrypoint: Option<Vec<String>>,
    pub Env: Option<Vec<String>>,
    // ExposedPorts
    pub Hostname: String,
    pub Image: String,
    pub Labels: HashMap<String, String>,
    // pub MacAddress: String,
    pub OnBuild: Option<String>,
    // pub NetworkDisabled: bool,
    pub OpenStdin: bool,
    pub StdinOnce: bool,
    pub Tty: bool,
    pub User: String,
    pub WorkingDir: String,
}

impl Config {
    pub fn env(&self) -> HashMap<String, String> {
        let mut map = HashMap::new();
        match self.Env {
            Some(ref vars) => {
                for e in vars {
                    let pair: Vec<&str> = e.split("=").collect();
                    map.insert(pair[0].to_owned(), pair[1].to_owned());
                }
            }
            _ => (),
        };
        map
    }
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Port {
    pub IP: Option<String>,
    pub PrivatePort: u64,
    pub PublicPort: Option<u64>,
    pub Type: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Stats {
    pub read: String,
    pub networks: HashMap<String, Network>,
    pub memory_stats: MemoryStats,
    pub blkio_stats: BlkioStats,
    pub cpu_stats: CpuStats,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Network {
    pub rx_dropped: u64,
    pub rx_bytes: u64,
    pub rx_errors: u64,
    pub tx_packets: u64,
    pub tx_dropped: u64,
    pub rx_packets: u64,
    pub tx_errors: u64,
    pub tx_bytes: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStats {
    pub max_usage: u64,
    pub usage: u64,
    pub failcnt: u64,
    pub limit: u64,
    pub stats: MemoryStat,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MemoryStat {
    pub total_pgmajfault: u64,
    pub cache: u64,
    pub mapped_file: u64,
    pub total_inactive_file: u64,
    pub pgpgout: u64,
    pub rss: u64,
    pub total_mapped_file: u64,
    pub writeback: u64,
    pub unevictable: u64,
    pub pgpgin: u64,
    pub total_unevictable: u64,
    pub pgmajfault: u64,
    pub total_rss: u64,
    pub total_rss_huge: u64,
    pub total_writeback: u64,
    pub total_inactive_anon: u64,
    pub rss_huge: u64,
    pub hierarchical_memory_limit: u64,
    pub hierarchical_memsw_limit: u64,
    pub total_pgfault: u64,
    pub total_active_file: u64,
    pub active_anon: u64,
    pub total_active_anon: u64,
    pub total_pgpgout: u64,
    pub total_cache: u64,
    pub inactive_anon: u64,
    pub active_file: u64,
    pub pgfault: u64,
    pub inactive_file: u64,
    pub total_pgpgin: u64,
    pub swap: u64,
    pub total_swap: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct CpuStats {
    pub cpu_usage: CpuUsage,
    pub system_cpu_usage: u64,
    pub throttling_data: ThrottlingData,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct CpuUsage {
    pub percpu_usage: Vec<u64>,
    pub usage_in_usermode: u64,
    pub total_usage: u64,
    pub usage_in_kernelmode: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct ThrottlingData {
    pub periods: u64,
    pub throttled_periods: u64,
    pub throttled_time: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStats {
    pub io_service_bytes_recursive: Vec<BlkioStat>,
    pub io_serviced_recursive: Vec<BlkioStat>,
    pub io_queue_recursive: Vec<BlkioStat>,
    pub io_service_time_recursive: Vec<BlkioStat>,
    pub io_wait_time_recursive: Vec<BlkioStat>,
    pub io_merged_recursive: Vec<BlkioStat>,
    pub io_time_recursive: Vec<BlkioStat>,
    pub sectors_recursive: Vec<BlkioStat>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlkioStat {
    pub major: u64,
    pub minor: u64,
    pub op: String,
    pub value: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Change {
    pub Kind: u64,
    pub Path: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Top {
    pub Titles: Vec<String>,
    pub Processes: Vec<Vec<String>>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Version {
    pub ApiVersion: String,
    pub Version: String,
    pub GitCommit: String,
    pub GoVersion: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Info {
    pub Containers: u64,
    pub Images: u64,
    pub Driver: String,
    pub DockerRootDir: String,
    pub DriverStatus: Vec<Vec<String>>,
    pub ExecutionDriver: String,
    pub ID: String,
    pub KernelVersion: String,
    // pub Labels: Option<???>,
    pub MemTotal: u64,
    pub MemoryLimit: bool,
    pub NCPU: u64,
    pub NEventsListener: u64,
    pub NGoroutines: u64,
    pub Name: String,
    pub OperatingSystem: String,
    // pub RegistryConfig:???
    pub SwapLimit: bool,
    pub SystemTime: Option<String>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct ContainerCreateInfo {
    pub Id: String,
    pub Warnings: Option<Vec<String>>,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct History {
    pub Id: String,
    pub Created: u64,
    pub CreatedBy: String,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Exit {
    pub StatusCode: u64,
}

#[derive(Debug, RustcEncodable, RustcDecodable)]
#[allow(non_snake_case)]
pub struct Event {
    pub status: String,
    pub id: String,
    pub from: Option<String>,
    pub time: u64,
    pub timeNano: u64,
}

#[derive(Debug)]
pub enum BuildOutput {
    Stream(String),
    Err(String),
}

// fixme: all fields are options because PullInfo.progressDefault is sometimes an empty object instead of a null/absent value
#[derive(Clone, Debug, RustcDecodable)]
pub struct ProgressDetail {
    current: Option<u64>,
    total: Option<u64>,
    status: Option<String>, // fixme: it looks like this field isn't deserializing properly
}

#[derive(Clone, Debug, RustcDecodable)]
#[allow(non_snake_case)]
pub struct PullInfo {
    pub id: Option<String>,
    pub status: String,
    pub progress: Option<String>,
    pub progressDetail: Option<ProgressDetail>,
}

#[derive(Debug)]
pub enum PullOutput {
    Status {
        id: Option<String>,
        status: String,
        progress: Option<String>,
        progress_detail: Option<ProgressDetail>,
    },
    Err(String),
}

#[derive(Debug)]
pub enum Status {
    Untagged(String),
    Deleted(String),
}
<|endoftext|>


<commit_before>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, theta: int) {
        // TODO theta = 60degrees use 3/4th and 1/4th
        // TODO theta = 0 SpinUp
        // TODO theta = 180 SpinDown
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let spin = match self.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            SpinSuper => SpinUp
        };
        friend.spin = spin;

        let spin = match friend.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    pub fn premeditated (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        if rnd < 0.33 {
            let direction = Detector::D12;
        } else if rnd >= 0.33 && rnd < 0.66 {
            let direction = Detector::D3;
        } else {
            let direction = Detector::D9;
        }

        // TODO: Use plan
        friend.spin = SpinUp;

        let spin = match friend.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

fn main () {

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    lhs.spooky(&mut rhs);

    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

    // premeditated should give +55.6% difference, spooky would give 50%
}
<commit_msg>add detector, and plan<commit_after>extern crate core;

use core::num::FromPrimitive;
use core::fmt;

use std::rand::random;

use Direction::{SpinUp, SpinDown, SpinSuper};
use Plan::{Trivial, OddBall};

#[derive(Copy)]
#[derive(Show)]
enum Direction {
    SpinUp,
    SpinDown,
    SpinSuper,
}

impl fmt::String for Direction {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r = match self {
            &SpinUp => "SpinUp",
            &SpinDown => "SpinDown",
            &SpinSuper => "SpinSuper"
        };
        write!(f, "{}", r)
    }
}

struct Pair<T> {
    lhs: T,
    rhs: T
}

struct Particle {
    spin: Direction
}

enum Plan {
    Trivial, // up-up-up -> down-down-down
    OddBall  // up-down-up -> down-up-down
}

enum Detector {
    D12, // 12 o'clock
    D3, // 3 o'clock
    D9, // 9 o' clock
}

impl Particle {
    fn new_pair () -> Pair<Particle> {
        let d1 = SpinSuper;
        let d2 = SpinSuper;
        let p1 = Particle{spin: d1};
        let p2 = Particle{spin: d2};

        return Pair{lhs: p1, rhs: p2};
    }

    pub fn measure (&mut self, theta: int) {
        // TODO theta = 60degrees use 3/4th and 1/4th
        // TODO theta = 0 SpinUp
        // TODO theta = 180 SpinDown
    }

    // NOTE on spooky and premeditated only if measured in the same
    // direction must the spins be opposite

    // measure with with a message
    pub fn spooky (&mut self, friend: &mut Particle) -> Pair<Direction> {

        let spin = match self.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            SpinSuper => SpinUp
        };
        friend.spin = spin;

        let spin = match friend.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }

    pub fn premeditated (&mut self, friend: &mut Particle, plan: Plan) -> Pair<Direction> {

        let rnd = random::<f32>();

        let direction;

        if rnd < 0.33 {
            direction = Detector::D12;
        } else if rnd >= 0.33 && rnd < 0.66 {
            direction = Detector::D3;
        } else {
            direction = Detector::D9;
        }

        let spin = match plan {
            Trivial => SpinUp,
            OddBall => match direction {
                Detector::D3 => SpinDown,
                _ => SpinUp
            }
        };
        friend.spin = spin;

        let spin = match friend.spin {
            SpinUp => SpinDown,
            SpinDown => SpinUp,
            _ => panic!("broke the universe")
        };
        self.spin = spin;

        return Pair{lhs: self.spin, rhs: friend.spin};
    }
}

fn main () {

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;

    lhs.spooky(&mut rhs);

    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

    // premeditated should give +55.6% difference, spooky would give 50%

    let particles = Particle::new_pair();

    let mut lhs = particles.lhs;
    let mut rhs = particles.rhs;
    lhs.premeditated(&mut rhs, OddBall);
    println!("lhs.spin {}, rhs.spin {}", lhs.spin, rhs.spin);

}
<|endoftext|>


<commit_before>// Copyright 2015 The Ramp Developers
//
//    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.

//! Memory management functions. The base functions align to a pointer-width, so they shouldn't
//! be used for anything that requires an alignment greater than that.

use std::alloc::{self, AllocRef};
use std::intrinsics::abort;
use std::io::{self, Write};
use std::mem;
use std::ptr;

use ll::limb::Limb;
use ll::limb_ptr::LimbsMut;

/// Returns a Layout with the given size and pointer-width (i.e., usize) alignment. Panics if
/// unable to create the Layout.
unsafe fn get_usize_align_layout(size: usize) -> alloc::Layout {
    let alignment = mem::align_of::<usize>();

    match alloc::Layout::from_size_align(size, alignment) {
        Ok(l) => l,
        Err(layout_err) => {
            let _ = writeln!(
                io::stderr(),
                "Failed to construct mem layout (size={}, alignment={}): {}",
                size,
                alignment,
                layout_err
            );
            abort();
        }
    }
}

pub unsafe fn allocate_bytes(size: usize) -> *mut u8 {
    let layout = get_usize_align_layout(size);
    let ret = match alloc::Global.alloc(layout.clone()) {
        Ok(p) => p.as_ptr(),
        Err(e) => {
            writeln!(
                io::stderr(),
                "Failed to allocate memory (layout={:?}).\nError: {:?}",
                layout,
                e
            )
            .unwrap();
            abort();
        }
    };

    ptr::write_bytes(ret, 0, size);
    ret
}

pub unsafe fn deallocate_bytes(ptr: ptr::NonNull<u8>, size: usize) {
    let layout = get_usize_align_layout(size);
    alloc::Global.dealloc(ptr, layout);
}

/// Allocate for temporary storage. Ensures that the allocations are
/// freed when the structure drops
pub struct TmpAllocator {
    mark: *mut Marker,
}

struct Marker {
    next: *mut Marker,
    size: usize,
}

impl TmpAllocator {
    pub fn new() -> TmpAllocator {
        TmpAllocator {
            mark: ptr::null_mut(),
        }
    }

    pub unsafe fn allocate_bytes(&mut self, size: usize) -> *mut u8 {
        let size = size + mem::size_of::<Marker>();
        let ptr = allocate_bytes(size);

        let mark = ptr as *mut Marker;
        (*mark).size = size;
        (*mark).next = self.mark;

        self.mark = mark;

        ptr.offset(mem::size_of::<Marker>() as isize)
    }

    /// Allocate space for n limbs
    pub unsafe fn allocate(&mut self, n: usize) -> LimbsMut {
        let ptr = self.allocate_bytes(n * mem::size_of::<Limb>()) as *mut Limb;
        LimbsMut::new(ptr, 0, n as i32)
    }

    /// Allocates space for n1+n2 limbs and returns a pair of pointers.
    pub unsafe fn allocate_2(&mut self, n1: usize, n2: usize) -> (LimbsMut, LimbsMut) {
        let mut x = self.allocate(n1 + n2);
        let mut y = x.offset(n1 as isize);
        (
            LimbsMut::new(&mut *x, 0, n1 as i32),
            LimbsMut::new(&mut *y, 0, n2 as i32),
        )
    }
}

impl Drop for TmpAllocator {
    fn drop(&mut self) {
        unsafe {
            let mut next;
            let mut mark = self.mark;
            // Iterate the list until we hit a null ptr
            while let Some(checked_mark) = ptr::NonNull::new(mark) {
                next = checked_mark.as_ref().next;
                let size = checked_mark.as_ref().size;
                deallocate_bytes(checked_mark.cast(), size);
                mark = next;
            }
        }
    }
}
<commit_msg>Fixed compile error due to new alloc API<commit_after>// Copyright 2015 The Ramp Developers
//
//    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.

//! Memory management functions. The base functions align to a pointer-width, so they shouldn't
//! be used for anything that requires an alignment greater than that.

use std::alloc::{self, AllocRef};
use std::intrinsics::abort;
use std::io::{self, Write};
use std::mem;
use std::ptr;

use ll::limb::Limb;
use ll::limb_ptr::LimbsMut;

/// Returns a Layout with the given size and pointer-width (i.e., usize) alignment. Panics if
/// unable to create the Layout.
unsafe fn get_usize_align_layout(size: usize) -> alloc::Layout {
    let alignment = mem::align_of::<usize>();

    match alloc::Layout::from_size_align(size, alignment) {
        Ok(l) => l,
        Err(layout_err) => {
            let _ = writeln!(
                io::stderr(),
                "Failed to construct mem layout (size={}, alignment={}): {}",
                size,
                alignment,
                layout_err
            );
            abort();
        }
    }
}

pub unsafe fn allocate_bytes(size: usize) -> *mut u8 {
    let layout = get_usize_align_layout(size);
    let ret = match alloc::Global.alloc(layout.clone()) {
        Ok((p, _)) => p.as_ptr(),
        Err(e) => {
            writeln!(
                io::stderr(),
                "Failed to allocate memory (layout={:?}).\nError: {:?}",
                layout,
                e
            )
            .unwrap();
            abort();
        }
    };

    ptr::write_bytes(ret, 0, size);
    ret
}

pub unsafe fn deallocate_bytes(ptr: ptr::NonNull<u8>, size: usize) {
    let layout = get_usize_align_layout(size);
    alloc::Global.dealloc(ptr, layout);
}

/// Allocate for temporary storage. Ensures that the allocations are
/// freed when the structure drops
pub struct TmpAllocator {
    mark: *mut Marker,
}

struct Marker {
    next: *mut Marker,
    size: usize,
}

impl TmpAllocator {
    pub fn new() -> TmpAllocator {
        TmpAllocator {
            mark: ptr::null_mut(),
        }
    }

    pub unsafe fn allocate_bytes(&mut self, size: usize) -> *mut u8 {
        let size = size + mem::size_of::<Marker>();
        let ptr = allocate_bytes(size);

        let mark = ptr as *mut Marker;
        (*mark).size = size;
        (*mark).next = self.mark;

        self.mark = mark;

        ptr.offset(mem::size_of::<Marker>() as isize)
    }

    /// Allocate space for n limbs
    pub unsafe fn allocate(&mut self, n: usize) -> LimbsMut {
        let ptr = self.allocate_bytes(n * mem::size_of::<Limb>()) as *mut Limb;
        LimbsMut::new(ptr, 0, n as i32)
    }

    /// Allocates space for n1+n2 limbs and returns a pair of pointers.
    pub unsafe fn allocate_2(&mut self, n1: usize, n2: usize) -> (LimbsMut, LimbsMut) {
        let mut x = self.allocate(n1 + n2);
        let mut y = x.offset(n1 as isize);
        (
            LimbsMut::new(&mut *x, 0, n1 as i32),
            LimbsMut::new(&mut *y, 0, n2 as i32),
        )
    }
}

impl Drop for TmpAllocator {
    fn drop(&mut self) {
        unsafe {
            let mut next;
            let mut mark = self.mark;
            // Iterate the list until we hit a null ptr
            while let Some(checked_mark) = ptr::NonNull::new(mark) {
                next = checked_mark.as_ref().next;
                let size = checked_mark.as_ref().size;
                deallocate_bytes(checked_mark.cast(), size);
                mark = next;
            }
        }
    }
}
<|endoftext|>


<commit_before>use criterion::{criterion_group, criterion_main, Criterion};
use nibble_vec::NibbleVec;

fn even_8to5() -> NibbleVec {
    NibbleVec::from_byte_vec(vec![8 << 4 | 7, 6 << 4 | 5])
}

fn odd_11to9() -> NibbleVec {
    let mut result = NibbleVec::from_byte_vec(vec![11 << 4 | 10]);
    result.push(9);
    result
}

fn split_test(nibble_vec: &NibbleVec, idx: usize) {
    let mut init = nibble_vec.clone();
    let _tail = init.split(idx);
}

fn nib_split_even(b: &mut Criterion) {
    let even_length = even_8to5();
    b.bench_function("make nib vec", |b| b.iter(|| {
        split_test(&even_length, 1);
        split_test(&even_length, 2);
    }));
}

fn nib_make_split(b: &mut Criterion) {
    b.bench_function("nib_make_split", |b| {
        b.iter(|| {
            let odd_length = odd_11to9();
            split_test(&odd_length, 0);
            split_test(&odd_length, 1);
        })
    });
}

fn nib_get(b: &mut Criterion) {
    b.bench_function("nib_make_split", |b| {
        let v = vec![243, 2, 3, 251, 5, 6, 7, 8, 255];
        let nv = NibbleVec::from(v.clone());
        b.iter(|| {
            for (i, _) in v.iter().enumerate() {
                nv.get(i);
            }
        })
    });
}

fn join_test(vec1: &NibbleVec, vec2: &NibbleVec) {
    let _joined = vec1.clone().join(vec2);
}

fn nib_join_test(b: &mut Criterion) {
    b.bench_function("trie remove", |b| {
        b.iter(|| {
            let v1 = even_8to5();
            let v2 = odd_11to9();
            join_test(&v1, &v2);
            join_test(&v1, &v1);
        });
    });
}

criterion_group!(benches, nib_split_even, nib_make_split, nib_join_test, nib_get);
criterion_main!(benches);
<commit_msg>update smallvec bench<commit_after>use criterion::{criterion_group, criterion_main, Criterion};
use nibble_vec::NibbleVec;

fn even_8to5() -> NibbleVec {
    NibbleVec::from_byte_vec(vec![8 << 4 | 7, 6 << 4 | 5])
}

fn odd_11to9() -> NibbleVec {
    let mut result = NibbleVec::from_byte_vec(vec![11 << 4 | 10]);
    result.push(9);
    result
}

fn split_test(nibble_vec: &NibbleVec, idx: usize) {
    let mut init = nibble_vec.clone();
    let _tail = init.split(idx);
}

fn nib_split_even(b: &mut Criterion) {
    let even_length = even_8to5();
    b.bench_function("split even not including building the vec", |b| b.iter(|| {
        split_test(&even_length, 1);
        split_test(&even_length, 2);
    }));
}

fn nib_make_split(b: &mut Criterion) {
    b.bench_function("nib build nibvec split odd len", |b| {
        b.iter(|| {
            let odd_length = odd_11to9();
            split_test(&odd_length, 0);
            split_test(&odd_length, 1);
        })
    });
}

fn nib_get(b: &mut Criterion) {
    b.bench_function("nib get on vec of 9 elements", |b| {
        let v = vec![243, 2, 3, 251, 5, 6, 7, 8, 255];
        let nv = NibbleVec::from(v.clone());
        b.iter(|| {
            for (i, _) in v.iter().enumerate() {
                nv.get(i);
            }
        })
    });
}

fn join_test(vec1: &NibbleVec, vec2: &NibbleVec) {
    let _joined = vec1.clone().join(vec2);
}

fn nib_join_test(b: &mut Criterion) {
    b.bench_function("join even nibvec to odd nib", |b| {
        b.iter(|| {
            let v1 = even_8to5();
            let v2 = odd_11to9();
            join_test(&v1, &v2);
            join_test(&v1, &v1);
        });
    });
}

criterion_group!(benches, nib_split_even, nib_make_split, nib_join_test, nib_get);
criterion_main!(benches);
<|endoftext|>