<commit_before>use byteorder::{ReadBytesExt, LittleEndian};
use rwinstructs::timestamp::{WinTimestamp};
use rshellitems::shellitem::{ShellItem};
use lnkpkg::locationinfo::{LocationInfo};
use lnkpkg::flags::{DataFlags,FileFlags};
use lnkpkg::flags;
use lnkpkg::errors::{LnkError};
use lnkpkg::utils;
use std::io::SeekFrom;
use std::io::Read;
use std::io::Seek;

#[derive(Clone, Debug)]
pub struct Guid(pub [u8;16]);

#[derive(Debug)]
// 76 bytes long
pub struct ShellLinkHeader {
    pub header_size: u32,
    pub guid: Guid,
    pub data_flags: DataFlags,
    pub file_flags: FileFlags,
    pub created: WinTimestamp,
    pub accessed: WinTimestamp,
    pub modified: WinTimestamp,
    pub file_size: u32,
    pub icon_offset: i32,
    pub window_flag: u32,
    pub hot_key: u16,
    pub unknown1: u16,
    pub unknown2: u32,
    pub unknown3: u32
}

impl ShellLinkHeader {
    pub fn new<R: Read>(mut reader: R) -> Result<ShellLinkHeader,LnkError> {
        let header_size = reader.read_u32::<LittleEndian>()?;
        let mut guid = Guid([0; 16]);
        reader.read_exact(&mut guid.0)?;

        let data_flags = DataFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );

        let file_flags = FileFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );
        let created = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let accessed = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let modified = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let file_size = reader.read_u32::<LittleEndian>()?;
        let icon_offset = reader.read_i32::<LittleEndian>()?;
        let window_flag = reader.read_u32::<LittleEndian>()?;
        let hot_key = reader.read_u16::<LittleEndian>()?;
        let unknown1 = reader.read_u16::<LittleEndian>()?;
        let unknown2 = reader.read_u32::<LittleEndian>()?;
        let unknown3 = reader.read_u32::<LittleEndian>()?;

        Ok(
            ShellLinkHeader {
                header_size: header_size,
                guid: guid,
                data_flags: data_flags,
                file_flags: file_flags,
                created: created,
                accessed: accessed,
                modified: modified,
                file_size: file_size,
                icon_offset: icon_offset,
                window_flag: window_flag,
                hot_key: hot_key,
                unknown1: unknown1,
                unknown2: unknown2,
                unknown3: unknown3
            }
        )
    }

    pub fn get_data_flags(&self) -> DataFlags {
        self.data_flags
    }
}

#[derive(Debug)]
pub struct TargetIdList {
    pub list_size: u16,
    pub shell_items: Vec<ShellItem>
}

impl TargetIdList{
    pub fn new<R: Read>(mut reader: R) -> Result<TargetIdList, LnkError> {
        let list_size = reader.read_u16::<LittleEndian>()?;
        let mut shell_items: Vec<ShellItem> = Vec::new();

        let mut total_read: u16 = 0;
        while total_read < list_size {
            let mut shell_item = ShellItem::new(&mut reader)?;
            let size = shell_item.get_size();
            total_read += size;

            if size == 0 {
                // Null shell item is terminator
                break
            }

            shell_items.push(shell_item);
        }

        Ok(
            TargetIdList {
                list_size: list_size,
                shell_items: shell_items
            }
        )
    }

    pub fn get_size(&self) -> u16 {
        self.list_size
    }
}

#[derive(Debug)]
pub struct DataStrings {
    pub description: Option<String>,
    pub relative_path: Option<String>,
    pub working_directory: Option<String>,
    pub command_line_args: Option<String>,
    pub icon_location: Option<String>
}
impl DataStrings {
    pub fn new<R: Read>(mut reader: R, data_flags: DataFlags) -> Result<DataStrings,LnkError> {
        let unicode_flag = data_flags.contains(flags::IS_UNICODE);

        let mut description = None;
        if data_flags.contains(flags::HAS_NAME) {
            if unicode_flag {
                description = Some(utils::read_string_utf16(&mut reader)?);
            } else {
                description = Some(utils::read_string_utf8(&mut reader)?);
            }
        }

        let mut relative_path = None;
        if data_flags.contains(flags::HAS_RELATIVE_PATH) {
            if unicode_flag {
                relative_path = Some(utils::read_string_utf16(&mut reader)?);
            } else {
                relative_path = Some(utils::read_string_utf8(&mut reader)?);
            }
        }

        let mut working_directory = None;
        if data_flags.contains(flags::HAS_WORKING_DIR) {
            if unicode_flag {
                working_directory = Some(utils::read_string_utf16(&mut reader)?);
            } else {
                working_directory = Some(utils::read_string_utf8(&mut reader)?);
            }
        }

        let mut command_line_args = None;
        if data_flags.contains(flags::HAS_ARGUMENTS) {
            if unicode_flag {
                command_line_args = Some(utils::read_string_utf16(&mut reader)?);
            } else {
                command_line_args = Some(utils::read_string_utf8(&mut reader)?);
            }
        }

        let mut icon_location = None;
        if data_flags.contains(flags::HAS_ICON_LOCATION) {
            if unicode_flag {
                icon_location = Some(utils::read_string_utf16(&mut reader)?);
            } else {
                icon_location = Some(utils::read_string_utf8(&mut reader)?);
            }
        }

        Ok(
            DataStrings {
                description: description,
                relative_path: relative_path,
                working_directory: working_directory,
                command_line_args: command_line_args,
                icon_location: icon_location
            }
        )
    }
}

#[derive(Debug)]
pub struct Lnk {
    pub header: ShellLinkHeader,
    pub target_list: Option<TargetIdList>,
    pub location_info: Option<LocationInfo>,
    pub data_strings: DataStrings
}

impl Lnk {
    pub fn new<Rs: Read+Seek>(mut reader: Rs) -> Result<Lnk,LnkError> {
        let header = ShellLinkHeader::new(&mut reader)?;
        let header_flags = header.get_data_flags();

        let mut target_list = None;
        if header_flags.contains(flags::HAS_TARGET_ID_LIST) {
            target_list = Some(TargetIdList::new(&mut reader)?);
        }

        let mut location_offset = reader.seek(
            SeekFrom::Current(0)
        )?;

        let mut location_info = None;
        if header_flags.contains(flags::HAS_LINK_INFO) {
            location_info = Some(LocationInfo::new(&mut reader)?);
        }

        println!("offset: {}",reader.seek(
            SeekFrom::Current(0)
        )?);
        let data_strings = DataStrings::new(
            &mut reader,
            header_flags
        )?;

        Ok(
            Lnk {
                header: header,
                target_list: target_list,
                location_info: location_info,
                data_strings: data_strings
            }
        )
    }
}
<commit_msg>renamed string helper methods<commit_after>use byteorder::{ReadBytesExt, LittleEndian};
use rwinstructs::timestamp::{WinTimestamp};
use rshellitems::shellitem::{ShellItem};
use lnkpkg::locationinfo::{LocationInfo};
use lnkpkg::flags::{DataFlags,FileFlags};
use lnkpkg::flags;
use lnkpkg::errors::{LnkError};
use lnkpkg::utils;
use std::io::SeekFrom;
use std::io::Read;
use std::io::Seek;

#[derive(Clone, Debug)]
pub struct Guid(pub [u8;16]);

#[derive(Debug)]
// 76 bytes long
pub struct ShellLinkHeader {
    pub header_size: u32,
    pub guid: Guid,
    pub data_flags: DataFlags,
    pub file_flags: FileFlags,
    pub created: WinTimestamp,
    pub accessed: WinTimestamp,
    pub modified: WinTimestamp,
    pub file_size: u32,
    pub icon_offset: i32,
    pub window_flag: u32,
    pub hot_key: u16,
    pub unknown1: u16,
    pub unknown2: u32,
    pub unknown3: u32
}

impl ShellLinkHeader {
    pub fn new<R: Read>(mut reader: R) -> Result<ShellLinkHeader,LnkError> {
        let header_size = reader.read_u32::<LittleEndian>()?;
        let mut guid = Guid([0; 16]);
        reader.read_exact(&mut guid.0)?;

        let data_flags = DataFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );

        let file_flags = FileFlags::from_bits_truncate(
            reader.read_u32::<LittleEndian>()?
        );
        let created = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let accessed = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let modified = WinTimestamp(reader.read_u64::<LittleEndian>()?);
        let file_size = reader.read_u32::<LittleEndian>()?;
        let icon_offset = reader.read_i32::<LittleEndian>()?;
        let window_flag = reader.read_u32::<LittleEndian>()?;
        let hot_key = reader.read_u16::<LittleEndian>()?;
        let unknown1 = reader.read_u16::<LittleEndian>()?;
        let unknown2 = reader.read_u32::<LittleEndian>()?;
        let unknown3 = reader.read_u32::<LittleEndian>()?;

        Ok(
            ShellLinkHeader {
                header_size: header_size,
                guid: guid,
                data_flags: data_flags,
                file_flags: file_flags,
                created: created,
                accessed: accessed,
                modified: modified,
                file_size: file_size,
                icon_offset: icon_offset,
                window_flag: window_flag,
                hot_key: hot_key,
                unknown1: unknown1,
                unknown2: unknown2,
                unknown3: unknown3
            }
        )
    }

    pub fn get_data_flags(&self) -> DataFlags {
        self.data_flags
    }
}

#[derive(Debug)]
pub struct TargetIdList {
    pub list_size: u16,
    pub shell_items: Vec<ShellItem>
}

impl TargetIdList{
    pub fn new<R: Read>(mut reader: R) -> Result<TargetIdList, LnkError> {
        let list_size = reader.read_u16::<LittleEndian>()?;
        let mut shell_items: Vec<ShellItem> = Vec::new();

        let mut total_read: u16 = 0;
        while total_read < list_size {
            let mut shell_item = ShellItem::new(&mut reader)?;
            let size = shell_item.get_size();
            total_read += size;

            if size == 0 {
                // Null shell item is terminator
                break
            }

            shell_items.push(shell_item);
        }

        Ok(
            TargetIdList {
                list_size: list_size,
                shell_items: shell_items
            }
        )
    }

    pub fn get_size(&self) -> u16 {
        self.list_size
    }
}

#[derive(Debug)]
pub struct DataStrings {
    pub description: Option<String>,
    pub relative_path: Option<String>,
    pub working_directory: Option<String>,
    pub command_line_args: Option<String>,
    pub icon_location: Option<String>
}
impl DataStrings {
    pub fn new<R: Read>(mut reader: R, data_flags: DataFlags) -> Result<DataStrings,LnkError> {
        let unicode_flag = data_flags.contains(flags::IS_UNICODE);

        let mut description = None;
        if data_flags.contains(flags::HAS_NAME) {
            if unicode_flag {
                description = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                description = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut relative_path = None;
        if data_flags.contains(flags::HAS_RELATIVE_PATH) {
            if unicode_flag {
                relative_path = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                relative_path = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut working_directory = None;
        if data_flags.contains(flags::HAS_WORKING_DIR) {
            if unicode_flag {
                working_directory = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                working_directory = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut command_line_args = None;
        if data_flags.contains(flags::HAS_ARGUMENTS) {
            if unicode_flag {
                command_line_args = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                command_line_args = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        let mut icon_location = None;
        if data_flags.contains(flags::HAS_ICON_LOCATION) {
            if unicode_flag {
                icon_location = Some(utils::read_string_u16_w_size(&mut reader)?);
            } else {
                icon_location = Some(utils::read_string_u8_w_size(&mut reader)?);
            }
        }

        Ok(
            DataStrings {
                description: description,
                relative_path: relative_path,
                working_directory: working_directory,
                command_line_args: command_line_args,
                icon_location: icon_location
            }
        )
    }
}

#[derive(Debug)]
pub struct Lnk {
    pub header: ShellLinkHeader,
    pub target_list: Option<TargetIdList>,
    pub location_info: Option<LocationInfo>,
    pub data_strings: DataStrings
}

impl Lnk {
    pub fn new<Rs: Read+Seek>(mut reader: Rs) -> Result<Lnk,LnkError> {
        let header = ShellLinkHeader::new(&mut reader)?;
        let header_flags = header.get_data_flags();

        let mut target_list = None;
        if header_flags.contains(flags::HAS_TARGET_ID_LIST) {
            target_list = Some(TargetIdList::new(&mut reader)?);
        }

        let mut location_offset = reader.seek(
            SeekFrom::Current(0)
        )?;

        let mut location_info = None;
        if header_flags.contains(flags::HAS_LINK_INFO) {
            location_info = Some(LocationInfo::new(&mut reader)?);
        }

        println!("offset: {}",reader.seek(
            SeekFrom::Current(0)
        )?);
        let data_strings = DataStrings::new(
            &mut reader,
            header_flags
        )?;

        Ok(
            Lnk {
                header: header,
                target_list: target_list,
                location_info: location_info,
                data_strings: data_strings
            }
        )
    }
}
<|endoftext|>


<commit_before>use primal_estimate;
use primal_bit::{self, BitVec};
use std::{iter, cmp};

use streaming::StreamingSieve;

pub struct Sieve {
    #[allow(dead_code)]
    stream: StreamingSieve,
    seen: BitVec,
}

/// Iterator over the primes stored in a sieve.
#[derive(Clone)]
pub struct PrimeIterator<'a> {
    two: bool,
    iter: iter::Enumerate<primal_bit::Iter<'a>>,
}

impl Sieve {
    pub fn new(limit: usize) -> Sieve {
        let mut stream = StreamingSieve::new(limit);

        let mut seen = BitVec::with_capacity(limit / 2);
        while let Some((n, bits)) = stream.next() {
            seen.push_all(&bits, (limit - n + 1) / 2);
        }
        Sieve {
            stream: stream,
            seen: seen,
        }
    }
    pub fn upper_bound(&self) -> usize {
        (self.seen.len() - 1) * 2 + 1
    }
    pub fn is_prime(&self, n: usize) -> bool {
        if n % 2 == 0 {
            n == 2
        } else {
            assert!(n <= self.upper_bound());
            !self.seen[n / 2]
        }
    }

    /// Iterator over the primes stored in this map.
    pub fn primes<'a>(&'a self) -> PrimeIterator<'a> {
        PrimeIterator {
            two: true,
            iter: self.seen.iter().enumerate()
        }
    }
}

impl<'a> Iterator for PrimeIterator<'a> {
    type Item = usize;
    #[inline]
    fn next(&mut self) -> Option<usize> {
        if self.two {
            self.two = false;
            Some(2)
        } else {
            for (i, is_not_prime) in &mut self.iter {
                if !is_not_prime {
                    return Some(2 * i + 1)
                }
            }
            None
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let mut iter = self.clone();
        // TODO: this doesn't run in constant time, is it super-bad?
        match (iter.next(), iter.next_back()) {
            (Some(lo), Some(hi)) => {
                let (below_hi, above_hi) = primal_estimate::prime_pi(hi as u64);
                let (below_lo, above_lo) = primal_estimate::prime_pi(lo as u64);

                ((below_hi - cmp::min(above_lo, below_hi)) as usize,
                 Some((above_hi - below_lo + 1) as usize))
            }
            (Some(_), None) => (1, Some(1)),
            (None, _) => (0, Some(0))
        }
    }
}

impl<'a> DoubleEndedIterator for PrimeIterator<'a> {
    #[inline]
    fn next_back(&mut self) -> Option<usize> {
        loop {
            match self.iter.next_back() {
                Some((i, false)) => return Some(2 * i + 1),
                Some((_, true)) => {/* continue */}
                None if self.two => {
                    self.two = false;
                    return Some(2)
                }
                None => return None
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use primal_smallsieve::Primes;
    use super::Sieve;

    #[test]
    fn is_prime() {
        let limit = 1_000_000;
        let real = Primes::sieve(limit);
        let primes = Sieve::new(limit);

        for i in 0..limit {
            assert_eq!(primes.is_prime(i),
                       real.is_prime(i))
        }
    }

    #[test]
    fn upper_bound() {
        let primes = Sieve::new(30);
        assert_eq!(primes.upper_bound(), 29);
        let primes = Sieve::new(31);
        assert_eq!(primes.upper_bound(), 31);

        let primes = Sieve::new(30000);
        assert_eq!(primes.upper_bound(), 29999);
        let primes = Sieve::new(30001);
        assert_eq!(primes.upper_bound(), 30001);
    }

    #[test]
    fn primes_iterator() {
        let primes = Sieve::new(50);
        let mut expected = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47];

        assert_eq!(primes.primes().collect::<Vec<usize>>(), expected);

        expected.reverse();
        assert_eq!(primes.primes().rev().collect::<Vec<usize>>(), expected);
    }

    #[test]
    fn size_hint() {
        let mut i = 0;
        while i < 1000 {
            let sieve = Sieve::new(i);

            let mut primes = sieve.primes();

            // check the size hint at each and every iteration
            loop {
                let (lo, hi) = primes.size_hint();

                let copy = primes.clone();
                let len = copy.count();

                let next = primes.next();

                assert!(lo <= len && len <= hi.unwrap(),
                        "found failing size_hint for {:?} to {}, should satisfy: {} <= {} <= {:?}",
                        next, i, lo, len, hi);

                if next.is_none() {
                    break
                }
            }

            i += 100;
        }
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use super::Sieve;
    use test::Bencher;

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        b.iter(|| Sieve::new(100))
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        b.iter(|| Sieve::new(10_000))
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        b.iter(|| Sieve::new(100_000))
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        b.iter(|| Sieve::new(10_000_000))
    }

    fn bench_iterate(b: &mut Bencher, upto: usize) {
        let sieve = Sieve::new(upto);

        b.iter(|| {
            sieve.primes().count()
        })
    }

    #[bench]
    fn iterate_small(b: &mut Bencher) { bench_iterate(b, 100) }
    #[bench]
    fn iterate_large(b: &mut Bencher) { bench_iterate(b, 100_000) }
}
<commit_msg>sieve: remove iterator for now, too annoying.<commit_after>use primal_bit::BitVec;

use streaming::StreamingSieve;

pub struct Sieve {
    #[allow(dead_code)]
    stream: StreamingSieve,
    seen: BitVec,
}

impl Sieve {
    pub fn new(limit: usize) -> Sieve {
        let mut stream = StreamingSieve::new(limit);

        let mut seen = BitVec::with_capacity(limit / 2);
        while let Some((n, bits)) = stream.next() {
            seen.push_all(&bits, (limit - n + 1) / 2);
        }
        Sieve {
            stream: stream,
            seen: seen,
        }
    }
    pub fn upper_bound(&self) -> usize {
        (self.seen.len() - 1) * 2 + 1
    }
    pub fn is_prime(&self, n: usize) -> bool {
        if n % 2 == 0 {
            n == 2
        } else {
            assert!(n <= self.upper_bound());
            !self.seen[n / 2]
        }
    }
}

#[cfg(test)]
mod tests {
    use primal_smallsieve::Primes;
    use super::Sieve;

    #[test]
    fn is_prime() {
        let limit = 1_000_000;
        let real = Primes::sieve(limit);
        let primes = Sieve::new(limit);

        for i in 0..limit {
            assert_eq!(primes.is_prime(i),
                       real.is_prime(i))
        }
    }

    #[test]
    fn upper_bound() {
        let primes = Sieve::new(30);
        assert_eq!(primes.upper_bound(), 29);
        let primes = Sieve::new(31);
        assert_eq!(primes.upper_bound(), 31);

        let primes = Sieve::new(30000);
        assert_eq!(primes.upper_bound(), 29999);
        let primes = Sieve::new(30001);
        assert_eq!(primes.upper_bound(), 30001);
    }
}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use super::Sieve;
    use test::Bencher;

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        b.iter(|| Sieve::new(100))
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        b.iter(|| Sieve::new(10_000))
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        b.iter(|| Sieve::new(100_000))
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        b.iter(|| Sieve::new(10_000_000))
    }
}
<|endoftext|>


<commit_before>extern crate rmp;
extern crate byteorder;
#[macro_use] extern crate serde;

pub use decode::Deserializer;
pub use encode::Serializer;

pub mod decode;
pub mod encode;
<commit_msg>docs: add docs for serde binding<commit_after>//! # Type-based Serialization and Deserialization
//!
//! Serde provides a mechanism for low boilerplate serialization & deserialization of values to and
//! from MessagePack via the serialization API. To be able to serialize a piece of data, it must
//! implement the `serde::Serialize` trait. To be able to deserialize a piece of data, it must
//! implement the `serde::Deserialize` trait. Serde provides provides an annotation to
//! automatically generate the code for these traits: `#[derive(Serialize, Deserialize)]`.
//!
//! # Examples
//!
//! Let's try to encode and decode some built-in types.
//!
//! ```rust
//! extern crate serde;
//! extern crate rmp_serde;
//!
//! use serde::{Deserialize, Serialize};
//! use rmp_serde::{Deserializer, Serializer};
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = (42u8, "the Answer");
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//!
//!     assert_eq!(vec![0x92, 0x2a, 0xaa, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72], buf);
//!
//!     let mut de = Deserializer::new(&buf[..]);
//!     assert_eq!((42, "the Answer".to_owned()), Deserialize::deserialize(&mut de).unwrap());
//! }
//! ```
//!
//! No one gonna hurt if we add some reflection magic.
//!
//! ```ignore
//! #![feature(proc_macro)]
//!
//! #[macro_use] extern crate serde_derive;
//! extern crate rmp_serde;
//!
//! use std::collections::HashMap;
//! use serde::{Deserialize, Serialize};
//! use rmp_serde::{Deserializer, Serializer};
//!
//! #[derive(Debug, PartialEq, Deserialize, Serialize)]
//! struct Human {
//!     age: u32,
//!     name: String,
//! }
//!
//! fn main() {
//!     let mut buf = Vec::new();
//!     let val = Human {
//!         age: 42,
//!         name: "John".into(),
//!     };
//!
//!     val.serialize(&mut Serializer::new(&mut buf)).unwrap();
//! }
//! ```

extern crate rmp;
extern crate byteorder;
#[macro_use] extern crate serde;

pub use decode::Deserializer;
pub use encode::Serializer;

pub mod decode;
pub mod encode;
<|endoftext|>


<commit_before>use ffi;

use Push;
use PushGuard;
use PushOne;
use AsMutLua;
use TuplePushError;

use std::collections::{HashMap, HashSet};
use std::hash::Hash;
use std::iter;

#[inline]
fn push_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
    where L: AsMutLua<'lua>,
          V: for<'b> Push<&'b mut L, Err = E>,
          I: Iterator<Item = V>
{
    // creating empty table
    unsafe { ffi::lua_newtable(lua.as_mut_lua().0) };

    for (elem, index) in iterator.zip((1..)) {
        let size = match elem.push_to_lua(&mut lua) {
            Ok(pushed) => pushed.forget(),
            Err((_err, _lua)) => panic!(),     // TODO: wrong   return Err((err, lua)),      // FIXME: destroy the temporary table
        };

        match size {
            0 => continue,
            1 => {
                let index = index as u32;
                match index.push_to_lua(&mut lua) {
                    Ok(pushed) => pushed.forget(),
                    Err(_) => unreachable!(),
                };
                unsafe { ffi::lua_insert(lua.as_mut_lua().0, -2) }
                unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) }
            }
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!(),
        }
    }

    let raw_lua = lua.as_lua();
    Ok(PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    })
}

#[inline]
fn push_rec_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
    where L: AsMutLua<'lua>,
          V: for<'a> Push<&'a mut L, Err = E>,
          I: Iterator<Item = V>
{
    let (nrec, _) = iterator.size_hint();

    // creating empty table with pre-allocated non-array elements
    unsafe { ffi::lua_createtable(lua.as_mut_lua().0, 0, nrec as i32) };

    for elem in iterator {
        let size = match elem.push_to_lua(&mut lua) {
            Ok(pushed) => pushed.forget(),
            Err((_err, _lua)) => panic!(),     // TODO: wrong   return Err((err, lua)),      // FIXME: destroy the temporary table
        };

        match size {
            0 => continue,
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!(),
        }
    }

    let raw_lua = lua.as_lua();
    Ok(PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    })
}

impl<'lua, L, T, E> Push<L> for Vec<T>
    where L: AsMutLua<'lua>,
          T: for<'a> Push<&'a mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        push_iter(lua, self.into_iter())
    }
}

impl<'lua, L, T, E> PushOne<L> for Vec<T>
    where L: AsMutLua<'lua>,
          T: for<'a> Push<&'a mut L, Err = E>
{
}

impl<'a, 'lua, L, T, E> Push<L> for &'a [T]
    where L: AsMutLua<'lua>,
          T: Clone + for<'b> Push<&'b mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        push_iter(lua, self.iter().map(|e| e.clone()))
    }
}

impl<'a, 'lua, L, T, E> PushOne<L> for &'a [T]
    where L: AsMutLua<'lua>,
          T: Clone + for<'b> Push<&'b mut L, Err = E>
{
}

// TODO: use an enum for the error to allow different error types for K and V
impl<'lua, L, K, V, E> Push<L> for HashMap<K, V>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
          V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        match push_rec_iter(lua, self.into_iter()) {
            Ok(g) => Ok(g),
            Err((TuplePushError::First(err), lua)) => Err((err, lua)),
            Err((TuplePushError::Other(err), lua)) => Err((err, lua)),
        }
    }
}

impl<'lua, L, K, V, E> PushOne<L> for HashMap<K, V>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
          V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
{
}

impl<'lua, L, K, E> Push<L> for HashSet<K>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        match push_rec_iter(lua, self.into_iter().zip(iter::repeat(true))) {
            Ok(g) => Ok(g),
            Err((TuplePushError::First(err), lua)) => Err((err, lua)),
            Err((TuplePushError::Other(_), _)) => unreachable!(),
        }
    }
}

impl<'lua, L, K, E> PushOne<L> for HashSet<K>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
{
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::collections::HashSet;
    use Lua;
    use LuaTable;

    #[test]
    fn write() {
        let mut lua = Lua::new();

        lua.set("a", vec![9, 8, 7]);

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: Vec<(i32, i32)> = table.iter().filter_map(|e| e).collect();
        assert_eq!(values, vec![(1, 9), (2, 8), (3, 7)]);
    }

    #[test]
    fn write_map() {
        let mut lua = Lua::new();

        let mut map = HashMap::new();
        map.insert(5, 8);
        map.insert(13, 21);
        map.insert(34, 55);

        lua.set("a", map.clone());

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: HashMap<i32, i32> = table.iter().filter_map(|e| e).collect();
        assert_eq!(values, map);
    }

    #[test]
    fn write_set() {
        let mut lua = Lua::new();

        let mut set = HashSet::new();
        set.insert(5);
        set.insert(8);
        set.insert(13);
        set.insert(21);
        set.insert(34);
        set.insert(55);

        lua.set("a", set.clone());

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: HashSet<i32> = table.iter()
            .filter_map(|e| e)
            .map(|(elem, set): (i32, bool)| {
                assert!(set);
                elem
            })
            .collect();

        assert_eq!(values, set);
    }

    #[test]
    fn globals_table() {
        let mut lua = Lua::new();

        lua.globals_table().set("a", 12);

        let val: i32 = lua.get("a").unwrap();
        assert_eq!(val, 12);
    }
}
<commit_msg>Implement reading vectors of AnyLuaValue<commit_after>use ffi;
use any::AnyLuaValue;

use Push;
use PushGuard;
use PushOne;
use AsMutLua;
use TuplePushError;
use LuaRead;

use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::Hash;
use std::iter;

#[inline]
fn push_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
    where L: AsMutLua<'lua>,
          V: for<'b> Push<&'b mut L, Err = E>,
          I: Iterator<Item = V>
{
    // creating empty table
    unsafe { ffi::lua_newtable(lua.as_mut_lua().0) };

    for (elem, index) in iterator.zip((1..)) {
        let size = match elem.push_to_lua(&mut lua) {
            Ok(pushed) => pushed.forget(),
            Err((_err, _lua)) => panic!(),     // TODO: wrong   return Err((err, lua)),      // FIXME: destroy the temporary table
        };

        match size {
            0 => continue,
            1 => {
                let index = index as u32;
                match index.push_to_lua(&mut lua) {
                    Ok(pushed) => pushed.forget(),
                    Err(_) => unreachable!(),
                };
                unsafe { ffi::lua_insert(lua.as_mut_lua().0, -2) }
                unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) }
            }
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!(),
        }
    }

    let raw_lua = lua.as_lua();
    Ok(PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    })
}

#[inline]
fn push_rec_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
    where L: AsMutLua<'lua>,
          V: for<'a> Push<&'a mut L, Err = E>,
          I: Iterator<Item = V>
{
    let (nrec, _) = iterator.size_hint();

    // creating empty table with pre-allocated non-array elements
    unsafe { ffi::lua_createtable(lua.as_mut_lua().0, 0, nrec as i32) };

    for elem in iterator {
        let size = match elem.push_to_lua(&mut lua) {
            Ok(pushed) => pushed.forget(),
            Err((_err, _lua)) => panic!(),     // TODO: wrong   return Err((err, lua)),      // FIXME: destroy the temporary table
        };

        match size {
            0 => continue,
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!(),
        }
    }

    let raw_lua = lua.as_lua();
    Ok(PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    })
}

impl<'lua, L, T, E> Push<L> for Vec<T>
    where L: AsMutLua<'lua>,
          T: for<'a> Push<&'a mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        push_iter(lua, self.into_iter())
    }
}

impl<'lua, L, T, E> PushOne<L> for Vec<T>
    where L: AsMutLua<'lua>,
          T: for<'a> Push<&'a mut L, Err = E>
{
}

impl<'lua, L> LuaRead<L> for Vec<AnyLuaValue>
    where L: AsMutLua<'lua>
{
    fn lua_read_at_position(lua: L, index: i32) -> Result<Self, L> {
        // We need this as iteration order isn't guaranteed to match order of
        // keys, even if they're numeric
        // https://www.lua.org/manual/5.2/manual.html#pdf-next
        let mut dict: BTreeMap<i32, AnyLuaValue> = BTreeMap::new();

        let mut me = lua;
        unsafe { ffi::lua_pushnil(me.as_mut_lua().0) };
        let index = index - 1;

        loop {
            if unsafe { ffi::lua_next(me.as_mut_lua().0, index) } == 0 {
                break;
            }

            let key;

            {
                let maybe_key: Option<i32> =
                    LuaRead::lua_read_at_position(&mut me, -2).ok();
                match maybe_key {
                    None => return Err(me),
                    Some(k) => key = k,
                }
            }

            let value: AnyLuaValue =
                LuaRead::lua_read_at_position(&mut me, -1).ok().unwrap();

            unsafe { ffi::lua_pop(me.as_mut_lua().0, 1) };

            dict.insert(key, value);
        }

        let (maximum_key, minimum_key) =
            (*dict.keys().max().unwrap_or(&1), *dict.keys().min().unwrap_or(&1));

        if minimum_key != 1 {
            // Rust doesn't support sparse arrays or arrays with negative
            // indices
            return Err(me);
        }

        let mut result =
            Vec::with_capacity(maximum_key as usize);

        // We expect to start with first element of table and have this
        // be smaller that first key by one
        let mut previous_key = 0;

        // By this point, we actually iterate the map to move values to Vec
        // and check that table represented non-sparse 1-indexed array
        for (k, v) in dict {
            if previous_key + 1 != k {
                return Err(me)
            } else {
                // We just push, thus converting Lua 1-based indexing
                // to Rust 0-based indexing
                result.push(v);
                previous_key = k;
            }
        }

        Ok(result)
    }
}

impl<'a, 'lua, L, T, E> Push<L> for &'a [T]
    where L: AsMutLua<'lua>,
          T: Clone + for<'b> Push<&'b mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        push_iter(lua, self.iter().map(|e| e.clone()))
    }
}

impl<'a, 'lua, L, T, E> PushOne<L> for &'a [T]
    where L: AsMutLua<'lua>,
          T: Clone + for<'b> Push<&'b mut L, Err = E>
{
}

// TODO: use an enum for the error to allow different error types for K and V
impl<'lua, L, K, V, E> Push<L> for HashMap<K, V>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
          V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        match push_rec_iter(lua, self.into_iter()) {
            Ok(g) => Ok(g),
            Err((TuplePushError::First(err), lua)) => Err((err, lua)),
            Err((TuplePushError::Other(err), lua)) => Err((err, lua)),
        }
    }
}

impl<'lua, L, K, V, E> PushOne<L> for HashMap<K, V>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
          V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
{
}

impl<'lua, L, K, E> Push<L> for HashSet<K>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        match push_rec_iter(lua, self.into_iter().zip(iter::repeat(true))) {
            Ok(g) => Ok(g),
            Err((TuplePushError::First(err), lua)) => Err((err, lua)),
            Err((TuplePushError::Other(_), _)) => unreachable!(),
        }
    }
}

impl<'lua, L, K, E> PushOne<L> for HashSet<K>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
{
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::collections::HashSet;
    use Lua;
    use LuaTable;
    use AnyLuaValue;

    #[test]
    fn write() {
        let mut lua = Lua::new();

        lua.set("a", vec![9, 8, 7]);

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: Vec<(i32, i32)> = table.iter().filter_map(|e| e).collect();
        assert_eq!(values, vec![(1, 9), (2, 8), (3, 7)]);
    }

    #[test]
    fn write_map() {
        let mut lua = Lua::new();

        let mut map = HashMap::new();
        map.insert(5, 8);
        map.insert(13, 21);
        map.insert(34, 55);

        lua.set("a", map.clone());

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: HashMap<i32, i32> = table.iter().filter_map(|e| e).collect();
        assert_eq!(values, map);
    }

    #[test]
    fn write_set() {
        let mut lua = Lua::new();

        let mut set = HashSet::new();
        set.insert(5);
        set.insert(8);
        set.insert(13);
        set.insert(21);
        set.insert(34);
        set.insert(55);

        lua.set("a", set.clone());

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: HashSet<i32> = table.iter()
            .filter_map(|e| e)
            .map(|(elem, set): (i32, bool)| {
                assert!(set);
                elem
            })
            .collect();

        assert_eq!(values, set);
    }

    #[test]
    fn globals_table() {
        let mut lua = Lua::new();

        lua.globals_table().set("a", 12);

        let val: i32 = lua.get("a").unwrap();
        assert_eq!(val, 12);
    }

    #[test]
    fn reading_vec_works() {
        let mut lua = Lua::new();

        let orig = [1., 2., 3.];

        lua.set("v", &orig[..]);

        let read: Vec<_> = lua.get("v").unwrap();
        for (o, r) in orig.iter().zip(read.iter()) {
            if let AnyLuaValue::LuaNumber(ref n) = *r {
                assert_eq!(o, n);
            } else {
                panic!("Unexpected variant");
            }
        }
    }

    #[test]
    fn reading_vec_from_sparse_table_doesnt_work() {
        let mut lua = Lua::new();

        lua.execute::<()>(r#"v = { [-1] = -1, [2] = 2, [42] = 42 }"#).unwrap();

        let read: Option<Vec<_>> = lua.get("v");
        if read.is_some() {
            panic!("Unexpected success");
        }
    }

    #[test]
    fn reading_vec_with_empty_table_works() {
        let mut lua = Lua::new();

        lua.execute::<()>(r#"v = { }"#).unwrap();

        let read: Vec<_> = lua.get("v").unwrap();
        assert_eq!(read.len(), 0);
    }

    #[test]
    fn reading_vec_with_complex_indexes_doesnt_work() {
        let mut lua = Lua::new();

        lua.execute::<()>(r#"v = { [-1] = -1, ["foo"] = 2, [{}] = 42 }"#).unwrap();

        let read: Option<Vec<_>> = lua.get("v");
        if read.is_some() {
            panic!("Unexpected success");
        }
    }

    #[test]
    fn reading_heterogenous_vec_works() {
        let mut lua = Lua::new();

        let orig = [
            AnyLuaValue::LuaNumber(1.),
            AnyLuaValue::LuaBoolean(false),
            AnyLuaValue::LuaNumber(3.),
            // Pushing String to and reading it from makes it a number
            //AnyLuaValue::LuaString(String::from("3"))
        ];

        lua.set("v", &orig[..]);

        let read: Vec<_> = lua.get("v").unwrap();
        assert_eq!(read, orig);
    }
}
<|endoftext|>


<commit_before>//! # CLI
//!
//! The command line version of the library. Given a file path argument, it will ingest all the
//! data into memory, and attempt parsing. If the parsing is successful, JSON is outputted to
//! stdout, else a non-helpful error message is printed. Sorry!
#[macro_use]
extern crate structopt_derive;
extern crate structopt;
extern crate boxcars;
extern crate serde_json;
extern crate rayon;

#[macro_use]
extern crate error_chain;

mod errors {
    use boxcars;
    use serde_json;
    error_chain! {
        foreign_links {
            Io(::std::io::Error);
            Serde(serde_json::Error);
        }

        links {
            Boxcar(boxcars::Error, boxcars::ErrorKind);
        }
    }
}

use errors::*;
use structopt::StructOpt;
use std::fs::File;
use std::io::{Read, Write, BufWriter};
use error_chain::ChainedError;
use rayon::prelude::*;

#[derive(StructOpt, Debug, Clone, PartialEq)]
#[structopt(name = "rrrocket", about = "Parses a Rocket League replay file and outputs JSON")]
struct Opt {
    #[structopt(short = "c", long = "crc-check", help = "validate replay is not corrupt", default_value = "true")]
    crc: bool,

    #[structopt(help = "Rocket League replay files")]
    input: Vec<String>,
}

fn parse_file(input: &str, crc: bool) -> Result<boxcars::Replay> {
    let mut f = File::open(input)?;
    let mut buffer = vec![];
    f.read_to_end(&mut buffer)?;
	Ok(boxcars::parse(&buffer, crc)?)
}

fn run() -> Result<()> {
    let opt = Opt::from_args();
    let compute_crc = opt.crc;
    println!("{}", compute_crc);
    let res: Result<Vec<()>> = opt.input.par_iter()
        .map(|file| {
            let outfile = format!("{}.json", file);
            let data = parse_file(file, compute_crc)?;
            let mut out_file = BufWriter::new(File::open(outfile)?);
            serde_json::to_writer(&mut out_file, &data)?;
            Ok(())
        }).collect();
    res?;
    Ok(())
}

fn main() {
    if let Err(ref e) = run() {
        writeln!(::std::io::stderr(), "{}", e.display_chain())
			.expect("Error writing to stderr");
        ::std::process::exit(1);
    }
}
<commit_msg>Update rrrocket help to mention multiple inputs<commit_after>//! # CLI
//!
//! The command line version of the library. Given a file path argument, it will ingest all the
//! data into memory, and attempt parsing. If the parsing is successful, JSON is outputted to
//! stdout, else a non-helpful error message is printed. Sorry!
#[macro_use]
extern crate structopt_derive;
extern crate structopt;
extern crate boxcars;
extern crate serde_json;
extern crate rayon;

#[macro_use]
extern crate error_chain;

mod errors {
    use boxcars;
    use serde_json;
    error_chain! {
        foreign_links {
            Io(::std::io::Error);
            Serde(serde_json::Error);
        }

        links {
            Boxcar(boxcars::Error, boxcars::ErrorKind);
        }
    }
}

use errors::*;
use structopt::StructOpt;
use std::fs::File;
use std::io::{Read, Write, BufWriter};
use error_chain::ChainedError;
use rayon::prelude::*;

#[derive(StructOpt, Debug, Clone, PartialEq)]
#[structopt(name = "rrrocket", about = "Parses Rocket League replay files and outputs a .json file with the decoded information")]
struct Opt {
    #[structopt(short = "c", long = "crc-check", help = "validate replay is not corrupt", default_value = "true")]
    crc: bool,

    #[structopt(help = "Rocket League replay files")]
    input: Vec<String>,
}

fn parse_file(input: &str, crc: bool) -> Result<boxcars::Replay> {
    let mut f = File::open(input)?;
    let mut buffer = vec![];
    f.read_to_end(&mut buffer)?;
	Ok(boxcars::parse(&buffer, crc)?)
}

fn run() -> Result<()> {
    let opt = Opt::from_args();
    let compute_crc = opt.crc;
    println!("{}", compute_crc);
    let res: Result<Vec<()>> = opt.input.par_iter()
        .map(|file| {
            let outfile = format!("{}.json", file);
            let data = parse_file(file, compute_crc)?;
            let mut out_file = BufWriter::new(File::open(outfile)?);
            serde_json::to_writer(&mut out_file, &data)?;
            Ok(())
        }).collect();
    res?;
    Ok(())
}

fn main() {
    if let Err(ref e) = run() {
        writeln!(::std::io::stderr(), "{}", e.display_chain())
			.expect("Error writing to stderr");
        ::std::process::exit(1);
    }
}
<|endoftext|>


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

// based on:
// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java

extern mod std;

use core::os;

// Using sqrt from the standard library is way slower than using libc
// directly even though std just calls libc, I guess it must be
// because the the indirection through another dynamic linker
// stub. Kind of shocking. Might be able to make it faster still with
// an llvm intrinsic.
#[nolink]
extern mod libc {
    #[legacy_exports];
    fn sqrt(n: float) -> float;
}

fn main() {
    let args = os::args();
    let args = if os::getenv(~"RUST_BENCH").is_some() {
        ~[~"", ~"4000000"]
    } else if args.len() <= 1u {
        ~[~"", ~"100000"]
    } else {
        args
    };
    let n = int::from_str(args[1]).get();
    let mut bodies: ~[Body::props] = NBodySystem::make();
    io::println(fmt!("%f", NBodySystem::energy(bodies)));
    let mut i = 0;
    while i < n {
        NBodySystem::advance(bodies, 0.01);
        i += 1;
    }
    io::println(fmt!("%f", NBodySystem::energy(bodies)));
}

mod NBodySystem {
    use Body;

    pub fn make() -> ~[Body::props] {
        let mut bodies: ~[Body::props] =
            ~[Body::sun(),
              Body::jupiter(),
              Body::saturn(),
              Body::uranus(),
              Body::neptune()];

        let mut px = 0.0;
        let mut py = 0.0;
        let mut pz = 0.0;

        let mut i = 0;
        while i < 5 {
            px += bodies[i].vx * bodies[i].mass;
            py += bodies[i].vy * bodies[i].mass;
            pz += bodies[i].vz * bodies[i].mass;

            i += 1;
        }

        // side-effecting
        Body::offset_momentum(&mut bodies[0], px, py, pz);

        return bodies;
    }

    pub fn advance(bodies: &mut [Body::props], dt: float) {
        let mut i = 0;
        while i < 5 {
            let mut j = i + 1;
            while j < 5 {
                advance_one(&mut bodies[i],
                            &mut bodies[j], dt);
                j += 1;
            }

            i += 1;
        }

        i = 0;
        while i < 5 {
            move_(&mut bodies[i], dt);
            i += 1;
        }
    }

    pub fn advance_one(bi: &mut Body::props,
                       bj: &mut Body::props,
                       dt: float) unsafe {
        let dx = bi.x - bj.x;
        let dy = bi.y - bj.y;
        let dz = bi.z - bj.z;

        let dSquared = dx * dx + dy * dy + dz * dz;

        let distance = ::libc::sqrt(dSquared);
        let mag = dt / (dSquared * distance);

        bi.vx -= dx * bj.mass * mag;
        bi.vy -= dy * bj.mass * mag;
        bi.vz -= dz * bj.mass * mag;

        bj.vx += dx * bi.mass * mag;
        bj.vy += dy * bi.mass * mag;
        bj.vz += dz * bi.mass * mag;
    }

    pub fn move_(b: &mut Body::props, dt: float) {
        b.x += dt * b.vx;
        b.y += dt * b.vy;
        b.z += dt * b.vz;
    }

    pub fn energy(bodies: &[Body::props]) -> float unsafe {
        let mut dx;
        let mut dy;
        let mut dz;
        let mut distance;
        let mut e = 0.0;

        let mut i = 0;
        while i < 5 {
            e +=
                0.5 * bodies[i].mass *
                (bodies[i].vx * bodies[i].vx + bodies[i].vy * bodies[i].vy
                 + bodies[i].vz * bodies[i].vz);

            let mut j = i + 1;
            while j < 5 {
                dx = bodies[i].x - bodies[j].x;
                dy = bodies[i].y - bodies[j].y;
                dz = bodies[i].z - bodies[j].z;

                distance = ::libc::sqrt(dx * dx + dy * dy + dz * dz);
                e -= bodies[i].mass * bodies[j].mass / distance;

                j += 1;
            }

            i += 1;
        }
        return e;

    }
}

mod Body {
    use Body;

    pub const PI: float = 3.141592653589793;
    pub const SOLAR_MASS: float = 39.478417604357432;
    // was 4 * PI * PI originally
    pub const DAYS_PER_YEAR: float = 365.24;

    pub type props =
        {mut x: float,
         mut y: float,
         mut z: float,
         mut vx: float,
         mut vy: float,
         mut vz: float,
         mass: float};

    pub fn jupiter() -> Body::props {
        return {mut x: 4.84143144246472090e+00,
             mut y: -1.16032004402742839e+00,
             mut z: -1.03622044471123109e-01,
             mut vx: 1.66007664274403694e-03 * DAYS_PER_YEAR,
             mut vy: 7.69901118419740425e-03 * DAYS_PER_YEAR,
             mut vz: -6.90460016972063023e-05 * DAYS_PER_YEAR,
             mass: 9.54791938424326609e-04 * SOLAR_MASS};
    }

    pub fn saturn() -> Body::props {
        return {mut x: 8.34336671824457987e+00,
             mut y: 4.12479856412430479e+00,
             mut z: -4.03523417114321381e-01,
             mut vx: -2.76742510726862411e-03 * DAYS_PER_YEAR,
             mut vy: 4.99852801234917238e-03 * DAYS_PER_YEAR,
             mut vz: 2.30417297573763929e-05 * DAYS_PER_YEAR,
             mass: 2.85885980666130812e-04 * SOLAR_MASS};
    }

    pub fn uranus() -> Body::props {
        return {mut x: 1.28943695621391310e+01,
             mut y: -1.51111514016986312e+01,
             mut z: -2.23307578892655734e-01,
             mut vx: 2.96460137564761618e-03 * DAYS_PER_YEAR,
             mut vy: 2.37847173959480950e-03 * DAYS_PER_YEAR,
             mut vz: -2.96589568540237556e-05 * DAYS_PER_YEAR,
             mass: 4.36624404335156298e-05 * SOLAR_MASS};
    }

    pub fn neptune() -> Body::props {
        return {mut x: 1.53796971148509165e+01,
             mut y: -2.59193146099879641e+01,
             mut z: 1.79258772950371181e-01,
             mut vx: 2.68067772490389322e-03 * DAYS_PER_YEAR,
             mut vy: 1.62824170038242295e-03 * DAYS_PER_YEAR,
             mut vz: -9.51592254519715870e-05 * DAYS_PER_YEAR,
             mass: 5.15138902046611451e-05 * SOLAR_MASS};
    }

    pub fn sun() -> Body::props {
        return {mut x: 0.0,
             mut y: 0.0,
             mut z: 0.0,
             mut vx: 0.0,
             mut vy: 0.0,
             mut vz: 0.0,
             mass: SOLAR_MASS};
    }

    pub fn offset_momentum(props: &mut Body::props,
                       px: float, py: float, pz: float) {
        props.vx = -px / SOLAR_MASS;
        props.vy = -py / SOLAR_MASS;
        props.vz = -pz / SOLAR_MASS;
    }

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

// based on:
// http://shootout.alioth.debian.org/u32/benchmark.php?test=nbody&lang=java

/* nest some /* comments */ */

extern mod std;

use core::os;

// Using sqrt from the standard library is way slower than using libc
// directly even though std just calls libc, I guess it must be
// because the the indirection through another dynamic linker
// stub. Kind of shocking. Might be able to make it faster still with
// an llvm intrinsic.
#[nolink]
extern mod libc {
    #[legacy_exports];
    fn sqrt(n: float) -> float;
}

fn main() {
    let args = os::args();
    let args = if os::getenv(~"RUST_BENCH").is_some() {
        ~[~"", ~"4000000"]
    } else if args.len() <= 1u {
        ~[~"", ~"100000"]
    } else {
        args
    };
    let n = int::from_str(args[1]).get();
    let mut bodies: ~[Body::props] = NBodySystem::make();
    io::println(fmt!("%f", NBodySystem::energy(bodies)));
    let mut i = 0;
    while i < n {
        NBodySystem::advance(bodies, 0.01);
        i += 1;
    }
    io::println(fmt!("%f", NBodySystem::energy(bodies)));
}

mod NBodySystem {
    use Body;

    pub fn make() -> ~[Body::props] {
        let mut bodies: ~[Body::props] =
            ~[Body::sun(),
              Body::jupiter(),
              Body::saturn(),
              Body::uranus(),
              Body::neptune()];

        let mut px = 0.0;
        let mut py = 0.0;
        let mut pz = 0.0;

        let mut i = 0;
        while i < 5 {
            px += bodies[i].vx * bodies[i].mass;
            py += bodies[i].vy * bodies[i].mass;
            pz += bodies[i].vz * bodies[i].mass;

            i += 1;
        }

        // side-effecting
        Body::offset_momentum(&mut bodies[0], px, py, pz);

        return bodies;
    }

    pub fn advance(bodies: &mut [Body::props], dt: float) {
        let mut i = 0;
        while i < 5 {
            let mut j = i + 1;
            while j < 5 {
                advance_one(&mut bodies[i],
                            &mut bodies[j], dt);
                j += 1;
            }

            i += 1;
        }

        i = 0;
        while i < 5 {
            move_(&mut bodies[i], dt);
            i += 1;
        }
    }

    pub fn advance_one(bi: &mut Body::props,
                       bj: &mut Body::props,
                       dt: float) unsafe {
        let dx = bi.x - bj.x;
        let dy = bi.y - bj.y;
        let dz = bi.z - bj.z;

        let dSquared = dx * dx + dy * dy + dz * dz;

        let distance = ::libc::sqrt(dSquared);
        let mag = dt / (dSquared * distance);

        bi.vx -= dx * bj.mass * mag;
        bi.vy -= dy * bj.mass * mag;
        bi.vz -= dz * bj.mass * mag;

        bj.vx += dx * bi.mass * mag;
        bj.vy += dy * bi.mass * mag;
        bj.vz += dz * bi.mass * mag;
    }

    pub fn move_(b: &mut Body::props, dt: float) {
        b.x += dt * b.vx;
        b.y += dt * b.vy;
        b.z += dt * b.vz;
    }

    pub fn energy(bodies: &[Body::props]) -> float unsafe {
        let mut dx;
        let mut dy;
        let mut dz;
        let mut distance;
        let mut e = 0.0;

        let mut i = 0;
        while i < 5 {
            e +=
                0.5 * bodies[i].mass *
                (bodies[i].vx * bodies[i].vx + bodies[i].vy * bodies[i].vy
                 + bodies[i].vz * bodies[i].vz);

            let mut j = i + 1;
            while j < 5 {
                dx = bodies[i].x - bodies[j].x;
                dy = bodies[i].y - bodies[j].y;
                dz = bodies[i].z - bodies[j].z;

                distance = ::libc::sqrt(dx * dx + dy * dy + dz * dz);
                e -= bodies[i].mass * bodies[j].mass / distance;

                j += 1;
            }

            i += 1;
        }
        return e;

    }
}

mod Body {
    use Body;

    pub const PI: float = 3.141592653589793;
    pub const SOLAR_MASS: float = 39.478417604357432;
    // was 4 * PI * PI originally
    pub const DAYS_PER_YEAR: float = 365.24;

    pub type props =
        {mut x: float,
         mut y: float,
         mut z: float,
         mut vx: float,
         mut vy: float,
         mut vz: float,
         mass: float};

    pub fn jupiter() -> Body::props {
        return {mut x: 4.84143144246472090e+00,
             mut y: -1.16032004402742839e+00,
             mut z: -1.03622044471123109e-01,
             mut vx: 1.66007664274403694e-03 * DAYS_PER_YEAR,
             mut vy: 7.69901118419740425e-03 * DAYS_PER_YEAR,
             mut vz: -6.90460016972063023e-05 * DAYS_PER_YEAR,
             mass: 9.54791938424326609e-04 * SOLAR_MASS};
    }

    pub fn saturn() -> Body::props {
        return {mut x: 8.34336671824457987e+00,
             mut y: 4.12479856412430479e+00,
             mut z: -4.03523417114321381e-01,
             mut vx: -2.76742510726862411e-03 * DAYS_PER_YEAR,
             mut vy: 4.99852801234917238e-03 * DAYS_PER_YEAR,
             mut vz: 2.30417297573763929e-05 * DAYS_PER_YEAR,
             mass: 2.85885980666130812e-04 * SOLAR_MASS};
    }

    pub fn uranus() -> Body::props {
        return {mut x: 1.28943695621391310e+01,
             mut y: -1.51111514016986312e+01,
             mut z: -2.23307578892655734e-01,
             mut vx: 2.96460137564761618e-03 * DAYS_PER_YEAR,
             mut vy: 2.37847173959480950e-03 * DAYS_PER_YEAR,
             mut vz: -2.96589568540237556e-05 * DAYS_PER_YEAR,
             mass: 4.36624404335156298e-05 * SOLAR_MASS};
    }

    pub fn neptune() -> Body::props {
        return {mut x: 1.53796971148509165e+01,
             mut y: -2.59193146099879641e+01,
             mut z: 1.79258772950371181e-01,
             mut vx: 2.68067772490389322e-03 * DAYS_PER_YEAR,
             mut vy: 1.62824170038242295e-03 * DAYS_PER_YEAR,
             mut vz: -9.51592254519715870e-05 * DAYS_PER_YEAR,
             mass: 5.15138902046611451e-05 * SOLAR_MASS};
    }

    pub fn sun() -> Body::props {
        return {mut x: 0.0,
             mut y: 0.0,
             mut z: 0.0,
             mut vx: 0.0,
             mut vy: 0.0,
             mut vz: 0.0,
             mass: SOLAR_MASS};
    }

    pub fn offset_momentum(props: &mut Body::props,
                       px: float, py: float, pz: float) {
        props.vx = -px / SOLAR_MASS;
        props.vy = -py / SOLAR_MASS;
        props.vz = -pz / SOLAR_MASS;
    }

}
<|endoftext|>


<commit_before>use crate::future::Either;
use crate::stream::{Fuse, StreamExt};
use core::fmt;
use core::pin::Pin;
use futures_core::future::{FusedFuture, Future};
use futures_core::stream::{FusedStream, Stream};
use futures_core::task::{Context, Poll};
#[cfg(feature = "sink")]
use futures_sink::Sink;
use pin_utils::{unsafe_pinned, unsafe_unpinned};

/// A `Stream` that implements a `peek` method.
///
/// The `peek` method can be used to retrieve a reference
/// to the next `Stream::Item` if available. A subsequent
/// call to `poll` will return the owned item.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Peekable<St: Stream> {
    stream: Fuse<St>,
    peeked: Option<St::Item>,
}

impl<St: Stream + Unpin> Unpin for Peekable<St> {}

impl<St: Stream> Peekable<St> {
    unsafe_pinned!(stream: Fuse<St>);
    unsafe_unpinned!(peeked: Option<St::Item>);

    pub(super) fn new(stream: St) -> Peekable<St> {
        Peekable {
            stream: stream.fuse(),
            peeked: None,
        }
    }

    /// Acquires a reference to the underlying stream that this combinator is
    /// pulling from.
    pub fn get_ref(&self) -> &St {
        self.stream.get_ref()
    }

    /// Acquires a mutable reference to the underlying stream that this
    /// combinator is pulling from.
    ///
    /// Note that care must be taken to avoid tampering with the state of the
    /// stream which may otherwise confuse this combinator.
    pub fn get_mut(&mut self) -> &mut St {
        self.stream.get_mut()
    }

    /// Acquires a pinned mutable reference to the underlying stream that this
    /// combinator is pulling from.
    ///
    /// Note that care must be taken to avoid tampering with the state of the
    /// stream which may otherwise confuse this combinator.
    pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut St> {
        self.stream().get_pin_mut()
    }

    /// Consumes this combinator, returning the underlying stream.
    ///
    /// Note that this may discard intermediate state of this combinator, so
    /// care should be taken to avoid losing resources when this is called.
    pub fn into_inner(self) -> St {
        self.stream.into_inner()
    }

    /// Produces a `Peek` future which retrieves a reference to the next item
    /// in the stream, or `None` if the underlying stream terminates.
    pub fn peek(self: Pin<&mut Self>) -> Peek<'_, St> {
        Peek { inner: Some(self) }
    }

    /// Attempt to poll the underlying stream, and return the mutable borrow
    /// in case that is desirable to try for another time.
    /// In case a peeking poll is successful, the reference to the next item
    /// will be in the `Either::Right` variant; otherwise, the mutable borrow
    /// will be in the `Either::Left` variant.
    fn do_poll_peek(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Either<Pin<&mut Self>, Option<&St::Item>> {
        if self.peeked.is_some() {
            let this: &Self = self.into_ref().get_ref();
            return Either::Right(this.peeked.as_ref());
        }
        match self.as_mut().stream().poll_next(cx) {
            Poll::Ready(None) => Either::Right(None),
            Poll::Ready(Some(item)) => {
                *self.as_mut().peeked() = Some(item);
                let this: &Self = self.into_ref().get_ref();
                Either::Right(this.peeked.as_ref())
            }
            _ => Either::Left(self),
        }
    }

    /// Peek retrieves a reference to the next item in the stream.
    ///
    /// This method polls the underlying stream and return either a reference
    /// to the next item if the stream is ready or passes through any errors.
    pub fn poll_peek(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<&St::Item>> {
        match self.do_poll_peek(cx) {
            Either::Left(_) => Poll::Pending,
            Either::Right(poll) => Poll::Ready(poll),
        }
    }
}

impl<St: Stream> FusedStream for Peekable<St> {
    fn is_terminated(&self) -> bool {
        self.peeked.is_none() && self.stream.is_terminated()
    }
}

impl<S: Stream> Stream for Peekable<S> {
    type Item = S::Item;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        if let Some(item) = self.as_mut().peeked().take() {
            return Poll::Ready(Some(item));
        }
        self.as_mut().stream().poll_next(cx)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let peek_len = if self.peeked.is_some() { 1 } else { 0 };
        let (lower, upper) = self.stream.size_hint();
        let lower = lower.saturating_add(peek_len);
        let upper = match upper {
            Some(x) => x.checked_add(peek_len),
            None => None,
        };
        (lower, upper)
    }
}

// Forwarding impl of Sink from the underlying stream
#[cfg(feature = "sink")]
impl<S, Item> Sink<Item> for Peekable<S>
where
    S: Sink<Item> + Stream,
{
    type Error = S::Error;

    delegate_sink!(stream, Item);
}

/// Future for the [`peek()`] function from [`Peekable`]
#[must_use = "futures do nothing unless polled"]
pub struct Peek<'a, St: Stream> {
    inner: Option<Pin<&'a mut Peekable<St>>>,
}

impl<St: Stream> Unpin for Peek<'_, St> {}

impl<St> fmt::Debug for Peek<'_, St>
where
    St: Stream + fmt::Debug,
    St::Item: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Peek")
            .field("inner", &self.inner)
            .finish()
    }
}

impl<St: Stream> FusedFuture for Peek<'_, St> {
    fn is_terminated(&self) -> bool {
        self.inner.is_none()
    }
}

impl<'a, St> Future for Peek<'a, St>
where
    St: Stream,
{
    type Output = Option<&'a St::Item>;
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        if let Some(peekable) = self.inner.take() {
            match peekable.do_poll_peek(cx) {
                Either::Left(peekable) => {
                    self.inner = Some(peekable);
                    Poll::Pending
                }
                Either::Right(peek) => Poll::Ready(peek),
            }
        } else {
            panic!("Peek polled after completion")
        }
    }
}
<commit_msg>rectify cargo doc reference<commit_after>use crate::future::Either;
use crate::stream::{Fuse, StreamExt};
use core::fmt;
use core::pin::Pin;
use futures_core::future::{FusedFuture, Future};
use futures_core::stream::{FusedStream, Stream};
use futures_core::task::{Context, Poll};
#[cfg(feature = "sink")]
use futures_sink::Sink;
use pin_utils::{unsafe_pinned, unsafe_unpinned};

/// A `Stream` that implements a `peek` method.
///
/// The `peek` method can be used to retrieve a reference
/// to the next `Stream::Item` if available. A subsequent
/// call to `poll` will return the owned item.
#[derive(Debug)]
#[must_use = "streams do nothing unless polled"]
pub struct Peekable<St: Stream> {
    stream: Fuse<St>,
    peeked: Option<St::Item>,
}

impl<St: Stream + Unpin> Unpin for Peekable<St> {}

impl<St: Stream> Peekable<St> {
    unsafe_pinned!(stream: Fuse<St>);
    unsafe_unpinned!(peeked: Option<St::Item>);

    pub(super) fn new(stream: St) -> Peekable<St> {
        Peekable {
            stream: stream.fuse(),
            peeked: None,
        }
    }

    /// Acquires a reference to the underlying stream that this combinator is
    /// pulling from.
    pub fn get_ref(&self) -> &St {
        self.stream.get_ref()
    }

    /// Acquires a mutable reference to the underlying stream that this
    /// combinator is pulling from.
    ///
    /// Note that care must be taken to avoid tampering with the state of the
    /// stream which may otherwise confuse this combinator.
    pub fn get_mut(&mut self) -> &mut St {
        self.stream.get_mut()
    }

    /// Acquires a pinned mutable reference to the underlying stream that this
    /// combinator is pulling from.
    ///
    /// Note that care must be taken to avoid tampering with the state of the
    /// stream which may otherwise confuse this combinator.
    pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut St> {
        self.stream().get_pin_mut()
    }

    /// Consumes this combinator, returning the underlying stream.
    ///
    /// Note that this may discard intermediate state of this combinator, so
    /// care should be taken to avoid losing resources when this is called.
    pub fn into_inner(self) -> St {
        self.stream.into_inner()
    }

    /// Produces a `Peek` future which retrieves a reference to the next item
    /// in the stream, or `None` if the underlying stream terminates.
    pub fn peek(self: Pin<&mut Self>) -> Peek<'_, St> {
        Peek { inner: Some(self) }
    }

    /// Attempt to poll the underlying stream, and return the mutable borrow
    /// in case that is desirable to try for another time.
    /// In case a peeking poll is successful, the reference to the next item
    /// will be in the `Either::Right` variant; otherwise, the mutable borrow
    /// will be in the `Either::Left` variant.
    fn do_poll_peek(
        mut self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Either<Pin<&mut Self>, Option<&St::Item>> {
        if self.peeked.is_some() {
            let this: &Self = self.into_ref().get_ref();
            return Either::Right(this.peeked.as_ref());
        }
        match self.as_mut().stream().poll_next(cx) {
            Poll::Ready(None) => Either::Right(None),
            Poll::Ready(Some(item)) => {
                *self.as_mut().peeked() = Some(item);
                let this: &Self = self.into_ref().get_ref();
                Either::Right(this.peeked.as_ref())
            }
            _ => Either::Left(self),
        }
    }

    /// Peek retrieves a reference to the next item in the stream.
    ///
    /// This method polls the underlying stream and return either a reference
    /// to the next item if the stream is ready or passes through any errors.
    pub fn poll_peek(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
    ) -> Poll<Option<&St::Item>> {
        match self.do_poll_peek(cx) {
            Either::Left(_) => Poll::Pending,
            Either::Right(poll) => Poll::Ready(poll),
        }
    }
}

impl<St: Stream> FusedStream for Peekable<St> {
    fn is_terminated(&self) -> bool {
        self.peeked.is_none() && self.stream.is_terminated()
    }
}

impl<S: Stream> Stream for Peekable<S> {
    type Item = S::Item;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        if let Some(item) = self.as_mut().peeked().take() {
            return Poll::Ready(Some(item));
        }
        self.as_mut().stream().poll_next(cx)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let peek_len = if self.peeked.is_some() { 1 } else { 0 };
        let (lower, upper) = self.stream.size_hint();
        let lower = lower.saturating_add(peek_len);
        let upper = match upper {
            Some(x) => x.checked_add(peek_len),
            None => None,
        };
        (lower, upper)
    }
}

// Forwarding impl of Sink from the underlying stream
#[cfg(feature = "sink")]
impl<S, Item> Sink<Item> for Peekable<S>
where
    S: Sink<Item> + Stream,
{
    type Error = S::Error;

    delegate_sink!(stream, Item);
}

/// Future for the [`Peekable::peek()`](self::Peekable::peek) function from [`Peekable`]
#[must_use = "futures do nothing unless polled"]
pub struct Peek<'a, St: Stream> {
    inner: Option<Pin<&'a mut Peekable<St>>>,
}

impl<St: Stream> Unpin for Peek<'_, St> {}

impl<St> fmt::Debug for Peek<'_, St>
where
    St: Stream + fmt::Debug,
    St::Item: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Peek")
            .field("inner", &self.inner)
            .finish()
    }
}

impl<St: Stream> FusedFuture for Peek<'_, St> {
    fn is_terminated(&self) -> bool {
        self.inner.is_none()
    }
}

impl<'a, St> Future for Peek<'a, St>
where
    St: Stream,
{
    type Output = Option<&'a St::Item>;
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        if let Some(peekable) = self.inner.take() {
            match peekable.do_poll_peek(cx) {
                Either::Left(peekable) => {
                    self.inner = Some(peekable);
                    Poll::Pending
                }
                Either::Right(peek) => Poll::Ready(peek),
            }
        } else {
            panic!("Peek polled after completion")
        }
    }
}
<|endoftext|>