<commit_before>use std::borrow::Cow;
use std::fmt::Debug;
use std::net::{ToSocketAddrs, SocketAddr, SocketAddrV6, IpAddr, Ipv6Addr};
use std::str::FromStr;
use std::time::Duration;

use hyper::header::{Header, HeaderFormat};

use error::{SSDPResult, MsgError};
use header::{HeaderRef, HeaderMut, MX};
use message::{self, MessageType};
use message::ssdp::SSDPMessage;
use receiver::{SSDPReceiver, FromRawSSDP};
use net;

/// Overhead to add to device response times to account for transport time.
const NETWORK_TIMEOUT_OVERHEAD: u8 = 1;

/// Devices are required to respond within 1 second of receiving unicast message.
const DEFAULT_UNICAST_TIMEOUT: u8 = 1 + NETWORK_TIMEOUT_OVERHEAD;

/// Search request that can be sent via unicast or multicast to devices on the network.
#[derive(Debug, Clone)]
pub struct SearchRequest {
    message: SSDPMessage,
}

impl SearchRequest {
    /// Construct a new SearchRequest.
    pub fn new() -> Self {
        SearchRequest { message: SSDPMessage::new(MessageType::Search) }
    }

    /// Send this search request to a single host.
    ///
    /// Currently this sends the unicast message on all available network
    /// interfaces. This assumes that the network interfaces are operating
    /// on either different subnets or different ip address ranges.
    pub fn unicast<A: ToSocketAddrs>(&mut self, dst_addr: A) -> SSDPResult<SSDPReceiver<SearchResponse>> {
        let mode = try!(net::IpVersionMode::from_addr(&dst_addr));
        let mut connectors = try!(message::all_local_connectors(None, mode));

        // Send On All Connectors
        for connector in &mut connectors {
            try!(self.message.send(connector, &dst_addr));
        }

        let mut raw_connectors = Vec::with_capacity(connectors.len());
        raw_connectors.extend(connectors.into_iter().map(|conn| conn.deconstruct()));

        let opt_timeout = opt_unicast_timeout(self.get::<MX>());

        Ok(try!(SSDPReceiver::new(raw_connectors, opt_timeout)))
    }

    /// Send this search request to the standard multicast address:port.
    pub fn multicast(&mut self) -> SSDPResult<SSDPReceiver<SearchResponse>> {
        self.multicast_with_port(message::UPNP_MULTICAST_PORT)
    }

    /// Send this search request to the standard multicast address but a custom port
    pub fn multicast_with_port(&mut self, port: u16) -> SSDPResult<SSDPReceiver<SearchResponse>> {
        let mcast_timeout = try!(multicast_timeout(self.get::<MX>()));
        let mcast_ttl = Some(message::UPNP_MULTICAST_TTL);

        let mut connectors = try!(message::all_local_connectors(mcast_ttl, net::IpVersionMode::Any));

        // Send On All Connectors
        for conn in &mut connectors {
            match try!(conn.local_addr()) {
                SocketAddr::V4(_) => {
                    try!(self.message.send(conn, &(message::UPNP_MULTICAST_IPV4_ADDR, port)))
                }
                SocketAddr::V6(n) => {
                    try!(self.message.send(conn,
                                           &SocketAddrV6::new(try!(
                    FromStr::from_str(message::UPNP_MULTICAST_IPV6_LINK_LOCAL_ADDR)),
                                                              port,
                                                              n.flowinfo(),
                                                              n.scope_id())))
                }
            }
        }

        let mut raw_connectors = Vec::with_capacity(connectors.len());
        raw_connectors.extend(connectors.into_iter().map(|conn| conn.deconstruct()));

        Ok(try!(SSDPReceiver::new(raw_connectors, Some(mcast_timeout))))
    }
}

impl Default for SearchRequest {
    fn default() -> Self {
        SearchRequest::new()
    }
}

/// Get the require timeout to use for a multicast search request.
fn multicast_timeout(mx: Option<&MX>) -> SSDPResult<Duration> {
    match mx {
        Some(&MX(n)) => Ok(Duration::new((n + NETWORK_TIMEOUT_OVERHEAD) as u64, 0)),
        None => try!(Err(MsgError::new("Multicast Searches Require An MX Header"))),
    }
}

/// Get the default timeout to use for a unicast search request.
fn opt_unicast_timeout(mx: Option<&MX>) -> Option<Duration> {
    match mx {
        Some(&MX(n)) => Some(Duration::new((n + NETWORK_TIMEOUT_OVERHEAD) as u64, 0)),
        None => Some(Duration::new(DEFAULT_UNICAST_TIMEOUT as u64, 0)),
    }
}

impl FromRawSSDP for SearchRequest {
    fn raw_ssdp(bytes: &[u8]) -> SSDPResult<SearchRequest> {
        let message = try!(SSDPMessage::raw_ssdp(bytes));

        if message.message_type() != MessageType::Search {
            try!(Err(MsgError::new("SSDP Message Received Is Not A SearchRequest")))
        } else {
            Ok(SearchRequest { message: message })
        }
    }
}

impl HeaderRef for SearchRequest {
    fn get<H>(&self) -> Option<&H>
        where H: Header + HeaderFormat
    {
        self.message.get::<H>()
    }

    fn get_raw(&self, name: &str) -> Option<&[Vec<u8>]> {
        self.message.get_raw(name)
    }
}

impl HeaderMut for SearchRequest {
    fn set<H>(&mut self, value: H)
        where H: Header + HeaderFormat
    {
        self.message.set(value)
    }

    fn set_raw<K>(&mut self, name: K, value: Vec<Vec<u8>>)
        where K: Into<Cow<'static, str>> + Debug
    {
        self.message.set_raw(name, value)
    }
}

/// Search response that can be received or sent via unicast to devices on the network.
#[derive(Debug, Clone)]
pub struct SearchResponse {
    message: SSDPMessage,
}

impl SearchResponse {
    /// Construct a new SearchResponse.
    pub fn new() -> Self {
        SearchResponse { message: SSDPMessage::new(MessageType::Response) }
    }

    /// Send this search response to a single host.
    ///
    /// Currently this sends the unicast message on all available network
    /// interfaces. This assumes that the network interfaces are operating
    /// on either different subnets or different ip address ranges.
    pub fn unicast<A: ToSocketAddrs>(&mut self, dst_addr: A) -> SSDPResult<()> {
        let mode = try!(net::IpVersionMode::from_addr(&dst_addr));
        let mut connectors = try!(message::all_local_connectors(None, mode));

        // Send On All Connectors
        for conn in &mut connectors {
            try!(self.message.send(conn, &dst_addr));
        }

        Ok(())
    }
}

impl Default for SearchResponse {
    fn default() -> Self {
        SearchResponse::new()
    }
}

/// Search listener that can listen for search messages sent within the network.
pub struct SearchListener;

impl SearchListener {
    /// Listen for notify messages on all local network interfaces.
    pub fn listen() -> SSDPResult<SSDPReceiver<SearchRequest>> {
        SearchListener::listen_on_port(message::UPNP_MULTICAST_PORT)
    }

    /// Listen for notify messages on a custom port on all local network interfaces.
    pub fn listen_on_port(port: u16) -> SSDPResult<SSDPReceiver<SearchRequest>> {
        // Generate a list of reused sockets on the standard multicast address.
        let reuse_sockets = try!(message::map_local(|&addr| match addr {
            SocketAddr::V4(_) => {
                let mcast_ip: IpAddr = FromStr::from_str(message::UPNP_MULTICAST_IPV4_ADDR).unwrap();
                let s = try!(net::bind_reuse((mcast_ip, port)));
                debug!("Joining ipv4 multicast {} at iface: {}", mcast_ip, addr);
                try!(net::join_multicast(&s, &addr, &mcast_ip));
                Ok(Some(s))
            }
            SocketAddr::V6(n) => {
                let mcast_ip: Ipv6Addr = FromStr::from_str(message::UPNP_MULTICAST_IPV6_LINK_LOCAL_ADDR)
                                             .unwrap();
                let mut x = n.clone();
                x.set_ip(mcast_ip);
                x.set_port(port);
                let s = try!(net::bind_reuse(x));
                debug!("Joining ipv6 multicast {} at iface: {}", mcast_ip, addr);
                try!(net::join_multicast(&s, &addr, &IpAddr::V6(mcast_ip)));
                Ok(Some(s))
            }
        }));

        Ok(try!(SSDPReceiver::new(reuse_sockets, None)))
    }
}

impl FromRawSSDP for SearchResponse {
    fn raw_ssdp(bytes: &[u8]) -> SSDPResult<SearchResponse> {
        let message = try!(SSDPMessage::raw_ssdp(bytes));

        if message.message_type() != MessageType::Response {
            try!(Err(MsgError::new("SSDP Message Received Is Not A SearchResponse")))
        } else {
            Ok(SearchResponse { message: message })
        }
    }
}

impl HeaderRef for SearchResponse {
    fn get<H>(&self) -> Option<&H>
        where H: Header + HeaderFormat
    {
        self.message.get::<H>()
    }

    fn get_raw(&self, name: &str) -> Option<&[Vec<u8>]> {
        self.message.get_raw(name)
    }
}

impl HeaderMut for SearchResponse {
    fn set<H>(&mut self, value: H)
        where H: Header + HeaderFormat
    {
        self.message.set(value)
    }

    fn set_raw<K>(&mut self, name: K, value: Vec<Vec<u8>>)
        where K: Into<Cow<'static, str>> + Debug
    {
        self.message.set_raw(name, value)
    }
}

#[cfg(test)]
mod tests {
    use header::MX;

    #[test]
    fn positive_multicast_timeout() {
        super::multicast_timeout(Some(&MX(5))).unwrap();
    }

    #[test]
    fn positive_some_opt_multicast_timeout() {
        super::opt_unicast_timeout(Some(&MX(5))).unwrap();
    }

    #[test]
    fn positive_none_opt_multicast_timeout() {
        super::opt_unicast_timeout(None).unwrap();
    }

    #[test]
    #[should_panic]
    fn negative_multicast_timeout() {
        super::multicast_timeout(None).unwrap();
    }
}
<commit_msg>fix: `SearchResponse::unicast` does not work on multihomed networks<commit_after>use std::borrow::Cow;
use std::fmt::Debug;
use std::net::{ToSocketAddrs, SocketAddr, SocketAddrV6, IpAddr, Ipv6Addr};
use std::str::FromStr;
use std::time::Duration;
use std::io;

use hyper::header::{Header, HeaderFormat};

use error::{SSDPResult, MsgError};
use header::{HeaderRef, HeaderMut, MX};
use message::{self, MessageType};
use message::ssdp::SSDPMessage;
use receiver::{SSDPReceiver, FromRawSSDP};
use net;

/// Overhead to add to device response times to account for transport time.
const NETWORK_TIMEOUT_OVERHEAD: u8 = 1;

/// Devices are required to respond within 1 second of receiving unicast message.
const DEFAULT_UNICAST_TIMEOUT: u8 = 1 + NETWORK_TIMEOUT_OVERHEAD;

/// Search request that can be sent via unicast or multicast to devices on the network.
#[derive(Debug, Clone)]
pub struct SearchRequest {
    message: SSDPMessage,
}

impl SearchRequest {
    /// Construct a new SearchRequest.
    pub fn new() -> SearchRequest {
        SearchRequest { message: SSDPMessage::new(MessageType::Search) }
    }

    /// Send this search request to a single host.
    ///
    /// Currently this sends the unicast message on all available network
    /// interfaces. This assumes that the network interfaces are operating
    /// on either different subnets or different ip address ranges.
    pub fn unicast<A: ToSocketAddrs>(&mut self, dst_addr: A) -> SSDPResult<SSDPReceiver<SearchResponse>> {
        let mode = try!(net::IpVersionMode::from_addr(&dst_addr));
        let mut connectors = try!(message::all_local_connectors(None, mode));

        // Send On All Connectors
        for connector in &mut connectors {
            try!(self.message.send(connector, &dst_addr));
        }

        let mut raw_connectors = Vec::with_capacity(connectors.len());
        raw_connectors.extend(connectors.into_iter().map(|conn| conn.deconstruct()));

        let opt_timeout = opt_unicast_timeout(self.get::<MX>());

        Ok(try!(SSDPReceiver::new(raw_connectors, opt_timeout)))
    }

    /// Send this search request to the standard multicast address:port.
    pub fn multicast(&mut self) -> SSDPResult<SSDPReceiver<SearchResponse>> {
        self.multicast_with_port(message::UPNP_MULTICAST_PORT)
    }

    /// Send this search request to the standard multicast address but a custom port
    pub fn multicast_with_port(&mut self, port: u16) -> SSDPResult<SSDPReceiver<SearchResponse>> {
        let mcast_timeout = try!(multicast_timeout(self.get::<MX>()));
        let mcast_ttl = Some(message::UPNP_MULTICAST_TTL);

        let mut connectors = try!(message::all_local_connectors(mcast_ttl, net::IpVersionMode::Any));

        // Send On All Connectors
        for conn in &mut connectors {
            match try!(conn.local_addr()) {
                SocketAddr::V4(_) => {
                    try!(self.message.send(conn, &(message::UPNP_MULTICAST_IPV4_ADDR, port)))
                }
                SocketAddr::V6(n) => {
                    try!(self.message.send(conn,
                                           &SocketAddrV6::new(try!(
                    FromStr::from_str(message::UPNP_MULTICAST_IPV6_LINK_LOCAL_ADDR)),
                                                              port,
                                                              n.flowinfo(),
                                                              n.scope_id())))
                }
            }
        }

        let mut raw_connectors = Vec::with_capacity(connectors.len());
        raw_connectors.extend(connectors.into_iter().map(|conn| conn.deconstruct()));

        Ok(try!(SSDPReceiver::new(raw_connectors, Some(mcast_timeout))))
    }
}

impl Default for SearchRequest {
    fn default() -> Self {
        SearchRequest::new()
    }
}

/// Get the require timeout to use for a multicast search request.
fn multicast_timeout(mx: Option<&MX>) -> SSDPResult<Duration> {
    match mx {
        Some(&MX(n)) => Ok(Duration::new((n + NETWORK_TIMEOUT_OVERHEAD) as u64, 0)),
        None => try!(Err(MsgError::new("Multicast Searches Require An MX Header"))),
    }
}

/// Get the default timeout to use for a unicast search request.
fn opt_unicast_timeout(mx: Option<&MX>) -> Option<Duration> {
    match mx {
        Some(&MX(n)) => Some(Duration::new((n + NETWORK_TIMEOUT_OVERHEAD) as u64, 0)),
        None => Some(Duration::new(DEFAULT_UNICAST_TIMEOUT as u64, 0)),
    }
}

impl FromRawSSDP for SearchRequest {
    fn raw_ssdp(bytes: &[u8]) -> SSDPResult<SearchRequest> {
        let message = try!(SSDPMessage::raw_ssdp(bytes));

        if message.message_type() != MessageType::Search {
            try!(Err(MsgError::new("SSDP Message Received Is Not A SearchRequest")))
        } else {
            Ok(SearchRequest { message: message })
        }
    }
}

impl HeaderRef for SearchRequest {
    fn get<H>(&self) -> Option<&H>
        where H: Header + HeaderFormat
    {
        self.message.get::<H>()
    }

    fn get_raw(&self, name: &str) -> Option<&[Vec<u8>]> {
        self.message.get_raw(name)
    }
}

impl HeaderMut for SearchRequest {
    fn set<H>(&mut self, value: H)
        where H: Header + HeaderFormat
    {
        self.message.set(value)
    }

    fn set_raw<K>(&mut self, name: K, value: Vec<Vec<u8>>)
        where K: Into<Cow<'static, str>> + Debug
    {
        self.message.set_raw(name, value)
    }
}

/// Search response that can be received or sent via unicast to devices on the network.
#[derive(Debug, Clone)]
pub struct SearchResponse {
    message: SSDPMessage,
}

impl SearchResponse {
    /// Construct a new SearchResponse.
    pub fn new() -> SearchResponse {
        SearchResponse { message: SSDPMessage::new(MessageType::Response) }
    }

    /// Send this search response to a single host.
    ///
    /// Currently this sends the unicast message on all available network
    /// interfaces. This assumes that the network interfaces are operating
    /// on either different subnets or different ip address ranges.
    pub fn unicast<A: ToSocketAddrs>(&mut self, dst_addr: A) -> SSDPResult<()> {
        let mode = try!(net::IpVersionMode::from_addr(&dst_addr));
        let mut connectors = try!(message::all_local_connectors(None, mode));

        let mut success_count = 0;
        let mut error_count = 0;
        // Send On All Connectors
        for conn in &mut connectors {
            // Some routing errors are expected, not all interfaces can find the target addresses
            match self.message.send(conn, &dst_addr) {
                Ok(_) => success_count += 1,
                Err(_) => error_count += 1,
            }
        }

        if success_count == 0 && error_count > 0 {
            try!(Err(io::Error::last_os_error()));
        }

        Ok(())
    }
}

impl Default for SearchResponse {
    fn default() -> Self {
        SearchResponse::new()
    }
}

/// Search listener that can listen for search messages sent within the network.
pub struct SearchListener;

impl SearchListener {
    /// Listen for notify messages on all local network interfaces.
    pub fn listen() -> SSDPResult<SSDPReceiver<SearchRequest>> {
        SearchListener::listen_on_port(message::UPNP_MULTICAST_PORT)
    }

    /// Listen for notify messages on a custom port on all local network interfaces.
    pub fn listen_on_port(port: u16) -> SSDPResult<SSDPReceiver<SearchRequest>> {
        // Generate a list of reused sockets on the standard multicast address.
        let reuse_sockets = try!(message::map_local(|&addr| match addr {
            SocketAddr::V4(_) => {
                let mcast_ip: IpAddr = FromStr::from_str(message::UPNP_MULTICAST_IPV4_ADDR).unwrap();
                let s = try!(net::bind_reuse((mcast_ip, port)));
                debug!("Joining ipv4 multicast {} at iface: {}", mcast_ip, addr);
                try!(net::join_multicast(&s, &addr, &mcast_ip));
                Ok(Some(s))
            }
            SocketAddr::V6(n) => {
                let mcast_ip: Ipv6Addr = FromStr::from_str(message::UPNP_MULTICAST_IPV6_LINK_LOCAL_ADDR)
                                             .unwrap();
                let mut x = n.clone();
                x.set_ip(mcast_ip);
                x.set_port(port);
                let s = try!(net::bind_reuse(x));
                debug!("Joining ipv6 multicast {} at iface: {}", mcast_ip, addr);
                try!(net::join_multicast(&s, &addr, &IpAddr::V6(mcast_ip)));
                Ok(Some(s))
            }
        }));

        Ok(try!(SSDPReceiver::new(reuse_sockets, None)))
    }
}

impl FromRawSSDP for SearchResponse {
    fn raw_ssdp(bytes: &[u8]) -> SSDPResult<SearchResponse> {
        let message = try!(SSDPMessage::raw_ssdp(bytes));

        if message.message_type() != MessageType::Response {
            try!(Err(MsgError::new("SSDP Message Received Is Not A SearchResponse")))
        } else {
            Ok(SearchResponse { message: message })
        }
    }
}

impl HeaderRef for SearchResponse {
    fn get<H>(&self) -> Option<&H>
        where H: Header + HeaderFormat
    {
        self.message.get::<H>()
    }

    fn get_raw(&self, name: &str) -> Option<&[Vec<u8>]> {
        self.message.get_raw(name)
    }
}

impl HeaderMut for SearchResponse {
    fn set<H>(&mut self, value: H)
        where H: Header + HeaderFormat
    {
        self.message.set(value)
    }

    fn set_raw<K>(&mut self, name: K, value: Vec<Vec<u8>>)
        where K: Into<Cow<'static, str>> + Debug
    {
        self.message.set_raw(name, value)
    }
}

#[cfg(test)]
mod tests {
    use header::MX;

    #[test]
    fn positive_multicast_timeout() {
        super::multicast_timeout(Some(&MX(5))).unwrap();
    }

    #[test]
    fn positive_some_opt_multicast_timeout() {
        super::opt_unicast_timeout(Some(&MX(5))).unwrap();
    }

    #[test]
    fn positive_none_opt_multicast_timeout() {
        super::opt_unicast_timeout(None).unwrap();
    }

    #[test]
    #[should_panic]
    fn negative_multicast_timeout() {
        super::multicast_timeout(None).unwrap();
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Metadata {
  /// Marks whether the current metadata block is the last.
  is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  length: u32,
  /// Block data containing one of the eight different types of metadata.
  pub data: Data,
}

impl Metadata {
  pub fn new(is_last: bool, length: u32, data: Data) -> Self {
    Metadata {
      is_last: is_last,
      length: length,
      data: data,
    }
  }

  /// Return whether the current metadata block is the last.
  #[inline]
  pub fn is_last(&self) -> bool {
    self.is_last
  }
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum Data {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct StreamInfo {
  /// Minimum block size, in samples, used in the stream.
  pub min_block_size: u16,
  /// Maximum block size, in samples, used in the stream.
  pub max_block_size: u16,
  /// Minimum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub min_frame_size: u32,
  /// Maximum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub max_frame_size: u32,
  /// Sample rate in hertz (Hz).
  pub sample_rate: u32,
  /// Number of channels. FLAC supports one to eight channel.
  pub channels: u8,
  /// Bits per sample. FLAC supports four to thirty-two bits per sample.
  pub bits_per_sample: u8,
  /// Total samples in the stream. A value of zero means the number is
  /// unknown.
  pub total_samples: u64,
  /// MD5 signature of the unencoded audio data.
  pub md5_sum: [u8; 16],
}

impl StreamInfo {
  pub fn new() -> StreamInfo {
    StreamInfo {
      min_block_size: 0,
      max_block_size: 0,
      min_frame_size: 0,
      max_frame_size: 0,
      sample_rate: 0,
      channels: 0,
      bits_per_sample: 0,
      total_samples: 0,
      md5_sum: [0; 16],
    }
  }

  #[inline]
  pub fn is_varied_block_size(&self) -> bool {
    self.min_block_size != self.max_block_size
  }

  #[inline]
  pub fn is_fixed_block_size(&self) -> bool {
    self.min_block_size == self.max_block_size
  }
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  /// Registered application ID.
  pub id: String,
  /// Data used by the third-party application.
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  /// Sample number of the first sample in the target frame.
  pub sample_number: u64,
  /// Byte offset of the target frame's header.
  pub stream_offset: u64,
  /// Number of samples in the target frame.
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  /// Vendor name.
  pub vendor_string: String,
  /// Comments associated with a name, or category, followed by it's
  /// contents.
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  /// Media catalog number.
  pub media_catalog_number: String,
  /// Number of lead-in samples.
  pub lead_in: u64,
  /// Whether or not this `CueSheet` corresponds to a Compact Disc.
  pub is_cd: bool,
  /// One or more tracks.
  pub tracks: Vec<CueSheetTrack>,
}

/// Track information inside a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  /// Track offset, in samples, relative to the beginning of the FLAC audio
  /// stream.
  pub offset: u64,
  /// Track number.
  pub number: u8,
  /// Twelve digit alphanumeric code.
  pub isrc: String,
  /// Whether the cue sheet track is audio.
  pub is_audio: bool,
  /// Whether the cue sheet track is pre-emphasis.
  pub is_pre_emphasis: bool,
  /// For all tracks except the lead-out track.
  pub indices: Vec<CueSheetTrackIndex>,
}

/// An index point within a track, inside of a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  /// Offset, in samples, relative to the track offset of the index point.
  pub offset: u64,
  /// Index point number.
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  /// Picture type, based on the ID3v2 APIC frame.
  pub picture_type: PictureType,
  /// Multipurpose Internet Mail Extensions (MIME) type.
  pub mime_type: String,
  /// A string describing the picture.
  pub description: String,
  /// Width of the picture in pixels.
  pub width: u32,
  /// Height of the picture in pixels.
  pub height: u32,
  /// Color depth of the picture in bits-per-pixel.
  pub depth: u32,
  /// Number of colors used.
  pub colors: u32,
  /// Binary picture data.
  pub data: Vec<u8>,
}

/// The picture type according to the ID3v2 attached picture frame.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  /// Other picture type not categorized in this enum.
  Other,
  /// 32x32 pixels 'file icon'.
  FileIconStandard,
  /// Other, or non-standard, file icon.
  FileIcon,
  /// Cover (front).
  FrontCover,
  /// Cover (back).
  BackCover,
  /// Leaflet page.
  LeafletPage,
  /// Media, like label side of a CD.
  Media,
  /// Lead artist, lead performer, or soloist.
  LeadArtist,
  /// Artist or performer.
  Artist,
  /// Conductor.
  Conductor,
  /// Band or orchestra.
  Band,
  /// Composer.
  Composer,
  /// Lyricist or text writer.
  Lyricist,
  /// Recording location.
  RecordingLocation,
  /// During recording.
  DuringRecording,
  /// During performance.
  DuringPerformace,
  /// Movie, or video, screen capture.
  VideoScreenCapture,
  /// A bright colored fish.
  Fish,
  /// Illustration.
  Illustration,
  /// Band, or artist, logotype.
  BandLogo,
  /// Publisher, or studio, logotype.
  PublisherLogo,
}

impl fmt::Display for PictureType {
  fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    write!(formatter, "{}", match *self {
      PictureType::Other              => "Other",
      PictureType::FileIconStandard   => "File Icon (standard)",
      PictureType::FileIcon           => "File Icon",
      PictureType::FrontCover         => "Cover (front)",
      PictureType::BackCover          => "Cover (back)",
      PictureType::LeafletPage        => "Leaflet Page",
      PictureType::Media              => "Media",
      PictureType::LeadArtist         => "Lead Artist",
      PictureType::Artist             => "Arist",
      PictureType::Conductor          => "Conductor",
      PictureType::Band               => "Band",
      PictureType::Composer           => "Composer",
      PictureType::Lyricist           => "Lyricist",
      PictureType::RecordingLocation  => "Recoding Location",
      PictureType::DuringRecording    => "During Recording",
      PictureType::DuringPerformace   => "During Performace",
      PictureType::VideoScreenCapture => "Video Screen Capture",
      PictureType::Fish               => "Fish",
      PictureType::Illustration       => "Illustration",
      PictureType::BandLogo           => "Band Logo",
      PictureType::PublisherLogo      => "Publisher Logo",
    })
  }
}

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

  #[test]
  fn test_is_varied_block_size() {
    let mut info = StreamInfo::new();

    info.min_block_size = 512;
    info.max_block_size = 1024;

    assert!(info.is_varied_block_size());

    info.min_block_size = 2048;
    info.max_block_size = 2048;

    assert!(!info.is_varied_block_size());
  }

  #[test]
  fn test_is_fixed_block_size() {
    let mut info = StreamInfo::new();

    info.min_block_size = 512;
    info.max_block_size = 512;

    assert!(info.is_fixed_block_size());

    info.min_block_size = 1024;
    info.max_block_size = 2048;

    assert!(!info.is_fixed_block_size());
  }
}
<commit_msg>Export new `Type` in metadata module<commit_after>use std::collections::HashMap;
use std::fmt;

/// Data associated with a single metadata block.
#[derive(Debug)]
pub struct Metadata {
  /// Marks whether the current metadata block is the last.
  is_last: bool,
  /// The length, in bytes, of the block being parsed. This does not include
  /// the metadata block header.
  length: u32,
  /// Block data containing one of the eight different types of metadata.
  pub data: Data,
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Type {
  StreamInfo,
  Padding,
  Application,
  SeekTable,
  VorbisComment,
  CueSheet,
  Picture,
  Unknown,
}

impl Metadata {
  pub fn new(is_last: bool, length: u32, data: Data) -> Self {
    Metadata {
      is_last: is_last,
      length: length,
      data: data,
    }
  }

  /// Return whether the current metadata block is the last.
  #[inline]
  pub fn is_last(&self) -> bool {
    self.is_last
  }
}

/// General enum that hold all the different metadata block data.
#[derive(Debug, PartialEq, Eq)]
pub enum Data {
  /// Information regarding the entire audio stream.
  StreamInfo(StreamInfo),
  /// Block that represents a number of padded bytes.
  Padding(u32),
  /// Data used by third-party applications.
  Application(Application),
  /// Table of multiple points to seek, or skip, to within the FLAC file.
  SeekTable(Vec<SeekPoint>),
  /// Stores human-readable name/value pairs.
  VorbisComment(VorbisComment),
  /// Stores cue information
  CueSheet(CueSheet),
  /// Stores pictures associated with the FLAC file.
  Picture(Picture),
  /// A type of block data that isn't know or doesn't match the type above.
  Unknown(Vec<u8>),
}

/// Information regarding the entire audio stream.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct StreamInfo {
  /// Minimum block size, in samples, used in the stream.
  pub min_block_size: u16,
  /// Maximum block size, in samples, used in the stream.
  pub max_block_size: u16,
  /// Minimum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub min_frame_size: u32,
  /// Maximum frame size, in bytes, used in the stream. May be zero to imply
  /// the value isn't know.
  pub max_frame_size: u32,
  /// Sample rate in hertz (Hz).
  pub sample_rate: u32,
  /// Number of channels. FLAC supports one to eight channel.
  pub channels: u8,
  /// Bits per sample. FLAC supports four to thirty-two bits per sample.
  pub bits_per_sample: u8,
  /// Total samples in the stream. A value of zero means the number is
  /// unknown.
  pub total_samples: u64,
  /// MD5 signature of the unencoded audio data.
  pub md5_sum: [u8; 16],
}

impl StreamInfo {
  pub fn new() -> StreamInfo {
    StreamInfo {
      min_block_size: 0,
      max_block_size: 0,
      min_frame_size: 0,
      max_frame_size: 0,
      sample_rate: 0,
      channels: 0,
      bits_per_sample: 0,
      total_samples: 0,
      md5_sum: [0; 16],
    }
  }

  #[inline]
  pub fn is_varied_block_size(&self) -> bool {
    self.min_block_size != self.max_block_size
  }

  #[inline]
  pub fn is_fixed_block_size(&self) -> bool {
    self.min_block_size == self.max_block_size
  }
}

/// Data used by third-party applications.
#[derive(Debug, PartialEq, Eq)]
pub struct Application {
  /// Registered application ID.
  pub id: String,
  /// Data used by the third-party application.
  pub data: Vec<u8>,
}

/// Seek, or skip, to a point within the FLAC file.
#[derive(Debug, PartialEq, Eq)]
pub struct SeekPoint {
  /// Sample number of the first sample in the target frame.
  pub sample_number: u64,
  /// Byte offset of the target frame's header.
  pub stream_offset: u64,
  /// Number of samples in the target frame.
  pub frame_samples: u16,
}

/// Stores human-readable name/value pairs.
#[derive(Debug, PartialEq, Eq)]
pub struct VorbisComment {
  /// Vendor name.
  pub vendor_string: String,
  /// Comments associated with a name, or category, followed by it's
  /// contents.
  pub comments: HashMap<String, String>,
}

/// Stores cue information.
///
/// Generally for storing information from Compact Disk Digital Audio, but
/// can be used as a cueing mechanism for playback.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheet {
  /// Media catalog number.
  pub media_catalog_number: String,
  /// Number of lead-in samples.
  pub lead_in: u64,
  /// Whether or not this `CueSheet` corresponds to a Compact Disc.
  pub is_cd: bool,
  /// One or more tracks.
  pub tracks: Vec<CueSheetTrack>,
}

/// Track information inside a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrack {
  /// Track offset, in samples, relative to the beginning of the FLAC audio
  /// stream.
  pub offset: u64,
  /// Track number.
  pub number: u8,
  /// Twelve digit alphanumeric code.
  pub isrc: String,
  /// Whether the cue sheet track is audio.
  pub is_audio: bool,
  /// Whether the cue sheet track is pre-emphasis.
  pub is_pre_emphasis: bool,
  /// For all tracks except the lead-out track.
  pub indices: Vec<CueSheetTrackIndex>,
}

/// An index point within a track, inside of a cue sheet.
#[derive(Debug, PartialEq, Eq)]
pub struct CueSheetTrackIndex {
  /// Offset, in samples, relative to the track offset of the index point.
  pub offset: u64,
  /// Index point number.
  pub number: u8,
}

/// Stores pictures associated with the FLAC file.
///
/// More than likely these pictures will be cover art, but you can have more
/// than one within a file, which are distinguished by `PictureType`and it's
/// mime type string.
#[derive(Debug, PartialEq, Eq)]
pub struct Picture {
  /// Picture type, based on the ID3v2 APIC frame.
  pub picture_type: PictureType,
  /// Multipurpose Internet Mail Extensions (MIME) type.
  pub mime_type: String,
  /// A string describing the picture.
  pub description: String,
  /// Width of the picture in pixels.
  pub width: u32,
  /// Height of the picture in pixels.
  pub height: u32,
  /// Color depth of the picture in bits-per-pixel.
  pub depth: u32,
  /// Number of colors used.
  pub colors: u32,
  /// Binary picture data.
  pub data: Vec<u8>,
}

/// The picture type according to the ID3v2 attached picture frame.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum PictureType {
  /// Other picture type not categorized in this enum.
  Other,
  /// 32x32 pixels 'file icon'.
  FileIconStandard,
  /// Other, or non-standard, file icon.
  FileIcon,
  /// Cover (front).
  FrontCover,
  /// Cover (back).
  BackCover,
  /// Leaflet page.
  LeafletPage,
  /// Media, like label side of a CD.
  Media,
  /// Lead artist, lead performer, or soloist.
  LeadArtist,
  /// Artist or performer.
  Artist,
  /// Conductor.
  Conductor,
  /// Band or orchestra.
  Band,
  /// Composer.
  Composer,
  /// Lyricist or text writer.
  Lyricist,
  /// Recording location.
  RecordingLocation,
  /// During recording.
  DuringRecording,
  /// During performance.
  DuringPerformace,
  /// Movie, or video, screen capture.
  VideoScreenCapture,
  /// A bright colored fish.
  Fish,
  /// Illustration.
  Illustration,
  /// Band, or artist, logotype.
  BandLogo,
  /// Publisher, or studio, logotype.
  PublisherLogo,
}

impl fmt::Display for PictureType {
  fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
    write!(formatter, "{}", match *self {
      PictureType::Other              => "Other",
      PictureType::FileIconStandard   => "File Icon (standard)",
      PictureType::FileIcon           => "File Icon",
      PictureType::FrontCover         => "Cover (front)",
      PictureType::BackCover          => "Cover (back)",
      PictureType::LeafletPage        => "Leaflet Page",
      PictureType::Media              => "Media",
      PictureType::LeadArtist         => "Lead Artist",
      PictureType::Artist             => "Arist",
      PictureType::Conductor          => "Conductor",
      PictureType::Band               => "Band",
      PictureType::Composer           => "Composer",
      PictureType::Lyricist           => "Lyricist",
      PictureType::RecordingLocation  => "Recoding Location",
      PictureType::DuringRecording    => "During Recording",
      PictureType::DuringPerformace   => "During Performace",
      PictureType::VideoScreenCapture => "Video Screen Capture",
      PictureType::Fish               => "Fish",
      PictureType::Illustration       => "Illustration",
      PictureType::BandLogo           => "Band Logo",
      PictureType::PublisherLogo      => "Publisher Logo",
    })
  }
}

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

  #[test]
  fn test_is_varied_block_size() {
    let mut info = StreamInfo::new();

    info.min_block_size = 512;
    info.max_block_size = 1024;

    assert!(info.is_varied_block_size());

    info.min_block_size = 2048;
    info.max_block_size = 2048;

    assert!(!info.is_varied_block_size());
  }

  #[test]
  fn test_is_fixed_block_size() {
    let mut info = StreamInfo::new();

    info.min_block_size = 512;
    info.max_block_size = 512;

    assert!(info.is_fixed_block_size());

    info.min_block_size = 1024;
    info.max_block_size = 2048;

    assert!(!info.is_fixed_block_size());
  }
}
<|endoftext|>


<commit_before>use parsers::*;

#[deriving(Show)]
#[deriving(Eq)]
#[deriving(PartialEq)]
#[deriving(Clone)]
enum Input {
  A, B, C, D
}

//need more tests :/

#[test]
fn test_seq() {
  let input = [A, B, C, D];
  let parser = seq!(literal(A), literal(B), literal(C));
  assert_eq!( parser.parse(&input) , Ok(((A, (B, C)), input.slice_from(3))));
}

fn test_seq_map() {
  let input = [A, B];
  let parser = seq!(literal(A), literal(B) to |&: (a, b)| 5u);
  let expected = Ok( (5u, [].as_slice()) );
  assert_eq!( parser.parse(&input), expected );
}

#[test]
fn test_rep() {
  let input = [A, B, A, B, A, C];
  let parser = rep!(seq!(literal(A), literal(B)));
  let expected = Ok((
    vec![(A, B), (A, B)],
    input.slice_from(4)
  ));
  assert_eq!( parser.parse(&input), expected );
}

#[test]
fn test_or() {
  let input = [A, B, A, C];
  let parser = rep!(or!(literal(A), literal(B)));
  let expected = Ok((
    vec![A, B, A],
    input.slice_from(3)
  ));
  assert_eq!( parser.parse(&input), expected );
}

#[test]
fn test_multi_or() {
  let input = [A];
  let parser = or!(literal(A), literal(B), literal(C));
  let expected = Ok( (A, [].as_slice()) );
  assert_eq!( parser.parse(&input), expected );
}

#[test]
fn test_or_map() {
  let input = [B];
  let parser = or!(literal(A), literal(B) to |&: x| 5u);
  let expected = Ok( (5u, [].as_slice()) );
  assert_eq!( parser.parse(&input), expected );
}

#[test]
fn test_map() {
  let input = [A];
  let parser = map!(literal(A), |&: a| 5u);
  let expected = Ok( (5u, [].as_slice()) );
  assert_eq!( parser.parse(&input), expected );
}

#[test]
fn test_recursive_or() {
  let input = [A, A, C];
  fn a_seq<'a>() -> Box<Parser<'a, &'a [Input], uint> + 'a> {
    box or!(
      map!(literal(C), |&: _| 2u),
      map!(seq!(literal(A), lazy!(a_seq())), |&: (a, seq)| 1u + seq)
    )
  }
  let parser = a_seq();
  let expected = Ok( (4u, [].as_slice()) );
  assert_eq!( parser.parse(&input), expected );

}

#[test]
fn test_repsep() {
  let input = [A, B, C, B, A, A];
  let parser = repsep!(or!(literal(A), literal(C)) , literal(B));
  let expected = Ok((vec![A, C, A], input.slice_from(5)));
  assert_eq!( parser.parse(&input), expected );
}

#[test]
fn test_opt() {
  let input = [A, A, B];
  let parser = rep!(seq!(literal(A), opt!(literal(B))));
  let expected = Ok((vec![(A, None), (A, Some(B))], input.slice_from(3)));
  assert_eq!( parser.parse(&input), expected );
}

#[test]
fn test_matcher() {
  let input = [A, B, C];
  let parser = rep!(matcher!(Input : A => 4u, B => 5u));
  let expected = Ok( (vec![4u, 5u], input.slice_from(2)) );
  assert_eq!( parser.parse(&input), expected );

}

<commit_msg>fixing enum namespacing in tests for latest rust nightly<commit_after>use parsers::*;

#[deriving(Show, Eq, PartialEq, Clone)]
enum Input {
  A,
  B,
  C,
  D,
}

//need more tests :/

#[test]
fn test_seq() {
  let input = [Input::A, Input::B, Input::C, Input::D];
  let parser = seq!(literal(Input::A), literal(Input::B), literal(Input::C));
  assert_eq!( parser.parse(input.as_slice()) , Ok(((Input::A, (Input::B, Input::C)), input.slice_from(3))));
}

#[test]
fn test_seq_map() {
  let input = [Input::A, Input::B];
  let parser = seq!(literal(Input::A), literal(Input::B) to |&: (a, b)| 5u);
  let expected = Ok( (5u, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_rep() {
  let input = [Input::A, Input::B, Input::A, Input::B, Input::A, Input::C];
  let parser = rep!(seq!(literal(Input::A), literal(Input::B)));
  let expected = Ok((
    vec![(Input::A, Input::B), (Input::A, Input::B)],
    input.slice_from(4)
  ));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_or() {
  let input = [Input::A, Input::B, Input::A, Input::C];
  let parser = rep!(or!(literal(Input::A), literal(Input::B)));
  let expected = Ok((
    vec![Input::A, Input::B, Input::A],
    input.slice_from(3)
  ));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_multi_or() {
  let input = [Input::A];
  let parser = or!(literal(Input::A), literal(Input::B), literal(Input::C));
  let expected = Ok( (Input::A, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_or_map() {
  let input = [Input::B];
  let parser = or!(literal(Input::A), literal(Input::B) to |&: x| 5u);
  let expected = Ok( (5u, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_map() {
  let input = [Input::A];
  let parser = map!(literal(Input::A), |&: a| 5u);
  let expected = Ok( (5u, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_recursive_or() {
  let input = [Input::A, Input::A, Input::C];
  fn a_seq<'a>() -> Box<Parser<'a, &'a [Input], uint> + 'a> {
    box or!(
      map!(literal(Input::C), |&: _| 2u),
      map!(seq!(literal(Input::A), lazy!(a_seq())), |&: (a, seq)| 1u + seq)
    )
  }
  let parser = a_seq();
  let expected = Ok( (4u, [].as_slice()) );
  assert_eq!( parser.parse(input.as_slice()), expected );

}

#[test]
fn test_repsep() {
  let input = [Input::A, Input::B, Input::C, Input::B, Input::A, Input::A];
  let parser = repsep!(or!(literal(Input::A), literal(Input::C)) , literal(Input::B));
  let expected = Ok((vec![Input::A, Input::C, Input::A], input.slice_from(5)));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_opt() {
  let input = [Input::A, Input::A, Input::B];
  let parser = rep!(seq!(literal(Input::A), opt!(literal(Input::B))));
  let expected = Ok((vec![(Input::A, None), (Input::A, Some(Input::B))], input.slice_from(3)));
  assert_eq!( parser.parse(input.as_slice()), expected );
}

#[test]
fn test_matcher() {
  let input = [Input::A, Input::B, Input::C];
  let parser = rep!(matcher!(Input : Input::A => 4u, Input::B => 5u));
  let expected = Ok( (vec![4u, 5u], input.slice_from(2)) );
  assert_eq!( parser.parse(input.as_slice()), expected );

}

<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../../std/primitive.array.html).*

#![unstable(feature = "fixed_size_array",
            reason = "traits and impls are better expressed through generic \
                      integer constants",
            issue = "27778")]

use borrow::{Borrow, BorrowMut};
use cmp::Ordering;
use fmt;
use hash::{Hash, self};
use marker::Unsize;
use slice::{Iter, IterMut};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
///
/// The trait is marked unsafe in order to restrict implementors to fixed-size
/// arrays. User of this trait can assume that implementors have the exact
/// layout in memory of a fixed size array (for example, for unsafe
/// initialization).
///
/// Note that the traits AsRef and AsMut provide similar methods for types that
/// may not be fixed-size arrays. Implementors should prefer those traits
/// instead.
pub unsafe trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

macro_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
        }
    }
}

macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
        }
    }
}

// macro for implementing n-ary tuple functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Copy> Clone for [T; $N] {
                fn clone(&self) -> [T; $N] {
                    *self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
<commit_msg>Fix typo in doc<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../../std/primitive.array.html).*

#![unstable(feature = "fixed_size_array",
            reason = "traits and impls are better expressed through generic \
                      integer constants",
            issue = "27778")]

use borrow::{Borrow, BorrowMut};
use cmp::Ordering;
use fmt;
use hash::{Hash, self};
use marker::Unsize;
use slice::{Iter, IterMut};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
///
/// The trait is marked unsafe in order to restrict implementors to fixed-size
/// arrays. User of this trait can assume that implementors have the exact
/// layout in memory of a fixed size array (for example, for unsafe
/// initialization).
///
/// Note that the traits AsRef and AsMut provide similar methods for types that
/// may not be fixed-size arrays. Implementors should prefer those traits
/// instead.
pub unsafe trait FixedSizeArray<T> {
    /// Converts the array to immutable slice
    fn as_slice(&self) -> &[T];
    /// Converts the array to mutable slice
    fn as_mut_slice(&mut self) -> &mut [T];
}

unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
    #[inline]
    fn as_slice(&self) -> &[T] {
        self
    }
    #[inline]
    fn as_mut_slice(&mut self) -> &mut [T] {
        self
    }
}

macro_rules! __impl_slice_eq1 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq1! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Rhs> for $Lhs where A: PartialEq<B> {
            #[inline]
            fn eq(&self, other: &$Rhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Rhs) -> bool { self[..] != other[..] }
        }
    }
}

macro_rules! __impl_slice_eq2 {
    ($Lhs: ty, $Rhs: ty) => {
        __impl_slice_eq2! { $Lhs, $Rhs, Sized }
    };
    ($Lhs: ty, $Rhs: ty, $Bound: ident) => {
        __impl_slice_eq1!($Lhs, $Rhs, $Bound);

        #[stable(feature = "rust1", since = "1.0.0")]
        impl<'a, 'b, A: $Bound, B> PartialEq<$Lhs> for $Rhs where B: PartialEq<A> {
            #[inline]
            fn eq(&self, other: &$Lhs) -> bool { self[..] == other[..] }
            #[inline]
            fn ne(&self, other: &$Lhs) -> bool { self[..] != other[..] }
        }
    }
}

// macro for implementing n-element array functions and operations
macro_rules! array_impls {
    ($($N:expr)+) => {
        $(
            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsRef<[T]> for [T; $N] {
                #[inline]
                fn as_ref(&self) -> &[T] {
                    &self[..]
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T> AsMut<[T]> for [T; $N] {
                #[inline]
                fn as_mut(&mut self) -> &mut [T] {
                    &mut self[..]
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> Borrow<[T]> for [T; $N] {
                fn borrow(&self) -> &[T] {
                    self
                }
            }

            #[stable(feature = "array_borrow", since = "1.4.0")]
            impl<T> BorrowMut<[T]> for [T; $N] {
                fn borrow_mut(&mut self) -> &mut [T] {
                    self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Copy> Clone for [T; $N] {
                fn clone(&self) -> [T; $N] {
                    *self
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: Hash> Hash for [T; $N] {
                fn hash<H: hash::Hasher>(&self, state: &mut H) {
                    Hash::hash(&self[..], state)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T: fmt::Debug> fmt::Debug for [T; $N] {
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    fmt::Debug::fmt(&&self[..], f)
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a [T; $N] {
                type Item = &'a T;
                type IntoIter = Iter<'a, T>;

                fn into_iter(self) -> Iter<'a, T> {
                    self.iter()
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<'a, T> IntoIterator for &'a mut [T; $N] {
                type Item = &'a mut T;
                type IntoIter = IterMut<'a, T>;

                fn into_iter(self) -> IterMut<'a, T> {
                    self.iter_mut()
                }
            }

            // NOTE: some less important impls are omitted to reduce code bloat
            __impl_slice_eq1! { [A; $N], [B; $N] }
            __impl_slice_eq2! { [A; $N], [B] }
            __impl_slice_eq2! { [A; $N], &'b [B] }
            __impl_slice_eq2! { [A; $N], &'b mut [B] }
            // __impl_slice_eq2! { [A; $N], &'b [B; $N] }
            // __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Eq> Eq for [T; $N] { }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:PartialOrd> PartialOrd for [T; $N] {
                #[inline]
                fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
                    PartialOrd::partial_cmp(&&self[..], &&other[..])
                }
                #[inline]
                fn lt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::lt(&&self[..], &&other[..])
                }
                #[inline]
                fn le(&self, other: &[T; $N]) -> bool {
                    PartialOrd::le(&&self[..], &&other[..])
                }
                #[inline]
                fn ge(&self, other: &[T; $N]) -> bool {
                    PartialOrd::ge(&&self[..], &&other[..])
                }
                #[inline]
                fn gt(&self, other: &[T; $N]) -> bool {
                    PartialOrd::gt(&&self[..], &&other[..])
                }
            }

            #[stable(feature = "rust1", since = "1.0.0")]
            impl<T:Ord> Ord for [T; $N] {
                #[inline]
                fn cmp(&self, other: &[T; $N]) -> Ordering {
                    Ord::cmp(&&self[..], &&other[..])
                }
            }
        )+
    }
}

array_impls! {
     0  1  2  3  4  5  6  7  8  9
    10 11 12 13 14 15 16 17 18 19
    20 21 22 23 24 25 26 27 28 29
    30 31 32
}

// The Default impls cannot be generated using the array_impls! macro because
// they require array literals.

macro_rules! array_impl_default {
    {$n:expr, $t:ident $($ts:ident)*} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] where T: Default {
            fn default() -> [T; $n] {
                [$t::default(), $($ts::default()),*]
            }
        }
        array_impl_default!{($n - 1), $($ts)*}
    };
    {$n:expr,} => {
        #[stable(since = "1.4.0", feature = "array_default")]
        impl<T> Default for [T; $n] {
            fn default() -> [T; $n] { [] }
        }
    };
}

array_impl_default!{32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use std::ptr;

// We should use {u32,u64}::BYTES when they are stable;
const U32_BYTES: usize = 4;
const U64_BYTES: usize = 8;

macro_rules! number_stream(
    ($name:ident, $number_type:ty, $bytes_in_type:expr) => (
struct $name<'a> {
    start: *const $number_type,
    end: *const $number_type,
    marker: PhantomData<&'a ()>
}

impl<'a> $name<'a> {
    fn new(bytes: &'a [u8]) -> ($name<'a>, &'a [u8]) {
        let full_chunks = bytes.len() / $bytes_in_type;
        let (mine, theirs) = bytes.split_at(full_chunks * $bytes_in_type);

        let start = mine.as_ptr() as *const $number_type;
        let end = unsafe { start.offset(full_chunks as isize) };

        let me = $name {
            start: start,
            end: end,
            marker: PhantomData,
        };

        (me, theirs)
    }
}

impl<'a> Iterator for $name<'a> {
    type Item = $number_type;

    fn next(&mut self) -> Option<$number_type> {
        if self.start >= self.end { return None }

        let v: $number_type = unsafe { ptr::read(self.start) };

        self.start = unsafe { self.start.offset(1) };
        Some(v)
    }
}
));

number_stream!(U32FromBytes, u32, U32_BYTES);
number_stream!(U64FromBytes, u64, U64_BYTES);

/// Converts a slice of bytes into an iterator of numbers.
///
/// The data is always treated as little endian. Only complete ranges
/// of bytes are parsed as the number, any left-over bytes are returned.
// FIXME: Probably doesn't work on big endian machines.
pub trait NumberStreams {
    /// Reads u32s from the bytes
    fn u32_stream(&self) -> (U32FromBytes, &[u8]);
    /// Reads u64s from the bytes
    fn u64_stream(&self) -> (U64FromBytes, &[u8]);
}

impl<'a> NumberStreams for [u8] {
    fn u32_stream(&self) -> (U32FromBytes, &[u8]) { U32FromBytes::new(self) }
    fn u64_stream(&self) -> (U64FromBytes, &[u8]) { U64FromBytes::new(self) }
}

#[cfg(test)]
mod test {
    use ::std::slice;
    use super::{U32FromBytes,U32_BYTES};
    use super::{U64FromBytes,U64_BYTES};

    fn u32_slice_as_u8(values: &[u32]) -> &[u8] {
        unsafe {
            slice::from_raw_parts(
                values.as_ptr() as *const u8,
                values.len() * U32_BYTES,
            )
        }
    }

    #[test]
    fn can_read_u32_from_bytes() {
        let orig_values: &[u32] = &[0,1];
        let as_u8 = u32_slice_as_u8(orig_values);

        let (iter, rest) = U32FromBytes::new(as_u8);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert!(rest.is_empty());
    }

    #[test]
    fn can_read_u32_from_bytes_with_leftovers() {
        let orig_values: &[u32] = &[0,1];
        let mut as_u8: Vec<_> = u32_slice_as_u8(orig_values).into();
        as_u8.push(42);

        let (iter, rest) = U32FromBytes::new(&as_u8);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert_eq!(rest, [42]);
    }

    fn u64_slice_as_u8(values: &[u64]) -> &[u8] {
        unsafe {
            slice::from_raw_parts(
                values.as_ptr() as *const u8,
                values.len() * U64_BYTES,
            )
        }
    }

    #[test]
    fn can_read_u64_from_bytes() {
        let orig_values: &[u64] = &[0,1];
        let as_u8 = u64_slice_as_u8(orig_values);

        let (iter, rest) = U64FromBytes::new(as_u8);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert!(rest.is_empty());
    }

    #[test]
    fn can_read_u64_from_bytes_with_leftovers() {
        let orig_values: &[u64] = &[0,1];
        let mut as_u8: Vec<_> = u64_slice_as_u8(orig_values).into();
        as_u8.push(42);

        let (iter, rest) = U64FromBytes::new(&as_u8);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert_eq!(rest, [42]);
    }
}
<commit_msg>Specialize Iterator::{size_hint,count}<commit_after>use std::marker::PhantomData;
use std::ptr;

// We should use {u32,u64}::BYTES when they are stable;
const U32_BYTES: usize = 4;
const U64_BYTES: usize = 8;

macro_rules! number_stream(
    ($name:ident, $number_type:ty, $bytes_in_type:expr) => (
#[allow(raw_pointer_derive)]
#[derive(Debug,Copy,Clone)]
struct $name<'a> {
    start: *const $number_type,
    end: *const $number_type,
    marker: PhantomData<&'a ()>
}

impl<'a> $name<'a> {
    fn new(bytes: &'a [u8]) -> ($name<'a>, &'a [u8]) {
        let full_chunks = bytes.len() / $bytes_in_type;
        let (mine, theirs) = bytes.split_at(full_chunks * $bytes_in_type);

        let start = mine.as_ptr() as *const $number_type;
        let end = unsafe { start.offset(full_chunks as isize) };

        let me = $name {
            start: start,
            end: end,
            marker: PhantomData,
        };

        (me, theirs)
    }
}

impl<'a> Iterator for $name<'a> {
    type Item = $number_type;

    fn next(&mut self) -> Option<$number_type> {
        if self.start >= self.end { return None }

        let v: $number_type = unsafe { ptr::read(self.start) };

        self.start = unsafe { self.start.offset(1) };
        Some(v)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let cnt = self.count();
        (cnt, Some(cnt))
    }

    fn count(self) -> usize() {
        let total_bytes = self.end as usize - self.start as usize;
        total_bytes / $bytes_in_type
    }
}
));

number_stream!(U32FromBytes, u32, U32_BYTES);
number_stream!(U64FromBytes, u64, U64_BYTES);

/// Converts a slice of bytes into an iterator of numbers.
///
/// The data is always treated as little endian. Only complete ranges
/// of bytes are parsed as the number, any left-over bytes are returned.
// FIXME: Probably doesn't work on big endian machines.
pub trait NumberStreams {
    /// Reads u32s from the bytes
    fn u32_stream(&self) -> (U32FromBytes, &[u8]);
    /// Reads u64s from the bytes
    fn u64_stream(&self) -> (U64FromBytes, &[u8]);
}

impl<'a> NumberStreams for [u8] {
    fn u32_stream(&self) -> (U32FromBytes, &[u8]) { U32FromBytes::new(self) }
    fn u64_stream(&self) -> (U64FromBytes, &[u8]) { U64FromBytes::new(self) }
}

#[cfg(test)]
mod test {
    use ::std::slice;
    use super::{U32FromBytes,U32_BYTES};
    use super::{U64FromBytes,U64_BYTES};

    fn u32_slice_as_u8(values: &[u32]) -> &[u8] {
        unsafe {
            slice::from_raw_parts(
                values.as_ptr() as *const u8,
                values.len() * U32_BYTES,
            )
        }
    }

    #[test]
    fn can_read_u32_from_bytes() {
        let orig_values: &[u32] = &[0,1];
        let as_u8 = u32_slice_as_u8(orig_values);

        let (iter, rest) = U32FromBytes::new(as_u8);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert!(rest.is_empty());
    }

    #[test]
    fn can_read_u32_from_bytes_with_leftovers() {
        let orig_values: &[u32] = &[0,1];
        let mut as_u8: Vec<_> = u32_slice_as_u8(orig_values).into();
        as_u8.push(42);

        let (iter, rest) = U32FromBytes::new(&as_u8);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert_eq!(rest, [42]);
    }

    fn u64_slice_as_u8(values: &[u64]) -> &[u8] {
        unsafe {
            slice::from_raw_parts(
                values.as_ptr() as *const u8,
                values.len() * U64_BYTES,
            )
        }
    }

    #[test]
    fn can_read_u64_from_bytes() {
        let orig_values: &[u64] = &[0,1];
        let as_u8 = u64_slice_as_u8(orig_values);

        let (iter, rest) = U64FromBytes::new(as_u8);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert!(rest.is_empty());
    }

    #[test]
    fn can_read_u64_from_bytes_with_leftovers() {
        let orig_values: &[u64] = &[0,1];
        let mut as_u8: Vec<_> = u64_slice_as_u8(orig_values).into();
        as_u8.push(42);

        let (iter, rest) = U64FromBytes::new(&as_u8);
        let values: Vec<_> = iter.collect();

        assert_eq!(&values[..], &orig_values[..]);
        assert_eq!(rest, [42]);
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(any(feature = "force-inprocess", not(target_os = "macos")))]
struct Incrementor {
    last_value: u64,
}

#[cfg(any(feature = "force-inprocess", not(target_os = "macos")))]
impl Incrementor {
    fn new() -> Incrementor {
        Incrementor {
            last_value: 0
        }
    }

    fn increment(&mut self) -> u64 {
        self.last_value += 1;
        self.last_value
    }
}

#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
                                                target_os = "freebsd")))]
mod unix;

#[cfg(all(not(feature = "force-inprocess"), target_os = "macos"))]
mod macos;

#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
mod inprocess;

#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
                                                target_os = "freebsd")))]
pub use self::unix::*;

#[cfg(all(not(feature = "force-inprocess"), target_os = "macos"))]
pub use self::macos::*;

#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
pub use self::inprocess::*;

#[cfg(test)]
mod test;
<commit_msg>Restore explicit exports of platform API<commit_after>// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[cfg(any(feature = "force-inprocess", not(target_os = "macos")))]
struct Incrementor {
    last_value: u64,
}

#[cfg(any(feature = "force-inprocess", not(target_os = "macos")))]
impl Incrementor {
    fn new() -> Incrementor {
        Incrementor {
            last_value: 0
        }
    }

    fn increment(&mut self) -> u64 {
        self.last_value += 1;
        self.last_value
    }
}

#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
                                                target_os = "freebsd")))]
mod unix;

#[cfg(all(not(feature = "force-inprocess"), target_os = "macos"))]
mod macos;

#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
mod inprocess;

#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
                                                target_os = "freebsd")))]
mod os {
    pub use super::unix::*;
}

#[cfg(all(not(feature = "force-inprocess"), target_os = "macos"))]
mod os {
    pub use super::macos::*;
}

#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
mod os {
    pub use super::inprocess::*;
}

pub use self::os::{OsIpcChannel, OsIpcOneShotServer, OsIpcReceiver, OsIpcReceiverSet};
pub use self::os::{OsIpcSelectionResult, OsIpcSender, OsIpcSharedMemory};
pub use self::os::{OsOpaqueIpcChannel, channel};

#[cfg(test)]
mod test;
<|endoftext|>