<commit_before>use error::{FlacError, FlacResult};

#[deriving(Copy)]
struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32
}

/// The streaminfo metadata block, with important information about the stream.
#[deriving(Copy)]
pub struct StreamInfo {
    /// The minimum block size (in samples) used in the stream.
    pub min_block_size: u16,
    /// The maximum block size (in samples) used in the stream.
    pub max_block_size: u16,
    /// The minimum frame size (in bytes) used in the stream.
    pub min_frame_size: Option<u32>,
    /// The maximum frame size (in bytes) used in the stream.
    pub max_frame_size: Option<u32>,
    /// The sample rate in Hz.
    pub sample_rate: u32,
    /// The number of channels.
    pub n_channels: u8,
    /// The number of bits per sample.
    pub bits_per_sample: u8,
    /// The total number of inter-channel samples in the stream.
    pub n_samples: Option<u64>,
    /// MD5 signature of the unencoded audio data.
    pub md5sum: [u8, ..16]
}

/// A seek point in the seek table.
#[deriving(Copy)]
pub struct SeekPoint {
    pub sample: u64,
    pub offset: u64,
    pub n_samples: u16
}

/// A seek table to aid seeking in the stream.
pub struct SeekTable {
    seekpoints: Vec<SeekPoint>
}

/// A metadata about the flac stream.
pub enum MetadataBlock {
    StreamInfo(StreamInfo),
    Padding { length: u32 },
    Application { id: u32, data: Vec<u8> },
    SeekTable(SeekTable),
    VorbisComment, // TODO
    CueSheet, // TODO
    Picture, // TODO
    Reserved
}

fn read_metadata_block_header(input: &mut Reader)
                              -> FlacResult<MetadataBlockHeader> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte >> 7) == 1;
    let block_type = byte & 0b0111_1111;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_uint_n(3)) as u32;

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length
    };
    Ok(header)
}

fn read_metadata_block(input: &mut Reader, block_type: u8, length: u32)
                       -> FlacResult<MetadataBlock> {
    match block_type {
        0 => {
            // The streaminfo block has a fixed size of 34 bytes.
            if length == 34 {
                let streaminfo = try!(read_streaminfo_block(input));
                Ok(MetadataBlock::StreamInfo(streaminfo))
            } else {
                Err(FlacError::InvalidMetadataBlockLength)
            }
        },
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application { id: id, data: data })
        },
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        127 => {
            // This code is invalid to avoid confusion with a frame sync code.
            Err(FlacError::InvalidMetadataBlockType)
        },
        _ => {
            // Any other block type is 'reserved' at the moment of writing. The
            // reference implementation reads it as an 'unknown' block. That is
            // one way of handling it, but maybe there should be some kind of
            // 'strict' mode (configurable at compile time?) so that this can
            // be an error if desired.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Reserved)
        }
    }
}

fn read_streaminfo_block(input: &mut Reader) -> FlacResult<StreamInfo> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_uint_n(3)) as u32;
    let max_frame_size = try!(input.read_be_uint_n(3)) as u32;

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_byte());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = sample_rate_msb as u32 << 4 | sample_rate_lsb as u32 >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0b0000_0111) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_byte());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0b0000_1111;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = n_samples_msb as u64 << 32 | n_samples_lsb as u64;

    let mut md5sum = [0u8, ..16];
    try!(input.read_at_least(16, &mut md5sum));

    // Lower bounds can never be larger than upper bounds. Note that 0 indicates
    // unknown for the frame size. Also, the block size must be at least 16.
    if min_block_size > max_block_size {
        return Err(FlacError::InconsistentBounds);
    }
    if min_block_size < 16 {
        return Err(FlacError::InvalidBlockSize);
    }
    if min_frame_size > max_frame_size && max_frame_size != 0 {
        return Err(FlacError::InconsistentBounds);
    }

    // A sample rate of 0 is invalid, and the maximum sample rate is limited by
    // the structure of the frame headers to 655350 Hz.
    if sample_rate == 0 || sample_rate > 655350 {
        return Err(FlacError::InvalidSampleRate);
    }

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 { None } else { Some(min_frame_size) },
        max_frame_size: if max_frame_size == 0 { None } else { Some(max_frame_size) },
        sample_rate: sample_rate,
        n_channels: n_channels,
        bits_per_sample: bits_per_sample,
        n_samples: if n_samples == 0 { None } else { Some(n_samples) },
        md5sum: md5sum
    };
    Ok(stream_info)
}

fn read_padding_block(input: &mut Reader, length: u32) -> FlacResult<()> {
    // The specification dictates that all bits of the padding block must be 0.
    // However, the reference implementation does not issue an error when this
    // is not the case, and frankly, when you are going to skip over these
    // bytes and do nothing with them whatsoever, why waste all those CPU
    // cycles checking that the padding is valid?
    skip_block(input, length)
}

fn skip_block(input: &mut Reader, length: u32) -> FlacResult<()> {
    for _ in range(0, length) {
        try!(input.read_byte());
    }

    Ok(())
}

fn read_application_block(input: &mut Reader, length: u32)
                          -> FlacResult<(u32, Vec<u8>)> {
    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    let data = try!(input.read_exact((length - 4) as uint));

    Ok((id, data))
}

/// Reads metadata blocks from a stream and exposes them as an iterator.
///
/// It is assumed that the next byte that the reader will read, is the first
/// byte of a metadata block header. This means that the iterator will yield at
/// least a single value. If the iterator ever yields an error, then no more
/// data will be read thereafter, and the next value will be `None`.
pub struct MetadataBlockReader<'r, R> where R: 'r {
    input: &'r mut R,
    done: bool
}

/// Either a `MetadataBlock` or a `FlacError`.
pub type MetadataBlockResult = FlacResult<MetadataBlock>;

impl<'r, R> MetadataBlockReader<'r, R> where R: Reader {

    /// Creates a metadata block reader that will yield at least one element.
    pub fn new(input: &'r mut R) -> MetadataBlockReader<'r, R> {
        MetadataBlockReader { input: input, done: false }
    }

    fn read_next(&mut self) -> MetadataBlockResult {
        let header = try!(read_metadata_block_header(self.input));
        let block = try!(read_metadata_block(self.input, header.block_type,
                                                         header.length));
        self.done = header.is_last;
        Ok(block)
    }
}

impl<'r, R> Iterator<MetadataBlockResult>
    for MetadataBlockReader<'r, R> where R: Reader {

    fn next(&mut self) -> Option<MetadataBlockResult> {
        if self.done {
            None
        } else {
            let block = self.read_next();

            // After a failure, no more attempts to read will be made,
            // because we don't know where we are in the stream.
            if !block.is_ok() { self.done = true; }

            Some(block)
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        // When done, there will be no more blocks,
        // when not done, there will be at least one more.
        if self.done {
            (0, Some(0))
        } else {
            (1, None)
        }
    }
}
<commit_msg>fix lifetime errors for latest rustc nightly<commit_after>use error::{FlacError, FlacResult};

#[deriving(Copy)]
struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32
}

/// The streaminfo metadata block, with important information about the stream.
#[deriving(Copy)]
pub struct StreamInfo {
    /// The minimum block size (in samples) used in the stream.
    pub min_block_size: u16,
    /// The maximum block size (in samples) used in the stream.
    pub max_block_size: u16,
    /// The minimum frame size (in bytes) used in the stream.
    pub min_frame_size: Option<u32>,
    /// The maximum frame size (in bytes) used in the stream.
    pub max_frame_size: Option<u32>,
    /// The sample rate in Hz.
    pub sample_rate: u32,
    /// The number of channels.
    pub n_channels: u8,
    /// The number of bits per sample.
    pub bits_per_sample: u8,
    /// The total number of inter-channel samples in the stream.
    pub n_samples: Option<u64>,
    /// MD5 signature of the unencoded audio data.
    pub md5sum: [u8, ..16]
}

/// A seek point in the seek table.
#[deriving(Copy)]
pub struct SeekPoint {
    pub sample: u64,
    pub offset: u64,
    pub n_samples: u16
}

/// A seek table to aid seeking in the stream.
pub struct SeekTable {
    seekpoints: Vec<SeekPoint>
}

/// A metadata about the flac stream.
pub enum MetadataBlock {
    StreamInfo(StreamInfo),
    Padding { length: u32 },
    Application { id: u32, data: Vec<u8> },
    SeekTable(SeekTable),
    VorbisComment, // TODO
    CueSheet, // TODO
    Picture, // TODO
    Reserved
}

fn read_metadata_block_header(input: &mut Reader)
                              -> FlacResult<MetadataBlockHeader> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte >> 7) == 1;
    let block_type = byte & 0b0111_1111;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_uint_n(3)) as u32;

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length
    };
    Ok(header)
}

fn read_metadata_block(input: &mut Reader, block_type: u8, length: u32)
                       -> FlacResult<MetadataBlock> {
    match block_type {
        0 => {
            // The streaminfo block has a fixed size of 34 bytes.
            if length == 34 {
                let streaminfo = try!(read_streaminfo_block(input));
                Ok(MetadataBlock::StreamInfo(streaminfo))
            } else {
                Err(FlacError::InvalidMetadataBlockLength)
            }
        },
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application { id: id, data: data })
        },
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        127 => {
            // This code is invalid to avoid confusion with a frame sync code.
            Err(FlacError::InvalidMetadataBlockType)
        },
        _ => {
            // Any other block type is 'reserved' at the moment of writing. The
            // reference implementation reads it as an 'unknown' block. That is
            // one way of handling it, but maybe there should be some kind of
            // 'strict' mode (configurable at compile time?) so that this can
            // be an error if desired.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Reserved)
        }
    }
}

fn read_streaminfo_block(input: &mut Reader) -> FlacResult<StreamInfo> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_uint_n(3)) as u32;
    let max_frame_size = try!(input.read_be_uint_n(3)) as u32;

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_byte());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = sample_rate_msb as u32 << 4 | sample_rate_lsb as u32 >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0b0000_0111) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_byte());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0b0000_1111;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = n_samples_msb as u64 << 32 | n_samples_lsb as u64;

    let mut md5sum = [0u8, ..16];
    try!(input.read_at_least(16, &mut md5sum));

    // Lower bounds can never be larger than upper bounds. Note that 0 indicates
    // unknown for the frame size. Also, the block size must be at least 16.
    if min_block_size > max_block_size {
        return Err(FlacError::InconsistentBounds);
    }
    if min_block_size < 16 {
        return Err(FlacError::InvalidBlockSize);
    }
    if min_frame_size > max_frame_size && max_frame_size != 0 {
        return Err(FlacError::InconsistentBounds);
    }

    // A sample rate of 0 is invalid, and the maximum sample rate is limited by
    // the structure of the frame headers to 655350 Hz.
    if sample_rate == 0 || sample_rate > 655350 {
        return Err(FlacError::InvalidSampleRate);
    }

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 { None } else { Some(min_frame_size) },
        max_frame_size: if max_frame_size == 0 { None } else { Some(max_frame_size) },
        sample_rate: sample_rate,
        n_channels: n_channels,
        bits_per_sample: bits_per_sample,
        n_samples: if n_samples == 0 { None } else { Some(n_samples) },
        md5sum: md5sum
    };
    Ok(stream_info)
}

fn read_padding_block(input: &mut Reader, length: u32) -> FlacResult<()> {
    // The specification dictates that all bits of the padding block must be 0.
    // However, the reference implementation does not issue an error when this
    // is not the case, and frankly, when you are going to skip over these
    // bytes and do nothing with them whatsoever, why waste all those CPU
    // cycles checking that the padding is valid?
    skip_block(input, length)
}

fn skip_block(input: &mut Reader, length: u32) -> FlacResult<()> {
    for _ in range(0, length) {
        try!(input.read_byte());
    }

    Ok(())
}

fn read_application_block(input: &mut Reader, length: u32)
                          -> FlacResult<(u32, Vec<u8>)> {
    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    let data = try!(input.read_exact((length - 4) as uint));

    Ok((id, data))
}

/// Reads metadata blocks from a stream and exposes them as an iterator.
///
/// It is assumed that the next byte that the reader will read, is the first
/// byte of a metadata block header. This means that the iterator will yield at
/// least a single value. If the iterator ever yields an error, then no more
/// data will be read thereafter, and the next value will be `None`.
pub struct MetadataBlockReader<'r, R> where R: 'r {
    input: &'r mut R,
    done: bool
}

/// Either a `MetadataBlock` or a `FlacError`.
pub type MetadataBlockResult = FlacResult<MetadataBlock>;

impl<'r, R> MetadataBlockReader<'r, R> where R: Reader + 'r {

    /// Creates a metadata block reader that will yield at least one element.
    pub fn new(input: &'r mut R) -> MetadataBlockReader<'r, R> {
        MetadataBlockReader { input: input, done: false }
    }

    fn read_next(&mut self) -> MetadataBlockResult {
        let header = try!(read_metadata_block_header(self.input));
        let block = try!(read_metadata_block(self.input, header.block_type,
                                                         header.length));
        self.done = header.is_last;
        Ok(block)
    }
}

impl<'r, R> Iterator<MetadataBlockResult>
    for MetadataBlockReader<'r, R> where R: Reader + 'r {

    fn next(&mut self) -> Option<MetadataBlockResult> {
        if self.done {
            None
        } else {
            let block = self.read_next();

            // After a failure, no more attempts to read will be made,
            // because we don't know where we are in the stream.
            if !block.is_ok() { self.done = true; }

            Some(block)
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        // When done, there will be no more blocks,
        // when not done, there will be at least one more.
        if self.done {
            (0, Some(0))
        } else {
            (1, None)
        }
    }
}
<|endoftext|>


<commit_before>//! Defines the `IntoIter` owned iterator for arrays.

use crate::{
    fmt,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
    mem::{self, MaybeUninit},
    ops::Range,
    ptr,
};

/// A by-value [array] iterator.
///
/// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "65798")]
pub struct IntoIter<T, const N: usize> {
    /// This is the array we are iterating over.
    ///
    /// Elements with index `i` where `alive.start <= i < alive.end` have not
    /// been yielded yet and are valid array entries. Elements with indices `i
    /// < alive.start` or `i >= alive.end` have been yielded already and must
    /// not be accessed anymore! Those dead elements might even be in a
    /// completely uninitialized state!
    ///
    /// So the invariants are:
    /// - `data[alive]` is alive (i.e. contains valid elements)
    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
    ///   elements were already read and must not be touched anymore!)
    data: [MaybeUninit<T>; N],

    /// The elements in `data` that have not been yielded yet.
    ///
    /// Invariants:
    /// - `alive.start <= alive.end`
    /// - `alive.end <= N`
    alive: Range<usize>,
}

impl<T, const N: usize> IntoIter<T, N> {
    /// Creates a new iterator over the given `array`.
    ///
    /// *Note*: this method might never get stabilized and/or removed in the
    /// future as there will likely be another, preferred way of obtaining this
    /// iterator (either via `IntoIterator` for arrays or via another way).
    #[unstable(feature = "array_value_iter", issue = "65798")]
    pub fn new(array: [T; N]) -> Self {
        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
        // promise:
        //
        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
        // > as `T`.
        //
        // The docs even show a transmute from an array of `MaybeUninit<T>` to
        // an array of `T`.
        //
        // With that, this initialization satisfies the invariants.

        // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
        // works with const generics:
        //     `mem::transmute::<[T; {N}], [MaybeUninit<T>; {N}]>(array)`
        //
        // Until then, we do it manually here. We first create a bitwise copy
        // but cast the pointer so that it is treated as a different type. Then
        // we forget `array` so that it is not dropped.
        let data = unsafe {
            let data = ptr::read(&array as *const [T; N] as *const [MaybeUninit<T>; N]);
            mem::forget(array);
            data
        };

        Self { data, alive: 0..N }
    }

    /// Returns an immutable slice of all elements that have not been yielded
    /// yet.
    fn as_slice(&self) -> &[T] {
        let slice = &self.data[self.alive.clone()];
        // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
        // the size and alignment of `T`. Furthermore, we know that all
        // elements within `alive` are properly initialized.
        unsafe { mem::transmute::<&[MaybeUninit<T>], &[T]>(slice) }
    }

    /// Returns a mutable slice of all elements that have not been yielded yet.
    fn as_mut_slice(&mut self) -> &mut [T] {
        // This transmute is safe, same as in `as_slice` above.
        let slice = &mut self.data[self.alive.clone()];
        // SAFETY: This transmute is safe. As mentioned in `new`, `MaybeUninit` retains
        // the size and alignment of `T`. Furthermore, we know that all
        // elements within `alive` are properly initialized.
        unsafe { mem::transmute::<&mut [MaybeUninit<T>], &mut [T]>(slice) }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, N> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Bump start index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. Increasing `alive.start` by 1
        // maintains the invariant regarding `alive`. However, due to this
        // change, for a short time, the alive zone is not `data[alive]`
        // anymore, but `data[idx..alive.end]`.
        let idx = self.alive.start;
        self.alive.start += 1;

        // Read the element from the array.
        // SAFETY: This is safe: `idx` is an index
        // into the "alive" region of the array. Reading this element means
        // that `data[idx]` is regarded as dead now (i.e. do not touch). As
        // `idx` was the start of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(idx).read() };

        Some(out)
    }

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

    fn count(self) -> usize {
        self.len()
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.alive.start == self.alive.end {
            return None;
        }

        // Decrease end index.
        //
        // From the check above we know that `alive.start != alive.end`.
        // Combine this with the invariant `alive.start <= alive.end`, we know
        // that `alive.start < alive.end`. As `alive.start` cannot be negative,
        // `alive.end` is at least 1, meaning that we can safely decrement it
        // by one. This also maintains the invariant `alive.start <=
        // alive.end`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[alive.start..alive.end
        // + 1]`.
        self.alive.end -= 1;

        // Read the element from the array.
        // SAFETY: This is safe: `alive.end` is an
        // index into the "alive" region of the array. Compare the previous
        // comment that states that the alive region is
        // `data[alive.start..alive.end + 1]`. Reading this element means that
        // `data[alive.end]` is regarded as dead now (i.e. do not touch). As
        // `alive.end` was the end of the alive-zone, the alive zone is now
        // `data[alive]` again, restoring all invariants.
        let out = unsafe { self.data.get_unchecked(self.alive.end).read() };

        Some(out)
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, N> {
    fn drop(&mut self) {
        // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
        // of elements that have not been moved out yet and that remain
        // to be dropped.
        unsafe { ptr::drop_in_place(self.as_mut_slice()) }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
    fn len(&self) -> usize {
        // Will never underflow due to the invariant `alive.start <=
        // alive.end`.
        self.alive.end - self.alive.start
    }
    fn is_empty(&self) -> bool {
        self.alive.is_empty()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}

// The iterator indeed reports the correct length. The number of "alive"
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
    fn clone(&self) -> Self {
        // SAFETY: each point of unsafety is documented inside the unsafe block
        unsafe {
            // This creates a new uninitialized array. Note that the `assume_init`
            // refers to the array, not the individual elements. And it is Ok if
            // the array is in an uninitialized state as all elements may be
            // uninitialized (all bit patterns are valid). Compare the
            // `MaybeUninit` docs for more information.
            let mut new_data: [MaybeUninit<T>; N] = MaybeUninit::uninit().assume_init();

            // Clone all alive elements.
            for idx in self.alive.clone() {
                // The element at `idx` in the old array is alive, so we can
                // safely call `get_ref()`. We then clone it, and write the
                // clone into the new array.
                let clone = self.data.get_unchecked(idx).get_ref().clone();
                new_data.get_unchecked_mut(idx).write(clone);
            }

            Self { data: new_data, alive: self.alive.clone() }
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Only print the elements that were not yielded yet: we cannot
        // access the yielded elements anymore.
        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
    }
}
<commit_msg>Auto merge of #75271 - cuviper:array-iter, r=LukasKalbertodt<commit_after>//! Defines the `IntoIter` owned iterator for arrays.

use crate::{
    fmt,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
    mem::{self, MaybeUninit},
    ops::Range,
    ptr,
};

/// A by-value [array] iterator.
///
/// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "65798")]
pub struct IntoIter<T, const N: usize> {
    /// This is the array we are iterating over.
    ///
    /// Elements with index `i` where `alive.start <= i < alive.end` have not
    /// been yielded yet and are valid array entries. Elements with indices `i
    /// < alive.start` or `i >= alive.end` have been yielded already and must
    /// not be accessed anymore! Those dead elements might even be in a
    /// completely uninitialized state!
    ///
    /// So the invariants are:
    /// - `data[alive]` is alive (i.e. contains valid elements)
    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
    ///   elements were already read and must not be touched anymore!)
    data: [MaybeUninit<T>; N],

    /// The elements in `data` that have not been yielded yet.
    ///
    /// Invariants:
    /// - `alive.start <= alive.end`
    /// - `alive.end <= N`
    alive: Range<usize>,
}

impl<T, const N: usize> IntoIter<T, N> {
    /// Creates a new iterator over the given `array`.
    ///
    /// *Note*: this method might never get stabilized and/or removed in the
    /// future as there will likely be another, preferred way of obtaining this
    /// iterator (either via `IntoIterator` for arrays or via another way).
    #[unstable(feature = "array_value_iter", issue = "65798")]
    pub fn new(array: [T; N]) -> Self {
        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
        // promise:
        //
        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
        // > as `T`.
        //
        // The docs even show a transmute from an array of `MaybeUninit<T>` to
        // an array of `T`.
        //
        // With that, this initialization satisfies the invariants.

        // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
        // works with const generics:
        //     `mem::transmute::<[T; N], [MaybeUninit<T>; N]>(array)`
        //
        // Until then, we can use `mem::transmute_copy` to create a bitwise copy
        // as a different type, then forget `array` so that it is not dropped.
        unsafe {
            let iter = Self { data: mem::transmute_copy(&array), alive: 0..N };
            mem::forget(array);
            iter
        }
    }

    /// Returns an immutable slice of all elements that have not been yielded
    /// yet.
    fn as_slice(&self) -> &[T] {
        // SAFETY: We know that all elements within `alive` are properly initialized.
        unsafe {
            let slice = self.data.get_unchecked(self.alive.clone());
            MaybeUninit::slice_get_ref(slice)
        }
    }

    /// Returns a mutable slice of all elements that have not been yielded yet.
    fn as_mut_slice(&mut self) -> &mut [T] {
        // SAFETY: We know that all elements within `alive` are properly initialized.
        unsafe {
            let slice = self.data.get_unchecked_mut(self.alive.clone());
            MaybeUninit::slice_get_mut(slice)
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, N> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        // Get the next index from the front.
        //
        // Increasing `alive.start` by 1 maintains the invariant regarding
        // `alive`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[idx..alive.end]`.
        self.alive.next().map(|idx| {
            // Read the element from the array.
            // SAFETY: `idx` is an index into the former "alive" region of the
            // array. Reading this element means that `data[idx]` is regarded as
            // dead now (i.e. do not touch). As `idx` was the start of the
            // alive-zone, the alive zone is now `data[alive]` again, restoring
            // all invariants.
            unsafe { self.data.get_unchecked(idx).read() }
        })
    }

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

    fn count(self) -> usize {
        self.len()
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
    fn next_back(&mut self) -> Option<Self::Item> {
        // Get the next index from the back.
        //
        // Decreasing `alive.end` by 1 maintains the invariant regarding
        // `alive`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`.
        self.alive.next_back().map(|idx| {
            // Read the element from the array.
            // SAFETY: `idx` is an index into the former "alive" region of the
            // array. Reading this element means that `data[idx]` is regarded as
            // dead now (i.e. do not touch). As `idx` was the end of the
            // alive-zone, the alive zone is now `data[alive]` again, restoring
            // all invariants.
            unsafe { self.data.get_unchecked(idx).read() }
        })
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, N> {
    fn drop(&mut self) {
        // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
        // of elements that have not been moved out yet and that remain
        // to be dropped.
        unsafe { ptr::drop_in_place(self.as_mut_slice()) }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
    fn len(&self) -> usize {
        // Will never underflow due to the invariant `alive.start <=
        // alive.end`.
        self.alive.end - self.alive.start
    }
    fn is_empty(&self) -> bool {
        self.alive.is_empty()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}

// The iterator indeed reports the correct length. The number of "alive"
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
    fn clone(&self) -> Self {
        // Note, we don't really need to match the exact same alive range, so
        // we can just clone into offset 0 regardless of where `self` is.
        let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 };

        // Clone all alive elements.
        for (src, dst) in self.as_slice().iter().zip(&mut new.data) {
            // Write a clone into the new array, then update its alive range.
            // If cloning panics, we'll correctly drop the previous items.
            dst.write(src.clone());
            new.alive.end += 1;
        }

        new
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Only print the elements that were not yielded yet: we cannot
        // access the yielded elements anymore.
        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
    }
}
<|endoftext|>


<commit_before>#![unstable(reason = "not public", issue = "none", feature = "fd")]

use crate::cmp;
use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
use crate::mem;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::cvt;
use crate::sys_common::AsInner;

use libc::{c_int, c_void};

#[derive(Debug)]
pub struct FileDesc {
    fd: c_int,
}

// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`,
// with the man page quoting that if the count of bytes to read is
// greater than `SSIZE_MAX` the result is "unspecified".
//
// On macOS, however, apparently the 64-bit libc is either buggy or
// intentionally showing odd behavior by rejecting any read with a size
// larger than or equal to INT_MAX. To handle both of these the read
// size is capped on both platforms.
#[cfg(target_os = "macos")]
const READ_LIMIT: usize = c_int::MAX as usize - 1;
#[cfg(not(target_os = "macos"))]
const READ_LIMIT: usize = libc::ssize_t::MAX as usize;

#[cfg(any(target_os = "linux", target_os = "macos"))]
fn max_iov() -> usize {
    static LIM: AtomicUsize = AtomicUsize::new(0);

    let mut lim = LIM.load(Ordering::Relaxed);
    if lim == 0 {
        let ret = unsafe {
            libc::sysconf(
                #[cfg(target_os = "linux")]
                libc::_SC_IOV_MAX,
                #[cfg(target_os = "macos")]
                libc::_SC_UIO_MAXIOV,
            )
        };

        // 1024 is the default value on modern Linux systems
        // and hopefully more useful than `c_int::MAX`.
        lim = if ret > 0 { ret as usize } else { 1024 };
        LIM.store(lim, Ordering::Relaxed);
    }

    lim
}

#[cfg(not(any(target_os = "linux", target_os = "macos")))]
fn max_iov() -> usize {
    c_int::MAX as usize
}

impl FileDesc {
    pub fn new(fd: c_int) -> FileDesc {
        FileDesc { fd }
    }

    pub fn raw(&self) -> c_int {
        self.fd
    }

    /// Extracts the actual file descriptor without closing it.
    pub fn into_raw(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT))
        })?;
        Ok(ret as usize)
    }

    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::readv(
                self.fd,
                bufs.as_ptr() as *const libc::iovec,
                cmp::min(bufs.len(), max_iov()) as c_int,
            )
        })?;
        Ok(ret as usize)
    }

    #[inline]
    pub fn is_read_vectored(&self) -> bool {
        true
    }

    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut me = self;
        (&mut me).read_to_end(buf)
    }

    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
        #[cfg(target_os = "android")]
        use super::android::cvt_pread64;

        #[cfg(not(target_os = "android"))]
        unsafe fn cvt_pread64(
            fd: c_int,
            buf: *mut c_void,
            count: usize,
            offset: i64,
        ) -> io::Result<isize> {
            #[cfg(not(target_os = "linux"))]
            use libc::pread as pread64;
            #[cfg(target_os = "linux")]
            use libc::pread64;
            cvt(pread64(fd, buf, count, offset))
        }

        unsafe {
            cvt_pread64(
                self.fd,
                buf.as_mut_ptr() as *mut c_void,
                cmp::min(buf.len(), READ_LIMIT),
                offset as i64,
            )
            .map(|n| n as usize)
        }
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT))
        })?;
        Ok(ret as usize)
    }

    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::writev(
                self.fd,
                bufs.as_ptr() as *const libc::iovec,
                cmp::min(bufs.len(), max_iov()) as c_int,
            )
        })?;
        Ok(ret as usize)
    }

    #[inline]
    pub fn is_write_vectored(&self) -> bool {
        true
    }

    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
        #[cfg(target_os = "android")]
        use super::android::cvt_pwrite64;

        #[cfg(not(target_os = "android"))]
        unsafe fn cvt_pwrite64(
            fd: c_int,
            buf: *const c_void,
            count: usize,
            offset: i64,
        ) -> io::Result<isize> {
            #[cfg(not(target_os = "linux"))]
            use libc::pwrite as pwrite64;
            #[cfg(target_os = "linux")]
            use libc::pwrite64;
            cvt(pwrite64(fd, buf, count, offset))
        }

        unsafe {
            cvt_pwrite64(
                self.fd,
                buf.as_ptr() as *const c_void,
                cmp::min(buf.len(), READ_LIMIT),
                offset as i64,
            )
            .map(|n| n as usize)
        }
    }

    #[cfg(target_os = "linux")]
    pub fn get_cloexec(&self) -> io::Result<bool> {
        unsafe { Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
    }

    #[cfg(not(any(
        target_env = "newlib",
        target_os = "solaris",
        target_os = "illumos",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "l4re",
        target_os = "linux",
        target_os = "haiku",
        target_os = "redox"
    )))]
    pub fn set_cloexec(&self) -> io::Result<()> {
        unsafe {
            cvt(libc::ioctl(self.fd, libc::FIOCLEX))?;
            Ok(())
        }
    }
    #[cfg(any(
        target_env = "newlib",
        target_os = "solaris",
        target_os = "illumos",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "l4re",
        target_os = "linux",
        target_os = "haiku",
        target_os = "redox"
    ))]
    pub fn set_cloexec(&self) -> io::Result<()> {
        unsafe {
            let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
            let new = previous | libc::FD_CLOEXEC;
            if new != previous {
                cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?;
            }
            Ok(())
        }
    }

    #[cfg(target_os = "linux")]
    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
        unsafe {
            let v = nonblocking as c_int;
            cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?;
            Ok(())
        }
    }

    #[cfg(not(target_os = "linux"))]
    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
        unsafe {
            let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?;
            let new = if nonblocking {
                previous | libc::O_NONBLOCK
            } else {
                previous & !libc::O_NONBLOCK
            };
            if new != previous {
                cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
            }
            Ok(())
        }
    }

    pub fn duplicate(&self) -> io::Result<FileDesc> {
        // We want to atomically duplicate this file descriptor and set the
        // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
        // is a POSIX flag that was added to Linux in 2.6.24.
        let fd = cvt(unsafe { libc::fcntl(self.raw(), libc::F_DUPFD_CLOEXEC, 0) })?;
        Ok(FileDesc::new(fd))
    }
}

impl<'a> Read for &'a FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (**self).read(buf)
    }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}

impl AsInner<c_int> for FileDesc {
    fn as_inner(&self) -> &c_int {
        &self.fd
    }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        // Note that errors are ignored when closing a file descriptor. The
        // reason for this is that if an error occurs we don't actually know if
        // the file descriptor was closed or not, and if we retried (for
        // something like EINTR), we might close another valid file descriptor
        // opened after we closed ours.
        let _ = unsafe { libc::close(self.fd) };
    }
}

#[cfg(test)]
mod tests {
    use super::{FileDesc, IoSlice};

    #[test]
    fn limit_vector_count() {
        let stdout = FileDesc { fd: 1 };
        let bufs = (0..1500).map(|_| IoSlice::new(&[])).collect::<Vec<_>>();

        assert!(stdout.write_vectored(&bufs).is_ok());
    }
}
<commit_msg>Rely only on POSIX semantics for I/O vector count<commit_after>#![unstable(reason = "not public", issue = "none", feature = "fd")]

use crate::cmp;
use crate::io::{self, Initializer, IoSlice, IoSliceMut, Read};
use crate::mem;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::cvt;
use crate::sys_common::AsInner;

use libc::{c_int, c_void};

#[derive(Debug)]
pub struct FileDesc {
    fd: c_int,
}

// The maximum read limit on most POSIX-like systems is `SSIZE_MAX`,
// with the man page quoting that if the count of bytes to read is
// greater than `SSIZE_MAX` the result is "unspecified".
//
// On macOS, however, apparently the 64-bit libc is either buggy or
// intentionally showing odd behavior by rejecting any read with a size
// larger than or equal to INT_MAX. To handle both of these the read
// size is capped on both platforms.
#[cfg(target_os = "macos")]
const READ_LIMIT: usize = c_int::MAX as usize - 1;
#[cfg(not(target_os = "macos"))]
const READ_LIMIT: usize = libc::ssize_t::MAX as usize;

fn max_iov() -> usize {
    static LIM: AtomicUsize = AtomicUsize::new(0);

    let mut lim = LIM.load(Ordering::Relaxed);
    if lim == 0 {
        let ret = unsafe { libc::sysconf(libc::_SC_IOV_MAX) };

        // 16 is the minimum value required by POSIX.
        lim = if ret > 0 { ret as usize } else { 16 };
        LIM.store(lim, Ordering::Relaxed);
    }

    lim
}

impl FileDesc {
    pub fn new(fd: c_int) -> FileDesc {
        FileDesc { fd }
    }

    pub fn raw(&self) -> c_int {
        self.fd
    }

    /// Extracts the actual file descriptor without closing it.
    pub fn into_raw(self) -> c_int {
        let fd = self.fd;
        mem::forget(self);
        fd
    }

    pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::read(self.fd, buf.as_mut_ptr() as *mut c_void, cmp::min(buf.len(), READ_LIMIT))
        })?;
        Ok(ret as usize)
    }

    pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::readv(
                self.fd,
                bufs.as_ptr() as *const libc::iovec,
                cmp::min(bufs.len(), max_iov()) as c_int,
            )
        })?;
        Ok(ret as usize)
    }

    #[inline]
    pub fn is_read_vectored(&self) -> bool {
        true
    }

    pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
        let mut me = self;
        (&mut me).read_to_end(buf)
    }

    pub fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<usize> {
        #[cfg(target_os = "android")]
        use super::android::cvt_pread64;

        #[cfg(not(target_os = "android"))]
        unsafe fn cvt_pread64(
            fd: c_int,
            buf: *mut c_void,
            count: usize,
            offset: i64,
        ) -> io::Result<isize> {
            #[cfg(not(target_os = "linux"))]
            use libc::pread as pread64;
            #[cfg(target_os = "linux")]
            use libc::pread64;
            cvt(pread64(fd, buf, count, offset))
        }

        unsafe {
            cvt_pread64(
                self.fd,
                buf.as_mut_ptr() as *mut c_void,
                cmp::min(buf.len(), READ_LIMIT),
                offset as i64,
            )
            .map(|n| n as usize)
        }
    }

    pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::write(self.fd, buf.as_ptr() as *const c_void, cmp::min(buf.len(), READ_LIMIT))
        })?;
        Ok(ret as usize)
    }

    pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
        let ret = cvt(unsafe {
            libc::writev(
                self.fd,
                bufs.as_ptr() as *const libc::iovec,
                cmp::min(bufs.len(), max_iov()) as c_int,
            )
        })?;
        Ok(ret as usize)
    }

    #[inline]
    pub fn is_write_vectored(&self) -> bool {
        true
    }

    pub fn write_at(&self, buf: &[u8], offset: u64) -> io::Result<usize> {
        #[cfg(target_os = "android")]
        use super::android::cvt_pwrite64;

        #[cfg(not(target_os = "android"))]
        unsafe fn cvt_pwrite64(
            fd: c_int,
            buf: *const c_void,
            count: usize,
            offset: i64,
        ) -> io::Result<isize> {
            #[cfg(not(target_os = "linux"))]
            use libc::pwrite as pwrite64;
            #[cfg(target_os = "linux")]
            use libc::pwrite64;
            cvt(pwrite64(fd, buf, count, offset))
        }

        unsafe {
            cvt_pwrite64(
                self.fd,
                buf.as_ptr() as *const c_void,
                cmp::min(buf.len(), READ_LIMIT),
                offset as i64,
            )
            .map(|n| n as usize)
        }
    }

    #[cfg(target_os = "linux")]
    pub fn get_cloexec(&self) -> io::Result<bool> {
        unsafe { Ok((cvt(libc::fcntl(self.fd, libc::F_GETFD))? & libc::FD_CLOEXEC) != 0) }
    }

    #[cfg(not(any(
        target_env = "newlib",
        target_os = "solaris",
        target_os = "illumos",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "l4re",
        target_os = "linux",
        target_os = "haiku",
        target_os = "redox"
    )))]
    pub fn set_cloexec(&self) -> io::Result<()> {
        unsafe {
            cvt(libc::ioctl(self.fd, libc::FIOCLEX))?;
            Ok(())
        }
    }
    #[cfg(any(
        target_env = "newlib",
        target_os = "solaris",
        target_os = "illumos",
        target_os = "emscripten",
        target_os = "fuchsia",
        target_os = "l4re",
        target_os = "linux",
        target_os = "haiku",
        target_os = "redox"
    ))]
    pub fn set_cloexec(&self) -> io::Result<()> {
        unsafe {
            let previous = cvt(libc::fcntl(self.fd, libc::F_GETFD))?;
            let new = previous | libc::FD_CLOEXEC;
            if new != previous {
                cvt(libc::fcntl(self.fd, libc::F_SETFD, new))?;
            }
            Ok(())
        }
    }

    #[cfg(target_os = "linux")]
    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
        unsafe {
            let v = nonblocking as c_int;
            cvt(libc::ioctl(self.fd, libc::FIONBIO, &v))?;
            Ok(())
        }
    }

    #[cfg(not(target_os = "linux"))]
    pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
        unsafe {
            let previous = cvt(libc::fcntl(self.fd, libc::F_GETFL))?;
            let new = if nonblocking {
                previous | libc::O_NONBLOCK
            } else {
                previous & !libc::O_NONBLOCK
            };
            if new != previous {
                cvt(libc::fcntl(self.fd, libc::F_SETFL, new))?;
            }
            Ok(())
        }
    }

    pub fn duplicate(&self) -> io::Result<FileDesc> {
        // We want to atomically duplicate this file descriptor and set the
        // CLOEXEC flag, and currently that's done via F_DUPFD_CLOEXEC. This
        // is a POSIX flag that was added to Linux in 2.6.24.
        let fd = cvt(unsafe { libc::fcntl(self.raw(), libc::F_DUPFD_CLOEXEC, 0) })?;
        Ok(FileDesc::new(fd))
    }
}

impl<'a> Read for &'a FileDesc {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (**self).read(buf)
    }

    #[inline]
    unsafe fn initializer(&self) -> Initializer {
        Initializer::nop()
    }
}

impl AsInner<c_int> for FileDesc {
    fn as_inner(&self) -> &c_int {
        &self.fd
    }
}

impl Drop for FileDesc {
    fn drop(&mut self) {
        // Note that errors are ignored when closing a file descriptor. The
        // reason for this is that if an error occurs we don't actually know if
        // the file descriptor was closed or not, and if we retried (for
        // something like EINTR), we might close another valid file descriptor
        // opened after we closed ours.
        let _ = unsafe { libc::close(self.fd) };
    }
}

#[cfg(test)]
mod tests {
    use super::{FileDesc, IoSlice};

    #[test]
    fn limit_vector_count() {
        let stdout = FileDesc { fd: 1 };
        let bufs = (0..1500).map(|_| IoSlice::new(&[])).collect::<Vec<_>>();

        assert!(stdout.write_vectored(&bufs).is_ok());
    }
}
<|endoftext|>


<commit_before>//!
//! This module defines a manager for holding multiple instances of mock servers.
//!

use crate::mock_server::{MockServer, MockServerConfig};

use pact_matching::models::RequestResponsePact;
use std::collections::BTreeMap;
use rustls::ServerConfig;
use std::net::SocketAddr;
use std::cell::RefCell;
use std::ops::Deref;
use std::sync::{Mutex, Arc};

struct ServerEntry {
  mock_server: Arc<Mutex<MockServer>>,
  join_handle: tokio::task::JoinHandle<()>,
}

/// Struct to represent many mock servers running in a background thread
pub struct ServerManager {
    runtime: tokio::runtime::Runtime,
    mock_servers: BTreeMap<String, ServerEntry>,
}

impl ServerManager {
    /// Construct a new ServerManager for scheduling several instances of mock servers
    /// on one tokio runtime.
    pub fn new() -> ServerManager {
        ServerManager {
            runtime: tokio::runtime::Builder::new()
                .threaded_scheduler()
                .core_threads(1)
                .enable_all()
                .build()
                .unwrap(),
            mock_servers: BTreeMap::new(),
        }
    }

    /// Start a new server on the runtime
    pub fn start_mock_server_with_addr(
      &mut self,
      id: String,
      pact: RequestResponsePact,
      addr: SocketAddr,
      config: MockServerConfig
    ) -> Result<SocketAddr, String> {
      let (mock_server, future) =
        self.runtime.block_on(MockServer::new(id.clone(), pact, addr, config))?;

      let port = { mock_server.lock().unwrap().port.clone() };
      self.mock_servers.insert(
        id,
        ServerEntry {
          mock_server,
          join_handle: self.runtime.spawn(future),
        },
      );

      match port {
        Some(port) => Ok(SocketAddr::new(addr.ip(), port)),
        None => Ok(addr)
      }
    }

    /// Start a new TLS server on the runtime
    pub fn start_tls_mock_server_with_addr(
      &mut self,
      id: String,
      pact: RequestResponsePact,
      addr: SocketAddr,
      tls: &ServerConfig,
      config: MockServerConfig
    ) -> Result<SocketAddr, String> {
      let (mock_server, future) =
        self.runtime.block_on(MockServer::new_tls(id.clone(), pact, addr, tls, config))?;

      let port = { mock_server.lock().unwrap().port.clone() };
      self.mock_servers.insert(
        id,
        ServerEntry {
          mock_server,
          join_handle: self.runtime.spawn(future),
        }
      );

      match port {
        Some(port) => Ok(SocketAddr::new(addr.ip(), port)),
        None => Ok(addr)
      }
    }

    /// Start a new server on the runtime
    pub fn start_mock_server(
      &mut self,
      id: String,
      pact: RequestResponsePact,
      port: u16,
      config: MockServerConfig
    ) -> Result<u16, String> {
        self.start_mock_server_with_addr(id, pact, ([0, 0, 0, 0], port as u16).into(), config)
            .map(|addr| addr.port())
    }

  /// Start a new server on the runtime, returning the future
  pub async fn start_mock_server_nonblocking(
    &mut self,
    id: String,
    pact: RequestResponsePact,
    port: u16,
    config: MockServerConfig
  ) -> Result<u16, String> {
    let addr= ([0, 0, 0, 0], port as u16).into();
    let (mock_server, future) = MockServer::new(id.clone(), pact, addr, config).await?;

    let port = {
      mock_server.lock().unwrap().port.clone()
    };
    self.mock_servers.insert(
      id,
      ServerEntry {
        mock_server,
        join_handle: self.runtime.spawn(future),
      },
    );

    port.ok_or_else(|| "Started mock server has no port".to_string())
  }

    /// Start a new TLS server on the runtime
    pub fn start_tls_mock_server(
      &mut self,
      id: String,
      pact: RequestResponsePact,
      port: u16,
      tls: &ServerConfig,
      config: MockServerConfig
    ) -> Result<u16, String> {
        self.start_tls_mock_server_with_addr(id, pact, ([0, 0, 0, 0], port as u16).into(), tls, config)
          .map(|addr| addr.port())
    }

    /// Shut down a server by its id
    pub fn shutdown_mock_server_by_id(&mut self, id: String) -> bool {
      match self.mock_servers.remove(&id) {
        Some(mut entry) => {
          let mut ms = entry.mock_server.lock().unwrap();
          match ms.shutdown() {
            Ok(()) => {
              self.runtime.block_on(entry.join_handle).unwrap();
              true
            }
            Err(_) => false,
          }
        },
        None => false,
      }
    }

    /// Shut down a server by its local port number
    pub fn shutdown_mock_server_by_port(&mut self, port: u16) -> bool {
      log::debug!("Shutting down mock server with port {}", port);
      let result = self
        .mock_servers
        .iter()
        .find(|(_id, entry)| entry.mock_server.lock().unwrap().port.unwrap_or_default() == port)
        .map(|(_id, entry)| entry.mock_server.lock().unwrap().id.clone());

      if let Some(id) = result {
        if let Some(mut entry) = self.mock_servers.remove(&id) {
          let mut ms = entry.mock_server.lock().unwrap();
          return match ms.shutdown() {
            Ok(()) => {
              self.runtime.block_on(entry.join_handle).unwrap();
              true
            }
            Err(_) => false,
          };
        }
      }

      false
    }

    /// Find mock server by id, and map it using supplied function if found
    pub fn find_mock_server_by_id<R>(
      &self,
      id: &String,
      f: &dyn Fn(&MockServer) -> R,
    ) -> Option<R> {
      match self.mock_servers.get(id) {
        Some(entry) => Some(f(&entry.mock_server.lock().unwrap())),
        None => None,
      }
    }

    /// Find a mock server by port number and apply a mutating operation on it if successful
    pub fn find_mock_server_by_port_mut<R>(
      &mut self,
      port: u16,
      f: &dyn Fn(&mut MockServer) -> R,
    ) -> Option<R> {
      match self
        .mock_servers
        .iter_mut()
        .find(|(_id, entry)| entry.mock_server.lock().unwrap().port.unwrap_or_default() == port)
      {
        Some((_id, entry)) => Some(f(&mut entry.mock_server.lock().unwrap())),
        None => None,
      }
    }

    /// Map all the running mock servers
    pub fn map_mock_servers<R>(&self, f: &dyn Fn(&MockServer) -> R) -> Vec<R> {
      let mut results = vec![];
      for (_id_, entry) in self.mock_servers.iter() {
        results.push(f(&entry.mock_server.lock().unwrap()));
      }
      return results;
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::net::TcpStream;
    use std::{thread, time};
    use env_logger;

    #[test]
    fn manager_should_start_and_shutdown_mock_server() {
        env_logger::try_init().unwrap_or(());
        let mut manager = ServerManager::new();
        let start_result = manager.start_mock_server("foobar".into(), RequestResponsePact::default(),
                                                     0, MockServerConfig::default());

        assert!(start_result.is_ok());
        let server_port = start_result.unwrap();

        // Server should be up
        assert!(TcpStream::connect(("127.0.0.1", server_port)).is_ok());

        // Should be able to read matches without blocking
        let matches =
            manager.find_mock_server_by_port_mut(server_port, &|mock_server| mock_server.matches());
        assert_eq!(matches, Some(vec![]));

        let stopped = manager.shutdown_mock_server_by_port(server_port);
        assert!(stopped);

        // The tokio runtime is now out of tasks
        drop(manager);

        let ten_millis = time::Duration::from_millis(200);
        thread::sleep(ten_millis);

        // Server should be down
        assert!(TcpStream::connect(("127.0.0.1", server_port)).is_err());
    }
}
<commit_msg>chore: add longer sleep for test failing on windows<commit_after>//!
//! This module defines a manager for holding multiple instances of mock servers.
//!

use crate::mock_server::{MockServer, MockServerConfig};

use pact_matching::models::RequestResponsePact;
use std::collections::BTreeMap;
use rustls::ServerConfig;
use std::net::SocketAddr;
use std::cell::RefCell;
use std::ops::Deref;
use std::sync::{Mutex, Arc};

struct ServerEntry {
  mock_server: Arc<Mutex<MockServer>>,
  join_handle: tokio::task::JoinHandle<()>,
}

/// Struct to represent many mock servers running in a background thread
pub struct ServerManager {
    runtime: tokio::runtime::Runtime,
    mock_servers: BTreeMap<String, ServerEntry>,
}

impl ServerManager {
    /// Construct a new ServerManager for scheduling several instances of mock servers
    /// on one tokio runtime.
    pub fn new() -> ServerManager {
        ServerManager {
            runtime: tokio::runtime::Builder::new()
                .threaded_scheduler()
                .core_threads(1)
                .enable_all()
                .build()
                .unwrap(),
            mock_servers: BTreeMap::new(),
        }
    }

    /// Start a new server on the runtime
    pub fn start_mock_server_with_addr(
      &mut self,
      id: String,
      pact: RequestResponsePact,
      addr: SocketAddr,
      config: MockServerConfig
    ) -> Result<SocketAddr, String> {
      let (mock_server, future) =
        self.runtime.block_on(MockServer::new(id.clone(), pact, addr, config))?;

      let port = { mock_server.lock().unwrap().port.clone() };
      self.mock_servers.insert(
        id,
        ServerEntry {
          mock_server,
          join_handle: self.runtime.spawn(future),
        },
      );

      match port {
        Some(port) => Ok(SocketAddr::new(addr.ip(), port)),
        None => Ok(addr)
      }
    }

    /// Start a new TLS server on the runtime
    pub fn start_tls_mock_server_with_addr(
      &mut self,
      id: String,
      pact: RequestResponsePact,
      addr: SocketAddr,
      tls: &ServerConfig,
      config: MockServerConfig
    ) -> Result<SocketAddr, String> {
      let (mock_server, future) =
        self.runtime.block_on(MockServer::new_tls(id.clone(), pact, addr, tls, config))?;

      let port = { mock_server.lock().unwrap().port.clone() };
      self.mock_servers.insert(
        id,
        ServerEntry {
          mock_server,
          join_handle: self.runtime.spawn(future),
        }
      );

      match port {
        Some(port) => Ok(SocketAddr::new(addr.ip(), port)),
        None => Ok(addr)
      }
    }

    /// Start a new server on the runtime
    pub fn start_mock_server(
      &mut self,
      id: String,
      pact: RequestResponsePact,
      port: u16,
      config: MockServerConfig
    ) -> Result<u16, String> {
        self.start_mock_server_with_addr(id, pact, ([0, 0, 0, 0], port as u16).into(), config)
            .map(|addr| addr.port())
    }

  /// Start a new server on the runtime, returning the future
  pub async fn start_mock_server_nonblocking(
    &mut self,
    id: String,
    pact: RequestResponsePact,
    port: u16,
    config: MockServerConfig
  ) -> Result<u16, String> {
    let addr= ([0, 0, 0, 0], port as u16).into();
    let (mock_server, future) = MockServer::new(id.clone(), pact, addr, config).await?;

    let port = {
      mock_server.lock().unwrap().port.clone()
    };
    self.mock_servers.insert(
      id,
      ServerEntry {
        mock_server,
        join_handle: self.runtime.spawn(future),
      },
    );

    port.ok_or_else(|| "Started mock server has no port".to_string())
  }

    /// Start a new TLS server on the runtime
    pub fn start_tls_mock_server(
      &mut self,
      id: String,
      pact: RequestResponsePact,
      port: u16,
      tls: &ServerConfig,
      config: MockServerConfig
    ) -> Result<u16, String> {
        self.start_tls_mock_server_with_addr(id, pact, ([0, 0, 0, 0], port as u16).into(), tls, config)
          .map(|addr| addr.port())
    }

    /// Shut down a server by its id
    pub fn shutdown_mock_server_by_id(&mut self, id: String) -> bool {
      match self.mock_servers.remove(&id) {
        Some(mut entry) => {
          let mut ms = entry.mock_server.lock().unwrap();
          match ms.shutdown() {
            Ok(()) => {
              self.runtime.block_on(entry.join_handle).unwrap();
              true
            }
            Err(_) => false,
          }
        },
        None => false,
      }
    }

    /// Shut down a server by its local port number
    pub fn shutdown_mock_server_by_port(&mut self, port: u16) -> bool {
      log::debug!("Shutting down mock server with port {}", port);
      let result = self
        .mock_servers
        .iter()
        .find(|(_id, entry)| entry.mock_server.lock().unwrap().port.unwrap_or_default() == port)
        .map(|(_id, entry)| entry.mock_server.lock().unwrap().id.clone());

      if let Some(id) = result {
        if let Some(mut entry) = self.mock_servers.remove(&id) {
          let mut ms = entry.mock_server.lock().unwrap();
          return match ms.shutdown() {
            Ok(()) => {
              self.runtime.block_on(entry.join_handle).unwrap();
              true
            }
            Err(_) => false,
          };
        }
      }

      false
    }

    /// Find mock server by id, and map it using supplied function if found
    pub fn find_mock_server_by_id<R>(
      &self,
      id: &String,
      f: &dyn Fn(&MockServer) -> R,
    ) -> Option<R> {
      match self.mock_servers.get(id) {
        Some(entry) => Some(f(&entry.mock_server.lock().unwrap())),
        None => None,
      }
    }

    /// Find a mock server by port number and apply a mutating operation on it if successful
    pub fn find_mock_server_by_port_mut<R>(
      &mut self,
      port: u16,
      f: &dyn Fn(&mut MockServer) -> R,
    ) -> Option<R> {
      match self
        .mock_servers
        .iter_mut()
        .find(|(_id, entry)| entry.mock_server.lock().unwrap().port.unwrap_or_default() == port)
      {
        Some((_id, entry)) => Some(f(&mut entry.mock_server.lock().unwrap())),
        None => None,
      }
    }

    /// Map all the running mock servers
    pub fn map_mock_servers<R>(&self, f: &dyn Fn(&MockServer) -> R) -> Vec<R> {
      let mut results = vec![];
      for (_id_, entry) in self.mock_servers.iter() {
        results.push(f(&entry.mock_server.lock().unwrap()));
      }
      return results;
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::net::TcpStream;
    use std::{thread, time};
    use env_logger;

    #[test]
    fn manager_should_start_and_shutdown_mock_server() {
        env_logger::try_init().unwrap_or(());
        let mut manager = ServerManager::new();
        let start_result = manager.start_mock_server("foobar".into(), RequestResponsePact::default(),
                                                     0, MockServerConfig::default());

        assert!(start_result.is_ok());
        let server_port = start_result.unwrap();

        // Server should be up
        assert!(TcpStream::connect(("127.0.0.1", server_port)).is_ok());

        // Should be able to read matches without blocking
        let matches =
            manager.find_mock_server_by_port_mut(server_port, &|mock_server| mock_server.matches());
        assert_eq!(matches, Some(vec![]));

        let stopped = manager.shutdown_mock_server_by_port(server_port);
        assert!(stopped);

        // The tokio runtime is now out of tasks
        drop(manager);

        let millis = time::Duration::from_millis(500);
        thread::sleep(millis);

        // Server should be down
        assert!(TcpStream::connect(("127.0.0.1", server_port)).is_err());
    }
}
<|endoftext|>


<commit_before>//! Simple script to verify the coding style of this library
//!
//! ## How to run
//!
//! The first argument to this script is the directory to run on, so running
//! this script should be as simple as:
//!
//! ```notrust
//! rustc ci/style.rs
//! ./style src
//! ```
//!
//! ## Guidelines
//!
//! The current style is:
//!
//! * No trailing whitespace
//! * No tabs
//! * 80-character lines
//! * Specific module layout:
//!     1. use directives
//!     2. typedefs
//!     3. structs
//!     4. constants
//!     5. f! { ... } functions
//!     6. extern functions
//!     7. modules + pub use
//!
//! Things not verified:
//!
//! * alignment
//! * 4-space tabs
//! * leading colons on paths

use std::env;
use std::fs;
use std::io::prelude::*;
use std::path::Path;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    let arg = env::args().skip(1).next().unwrap_or(".".to_string());

    let mut errors = Errors { errs: false };
    walk(Path::new(&arg), &mut errors);

    if errors.errs {
        panic!("found some lint errors");
    } else {
        println!("good style!");
    }
}

fn walk(path: &Path, err: &mut Errors) {
    for entry in t!(path.read_dir()).map(|e| t!(e)) {
        let path = entry.path();
        if t!(entry.file_type()).is_dir() {
            walk(&path, err);
            continue
        }

        let name = entry.file_name().into_string().unwrap();
        match &name[..] {
            n if !n.ends_with(".rs") => continue,

            "dox.rs" |
            "lib.rs" |
            "ctypes.rs" |
            "libc.rs" |
            "macros.rs" => continue,

            _ => {}
        }

        let mut contents = String::new();
        t!(t!(fs::File::open(&path)).read_to_string(&mut contents));

        check_style(&contents, &path, err);
    }
}

struct Errors {
    errs: bool,
}

#[derive(Clone, Copy, PartialEq)]
enum State {
    Start,
    Imports,
    Typedefs,
    Structs,
    Constants,
    FunctionDefinitions,
    Functions,
    Modules,
}

fn check_style(file: &str, path: &Path, err: &mut Errors) {
    let mut state = State::Start;
    let mut s_macros = 0;
    let mut f_macros = 0;
    let mut prev_blank = false;

    for (i, line) in file.lines().enumerate() {
        if line == "" {
            if prev_blank {
                err.error(path, i, "double blank line");
            }
            prev_blank = true;
        } else {
            prev_blank = false;
        }
        if line != line.trim_end() {
            err.error(path, i, "trailing whitespace");
        }
        if line.contains("\t") {
            err.error(path, i, "tab character");
        }
        if line.len() > 80 {
            err.error(path, i, "line longer than 80 chars");
        }
        if line.contains("#[cfg(") && !line.contains(" if ")
            && !(line.contains("target_endian") ||
                 line.contains("target_arch"))
        {
            if state != State::Structs {
                err.error(path, i, "use cfg_if! and submodules \
                                    instead of #[cfg]");
            }
        }
        if line.contains("#[derive(") && (line.contains("Copy") || line.contains("Clone")) {
            err.error(path, i, "impl ::Copy and ::Clone manually");
        }

        let line = line.trim_start();
        let is_pub = line.starts_with("pub ");
        let line = if is_pub {&line[4..]} else {line};

        let line_state = if line.starts_with("use ") {
            if line.contains("c_void") {
                continue;
            }
            if is_pub {
                State::Modules
            } else {
                State::Imports
            }
        } else if line.starts_with("const ") {
            State::Constants
        } else if line.starts_with("type ") {
            State::Typedefs
        } else if line.starts_with("s! {") {
            s_macros += 1;
            State::Structs
        } else if line.starts_with("f! {") {
            f_macros += 1;
            State::FunctionDefinitions
        } else if line.starts_with("extern ") {
            State::Functions
        } else if line.starts_with("mod ") {
            State::Modules
        } else {
            continue
        };

        if state as usize > line_state as usize {
            err.error(path, i, &format!("{} found after {} when \
                                         it belongs before",
                                        line_state.desc(), state.desc()));
        }

        if f_macros == 2 {
            f_macros += 1;
            err.error(path, i, "multiple f! macros in one module");
        }
        if s_macros == 2 {
            s_macros += 1;
            err.error(path, i, "multiple s! macros in one module");
        }

        state = line_state;
    }
}

impl State {
    fn desc(&self) -> &str {
        match *self {
            State::Start => "start",
            State::Imports => "import",
            State::Typedefs => "typedef",
            State::Structs => "struct",
            State::Constants => "constant",
            State::FunctionDefinitions => "function definition",
            State::Functions => "extern function",
            State::Modules => "module",
        }
    }
}

impl Errors {
    fn error(&mut self, path: &Path, line: usize, msg: &str) {
        self.errs = true;
        println!("{}:{} - {}", path.display(), line + 1, msg);
    }
}
<commit_msg>Update style.rs for new Rustfmt style<commit_after>//! Simple script to verify the coding style of this library
//!
//! ## How to run
//!
//! The first argument to this script is the directory to run on, so running
//! this script should be as simple as:
//!
//! ```notrust
//! rustc ci/style.rs
//! ./style src
//! ```
//!
//! ## Guidelines
//!
//! The current style is:
//!
//! * No trailing whitespace
//! * No tabs
//! * 80-character lines
//! * Specific module layout:
//!     1. use directives
//!     2. typedefs
//!     3. structs
//!     4. constants
//!     5. f! { ... } functions
//!     6. extern functions
//!     7. modules + pub use
//!
//! Things not verified:
//!
//! * alignment
//! * 4-space tabs
//! * leading colons on paths

use std::env;
use std::fs;
use std::io::prelude::*;
use std::path::Path;

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(e) => e,
        Err(e) => panic!("{} failed with {}", stringify!($e), e),
    })
}

fn main() {
    let arg = env::args().skip(1).next().unwrap_or(".".to_string());

    let mut errors = Errors { errs: false };
    walk(Path::new(&arg), &mut errors);

    if errors.errs {
        panic!("found some lint errors");
    } else {
        println!("good style!");
    }
}

fn walk(path: &Path, err: &mut Errors) {
    for entry in t!(path.read_dir()).map(|e| t!(e)) {
        let path = entry.path();
        if t!(entry.file_type()).is_dir() {
            walk(&path, err);
            continue
        }

        let name = entry.file_name().into_string().unwrap();
        match &name[..] {
            n if !n.ends_with(".rs") => continue,

            "dox.rs" |
            "lib.rs" |
            "ctypes.rs" |
            "libc.rs" |
            "macros.rs" => continue,

            _ => {}
        }

        let mut contents = String::new();
        t!(t!(fs::File::open(&path)).read_to_string(&mut contents));

        check_style(&contents, &path, err);
    }
}

struct Errors {
    errs: bool,
}

#[derive(Clone, Copy, PartialEq)]
enum State {
    Start,
    Imports,
    Typedefs,
    Structs,
    Constants,
    FunctionDefinitions,
    Functions,
    Modules,
}

fn check_style(file: &str, path: &Path, err: &mut Errors) {
    let mut state = State::Start;
    let mut s_macros = 0;
    let mut f_macros = 0;
    let mut prev_blank = false;

    for (i, line) in file.lines().enumerate() {
        if line == "" {
            if prev_blank {
                err.error(path, i, "double blank line");
            }
            prev_blank = true;
        } else {
            prev_blank = false;
        }
        if line != line.trim_end() {
            err.error(path, i, "trailing whitespace");
        }
        if line.contains("\t") {
            err.error(path, i, "tab character");
        }
        if line.len() > 80 {
            err.error(path, i, "line longer than 80 chars");
        }
        // This doesn't work any more due to rustfmt changes
        /*if line.contains("#[cfg(") && !line.contains(" if ")
            && !(line.contains("target_endian") ||
                 line.contains("target_arch"))
        {
            if state != State::Structs {
                err.error(path, i, "use cfg_if! and submodules \
                                    instead of #[cfg]");
            }
        }*/
        if line.contains("#[derive(") && (line.contains("Copy") || line.contains("Clone")) {
            err.error(path, i, "impl ::Copy and ::Clone manually");
        }

        let orig_line = line;
        let line = line.trim_start();
        let is_pub = line.starts_with("pub ");
        let line = if is_pub {&line[4..]} else {line};

        let line_state = if line.starts_with("use ") {
            if line.contains("c_void") {
                continue;
            }
            if is_pub {
                State::Modules
            } else {
                State::Imports
            }
        } else if line.starts_with("const ") {
            State::Constants
        } else if line.starts_with("type ") {
            State::Typedefs
        } else if line.starts_with("s! {") {
            s_macros += 1;
            State::Structs
        } else if line.starts_with("f! {") {
            f_macros += 1;
            State::FunctionDefinitions
        } else if line.starts_with("extern ") && !orig_line.starts_with(" ") {
            State::Functions
        } else if line.starts_with("mod ") {
            State::Modules
        } else {
            continue
        };

        if state as usize > line_state as usize {
            err.error(path, i, &format!("{} found after {} when \
                                         it belongs before",
                                        line_state.desc(), state.desc()));
        }

        if f_macros == 2 {
            f_macros += 1;
            err.error(path, i, "multiple f! macros in one module");
        }
        if s_macros == 2 {
            s_macros += 1;
            err.error(path, i, "multiple s! macros in one module");
        }

        state = line_state;
    }
}

impl State {
    fn desc(&self) -> &str {
        match *self {
            State::Start => "start",
            State::Imports => "import",
            State::Typedefs => "typedef",
            State::Structs => "struct",
            State::Constants => "constant",
            State::FunctionDefinitions => "function definition",
            State::Functions => "extern function",
            State::Modules => "module",
        }
    }
}

impl Errors {
    fn error(&mut self, path: &Path, line: usize, msg: &str) {
        self.errs = true;
        println!("{}:{} - {}", path.display(), line + 1, msg);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use toml;

use cargo_edit::Manifest;
use list_error::ListError;

type PkgName = String;
type PkgVersion = String;
type Package = (PkgName, PkgVersion);
type Dependency = Package;
type Dependencies = Vec<Dependency>;

/// A package as declared in the lock file
pub type Packages = BTreeMap<Package, Dependencies>;

/// Parse stuff like `"docopt 0.6.67 (registry+https://github.com/rust-lang/crates.io-index)"`
/// by splitting at whitespace and taking the first two things.
fn parse_dep_from_str(input: &str) -> Option<Dependency> {
    let pkg = input.split(' ').collect::<Vec<&str>>();
    if pkg.len() != 3 {
        return None;
    }

    let (name, version) = (pkg[0], pkg[1]);

    Some((String::from(name), String::from(version)))
}

fn get_root_deps(lock_file: &toml::Table) -> Result<Vec<Dependency>, ListError> {
    let root_deps = try!(lock_file.get("root")
                                  .and_then(|field| field.lookup("dependencies"))
                                  .ok_or(ListError::SectionMissing("dependencies".to_owned())));

    let output = root_deps.as_slice()
                          .unwrap_or(&vec![])
                          .iter()
                          .filter_map(|dep| {
                              let dep = dep.clone();
                              if let toml::Value::String(pkg_desc) = dep {
                                  parse_dep_from_str(&pkg_desc)
                              } else {
                                  None
                              }
                          })
                          .collect::<Vec<Dependency>>();

    Ok(output)
}

fn get_packages(lock_file: &toml::Table) -> Result<Packages, ListError> {
    let packages: &toml::Value = try!(lock_file.get("package").ok_or(ListError::PackagesMissing));

    let mut output = BTreeMap::new();

    for pkg in packages.as_slice().unwrap_or(&vec![]) {
        let package = try!(pkg.as_table().ok_or(ListError::PackageInvalid));

        let name = try!(package.get("name")
                               .and_then(|item| item.as_str())
                               .ok_or(ListError::PackageFieldMissing("name")));

        let version = try!(package.get("version")
                                  .and_then(|item| item.as_str())
                                  .ok_or(ListError::PackageFieldMissing("version")));

        let deps: Dependencies = package.get("dependencies")
                                        .and_then(|item| {
                                            let item = item.clone();
                                            if let toml::Value::Array(d) = item {
                                                Some(d)
                                            } else {
                                                None
                                            }
                                        })
                                        .and_then(|items| {
                                            Some(items.iter()
                                                      .filter_map(|i| i.as_str())
                                                      .filter_map(parse_dep_from_str)
                                                      .collect::<Dependencies>())
                                        })
                                        .unwrap_or(vec![]);

        output.insert((name.to_owned(), version.to_owned()), deps);
    }

    Ok(output)
}

fn list_deps_helper(pkgs: &Packages,
                    deps: &[Dependency],
                    levels: &mut Vec<bool>)
                    -> Result<String, ListError> {
    let mut output = String::new();
    for (i, dep) in deps.iter().enumerate() {
        // For any indent level where the parent is the last dependency in the list, we
        // don't want
        // to print out a branch.
        for is_last in levels.iter().cloned() {
            let indent = if is_last {
                "    "
            } else {
                "│   "
            };
            output.push_str(indent);
        }

        let is_last = i == deps.len() - 1;
        let branch = if !is_last {
            "├──"
        } else {
            "└──"
        };

        output.push_str(&format!("{} {} ({})\n", branch, dep.0, dep.1));

        if let Some(subdeps) = pkgs.get(dep) {
            levels.push(is_last);
            let sublist = try!(list_deps_helper(pkgs, subdeps, levels));
            output.push_str(&sublist);
            levels.pop();
        }
    }
    Ok(output)
}

fn list_deps(pkgs: &Packages, deps: &[Dependency]) -> Result<String, ListError> {
    list_deps_helper(pkgs, deps, &mut vec![])
}

/// Parse a `Cargo.lock` file and list its dependencies
pub fn parse_lock_file(manifest: &Manifest) -> Result<String, ListError> {
    let lock_file = &manifest.data;

    let root_deps = try!(get_root_deps(lock_file));
    let pkgs = try!(get_packages(lock_file));

    list_deps(&pkgs, &root_deps)
}

#[cfg(test)]
mod test {
    use cargo_edit::Manifest;
    use super::parse_lock_file;

    #[test]
    fn basic_tree() {
        let manifile = Manifest::open_lock_file(&Some("tests/fixtures/tree/Cargo.lock")).unwrap();

        assert_eq!(parse_lock_file(&manifile).unwrap(),
                   "\
├── clippy (0.0.5)
├── docopt (0.6.67)
│   ├── regex (0.1.38)
│   │   ├── aho-corasick (0.2.1)
│   │   │   └── memchr (0.1.3)
│   │   │       └── libc (0.1.8)
│   │   ├── memchr (0.1.3)
│   │   │   └── libc (0.1.8)
│   │   └── regex-syntax (0.1.2)
│   ├── rustc-serialize (0.3.15)
│   └── strsim (0.3.0)
├── pad (0.1.4)
│   └── unicode-width (0.1.1)
├── rustc-serialize (0.3.15)
├── semver (0.1.19)
└── toml (0.1.20)
    └── rustc-serialize (0.3.15)
");
    }
}
<commit_msg>Auto merge of #70 - killercup:feature/pub-types, r=killercup<commit_after>use std::collections::BTreeMap;

use toml;

use cargo_edit::Manifest;
use list_error::ListError;

pub type PkgName = String;
pub type PkgVersion = String;
pub type Package = (PkgName, PkgVersion);
pub type Dependency = Package;
pub type Dependencies = Vec<Dependency>;

/// A package as declared in the lock file
pub type Packages = BTreeMap<Package, Dependencies>;

/// Parse stuff like `"docopt 0.6.67 (registry+https://github.com/rust-lang/crates.io-index)"`
/// by splitting at whitespace and taking the first two things.
fn parse_dep_from_str(input: &str) -> Option<Dependency> {
    let pkg = input.split(' ').collect::<Vec<&str>>();
    if pkg.len() != 3 {
        return None;
    }

    let (name, version) = (pkg[0], pkg[1]);

    Some((String::from(name), String::from(version)))
}

fn get_root_deps(lock_file: &toml::Table) -> Result<Vec<Dependency>, ListError> {
    let root_deps = try!(lock_file.get("root")
                                  .and_then(|field| field.lookup("dependencies"))
                                  .ok_or(ListError::SectionMissing("dependencies".to_owned())));

    let output = root_deps.as_slice()
                          .unwrap_or(&vec![])
                          .iter()
                          .filter_map(|dep| {
                              let dep = dep.clone();
                              if let toml::Value::String(pkg_desc) = dep {
                                  parse_dep_from_str(&pkg_desc)
                              } else {
                                  None
                              }
                          })
                          .collect::<Vec<Dependency>>();

    Ok(output)
}

fn get_packages(lock_file: &toml::Table) -> Result<Packages, ListError> {
    let packages: &toml::Value = try!(lock_file.get("package").ok_or(ListError::PackagesMissing));

    let mut output = BTreeMap::new();

    for pkg in packages.as_slice().unwrap_or(&vec![]) {
        let package = try!(pkg.as_table().ok_or(ListError::PackageInvalid));

        let name = try!(package.get("name")
                               .and_then(|item| item.as_str())
                               .ok_or(ListError::PackageFieldMissing("name")));

        let version = try!(package.get("version")
                                  .and_then(|item| item.as_str())
                                  .ok_or(ListError::PackageFieldMissing("version")));

        let deps: Dependencies = package.get("dependencies")
                                        .and_then(|item| {
                                            let item = item.clone();
                                            if let toml::Value::Array(d) = item {
                                                Some(d)
                                            } else {
                                                None
                                            }
                                        })
                                        .and_then(|items| {
                                            Some(items.iter()
                                                      .filter_map(|i| i.as_str())
                                                      .filter_map(parse_dep_from_str)
                                                      .collect::<Dependencies>())
                                        })
                                        .unwrap_or(vec![]);

        output.insert((name.to_owned(), version.to_owned()), deps);
    }

    Ok(output)
}

fn list_deps_helper(pkgs: &Packages,
                    deps: &[Dependency],
                    levels: &mut Vec<bool>)
                    -> Result<String, ListError> {
    let mut output = String::new();
    for (i, dep) in deps.iter().enumerate() {
        // For any indent level where the parent is the last dependency in the list, we
        // don't want
        // to print out a branch.
        for is_last in levels.iter().cloned() {
            let indent = if is_last {
                "    "
            } else {
                "│   "
            };
            output.push_str(indent);
        }

        let is_last = i == deps.len() - 1;
        let branch = if !is_last {
            "├──"
        } else {
            "└──"
        };

        output.push_str(&format!("{} {} ({})\n", branch, dep.0, dep.1));

        if let Some(subdeps) = pkgs.get(dep) {
            levels.push(is_last);
            let sublist = try!(list_deps_helper(pkgs, subdeps, levels));
            output.push_str(&sublist);
            levels.pop();
        }
    }
    Ok(output)
}

fn list_deps(pkgs: &Packages, deps: &[Dependency]) -> Result<String, ListError> {
    list_deps_helper(pkgs, deps, &mut vec![])
}

/// Parse a `Cargo.lock` file and list its dependencies
pub fn parse_lock_file(manifest: &Manifest) -> Result<String, ListError> {
    let lock_file = &manifest.data;

    let root_deps = try!(get_root_deps(lock_file));
    let pkgs = try!(get_packages(lock_file));

    list_deps(&pkgs, &root_deps)
}

#[cfg(test)]
mod test {
    use cargo_edit::Manifest;
    use super::parse_lock_file;

    #[test]
    fn basic_tree() {
        let manifile = Manifest::open_lock_file(&Some("tests/fixtures/tree/Cargo.lock")).unwrap();

        assert_eq!(parse_lock_file(&manifile).unwrap(),
                   "\
├── clippy (0.0.5)
├── docopt (0.6.67)
│   ├── regex (0.1.38)
│   │   ├── aho-corasick (0.2.1)
│   │   │   └── memchr (0.1.3)
│   │   │       └── libc (0.1.8)
│   │   ├── memchr (0.1.3)
│   │   │   └── libc (0.1.8)
│   │   └── regex-syntax (0.1.2)
│   ├── rustc-serialize (0.3.15)
│   └── strsim (0.3.0)
├── pad (0.1.4)
│   └── unicode-width (0.1.1)
├── rustc-serialize (0.3.15)
├── semver (0.1.19)
└── toml (0.1.20)
    └── rustc-serialize (0.3.15)
");
    }
}
<|endoftext|>


<commit_before>//! Reads in MIDI events and uses them to trigger an ADSR

extern crate oxcable;

use oxcable::adsr;
use oxcable::chain::{DeviceChain, Tick};
use oxcable::types::{AudioDevice, MidiDevice, MidiMessage, Time, Sample};
use oxcable::io::audio::AudioEngine;
use oxcable::io::midi::{MidiEngine, MidiIn};
use oxcable::oscillator::{self, Oscillator};

struct WrappedAdsr {
    midi: MidiIn,
    adsr: adsr::Adsr
}
impl AudioDevice for WrappedAdsr {
    fn num_inputs(&self) -> usize {
        self.adsr.num_inputs()
    }

    fn num_outputs(&self) -> usize {
        self.adsr.num_outputs()
    }

    fn tick(&mut self, t: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        for event in self.midi.get_events(t) {
            println!("{:?}", event);
            match event.payload {
                MidiMessage::NoteOn(_,_) =>
                    self.adsr.handle_message(adsr::NoteDown),
                MidiMessage::NoteOff(_,_) =>
                    self.adsr.handle_message(adsr::NoteUp),
                _ => ()
            }
        }
        self.adsr.tick(t, inputs, outputs);
    }
}

#[cfg(not(test))]
fn main() {
    println!("Initializing signal chain...");
    let audio_engine = AudioEngine::with_buffer_size(256).unwrap();
    let midi_engine = MidiEngine::open().unwrap();

    let mut chain = DeviceChain::from(
        Oscillator::new(oscillator::Saw(oscillator::PolyBlep)).freq(220.0)
    ).into(
        WrappedAdsr {
            midi: midi_engine.choose_input().unwrap(),
            adsr: adsr::Adsr::default(1)
        }
    ).into(
        audio_engine.default_output(1).unwrap()
    );

    println!("Playing. Press Enter to quit...");
    chain.tick_until_enter();
    println!("Done!");
}
<commit_msg>Remove unused warnings when running tests<commit_after>//! Reads in MIDI events and uses them to trigger an ADSR

extern crate oxcable;

#[cfg(not(test))]
mod wrapper {
    use oxcable::adsr;
    use oxcable::io::midi::MidiIn;
    use oxcable::types::{AudioDevice, MidiDevice, MidiMessage, Time, Sample};

    pub struct WrappedAdsr {
        pub midi: MidiIn,
        pub adsr: adsr::Adsr
    }
    impl AudioDevice for WrappedAdsr {
        fn num_inputs(&self) -> usize {
            self.adsr.num_inputs()
        }

        fn num_outputs(&self) -> usize {
            self.adsr.num_outputs()
        }

        fn tick(&mut self, t: Time, inputs: &[Sample], outputs: &mut[Sample]) {
            for event in self.midi.get_events(t) {
                println!("{:?}", event);
                match event.payload {
                    MidiMessage::NoteOn(_,_) =>
                        self.adsr.handle_message(adsr::NoteDown),
                    MidiMessage::NoteOff(_,_) =>
                        self.adsr.handle_message(adsr::NoteUp),
                    _ => ()
                }
            }
            self.adsr.tick(t, inputs, outputs);
        }
    }
}

#[cfg(not(test))]
fn main() {
    use oxcable::adsr::Adsr;
    use oxcable::chain::{DeviceChain, Tick};
    use oxcable::io::audio::AudioEngine;
    use oxcable::io::midi::MidiEngine;
    use oxcable::oscillator::{self, Oscillator};

    println!("Initializing signal chain...");
    let audio_engine = AudioEngine::with_buffer_size(256).unwrap();
    let midi_engine = MidiEngine::open().unwrap();

    let mut chain = DeviceChain::from(
        Oscillator::new(oscillator::Saw(oscillator::PolyBlep)).freq(220.0)
    ).into(
        wrapper::WrappedAdsr {
            midi: midi_engine.choose_input().unwrap(),
            adsr: Adsr::default(1)
        }
    ).into(
        audio_engine.default_output(1).unwrap()
    );

    println!("Playing. Press Enter to quit...");
    chain.tick_until_enter();
    println!("Done!");
}
<|endoftext|>