<commit_before>//! The module defines MPD status data structures

use std::str::FromStr;
use std::fmt;
use time::Duration;
use rustc_serialize::{Encodable, Encoder};

use error::{Error, ParseError};
use song::{Id, QueuePlace};
use convert::FromIter;

/// MPD status
#[derive(Debug, PartialEq, Clone, Default)]
pub struct Status {
    /// volume (0-100, or -1 if volume is unavailable (e.g. for HTTPD output type)
    pub volume: i8,
    /// repeat mode
    pub repeat: bool,
    /// random mode
    pub random: bool,
    /// single mode
    pub single: bool,
    /// consume mode
    pub consume: bool,
    /// queue version number
    pub queue_version: u32,
    /// queue length
    pub queue_len: u32,
    /// playback state
    pub state: State,
    /// currently playing song place in the queue
    pub song: Option<QueuePlace>,
    /// next song to play place in the queue
    pub nextsong: Option<QueuePlace>,
    /// time current song played, and total song duration (in seconds resolution)
    pub time: Option<(Duration, Duration)>,
    /// elapsed play time current song played (in milliseconds resolution)
    pub elapsed: Option<Duration>,
    /// current song duration
    pub duration: Option<Duration>,
    /// current song bitrate, kbps
    pub bitrate: Option<u32>,
    /// crossfade timeout, seconds
    pub crossfade: Option<Duration>,
    /// mixramp threshold, dB
    pub mixrampdb: f32,
    /// mixramp duration, seconds
    pub mixrampdelay: Option<Duration>,
    /// current audio playback format
    pub audio: Option<AudioFormat>,
    /// current DB updating job number (if DB updating is in progress)
    pub updating_db: Option<u32>,
    /// last player error (if happened, can be reset with `clearerror()` method)
    pub error: Option<String>,
    /// replay gain mode
    pub replaygain: Option<ReplayGain>,
}

impl Encodable for Status {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_struct("Status", 21, |e| {
            e.emit_struct_field("volume", 0, |e| self.volume.encode(e))
             .and_then(|_| e.emit_struct_field("repeat", 1, |e| self.repeat.encode(e)))
             .and_then(|_| e.emit_struct_field("random", 2, |e| self.random.encode(e)))
             .and_then(|_| e.emit_struct_field("single", 3, |e| self.single.encode(e)))
             .and_then(|_| e.emit_struct_field("consume", 4, |e| self.consume.encode(e)))
             .and_then(|_| e.emit_struct_field("queue_version", 5, |e| self.queue_version.encode(e)))
             .and_then(|_| e.emit_struct_field("queue_len", 6, |e| self.queue_len.encode(e)))
             .and_then(|_| e.emit_struct_field("state", 7, |e| self.state.encode(e)))
             .and_then(|_| e.emit_struct_field("song", 8, |e| self.song.encode(e)))
             .and_then(|_| e.emit_struct_field("nextsong", 9, |e| self.nextsong.encode(e)))
             .and_then(|_| {
                 e.emit_struct_field("time", 10, |e| {
                     e.emit_option(|e| {
                         self.time
                             .map(|p| {
                                 e.emit_option_some(|e| {
                                     e.emit_tuple(2, |e| {
                                         e.emit_tuple_arg(0, |e| p.0.num_seconds().encode(e))
                                          .and_then(|_| e.emit_tuple_arg(1, |e| p.1.num_seconds().encode(e)))
                                     })
                                 })
                             })
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| {
                 e.emit_struct_field("elapsed", 11, |e| {
                     e.emit_option(|e| {
                         self.elapsed
                             .map(|d| e.emit_option_some(|e| d.num_seconds().encode(e)))
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| {
                 e.emit_struct_field("duration", 12, |e| {
                     e.emit_option(|e| {
                         self.duration
                             .map(|d| e.emit_option_some(|e| d.num_seconds().encode(e)))
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| e.emit_struct_field("bitrate", 13, |e| self.bitrate.encode(e)))
             .and_then(|_| {
                 e.emit_struct_field("crossfade", 14, |e| {
                     e.emit_option(|e| {
                         self.crossfade
                             .map(|d| e.emit_option_some(|e| d.num_seconds().encode(e)))
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| e.emit_struct_field("mixrampdb", 15, |e| self.mixrampdb.encode(e)))
             .and_then(|_| {
                 e.emit_struct_field("mixrampdelay", 16, |e| {
                     e.emit_option(|e| {
                         self.mixrampdelay
                             .map(|d| e.emit_option_some(|e| d.num_seconds().encode(e)))
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| e.emit_struct_field("audio", 17, |e| self.audio.encode(e)))
             .and_then(|_| e.emit_struct_field("updating_db", 18, |e| self.updating_db.encode(e)))
             .and_then(|_| e.emit_struct_field("error", 19, |e| self.error.encode(e)))
             .and_then(|_| e.emit_struct_field("replaygain", 20, |e| self.replaygain.encode(e)))
        })

    }
}

impl FromIter for Status {
    fn from_iter<I: Iterator<Item = Result<(String, String), Error>>>(iter: I) -> Result<Status, Error> {
        let mut result = Status::default();

        for res in iter {
            let line = try!(res);
            match &*line.0 {
                "volume" => result.volume = try!(line.1.parse()),

                "repeat" => result.repeat = &*line.1 == "1",
                "random" => result.random = &*line.1 == "1",
                "single" => result.single = &*line.1 == "1",
                "consume" => result.consume = &*line.1 == "1",

                "playlist" => result.queue_version = try!(line.1.parse()),
                "playlistlength" => result.queue_len = try!(line.1.parse()),
                "state" => result.state = try!(line.1.parse()),
                "songid" => {
                    match result.song {
                        None => {
                            result.song = Some(QueuePlace {
                                id: Id(try!(line.1.parse())),
                                pos: 0,
                                prio: 0,
                            })
                        }
                        Some(ref mut place) => place.id = Id(try!(line.1.parse())),
                    }
                }
                "song" => {
                    match result.song {
                        None => {
                            result.song = Some(QueuePlace {
                                pos: try!(line.1.parse()),
                                id: Id(0),
                                prio: 0,
                            })
                        }
                        Some(ref mut place) => place.pos = try!(line.1.parse()),
                    }
                }
                "nextsongid" => {
                    match result.nextsong {
                        None => {
                            result.nextsong = Some(QueuePlace {
                                id: Id(try!(line.1.parse())),
                                pos: 0,
                                prio: 0,
                            })
                        }
                        Some(ref mut place) => place.id = Id(try!(line.1.parse())),
                    }
                }
                "nextsong" => {
                    match result.nextsong {
                        None => {
                            result.nextsong = Some(QueuePlace {
                                pos: try!(line.1.parse()),
                                id: Id(0),
                                prio: 0,
                            })
                        }
                        Some(ref mut place) => place.pos = try!(line.1.parse()),
                    }
                }
                "time" => {
                    result.time = try!({
                        let mut splits = line.1.splitn(2, ':').map(|v| v.parse().map_err(ParseError::BadInteger).map(Duration::seconds));
                        match (splits.next(), splits.next()) {
                            (Some(Ok(a)), Some(Ok(b))) => Ok(Some((a, b))),
                            (Some(Err(e)), _) | (_, Some(Err(e))) => Err(e),
                            _ => Ok(None),
                        }
                    })
                }
                // TODO" => float errors don't work on stable
                "elapsed" => {
                    result.elapsed = line.1
                                         .parse::<f32>()
                                         .ok()
                                         .map(|v| Duration::seconds((v * 1000.0) as i64))
                }
                "duration" => result.duration = Some(Duration::seconds(try!(line.1.parse()))),
                "bitrate" => result.bitrate = Some(try!(line.1.parse())),
                "xfade" => result.crossfade = Some(Duration::seconds(try!(line.1.parse()))),
                // "mixrampdb" => 0.0, //get_field!(map, "mixrampdb"),
                // "mixrampdelay" => None, //get_field!(map, opt "mixrampdelay").map(|v: f64| Duration::milliseconds((v * 1000.0) as i64)),
                "audio" => result.audio = Some(try!(line.1.parse())),
                "updating_db" => result.updating_db = Some(try!(line.1.parse())),
                "error" => result.error = Some(line.1.to_owned()),
                "replay_gain_mode" => result.replaygain = Some(try!(line.1.parse())),
                _ => (),
            }
        }

        Ok(result)
    }
}

/// Audio playback format
#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable)]
pub struct AudioFormat {
    /// sample rate, kbps
    pub rate: u32,
    /// sample resolution in bits, can be 0 for floating point resolution
    pub bits: u8,
    /// number of channels
    pub chans: u8,
}

impl FromStr for AudioFormat {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<AudioFormat, ParseError> {
        let mut it = s.split(':');
        Ok(AudioFormat {
            rate: try!(it.next()
                         .ok_or(ParseError::NoRate)
                         .and_then(|v| v.parse().map_err(ParseError::BadRate))),
            bits: try!(it.next()
                         .ok_or(ParseError::NoBits)
                         .and_then(|v| if &*v == "f" { Ok(0) } else { v.parse().map_err(ParseError::BadBits) })),
            chans: try!(it.next()
                          .ok_or(ParseError::NoChans)
                          .and_then(|v| v.parse().map_err(ParseError::BadChans))),
        })
    }
}

/// Playback state
#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum State {
    /// player stopped
    Stop,
    /// player is playing
    Play,
    /// player paused
    Pause,
}

impl Default for State {
    fn default() -> State {
        State::Stop
    }
}

impl FromStr for State {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<State, ParseError> {
        match s {
            "stop" => Ok(State::Stop),
            "play" => Ok(State::Play),
            "pause" => Ok(State::Pause),
            _ => Err(ParseError::BadState(s.to_owned())),
        }
    }
}

/// Replay gain mode
#[derive(Debug, Clone, Copy, PartialEq, RustcEncodable, RustcDecodable)]
pub enum ReplayGain {
    /// off
    Off,
    /// track
    Track,
    /// album
    Album,
    /// auto
    Auto,
}

impl FromStr for ReplayGain {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<ReplayGain, ParseError> {
        use self::ReplayGain::*;
        match s {
            "off" => Ok(Off),
            "track" => Ok(Track),
            "album" => Ok(Album),
            "auto" => Ok(Auto),
            _ => Err(ParseError::BadValue(s.to_owned())),
        }
    }
}

impl fmt::Display for ReplayGain {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ReplayGain::*;
        f.write_str(match *self {
            Off => "off",
            Track => "track",
            Album => "album",
            Auto => "auto",
        })
    }
}
<commit_msg>Fix the elapsed time counter<commit_after>//! The module defines MPD status data structures

use std::str::FromStr;
use std::fmt;
use time::Duration;
use rustc_serialize::{Encodable, Encoder};

use error::{Error, ParseError};
use song::{Id, QueuePlace};
use convert::FromIter;

/// MPD status
#[derive(Debug, PartialEq, Clone, Default)]
pub struct Status {
    /// volume (0-100, or -1 if volume is unavailable (e.g. for HTTPD output type)
    pub volume: i8,
    /// repeat mode
    pub repeat: bool,
    /// random mode
    pub random: bool,
    /// single mode
    pub single: bool,
    /// consume mode
    pub consume: bool,
    /// queue version number
    pub queue_version: u32,
    /// queue length
    pub queue_len: u32,
    /// playback state
    pub state: State,
    /// currently playing song place in the queue
    pub song: Option<QueuePlace>,
    /// next song to play place in the queue
    pub nextsong: Option<QueuePlace>,
    /// time current song played, and total song duration (in seconds resolution)
    pub time: Option<(Duration, Duration)>,
    /// elapsed play time current song played (in milliseconds resolution)
    pub elapsed: Option<Duration>,
    /// current song duration
    pub duration: Option<Duration>,
    /// current song bitrate, kbps
    pub bitrate: Option<u32>,
    /// crossfade timeout, seconds
    pub crossfade: Option<Duration>,
    /// mixramp threshold, dB
    pub mixrampdb: f32,
    /// mixramp duration, seconds
    pub mixrampdelay: Option<Duration>,
    /// current audio playback format
    pub audio: Option<AudioFormat>,
    /// current DB updating job number (if DB updating is in progress)
    pub updating_db: Option<u32>,
    /// last player error (if happened, can be reset with `clearerror()` method)
    pub error: Option<String>,
    /// replay gain mode
    pub replaygain: Option<ReplayGain>,
}

impl Encodable for Status {
    fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
        e.emit_struct("Status", 21, |e| {
            e.emit_struct_field("volume", 0, |e| self.volume.encode(e))
             .and_then(|_| e.emit_struct_field("repeat", 1, |e| self.repeat.encode(e)))
             .and_then(|_| e.emit_struct_field("random", 2, |e| self.random.encode(e)))
             .and_then(|_| e.emit_struct_field("single", 3, |e| self.single.encode(e)))
             .and_then(|_| e.emit_struct_field("consume", 4, |e| self.consume.encode(e)))
             .and_then(|_| e.emit_struct_field("queue_version", 5, |e| self.queue_version.encode(e)))
             .and_then(|_| e.emit_struct_field("queue_len", 6, |e| self.queue_len.encode(e)))
             .and_then(|_| e.emit_struct_field("state", 7, |e| self.state.encode(e)))
             .and_then(|_| e.emit_struct_field("song", 8, |e| self.song.encode(e)))
             .and_then(|_| e.emit_struct_field("nextsong", 9, |e| self.nextsong.encode(e)))
             .and_then(|_| {
                 e.emit_struct_field("time", 10, |e| {
                     e.emit_option(|e| {
                         self.time
                             .map(|p| {
                                 e.emit_option_some(|e| {
                                     e.emit_tuple(2, |e| {
                                         e.emit_tuple_arg(0, |e| p.0.num_seconds().encode(e))
                                          .and_then(|_| e.emit_tuple_arg(1, |e| p.1.num_seconds().encode(e)))
                                     })
                                 })
                             })
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| {
                 e.emit_struct_field("elapsed", 11, |e| {
                     e.emit_option(|e| {
                         self.elapsed
                             .map(|d| e.emit_option_some(|e| d.num_seconds().encode(e)))
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| {
                 e.emit_struct_field("duration", 12, |e| {
                     e.emit_option(|e| {
                         self.duration
                             .map(|d| e.emit_option_some(|e| d.num_seconds().encode(e)))
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| e.emit_struct_field("bitrate", 13, |e| self.bitrate.encode(e)))
             .and_then(|_| {
                 e.emit_struct_field("crossfade", 14, |e| {
                     e.emit_option(|e| {
                         self.crossfade
                             .map(|d| e.emit_option_some(|e| d.num_seconds().encode(e)))
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| e.emit_struct_field("mixrampdb", 15, |e| self.mixrampdb.encode(e)))
             .and_then(|_| {
                 e.emit_struct_field("mixrampdelay", 16, |e| {
                     e.emit_option(|e| {
                         self.mixrampdelay
                             .map(|d| e.emit_option_some(|e| d.num_seconds().encode(e)))
                             .unwrap_or_else(|| e.emit_option_none())
                     })
                 })
             })
             .and_then(|_| e.emit_struct_field("audio", 17, |e| self.audio.encode(e)))
             .and_then(|_| e.emit_struct_field("updating_db", 18, |e| self.updating_db.encode(e)))
             .and_then(|_| e.emit_struct_field("error", 19, |e| self.error.encode(e)))
             .and_then(|_| e.emit_struct_field("replaygain", 20, |e| self.replaygain.encode(e)))
        })

    }
}

impl FromIter for Status {
    fn from_iter<I: Iterator<Item = Result<(String, String), Error>>>(iter: I) -> Result<Status, Error> {
        let mut result = Status::default();

        for res in iter {
            let line = try!(res);
            match &*line.0 {
                "volume" => result.volume = try!(line.1.parse()),

                "repeat" => result.repeat = &*line.1 == "1",
                "random" => result.random = &*line.1 == "1",
                "single" => result.single = &*line.1 == "1",
                "consume" => result.consume = &*line.1 == "1",

                "playlist" => result.queue_version = try!(line.1.parse()),
                "playlistlength" => result.queue_len = try!(line.1.parse()),
                "state" => result.state = try!(line.1.parse()),
                "songid" => {
                    match result.song {
                        None => {
                            result.song = Some(QueuePlace {
                                id: Id(try!(line.1.parse())),
                                pos: 0,
                                prio: 0,
                            })
                        }
                        Some(ref mut place) => place.id = Id(try!(line.1.parse())),
                    }
                }
                "song" => {
                    match result.song {
                        None => {
                            result.song = Some(QueuePlace {
                                pos: try!(line.1.parse()),
                                id: Id(0),
                                prio: 0,
                            })
                        }
                        Some(ref mut place) => place.pos = try!(line.1.parse()),
                    }
                }
                "nextsongid" => {
                    match result.nextsong {
                        None => {
                            result.nextsong = Some(QueuePlace {
                                id: Id(try!(line.1.parse())),
                                pos: 0,
                                prio: 0,
                            })
                        }
                        Some(ref mut place) => place.id = Id(try!(line.1.parse())),
                    }
                }
                "nextsong" => {
                    match result.nextsong {
                        None => {
                            result.nextsong = Some(QueuePlace {
                                pos: try!(line.1.parse()),
                                id: Id(0),
                                prio: 0,
                            })
                        }
                        Some(ref mut place) => place.pos = try!(line.1.parse()),
                    }
                }
                "time" => {
                    result.time = try!({
                        let mut splits = line.1.splitn(2, ':').map(|v| v.parse().map_err(ParseError::BadInteger).map(Duration::seconds));
                        match (splits.next(), splits.next()) {
                            (Some(Ok(a)), Some(Ok(b))) => Ok(Some((a, b))),
                            (Some(Err(e)), _) | (_, Some(Err(e))) => Err(e),
                            _ => Ok(None),
                        }
                    })
                }
                // TODO" => float errors don't work on stable
                "elapsed" => {
                    result.elapsed = line.1
                                         .parse::<f32>()
                                         .ok()
                                         .map(|v| Duration::milliseconds((v * 1000.0) as i64))
                }
                "duration" => result.duration = Some(Duration::seconds(try!(line.1.parse()))),
                "bitrate" => result.bitrate = Some(try!(line.1.parse())),
                "xfade" => result.crossfade = Some(Duration::seconds(try!(line.1.parse()))),
                // "mixrampdb" => 0.0, //get_field!(map, "mixrampdb"),
                // "mixrampdelay" => None, //get_field!(map, opt "mixrampdelay").map(|v: f64| Duration::milliseconds((v * 1000.0) as i64)),
                "audio" => result.audio = Some(try!(line.1.parse())),
                "updating_db" => result.updating_db = Some(try!(line.1.parse())),
                "error" => result.error = Some(line.1.to_owned()),
                "replay_gain_mode" => result.replaygain = Some(try!(line.1.parse())),
                _ => (),
            }
        }

        Ok(result)
    }
}

/// Audio playback format
#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable)]
pub struct AudioFormat {
    /// sample rate, kbps
    pub rate: u32,
    /// sample resolution in bits, can be 0 for floating point resolution
    pub bits: u8,
    /// number of channels
    pub chans: u8,
}

impl FromStr for AudioFormat {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<AudioFormat, ParseError> {
        let mut it = s.split(':');
        Ok(AudioFormat {
            rate: try!(it.next()
                         .ok_or(ParseError::NoRate)
                         .and_then(|v| v.parse().map_err(ParseError::BadRate))),
            bits: try!(it.next()
                         .ok_or(ParseError::NoBits)
                         .and_then(|v| if &*v == "f" { Ok(0) } else { v.parse().map_err(ParseError::BadBits) })),
            chans: try!(it.next()
                          .ok_or(ParseError::NoChans)
                          .and_then(|v| v.parse().map_err(ParseError::BadChans))),
        })
    }
}

/// Playback state
#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum State {
    /// player stopped
    Stop,
    /// player is playing
    Play,
    /// player paused
    Pause,
}

impl Default for State {
    fn default() -> State {
        State::Stop
    }
}

impl FromStr for State {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<State, ParseError> {
        match s {
            "stop" => Ok(State::Stop),
            "play" => Ok(State::Play),
            "pause" => Ok(State::Pause),
            _ => Err(ParseError::BadState(s.to_owned())),
        }
    }
}

/// Replay gain mode
#[derive(Debug, Clone, Copy, PartialEq, RustcEncodable, RustcDecodable)]
pub enum ReplayGain {
    /// off
    Off,
    /// track
    Track,
    /// album
    Album,
    /// auto
    Auto,
}

impl FromStr for ReplayGain {
    type Err = ParseError;
    fn from_str(s: &str) -> Result<ReplayGain, ParseError> {
        use self::ReplayGain::*;
        match s {
            "off" => Ok(Off),
            "track" => Ok(Track),
            "album" => Ok(Album),
            "auto" => Ok(Auto),
            _ => Err(ParseError::BadValue(s.to_owned())),
        }
    }
}

impl fmt::Display for ReplayGain {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::ReplayGain::*;
        f.write_str(match *self {
            Off => "off",
            Track => "track",
            Album => "album",
            Auto => "auto",
        })
    }
}
<|endoftext|>


<commit_before>use std::num::{One, Zero};
use extra::complex::Cmplx;

use rational::Rational;

#[deriving(Eq)]
pub enum LNumeric {
    NExact(Cmplx<Rational>),
    NInexact(Cmplx<f64>)
}

impl LNumeric {
    pub fn is_inexact(&self) -> bool {
        match *self {
            NExact(_) => false,
            NInexact(_) => true,
        }
    }

    pub fn is_exact(&self) -> bool {
        match *self {
            NExact(_) => true,
            NInexact(_) => false,
        }
    }

    pub fn is_real(&self) -> bool {
        match *self {
            NExact(c) => c.im.is_zero(),
            NInexact(c) => c.im.is_zero(),
        }
    }
}

pub fn to_str(&n: &LNumeric) -> ~str {
    match n {
        NExact(Cmplx{ re: re, im: im }) => {
            if im.is_zero() {
                re.to_str()
            } else if re.is_zero() {
                im.to_str() + "i"
            } else if im.is_negative() {
                re.to_str() + im.to_str() + "i"
            } else {
                re.to_str() + "+" + im.to_str() + "i"
            }
        },
        NInexact(Cmplx{ re: re, im: im }) => {
            if im == 0f64 {
                re.to_str()
            } else if re == 0f64 {
                im.to_str() + "i"
            } else if im < 0f64 {
                re.to_str() + im.to_str() + "i"
            } else {
                re.to_str() + "+" + im.to_str() + "i"
            }
        },
    }
}

impl ToStr for LNumeric {
    fn to_str(&self) -> ~str {
        to_str(self)
    }
}

impl One for LNumeric {
    fn one() -> LNumeric {
        NExact(Cmplx { re: One::one(), im: Zero::zero() })
    }
}

impl Zero for LNumeric {
    fn zero() -> LNumeric {
        NExact(Zero::zero())
    }

    fn is_zero(&self) -> bool {
        match *self {
            NExact(cmplx) => cmplx.is_zero(),
            NInexact(cmplx) => cmplx.is_zero(),
        }
    }
}

pub fn to_inexact(&n: &LNumeric) -> Cmplx<f64> {
    match n {
        NExact(Cmplx { re: re, im: im }) => Cmplx {re: re.to_f64(), im: im.to_f64()},
        NInexact(cmplx) => cmplx
    }
}

pub fn neg(&n: &LNumeric) -> LNumeric {
    match n {
        NExact(cmplx) => NExact(-cmplx),
        NInexact(cmplx) => NInexact(-cmplx),
    }
}

impl Neg<LNumeric> for LNumeric {
    fn neg(&self) -> LNumeric {
        neg(self)
    }
}

pub fn add(&lhs: &LNumeric, &rhs: &LNumeric) -> LNumeric {
    match (lhs, rhs) {
        (NExact(cmplx0), NExact(cmplx1)) => NExact(cmplx0 + cmplx1),
        _ => {
            let cmplx0 = to_inexact(&lhs);
            let cmplx1 = to_inexact(&rhs);
            NInexact(cmplx0 + cmplx1)
        },
    }
}

impl Add<LNumeric, LNumeric> for LNumeric {
    fn add(&self, rhs: &LNumeric) -> LNumeric {
        add(self, rhs)
    }
}

pub fn sub(&lhs: &LNumeric, &rhs: &LNumeric) -> LNumeric {
    match (lhs, rhs) {
        (NExact(cmplx0), NExact(cmplx1)) => NExact(cmplx0 - cmplx1),
        _ => {
            let cmplx0 = to_inexact(&lhs);
            let cmplx1 = to_inexact(&rhs);
            NInexact(cmplx0 - cmplx1)
        },
    }
}

impl Sub<LNumeric, LNumeric> for LNumeric {
    fn sub(&self, rhs: &LNumeric) -> LNumeric {
        sub(self, rhs)
    }
}

pub fn mul(&lhs: &LNumeric, &rhs: &LNumeric) -> LNumeric {
    match (lhs, rhs) {
        (NExact(cmplx0), NExact(cmplx1)) => NExact(cmplx0 * cmplx1),
        _ => {
            let cmplx0 = to_inexact(&lhs);
            let cmplx1 = to_inexact(&rhs);
            NInexact(cmplx0 * cmplx1)
        },
    }
}

impl Mul<LNumeric, LNumeric> for LNumeric {
    fn mul(&self, rhs: &LNumeric) -> LNumeric {
        mul(self, rhs)
    }
}

pub fn div(&lhs: &LNumeric, &rhs: &LNumeric) -> LNumeric {
    match (lhs, rhs) {
        (NExact(cmplx0), NExact(cmplx1)) => NExact(cmplx0 / cmplx1),
        _ => {
            let cmplx0 = to_inexact(&lhs);
            let cmplx1 = to_inexact(&rhs);
            NInexact(cmplx0 / cmplx1)
        },
    }
}

impl Div<LNumeric, LNumeric> for LNumeric {
    fn div(&self, rhs: &LNumeric) -> LNumeric {
        div(self, rhs)
    }
}

pub fn cmplx_exp<T: Clone + Exponential + Trigonometric + Num>(c: &Cmplx<T>) -> Cmplx<T> {
    // e^(a+bi) = e^a * (cos b + i sin b)
    let pow = c.re.exp();
    Cmplx { re: c.im.cos() * pow, im: c.im.sin() * pow }
}

impl Exponential for LNumeric {
    fn exp(&self) -> LNumeric {
        NInexact( cmplx_exp( &to_inexact(self)) )
    }

    fn exp2(&self) -> LNumeric {
        let x = to_inexact(self);
        let l2 = Real::ln_2();
        NInexact( cmplx_exp( &Cmplx{ re: x.re * l2, im: x.im * l2 }) )
    }

    fn ln(&self) -> LNumeric {
        let (norm, arg) = to_inexact(self).to_polar();
        NInexact( Cmplx{ re: norm.ln(), im: arg } )
    }

    fn log(&self, base: &LNumeric) -> LNumeric {
        self.ln() / base.ln()
    }

    fn log2(&self) -> LNumeric {
        let (norm, arg) = to_inexact(self).to_polar();
        let l2 = Real::ln_2();
        NInexact( Cmplx{ re: norm.ln() / l2, im: arg / l2 } )
    }

    fn log10(&self) -> LNumeric {
        let (norm, arg) = to_inexact(self).to_polar();
        let l10 = Real::ln_10();
        NInexact( Cmplx{ re: norm.ln() / l10, im: arg / l10 } )
    }
}

pub fn from_int(n: int) -> LNumeric {
    NExact( Cmplx{ re: Rational::new(n, 1), im: Zero::zero() } )
}

pub fn from_rational(re: Rational) -> LNumeric {
    NExact( Cmplx{ re: re, im: Zero::zero() } )
}

pub fn from_f64(re: f64) -> LNumeric {
    NInexact( Cmplx{ re: re, im: 0f64 } )
}

pub fn from_real(re: &LReal) -> LNumeric {
    match *re {
        NRational(x) => from_rational(x),
        NFloat(x) => from_f64(x),
    }
}

pub fn exact(re: Rational, im: Rational) -> LNumeric {
    NExact( Cmplx { re: re, im: im } )
}

pub fn inexact(re: f64, im: f64) -> LNumeric {
    NInexact( Cmplx { re: re, im: im } )
}

pub enum LReal {
    NRational(Rational),
    NFloat(f64)
}

priv fn coerce<T>(a: &LReal, b: &LReal,
                    op_r: &fn(&Rational, &Rational) -> T,
                    op_f: &fn(f64, f64) -> T) -> T
{
    match (a, b) {
        (&NRational(ref x), &NRational(ref y)) => op_r(x, y),
        (&NRational(ref x), &NFloat(y)) => op_f(x.to_f64(), y),
        (&NFloat(x), &NRational(ref y)) => op_f(x, y.to_f64()),
        (&NFloat(x), &NFloat(y)) => op_f(x, y),
    }
}

impl Eq for LReal {
    fn eq(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x == y}, |x,y| {x == y})
    }

    fn ne(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x != y}, |x,y| {x != y})
    }
}

impl Ord for LReal {
    fn lt(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x < y}, |x,y| {x < y})
    }

    fn le(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x <= y}, |x,y| {x <= y})
    }

    fn gt(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x > y}, |x,y| {x > y})
    }

    fn ge(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x >= y}, |x,y| {x >= y})
    }
}

impl Round for LReal {
    fn floor(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.floor() ),
            NFloat( f ) => NFloat( f.floor() ),
        }
    }

    fn ceil(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.ceil() ),
            NFloat( f ) => NFloat( f.ceil() ),
        }
    }

    fn round(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.round() ),
            NFloat( f ) => NFloat( f.round() ),
        }
    }

    fn trunc(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.trunc() ),
            NFloat( f ) => NFloat( f.trunc() ),
        }
    }

    fn fract(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.fract() ),
            NFloat( f ) => NFloat( f.fract() ),
        }
    }
}

pub fn get_real(n: &LNumeric) -> Option<LReal>
{
    match *n {
        NExact( Cmplx{ re: re, im: im } ) => if im.is_zero() {
                Some( NRational ( re ) )
            } else {
                None
            },
        NInexact( Cmplx{ re: re, im: im } ) => if im.is_zero() {
                Some( NFloat ( re ) )
            } else {
                None
            },
    }
}

pub fn get_int(n: &LNumeric) -> Option<int>
{
    match *n {
        NExact( Cmplx{ re: re, im: im } ) => if im.is_zero() && re.numerator() == 1 {
                Some(re.denominator())
            } else {
                None
            },
        NInexact(_) => None,
    }
}

pub fn get_uint(n: &LNumeric) -> Option<uint>
{
    match *n {
        NExact( Cmplx{ re: re, im: im } ) =>
            if im.is_zero() && re.numerator() == 1 && re.denominator() >= 0 {
                Some(re.denominator() as uint)
            } else {
                None
            },
        NInexact(_) => None,
    }
}

pub fn modulo(l: int, r: int) -> int
{
    let q = l % r;
    if q < 0 {
        if r < q {
            q
        } else {
            q + r
        }
    } else if q > 0 {
        if q < r {
            q
        } else {
            q + r
        }
    } else {
        q
    }
}

#[test]
fn test_eq() {
    assert_eq!(NRational(Rational::new(2,1)) == NRational(Rational::new(2,1)), true);
    assert_eq!(NRational(Rational::new(2,1)) < NFloat(3.0), true);
    assert_eq!(NFloat(3.0) > NRational(Rational::new(2,1)), true);
}
<commit_msg>add ApproxEq to LNumeric<commit_after>use std::num::{One, Zero};
use extra::complex::Cmplx;

use rational::Rational;

#[deriving(Eq)]
pub enum LNumeric {
    NExact(Cmplx<Rational>),
    NInexact(Cmplx<f64>)
}

impl LNumeric {
    pub fn is_inexact(&self) -> bool {
        match *self {
            NExact(_) => false,
            NInexact(_) => true,
        }
    }

    pub fn is_exact(&self) -> bool {
        match *self {
            NExact(_) => true,
            NInexact(_) => false,
        }
    }

    pub fn is_real(&self) -> bool {
        match *self {
            NExact(c) => c.im.is_zero(),
            NInexact(c) => c.im.is_zero(),
        }
    }
}

pub fn to_str(&n: &LNumeric) -> ~str {
    match n {
        NExact(Cmplx{ re: re, im: im }) => {
            if im.is_zero() {
                re.to_str()
            } else if re.is_zero() {
                im.to_str() + "i"
            } else if im.is_negative() {
                re.to_str() + im.to_str() + "i"
            } else {
                re.to_str() + "+" + im.to_str() + "i"
            }
        },
        NInexact(Cmplx{ re: re, im: im }) => {
            if im == 0f64 {
                re.to_str()
            } else if re == 0f64 {
                im.to_str() + "i"
            } else if im < 0f64 {
                re.to_str() + im.to_str() + "i"
            } else {
                re.to_str() + "+" + im.to_str() + "i"
            }
        },
    }
}

impl ApproxEq<f64> for LNumeric {
    #[inline]
    fn approx_epsilon() -> f64 {
        ApproxEq::approx_epsilon::<f64, f64>() * Real::sqrt2()
    }

    #[inline]
    fn approx_eq(&self, other: &LNumeric) -> bool
    {
        self.approx_eq_eps(other, &ApproxEq::approx_epsilon::<f64, LNumeric>())
    }

    #[inline]
    fn approx_eq_eps(&self, other: &LNumeric, approx_epsilon: &f64) -> bool
    {
        let delta = *self - *other;
        let delta2 = to_inexact(&delta).norm();
        delta2 < *approx_epsilon
    }
}

impl ToStr for LNumeric {
    fn to_str(&self) -> ~str {
        to_str(self)
    }
}

impl One for LNumeric {
    fn one() -> LNumeric {
        NExact(Cmplx { re: One::one(), im: Zero::zero() })
    }
}

impl Zero for LNumeric {
    fn zero() -> LNumeric {
        NExact(Zero::zero())
    }

    fn is_zero(&self) -> bool {
        match *self {
            NExact(cmplx) => cmplx.is_zero(),
            NInexact(cmplx) => cmplx.is_zero(),
        }
    }
}

pub fn to_inexact(&n: &LNumeric) -> Cmplx<f64> {
    match n {
        NExact(Cmplx { re: re, im: im }) => Cmplx {re: re.to_f64(), im: im.to_f64()},
        NInexact(cmplx) => cmplx
    }
}

pub fn neg(&n: &LNumeric) -> LNumeric {
    match n {
        NExact(cmplx) => NExact(-cmplx),
        NInexact(cmplx) => NInexact(-cmplx),
    }
}

impl Neg<LNumeric> for LNumeric {
    fn neg(&self) -> LNumeric {
        neg(self)
    }
}

pub fn add(&lhs: &LNumeric, &rhs: &LNumeric) -> LNumeric {
    match (lhs, rhs) {
        (NExact(cmplx0), NExact(cmplx1)) => NExact(cmplx0 + cmplx1),
        _ => {
            let cmplx0 = to_inexact(&lhs);
            let cmplx1 = to_inexact(&rhs);
            NInexact(cmplx0 + cmplx1)
        },
    }
}

impl Add<LNumeric, LNumeric> for LNumeric {
    fn add(&self, rhs: &LNumeric) -> LNumeric {
        add(self, rhs)
    }
}

pub fn sub(&lhs: &LNumeric, &rhs: &LNumeric) -> LNumeric {
    match (lhs, rhs) {
        (NExact(cmplx0), NExact(cmplx1)) => NExact(cmplx0 - cmplx1),
        _ => {
            let cmplx0 = to_inexact(&lhs);
            let cmplx1 = to_inexact(&rhs);
            NInexact(cmplx0 - cmplx1)
        },
    }
}

impl Sub<LNumeric, LNumeric> for LNumeric {
    fn sub(&self, rhs: &LNumeric) -> LNumeric {
        sub(self, rhs)
    }
}

pub fn mul(&lhs: &LNumeric, &rhs: &LNumeric) -> LNumeric {
    match (lhs, rhs) {
        (NExact(cmplx0), NExact(cmplx1)) => NExact(cmplx0 * cmplx1),
        _ => {
            let cmplx0 = to_inexact(&lhs);
            let cmplx1 = to_inexact(&rhs);
            NInexact(cmplx0 * cmplx1)
        },
    }
}

impl Mul<LNumeric, LNumeric> for LNumeric {
    fn mul(&self, rhs: &LNumeric) -> LNumeric {
        mul(self, rhs)
    }
}

pub fn div(&lhs: &LNumeric, &rhs: &LNumeric) -> LNumeric {
    match (lhs, rhs) {
        (NExact(cmplx0), NExact(cmplx1)) => NExact(cmplx0 / cmplx1),
        _ => {
            let cmplx0 = to_inexact(&lhs);
            let cmplx1 = to_inexact(&rhs);
            NInexact(cmplx0 / cmplx1)
        },
    }
}

impl Div<LNumeric, LNumeric> for LNumeric {
    fn div(&self, rhs: &LNumeric) -> LNumeric {
        div(self, rhs)
    }
}

pub fn cmplx_exp<T: Clone + Exponential + Trigonometric + Num>(c: &Cmplx<T>) -> Cmplx<T> {
    // e^(a+bi) = e^a * (cos b + i sin b)
    let pow = c.re.exp();
    Cmplx { re: c.im.cos() * pow, im: c.im.sin() * pow }
}

impl Exponential for LNumeric {
    fn exp(&self) -> LNumeric {
        NInexact( cmplx_exp( &to_inexact(self)) )
    }

    fn exp2(&self) -> LNumeric {
        let x = to_inexact(self);
        let l2 = Real::ln_2();
        NInexact( cmplx_exp( &Cmplx{ re: x.re * l2, im: x.im * l2 }) )
    }

    fn ln(&self) -> LNumeric {
        let (norm, arg) = to_inexact(self).to_polar();
        NInexact( Cmplx{ re: norm.ln(), im: arg } )
    }

    fn log(&self, base: &LNumeric) -> LNumeric {
        self.ln() / base.ln()
    }

    fn log2(&self) -> LNumeric {
        let (norm, arg) = to_inexact(self).to_polar();
        let l2 = Real::ln_2();
        NInexact( Cmplx{ re: norm.ln() / l2, im: arg / l2 } )
    }

    fn log10(&self) -> LNumeric {
        let (norm, arg) = to_inexact(self).to_polar();
        let l10 = Real::ln_10();
        NInexact( Cmplx{ re: norm.ln() / l10, im: arg / l10 } )
    }
}

pub fn from_int(n: int) -> LNumeric {
    NExact( Cmplx{ re: Rational::new(n, 1), im: Zero::zero() } )
}

pub fn from_rational(re: Rational) -> LNumeric {
    NExact( Cmplx{ re: re, im: Zero::zero() } )
}

pub fn from_f64(re: f64) -> LNumeric {
    NInexact( Cmplx{ re: re, im: 0f64 } )
}

pub fn from_real(re: &LReal) -> LNumeric {
    match *re {
        NRational(x) => from_rational(x),
        NFloat(x) => from_f64(x),
    }
}

pub fn exact(re: Rational, im: Rational) -> LNumeric {
    NExact( Cmplx { re: re, im: im } )
}

pub fn inexact(re: f64, im: f64) -> LNumeric {
    NInexact( Cmplx { re: re, im: im } )
}

pub enum LReal {
    NRational(Rational),
    NFloat(f64)
}

priv fn coerce<T>(a: &LReal, b: &LReal,
                    op_r: &fn(&Rational, &Rational) -> T,
                    op_f: &fn(f64, f64) -> T) -> T
{
    match (a, b) {
        (&NRational(ref x), &NRational(ref y)) => op_r(x, y),
        (&NRational(ref x), &NFloat(y)) => op_f(x.to_f64(), y),
        (&NFloat(x), &NRational(ref y)) => op_f(x, y.to_f64()),
        (&NFloat(x), &NFloat(y)) => op_f(x, y),
    }
}

impl Eq for LReal {
    fn eq(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x == y}, |x,y| {x == y})
    }

    fn ne(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x != y}, |x,y| {x != y})
    }
}

impl Ord for LReal {
    fn lt(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x < y}, |x,y| {x < y})
    }

    fn le(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x <= y}, |x,y| {x <= y})
    }

    fn gt(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x > y}, |x,y| {x > y})
    }

    fn ge(&self, other: &LReal) -> bool {
        coerce(self, other, |x,y| {x >= y}, |x,y| {x >= y})
    }
}

impl Round for LReal {
    fn floor(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.floor() ),
            NFloat( f ) => NFloat( f.floor() ),
        }
    }

    fn ceil(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.ceil() ),
            NFloat( f ) => NFloat( f.ceil() ),
        }
    }

    fn round(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.round() ),
            NFloat( f ) => NFloat( f.round() ),
        }
    }

    fn trunc(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.trunc() ),
            NFloat( f ) => NFloat( f.trunc() ),
        }
    }

    fn fract(&self) -> LReal {
        match *self {
            NRational( f ) => NRational( f.fract() ),
            NFloat( f ) => NFloat( f.fract() ),
        }
    }
}

pub fn get_real(n: &LNumeric) -> Option<LReal>
{
    match *n {
        NExact( Cmplx{ re: re, im: im } ) => if im.is_zero() {
                Some( NRational ( re ) )
            } else {
                None
            },
        NInexact( Cmplx{ re: re, im: im } ) => if im.is_zero() {
                Some( NFloat ( re ) )
            } else {
                None
            },
    }
}

pub fn get_int(n: &LNumeric) -> Option<int>
{
    match *n {
        NExact( Cmplx{ re: re, im: im } ) => if im.is_zero() && re.numerator() == 1 {
                Some(re.denominator())
            } else {
                None
            },
        NInexact(_) => None,
    }
}

pub fn get_uint(n: &LNumeric) -> Option<uint>
{
    match *n {
        NExact( Cmplx{ re: re, im: im } ) =>
            if im.is_zero() && re.numerator() == 1 && re.denominator() >= 0 {
                Some(re.denominator() as uint)
            } else {
                None
            },
        NInexact(_) => None,
    }
}

pub fn modulo(l: int, r: int) -> int
{
    let q = l % r;
    if q < 0 {
        if r < q {
            q
        } else {
            q + r
        }
    } else if q > 0 {
        if q < r {
            q
        } else {
            q + r
        }
    } else {
        q
    }
}

#[test]
fn test_eq() {
    assert_eq!(NRational(Rational::new(2,1)) == NRational(Rational::new(2,1)), true);
    assert_eq!(NRational(Rational::new(2,1)) < NFloat(3.0), true);
    assert_eq!(NFloat(3.0) > NRational(Rational::new(2,1)), true);
}
<|endoftext|>


<commit_before>//! Convenience wrapper for streams to switch between plain TCP and TLS at runtime.
//!
//!  There is no dependency on actual TLS implementations. Everything like
//! `native_tls` or `openssl` will work as long as there is a TLS stream supporting standard
//! `Read + Write` traits.
use pin_project::pin_project;
use std::{
    pin::Pin,
    task::{Context, Poll},
};

use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};

/// A stream that might be protected with TLS.
#[non_exhaustive]
#[pin_project(project = StreamProj)]
pub enum MaybeTlsStream<S> {
    /// Unencrypted socket stream.
    Plain(#[pin] S),
    /// Encrypted socket stream using `native-tls`.
    #[cfg(feature = "native-tls")]
    NativeTls(tokio_native_tls::TlsStream<S>),
    /// Encrypted socket stream using `rustls`.
    #[cfg(feature = "rustls-tls")]
    Rustls(tokio_rustls::client::TlsStream<S>),
}

impl<S: AsyncRead + AsyncWrite + Unpin> AsyncRead for MaybeTlsStream<S> {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut ReadBuf<'_>,
    ) -> Poll<std::io::Result<()>> {
        match self.project() {
            StreamProj::Plain(ref mut s) => Pin::new(s).poll_read(cx, buf),
            #[cfg(feature = "native-tls")]
            StreamProj::NativeTls(s) => Pin::new(s).poll_read(cx, buf),
            #[cfg(feature = "rustls-tls")]
            StreamProj::Rustls(s) => Pin::new(s).poll_read(cx, buf),
        }
    }
}

impl<S: AsyncRead + AsyncWrite + Unpin> AsyncWrite for MaybeTlsStream<S> {
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<Result<usize, std::io::Error>> {
        match self.project() {
            StreamProj::Plain(ref mut s) => Pin::new(s).poll_write(cx, buf),
            #[cfg(feature = "native-tls")]
            StreamProj::NativeTls(s) => Pin::new(s).poll_write(cx, buf),
            #[cfg(feature = "rustls-tls")]
            StreamProj::Rustls(s) => Pin::new(s).poll_write(cx, buf),
        }
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> {
        match self.project() {
            StreamProj::Plain(ref mut s) => Pin::new(s).poll_flush(cx),
            #[cfg(feature = "native-tls")]
            StreamProj::NativeTls(s) => Pin::new(s).poll_flush(cx),
            #[cfg(feature = "rustls-tls")]
            StreamProj::Rustls(s) => Pin::new(s).poll_flush(cx),
        }
    }

    fn poll_shutdown(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Result<(), std::io::Error>> {
        match self.project() {
            StreamProj::Plain(ref mut s) => Pin::new(s).poll_shutdown(cx),
            #[cfg(feature = "native-tls")]
            StreamProj::NativeTls(s) => Pin::new(s).poll_shutdown(cx),
            #[cfg(feature = "rustls-tls")]
            StreamProj::Rustls(s) => Pin::new(s).poll_shutdown(cx),
        }
    }
}
<commit_msg>Derive `Debug` trait for `MaybeTlsStream`<commit_after>//! Convenience wrapper for streams to switch between plain TCP and TLS at runtime.
//!
//!  There is no dependency on actual TLS implementations. Everything like
//! `native_tls` or `openssl` will work as long as there is a TLS stream supporting standard
//! `Read + Write` traits.
use pin_project::pin_project;
use std::{
    pin::Pin,
    task::{Context, Poll},
};

use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};

/// A stream that might be protected with TLS.
#[non_exhaustive]
#[pin_project(project = StreamProj)]
#[derive(Debug)]
pub enum MaybeTlsStream<S> {
    /// Unencrypted socket stream.
    Plain(#[pin] S),
    /// Encrypted socket stream using `native-tls`.
    #[cfg(feature = "native-tls")]
    NativeTls(tokio_native_tls::TlsStream<S>),
    /// Encrypted socket stream using `rustls`.
    #[cfg(feature = "rustls-tls")]
    Rustls(tokio_rustls::client::TlsStream<S>),
}

impl<S: AsyncRead + AsyncWrite + Unpin> AsyncRead for MaybeTlsStream<S> {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut ReadBuf<'_>,
    ) -> Poll<std::io::Result<()>> {
        match self.project() {
            StreamProj::Plain(ref mut s) => Pin::new(s).poll_read(cx, buf),
            #[cfg(feature = "native-tls")]
            StreamProj::NativeTls(s) => Pin::new(s).poll_read(cx, buf),
            #[cfg(feature = "rustls-tls")]
            StreamProj::Rustls(s) => Pin::new(s).poll_read(cx, buf),
        }
    }
}

impl<S: AsyncRead + AsyncWrite + Unpin> AsyncWrite for MaybeTlsStream<S> {
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<Result<usize, std::io::Error>> {
        match self.project() {
            StreamProj::Plain(ref mut s) => Pin::new(s).poll_write(cx, buf),
            #[cfg(feature = "native-tls")]
            StreamProj::NativeTls(s) => Pin::new(s).poll_write(cx, buf),
            #[cfg(feature = "rustls-tls")]
            StreamProj::Rustls(s) => Pin::new(s).poll_write(cx, buf),
        }
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), std::io::Error>> {
        match self.project() {
            StreamProj::Plain(ref mut s) => Pin::new(s).poll_flush(cx),
            #[cfg(feature = "native-tls")]
            StreamProj::NativeTls(s) => Pin::new(s).poll_flush(cx),
            #[cfg(feature = "rustls-tls")]
            StreamProj::Rustls(s) => Pin::new(s).poll_flush(cx),
        }
    }

    fn poll_shutdown(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Result<(), std::io::Error>> {
        match self.project() {
            StreamProj::Plain(ref mut s) => Pin::new(s).poll_shutdown(cx),
            #[cfg(feature = "native-tls")]
            StreamProj::NativeTls(s) => Pin::new(s).poll_shutdown(cx),
            #[cfg(feature = "rustls-tls")]
            StreamProj::Rustls(s) => Pin::new(s).poll_shutdown(cx),
        }
    }
}
<|endoftext|>


<commit_before>use ll;
use pa;
use pa::{PaError, PaResult};
use device::DeviceIndex;
use util::{to_pa_result, pa_time_to_duration};
use std::raw::Slice;
use std::mem;
use std::time::duration::Duration;

#[repr(u32)]
pub enum StreamCallbackResult
{
    Continue = ll::paContinue,
    Complete = ll::paComplete,
    Abort = ll::paAbort,
}

pub type StreamCallback<'a, T> = |input: &[T], output: &mut [T], timeinfo: StreamTimeInfo, StreamCallbackFlags|:'a -> StreamCallbackResult;
pub type StreamFinishedCallback<'a> = ||:'a;

struct StreamUserData<'a, T>
{
    num_input: uint,
    num_output: uint,
    callback: Option<StreamCallback<'a, T>>,
    finished_callback: Option<StreamFinishedCallback<'a>>,
}

pub struct StreamTimeInfo
{
    pub input_adc_time: Duration,
    pub current_time: Duration,
    pub output_dac_time: Duration,
}

bitflags!(
    flags StreamCallbackFlags: u64 {
        static inputUnderflow = 0x01,
        static inputOverflow = 0x02,
        static outputUnderflow = 0x04,
        static outputOverflow = 0x08,
        static primingOutput = 0x10
    }
)

bitflags!(
    flags StreamFlags: u64 {
        static ClipOff                               = 0x00000001,
        static DitherOff                             = 0x00000002,
        static NeverDropInput                        = 0x00000004,
        static PrimeOutputBuffersUsingStreamCallback = 0x00000008,
        static PlatformSpecific                      = 0xFFFF0000
    }
)

extern "C" fn stream_callback<T>(input: *const ::libc::c_void,
                                 output: *mut ::libc::c_void,
                                 frame_count: ::libc::c_ulong,
                                 time_info: *const ll::PaStreamCallbackTimeInfo,
                                 status_flags: ll::PaStreamCallbackFlags,
                                 user_data: *mut ::libc::c_void) -> ::libc::c_int
{
    let mut stream_data: Box<StreamUserData<T>> = unsafe { mem::transmute(user_data) };

    let input_buffer: &[T] = unsafe
    {
        mem::transmute(
            Slice { data: input as *const T, len: frame_count as uint * stream_data.num_input }
        )
    };
    let output_buffer: &mut [T] = unsafe
    {
        mem::transmute(
            Slice { data: output as *const T, len: frame_count as uint * stream_data.num_output }
        )
    };

    let flags = StreamCallbackFlags::from_bits_truncate(status_flags);

    let timeinfo = match unsafe { time_info.to_option() }
    {
        Some(ref info) => StreamTimeInfo { input_adc_time: pa_time_to_duration(info.inputBufferAdcTime),
                                           current_time: pa_time_to_duration(info.currentTime),
                                           output_dac_time: pa_time_to_duration(info.outputBufferDacTime) },
        None => StreamTimeInfo { input_adc_time: Duration::seconds(0),
                                 current_time: Duration::seconds(0),
                                 output_dac_time: Duration::seconds(0), },
    };

    let result = match stream_data.callback
    {
        Some(ref mut f) => (*f)(input_buffer, output_buffer, timeinfo, flags),
        None => Abort,
    };

    unsafe { mem::forget(stream_data); }

    result as i32
}

extern "C" fn stream_finished_callback<T>(user_data: *mut ::libc::c_void)
{
    let mut stream_data: Box<StreamUserData<T>> = unsafe { mem::transmute(user_data) };
    match stream_data.finished_callback
    {
        Some(ref mut f) => (*f)(),
        None => {},
    };
}

trait SampleType
{
    fn sample_format(_: Option<Self>) -> u64;
}
impl SampleType for f32 { fn sample_format(_: Option<f32>) -> u64 { 0x00000001 } }
impl SampleType for i32 { fn sample_format(_: Option<i32>) -> u64 { 0x00000002 } }
impl SampleType for i16 { fn sample_format(_: Option<i16>) -> u64 { 0x00000008 } }
impl SampleType for i8 { fn sample_format(_: Option<i8>) -> u64 { 0x00000010 } }
impl SampleType for u8 { fn sample_format(_: Option<u8>) -> u64 { 0x00000020 } }

fn get_sample_format<T: SampleType>() -> u64
{
    SampleType::sample_format(None::<T>)
}

pub fn get_sample_size<T: SampleType>() -> Result<uint, PaError>
{
    match unsafe { ll::Pa_GetSampleSize(get_sample_format::<T>()) }
    {
        n if n >= 0 => Ok(n as uint),
        m => to_pa_result(m).map(|_| 0),
    }
}

pub struct Stream<'a, T>
{
    pa_stream: *mut ll::PaStream,
    inputs: uint,
    outputs: uint,
    user_data: Box<StreamUserData<'a, T>>,
}

impl<'a, T: SampleType> Stream<'a, T>
{
    pub fn open_default(num_input_channels: uint,
                        num_output_channels: uint,
                        sample_rate: f64,
                        frames_per_buffer: u64,
                        callback: Option<StreamCallback<'a, T>>)
                       -> Result<Stream<'a, T>, PaError>
    {
        unsafe
        {
            let callback_pointer = match callback
            {
                Some(_) => Some(stream_callback::<T>),
                None => None,
            };
            let userdata = box StreamUserData
            {
                num_input: num_input_channels,
                num_output: num_output_channels,
                callback: callback,
                finished_callback: None,
            };
            let mut pa_stream = ::std::ptr::mut_null();

            let ud_pointer: *mut ::libc::c_void = ::std::mem::transmute(userdata);
            let ud_pointer_2 = ud_pointer.clone();
            let code = ll::Pa_OpenDefaultStream(&mut pa_stream as *mut *mut ll::PaStream,
                                                num_input_channels as i32,
                                                num_output_channels as i32,
                                                get_sample_format::<T>(),
                                                sample_rate,
                                                frames_per_buffer,
                                                callback_pointer,
                                                ud_pointer);
            match to_pa_result(code)
            {
                Ok(()) => Ok(Stream { pa_stream: pa_stream,
                                      user_data: ::std::mem::transmute(ud_pointer_2),
                                      inputs: num_input_channels,
                                      outputs: num_output_channels,
                             }),
                Err(v) => Err(v),
            }
        }
    }

    pub fn open(input: StreamParameters<T>,
                output: StreamParameters<T>,
                sample_rate: f64,
                frames_per_buffer: u64,
                flags: StreamFlags,
                callback: Option<StreamCallback<'a, T>>)
               -> Result<Stream<'a, T>, PaError>
    {
        unsafe
        {
            let callback_pointer = match callback
            {
                Some(_) => Some(stream_callback::<T>),
                None => None,
            };

            let user_data = box StreamUserData
            {
                num_input: input.channel_count,
                num_output: output.channel_count,
                callback: callback,
                finished_callback: None,
            };

            let mut pa_stream = ::std::ptr::mut_null();
            let ud_pointer: *mut ::libc::c_void = mem::transmute(user_data);
            let ud_pointer_2 = ud_pointer.clone();

            let result = ll::Pa_OpenStream(&mut pa_stream,
                                                  &input.to_ll(),
                                                  &output.to_ll(),
                                                  sample_rate,
                                                  frames_per_buffer,
                                                  flags.bits,
                                                  callback_pointer,
                                                  ud_pointer);
            match to_pa_result(result)
            {
                Ok(()) => Ok(Stream { pa_stream: pa_stream,
                                      user_data: mem::transmute(ud_pointer_2),
                                      inputs: input.channel_count,
                                      outputs: output.channel_count,
                          }),
                Err(v) => Err(v),
            }
        }
    }

    pub fn start(&self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_StartStream(self.pa_stream) })
    }

    pub fn stop(&self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_StopStream(self.pa_stream) })
    }

    pub fn abort(&self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_AbortStream(self.pa_stream) })
    }

    fn close(&self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_CloseStream(self.pa_stream) })
    }

    pub fn is_stopped(&self) -> Result<bool, PaError>
    {
        match unsafe { ll::Pa_IsStreamStopped(self.pa_stream) }
        {
            1 => Ok(true),
            n => to_pa_result(n).map(|_| false),
        }
    }

    pub fn is_active(&self) -> Result<bool, PaError>
    {
        match unsafe { ll::Pa_IsStreamActive(self.pa_stream) }
        {
            1 => Ok(true),
            n => to_pa_result(n).map(|_| false),
        }
    }

    pub fn read_available(&self) -> Result<uint, PaError>
    {
        match unsafe { ll::Pa_GetStreamReadAvailable(self.pa_stream) }
        {
            n if n >= 0 => { Ok(n as uint) },
            n => to_pa_result(n as i32).map(|_| 0),
        }
    }

    pub fn write_available(&self) -> Result<uint, PaError>
    {
        match unsafe { ll::Pa_GetStreamWriteAvailable(self.pa_stream) }
        {
            n if n >= 0 => { Ok(n as uint) },
            n => to_pa_result(n as i32).map(|_| 0),
        }
    }

    pub fn write(&self, buffer: &[T]) -> PaResult
    {
        if self.outputs == 0 { return Err(pa::CanNotWriteToAnInputOnlyStream) }

        let pointer = buffer.as_ptr() as *const ::libc::c_void;
        let frames = (buffer.len() / self.outputs) as u64;

        to_pa_result(unsafe { ll::Pa_WriteStream(self.pa_stream, pointer, frames) })
    }

    pub fn read(&self, buffer: &mut [T]) -> PaResult
    {
        if self.inputs == 0 { return Err(pa::CanNotReadFromAnOutputOnlyStream) }

        let pointer = buffer.as_mut_ptr() as *mut ::libc::c_void;
        let frames = (buffer.len() / self.inputs) as u64;

        to_pa_result(unsafe { ll::Pa_ReadStream(self.pa_stream, pointer, frames) })
    }

    pub fn cpu_load(&self) -> f64
    {
        unsafe { ll::Pa_GetStreamCpuLoad(self.pa_stream) }
    }

    pub fn time(&self) -> Duration
    {
        let time = unsafe { ll::Pa_GetStreamTime(self.pa_stream) };
        pa_time_to_duration(time)
    }

    pub fn info(&self) -> Option<StreamInfo>
    {
        unsafe
        {
            ll::Pa_GetStreamInfo(self.pa_stream)
                .to_option()
                .map(|s| StreamInfo::from_ll(s))
        }
    }

    pub fn set_finished_callback(&mut self, finished_callback: StreamFinishedCallback<'a>) -> PaResult
    {
        self.user_data.finished_callback = Some(finished_callback);
        let callback_pointer = Some(stream_finished_callback::<T>);
        to_pa_result(unsafe { ll::Pa_SetStreamFinishedCallback(self.pa_stream, callback_pointer) })
    }

    pub fn unset_finished_callback(&mut self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_SetStreamFinishedCallback(self.pa_stream, None) })
    }
}

#[unsafe_destructor]
impl<'a, T: SampleType> Drop for Stream<'a, T>
{
    fn drop(&mut self)
    {
        match self.close()
        {
            Err(v) => error!("Error: {}", v),
            Ok(_) => {},
        };
    }
}

pub struct StreamParameters<T>
{
    pub device: DeviceIndex,
    pub channel_count: uint,
    pub suggested_latency: Duration,
}

impl<T: SampleType> StreamParameters<T>
{
    fn to_ll(&self) -> ll::Struct_PaStreamParameters
    {
        ll::Struct_PaStreamParameters
        {
            device: self.device as i32,
            channelCount: self.channel_count as i32,
            sampleFormat: get_sample_format::<T>(),
            suggestedLatency: self.suggested_latency.num_milliseconds() as f64 / 1000.0,
            hostApiSpecificStreamInfo: ::std::ptr::mut_null(),
        }
    }
}

pub fn is_format_supported<I: SampleType, O: SampleType>(input: StreamParameters<I>, output: StreamParameters<O>, sample_rate: f64) -> PaResult
{
    to_pa_result(unsafe { ll::Pa_IsFormatSupported(&input.to_ll(), &output.to_ll(), sample_rate) })
}

pub struct StreamInfo
{
    pub input_latency: Duration,
    pub output_latency: Duration,
    pub sample_rate: f64,
}

impl StreamInfo
{
    fn from_ll(data: &ll::PaStreamInfo) -> StreamInfo
    {
        StreamInfo
        {
            input_latency: pa_time_to_duration(data.inputLatency),
            output_latency: pa_time_to_duration(data.outputLatency),
            sample_rate: data.sampleRate,
        }
    }
}

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

    // This test asserts that the sizes used by PortAudio are the same as
    // those used by Rust
    #[test]
    fn sample_sizes()
    {
        test_sample_size::<f32>();
        test_sample_size::<i32>();
        test_sample_size::<i16>();
        test_sample_size::<i8>();
        test_sample_size::<u8>();
    }

    fn test_sample_size<T: SampleType>()
    {
        use std::mem;

        let pa_size = super::get_sample_size::<T>();
        let rs_size = Ok(mem::size_of::<T>());
        assert_eq!(rs_size, pa_size);
    }

    // In the FFI some assumptions are made as to how Some(p) and None are
    // represented when used as function pointers. This test asserts these
    // assumptions.
    #[test]
    fn option_pointer()
    {
        use std::{mem, ptr};
        use libc;

        unsafe
        {
            assert!   (mem::transmute::<Option<extern "C" fn()>, *const libc::c_void>(Some(external_function)) != ptr::null());
            assert_eq!(mem::transmute::<Option<extern "C" fn()>, *const libc::c_void>(None)                    ,  ptr::null());
        }
    }

    extern "C" fn external_function() {}
}
<commit_msg>Forget the pointer in the finished callback<commit_after>use ll;
use pa;
use pa::{PaError, PaResult};
use device::DeviceIndex;
use util::{to_pa_result, pa_time_to_duration};
use std::raw::Slice;
use std::mem;
use std::time::duration::Duration;

#[repr(u32)]
pub enum StreamCallbackResult
{
    Continue = ll::paContinue,
    Complete = ll::paComplete,
    Abort = ll::paAbort,
}

pub type StreamCallback<'a, T> = |input: &[T], output: &mut [T], timeinfo: StreamTimeInfo, StreamCallbackFlags|:'a -> StreamCallbackResult;
pub type StreamFinishedCallback<'a> = ||:'a;

struct StreamUserData<'a, T>
{
    num_input: uint,
    num_output: uint,
    callback: Option<StreamCallback<'a, T>>,
    finished_callback: Option<StreamFinishedCallback<'a>>,
}

pub struct StreamTimeInfo
{
    pub input_adc_time: Duration,
    pub current_time: Duration,
    pub output_dac_time: Duration,
}

bitflags!(
    flags StreamCallbackFlags: u64 {
        static inputUnderflow = 0x01,
        static inputOverflow = 0x02,
        static outputUnderflow = 0x04,
        static outputOverflow = 0x08,
        static primingOutput = 0x10
    }
)

bitflags!(
    flags StreamFlags: u64 {
        static ClipOff                               = 0x00000001,
        static DitherOff                             = 0x00000002,
        static NeverDropInput                        = 0x00000004,
        static PrimeOutputBuffersUsingStreamCallback = 0x00000008,
        static PlatformSpecific                      = 0xFFFF0000
    }
)

extern "C" fn stream_callback<T>(input: *const ::libc::c_void,
                                 output: *mut ::libc::c_void,
                                 frame_count: ::libc::c_ulong,
                                 time_info: *const ll::PaStreamCallbackTimeInfo,
                                 status_flags: ll::PaStreamCallbackFlags,
                                 user_data: *mut ::libc::c_void) -> ::libc::c_int
{
    let mut stream_data: Box<StreamUserData<T>> = unsafe { mem::transmute(user_data) };

    let input_buffer: &[T] = unsafe
    {
        mem::transmute(
            Slice { data: input as *const T, len: frame_count as uint * stream_data.num_input }
        )
    };
    let output_buffer: &mut [T] = unsafe
    {
        mem::transmute(
            Slice { data: output as *const T, len: frame_count as uint * stream_data.num_output }
        )
    };

    let flags = StreamCallbackFlags::from_bits_truncate(status_flags);

    let timeinfo = match unsafe { time_info.to_option() }
    {
        Some(ref info) => StreamTimeInfo { input_adc_time: pa_time_to_duration(info.inputBufferAdcTime),
                                           current_time: pa_time_to_duration(info.currentTime),
                                           output_dac_time: pa_time_to_duration(info.outputBufferDacTime) },
        None => StreamTimeInfo { input_adc_time: Duration::seconds(0),
                                 current_time: Duration::seconds(0),
                                 output_dac_time: Duration::seconds(0), },
    };

    let result = match stream_data.callback
    {
        Some(ref mut f) => (*f)(input_buffer, output_buffer, timeinfo, flags),
        None => Abort,
    };

    unsafe { mem::forget(stream_data); }

    result as i32
}

extern "C" fn stream_finished_callback<T>(user_data: *mut ::libc::c_void)
{
    let mut stream_data: Box<StreamUserData<T>> = unsafe { mem::transmute(user_data) };
    match stream_data.finished_callback
    {
        Some(ref mut f) => (*f)(),
        None => {},
    };

    unsafe { mem::forget(stream_data); }
}

trait SampleType
{
    fn sample_format(_: Option<Self>) -> u64;
}
impl SampleType for f32 { fn sample_format(_: Option<f32>) -> u64 { 0x00000001 } }
impl SampleType for i32 { fn sample_format(_: Option<i32>) -> u64 { 0x00000002 } }
impl SampleType for i16 { fn sample_format(_: Option<i16>) -> u64 { 0x00000008 } }
impl SampleType for i8 { fn sample_format(_: Option<i8>) -> u64 { 0x00000010 } }
impl SampleType for u8 { fn sample_format(_: Option<u8>) -> u64 { 0x00000020 } }

fn get_sample_format<T: SampleType>() -> u64
{
    SampleType::sample_format(None::<T>)
}

pub fn get_sample_size<T: SampleType>() -> Result<uint, PaError>
{
    match unsafe { ll::Pa_GetSampleSize(get_sample_format::<T>()) }
    {
        n if n >= 0 => Ok(n as uint),
        m => to_pa_result(m).map(|_| 0),
    }
}

pub struct Stream<'a, T>
{
    pa_stream: *mut ll::PaStream,
    inputs: uint,
    outputs: uint,
    user_data: Box<StreamUserData<'a, T>>,
}

impl<'a, T: SampleType> Stream<'a, T>
{
    pub fn open_default(num_input_channels: uint,
                        num_output_channels: uint,
                        sample_rate: f64,
                        frames_per_buffer: u64,
                        callback: Option<StreamCallback<'a, T>>)
                       -> Result<Stream<'a, T>, PaError>
    {
        unsafe
        {
            let callback_pointer = match callback
            {
                Some(_) => Some(stream_callback::<T>),
                None => None,
            };
            let userdata = box StreamUserData
            {
                num_input: num_input_channels,
                num_output: num_output_channels,
                callback: callback,
                finished_callback: None,
            };
            let mut pa_stream = ::std::ptr::mut_null();

            let ud_pointer: *mut ::libc::c_void = ::std::mem::transmute(userdata);
            let ud_pointer_2 = ud_pointer.clone();
            let code = ll::Pa_OpenDefaultStream(&mut pa_stream as *mut *mut ll::PaStream,
                                                num_input_channels as i32,
                                                num_output_channels as i32,
                                                get_sample_format::<T>(),
                                                sample_rate,
                                                frames_per_buffer,
                                                callback_pointer,
                                                ud_pointer);
            match to_pa_result(code)
            {
                Ok(()) => Ok(Stream { pa_stream: pa_stream,
                                      user_data: ::std::mem::transmute(ud_pointer_2),
                                      inputs: num_input_channels,
                                      outputs: num_output_channels,
                             }),
                Err(v) => Err(v),
            }
        }
    }

    pub fn open(input: StreamParameters<T>,
                output: StreamParameters<T>,
                sample_rate: f64,
                frames_per_buffer: u64,
                flags: StreamFlags,
                callback: Option<StreamCallback<'a, T>>)
               -> Result<Stream<'a, T>, PaError>
    {
        unsafe
        {
            let callback_pointer = match callback
            {
                Some(_) => Some(stream_callback::<T>),
                None => None,
            };

            let user_data = box StreamUserData
            {
                num_input: input.channel_count,
                num_output: output.channel_count,
                callback: callback,
                finished_callback: None,
            };

            let mut pa_stream = ::std::ptr::mut_null();
            let ud_pointer: *mut ::libc::c_void = mem::transmute(user_data);
            let ud_pointer_2 = ud_pointer.clone();

            let result = ll::Pa_OpenStream(&mut pa_stream,
                                                  &input.to_ll(),
                                                  &output.to_ll(),
                                                  sample_rate,
                                                  frames_per_buffer,
                                                  flags.bits,
                                                  callback_pointer,
                                                  ud_pointer);
            match to_pa_result(result)
            {
                Ok(()) => Ok(Stream { pa_stream: pa_stream,
                                      user_data: mem::transmute(ud_pointer_2),
                                      inputs: input.channel_count,
                                      outputs: output.channel_count,
                          }),
                Err(v) => Err(v),
            }
        }
    }

    pub fn start(&self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_StartStream(self.pa_stream) })
    }

    pub fn stop(&self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_StopStream(self.pa_stream) })
    }

    pub fn abort(&self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_AbortStream(self.pa_stream) })
    }

    fn close(&self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_CloseStream(self.pa_stream) })
    }

    pub fn is_stopped(&self) -> Result<bool, PaError>
    {
        match unsafe { ll::Pa_IsStreamStopped(self.pa_stream) }
        {
            1 => Ok(true),
            n => to_pa_result(n).map(|_| false),
        }
    }

    pub fn is_active(&self) -> Result<bool, PaError>
    {
        match unsafe { ll::Pa_IsStreamActive(self.pa_stream) }
        {
            1 => Ok(true),
            n => to_pa_result(n).map(|_| false),
        }
    }

    pub fn read_available(&self) -> Result<uint, PaError>
    {
        match unsafe { ll::Pa_GetStreamReadAvailable(self.pa_stream) }
        {
            n if n >= 0 => { Ok(n as uint) },
            n => to_pa_result(n as i32).map(|_| 0),
        }
    }

    pub fn write_available(&self) -> Result<uint, PaError>
    {
        match unsafe { ll::Pa_GetStreamWriteAvailable(self.pa_stream) }
        {
            n if n >= 0 => { Ok(n as uint) },
            n => to_pa_result(n as i32).map(|_| 0),
        }
    }

    pub fn write(&self, buffer: &[T]) -> PaResult
    {
        if self.outputs == 0 { return Err(pa::CanNotWriteToAnInputOnlyStream) }

        let pointer = buffer.as_ptr() as *const ::libc::c_void;
        let frames = (buffer.len() / self.outputs) as u64;

        to_pa_result(unsafe { ll::Pa_WriteStream(self.pa_stream, pointer, frames) })
    }

    pub fn read(&self, buffer: &mut [T]) -> PaResult
    {
        if self.inputs == 0 { return Err(pa::CanNotReadFromAnOutputOnlyStream) }

        let pointer = buffer.as_mut_ptr() as *mut ::libc::c_void;
        let frames = (buffer.len() / self.inputs) as u64;

        to_pa_result(unsafe { ll::Pa_ReadStream(self.pa_stream, pointer, frames) })
    }

    pub fn cpu_load(&self) -> f64
    {
        unsafe { ll::Pa_GetStreamCpuLoad(self.pa_stream) }
    }

    pub fn time(&self) -> Duration
    {
        let time = unsafe { ll::Pa_GetStreamTime(self.pa_stream) };
        pa_time_to_duration(time)
    }

    pub fn info(&self) -> Option<StreamInfo>
    {
        unsafe
        {
            ll::Pa_GetStreamInfo(self.pa_stream)
                .to_option()
                .map(|s| StreamInfo::from_ll(s))
        }
    }

    pub fn set_finished_callback(&mut self, finished_callback: StreamFinishedCallback<'a>) -> PaResult
    {
        self.user_data.finished_callback = Some(finished_callback);
        let callback_pointer = Some(stream_finished_callback::<T>);
        to_pa_result(unsafe { ll::Pa_SetStreamFinishedCallback(self.pa_stream, callback_pointer) })
    }

    pub fn unset_finished_callback(&mut self) -> PaResult
    {
        to_pa_result(unsafe { ll::Pa_SetStreamFinishedCallback(self.pa_stream, None) })
    }
}

#[unsafe_destructor]
impl<'a, T: SampleType> Drop for Stream<'a, T>
{
    fn drop(&mut self)
    {
        match self.close()
        {
            Err(v) => error!("Error: {}", v),
            Ok(_) => {},
        };
    }
}

pub struct StreamParameters<T>
{
    pub device: DeviceIndex,
    pub channel_count: uint,
    pub suggested_latency: Duration,
}

impl<T: SampleType> StreamParameters<T>
{
    fn to_ll(&self) -> ll::Struct_PaStreamParameters
    {
        ll::Struct_PaStreamParameters
        {
            device: self.device as i32,
            channelCount: self.channel_count as i32,
            sampleFormat: get_sample_format::<T>(),
            suggestedLatency: self.suggested_latency.num_milliseconds() as f64 / 1000.0,
            hostApiSpecificStreamInfo: ::std::ptr::mut_null(),
        }
    }
}

pub fn is_format_supported<I: SampleType, O: SampleType>(input: StreamParameters<I>, output: StreamParameters<O>, sample_rate: f64) -> PaResult
{
    to_pa_result(unsafe { ll::Pa_IsFormatSupported(&input.to_ll(), &output.to_ll(), sample_rate) })
}

pub struct StreamInfo
{
    pub input_latency: Duration,
    pub output_latency: Duration,
    pub sample_rate: f64,
}

impl StreamInfo
{
    fn from_ll(data: &ll::PaStreamInfo) -> StreamInfo
    {
        StreamInfo
        {
            input_latency: pa_time_to_duration(data.inputLatency),
            output_latency: pa_time_to_duration(data.outputLatency),
            sample_rate: data.sampleRate,
        }
    }
}

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

    // This test asserts that the sizes used by PortAudio are the same as
    // those used by Rust
    #[test]
    fn sample_sizes()
    {
        test_sample_size::<f32>();
        test_sample_size::<i32>();
        test_sample_size::<i16>();
        test_sample_size::<i8>();
        test_sample_size::<u8>();
    }

    fn test_sample_size<T: SampleType>()
    {
        use std::mem;

        let pa_size = super::get_sample_size::<T>();
        let rs_size = Ok(mem::size_of::<T>());
        assert_eq!(rs_size, pa_size);
    }

    // In the FFI some assumptions are made as to how Some(p) and None are
    // represented when used as function pointers. This test asserts these
    // assumptions.
    #[test]
    fn option_pointer()
    {
        use std::{mem, ptr};
        use libc;

        unsafe
        {
            assert!   (mem::transmute::<Option<extern "C" fn()>, *const libc::c_void>(Some(external_function)) != ptr::null());
            assert_eq!(mem::transmute::<Option<extern "C" fn()>, *const libc::c_void>(None)                    ,  ptr::null());
        }
    }

    extern "C" fn external_function() {}
}
<|endoftext|>


<commit_before>use nom;
use nom::{Err, IResult};

use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::usize;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

/// FLAC stream that decodes and hold file information.
pub struct Stream {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  frames: Vec<Frame>,
  state: ParserState,
  output: Vec<i32>,
  frame_index: usize,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        output: Vec::new(),
        frame_index: 0,
      }
    }
  )
);

impl Stream {
  /// Constructor for the default state of a FLAC stream.
  ///
  /// This doesn't actually decode anything, it just hold the default values
  /// of each field.
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  /// Returns information for the current stream.
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(&mut producer, error_str)
  }

  fn from_stream_producer<P>(producer: &mut P, error_str: &str)
                             -> io::Result<Stream>
   where P: StreamProducer {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                         => break,
        Err(ErrorKind::EndOfInput)    => break,
        Err(ErrorKind::Consumed(_))   => continue,
        Err(ErrorKind::Incomplete(_)) => continue,
        Err(_)                        => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  pub fn iter(&mut self) -> Iter {
    let samples_left = self.info.total_samples;

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame<'a>(&'a mut self) -> Option<&'a [i32]> {
    if self.frames.is_empty() || self.frame_index >= self.frames.len() {
      None
    } else {
      let frame       = &self.frames[self.frame_index];
      let channels    = frame.header.channels as usize;
      let block_size  = frame.header.block_size as usize;
      let mut channel = 0;

      for subframe in &frame.subframes[0..channels] {
        let start  = channel * block_size;
        let end    = (channel + 1) * block_size;
        let output = &mut self.output[start..end];

        subframe::decode(&subframe, output);

        channel += 1;
      }

      frame::decode(frame.header.channel_assignment, &mut self.output);

      self.frame_index += 1;

      Some(&self.output[0..(block_size * channels)])
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata::block(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                               -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a> {
  stream: &'a mut Stream,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a> Iterator for Iter<'a> {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      let frame_index = self.stream.frame_index;

      if self.stream.next_frame().is_none() {
        return None;
      } else {
        let frame = &self.stream.frames[frame_index];

        self.sample_index = 0;
        self.block_size   = frame.header.block_size as usize;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel      += 1;
    self.samples_left -= 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a> IntoIterator for &'a mut Stream {
  type Item     = i32;
  type IntoIter = Iter<'a>;

  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Fix arithmetic overflow in iterator<commit_after>use nom;
use nom::{Err, IResult};

use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo, metadata_parser};
use frame::{frame_parser, Frame};
use utility::{ErrorKind, ByteStream, ReadStream, StreamProducer};

use std::io;
use std::usize;
use std::fs::File;

enum ParserState {
  Marker,
  Metadata,
  Frame,
}

/// FLAC stream that decodes and hold file information.
pub struct Stream {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  frames: Vec<Frame>,
  state: ParserState,
  output: Vec<i32>,
  frame_index: usize,
}

named!(pub stream_parser <&[u8], Stream>,
  chain!(
    blocks: metadata_parser ~
    frames: many1!(apply!(frame_parser, &blocks.0)),
    move|| {
      Stream {
        info: blocks.0,
        metadata: blocks.1,
        frames: frames,
        state: ParserState::Marker,
        output: Vec::new(),
        frame_index: 0,
      }
    }
  )
);

impl Stream {
  /// Constructor for the default state of a FLAC stream.
  ///
  /// This doesn't actually decode anything, it just hold the default values
  /// of each field.
  pub fn new() -> Stream {
    Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    }
  }

  /// Returns information for the current stream.
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  pub fn from_file(filename: &str) -> io::Result<Stream> {
    File::open(filename).and_then(|file| {
      let mut producer = ReadStream::new(file);
      let error_str    = format!("parser: couldn't parse the given file {}",
                                 filename);

      Stream::from_stream_producer(&mut producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  pub fn from_buffer(buffer: &[u8]) -> io::Result<Stream> {
    let mut producer = ByteStream::new(buffer);
    let error_str    = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(&mut producer, error_str)
  }

  fn from_stream_producer<P>(producer: &mut P, error_str: &str)
                             -> io::Result<Stream>
   where P: StreamProducer {
    let mut is_error = false;
    let mut stream   = Stream {
      info: StreamInfo::new(),
      metadata: Vec::new(),
      frames: Vec::new(),
      state: ParserState::Marker,
      output: Vec::new(),
      frame_index: 0,
    };

    loop {
      match stream.handle(producer) {
        Ok(_)                         => break,
        Err(ErrorKind::EndOfInput)    => break,
        Err(ErrorKind::Consumed(_))   => continue,
        Err(ErrorKind::Incomplete(_)) => continue,
        Err(_)                        => {
          is_error = true;

          break;
        }
      }
    }

    if !is_error {
      let channels    = stream.info.channels as usize;
      let block_size  = stream.info.max_block_size as usize;
      let output_size = block_size * channels;

      stream.output.reserve_exact(output_size);

      unsafe { stream.output.set_len(output_size) }

      Ok(stream)
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  pub fn iter(&mut self) -> Iter {
    let samples_left = self.info.total_samples;

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame<'a>(&'a mut self) -> Option<&'a [i32]> {
    if self.frames.is_empty() || self.frame_index >= self.frames.len() {
      None
    } else {
      let frame       = &self.frames[self.frame_index];
      let channels    = frame.header.channels as usize;
      let block_size  = frame.header.block_size as usize;
      let mut channel = 0;

      for subframe in &frame.subframes[0..channels] {
        let start  = channel * block_size;
        let end    = (channel + 1) * block_size;
        let output = &mut self.output[start..end];

        subframe::decode(&subframe, output);

        channel += 1;
      }

      frame::decode(frame.header.channel_assignment, &mut self.output);

      self.frame_index += 1;

      Some(&self.output[0..(block_size * channels)])
    }
  }

  fn handle_marker<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(0);

    match tag!(input, "fLaC") {
      IResult::Done(i, _)    => {
        self.state = ParserState::Metadata;

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_metadata<'a>(&mut self, input: &'a [u8])
                         -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(1);

    match metadata::block(input) {
      IResult::Done(i, block) => {
        let is_last = block.is_last;

        if let metadata::Data::StreamInfo(info) = block.data {
          self.info = info;
        } else {
          self.metadata.push(block);
        }

        if is_last {
          self.state = ParserState::Frame;
        }

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle_frame<'a>(&mut self, input: &'a [u8]) -> IResult<&'a [u8], ()> {
    let kind = nom::ErrorKind::Custom(2);

    match frame_parser(input, &self.info) {
      IResult::Done(i, frame) => {
        self.frames.push(frame);

        IResult::Error(Err::Position(kind, i))
      }
      IResult::Error(_)      => IResult::Error(Err::Code(kind)),
      IResult::Incomplete(n) => IResult::Incomplete(n),
    }
  }

  fn handle<S: StreamProducer>(&mut self, stream: &mut S)
                               -> Result<(), ErrorKind> {
    stream.parse(|input| {
      match self.state {
        ParserState::Marker   => self.handle_marker(input),
        ParserState::Metadata => self.handle_metadata(input),
        ParserState::Frame    => self.handle_frame(input),
      }
    })
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a> {
  stream: &'a mut Stream,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a> Iterator for Iter<'a> {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      let frame_index = self.stream.frame_index;

      if self.stream.next_frame().is_none() {
        return None;
      } else {
        let frame = &self.stream.frames[frame_index];

        self.sample_index = 0;
        self.block_size   = frame.header.block_size as usize;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a> IntoIterator for &'a mut Stream {
  type Item     = i32;
  type IntoIter = Iter<'a>;

  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<|endoftext|>