<commit_before>// Hound -- A WAV encoding and decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::fs;
use std::io;
use std::io::Write;
use std::path;
use super::{Error, Result, Sample, WavSpec};

/// Extends the functionality of `io::Write` with additional methods.
///
/// The methods may be used on any type that implements `io::Write`.
pub trait WriteExt: io::Write {
    /// Writes an unsigned 8-bit integer.
    fn write_u8(&mut self, x: u8) -> io::Result<()>;

    /// Writes a signed 16-bit integer in little endian format.
    fn write_le_i16(&mut self, x: i16) -> io::Result<()>;

    /// Writes an unsigned 16-bit integer in little endian format.
    fn write_le_u16(&mut self, x: u16) -> io::Result<()>;

    /// Writes a signed 24-bit integer in little endian format.
    ///
    /// The most significant byte of the `i32` is ignored.
    fn write_le_i24(&mut self, x: i32) -> io::Result<()>;

    /// Writes an unsigned 24-bit integer in little endian format.
    ///
    /// The most significant byte of the `u32` is ignored.
    fn write_le_u24(&mut self, x: u32) -> io::Result<()>;

    /// Writes a signed 32-bit integer in little endian format.
    fn write_le_i32(&mut self, x: i32) -> io::Result<()>;

    /// Writes an unsigned 32-bit integer in little endian format.
    fn write_le_u32(&mut self, x: u32) -> io::Result<()>;
}

impl<W> WriteExt for W where W: io::Write {
    fn write_u8(&mut self, x: u8) -> io::Result<()> {
        let buf = [x];
        self.write_all(&buf)
    }

    fn write_le_i16(&mut self, x: i16) -> io::Result<()> {
        self.write_le_u16(x as u16)
    }

    fn write_le_u16(&mut self, x: u16) -> io::Result<()> {
        let mut buf = [0u8; 2];
        buf[0] = (x & 0xff) as u8;
        buf[1] = (x >> 8) as u8;
        self.write_all(&buf)
    }

    fn write_le_i24(&mut self, x: i32) -> io::Result<()> {
        self.write_le_u24(x as u32)
    }

    fn write_le_u24(&mut self, x: u32) -> io::Result<()> {
        let mut buf = [0u8; 3];
        buf[0] = ((x >> 00) & 0xff) as u8;
        buf[1] = ((x >> 08) & 0xff) as u8;
        buf[2] = ((x >> 16) & 0xff) as u8;
        self.write_all(&buf)
    }

    fn write_le_i32(&mut self, x: i32) -> io::Result<()> {
        self.write_le_u32(x as u32)
    }

    fn write_le_u32(&mut self, x: u32) -> io::Result<()> {
        let mut buf = [0u8; 4];
        buf[0] = ((x >> 00) & 0xff) as u8;
        buf[1] = ((x >> 08) & 0xff) as u8;
        buf[2] = ((x >> 16) & 0xff) as u8;
        buf[3] = ((x >> 24) & 0xff) as u8;
        self.write_all(&buf)
    }
}

/// Generates a bitmask with `channels` ones in the least significant bits.
fn channel_mask(channels: u16) -> u32 {
    (0 .. channels).map(|c| 1 << c).fold(0, |a, c| a | c)
}

#[test]
fn verify_channel_mask()
{
    assert_eq!(channel_mask(0), 0);
    assert_eq!(channel_mask(1), 1);
    assert_eq!(channel_mask(2), 3);
    assert_eq!(channel_mask(3), 7);
    assert_eq!(channel_mask(4), 15);
}

/// A writer that accepts samples and writes the WAVE format.
///
/// TODO: add example.
///
/// After all samples have been written, the file must be finalized. This can
/// be done by calling `finalize`. If `finalize` is not called, the file will
/// be finalized upon drop. However, finalization involves IO that may fail,
/// and without calling `finalize`, such a failure cannot be observed.
pub struct WavWriter<W> where W: io::Write + io::Seek {
    /// Specifies properties of the audio data.
    spec: WavSpec,

    /// The (container) bytes per sample. This is the bit rate / 8 rounded up.
    bytes_per_sample: u16,

    /// Whether the header has been written already.
    wrote_header: bool,

    /// The writer that will be written to.
    writer: io::BufWriter<W>,

    /// The number of bytes written to the data section.
    ///
    /// This is an `u32` because WAVE cannot accomodate more data.
    data_bytes_written: u32,

    /// Whether `finalize_internal` has been called.
    finalized: bool
}

impl<W> WavWriter<W> where W: io::Write + io::Seek {
    /// Creates a writer that writes the WAVE format to the underlying writer.
    ///
    /// The underlying writer is assumed to be at offset 0. `WavWriter` employs
    /// buffering internally to avoid too many `write` calls to the underlying
    /// writer.
    pub fn new(writer: W, spec: WavSpec) -> WavWriter<W> {
        WavWriter {
            spec: spec,
            bytes_per_sample: (spec.bits_per_sample as f32 / 8.0).ceil() as u16,
            wrote_header: false,
            writer: io::BufWriter::new(writer),
            data_bytes_written: 0,
            finalized: false
        }
    }

    /// Writes the RIFF WAVE header
    fn write_header(&mut self) -> io::Result<()> {
        // Useful links:
        // https://msdn.microsoft.com/en-us/library/ms713462.aspx
        // https://msdn.microsoft.com/en-us/library/ms713497.aspx

        let mut header = [0u8; 68];
        let spec = &self.spec;

        // Write the header in-memory first.
        {
            let mut buffer: io::Cursor<&mut [u8]> = io::Cursor::new(&mut header);
            try!(buffer.write_all("RIFF".as_bytes()));

            // Skip 4 bytes that will be filled with the file size afterwards.
            try!(buffer.write_le_u32(0));

            try!(buffer.write_all("WAVE".as_bytes()));
            try!(buffer.write_all("fmt ".as_bytes()));
            try!(buffer.write_le_u32(40)); // Size of the WAVE header chunk.

            // The following is based on the WAVEFORMATEXTENSIBLE struct as
            // documented on MSDN.

            // The field wFormatTag, value 1 means WAVE_FORMAT_PCM, but we use
            // the slightly more sophisticated WAVE_FORMAT_EXTENSIBLE.
            try!(buffer.write_le_u16(0xfffe));
            // The field nChannels.
            try!(buffer.write_le_u16(spec.channels));
            // The field nSamplesPerSec.
            try!(buffer.write_le_u32(spec.sample_rate));
            let bytes_per_sec = spec.sample_rate
                              * self.bytes_per_sample as u32
                              * spec.channels as u32;
            // The field nAvgBytesPerSec;
            try!(buffer.write_le_u32(bytes_per_sec));
            // The field nBlockAlign. Block align * sample rate = bytes per sec.
            try!(buffer.write_le_u16((bytes_per_sec / spec.sample_rate) as u16));
            // The field wBitsPerSample. This is actually the size of the
            // container, so this is a multiple of 8.
            try!(buffer.write_le_u16(self.bytes_per_sample as u16 * 8));
            // The field cbSize, the number of remaining bytes in the struct.
            try!(buffer.write_le_u16(22));
            // The field wValidBitsPerSample, the real number of bits per sample.
            try!(buffer.write_le_u16(self.spec.bits_per_sample));
            // The field dwChannelMask.
            // TODO: add the option to specify the channel mask. For now, use
            // the default assignment.
            try!(buffer.write_le_u32(channel_mask(self.spec.channels)));
            // The field SubFormat. We use KSDATAFORMAT_SUBTYPE_PCM. The
            // following GUIDS are defined:
            // - PCM:        00000001-0000-0010-8000-00aa00389b71
            // - IEEE_FLOAT: 00000003-0000-0010-8000-00aa00389b71
            // The byte order of a GUID is native for the first three sections,
            // which is assumed to be little endian, and big endian for the
            // last 8-byte section (which does contain a hyphen, for reasons
            // unknown to me).
            try!(buffer.write_all(&[0x01, 0x00, 0x00, 0x00,
                                    0x00, 0x00, 0x10, 0x00,
                                    0x80, 0x00, 0x00, 0xaa,
                                    0x00, 0x38, 0x9b, 0x71]));

            // So far the "fmt " section, now comes the "data" section. We will
            // only write the header here, actual data are the samples. The
            // number of bytes that this will take is not known at this point.
            // The 0 will be overwritten later.
            try!(buffer.write_all("data".as_bytes()));
            try!(buffer.write_le_u32(0));
        }

        // Then write the entire header at once.
        try!(self.writer.write_all(&header));

        Ok(())
    }

    /// Writes a single sample for one channel.
    ///
    /// WAVE interleaves channel data, so the channel that this writes the
    /// sample to depends on previous writes.
    pub fn write_sample<S: Sample>(&mut self, sample: S) -> Result<()> {
        if !self.wrote_header {
            try!(self.write_header());
            self.wrote_header = true;
        }

        // TODO: do we need bits per sample? Is the padding at the obvious side?
        try!(sample.write(&mut self.writer, self.spec.bits_per_sample));
        self.data_bytes_written += self.bytes_per_sample as u32;
        Ok(())
    }

    /// Performs finalization. After calling this, the writer should be destructed.
    fn finalize_internal(&mut self) -> Result<()> {
        self.finalized = true;

        // Flush remaining samples via the BufWriter.
        try!(self.writer.flush());

        // Extract the underlying writer and rewind it to the start, to update
        // the header fields of which we now know the value.
        let mut writer = self.writer.get_mut();

        // The header minus magic and 32-bit filesize is 60 bytes long.
        let file_size = self.data_bytes_written + 60;
        try!(writer.seek(io::SeekFrom::Start(4)));
        try!(writer.write_le_u32(file_size));
        try!(writer.seek(io::SeekFrom::Start(64)));
        try!(writer.write_le_u32(self.data_bytes_written));

        // Signal error if the last sample was not finished, but do so after
        // everything has been written, so that no data is lost, even though
        // the file is now ill-formed.
        if (self.data_bytes_written / self.bytes_per_sample as u32)
            % self.spec.channels as u32 != 0 {
            return Err(Error::UnfinishedSample);
        }

        Ok(())
    }

    /// Writes the parts of the WAVE format that require knowing all samples.
    ///
    /// This method must be called after all samples have been written. If it
    /// is not called, the destructor will finalize the file, but any errors
    /// that occur in the process cannot be observed in that manner.
    pub fn finalize(mut self) -> Result<()> {
        self.finalize_internal()
    }
}

impl<W> Drop for WavWriter<W> where W: io::Write + io::Seek {
    fn drop(&mut self) {
        // `finalize_internal` must be called only once. If that is done via
        // `finalize`, then this method is a no-op. If the user did not
        // finalize explicitly, then we should do it now. This can fail, but
        // drop should not panic, so a failure is ignored silently here.
        if !self.finalized {
            let _r = self.finalize_internal();
        }
    }
}

impl WavWriter<fs::File> {
    /// Creates a writer that writes the WAVE format to a file.
    ///
    /// This is a convenience constructor that creates the file and then
    /// constructs a `WavReader` from it. The file will be overwritten if it
    /// exists.
    pub fn create<P: AsRef<path::Path>>(filename: P, spec: WavSpec)
           -> io::Result<WavWriter<fs::File>> {
        let file = try!(fs::File::create(filename));
        Ok(WavWriter::new(file, spec))
    }
}

#[test]
fn short_write_should_signal_error() {
    let mut buffer = io::Cursor::new(Vec::new());

    let write_spec = WavSpec {
        channels: 17,
        sample_rate: 48000,
        bits_per_sample: 8
    };

    // Deliberately write one sample less than 17 * 5.
    let mut writer = WavWriter::new(&mut buffer, write_spec);
    for s in (0 .. 17 * 5 - 1) {
        writer.write_sample(s as i16).unwrap();
    }
    let error = writer.finalize().err().unwrap();

    match error {
        Error::UnfinishedSample => { },
        _ => panic!("UnfinishedSample error should have been returned.")
    }
}
<commit_msg>test that a wide write returns an error<commit_after>// Hound -- A WAV encoding and decoding library in Rust
// Copyright (C) 2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::fs;
use std::io;
use std::io::Write;
use std::path;
use super::{Error, Result, Sample, WavSpec};

/// Extends the functionality of `io::Write` with additional methods.
///
/// The methods may be used on any type that implements `io::Write`.
pub trait WriteExt: io::Write {
    /// Writes an unsigned 8-bit integer.
    fn write_u8(&mut self, x: u8) -> io::Result<()>;

    /// Writes a signed 16-bit integer in little endian format.
    fn write_le_i16(&mut self, x: i16) -> io::Result<()>;

    /// Writes an unsigned 16-bit integer in little endian format.
    fn write_le_u16(&mut self, x: u16) -> io::Result<()>;

    /// Writes a signed 24-bit integer in little endian format.
    ///
    /// The most significant byte of the `i32` is ignored.
    fn write_le_i24(&mut self, x: i32) -> io::Result<()>;

    /// Writes an unsigned 24-bit integer in little endian format.
    ///
    /// The most significant byte of the `u32` is ignored.
    fn write_le_u24(&mut self, x: u32) -> io::Result<()>;

    /// Writes a signed 32-bit integer in little endian format.
    fn write_le_i32(&mut self, x: i32) -> io::Result<()>;

    /// Writes an unsigned 32-bit integer in little endian format.
    fn write_le_u32(&mut self, x: u32) -> io::Result<()>;
}

impl<W> WriteExt for W where W: io::Write {
    fn write_u8(&mut self, x: u8) -> io::Result<()> {
        let buf = [x];
        self.write_all(&buf)
    }

    fn write_le_i16(&mut self, x: i16) -> io::Result<()> {
        self.write_le_u16(x as u16)
    }

    fn write_le_u16(&mut self, x: u16) -> io::Result<()> {
        let mut buf = [0u8; 2];
        buf[0] = (x & 0xff) as u8;
        buf[1] = (x >> 8) as u8;
        self.write_all(&buf)
    }

    fn write_le_i24(&mut self, x: i32) -> io::Result<()> {
        self.write_le_u24(x as u32)
    }

    fn write_le_u24(&mut self, x: u32) -> io::Result<()> {
        let mut buf = [0u8; 3];
        buf[0] = ((x >> 00) & 0xff) as u8;
        buf[1] = ((x >> 08) & 0xff) as u8;
        buf[2] = ((x >> 16) & 0xff) as u8;
        self.write_all(&buf)
    }

    fn write_le_i32(&mut self, x: i32) -> io::Result<()> {
        self.write_le_u32(x as u32)
    }

    fn write_le_u32(&mut self, x: u32) -> io::Result<()> {
        let mut buf = [0u8; 4];
        buf[0] = ((x >> 00) & 0xff) as u8;
        buf[1] = ((x >> 08) & 0xff) as u8;
        buf[2] = ((x >> 16) & 0xff) as u8;
        buf[3] = ((x >> 24) & 0xff) as u8;
        self.write_all(&buf)
    }
}

/// Generates a bitmask with `channels` ones in the least significant bits.
fn channel_mask(channels: u16) -> u32 {
    (0 .. channels).map(|c| 1 << c).fold(0, |a, c| a | c)
}

#[test]
fn verify_channel_mask()
{
    assert_eq!(channel_mask(0), 0);
    assert_eq!(channel_mask(1), 1);
    assert_eq!(channel_mask(2), 3);
    assert_eq!(channel_mask(3), 7);
    assert_eq!(channel_mask(4), 15);
}

/// A writer that accepts samples and writes the WAVE format.
///
/// TODO: add example.
///
/// After all samples have been written, the file must be finalized. This can
/// be done by calling `finalize`. If `finalize` is not called, the file will
/// be finalized upon drop. However, finalization involves IO that may fail,
/// and without calling `finalize`, such a failure cannot be observed.
pub struct WavWriter<W> where W: io::Write + io::Seek {
    /// Specifies properties of the audio data.
    spec: WavSpec,

    /// The (container) bytes per sample. This is the bit rate / 8 rounded up.
    bytes_per_sample: u16,

    /// Whether the header has been written already.
    wrote_header: bool,

    /// The writer that will be written to.
    writer: io::BufWriter<W>,

    /// The number of bytes written to the data section.
    ///
    /// This is an `u32` because WAVE cannot accomodate more data.
    data_bytes_written: u32,

    /// Whether `finalize_internal` has been called.
    finalized: bool
}

impl<W> WavWriter<W> where W: io::Write + io::Seek {
    /// Creates a writer that writes the WAVE format to the underlying writer.
    ///
    /// The underlying writer is assumed to be at offset 0. `WavWriter` employs
    /// buffering internally to avoid too many `write` calls to the underlying
    /// writer.
    pub fn new(writer: W, spec: WavSpec) -> WavWriter<W> {
        WavWriter {
            spec: spec,
            bytes_per_sample: (spec.bits_per_sample as f32 / 8.0).ceil() as u16,
            wrote_header: false,
            writer: io::BufWriter::new(writer),
            data_bytes_written: 0,
            finalized: false
        }
    }

    /// Writes the RIFF WAVE header
    fn write_header(&mut self) -> io::Result<()> {
        // Useful links:
        // https://msdn.microsoft.com/en-us/library/ms713462.aspx
        // https://msdn.microsoft.com/en-us/library/ms713497.aspx

        let mut header = [0u8; 68];
        let spec = &self.spec;

        // Write the header in-memory first.
        {
            let mut buffer: io::Cursor<&mut [u8]> = io::Cursor::new(&mut header);
            try!(buffer.write_all("RIFF".as_bytes()));

            // Skip 4 bytes that will be filled with the file size afterwards.
            try!(buffer.write_le_u32(0));

            try!(buffer.write_all("WAVE".as_bytes()));
            try!(buffer.write_all("fmt ".as_bytes()));
            try!(buffer.write_le_u32(40)); // Size of the WAVE header chunk.

            // The following is based on the WAVEFORMATEXTENSIBLE struct as
            // documented on MSDN.

            // The field wFormatTag, value 1 means WAVE_FORMAT_PCM, but we use
            // the slightly more sophisticated WAVE_FORMAT_EXTENSIBLE.
            try!(buffer.write_le_u16(0xfffe));
            // The field nChannels.
            try!(buffer.write_le_u16(spec.channels));
            // The field nSamplesPerSec.
            try!(buffer.write_le_u32(spec.sample_rate));
            let bytes_per_sec = spec.sample_rate
                              * self.bytes_per_sample as u32
                              * spec.channels as u32;
            // The field nAvgBytesPerSec;
            try!(buffer.write_le_u32(bytes_per_sec));
            // The field nBlockAlign. Block align * sample rate = bytes per sec.
            try!(buffer.write_le_u16((bytes_per_sec / spec.sample_rate) as u16));
            // The field wBitsPerSample. This is actually the size of the
            // container, so this is a multiple of 8.
            try!(buffer.write_le_u16(self.bytes_per_sample as u16 * 8));
            // The field cbSize, the number of remaining bytes in the struct.
            try!(buffer.write_le_u16(22));
            // The field wValidBitsPerSample, the real number of bits per sample.
            try!(buffer.write_le_u16(self.spec.bits_per_sample));
            // The field dwChannelMask.
            // TODO: add the option to specify the channel mask. For now, use
            // the default assignment.
            try!(buffer.write_le_u32(channel_mask(self.spec.channels)));
            // The field SubFormat. We use KSDATAFORMAT_SUBTYPE_PCM. The
            // following GUIDS are defined:
            // - PCM:        00000001-0000-0010-8000-00aa00389b71
            // - IEEE_FLOAT: 00000003-0000-0010-8000-00aa00389b71
            // The byte order of a GUID is native for the first three sections,
            // which is assumed to be little endian, and big endian for the
            // last 8-byte section (which does contain a hyphen, for reasons
            // unknown to me).
            try!(buffer.write_all(&[0x01, 0x00, 0x00, 0x00,
                                    0x00, 0x00, 0x10, 0x00,
                                    0x80, 0x00, 0x00, 0xaa,
                                    0x00, 0x38, 0x9b, 0x71]));

            // So far the "fmt " section, now comes the "data" section. We will
            // only write the header here, actual data are the samples. The
            // number of bytes that this will take is not known at this point.
            // The 0 will be overwritten later.
            try!(buffer.write_all("data".as_bytes()));
            try!(buffer.write_le_u32(0));
        }

        // Then write the entire header at once.
        try!(self.writer.write_all(&header));

        Ok(())
    }

    /// Writes a single sample for one channel.
    ///
    /// WAVE interleaves channel data, so the channel that this writes the
    /// sample to depends on previous writes.
    pub fn write_sample<S: Sample>(&mut self, sample: S) -> Result<()> {
        if !self.wrote_header {
            try!(self.write_header());
            self.wrote_header = true;
        }

        // TODO: do we need bits per sample? Is the padding at the obvious side?
        try!(sample.write(&mut self.writer, self.spec.bits_per_sample));
        self.data_bytes_written += self.bytes_per_sample as u32;
        Ok(())
    }

    /// Performs finalization. After calling this, the writer should be destructed.
    fn finalize_internal(&mut self) -> Result<()> {
        self.finalized = true;

        // Flush remaining samples via the BufWriter.
        try!(self.writer.flush());

        // Extract the underlying writer and rewind it to the start, to update
        // the header fields of which we now know the value.
        let mut writer = self.writer.get_mut();

        // The header minus magic and 32-bit filesize is 60 bytes long.
        let file_size = self.data_bytes_written + 60;
        try!(writer.seek(io::SeekFrom::Start(4)));
        try!(writer.write_le_u32(file_size));
        try!(writer.seek(io::SeekFrom::Start(64)));
        try!(writer.write_le_u32(self.data_bytes_written));

        // Signal error if the last sample was not finished, but do so after
        // everything has been written, so that no data is lost, even though
        // the file is now ill-formed.
        if (self.data_bytes_written / self.bytes_per_sample as u32)
            % self.spec.channels as u32 != 0 {
            return Err(Error::UnfinishedSample);
        }

        Ok(())
    }

    /// Writes the parts of the WAVE format that require knowing all samples.
    ///
    /// This method must be called after all samples have been written. If it
    /// is not called, the destructor will finalize the file, but any errors
    /// that occur in the process cannot be observed in that manner.
    pub fn finalize(mut self) -> Result<()> {
        self.finalize_internal()
    }
}

impl<W> Drop for WavWriter<W> where W: io::Write + io::Seek {
    fn drop(&mut self) {
        // `finalize_internal` must be called only once. If that is done via
        // `finalize`, then this method is a no-op. If the user did not
        // finalize explicitly, then we should do it now. This can fail, but
        // drop should not panic, so a failure is ignored silently here.
        if !self.finalized {
            let _r = self.finalize_internal();
        }
    }
}

impl WavWriter<fs::File> {
    /// Creates a writer that writes the WAVE format to a file.
    ///
    /// This is a convenience constructor that creates the file and then
    /// constructs a `WavReader` from it. The file will be overwritten if it
    /// exists.
    pub fn create<P: AsRef<path::Path>>(filename: P, spec: WavSpec)
           -> io::Result<WavWriter<fs::File>> {
        let file = try!(fs::File::create(filename));
        Ok(WavWriter::new(file, spec))
    }
}

#[test]
fn short_write_should_signal_error() {
    let mut buffer = io::Cursor::new(Vec::new());

    let write_spec = WavSpec {
        channels: 17,
        sample_rate: 48000,
        bits_per_sample: 8
    };

    // Deliberately write one sample less than 17 * 5.
    let mut writer = WavWriter::new(&mut buffer, write_spec);
    for s in (0 .. 17 * 5 - 1) {
        writer.write_sample(s as i16).unwrap();
    }
    let error = writer.finalize().err().unwrap();

    match error {
        Error::UnfinishedSample => { },
        _ => panic!("UnfinishedSample error should have been returned.")
    }
}

#[test]
fn wide_write_should_signal_error() {
    let mut buffer = io::Cursor::new(Vec::new());

    let spec8 = WavSpec {
        channels: 1,
        sample_rate: 44100,
        bits_per_sample: 8
    };
    {
        let mut writer = WavWriter::new(&mut buffer, spec8);
        assert!(writer.write_sample(127_i8).is_ok());
        assert!(writer.write_sample(127_i16).is_ok());
        assert!(writer.write_sample(127_i32).is_ok());
        assert!(writer.write_sample(128_i16).is_err());
        assert!(writer.write_sample(128_i32).is_err());
    }

    let spec16 = WavSpec { bits_per_sample: 16, .. spec8 };
    {
        let mut writer = WavWriter::new(&mut buffer, spec16);
        assert!(writer.write_sample(32767_i16).is_ok());
        assert!(writer.write_sample(32767_i32).is_ok());
        assert!(writer.write_sample(32768_i32).is_err());
    }

    let spec24 = WavSpec { bits_per_sample: 24, .. spec8 };
    {
        let mut writer = WavWriter::new(&mut buffer, spec24);
        assert!(writer.write_sample(8_388_607_i32).is_ok());
        assert!(writer.write_sample(8_388_608_i32).is_err());
    }
}
<|endoftext|>


<commit_before>use protobuf::descriptor::field_descriptor_proto;

use crate::gen::scope::FieldWithContext;
use crate::gen::scope::MessageWithScope;

/// Pair of (key, value) if this message is map entry
pub(crate) fn map_entry<'a>(
    d: &'a MessageWithScope,
) -> Option<(FieldWithContext<'a>, FieldWithContext<'a>)> {
    if d.message
        .get_proto()
        .options
        .get_or_default()
        .get_map_entry()
    {
        // Must be consistent with
        // DescriptorBuilder::ValidateMapEntry

        assert!(d.message.get_proto().get_name().ends_with("Entry"));

        assert_eq!(0, d.message.get_proto().extension.len());
        assert_eq!(0, d.message.get_proto().extension_range.len());
        assert_eq!(0, d.message.get_proto().nested_type.len());
        assert_eq!(0, d.message.get_proto().enum_type.len());

        assert_eq!(2, d.message.fields().count());
        let key = d.fields()[0].clone();
        let value = d.fields()[1].clone();

        assert_eq!("key", key.name());
        assert_eq!("value", value.name());

        assert_eq!(1, key.number());
        assert_eq!(2, value.number());

        assert_eq!(
            field_descriptor_proto::Label::LABEL_OPTIONAL,
            key.field.get_proto().get_label()
        );
        assert_eq!(
            field_descriptor_proto::Label::LABEL_OPTIONAL,
            value.field.get_proto().get_label()
        );

        Some((key, value))
    } else {
        None
    }
}
<commit_msg>Use more dynamic messages in codegen<commit_after>use protobuf::descriptor::field_descriptor_proto;

use crate::gen::scope::FieldWithContext;
use crate::gen::scope::MessageWithScope;

/// Pair of (key, value) if this message is map entry
pub(crate) fn map_entry<'a>(
    d: &'a MessageWithScope,
) -> Option<(FieldWithContext<'a>, FieldWithContext<'a>)> {
    if d.message.is_map_entry() {
        // Must be consistent with
        // DescriptorBuilder::ValidateMapEntry

        assert!(d.message.get_proto().get_name().ends_with("Entry"));

        assert_eq!(0, d.message.get_proto().extension.len());
        assert_eq!(0, d.message.get_proto().extension_range.len());
        assert_eq!(0, d.message.get_proto().nested_type.len());
        assert_eq!(0, d.message.get_proto().enum_type.len());

        assert_eq!(2, d.message.fields().count());
        let key = d.fields()[0].clone();
        let value = d.fields()[1].clone();

        assert_eq!("key", key.name());
        assert_eq!("value", value.name());

        assert_eq!(1, key.number());
        assert_eq!(2, value.number());

        assert_eq!(
            field_descriptor_proto::Label::LABEL_OPTIONAL,
            key.field.get_proto().get_label()
        );
        assert_eq!(
            field_descriptor_proto::Label::LABEL_OPTIONAL,
            value.field.get_proto().get_label()
        );

        Some((key, value))
    } else {
        None
    }
}
<|endoftext|>


<commit_before>#![feature(phase)]
#[phase(syntax, link)] extern crate log;
extern crate collections;
use std::io::{File, Open, Write, TempDir};
use std::os::args;
use std::cast;
use std::raw::Slice;
use collections::priority_queue::PriorityQueue;
#[cfg(not(test))]
use std::from_str::from_str;
#[cfg(test)]
use std::io::{ReadWrite, SeekSet};

/*
 * an entry is the number that we read and the file it came from, so after we took
 * out one Entry from the priority queue, we need to know where to take the next number
 * from.
 */
struct Entry {
	value: u64,
	source: File,
}

/* The priority queue depends on the ordering relation and always returns the biggest */
impl Ord for Entry {
	// lesser than implementation
	fn lt(&self, other: &Entry) -> bool {
		// we invert: for us the smallest will have the highest priority
		!(self.value < other.value)
	}
}

/* ordering needs equality for some reason, so there */
impl Eq for Entry {
	fn eq(&self, other: &Entry) -> bool {
		self.value == other.value
	}
}

/* A struct to hold our queue */
struct PriorityFile {
	queue: PriorityQueue<Entry>,
}

/*
 * 'Class' that takes a list of files and does a k-way merge of the smallest values
 * from the files
 */
impl PriorityFile {
	pub fn new(files: Vec<File>) -> PriorityFile {
		let mut queue: PriorityQueue<Entry> = PriorityQueue::new();
		// now that we got the queue, populate it with initial values

		// move_iter is required to get the values themselves, not borrowed pointers to them
		for mut f in files.move_iter() {
			// read from file, append to queue
			let number = match f.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			queue.push(Entry {value: number, source: f});
		};
		PriorityFile {queue: queue}
	}

	/* Returns the next smallest number from the list of files or None if exhausted */
	pub fn next(&mut self) -> Option<u64> {
		match self.queue.maybe_pop() {
			Some(mut res) => {
				let v = res.value;
				match res.source.read_le_u64() {
					Ok(num) => self.queue.push(Entry {value: num, source: res.source}),
					Err(_) => (),
				};
				Some(v)
			},
			None => None,
		}
	}
}

fn read_u64(from: &mut File, n: uint) -> Vec<u64> {
	// rust post 0.10 will directly return a Vec<u8> here
	let buf = match from.read_exact(n*8) {
		Ok(b) => b,
		Err(e) => fail!("reading failed {}", e),
	};
	//let u = buf.as_ptr();
	let u = buf.as_slice();

	let mut r: Slice<u64> = unsafe { cast::transmute(u) };
	assert_eq!(r.len % 8, 0);
	r.len /= 8;
	Vec::from_slice(unsafe { cast::transmute(r) })
}

fn write_u64(to: &mut File, items: &Vec<u64>) {
	let s = items.as_slice();
	let mut r: Slice<u8> = unsafe { cast::transmute(s) };
	r.len *= 8;
	let buf: &[u8] = unsafe { cast::transmute(r) };

	match to.write(buf) {
		Ok(_) => (),
		Err(e) => fail!("writing failed: {}", e),
	};
}

fn externalSort(mut fdInput: File, size: u64, mut fdOutput: File, memSize: u64) {
	let mut runs = size / memSize;
	let items_per_run = (memSize / 8) as uint;
	let over = ((size / 8) - (items_per_run as u64 * runs)) as uint;

	info!("There will be {} runs with {} elements each.", runs, items_per_run);
	if over > 0 {
		info!("And one additional run with {} items.", over);
	}

	// let's create a temporary directory to store the sorted chunks
	// neat: TempDir deletes the directory and its contents when it goes out of
	// scope
	let overflow_dir = match TempDir::new("externalsort") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let overflow_path = overflow_dir.path();
	info!("temp dir:\ncd {}", overflow_path.display());

	// start the sorting runs
	for n in range(0, runs) {
		// iterate over our 'run' buffer and read from the input file
		// I suppose the values are little endian, which considering we are most
		// likely on x86, is a reasonable assumption
		info!("Run {}, starting read", n);
		let mut run = read_u64(&mut fdInput, items_per_run);
		info!("Run {}, read finished", n);
		// O(n log n) sort from the stdlib, hopefully more or less equivalent to
		// C++ std::sort
		info!("Run {}, starting sort", n);
		run.sort();
		info!("Run {}, sort finished", n);

		// now write out the results into numbered files
		let file_path = overflow_path.join(n.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};

		info!("Run {}, starting write", n);
		write_u64(&mut file_file, &run);
		info!("Run {}, write finished", n);
	};

	/* additional run to catch remaining objects */
	if over > 0 {
		info!("overrun starting read");
		let mut run = read_u64(&mut fdInput, over);
		info!("overrun read finished");
		info!("overrun starting sort");
		run.sort();
		info!("overrun sort finished");

		let file_path = overflow_path.join(runs.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};
		info!("overrun starting write");
		write_u64(&mut file_file, &run);
		info!("overrun finished write");

		runs += 1;
	};

	/* sorting done, now merging */
	info!("Pre-sorting done, now k-way merge")

	// collect all file handles. Hopefully less than 4096
	let mut files = Vec::with_capacity(runs as uint);
	for n in range(0, runs) {
		let file_path = overflow_path.join(n.to_str());
		let fd = match File::open(&file_path) {
			Ok(f) => f,
			Err(e) => fail!("overflow file opening error {}", e),
		};
		files.push(fd);
	}

	// we got a nice class here that spits out sorted numbers until exhausted
	let mut pf = PriorityFile::new(files);
	// put the sorted numbers in a cache first, so they can all be written in bulk
	let mut write_cache = Vec::with_capacity(items_per_run);
	loop {
		match pf.next() {
			Some (number) => {
				// a new number was found, add it to the cache
				// and if the cache is full, write that to disk
				write_cache.push(number);
				debug!("Gathered element {}", number);
				if write_cache.len() >= items_per_run {
					info!("Writing out {} elements from cache", write_cache.len());
					write_u64(&mut fdOutput, &write_cache);
					info!("Write done");
					write_cache.clear();
				};
			},
			None => {
				info!("Ending, writing out remaining {} elements from cache", write_cache.len());
				// we finished, write remaining cache to disk
				write_u64(&mut fdOutput, &write_cache);
				info!("Write done");
				break;
			},
		};
	};
}

#[cfg(not(test))]
fn main() {
	if args().len() < 4 {
		fail!("Argument error: <inputFile> <outputFile> <memoryBufferInMB>");
	}
	let input_file_path = &Path::new(args()[1]);
	let size = match input_file_path.stat() {
		Ok(stat) => stat.size,
		Err(e) => fail!("Couldn't read {}", e),
	};
	let fin = match File::open(input_file_path) {
		Ok(f) => f,
		Err(e) => fail!("input file error: {}", e),
	};
	let fout = match File::open_mode(&Path::new(args()[2]), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	let buffer_size:u64 = match from_str(args()[3]) {
		Some(num) => num,
		None => fail!("Not numeric input"),
	};
	info!("Input file size {}", size);

	externalSort(fin, size, fout, buffer_size * 1024 * 1024);
}

#[test]
fn generate_5gb_and_sort() {
	let number_gigabytes = 1;

	let mut random = match File::open(&Path::new("/dev/urandom")) {
		Ok(f) => f,
		Err(e) => fail!("Error opening urandom: {}", e),
	};

	let test_dir = match TempDir::new("externalsort-test") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let test_path = test_dir.path();

	let mut unordered_nums = match File::open_mode(&test_path.join("input"), Open, ReadWrite) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut buffer = [0, .. 1024*1024];
	let mut left = number_gigabytes * 1024;
	while left > 0 {
		match random.read(buffer) {
			Ok(_) => match unordered_nums.write(buffer) {
				Ok(_) => (),
				Err(e) => fail!("failed writing random numbers {}", e),
			},
			Err(e) => fail!("failed reading random numbers {}", e),
		};
		left -= 1;
	}

	match unordered_nums.seek(0, SeekSet) {
		Ok(_) => (),
		Err(e) => fail!("Failed to seek: {}", e),
	};

	let ordered_nums = match File::open_mode(&test_path.join("output"), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	externalSort(unordered_nums, 1024 * 1024 * 1024 * number_gigabytes, ordered_nums, 1024 * 1024 * 100);
	let mut ordered_nums = match File::open(&test_path.join("output")) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut last = 0_u64;
	loop {
		let number = match ordered_nums.read_le_u64() {
			Ok(num) => num,
			Err(e) => fail!("failed to read u64 from file: {}", e),
		};
		assert!(number >= last);
		last = number;
	}
}
<commit_msg>Fixed up unittest<commit_after>#![feature(phase)]
#[phase(syntax, link)] extern crate log;
extern crate collections;
use std::io::{File, Open, Write, TempDir};
use std::os::args;
use std::cast;
use std::raw::Slice;
use collections::priority_queue::PriorityQueue;
#[cfg(not(test))]
use std::from_str::from_str;
#[cfg(test)]
use std::io::{ReadWrite, SeekSet, EndOfFile};

/*
 * an entry is the number that we read and the file it came from, so after we took
 * out one Entry from the priority queue, we need to know where to take the next number
 * from.
 */
struct Entry {
	value: u64,
	source: File,
}

/* The priority queue depends on the ordering relation and always returns the biggest */
impl Ord for Entry {
	// lesser than implementation
	fn lt(&self, other: &Entry) -> bool {
		// we invert: for us the smallest will have the highest priority
		!(self.value < other.value)
	}
}

/* ordering needs equality for some reason, so there */
impl Eq for Entry {
	fn eq(&self, other: &Entry) -> bool {
		self.value == other.value
	}
}

/* A struct to hold our queue */
struct PriorityFile {
	queue: PriorityQueue<Entry>,
}

/*
 * 'Class' that takes a list of files and does a k-way merge of the smallest values
 * from the files
 */
impl PriorityFile {
	pub fn new(files: Vec<File>) -> PriorityFile {
		let mut queue: PriorityQueue<Entry> = PriorityQueue::new();
		// now that we got the queue, populate it with initial values

		// move_iter is required to get the values themselves, not borrowed pointers to them
		for mut f in files.move_iter() {
			// read from file, append to queue
			let number = match f.read_le_u64() {
				Ok(num) => num,
				Err(e) => fail!("failed to read u64 from file: {}", e),
			};
			queue.push(Entry {value: number, source: f});
		};
		PriorityFile {queue: queue}
	}

	/* Returns the next smallest number from the list of files or None if exhausted */
	pub fn next(&mut self) -> Option<u64> {
		match self.queue.maybe_pop() {
			Some(mut res) => {
				let v = res.value;
				match res.source.read_le_u64() {
					Ok(num) => self.queue.push(Entry {value: num, source: res.source}),
					Err(_) => (),
				};
				Some(v)
			},
			None => None,
		}
	}
}

fn read_u64(from: &mut File, n: uint) -> Vec<u64> {
	// rust post 0.10 will directly return a Vec<u8> here
	let buf = match from.read_exact(n*8) {
		Ok(b) => b,
		Err(e) => fail!("reading failed {}", e),
	};
	//let u = buf.as_ptr();
	let u = buf.as_slice();

	let mut r: Slice<u64> = unsafe { cast::transmute(u) };
	assert_eq!(r.len % 8, 0);
	r.len /= 8;
	Vec::from_slice(unsafe { cast::transmute(r) })
}

fn write_u64(to: &mut File, items: &Vec<u64>) {
	let s = items.as_slice();
	let mut r: Slice<u8> = unsafe { cast::transmute(s) };
	r.len *= 8;
	let buf: &[u8] = unsafe { cast::transmute(r) };

	match to.write(buf) {
		Ok(_) => (),
		Err(e) => fail!("writing failed: {}", e),
	};
}

fn externalSort(mut fdInput: File, size: u64, mut fdOutput: File, memSize: u64) {
	let mut runs = size / memSize;
	let items_per_run = (memSize / 8) as uint;
	let over = ((size / 8) - (items_per_run as u64 * runs)) as uint;

	info!("There will be {} runs with {} elements each.", runs, items_per_run);
	if over > 0 {
		info!("And one additional run with {} items.", over);
	}

	// let's create a temporary directory to store the sorted chunks
	// neat: TempDir deletes the directory and its contents when it goes out of
	// scope
	let overflow_dir = match TempDir::new("externalsort") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let overflow_path = overflow_dir.path();
	info!("temp dir:\ncd {}", overflow_path.display());

	// start the sorting runs
	for n in range(0, runs) {
		// iterate over our 'run' buffer and read from the input file
		// I suppose the values are little endian, which considering we are most
		// likely on x86, is a reasonable assumption
		info!("Run {}, starting read", n);
		let mut run = read_u64(&mut fdInput, items_per_run);
		info!("Run {}, read finished", n);
		// O(n log n) sort from the stdlib, hopefully more or less equivalent to
		// C++ std::sort
		info!("Run {}, starting sort", n);
		run.sort();
		info!("Run {}, sort finished", n);

		// now write out the results into numbered files
		let file_path = overflow_path.join(n.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};

		info!("Run {}, starting write", n);
		write_u64(&mut file_file, &run);
		info!("Run {}, write finished", n);
	};

	/* additional run to catch remaining objects */
	if over > 0 {
		info!("overrun starting read");
		let mut run = read_u64(&mut fdInput, over);
		info!("overrun read finished");
		info!("overrun starting sort");
		run.sort();
		info!("overrun sort finished");

		let file_path = overflow_path.join(runs.to_str());
		let mut file_file = match File::open_mode(&file_path, Open, Write) {
			Ok(f) => f,
			Err(e) => fail!("overflow file failed opening for write: {}", e),
		};
		info!("overrun starting write");
		write_u64(&mut file_file, &run);
		info!("overrun finished write");

		runs += 1;
	};

	/* sorting done, now merging */
	info!("Pre-sorting done, now k-way merge")

	// collect all file handles. Hopefully less than 4096
	let mut files = Vec::with_capacity(runs as uint);
	for n in range(0, runs) {
		let file_path = overflow_path.join(n.to_str());
		let fd = match File::open(&file_path) {
			Ok(f) => f,
			Err(e) => fail!("overflow file opening error {}", e),
		};
		files.push(fd);
	}

	// we got a nice class here that spits out sorted numbers until exhausted
	let mut pf = PriorityFile::new(files);
	// put the sorted numbers in a cache first, so they can all be written in bulk
	let mut write_cache = Vec::with_capacity(items_per_run);
	loop {
		match pf.next() {
			Some (number) => {
				// a new number was found, add it to the cache
				// and if the cache is full, write that to disk
				write_cache.push(number);
				debug!("Gathered element {}", number);
				if write_cache.len() >= items_per_run {
					info!("Writing out {} elements from cache", write_cache.len());
					write_u64(&mut fdOutput, &write_cache);
					info!("Write done");
					write_cache.clear();
				};
			},
			None => {
				info!("Ending, writing out remaining {} elements from cache", write_cache.len());
				// we finished, write remaining cache to disk
				write_u64(&mut fdOutput, &write_cache);
				info!("Write done");
				break;
			},
		};
	};
}

#[cfg(not(test))]
fn main() {
	let argv = args();
	if argv.len() < 4 {
		fail!("Argument error: <inputFile> <outputFile> <memoryBufferInMB>");
	}
	let input_file_path = &Path::new(argv[1].clone());
	let size = match input_file_path.stat() {
		Ok(stat) => stat.size,
		Err(e) => fail!("Couldn't read {}", e),
	};
	let fin = match File::open(input_file_path) {
		Ok(f) => f,
		Err(e) => fail!("input file error: {}", e),
	};
	let fout = match File::open_mode(&Path::new(argv[2].clone()), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};
	let buffer_size:u64 = match from_str(args()[3].clone()) {
		Some(num) => num,
		None => fail!("Not numeric input"),
	};
	info!("Input file size {}", size);

	externalSort(fin, size, fout, buffer_size * 1024 * 1024);
}

#[test]
fn generate_5gb_and_sort() {
	let number_gigabytes = 1;

	let mut random = match File::open(&Path::new("/dev/urandom")) {
		Ok(f) => f,
		Err(e) => fail!("Error opening urandom: {}", e),
	};

	let test_dir = match TempDir::new("externalsort-test") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let test_path = test_dir.path();

	let mut unordered_nums = match File::open_mode(&test_path.join("input"), Open, ReadWrite) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut buffer = [0, .. 1024*1024];
	let mut left = number_gigabytes * 1024;
	while left > 0 {
		match random.read(buffer) {
			Ok(_) => match unordered_nums.write(buffer) {
				Ok(_) => (),
				Err(e) => fail!("failed writing random numbers {}", e),
			},
			Err(e) => fail!("failed reading random numbers {}", e),
		};
		left -= 1;
	}

	match unordered_nums.seek(0, SeekSet) {
		Ok(_) => (),
		Err(e) => fail!("Failed to seek: {}", e),
	};

	let ordered_nums = match File::open_mode(&test_path.join("output"), Open, Write) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	externalSort(unordered_nums, 1024 * 1024 * 1024 * number_gigabytes, ordered_nums, 1024 * 1024 * 100);
	let mut ordered_nums = match File::open(&test_path.join("output")) {
		Ok(f) => f,
		Err(e) => fail!("output file error: {}", e),
	};

	let mut last = 0_u64;
	loop {
		let number = match ordered_nums.read_le_u64() {
			Ok(num) => num,
			Err(e) => {
				match e.kind {
					EndOfFile => break,
					_ => fail!("Error reading from file: {}", e),
				}
			}
		};
		assert!(number >= last);
		last = number;
	}
}
<|endoftext|>


<commit_before>use std::cmp;

use misc::Slice;

// Note: There are different ways to implement ZipSlices.
// This version performed the best in benchmarks.
//
// I also implemented a version with three pointes (tptr, tend, uptr),
// that mimiced slice::Iter and only checked bounds by using tptr == tend,
// but that was inferior to this solution.

/// An iterator which iterates two slices simultaneously.
///
/// `ZipSlices` acts like a double-ended `.zip()` iterator, but more efficiently.
///
/// Note that elements past the end of the shortest of the two slices are ignored.
///
/// Iterator element type for `ZipSlices<T, U>` is `(T::Item, U::Item)`. For example,
/// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`.
pub struct ZipSlices<T, U> {
    t: T,
    u: U,
    len: usize,
    index: usize,
}

/// `ZipSlices` is only clonable if both slices are shared references (`&[_]`).
impl<T: Copy, U: Copy> Clone for ZipSlices<T, U> {
    fn clone(&self) -> Self {
        ZipSlices {
            t: self.t,
            u: self.u,
            len: self.len,
            index: self.index,
        }
    }
}

impl<'a, 'b, A, B> ZipSlices<&'a [A], &'b [B]> {
    /// Create a new `ZipSlices` from slices `a` and `b`.
    ///
    /// Act like a double-ended `.zip()` iterator, but more efficiently.
    ///
    /// Note that elements past the end of the shortest of the two slices are ignored.
    #[inline(always)]
    pub fn new(a: &'a [A], b: &'b [B]) -> Self {
        let minl = cmp::min(a.len(), b.len());
        ZipSlices {
            t: a,
            u: b,
            len: minl,
            index: 0,
        }
    }
}

impl<T, U> ZipSlices<T, U>
    where T: Slice, U: Slice
{
    /// Create a new `ZipSlices` from slices `a` and `b`.
    ///
    /// Act like a double-ended `.zip()` iterator, but more efficiently.
    ///
    /// Note that elements past the end of the shortest of the two slices are ignored.
    #[inline(always)]
    pub fn from_slices(a: T, b: U) -> Self {
        let minl = cmp::min(a.len(), b.len());
        ZipSlices {
            t: a,
            u: b,
            len: minl,
            index: 0,
        }
    }
}

impl<T, U> Iterator for ZipSlices<T, U>
    where T: Slice, U: Slice
{
    type Item = (T::Item, U::Item);

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            if self.index >= self.len {
                None
            } else {
                let i = self.index;
                self.index += 1;
                Some((
                    self.t.get_unchecked(i),
                    self.u.get_unchecked(i)))
            }
        }
    }

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

impl<T, U> DoubleEndedIterator for ZipSlices<T, U>
    where T: Slice, U: Slice
{
    #[inline(always)]
    fn next_back(&mut self) -> Option<Self::Item> {
        unsafe {
            if self.index >= self.len {
                None
            } else {
                self.len -= 1;
                let i = self.len;
                Some((
                    self.t.get_unchecked(i),
                    self.u.get_unchecked(i)))
            }
        }
    }
}

impl<T, U> ExactSizeIterator for ZipSlices<T, U> where T: Slice, U: Slice { }

<commit_msg>zipslices: Generalize Clone bounds from Copy to Clone.<commit_after>use std::cmp;

use misc::Slice;

// Note: There are different ways to implement ZipSlices.
// This version performed the best in benchmarks.
//
// I also implemented a version with three pointes (tptr, tend, uptr),
// that mimiced slice::Iter and only checked bounds by using tptr == tend,
// but that was inferior to this solution.

/// An iterator which iterates two slices simultaneously.
///
/// `ZipSlices` acts like a double-ended `.zip()` iterator, but more efficiently.
///
/// Note that elements past the end of the shortest of the two slices are ignored.
///
/// Iterator element type for `ZipSlices<T, U>` is `(T::Item, U::Item)`. For example,
/// for a `ZipSlices<&'a [A], &'b mut [B]>`, the element type is `(&'a A, &'b mut B)`.
#[derive(Clone)]
pub struct ZipSlices<T, U> {
    t: T,
    u: U,
    len: usize,
    index: usize,
}

impl<'a, 'b, A, B> ZipSlices<&'a [A], &'b [B]> {
    /// Create a new `ZipSlices` from slices `a` and `b`.
    ///
    /// Act like a double-ended `.zip()` iterator, but more efficiently.
    ///
    /// Note that elements past the end of the shortest of the two slices are ignored.
    #[inline(always)]
    pub fn new(a: &'a [A], b: &'b [B]) -> Self {
        let minl = cmp::min(a.len(), b.len());
        ZipSlices {
            t: a,
            u: b,
            len: minl,
            index: 0,
        }
    }
}

impl<T, U> ZipSlices<T, U>
    where T: Slice, U: Slice
{
    /// Create a new `ZipSlices` from slices `a` and `b`.
    ///
    /// Act like a double-ended `.zip()` iterator, but more efficiently.
    ///
    /// Note that elements past the end of the shortest of the two slices are ignored.
    #[inline(always)]
    pub fn from_slices(a: T, b: U) -> Self {
        let minl = cmp::min(a.len(), b.len());
        ZipSlices {
            t: a,
            u: b,
            len: minl,
            index: 0,
        }
    }
}

impl<T, U> Iterator for ZipSlices<T, U>
    where T: Slice, U: Slice
{
    type Item = (T::Item, U::Item);

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        unsafe {
            if self.index >= self.len {
                None
            } else {
                let i = self.index;
                self.index += 1;
                Some((
                    self.t.get_unchecked(i),
                    self.u.get_unchecked(i)))
            }
        }
    }

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

impl<T, U> DoubleEndedIterator for ZipSlices<T, U>
    where T: Slice, U: Slice
{
    #[inline(always)]
    fn next_back(&mut self) -> Option<Self::Item> {
        unsafe {
            if self.index >= self.len {
                None
            } else {
                self.len -= 1;
                let i = self.len;
                Some((
                    self.t.get_unchecked(i),
                    self.u.get_unchecked(i)))
            }
        }
    }
}

impl<T, U> ExactSizeIterator for ZipSlices<T, U> where T: Slice, U: Slice { }

<|endoftext|>


<commit_before>use async::*;
use async::camera::CameraData;
use async::mesh_renderer::MeshRendererData;
use async::resource::{MaterialId, MeshId};
use async::scheduler::WorkId;
use async::transform::{TransformInnerHandle, TransformGraph};
use bootstrap::window::{Message, Window};
use cell_extras::{AtomicInitCell, InitCell};
use input::Input;
use polygon::{GpuMesh, Renderer, RendererBuilder};
use polygon::anchor::Anchor;
use polygon::camera::{Camera as RenderCamera, CameraId};
use polygon::mesh_instance::MeshInstance;
use std::collections::HashMap;
use std::mem;
use std::ptr::{self, Unique};
use std::sync::{Arc, Barrier};
use std::sync::mpsc::{self, Receiver, Sender};
use std::time::{Duration, Instant};
use std::thread;
use stopwatch::Stopwatch;

#[derive(Debug)]
pub struct EngineBuilder {
    max_workers: usize,
}

static INSTANCE: AtomicInitCell<Unique<Engine>> = AtomicInitCell::new();
static MAIN_LOOP: AtomicInitCell<WorkId> = AtomicInitCell::new();

/// A builder for configuring the components and systems registered with the game engine.
///
/// Component managers and systems cannot be changed once the engine has been instantiated so they
/// must be provided all together when the instance is created. `EngineBuilder` provides an
/// interface for gathering all managers and systems to be provided to the engine.
impl EngineBuilder {
    /// Creates a new `EngineBuilder` object.
    pub fn new() -> EngineBuilder {
        EngineBuilder {
            max_workers: 1,
        }
    }

    /// Consumes the builder and creates the `Engine` instance.
    ///
    /// `func` is invoked once the engine has been setup, so `func` should kick off all game
    /// functionality.
    ///
    /// No `Engine` object is returned because this method instantiates the engine singleton.
    pub fn build<F>(self, func: F)
        where F: FnOnce()
    {
        let window = {
            let mut window = unsafe { mem::uninitialized() };
            let mut out = unsafe { Unique::new(&mut window as *mut _) };

            let barrier = Arc::new(Barrier::new(2));
            let barrier_clone = barrier.clone();

            thread::spawn(move || {
                let mut window = Window::new("gunship game").unwrap();

                let mut message_pump = window.message_pump();

                // write data out to `window` without dropping the old (uninitialized) value.
                unsafe { ptr::write(out.get_mut(), window); }

                // Sync with
                barrier_clone.wait();

                // We're done using the barrier, drop it so that the `Arc` can deallocate once
                // the other thread has receieved the Window.
                mem::drop(barrier_clone);

                message_pump.run();
            });

            // Wait until window thread finishe creating the window.
            barrier.wait();

            window
        };

        let renderer = RendererBuilder::new(&window).build();
        let (sender, receiever) = mpsc::channel();

        // Init aysnc subsystem.
        scheduler::init_thread();

        // Spawn our worker threads.
        if self.max_workers > 0 {
            for _ in 0..self.max_workers - 1 {
                let sender = sender.clone();
                thread::spawn(move || {
                    // Initialize thread-local renderer message channel.
                    RENDER_MESSAGE_CHANNEL.with(move |channel| { channel.init(sender); });

                    // Initialize worker thread to support fibers and wait for work to be available.
                    scheduler::run_wait_fiber();
                });
            }
        }

        // Set the current thread's channel.
        RENDER_MESSAGE_CHANNEL.with(move |channel| { channel.init(sender); });

        let engine = Engine {
            window: window,
            renderer: renderer,
            channel: receiever,

            mesh_map: HashMap::new(),

            scene_graph: TransformGraph::new(),
            camera: None,
            behaviors: Vec::new(),
            input: Input::new(),
        };

        let main_loop = scheduler::start(move || { main_loop(engine); });

        MAIN_LOOP.init(main_loop.work_id());

        func();

        wait_for_quit();
    }

    pub fn max_workers(&mut self, workers: usize) -> &mut EngineBuilder {
        assert!(workers > 0, "There must be at least one worker for the engine to run");
        self.max_workers = workers;
        self
    }
}

pub struct Engine {
    window: Window,

    renderer: Box<Renderer>,
    channel: Receiver<EngineMessage>,

    mesh_map: HashMap<MeshId, GpuMesh>,

    scene_graph: TransformGraph,
    camera: Option<(Box<CameraData>, CameraId)>,
    behaviors: Vec<Box<FnMut() + Send>>,
    input: Input,
}

impl Drop for Engine {
    fn drop(&mut self) {
        // TODO: Clear instance?
    }
}

// `Engine` does handles synchronization internally, so it's meant be shared between threads.
unsafe impl Send for Engine {}
unsafe impl Sync for Engine {}

thread_local! {
    // TODO: We don't want this to be completely public, only pub(crate), but `thread_local`
    // doesn't support pub(crate) syntax.
    pub static RENDER_MESSAGE_CHANNEL: InitCell<Sender<EngineMessage>> = InitCell::new();
}

// TODO: This shouln't be public, it's for engine-internal use.
pub fn scene_graph<F, T>(func: F) -> T
    where F: FnOnce(&TransformGraph) -> T
{
    let engine = INSTANCE.borrow();
    unsafe { func(&(***engine).scene_graph) }
}

// TODO: This shouln't be public, it's for engine-internal use.
pub fn input<F, T>(func: F) -> T
    where F: FnOnce(&Input) -> T
{
    let engine = INSTANCE.borrow();
    unsafe { func(&(***engine).input) }
}

pub enum EngineMessage {
    Anchor(TransformInnerHandle),
    Camera(Box<CameraData>, TransformInnerHandle),
    Material(MaterialId, ::polygon::material::MaterialSource),
    Mesh(MeshId, ::polygon::geometry::mesh::Mesh),
    MeshInstance(Box<MeshRendererData>, TransformInnerHandle),
    Behavior(Box<FnMut() + Send>),
}

pub fn send_message(message: EngineMessage) {
    RENDER_MESSAGE_CHANNEL.with(move |channel| {
        channel
            .send(message)
            .expect("Unable to send render resource message");
    });
}

pub fn run_each_frame<F>(func: F)
    where
    F: 'static,
    F: FnMut(),
    F: Send,
{
    send_message(EngineMessage::Behavior(Box::new(func)));
}

/// Suspends the calling worker until the engine main loop has finished.
pub fn wait_for_quit() {
    MAIN_LOOP.borrow().await();
}

fn main_loop(engine: Engine) {
    // TODO: This should be a constant, but we can't create constant `Duration` objects right now.
    let target_frame_time = Duration::new(0, 1_000_000_000 / 60);

    let mut engine = Box::new(engine);
    INSTANCE.init(unsafe { Unique::new(&mut *engine) });
    let engine = &mut *engine;

    let mut last_frame_time = Instant::now();

    'main: loop {
        // Timing scope for main loop.
        {
            let _stopwatch = Stopwatch::with_budget("main loop", target_frame_time);

            // Process any pending window messages.
            engine.input.clear();
            for message in &mut engine.window {
                // TODO: Process input messages.
                if let Message::Close = message {
                    break 'main;
                } else {
                    engine.input.push_input(message);
                }
            }

            // Kick off all game behaviors and wait for them to complete.
            if engine.behaviors.len() > 0 {
                let _stopwatch = Stopwatch::new("game behaviors");
                let mut pending = Vec::with_capacity(engine.behaviors.len());

                // Start all behaviors...
                for behavior in engine.behaviors.iter_mut() {
                    let async = scheduler::start(&mut **behavior);
                    pending.push(async);
                }

                // ... then wait for each of them to finish.
                for async in pending {
                    async.await();
                }
            } else {
                // There are no per-frame behaviors. We suspend the main loop fiber anyway to give
                // other work some time on the thread. Generally this case only matters when debugging
                // with a single thread.
                scheduler::suspend();
            }

            // Before drawing, process any pending render messages. These will be resources that were
            // loaded but need to be registered with the renderer before the next draw.
            while let Ok(message) = engine.channel.try_recv() {
                match message {
                    EngineMessage::Anchor(transform_inner) => {
                        let anchor = Anchor::new();
                        let anchor_id = engine.renderer.register_anchor(anchor);

                        transform_inner.set_anchor(anchor_id);
                    },
                    EngineMessage::Camera(camera_data, transform_inner) => {
                        assert!(engine.camera.is_none(), "Can't add camera, one is already registered");

                        let anchor_id = match transform_inner.anchor() {
                            Some(anchor) => anchor,
                            None => unimplemented!(), // TODO: Create the anchor.
                        };

                        let mut camera = RenderCamera::default();
                        camera.set_anchor(anchor_id);
                        let camera_id = engine.renderer.register_camera(camera);

                        engine.camera = Some((camera_data, camera_id));
                    },
                    EngineMessage::Material(_material_id, material_source) => {
                        let material = engine.renderer.build_material(material_source).expect("TODO: Handle material compilation failure");
                        let _gpu_material = engine.renderer.register_material(material);

                        // TODO: Create an association between `material_id` and `material_source`.
                    },
                    EngineMessage::Mesh(mesh_id, mesh_data) => {
                        let gpu_mesh = engine.renderer.register_mesh(&mesh_data);
                        let last = engine.mesh_map.insert(mesh_id, gpu_mesh);
                        assert!(last.is_none(), "Duplicate mesh_id found: {:?}", mesh_id);
                    },
                    EngineMessage::MeshInstance(mesh_renderer_data, transform_inner) => {
                        let anchor_id = match transform_inner.anchor() {
                            Some(anchor) => anchor,
                            None => unimplemented!(), // TODO: Create the anchor.
                        };

                        let gpu_mesh = *engine
                            .mesh_map
                            .get(&mesh_renderer_data.mesh_id())
                            .expect("No gpu mesh found for mesh id");

                        let mut mesh_instance = MeshInstance::new(
                            gpu_mesh,
                            engine.renderer.default_material(),
                        );
                        mesh_instance.material_mut().set_color("surface_color", ::math::Color::rgb(1.0, 0.0, 0.0)); // HACK HACK HACK
                        mesh_instance.set_anchor(anchor_id);

                        let _ = engine.renderer.register_mesh_instance(mesh_instance);
                    }
                    EngineMessage::Behavior(func) => {
                        engine.behaviors.push(func);
                    }
                }
            }

            // Update renderer's anchors with flattened scene graph.
            for node in engine.scene_graph.roots() {
                let node = node.borrow();

                // TODO: Do something like pre-sorting so we only try to update out of
                // date nodes.
                if let Some(anchor_id) = node.anchor() {
                    // Send position/rotation/scale to renderer anchor.
                    let anchor = engine.renderer
                        .get_anchor_mut(anchor_id)
                        .expect("Node had anchor id but render did not have specified anchor");
                    anchor.set_position(node.position);
                    anchor.set_orientation(node.orientation);
                    anchor.set_scale(node.scale);
                }
            }

            // Update the camera.
            if let Some((ref camera_data, ref camera_id)) = engine.camera {
                let render_camera = engine.renderer
                    .get_camera_mut(*camera_id)
                    .expect("Camera didn't exist for camera id");

                render_camera.set_fov(camera_data.fov());
                render_camera.set_aspect(camera_data.aspect());
                render_camera.set_near(camera_data.near());
                render_camera.set_far(camera_data.far());
            }

        }

        // Draw.
        engine.renderer.draw();

        // If we've already missed our target frame time then we want to immediately start the
        // next frame. Also, the remaining time calculations will overflow so we don't want to
        // run the below code.
        if last_frame_time.elapsed() > target_frame_time {
            last_frame_time = Instant::now();
            continue;
        }

        // Sleep the thread while there's more than a millisecond left.
        let mut remaining_time_ms = target_frame_time - last_frame_time.elapsed();
        while remaining_time_ms > Duration::from_millis(1) {
            thread::sleep(remaining_time_ms);

            if last_frame_time.elapsed() > target_frame_time {
                break;
            } else {
                remaining_time_ms = target_frame_time - last_frame_time.elapsed();
            }
        }

        // When there's less than a millisecond left the system scheduler isn't accurate enough to
        // awake it at the right time and it's possible to sleep too long. To avoid that we simply
        // busy loop until it's time for the next frame.
        while last_frame_time.elapsed() < target_frame_time {}

        last_frame_time = Instant::now();
    }
}
<commit_msg>Implement debug pause functionality in the main loop<commit_after>use async::*;
use async::camera::CameraData;
use async::mesh_renderer::MeshRendererData;
use async::resource::{MaterialId, MeshId};
use async::scheduler::WorkId;
use async::transform::{TransformInnerHandle, TransformGraph};
use bootstrap::window::{Message, Window};
use cell_extras::{AtomicInitCell, InitCell};
use input::{self, Input, ScanCode};
use polygon::{GpuMesh, Renderer, RendererBuilder};
use polygon::anchor::Anchor;
use polygon::camera::{Camera as RenderCamera, CameraId};
use polygon::mesh_instance::MeshInstance;
use std::collections::HashMap;
use std::mem;
use std::ptr::{self, Unique};
use std::sync::{Arc, Barrier};
use std::sync::mpsc::{self, Receiver, Sender};
use std::time::{Duration, Instant};
use std::thread;
use stopwatch::Stopwatch;

#[derive(Debug)]
pub struct EngineBuilder {
    max_workers: usize,
}

static INSTANCE: AtomicInitCell<Unique<Engine>> = AtomicInitCell::new();
static MAIN_LOOP: AtomicInitCell<WorkId> = AtomicInitCell::new();

/// A builder for configuring the components and systems registered with the game engine.
///
/// Component managers and systems cannot be changed once the engine has been instantiated so they
/// must be provided all together when the instance is created. `EngineBuilder` provides an
/// interface for gathering all managers and systems to be provided to the engine.
impl EngineBuilder {
    /// Creates a new `EngineBuilder` object.
    pub fn new() -> EngineBuilder {
        EngineBuilder {
            max_workers: 1,
        }
    }

    /// Consumes the builder and creates the `Engine` instance.
    ///
    /// `func` is invoked once the engine has been setup, so `func` should kick off all game
    /// functionality.
    ///
    /// No `Engine` object is returned because this method instantiates the engine singleton.
    pub fn build<F>(self, func: F)
        where F: FnOnce()
    {
        let window = {
            let mut window = unsafe { mem::uninitialized() };
            let mut out = unsafe { Unique::new(&mut window as *mut _) };

            let barrier = Arc::new(Barrier::new(2));
            let barrier_clone = barrier.clone();

            thread::spawn(move || {
                let mut window = Window::new("gunship game").unwrap();

                let mut message_pump = window.message_pump();

                // write data out to `window` without dropping the old (uninitialized) value.
                unsafe { ptr::write(out.get_mut(), window); }

                // Sync with
                barrier_clone.wait();

                // We're done using the barrier, drop it so that the `Arc` can deallocate once
                // the other thread has receieved the Window.
                mem::drop(barrier_clone);

                message_pump.run();
            });

            // Wait until window thread finishe creating the window.
            barrier.wait();

            window
        };

        let renderer = RendererBuilder::new(&window).build();
        let (sender, receiever) = mpsc::channel();

        // Init aysnc subsystem.
        scheduler::init_thread();

        // Spawn our worker threads.
        if self.max_workers > 0 {
            for _ in 0..self.max_workers - 1 {
                let sender = sender.clone();
                thread::spawn(move || {
                    // Initialize thread-local renderer message channel.
                    RENDER_MESSAGE_CHANNEL.with(move |channel| { channel.init(sender); });

                    // Initialize worker thread to support fibers and wait for work to be available.
                    scheduler::run_wait_fiber();
                });
            }
        }

        // Set the current thread's channel.
        RENDER_MESSAGE_CHANNEL.with(move |channel| { channel.init(sender); });

        let engine = Engine {
            window: window,
            renderer: renderer,
            channel: receiever,

            mesh_map: HashMap::new(),

            scene_graph: TransformGraph::new(),
            camera: None,
            behaviors: Vec::new(),
            input: Input::new(),

            debug_pause: false,
        };

        let main_loop = scheduler::start(move || { main_loop(engine); });

        MAIN_LOOP.init(main_loop.work_id());

        func();

        wait_for_quit();
    }

    pub fn max_workers(&mut self, workers: usize) -> &mut EngineBuilder {
        assert!(workers > 0, "There must be at least one worker for the engine to run");
        self.max_workers = workers;
        self
    }
}

pub struct Engine {
    window: Window,

    renderer: Box<Renderer>,
    channel: Receiver<EngineMessage>,

    mesh_map: HashMap<MeshId, GpuMesh>,

    scene_graph: TransformGraph,
    camera: Option<(Box<CameraData>, CameraId)>,
    behaviors: Vec<Box<FnMut() + Send>>,
    input: Input,

    debug_pause: bool,
}

impl Drop for Engine {
    fn drop(&mut self) {
        // TODO: Clear instance?
    }
}

// `Engine` does handles synchronization internally, so it's meant be shared between threads.
unsafe impl Send for Engine {}
unsafe impl Sync for Engine {}

thread_local! {
    // TODO: We don't want this to be completely public, only pub(crate), but `thread_local`
    // doesn't support pub(crate) syntax.
    pub static RENDER_MESSAGE_CHANNEL: InitCell<Sender<EngineMessage>> = InitCell::new();
}

// TODO: This shouln't be public, it's for engine-internal use.
pub fn scene_graph<F, T>(func: F) -> T
    where F: FnOnce(&TransformGraph) -> T
{
    let engine = INSTANCE.borrow();
    unsafe { func(&(***engine).scene_graph) }
}

// TODO: This shouln't be public, it's for engine-internal use.
pub fn input<F, T>(func: F) -> T
    where F: FnOnce(&Input) -> T
{
    let engine = INSTANCE.borrow();
    unsafe { func(&(***engine).input) }
}

pub enum EngineMessage {
    Anchor(TransformInnerHandle),
    Camera(Box<CameraData>, TransformInnerHandle),
    Material(MaterialId, ::polygon::material::MaterialSource),
    Mesh(MeshId, ::polygon::geometry::mesh::Mesh),
    MeshInstance(Box<MeshRendererData>, TransformInnerHandle),
    Behavior(Box<FnMut() + Send>),
}

pub fn send_message(message: EngineMessage) {
    RENDER_MESSAGE_CHANNEL.with(move |channel| {
        channel
            .send(message)
            .expect("Unable to send render resource message");
    });
}

pub fn run_each_frame<F>(func: F)
    where
    F: 'static,
    F: FnMut(),
    F: Send,
{
    send_message(EngineMessage::Behavior(Box::new(func)));
}

/// Suspends the calling worker until the engine main loop has finished.
pub fn wait_for_quit() {
    MAIN_LOOP.borrow().await();
}

fn main_loop(engine: Engine) {
    // TODO: This should be a constant, but we can't create constant `Duration` objects right now.
    let target_frame_time = Duration::new(0, 1_000_000_000 / 60);

    let mut engine = Box::new(engine);
    INSTANCE.init(unsafe { Unique::new(&mut *engine) });
    let engine = &mut *engine;

    let mut last_frame_time = Instant::now();

    'main: loop {
        // Timing scope for main loop.
        {
            let _stopwatch = Stopwatch::with_budget("main loop", target_frame_time);

            // Process any pending window messages.
            engine.input.clear();
            for message in &mut engine.window {
                // TODO: Process input messages.
                match message {
                    Message::Close => break 'main,
                    Message::Activate => {}, // We don't handle window focus currently.
                    _ => engine.input.push_input(message),
                }
            }

            if input::key_pressed(ScanCode::F10) {
                engine.debug_pause = !engine.debug_pause;
            }

            let debug_step = input::key_pressed(ScanCode::F11);

            // Kick off all game behaviors and wait for them to complete.
            if engine.behaviors.len() > 0 && (!engine.debug_pause || debug_step) {
                let _stopwatch = Stopwatch::new("game behaviors");
                let mut pending = Vec::with_capacity(engine.behaviors.len());

                // Start all behaviors...
                for behavior in engine.behaviors.iter_mut() {
                    let async = scheduler::start(&mut **behavior);
                    pending.push(async);
                }

                // ... then wait for each of them to finish.
                for async in pending {
                    async.await();
                }
            } else {
                // There are no per-frame behaviors. We suspend the main loop fiber anyway to give
                // other work some time on the thread. Generally this case only matters when debugging
                // with a single thread.
                scheduler::suspend();
            }

            // Before drawing, process any pending render messages. These will be resources that were
            // loaded but need to be registered with the renderer before the next draw.
            while let Ok(message) = engine.channel.try_recv() {
                match message {
                    EngineMessage::Anchor(transform_inner) => {
                        let anchor = Anchor::new();
                        let anchor_id = engine.renderer.register_anchor(anchor);

                        transform_inner.set_anchor(anchor_id);
                    },
                    EngineMessage::Camera(camera_data, transform_inner) => {
                        assert!(engine.camera.is_none(), "Can't add camera, one is already registered");

                        let anchor_id = match transform_inner.anchor() {
                            Some(anchor) => anchor,
                            None => unimplemented!(), // TODO: Create the anchor.
                        };

                        let mut camera = RenderCamera::default();
                        camera.set_anchor(anchor_id);
                        let camera_id = engine.renderer.register_camera(camera);

                        engine.camera = Some((camera_data, camera_id));
                    },
                    EngineMessage::Material(_material_id, material_source) => {
                        let material = engine.renderer.build_material(material_source).expect("TODO: Handle material compilation failure");
                        let _gpu_material = engine.renderer.register_material(material);

                        // TODO: Create an association between `material_id` and `material_source`.
                    },
                    EngineMessage::Mesh(mesh_id, mesh_data) => {
                        let gpu_mesh = engine.renderer.register_mesh(&mesh_data);
                        let last = engine.mesh_map.insert(mesh_id, gpu_mesh);
                        assert!(last.is_none(), "Duplicate mesh_id found: {:?}", mesh_id);
                    },
                    EngineMessage::MeshInstance(mesh_renderer_data, transform_inner) => {
                        let anchor_id = match transform_inner.anchor() {
                            Some(anchor) => anchor,
                            None => unimplemented!(), // TODO: Create the anchor.
                        };

                        let gpu_mesh = *engine
                            .mesh_map
                            .get(&mesh_renderer_data.mesh_id())
                            .expect("No gpu mesh found for mesh id");

                        let mut mesh_instance = MeshInstance::new(
                            gpu_mesh,
                            engine.renderer.default_material(),
                        );
                        mesh_instance.material_mut().set_color("surface_color", ::math::Color::rgb(1.0, 0.0, 0.0)); // HACK HACK HACK
                        mesh_instance.set_anchor(anchor_id);

                        let _ = engine.renderer.register_mesh_instance(mesh_instance);
                    }
                    EngineMessage::Behavior(func) => {
                        engine.behaviors.push(func);
                    }
                }
            }

            // Update renderer's anchors with flattened scene graph.
            for node in engine.scene_graph.roots() {
                let node = node.borrow();

                // TODO: Do something like pre-sorting so we only try to update out of
                // date nodes.
                if let Some(anchor_id) = node.anchor() {
                    // Send position/rotation/scale to renderer anchor.
                    let anchor = engine.renderer
                        .get_anchor_mut(anchor_id)
                        .expect("Node had anchor id but render did not have specified anchor");
                    anchor.set_position(node.position);
                    anchor.set_orientation(node.orientation);
                    anchor.set_scale(node.scale);
                }
            }

            // Update the camera.
            if let Some((ref camera_data, ref camera_id)) = engine.camera {
                let render_camera = engine.renderer
                    .get_camera_mut(*camera_id)
                    .expect("Camera didn't exist for camera id");

                render_camera.set_fov(camera_data.fov());
                render_camera.set_aspect(camera_data.aspect());
                render_camera.set_near(camera_data.near());
                render_camera.set_far(camera_data.far());
            }

        }

        // Draw.
        engine.renderer.draw();

        // If we've already missed our target frame time then we want to immediately start the
        // next frame. Also, the remaining time calculations will overflow so we don't want to
        // run the below code.
        let elapsed_time = last_frame_time.elapsed();
        if elapsed_time < target_frame_time {
            // Sleep the thread while there's more than a millisecond left.
            let mut remaining_time_ms = target_frame_time - elapsed_time;
            while remaining_time_ms > Duration::from_millis(1) {
                thread::sleep(remaining_time_ms);

                let elapsed_time = last_frame_time.elapsed();
                if elapsed_time > target_frame_time {
                    break;
                } else {
                    remaining_time_ms = target_frame_time - elapsed_time;
                }
            }

            // When there's less than a millisecond left the system scheduler isn't accurate enough to
            // awake it at the right time and it's possible to sleep too long. To avoid that we simply
            // busy loop until it's time for the next frame.
            while last_frame_time.elapsed() < target_frame_time {}
        }

        last_frame_time = Instant::now();
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;

use env::Env;
use gobjects::*;
use library;

pub struct StatusedTypeId{
    pub type_id: library::TypeId,
    pub name: String,
    pub status: GStatus,
}

pub fn analyze_parents(env: &Env, type_id: library::TypeId) -> (Vec<StatusedTypeId>, bool) {
    let mut parents = Vec::new();
    let mut has_ignored_parents = false;
    let mut type_ = env.library.type_(type_id).to_class();
    while type_.parent.is_some() {
        let parent_id = type_.parent.unwrap();
        let parent_type = env.library.type_(parent_id).to_class();

        let default_object: GObject = Default::default();
        let gobject = env.config.objects.get(&parent_id.full_name(&env.library))
            .unwrap_or(&default_object);

        parents.push(StatusedTypeId{
            type_id: parent_id,
            name: parent_type.name.clone(),
            status: gobject.status,
        });

        if gobject.status == GStatus::Ignore { has_ignored_parents = true; }

        if gobject.last_parent { break }

        type_ = parent_type;
    }

    (parents, has_ignored_parents)
}
<commit_msg>Use library::Class::parents<commit_after>use std::vec::Vec;

use env::Env;
use gobjects::*;
use library;

pub struct StatusedTypeId{
    pub type_id: library::TypeId,
    pub name: String,
    pub status: GStatus,
}

pub fn analyze_parents(env: &Env, type_id: library::TypeId) -> (Vec<StatusedTypeId>, bool) {
    let mut parents = Vec::new();
    let mut has_ignored_parents = false;
    let type_ = env.library.type_(type_id).to_class();

    for &parent_tid in &type_.parents {
        let parent_type = env.library.type_(parent_tid).to_class();

        let default_object: GObject = Default::default();
        let gobject = env.config.objects.get(&parent_tid.full_name(&env.library))
            .unwrap_or(&default_object);

        parents.push(StatusedTypeId{
            type_id: parent_tid,
            name: parent_type.name.clone(),
            status: gobject.status,
        });

        if gobject.status == GStatus::Ignore { has_ignored_parents = true; }

        if gobject.last_parent { break }
    }

    (parents, has_ignored_parents)
}
<|endoftext|>


<commit_before>use crate::{
    backend::Backend,
    buffer::{Buffer, Cell},
    layout::Rect,
};
use std::{fmt::Write, io};
use unicode_width::UnicodeWidthStr;

/// A backend used for the integration tests.
#[derive(Debug)]
pub struct TestBackend {
    width: u16,
    buffer: Buffer,
    height: u16,
    cursor: bool,
    pos: (u16, u16),
}

/// Returns a string representation of the given buffer for debugging purpose.
fn buffer_view(buffer: &Buffer) -> String {
    let mut view = String::with_capacity(buffer.content.len() + buffer.area.height as usize * 3);
    for cells in buffer.content.chunks(buffer.area.width as usize) {
        let mut overwritten = vec![];
        let mut skip: usize = 0;
        view.push('"');
        for (x, c) in cells.iter().enumerate() {
            if skip == 0 {
                view.push_str(&c.symbol);
            } else {
                overwritten.push((x, &c.symbol))
            }
            skip = std::cmp::max(skip, c.symbol.width()).saturating_sub(1);
        }
        view.push('"');
        if !overwritten.is_empty() {
            write!(
                &mut view,
                " Hidden by multi-width symbols: {:?}",
                overwritten
            )
            .unwrap();
        }
        view.push_str("\n");
    }
    view
}

impl TestBackend {
    pub fn new(width: u16, height: u16) -> TestBackend {
        TestBackend {
            width,
            height,
            buffer: Buffer::empty(Rect::new(0, 0, width, height)),
            cursor: false,
            pos: (0, 0),
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn assert_buffer(&self, expected: &Buffer) {
        assert_eq!(expected.area, self.buffer.area);
        let diff = expected.diff(&self.buffer);
        if diff.is_empty() {
            return;
        }

        let mut debug_info = String::from("Buffers are not equal");
        debug_info.push_str("\n");
        debug_info.push_str("Expected:");
        debug_info.push_str("\n");
        let expected_view = buffer_view(expected);
        debug_info.push_str(&expected_view);
        debug_info.push_str("\n");
        debug_info.push_str("Got:");
        debug_info.push_str("\n");
        let view = buffer_view(&self.buffer);
        debug_info.push_str(&view);
        debug_info.push_str("\n");

        debug_info.push_str("Diff:");
        debug_info.push_str("\n");
        let nice_diff = diff
            .iter()
            .enumerate()
            .map(|(i, (x, y, cell))| {
                let expected_cell = expected.get(*x, *y);
                format!(
                    "{}: at ({}, {}) expected {:?} got {:?}",
                    i, x, y, expected_cell, cell
                )
            })
            .collect::<Vec<String>>()
            .join("\n");
        debug_info.push_str(&nice_diff);
        panic!(debug_info);
    }
}

impl Backend for TestBackend {
    fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
    where
        I: Iterator<Item = (u16, u16, &'a Cell)>,
    {
        for (x, y, c) in content {
            let cell = self.buffer.get_mut(x, y);
            *cell = c.clone();
        }
        Ok(())
    }

    fn hide_cursor(&mut self) -> Result<(), io::Error> {
        self.cursor = false;
        Ok(())
    }

    fn show_cursor(&mut self) -> Result<(), io::Error> {
        self.cursor = true;
        Ok(())
    }

    fn get_cursor(&mut self) -> Result<(u16, u16), io::Error> {
        Ok(self.pos)
    }

    fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
        self.pos = (x, y);
        Ok(())
    }

    fn clear(&mut self) -> Result<(), io::Error> {
        Ok(())
    }

    fn size(&self) -> Result<Rect, io::Error> {
        Ok(Rect::new(0, 0, self.width, self.height))
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        Ok(())
    }
}
<commit_msg>chore: clippy fixes (#386)<commit_after>use crate::{
    backend::Backend,
    buffer::{Buffer, Cell},
    layout::Rect,
};
use std::{fmt::Write, io};
use unicode_width::UnicodeWidthStr;

/// A backend used for the integration tests.
#[derive(Debug)]
pub struct TestBackend {
    width: u16,
    buffer: Buffer,
    height: u16,
    cursor: bool,
    pos: (u16, u16),
}

/// Returns a string representation of the given buffer for debugging purpose.
fn buffer_view(buffer: &Buffer) -> String {
    let mut view = String::with_capacity(buffer.content.len() + buffer.area.height as usize * 3);
    for cells in buffer.content.chunks(buffer.area.width as usize) {
        let mut overwritten = vec![];
        let mut skip: usize = 0;
        view.push('"');
        for (x, c) in cells.iter().enumerate() {
            if skip == 0 {
                view.push_str(&c.symbol);
            } else {
                overwritten.push((x, &c.symbol))
            }
            skip = std::cmp::max(skip, c.symbol.width()).saturating_sub(1);
        }
        view.push('"');
        if !overwritten.is_empty() {
            write!(
                &mut view,
                " Hidden by multi-width symbols: {:?}",
                overwritten
            )
            .unwrap();
        }
        view.push('\n');
    }
    view
}

impl TestBackend {
    pub fn new(width: u16, height: u16) -> TestBackend {
        TestBackend {
            width,
            height,
            buffer: Buffer::empty(Rect::new(0, 0, width, height)),
            cursor: false,
            pos: (0, 0),
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn assert_buffer(&self, expected: &Buffer) {
        assert_eq!(expected.area, self.buffer.area);
        let diff = expected.diff(&self.buffer);
        if diff.is_empty() {
            return;
        }

        let mut debug_info = String::from("Buffers are not equal");
        debug_info.push('\n');
        debug_info.push_str("Expected:");
        debug_info.push('\n');
        let expected_view = buffer_view(expected);
        debug_info.push_str(&expected_view);
        debug_info.push('\n');
        debug_info.push_str("Got:");
        debug_info.push('\n');
        let view = buffer_view(&self.buffer);
        debug_info.push_str(&view);
        debug_info.push('\n');

        debug_info.push_str("Diff:");
        debug_info.push('\n');
        let nice_diff = diff
            .iter()
            .enumerate()
            .map(|(i, (x, y, cell))| {
                let expected_cell = expected.get(*x, *y);
                format!(
                    "{}: at ({}, {}) expected {:?} got {:?}",
                    i, x, y, expected_cell, cell
                )
            })
            .collect::<Vec<String>>()
            .join("\n");
        debug_info.push_str(&nice_diff);
        panic!(debug_info);
    }
}

impl Backend for TestBackend {
    fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
    where
        I: Iterator<Item = (u16, u16, &'a Cell)>,
    {
        for (x, y, c) in content {
            let cell = self.buffer.get_mut(x, y);
            *cell = c.clone();
        }
        Ok(())
    }

    fn hide_cursor(&mut self) -> Result<(), io::Error> {
        self.cursor = false;
        Ok(())
    }

    fn show_cursor(&mut self) -> Result<(), io::Error> {
        self.cursor = true;
        Ok(())
    }

    fn get_cursor(&mut self) -> Result<(u16, u16), io::Error> {
        Ok(self.pos)
    }

    fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
        self.pos = (x, y);
        Ok(())
    }

    fn clear(&mut self) -> Result<(), io::Error> {
        Ok(())
    }

    fn size(&self) -> Result<Rect, io::Error> {
        Ok(Rect::new(0, 0, self.width, self.height))
    }

    fn flush(&mut self) -> Result<(), io::Error> {
        Ok(())
    }
}
<|endoftext|>