<commit_before>use eventual::Async;
use protobuf::{self, Message, RepeatedField};
use std::borrow::Cow;
use std::sync::{mpsc, Mutex, Arc};
use std::collections::HashMap;

use mercury::{MercuryRequest, MercuryMethod};
use messaging::{SpircMessage, MercuryResponseSender, UpdateMessageSender};
use player::{Player, PlayerState};
use mixer::Mixer;
use session::Session;
use util;
use util::SpotifyId;
use version;

use protocol;
pub use protocol::spirc::{PlayStatus, MessageType};

#[derive(Clone)]
pub struct SpircManager(Arc<Mutex<SpircInternal>>);

struct SpircInternal {
    player: Player,
    session: Session,
    mixer: Box<Mixer + Send>,

    seq_nr: u32,

    name: String,
    ident: String,
    device_type: u8,
    can_play: bool,

    repeat: bool,
    shuffle: bool,

    is_active: bool,
    became_active_at: i64,

    last_command_ident: String,
    last_command_msgid: u32,

    tracks: Vec<SpotifyId>,
    index: u32,

    devices: HashMap<String, String>,
}

#[derive(Clone)]
pub struct State {
    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,
}

impl SpircManager {
    pub fn new(session: Session, player: Player, mixer: Box<Mixer + Send>) -> SpircManager {
        let ident = session.device_id().to_owned();
        let name = session.config().device_name.clone();

        SpircManager(Arc::new(Mutex::new(SpircInternal {
            player: player,
            session: session,
            mixer: mixer,

            seq_nr: 0,

            name: name,
            ident: ident,
            device_type: 5,
            can_play: true,

            repeat: false,
            shuffle: false,

            is_active: false,
            became_active_at: 0,

            last_command_ident: String::new(),
            last_command_msgid: 0,

            tracks: Vec::new(),
            index: 0,

            devices: HashMap::new(),
        })))
    }

    pub fn run(&self) {
        let rx = {
            let mut internal = self.0.lock().unwrap();
            let (tx, rx) = mpsc::channel::<SpircMessage>();

            let mercury_response_sender = MercuryResponseSender::create(tx.clone());

            internal.session.mercury_sub(internal.uri(), mercury_response_sender);

            let update_message_sender = UpdateMessageSender::create(tx.clone());

            internal.mixer.init(update_message_sender);

            internal.notify(true, None);

            // Use a weak pointer to avoid creating an Rc cycle between the player and the
            // SpircManager
            let _self = Arc::downgrade(&self.0);
            internal.player.add_observer(Box::new(move |state| {
                if let Some(_self) = _self.upgrade() {
                    let mut internal = _self.lock().unwrap();
                    internal.on_update(state);
                }
            }));

            rx
        };

        for msg in rx {
            match msg {
                SpircMessage::MercuryMsg(pkt) => {
                    let data = pkt.payload.first().unwrap();
                    let frame = protobuf::parse_from_bytes::<protocol::spirc::Frame>(data).unwrap();

                    debug!("{:?} {:?} {} {} {}",
                            frame.get_typ(),
                            frame.get_device_state().get_name(),
                            frame.get_ident(),
                            frame.get_seq_nr(),
                            frame.get_state_update_id());

                    self.0.lock().unwrap().handle(frame);
                }
                SpircMessage::UpdateMsg(_) => {
                    self.0.lock().unwrap().notify(false, None);
                }
            }
        }
    }

    pub fn devices(&self) -> HashMap<String, String> {
        self.0.lock().unwrap().devices.clone()
    }

    pub fn send_play(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePlay)
            .recipient(recipient)
            .send();
    }

    pub fn send_pause(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePause)
            .recipient(recipient)
            .send();
    }

    pub fn send_prev(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePrev)
            .recipient(recipient)
            .send();
    }

    pub fn send_next(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeNext)
            .recipient(recipient)
            .send();
    }

    pub fn send_replace_tracks<I: Iterator<Item = SpotifyId>>(&mut self,
                                                              recipient: &str,
                                                              track_ids: I) {
        let state = track_ids_to_state(track_ids);
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeReplace)
            .recipient(recipient)
            .state(state)
            .send();
    }

    pub fn send_load_tracks<I: Iterator<Item = SpotifyId>>(&mut self,
                                                           recipient: &str,
                                                           track_ids: I) {
        let state = track_ids_to_state(track_ids);
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeLoad)
            .recipient(recipient)
            .state(state)
            .send();
    }

    pub fn send_goodbye(&self) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeGoodbye)
            .send();
    }

    pub fn get_queue(&self) -> Vec<SpotifyId> {
        self.0.lock().unwrap().tracks.clone()
    }
}

impl SpircInternal {
    fn on_update(&mut self, player_state: &PlayerState) {
        let end_of_track = player_state.end_of_track();
        if end_of_track {
            self.index = (self.index + 1) % self.tracks.len() as u32;
            let track = self.tracks[self.index as usize];
            self.player.load(track, true, 0);
        } else {
            self.notify(false, None);
        }
    }

    fn handle(&mut self, frame: protocol::spirc::Frame) {
        if frame.get_ident() == self.ident ||
           (frame.get_recipient().len() > 0 && !frame.get_recipient().contains(&self.ident)) {
            return;
        }

        if frame.get_recipient().len() > 0 {
            self.last_command_ident = frame.get_ident().to_owned();
            self.last_command_msgid = frame.get_seq_nr();
        }

        if frame.has_ident() && !frame.has_goodbye() && frame.has_device_state() {
            self.devices.insert(frame.get_ident().into(),
                                frame.get_device_state().get_name().into());
        }

        match frame.get_typ() {
            MessageType::kMessageTypeHello => {
                self.notify(false, Some(frame.get_ident()));
            }
            MessageType::kMessageTypeLoad => {
                if !self.is_active {
                    self.is_active = true;
                    self.became_active_at = util::now_ms();
                }

                self.reload_tracks(&frame);
                if self.tracks.len() > 0 {
                    let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
                    let track = self.tracks[self.index as usize];
                    let position = frame.get_state().get_position_ms();
                    self.player.load(track, play, position);
                } else {
                    self.notify(false, Some(frame.get_ident()));
                }
            }
            MessageType::kMessageTypePlay => {
                self.player.play();
            }
            MessageType::kMessageTypePause => {
                self.player.pause();
            }
            MessageType::kMessageTypeNext => {
                self.index = (self.index + 1) % self.tracks.len() as u32;
                let track = self.tracks[self.index as usize];
                self.player.load(track, true, 0);
            }
            MessageType::kMessageTypePrev => {
                self.index = (self.index - 1) % self.tracks.len() as u32;
                let track = self.tracks[self.index as usize];
                self.player.load(track, true, 0);
            }
            MessageType::kMessageTypeSeek => {
                self.player.seek(frame.get_position());
            }
            MessageType::kMessageTypeReplace => {
                self.reload_tracks(&frame);
            }
            MessageType::kMessageTypeNotify => {
                if self.is_active && frame.get_device_state().get_is_active() {
                    self.is_active = false;
                    self.player.stop();
                }
            }
            MessageType::kMessageTypeVolume => {
                self.mixer.set_volume(frame.get_volume() as u16);
            }
            MessageType::kMessageTypeGoodbye => {
                if frame.has_ident() {
                    self.devices.remove(frame.get_ident());
                }
            }
            _ => (),
        }
    }

    fn reload_tracks(&mut self, ref frame: &protocol::spirc::Frame) {
        self.index = frame.get_state().get_playing_track_index();
        self.tracks = frame.get_state()
                           .get_track()
                           .iter()
                           .filter(|track| track.has_gid())
                           .map(|track| SpotifyId::from_raw(track.get_gid()))
                           .collect();
    }

    fn notify(&mut self, hello: bool, recipient: Option<&str>) {
        let mut cs = CommandSender::new(self,
                                        if hello {
                                            MessageType::kMessageTypeHello
                                        } else {
                                            MessageType::kMessageTypeNotify
                                        });
        if let Some(s) = recipient {
            cs = cs.recipient(&s);
        }
        cs.send();
    }

    fn spirc_state(&self, state: &State) -> protocol::spirc::State {
        protobuf_init!(protocol::spirc::State::new(), {
            status: state.status,
            position_ms: state.position_ms,
            position_measured_at: state.position_measured_at as u64,

            playing_track_index: self.index,
            track: self.tracks.iter().map(|track| {
                protobuf_init!(protocol::spirc::TrackRef::new(), {
                    gid: track.to_raw().to_vec()
                })
            }).collect(),

            shuffle: self.shuffle,
            repeat: self.repeat,

            playing_from_fallback: true,

            last_command_ident: self.last_command_ident.clone(),
            last_command_msgid: self.last_command_msgid
        })
    }

    fn device_state(&self, state: &State) -> protocol::spirc::DeviceState {
        protobuf_init!(protocol::spirc::DeviceState::new(), {
            sw_version: version::version_string(),
            is_active: self.is_active,
            can_play: self.can_play,
            volume: state.volume as u32,
            name: self.name.clone(),
            error_code: 0,
            became_active_at: if self.is_active { self.became_active_at as i64 } else { 0 },
            capabilities => [
                @{
                    typ: protocol::spirc::CapabilityType::kCanBePlayer,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kDeviceType,
                    intValue => [ self.device_type as i64 ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kGaiaEqConnectId,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportsLogout,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kIsObservable,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kVolumeSteps,
                    intValue => [64]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedContexts,
                    stringValue => [
                        "album",
                        "playlist",
                        "search",
                        "inbox",
                        "toplist",
                        "starred",
                        "publishedstarred",
                        "track",
                    ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedTypes,
                    stringValue => [
                        "audio/local",
                        "audio/track",
                        "local",
                        "track",
                    ]
                }
            ],
        })
    }

    fn uri(&self) -> String {
        format!("hm://remote/user/{}", self.session.username())
    }
}

struct CommandSender<'a> {
    spirc_internal: &'a mut SpircInternal,
    cmd: MessageType,
    recipient: Option<&'a str>,
    state: Option<protocol::spirc::State>,
}

impl<'a> CommandSender<'a> {
    fn new(spirc_internal: &'a mut SpircInternal, cmd: MessageType) -> CommandSender {
        CommandSender {
            spirc_internal: spirc_internal,
            cmd: cmd,
            recipient: None,
            state: None,
        }
    }

    fn recipient(mut self, r: &'a str) -> CommandSender {
        self.recipient = Some(r);
        self
    }

    fn state(mut self, s: protocol::spirc::State) -> CommandSender<'a> {
        self.state = Some(s);
        self
    }

    fn send(self) {
        //TODO: get data
        let state = Cow::Owned(State {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: util::now_ms(),
            volume: 0,
            track: None,
            end_of_track: false,
        });

        let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), {
            version: 1,
            ident: self.spirc_internal.ident.clone(),
            protocol_version: "2.0.0",
            seq_nr: { self.spirc_internal.seq_nr += 1; self.spirc_internal.seq_nr  },
            typ: self.cmd,
            recipient: RepeatedField::from_vec(
                self.recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![])
                ),
            device_state: self.spirc_internal.device_state(&state),
            state_update_id: state.update_time
        });

        if self.spirc_internal.is_active {
            pkt.set_state(self.spirc_internal.spirc_state(&state));
        }

        self.spirc_internal
            .session
            .mercury(MercuryRequest {
                method: MercuryMethod::SEND,
                uri: self.spirc_internal.uri(),
                content_type: None,
                payload: vec![pkt.write_to_bytes().unwrap()],
            })
            .fire();
    }
}

fn track_ids_to_state<I: Iterator<Item = SpotifyId>>(track_ids: I) -> protocol::spirc::State {
    let tracks: Vec<protocol::spirc::TrackRef> =
        track_ids.map(|i| {
                     protobuf_init!(protocol::spirc::TrackRef::new(), { gid: i.to_raw().to_vec()})
                 })
                 .collect();
    protobuf_init!(protocol::spirc::State::new(), {
                    track: RepeatedField::from_vec(tracks)
                })
}
<commit_msg>SpircManager: Update state from player and mixer before sending info<commit_after>use eventual::Async;
use protobuf::{self, Message, RepeatedField};
use std::sync::{mpsc, Mutex, Arc};
use std::collections::HashMap;

use mercury::{MercuryRequest, MercuryMethod};
use messaging::{SpircMessage, MercuryResponseSender, UpdateMessageSender};
use player::{Player, PlayerState};
use mixer::Mixer;
use session::Session;
use util;
use util::SpotifyId;
use version;

use protocol;
pub use protocol::spirc::{PlayStatus, MessageType};

#[derive(Clone)]
pub struct SpircManager(Arc<Mutex<SpircInternal>>);

struct SpircInternal {
    player: Player,
    session: Session,
    mixer: Box<Mixer + Send>,

    seq_nr: u32,

    name: String,
    ident: String,
    device_type: u8,
    can_play: bool,

    repeat: bool,
    shuffle: bool,

    is_active: bool,
    became_active_at: i64,

    last_command_ident: String,
    last_command_msgid: u32,

    tracks: Vec<SpotifyId>,
    index: u32,

    devices: HashMap<String, String>,
}

#[derive(Clone)]
pub struct State {
    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,
}

impl State {
    pub fn new() -> State {
        let state = State {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: 0,
            volume: 0,
            track: None,
            end_of_track: false,
        };
        state.update_time()
    }

    pub fn update_from_player(mut self, player: &Player) -> State {
        let player_state = player.state();
        let (position_ms, position_measured_at) = player_state.position();
        self.status = player_state.status();
        self.position_ms = position_ms;
        self.position_measured_at = position_measured_at;
        self.track = player_state.track;
        self.end_of_track = player_state.end_of_track();
        self.update_time()
    }

    pub fn update_from_mixer(mut self, mixer: &Box<Mixer + Send>) -> State {
        self.volume = mixer.volume();
        self.update_time()
    }

    fn update_time(mut self) -> State {
        self.update_time = util::now_ms();
        self
    }
}

impl SpircManager {
    pub fn new(session: Session, player: Player, mixer: Box<Mixer + Send>) -> SpircManager {
        let ident = session.device_id().to_owned();
        let name = session.config().device_name.clone();

        SpircManager(Arc::new(Mutex::new(SpircInternal {
            player: player,
            session: session,
            mixer: mixer,

            seq_nr: 0,

            name: name,
            ident: ident,
            device_type: 5,
            can_play: true,

            repeat: false,
            shuffle: false,

            is_active: false,
            became_active_at: 0,

            last_command_ident: String::new(),
            last_command_msgid: 0,

            tracks: Vec::new(),
            index: 0,

            devices: HashMap::new(),
        })))
    }

    pub fn run(&self) {
        let rx = {
            let mut internal = self.0.lock().unwrap();
            let (tx, rx) = mpsc::channel::<SpircMessage>();

            let mercury_response_sender = MercuryResponseSender::create(tx.clone());

            internal.session.mercury_sub(internal.uri(), mercury_response_sender);

            let update_message_sender = UpdateMessageSender::create(tx.clone());

            internal.mixer.init(update_message_sender);

            internal.notify(true, None);

            // Use a weak pointer to avoid creating an Rc cycle between the player and the
            // SpircManager
            let _self = Arc::downgrade(&self.0);
            internal.player.add_observer(Box::new(move |state| {
                if let Some(_self) = _self.upgrade() {
                    let mut internal = _self.lock().unwrap();
                    internal.on_update(state);
                }
            }));

            rx
        };

        for msg in rx {
            match msg {
                SpircMessage::MercuryMsg(pkt) => {
                    let data = pkt.payload.first().unwrap();
                    let frame = protobuf::parse_from_bytes::<protocol::spirc::Frame>(data).unwrap();

                    debug!("{:?} {:?} {} {} {}",
                            frame.get_typ(),
                            frame.get_device_state().get_name(),
                            frame.get_ident(),
                            frame.get_seq_nr(),
                            frame.get_state_update_id());

                    self.0.lock().unwrap().handle(frame);
                }
                SpircMessage::UpdateMsg(_) => {
                    self.0.lock().unwrap().notify(false, None);
                }
            }
        }
    }

    pub fn devices(&self) -> HashMap<String, String> {
        self.0.lock().unwrap().devices.clone()
    }

    pub fn send_play(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePlay)
            .recipient(recipient)
            .send();
    }

    pub fn send_pause(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePause)
            .recipient(recipient)
            .send();
    }

    pub fn send_prev(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypePrev)
            .recipient(recipient)
            .send();
    }

    pub fn send_next(&self, recipient: &str) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeNext)
            .recipient(recipient)
            .send();
    }

    pub fn send_replace_tracks<I: Iterator<Item = SpotifyId>>(&mut self,
                                                              recipient: &str,
                                                              track_ids: I) {
        let state = track_ids_to_state(track_ids);
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeReplace)
            .recipient(recipient)
            .state(state)
            .send();
    }

    pub fn send_load_tracks<I: Iterator<Item = SpotifyId>>(&mut self,
                                                           recipient: &str,
                                                           track_ids: I) {
        let state = track_ids_to_state(track_ids);
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeLoad)
            .recipient(recipient)
            .state(state)
            .send();
    }

    pub fn send_goodbye(&self) {
        let mut internal = self.0.lock().unwrap();
        CommandSender::new(&mut *internal, MessageType::kMessageTypeGoodbye)
            .send();
    }

    pub fn get_queue(&self) -> Vec<SpotifyId> {
        self.0.lock().unwrap().tracks.clone()
    }
}

impl SpircInternal {
    fn on_update(&mut self, player_state: &PlayerState) {
        let end_of_track = player_state.end_of_track();
        if end_of_track {
            self.index = (self.index + 1) % self.tracks.len() as u32;
            let track = self.tracks[self.index as usize];
            self.player.load(track, true, 0);
        } else {
            self.notify(false, None);
        }
    }

    fn handle(&mut self, frame: protocol::spirc::Frame) {
        if frame.get_ident() == self.ident ||
           (frame.get_recipient().len() > 0 && !frame.get_recipient().contains(&self.ident)) {
            return;
        }

        if frame.get_recipient().len() > 0 {
            self.last_command_ident = frame.get_ident().to_owned();
            self.last_command_msgid = frame.get_seq_nr();
        }

        if frame.has_ident() && !frame.has_goodbye() && frame.has_device_state() {
            self.devices.insert(frame.get_ident().into(),
                                frame.get_device_state().get_name().into());
        }

        match frame.get_typ() {
            MessageType::kMessageTypeHello => {
                self.notify(false, Some(frame.get_ident()));
            }
            MessageType::kMessageTypeLoad => {
                if !self.is_active {
                    self.is_active = true;
                    self.became_active_at = util::now_ms();
                }

                self.reload_tracks(&frame);
                if self.tracks.len() > 0 {
                    let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
                    let track = self.tracks[self.index as usize];
                    let position = frame.get_state().get_position_ms();
                    self.player.load(track, play, position);
                } else {
                    self.notify(false, Some(frame.get_ident()));
                }
            }
            MessageType::kMessageTypePlay => {
                self.player.play();
            }
            MessageType::kMessageTypePause => {
                self.player.pause();
            }
            MessageType::kMessageTypeNext => {
                self.index = (self.index + 1) % self.tracks.len() as u32;
                let track = self.tracks[self.index as usize];
                self.player.load(track, true, 0);
            }
            MessageType::kMessageTypePrev => {
                self.index = (self.index - 1) % self.tracks.len() as u32;
                let track = self.tracks[self.index as usize];
                self.player.load(track, true, 0);
            }
            MessageType::kMessageTypeSeek => {
                self.player.seek(frame.get_position());
            }
            MessageType::kMessageTypeReplace => {
                self.reload_tracks(&frame);
            }
            MessageType::kMessageTypeNotify => {
                if self.is_active && frame.get_device_state().get_is_active() {
                    self.is_active = false;
                    self.player.stop();
                }
            }
            MessageType::kMessageTypeVolume => {
                self.mixer.set_volume(frame.get_volume() as u16);
            }
            MessageType::kMessageTypeGoodbye => {
                if frame.has_ident() {
                    self.devices.remove(frame.get_ident());
                }
            }
            _ => (),
        }
    }

    fn reload_tracks(&mut self, ref frame: &protocol::spirc::Frame) {
        self.index = frame.get_state().get_playing_track_index();
        self.tracks = frame.get_state()
                           .get_track()
                           .iter()
                           .filter(|track| track.has_gid())
                           .map(|track| SpotifyId::from_raw(track.get_gid()))
                           .collect();
    }

    fn notify(&mut self, hello: bool, recipient: Option<&str>) {
        let mut cs = CommandSender::new(self,
                                        if hello {
                                            MessageType::kMessageTypeHello
                                        } else {
                                            MessageType::kMessageTypeNotify
                                        });
        if let Some(s) = recipient {
            cs = cs.recipient(&s);
        }
        cs.send();
    }

    fn spirc_state(&self, state: &State) -> protocol::spirc::State {
        protobuf_init!(protocol::spirc::State::new(), {
            status: state.status,
            position_ms: state.position_ms,
            position_measured_at: state.position_measured_at as u64,

            playing_track_index: self.index,
            track: self.tracks.iter().map(|track| {
                protobuf_init!(protocol::spirc::TrackRef::new(), {
                    gid: track.to_raw().to_vec()
                })
            }).collect(),

            shuffle: self.shuffle,
            repeat: self.repeat,

            playing_from_fallback: true,

            last_command_ident: self.last_command_ident.clone(),
            last_command_msgid: self.last_command_msgid
        })
    }

    fn device_state(&self, state: &State) -> protocol::spirc::DeviceState {
        protobuf_init!(protocol::spirc::DeviceState::new(), {
            sw_version: version::version_string(),
            is_active: self.is_active,
            can_play: self.can_play,
            volume: state.volume as u32,
            name: self.name.clone(),
            error_code: 0,
            became_active_at: if self.is_active { self.became_active_at as i64 } else { 0 },
            capabilities => [
                @{
                    typ: protocol::spirc::CapabilityType::kCanBePlayer,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kDeviceType,
                    intValue => [ self.device_type as i64 ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kGaiaEqConnectId,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportsLogout,
                    intValue => [0]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kIsObservable,
                    intValue => [1]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kVolumeSteps,
                    intValue => [64]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedContexts,
                    stringValue => [
                        "album",
                        "playlist",
                        "search",
                        "inbox",
                        "toplist",
                        "starred",
                        "publishedstarred",
                        "track",
                    ]
                },
                @{
                    typ: protocol::spirc::CapabilityType::kSupportedTypes,
                    stringValue => [
                        "audio/local",
                        "audio/track",
                        "local",
                        "track",
                    ]
                }
            ],
        })
    }

    fn uri(&self) -> String {
        format!("hm://remote/user/{}", self.session.username())
    }
}

struct CommandSender<'a> {
    spirc_internal: &'a mut SpircInternal,
    cmd: MessageType,
    recipient: Option<&'a str>,
    state: Option<protocol::spirc::State>,
}

impl<'a> CommandSender<'a> {
    fn new(spirc_internal: &'a mut SpircInternal, cmd: MessageType) -> CommandSender {
        CommandSender {
            spirc_internal: spirc_internal,
            cmd: cmd,
            recipient: None,
            state: None,
        }
    }

    fn recipient(mut self, r: &'a str) -> CommandSender {
        self.recipient = Some(r);
        self
    }

    fn state(mut self, s: protocol::spirc::State) -> CommandSender<'a> {
        self.state = Some(s);
        self
    }

    fn send(self) {
        let state = State::new()
                         .update_from_player(&self.spirc_internal.player)
                         .update_from_mixer(&self.spirc_internal.mixer);

        let mut pkt = protobuf_init!(protocol::spirc::Frame::new(), {
            version: 1,
            ident: self.spirc_internal.ident.clone(),
            protocol_version: "2.0.0",
            seq_nr: { self.spirc_internal.seq_nr += 1; self.spirc_internal.seq_nr  },
            typ: self.cmd,
            recipient: RepeatedField::from_vec(
                self.recipient.map(|r| vec![r.to_owned()] ).unwrap_or(vec![])
                ),
            device_state: self.spirc_internal.device_state(&state),
            state_update_id: state.update_time
        });

        if self.spirc_internal.is_active {
            pkt.set_state(self.spirc_internal.spirc_state(&state));
        }

        self.spirc_internal
            .session
            .mercury(MercuryRequest {
                method: MercuryMethod::SEND,
                uri: self.spirc_internal.uri(),
                content_type: None,
                payload: vec![pkt.write_to_bytes().unwrap()],
            })
            .fire();
    }
}

fn track_ids_to_state<I: Iterator<Item = SpotifyId>>(track_ids: I) -> protocol::spirc::State {
    let tracks: Vec<protocol::spirc::TrackRef> =
        track_ids.map(|i| {
                     protobuf_init!(protocol::spirc::TrackRef::new(), { gid: i.to_raw().to_vec()})
                 })
                 .collect();
    protobuf_init!(protocol::spirc::State::new(), {
                    track: RepeatedField::from_vec(tracks)
                })
}
<|endoftext|>


<commit_before>use crate::{AsFmtSerializer, Discard, Drain, Logger, Never, OwnedKVList, Record, KV};

// Separate module to test lack of imports
mod no_imports {
    use crate::{Discard, Logger};
    /// ensure o! macro expands without error inside a module
    #[test]
    fn test_o_macro_expansion() {
        let _ = Logger::root(Discard, o!("a" => "aa"));
    }
    /// ensure o! macro expands without error inside a module
    #[test]
    fn test_slog_o_macro_expansion() {
        let _ = Logger::root(Discard, slog_o!("a" => "aa"));
    }
}

#[cfg(feature = "std")]
mod std_only {
    use super::super::*;
    use std;

    #[derive(Clone)]
    struct CheckError;

    impl Drain for CheckError {
        type Ok = ();
        type Err = Never;
        fn log(
            &self,
            record: &Record,
            values: &OwnedKVList,
        ) -> std::result::Result<Self::Ok, Self::Err> {
            struct ErrorSerializer(String);

            impl Serializer for ErrorSerializer {
                fn emit_arguments(
                    &mut self,
                    key: Key,
                    val: &fmt::Arguments,
                ) -> Result {
                    use core::fmt::Write;

                    match key {
                        "error" => self.0.write_fmt(*val).unwrap(),
                        _ => {
                            self.0.write_str(&key).unwrap();
                            self.0.write_str(": ").unwrap();
                            self.0.write_fmt(*val).unwrap();
                            self.0.write_str("; ").unwrap();
                        }
                    }
                    Ok(())
                }
            }

            let mut serializer = ErrorSerializer(String::new());
            values.serialize(record, &mut serializer).unwrap();
            assert_eq!(serializer.0, format!("{}", record.msg()));
            Ok(())
        }
    }

    #[derive(Debug)]
    struct TestError<E = std::string::ParseError>(&'static str, Option<E>);

    impl TestError {
        fn new(message: &'static str) -> Self {
            TestError(message, None)
        }
    }

    impl<E> fmt::Display for TestError<E> {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.0)
        }
    }

    impl<E: std::error::Error + 'static> std::error::Error for TestError<E> {
        #[allow(deprecated)]
        fn cause(&self) -> Option<&std::error::Error> {
            self.1.as_ref().map(|error| error as _)
        }

        #[allow(deprecated)]
        fn description(&self) -> &str {
            "test error"
        }
    }

    #[test]
    fn logger_fmt_debug_sanity() {
        let root = Logger::root(Discard, o!("a" => "aa"));
        let log = root.new(o!("b" => "bb", "c" => "cc"));

        assert_eq!(format!("{:?}", log), "Logger(c, b, a)");
    }

    #[test]
    fn multichain() {
        #[derive(Clone)]
        struct CheckOwned;

        impl Drain for CheckOwned {
            type Ok = ();
            type Err = Never;
            fn log(
                &self,
                record: &Record<'_>,
                values: &OwnedKVList,
            ) -> std::result::Result<Self::Ok, Self::Err> {
                assert_eq!(
                    format!("{}", record.msg()),
                    format!("{:?}", values)
                );
                Ok(())
            }
        }

        let root = Logger::root(CheckOwned, o!("a" => "aa"));
        let log = root.new(o!("b1" => "bb", "b2" => "bb"));

        info!(log, "(b2, b1, a)");

        let log = Logger::root(log, o!("c" => "cc"));
        info!(log, "(c, b2, b1, a)");
        let log = Logger::root(log, o!("d1" => "dd", "d2" => "dd"));
        info!(log, "(d2, d1, c, b2, b1, a)");
    }

    #[test]
    fn error_fmt_no_source() {
        let logger =
            Logger::root(CheckError, o!("error" => #TestError::new("foo")));
        info!(logger, "foo");
        slog_info!(logger, "foo");
    }

    #[test]
    fn error_fmt_no_source_not_last() {
        let logger = Logger::root(
            CheckError,
            o!("error" => #TestError::new("foo"), "not-error" => "not-error"),
        );
        info!(logger, "not-error: not-error; foo");
        slog_info!(logger, "not-error: not-error; foo");
    }

    #[test]
    fn error_fmt_no_source_last() {
        let logger = Logger::root(
            CheckError,
            o!("not-error" => "not-error", "error" => #TestError::new("foo")),
        );
        info!(logger, "foonot-error: not-error; ");
        slog_info!(logger, "foonot-error: not-error; ");
    }
    #[test]
    fn error_fmt_single_source() {
        let logger = Logger::root(
            CheckError,
            o!("error" => #TestError("foo", Some(TestError::new("bar")))),
        );
        info!(logger, "foo: bar");
    }

    #[test]
    fn error_fmt_two_sources() {
        let logger = Logger::root(
            CheckError,
            o!("error" => #TestError("foo", Some(TestError("bar", Some(TestError::new("baz")))))),
        );
        info!(logger, "foo: bar: baz");
    }

    #[test]
    fn ioerror_impls_value() {
        let logger = Logger::root(Discard, o!());
        info!(logger, "not found"; "error" => std::io::Error::from(std::io::ErrorKind::NotFound));
        // compiles?
        info!(logger, "not found"; "error" => #std::io::Error::from(std::io::ErrorKind::NotFound));
    }
}

// Allow unused_must_use for macro testing.
#[allow(unused_must_use)]
#[test]
fn expressions() {
    use super::{Record, Result, Serializer, KV};

    struct Foo;

    impl Foo {
        fn bar(&self) -> u32 {
            1
        }
    }

    struct X {
        foo: Foo,
    }

    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    let foo = Foo;
    let r = X { foo: foo };

    warn!(log, "logging message");
    slog_warn!(log, "logging message");

    info!(log, #"with tag", "logging message");
    slog_info!(log, #"with tag", "logging message");

    warn!(log, "logging message"; "a" => "b");
    slog_warn!(log, "logging message"; "a" => "b");

    warn!(log, "logging message bar={}", r.foo.bar());
    slog_warn!(log, "logging message bar={}", r.foo.bar());

    warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar()
    );
    slog_warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar()
    );

    // trailing comma check
    warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar(),
    );
    slog_warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar(),
    );

    warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);

    // trailing comma check
    warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);

    warn!(log,
          "logging message bar={}", r.foo.bar(); "x" => 1, "y" => r.foo.bar());
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => 1, "y" => r.foo.bar());

    warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());

    warn!(log, "logging message bar={}", r.foo.bar();
          "x" => r.foo.bar(), "y" => r.foo.bar());
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => r.foo.bar(), "y" => r.foo.bar());

    // trailing comma check
    warn!(log,
          "logging message bar={}", r.foo.bar();
          "x" => r.foo.bar(), "y" => r.foo.bar(),);
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => r.foo.bar(), "y" => r.foo.bar(),);

    {
        #[derive(Clone)]
        struct K;

        impl KV for K {
            fn serialize(
                &self,
                _record: &Record<'_>,
                _serializer: &mut dyn Serializer,
            ) -> Result {
                Ok(())
            }
        }

        let x = K;

        let _log = log.new(o!(x.clone()));
        let _log = log.new(o!("foo" => "bar", x.clone()));
        let _log = log.new(o!("foo" => "bar", x.clone(), x.clone()));
        let _log = log
            .new(slog_o!("foo" => "bar", x.clone(), x.clone(), "aaa" => "bbb"));

        info!(log, "message"; "foo" => "bar", &x, &x, "aaa" => "bbb");
    }

    info!(
        log,
        "message {}",
          { 3 + 3; 2};
          "foo" => "bar",
          "foo" => { 3 + 3; 2},
          "aaa" => "bbb");
}

#[cfg(integer128)]
#[test]
fn integer_128_types() {
    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    info!(log, "i128 = {}", 42i128; "foo" => 7i128);
    info!(log, "u128 = {}", 42u128; "foo" => 7u128);
}

#[test]
fn expressions_fmt() {
    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    let f = "f";
    let d = (1, 2);

    info!(log, "message"; "f" => %f, "d" => ?d);
}

#[cfg(feature = "std")]
#[test]
fn display_and_alternate_display() {
    use core::cell::Cell;
    use core::fmt;

    struct Example;

    impl fmt::Display for Example {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            if f.alternate() {
                f.write_str("alternate")
            } else {
                f.write_str("normal")
            }
        }
    }

    #[derive(Clone, Default)]
    struct CheckExample;

    impl Drain for CheckExample {
        type Ok = ();
        type Err = Never;

        fn log(
            &self,
            record: &Record,
            values: &OwnedKVList,
        ) -> Result<(), Never> {
            let mut checked_n = false;
            let mut checked_a = false;
            {
                let mut serializer = AsFmtSerializer(|key, fmt_args| {
                    if key == "n" {
                        assert_eq!(format!("{}", fmt_args), "normal");
                        checked_n = true;
                    } else if key == "a" {
                        assert_eq!(format!("{}", fmt_args), "alternate");
                        checked_a = true;
                    } else {
                        panic!("Unexpected key: {}", key);
                    }
                    Ok(())
                });

                record.kv.serialize(record, &mut serializer).unwrap();
            }

            assert!(checked_n, "Expected the normal formatter to be used");
            assert!(checked_a, "Expected the alternate formatter to be used");

            Ok(())
        }
    }

    let log = Logger::root(CheckExample, o!());

    info!(log, ""; "n" => %Example, "a" => #%Example);
}

#[test]
fn makers() {
    use crate::*;
    let drain = Duplicate(
        Discard.filter(|r| r.level().is_at_least(Level::Info)),
        Discard.filter_level(Level::Warning),
    )
    .map(Fuse);
    let _log = Logger::root(
        Arc::new(drain),
        o!("version" => env!("CARGO_PKG_VERSION")),
    );
}

#[test]
fn simple_logger_erased() {
    use crate::*;
    fn takes_arced_drain(_l: Logger) {}

    let drain = Discard.filter_level(Level::Warning).map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));

    takes_arced_drain(log.to_erased());
}

#[test]
fn logger_to_erased() {
    use crate::*;

    fn takes_arced_drain(_l: Logger) {}

    let drain = Duplicate(
        Discard.filter(|r| r.level().is_at_least(Level::Info)),
        Discard.filter_level(Level::Warning),
    )
    .map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));

    takes_arced_drain(log.into_erased());
}

#[test]
fn logger_by_ref() {
    use crate::*;
    let drain = Discard.filter_level(Level::Warning).map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));
    let f = "f";
    let d = (1, 2);
    info!(&log, "message"; "f" => %f, "d" => ?d);
}

#[test]
fn test_never_type_clone() {
    // We just want to make sure that this compiles
    fn _do_not_run() {
        let x: Never = panic!("Can't actually construct a Never type here!");
        let y = x.clone();
    }
    // Always pass if we compiled
}

#[cfg(feature = "std")]
#[test]
fn can_hash_keys() {
    use std::collections::HashSet;
    use Key;
    let tab: HashSet<Key> = ["foo"].iter().map(|&k| k.into()).collect();
}
<commit_msg>Fix PR formatting (#237)<commit_after>use crate::{
    AsFmtSerializer, Discard, Drain, Logger, Never, OwnedKVList, Record, KV,
};

// Separate module to test lack of imports
mod no_imports {
    use crate::{Discard, Logger};
    /// ensure o! macro expands without error inside a module
    #[test]
    fn test_o_macro_expansion() {
        let _ = Logger::root(Discard, o!("a" => "aa"));
    }
    /// ensure o! macro expands without error inside a module
    #[test]
    fn test_slog_o_macro_expansion() {
        let _ = Logger::root(Discard, slog_o!("a" => "aa"));
    }
}

#[cfg(feature = "std")]
mod std_only {
    use super::super::*;
    use std;

    #[derive(Clone)]
    struct CheckError;

    impl Drain for CheckError {
        type Ok = ();
        type Err = Never;
        fn log(
            &self,
            record: &Record,
            values: &OwnedKVList,
        ) -> std::result::Result<Self::Ok, Self::Err> {
            struct ErrorSerializer(String);

            impl Serializer for ErrorSerializer {
                fn emit_arguments(
                    &mut self,
                    key: Key,
                    val: &fmt::Arguments,
                ) -> Result {
                    use core::fmt::Write;

                    match key {
                        "error" => self.0.write_fmt(*val).unwrap(),
                        _ => {
                            self.0.write_str(&key).unwrap();
                            self.0.write_str(": ").unwrap();
                            self.0.write_fmt(*val).unwrap();
                            self.0.write_str("; ").unwrap();
                        }
                    }
                    Ok(())
                }
            }

            let mut serializer = ErrorSerializer(String::new());
            values.serialize(record, &mut serializer).unwrap();
            assert_eq!(serializer.0, format!("{}", record.msg()));
            Ok(())
        }
    }

    #[derive(Debug)]
    struct TestError<E = std::string::ParseError>(&'static str, Option<E>);

    impl TestError {
        fn new(message: &'static str) -> Self {
            TestError(message, None)
        }
    }

    impl<E> fmt::Display for TestError<E> {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.0)
        }
    }

    impl<E: std::error::Error + 'static> std::error::Error for TestError<E> {
        #[allow(deprecated)]
        fn cause(&self) -> Option<&std::error::Error> {
            self.1.as_ref().map(|error| error as _)
        }

        #[allow(deprecated)]
        fn description(&self) -> &str {
            "test error"
        }
    }

    #[test]
    fn logger_fmt_debug_sanity() {
        let root = Logger::root(Discard, o!("a" => "aa"));
        let log = root.new(o!("b" => "bb", "c" => "cc"));

        assert_eq!(format!("{:?}", log), "Logger(c, b, a)");
    }

    #[test]
    fn multichain() {
        #[derive(Clone)]
        struct CheckOwned;

        impl Drain for CheckOwned {
            type Ok = ();
            type Err = Never;
            fn log(
                &self,
                record: &Record<'_>,
                values: &OwnedKVList,
            ) -> std::result::Result<Self::Ok, Self::Err> {
                assert_eq!(
                    format!("{}", record.msg()),
                    format!("{:?}", values)
                );
                Ok(())
            }
        }

        let root = Logger::root(CheckOwned, o!("a" => "aa"));
        let log = root.new(o!("b1" => "bb", "b2" => "bb"));

        info!(log, "(b2, b1, a)");

        let log = Logger::root(log, o!("c" => "cc"));
        info!(log, "(c, b2, b1, a)");
        let log = Logger::root(log, o!("d1" => "dd", "d2" => "dd"));
        info!(log, "(d2, d1, c, b2, b1, a)");
    }

    #[test]
    fn error_fmt_no_source() {
        let logger =
            Logger::root(CheckError, o!("error" => #TestError::new("foo")));
        info!(logger, "foo");
        slog_info!(logger, "foo");
    }

    #[test]
    fn error_fmt_no_source_not_last() {
        let logger = Logger::root(
            CheckError,
            o!("error" => #TestError::new("foo"), "not-error" => "not-error"),
        );
        info!(logger, "not-error: not-error; foo");
        slog_info!(logger, "not-error: not-error; foo");
    }

    #[test]
    fn error_fmt_no_source_last() {
        let logger = Logger::root(
            CheckError,
            o!("not-error" => "not-error", "error" => #TestError::new("foo")),
        );
        info!(logger, "foonot-error: not-error; ");
        slog_info!(logger, "foonot-error: not-error; ");
    }
    #[test]
    fn error_fmt_single_source() {
        let logger = Logger::root(
            CheckError,
            o!("error" => #TestError("foo", Some(TestError::new("bar")))),
        );
        info!(logger, "foo: bar");
    }

    #[test]
    fn error_fmt_two_sources() {
        let logger = Logger::root(
            CheckError,
            o!("error" => #TestError("foo", Some(TestError("bar", Some(TestError::new("baz")))))),
        );
        info!(logger, "foo: bar: baz");
    }

    #[test]
    fn ioerror_impls_value() {
        let logger = Logger::root(Discard, o!());
        info!(logger, "not found"; "error" => std::io::Error::from(std::io::ErrorKind::NotFound));
        // compiles?
        info!(logger, "not found"; "error" => #std::io::Error::from(std::io::ErrorKind::NotFound));
    }
}

// Allow unused_must_use for macro testing.
#[allow(unused_must_use)]
#[test]
fn expressions() {
    use super::{Record, Result, Serializer, KV};

    struct Foo;

    impl Foo {
        fn bar(&self) -> u32 {
            1
        }
    }

    struct X {
        foo: Foo,
    }

    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    let foo = Foo;
    let r = X { foo: foo };

    warn!(log, "logging message");
    slog_warn!(log, "logging message");

    info!(log, #"with tag", "logging message");
    slog_info!(log, #"with tag", "logging message");

    warn!(log, "logging message"; "a" => "b");
    slog_warn!(log, "logging message"; "a" => "b");

    warn!(log, "logging message bar={}", r.foo.bar());
    slog_warn!(log, "logging message bar={}", r.foo.bar());

    warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar()
    );
    slog_warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar()
    );

    // trailing comma check
    warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar(),
    );
    slog_warn!(
        log,
        "logging message bar={} foo={}",
        r.foo.bar(),
        r.foo.bar(),
    );

    warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1);

    // trailing comma check
    warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => 1,);

    warn!(log,
          "logging message bar={}", r.foo.bar(); "x" => 1, "y" => r.foo.bar());
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => 1, "y" => r.foo.bar());

    warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());
    slog_warn!(log, "logging message bar={}", r.foo.bar(); "x" => r.foo.bar());

    warn!(log, "logging message bar={}", r.foo.bar();
          "x" => r.foo.bar(), "y" => r.foo.bar());
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => r.foo.bar(), "y" => r.foo.bar());

    // trailing comma check
    warn!(log,
          "logging message bar={}", r.foo.bar();
          "x" => r.foo.bar(), "y" => r.foo.bar(),);
    slog_warn!(log,
               "logging message bar={}", r.foo.bar();
               "x" => r.foo.bar(), "y" => r.foo.bar(),);

    {
        #[derive(Clone)]
        struct K;

        impl KV for K {
            fn serialize(
                &self,
                _record: &Record<'_>,
                _serializer: &mut dyn Serializer,
            ) -> Result {
                Ok(())
            }
        }

        let x = K;

        let _log = log.new(o!(x.clone()));
        let _log = log.new(o!("foo" => "bar", x.clone()));
        let _log = log.new(o!("foo" => "bar", x.clone(), x.clone()));
        let _log = log
            .new(slog_o!("foo" => "bar", x.clone(), x.clone(), "aaa" => "bbb"));

        info!(log, "message"; "foo" => "bar", &x, &x, "aaa" => "bbb");
    }

    info!(
        log,
        "message {}",
          { 3 + 3; 2};
          "foo" => "bar",
          "foo" => { 3 + 3; 2},
          "aaa" => "bbb");
}

#[cfg(integer128)]
#[test]
fn integer_128_types() {
    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    info!(log, "i128 = {}", 42i128; "foo" => 7i128);
    info!(log, "u128 = {}", 42u128; "foo" => 7u128);
}

#[test]
fn expressions_fmt() {
    let log = Logger::root(Discard, o!("version" => env!("CARGO_PKG_VERSION")));

    let f = "f";
    let d = (1, 2);

    info!(log, "message"; "f" => %f, "d" => ?d);
}

#[cfg(feature = "std")]
#[test]
fn display_and_alternate_display() {
    use core::cell::Cell;
    use core::fmt;

    struct Example;

    impl fmt::Display for Example {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            if f.alternate() {
                f.write_str("alternate")
            } else {
                f.write_str("normal")
            }
        }
    }

    #[derive(Clone, Default)]
    struct CheckExample;

    impl Drain for CheckExample {
        type Ok = ();
        type Err = Never;

        fn log(
            &self,
            record: &Record,
            values: &OwnedKVList,
        ) -> Result<(), Never> {
            let mut checked_n = false;
            let mut checked_a = false;
            {
                let mut serializer = AsFmtSerializer(|key, fmt_args| {
                    if key == "n" {
                        assert_eq!(format!("{}", fmt_args), "normal");
                        checked_n = true;
                    } else if key == "a" {
                        assert_eq!(format!("{}", fmt_args), "alternate");
                        checked_a = true;
                    } else {
                        panic!("Unexpected key: {}", key);
                    }
                    Ok(())
                });

                record.kv.serialize(record, &mut serializer).unwrap();
            }

            assert!(checked_n, "Expected the normal formatter to be used");
            assert!(checked_a, "Expected the alternate formatter to be used");

            Ok(())
        }
    }

    let log = Logger::root(CheckExample, o!());

    info!(log, ""; "n" => %Example, "a" => #%Example);
}

#[test]
fn makers() {
    use crate::*;
    let drain = Duplicate(
        Discard.filter(|r| r.level().is_at_least(Level::Info)),
        Discard.filter_level(Level::Warning),
    )
    .map(Fuse);
    let _log = Logger::root(
        Arc::new(drain),
        o!("version" => env!("CARGO_PKG_VERSION")),
    );
}

#[test]
fn simple_logger_erased() {
    use crate::*;
    fn takes_arced_drain(_l: Logger) {}

    let drain = Discard.filter_level(Level::Warning).map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));

    takes_arced_drain(log.to_erased());
}

#[test]
fn logger_to_erased() {
    use crate::*;

    fn takes_arced_drain(_l: Logger) {}

    let drain = Duplicate(
        Discard.filter(|r| r.level().is_at_least(Level::Info)),
        Discard.filter_level(Level::Warning),
    )
    .map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));

    takes_arced_drain(log.into_erased());
}

#[test]
fn logger_by_ref() {
    use crate::*;
    let drain = Discard.filter_level(Level::Warning).map(Fuse);
    let log =
        Logger::root_typed(drain, o!("version" => env!("CARGO_PKG_VERSION")));
    let f = "f";
    let d = (1, 2);
    info!(&log, "message"; "f" => %f, "d" => ?d);
}

#[test]
fn test_never_type_clone() {
    // We just want to make sure that this compiles
    fn _do_not_run() {
        let x: Never = panic!("Can't actually construct a Never type here!");
        let y = x.clone();
    }
    // Always pass if we compiled
}

#[cfg(feature = "std")]
#[test]
fn can_hash_keys() {
    use std::collections::HashSet;
    use Key;
    let tab: HashSet<Key> = ["foo"].iter().map(|&k| k.into()).collect();
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::sync::Arc;

pub use crate::bam::errors::{Error, Result};
use crate::htslib;

/// An HTSlib thread pool. Create a thread pool and use `set_thread_pool()` methods
/// to share a thread pool across multiple BAM readers & writers.
/// The Rust wrapper holds the htslib thread pool behind a Rc, and a Rc reference
/// to the thread pool is held by each reader / writer so you don't need to
/// explicitly manage the lifetime of the `ThreadPool`.
#[derive(Clone, Debug)]
pub struct ThreadPool {
    pub(crate) handle: Arc<RefCell<InnerThreadPool>>,
}

impl ThreadPool {
    /// Create a new thread pool with `n_threads` threads.
    pub fn new(n_threads: u32) -> Result<ThreadPool> {
        let ret = unsafe { htslib::hts_tpool_init(n_threads as i32) };
        println!("got ptr: {:?}", ret);

        if ret.is_null() {
            Err(Error::ThreadPool)
        } else {
            let inner = htslib::htsThreadPool {
                pool: ret,
                qsize: n_threads as i32 * 1,
            };
            let inner = InnerThreadPool { inner };

            let handle = Arc::new(RefCell::new(inner));
            Ok(ThreadPool { handle })
        }
    }
}

/// Internal htsThreadPool
#[derive(Clone, Debug)]
pub struct InnerThreadPool {
    pub(crate) inner: htslib::htsThreadPool,
}

impl Drop for InnerThreadPool {
    fn drop(&mut self) {
        if self.inner.pool != std::ptr::null_mut() {
            unsafe {
                htslib::hts_tpool_destroy(self.inner.pool);
            }
        }

        self.inner.pool = std::ptr::null_mut();
    }
}
<commit_msg>small tweaks I missed in thread pool PR (#242)<commit_after>use std::cell::RefCell;
use std::sync::Arc;

pub use crate::bam::errors::{Error, Result};
use crate::htslib;

/// An HTSlib thread pool. Create a thread pool and use `set_thread_pool()` methods
/// to share a thread pool across multiple BAM readers & writers.
/// The Rust wrapper holds the htslib thread pool behind a Rc, and a Rc reference
/// to the thread pool is held by each reader / writer so you don't need to
/// explicitly manage the lifetime of the `ThreadPool`.
#[derive(Clone, Debug)]
pub struct ThreadPool {
    pub(crate) handle: Arc<RefCell<InnerThreadPool>>,
}

impl ThreadPool {
    /// Create a new thread pool with `n_threads` threads.
    pub fn new(n_threads: u32) -> Result<ThreadPool> {
        let ret = unsafe { htslib::hts_tpool_init(n_threads as i32) };

        if ret.is_null() {
            Err(Error::ThreadPool)
        } else {
            let inner = htslib::htsThreadPool {
                pool: ret,
                // this matches the default size
                // used in hts_set_threads.
                qsize: n_threads as i32 * 2,
            };
            let inner = InnerThreadPool { inner };

            let handle = Arc::new(RefCell::new(inner));
            Ok(ThreadPool { handle })
        }
    }
}

/// Internal htsThreadPool
#[derive(Clone, Debug)]
pub struct InnerThreadPool {
    pub(crate) inner: htslib::htsThreadPool,
}

impl Drop for InnerThreadPool {
    fn drop(&mut self) {
        if self.inner.pool != std::ptr::null_mut() {
            unsafe {
                htslib::hts_tpool_destroy(self.inner.pool);
            }
        }

        self.inner.pool = std::ptr::null_mut();
    }
}
<|endoftext|>


<commit_before>pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32
}
<commit_msg>Add `Color::rgba`<commit_after>pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32
}

impl Color {
    pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
        Color { r: r, g: g, b: b, a: a}
    }
}
<|endoftext|>


<commit_before>use traits::{AtEof, Compare, CompareResult, InputLength, InputIter, InputTake, Slice, FindSubstring, FindToken, ParseTo, AsBytes};
use util::Offset;

use std::str::{self, FromStr, Chars, CharIndices};
use std::ops::{Range, RangeTo, RangeFrom, RangeFull};
use std::iter::{Enumerate, Map};
use std::slice::Iter;

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item = char;
  type RawItem = char;
  type Iter = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize) -> Option<Self> {
    self.0.take(count).map(|s| CompleteStr(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self, Self)> {
    self.0.take_split(count).map(|(s1, s2)| {
      (CompleteStr(s1), CompleteStr(s2))
    })
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteStr<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteStr<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteStr<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second: &CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteStr<'a> {
  fn as_bytes(&self) -> &[u8] {
    self.0.as_bytes()
  }
}

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item = u8;
  type RawItem = u8;
  type Iter = Enumerate<Self::IterElem>;
  type IterElem = Map<Iter<'a, Self::Item>, fn(&u8) -> u8>; //Iter<'a, Self::RawItem>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize) -> Option<Self> {
    self.0.take(count).map(|s| CompleteByteSlice(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self, Self)> {
    self.0.take_split(count).map(|(s1, s2)| {
      (CompleteByteSlice(s1), CompleteByteSlice(s2))
    })
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteByteSlice<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteByteSlice<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteByteSlice<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second: &CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteByteSlice<'a> {
  fn as_bytes(&self) -> &[u8] {
    self.0.as_bytes()
  }
}

#[cfg(feature = "std")]
impl<'a> super::util::HexDisplay for CompleteByteSlice<'a> {
  fn to_hex(&self, chunk_size: usize) -> String {
    self.0.to_hex(chunk_size)
  }

  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    self.0.to_hex_from(chunk_size, from)
  }
}
<commit_msg>AsBytes is in util not root<commit_after>use traits::{AtEof, Compare, CompareResult, InputLength, InputIter, InputTake, Slice, FindSubstring, FindToken, ParseTo};
use util::{AsBytes, Offset};

use std::str::{self, FromStr, Chars, CharIndices};
use std::ops::{Range, RangeTo, RangeFrom, RangeFull};
use std::iter::{Enumerate, Map};
use std::slice::Iter;

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct CompleteStr<'a>(pub &'a str);

impl<'a> AtEof for CompleteStr<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteStr<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteStr<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteStr<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteStr(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteStr<'a> {
  type Item = char;
  type RawItem = char;
  type Iter = CharIndices<'a>;
  type IterElem = Chars<'a>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteStr<'a> {
  fn take(&self, count: usize) -> Option<Self> {
    self.0.take(count).map(|s| CompleteStr(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self, Self)> {
    self.0.take_split(count).map(|(s1, s2)| {
      (CompleteStr(s1), CompleteStr(s2))
    })
  }
}

impl<'a> InputLength for CompleteStr<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteStr<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteStr<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteStr<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteStr<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteStr<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteStr<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse().ok()
  }
}

impl<'a> Offset for CompleteStr<'a> {
  fn offset(&self, second: &CompleteStr<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteStr<'a> {
  fn as_bytes(&self) -> &[u8] {
    self.0.as_bytes()
  }
}

#[derive(Clone, Copy, Debug, PartialEq, Hash)]
pub struct CompleteByteSlice<'a>(pub &'a [u8]);

impl<'a> AtEof for CompleteByteSlice<'a> {
  fn at_eof(&self) -> bool {
    true
  }
}

impl<'a> Slice<Range<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: Range<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeTo<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeTo<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFrom<usize>> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFrom<usize>) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> Slice<RangeFull> for CompleteByteSlice<'a> {
  fn slice(&self, range: RangeFull) -> Self {
    CompleteByteSlice(self.0.slice(range))
  }
}

impl<'a> InputIter for CompleteByteSlice<'a> {
  type Item = u8;
  type RawItem = u8;
  type Iter = Enumerate<Self::IterElem>;
  type IterElem = Map<Iter<'a, Self::Item>, fn(&u8) -> u8>; //Iter<'a, Self::RawItem>;

  fn iter_indices(&self) -> Self::Iter {
    self.0.iter_indices()
  }
  fn iter_elements(&self) -> Self::IterElem {
    self.0.iter_elements()
  }
  fn position<P>(&self, predicate: P) -> Option<usize>
  where
    P: Fn(Self::RawItem) -> bool,
  {
    self.0.position(predicate)
  }
  fn slice_index(&self, count: usize) -> Option<usize> {
    self.0.slice_index(count)
  }
}

impl<'a> InputTake for CompleteByteSlice<'a> {
  fn take(&self, count: usize) -> Option<Self> {
    self.0.take(count).map(|s| CompleteByteSlice(s))
  }

  fn take_split(&self, count: usize) -> Option<(Self, Self)> {
    self.0.take_split(count).map(|(s1, s2)| {
      (CompleteByteSlice(s1), CompleteByteSlice(s2))
    })
  }
}

impl<'a> InputLength for CompleteByteSlice<'a> {
  fn input_len(&self) -> usize {
    self.0.input_len()
  }
}

impl<'a, 'b> Compare<&'b [u8]> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> Compare<&'b str> for CompleteByteSlice<'a> {
  fn compare(&self, t: &'b str) -> CompareResult {
    self.0.compare(t)
  }
  fn compare_no_case(&self, t: &'b str) -> CompareResult {
    self.0.compare_no_case(t)
  }
}

impl<'a, 'b> FindSubstring<&'b [u8]> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a, 'b> FindSubstring<&'b str> for CompleteByteSlice<'a> {
  fn find_substring(&self, substr: &'b str) -> Option<usize> {
    self.0.find_substring(substr)
  }
}

impl<'a> FindToken<char> for CompleteByteSlice<'a> {
  fn find_token(&self, token: char) -> bool {
    self.0.find_token(token)
  }
}

impl<'a> FindToken<u8> for CompleteByteSlice<'a> {
  fn find_token(&self, token: u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, 'b> FindToken<&'a u8> for CompleteByteSlice<'b> {
  fn find_token(&self, token: &u8) -> bool {
    self.0.find_token(token)
  }
}

impl<'a, R: FromStr> ParseTo<R> for CompleteByteSlice<'a> {
  fn parse_to(&self) -> Option<R> {
    self.0.parse_to()
  }
}

impl<'a> Offset for CompleteByteSlice<'a> {
  fn offset(&self, second: &CompleteByteSlice<'a>) -> usize {
    self.0.offset(second.0)
  }
}

impl<'a> AsBytes for CompleteByteSlice<'a> {
  fn as_bytes(&self) -> &[u8] {
    self.0.as_bytes()
  }
}

#[cfg(feature = "std")]
impl<'a> super::util::HexDisplay for CompleteByteSlice<'a> {
  fn to_hex(&self, chunk_size: usize) -> String {
    self.0.to_hex(chunk_size)
  }

  fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
    self.0.to_hex_from(chunk_size, from)
  }
}
<|endoftext|>


<commit_before>use std::os::raw::c_int;
use std::fmt::{Display, Formatter, Error as FormatError};
use std::error::Error as StdError;
use std::convert::{From, Into};
use std::result;

use ffi;

pub type PortMidiDeviceId = i32;

pub type Result<T> = result::Result<T, Error>;
impl From<ffi::PmError> for Result<()> {
    fn from(err: ffi::PmError) -> Self {
        match err {
            ffi::PmError::PmNoError | ffi::PmError::PmGotData => Ok(()),
            _ => Err(Error::PortMidi(err)),
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Error {
    PortMidi(ffi::PmError),
    Unknown,
    Unimplemented,
}
impl From<ffi::PmError> for Error {
    fn from(err: ffi::PmError) -> Self {
        match err {
            err @ _ => Error::PortMidi(err),
        }
    }
}

// Midi events
// -----------
/// Represents a single midi message, see also `MidiEvent`
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: u8,
    pub data1: u8,
    pub data2: u8,
}
impl From<[u8; 3]> for MidiMessage {
    fn from(raw: [u8; 3]) -> Self {
        MidiMessage {
            status: raw[0],
            data1: raw[1],
            data2: raw[2],
        }
    }
}
/// This can be used for `c_int` as well as `ffi::PmMessage` because these are only type aliases
impl From<i32> for MidiMessage {
    fn from(raw: i32) -> Self {
        MidiMessage {
            status: ((raw & 0x00_FF_00_00) >> 16) as u8,
            data1: ((raw & 0x00_00_FF_00) >> 8) as u8,
            data2: (raw & 0x00_00_00_FF) as u8,
        }
    }
}
impl Into<i32> for MidiMessage {
    fn into(self) -> i32 {
        (((self.data2 as i32) << 16)) | (((self.data1 as i32) << 8)) | self.status as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
///
/// TODO: what to do about the timestamp?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiEvent {
    pub message: MidiMessage,
    pub timestamp: ffi::PmTimestamp,
}

impl MidiEvent {
    pub fn wrap(event: ffi::PmEvent) -> MidiEvent {
        MidiEvent {
            message: MidiMessage::from(event.message),
            timestamp: event.timestamp,
        }
    }

    pub fn unwrap(&self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: MidiMessage::into(self.message),
            timestamp: self.timestamp,
        }
    }
}
<commit_msg>s/i32/ffi::PmMessage/g<commit_after>use std::os::raw::c_int;
use std::fmt::{Display, Formatter, Error as FormatError};
use std::error::Error as StdError;
use std::convert::{From, Into};
use std::result;

use ffi;

pub type PortMidiDeviceId = i32;

pub type Result<T> = result::Result<T, Error>;
impl From<ffi::PmError> for Result<()> {
    fn from(err: ffi::PmError) -> Self {
        match err {
            ffi::PmError::PmNoError | ffi::PmError::PmGotData => Ok(()),
            _ => Err(Error::PortMidi(err)),
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Error {
    PortMidi(ffi::PmError),
    Unknown,
    Unimplemented,
}
impl From<ffi::PmError> for Error {
    fn from(err: ffi::PmError) -> Self {
        match err {
            err @ _ => Error::PortMidi(err),
        }
    }
}

// Midi events
// -----------
/// Represents a single midi message, see also `MidiEvent`
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiMessage {
    pub status: u8,
    pub data1: u8,
    pub data2: u8,
}
impl From<[u8; 3]> for MidiMessage {
    fn from(raw: [u8; 3]) -> Self {
        MidiMessage {
            status: raw[0],
            data1: raw[1],
            data2: raw[2],
        }
    }
}
/// This can be used for `c_int` as well as `i32` because these are only type aliases
impl From<ffi::PmMessage> for MidiMessage {
    fn from(raw: i32) -> Self {
        MidiMessage {
            status: ((raw & 0x00_FF_00_00) >> 16) as u8,
            data1: ((raw & 0x00_00_FF_00) >> 8) as u8,
            data2: (raw & 0x00_00_00_FF) as u8,
        }
    }
}
impl Into<ffi::PmMessage> for MidiMessage {
    fn into(self) -> i32 {
        (((self.data2 as i32) << 16)) | (((self.data1 as i32) << 8)) | self.status as i32
    }
}

/// Represents a time stamped midi event. See also `MidiMessage`
///
/// See the PortMidi documentation for how SysEx and midi realtime messages
/// are handled
///
/// TODO: what to do about the timestamp?
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct MidiEvent {
    pub message: MidiMessage,
    pub timestamp: ffi::PmTimestamp,
}

impl MidiEvent {
    pub fn wrap(event: ffi::PmEvent) -> MidiEvent {
        MidiEvent {
            message: MidiMessage::from(event.message),
            timestamp: event.timestamp,
        }
    }

    pub fn unwrap(&self) -> ffi::PmEvent {
        ffi::PmEvent {
            message: MidiMessage::into(self.message),
            timestamp: self.timestamp,
        }
    }
}
<|endoftext|>


<commit_before>/// Escape HTML following [OWASP](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet)
///
/// Escape the following characters with HTML entity encoding to prevent switching
/// into any execution context, such as script, style, or event handlers. Using
/// hex entities is recommended in the spec. In addition to the 5 characters
/// significant in XML (&, <, >, ", '), the forward slash is included as it helps
/// to end an HTML entity.
///
/// & --> &
/// < --> <
/// > --> >
/// " --> "
/// ' --> '     ' is not recommended
/// / --> /     forward slash is included as it helps end an HTML entity
#[inline]
pub fn escape_html(input: &str) -> String {
    let mut output = String::with_capacity(input.len() * 2);
    for c in input.chars() {
        match c {
            '&' => output.push_str("&"),
            '<' => output.push_str("<"),
            '>' => output.push_str(">"),
            '"' => output.push_str("""),
            '\'' => output.push_str("'"),
            '/' => output.push_str("/"),
            // Additional one for old IE (unpatched IE8 and below)
            // See https://github.com/OWASP/owasp-java-encoder/wiki/Grave-Accent-Issue
            '`' => output.push_str("`"),
            _ => output.push(c)
        }
    }

    // Not using shrink_to_fit() on purpose
    output
}

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

    #[test]
    fn test_escape_html() {
        let tests = vec![
            (r"a&b", "a&b"),
            (r"<a", "<a"),
            (r">a", ">a"),
            (r#"""#, """),
            (r#"'"#, "'"),
            (r#"大阪"#, "大阪"),
        ];
        for (input, expected) in tests {
            assert_eq!(escape_html(input), expected);
        }
    }
}
<commit_msg>create a code block for the `escape_html` docs<commit_after>/// Escape HTML following [OWASP](https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet)
///
/// Escape the following characters with HTML entity encoding to prevent switching
/// into any execution context, such as script, style, or event handlers. Using
/// hex entities is recommended in the spec. In addition to the 5 characters
/// significant in XML (&, <, >, ", '), the forward slash is included as it helps
/// to end an HTML entity.
///
/// ```text
/// & --> &
/// < --> <
/// > --> >
/// " --> "
/// ' --> '     ' is not recommended
/// / --> /     forward slash is included as it helps end an HTML entity
/// ```
#[inline]
pub fn escape_html(input: &str) -> String {
    let mut output = String::with_capacity(input.len() * 2);
    for c in input.chars() {
        match c {
            '&' => output.push_str("&"),
            '<' => output.push_str("<"),
            '>' => output.push_str(">"),
            '"' => output.push_str("""),
            '\'' => output.push_str("'"),
            '/' => output.push_str("/"),
            // Additional one for old IE (unpatched IE8 and below)
            // See https://github.com/OWASP/owasp-java-encoder/wiki/Grave-Accent-Issue
            '`' => output.push_str("`"),
            _ => output.push(c)
        }
    }

    // Not using shrink_to_fit() on purpose
    output
}

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

    #[test]
    fn test_escape_html() {
        let tests = vec![
            (r"a&b", "a&b"),
            (r"<a", "<a"),
            (r">a", ">a"),
            (r#"""#, """),
            (r#"'"#, "'"),
            (r#"大阪"#, "大阪"),
        ];
        for (input, expected) in tests {
            assert_eq!(escape_html(input), expected);
        }
    }
}
<|endoftext|>