<commit_before>use byteorder::{BigEndian, ReadBytesExt};
use chrono::{Duration, TimeZone, UTC};
use std::io::{Read, Seek, SeekFrom};
use std::mem;
use std::string::{FromUtf8Error, FromUtf16Error};

use {Error, Result, PlistEvent, u64_to_usize};

impl From<FromUtf8Error> for Error {
    fn from(_: FromUtf8Error) -> Error {
        Error::InvalidData
    }
}

impl From<FromUtf16Error> for Error {
    fn from(_: FromUtf16Error) -> Error {
        Error::InvalidData
    }
}

struct StackItem {
    object_refs: Vec<u64>,
    ty: StackType,
}

enum StackType {
    Array,
    Dict,
    Root,
}

/// https://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c
/// https://hg.python.org/cpython/file/3.4/Lib/plistlib.py
pub struct EventReader<R> {
    stack: Vec<StackItem>,
    object_offsets: Vec<u64>,
    reader: R,
    ref_size: u8,
    finished: bool,
    // The largest single allocation allowed for this Plist.
    // Equal to the number of bytes in the Plist minus the magic and trailer.
    max_allocation: u64,
}

impl<R: Read + Seek> EventReader<R> {
    pub fn new(reader: R) -> EventReader<R> {
        EventReader {
            stack: Vec::new(),
            object_offsets: Vec::new(),
            reader: reader,
            ref_size: 0,
            finished: false,
            max_allocation: 0
        }
    }

    fn can_allocate<T>(&self, len: u64) -> bool {
        let byte_len = len.saturating_mul(mem::size_of::<T>() as u64);
        byte_len <= self.max_allocation
    }

    fn allocate_vec<T>(&self, len: u64) -> Result<Vec<T>> {
        if self.can_allocate::<T>(len) {
            let len = u64_to_usize(len)?;
            Ok(Vec::with_capacity(len))
        } else {
            Err(Error::InvalidData)
        }
    }

    fn read_trailer(&mut self) -> Result<()> {
        try!(self.reader.seek(SeekFrom::Start(0)));
        let mut magic = [0; 8];
        try!(self.reader.read(&mut magic));
        if &magic != b"bplist00" {
            return Err(Error::InvalidData);
        }

        // Trailer starts with 6 bytes of padding
        let trailer_start = try!(self.reader.seek(SeekFrom::End(-32 + 6)));

        let offset_size = try!(self.reader.read_u8());
        self.ref_size = try!(self.reader.read_u8());
        let num_objects = try!(self.reader.read_u64::<BigEndian>());
        let top_object = try!(self.reader.read_u64::<BigEndian>());
        let offset_table_offset = try!(self.reader.read_u64::<BigEndian>());

        // File size minus trailer and header
        self.max_allocation = trailer_start.saturating_sub(6 + 8);

        // Read offset table
        try!(self.reader.seek(SeekFrom::Start(offset_table_offset)));
        self.object_offsets = try!(self.read_ints(num_objects, offset_size));

        // Seek to top object
        self.stack.push(StackItem {
            object_refs: vec![top_object],
            ty: StackType::Root,
        });

        Ok(())
    }

    fn read_ints(&mut self, len: u64, size: u8) -> Result<Vec<u64>> {
        let mut ints = self.allocate_vec(len)?;
        for _ in 0..len {
            match size {
                1 => ints.push(try!(self.reader.read_u8()) as u64),
                2 => ints.push(try!(self.reader.read_u16::<BigEndian>()) as u64),
                4 => ints.push(try!(self.reader.read_u32::<BigEndian>()) as u64),
                8 => ints.push(try!(self.reader.read_u64::<BigEndian>()) as u64),
                _ => return Err(Error::InvalidData),
            }
        }
        Ok(ints)
    }

    fn read_refs(&mut self, len: u64) -> Result<Vec<u64>> {
        let ref_size = self.ref_size;
        self.read_ints(len, ref_size)
    }

    fn read_object_len(&mut self, len: u8) -> Result<u64> {
        if (len & 0x0f) == 0x0f {
            let len_power_of_two = try!(self.reader.read_u8()) & 0x03;
            Ok(match len_power_of_two {
                0 => try!(self.reader.read_u8()) as u64,
                1 => try!(self.reader.read_u16::<BigEndian>()) as u64,
                2 => try!(self.reader.read_u32::<BigEndian>()) as u64,
                3 => try!(self.reader.read_u64::<BigEndian>()),
                _ => return Err(Error::InvalidData),
            })
        } else {
            Ok(len as u64)
        }
    }

    fn read_data(&mut self, len: u64) -> Result<Vec<u8>> {
        let mut data = self.allocate_vec::<u8>(len)?;
        // Safe as u8 is a Copy type and we have already know len has been allocated.
        unsafe { data.set_len(len as usize) }
        self.reader.read_exact(&mut data)?;
        Ok(data)
    }

    fn seek_to_object(&mut self, object_ref: u64) -> Result<u64> {
        let object_ref = try!(u64_to_usize(object_ref));
        let offset = *self.object_offsets.get(object_ref).ok_or(Error::InvalidData)?;
        let pos = try!(self.reader.seek(SeekFrom::Start(offset)));
        Ok(pos)
    }

    fn read_next(&mut self) -> Result<Option<PlistEvent>> {
        if self.ref_size == 0 {
            // Initialise here rather than in new
            try!(self.read_trailer());
        }

        let object_ref = match self.stack.last_mut() {
            Some(stack_item) => stack_item.object_refs.pop(),
            // Reached the end of the plist
            None => return Ok(None),
        };

        match object_ref {
            Some(object_ref) => {
                try!(self.seek_to_object(object_ref));
            }
            None => {
                // We're at the end of an array or dict. Pop the top stack item and return
                let item = self.stack.pop().unwrap();
                match item.ty {
                    StackType::Array => return Ok(Some(PlistEvent::EndArray)),
                    StackType::Dict => return Ok(Some(PlistEvent::EndDictionary)),
                    // We're at the end of the plist
                    StackType::Root => return Ok(None),
                }
            }
        }

        let token = try!(self.reader.read_u8());
        let ty = (token & 0xf0) >> 4;
        let size = token & 0x0f;

        let result = match (ty, size) {
            (0x0, 0x00) => return Err(Error::InvalidData), // null
            (0x0, 0x08) => Some(PlistEvent::BooleanValue(false)),
            (0x0, 0x09) => Some(PlistEvent::BooleanValue(true)),
            (0x0, 0x0f) => return Err(Error::InvalidData), // fill
            (0x1, 0) => Some(PlistEvent::IntegerValue(try!(self.reader.read_u8()) as i64)),
            (0x1, 1) => {
                Some(PlistEvent::IntegerValue(try!(self.reader.read_u16::<BigEndian>()) as i64))
            }
            (0x1, 2) => {
                Some(PlistEvent::IntegerValue(try!(self.reader.read_u32::<BigEndian>()) as i64))
            }
            (0x1, 3) => Some(PlistEvent::IntegerValue(try!(self.reader.read_i64::<BigEndian>()))),
            (0x1, 4) => return Err(Error::InvalidData), // 128 bit int
            (0x1, _) => return Err(Error::InvalidData), // variable length int
            (0x2, 2) => {
                Some(PlistEvent::RealValue(try!(self.reader.read_f32::<BigEndian>()) as f64))
            }
            (0x2, 3) => Some(PlistEvent::RealValue(try!(self.reader.read_f64::<BigEndian>()))),
            (0x2, _) => return Err(Error::InvalidData), // odd length float
            (0x3, 3) => {;
                // Date
                // Seconds since 1/1/2001 00:00:00.
                let timestamp = try!(self.reader.read_f64::<BigEndian>());

                let millis = timestamp * 1_000.0;
                // Chrono's Duration can only millisecond values between ::std::i64::MIN and
                // ::std::i64::MAX.
                if millis > ::std::i64::MAX as f64 || millis < ::std::i64::MIN as f64 {
                    return Err(Error::InvalidData);
                }

                let whole_millis = millis.floor();
                let submilli_nanos = ((millis - whole_millis) * 1_000_000.0).floor();

                let dur = Duration::milliseconds(whole_millis as i64);
                let dur = dur + Duration::nanoseconds(submilli_nanos as i64);

                let plist_epoch = UTC.ymd(2001, 1, 1).and_hms(0, 0, 0);
                let date = try!(plist_epoch.checked_add(dur).ok_or(Error::InvalidData));

                Some(PlistEvent::DateValue(date))
            }
            (0x4, n) => {
                // Data
                let len = try!(self.read_object_len(n));
                Some(PlistEvent::DataValue(try!(self.read_data(len))))
            }
            (0x5, n) => {
                // ASCII string
                let len = try!(self.read_object_len(n));
                let raw = try!(self.read_data(len));
                let string = try!(String::from_utf8(raw));
                Some(PlistEvent::StringValue(string))
            }
            (0x6, n) => {
                // UTF-16 string
                let len_utf16_codepoints = try!(self.read_object_len(n));
                let mut raw_utf16 = self.allocate_vec(len_utf16_codepoints)?;

                for _ in 0..len_utf16_codepoints {
                    raw_utf16.push(try!(self.reader.read_u16::<BigEndian>()));
                }

                let string = try!(String::from_utf16(&raw_utf16));
                Some(PlistEvent::StringValue(string))
            }
            (0xa, n) => {
                // Array
                let len = try!(self.read_object_len(n));
                let mut object_refs = try!(self.read_refs(len));
                // Reverse so we can pop off the end of the stack in order
                object_refs.reverse();

                self.stack.push(StackItem {
                    ty: StackType::Array,
                    object_refs: object_refs,
                });

                Some(PlistEvent::StartArray(Some(len)))
            }
            (0xd, n) => {
                // Dict
                let len = try!(self.read_object_len(n));
                let key_refs = try!(self.read_refs(len));
                let value_refs = try!(self.read_refs(len));

                let mut object_refs = self.allocate_vec(len * 2)?;
                let len = key_refs.len();
                for i in 1..len + 1 {
                    // Reverse so we can pop off the end of the stack in order
                    object_refs.push(value_refs[len - i]);
                    object_refs.push(key_refs[len - i]);
                }

                self.stack.push(StackItem {
                    ty: StackType::Dict,
                    object_refs: object_refs,
                });

                Some(PlistEvent::StartDictionary(Some(len as u64)))
            }
            (_, _) => return Err(Error::InvalidData),
        };

        Ok(result)
    }
}

impl<R: Read + Seek> Iterator for EventReader<R> {
    type Item = Result<PlistEvent>;

    fn next(&mut self) -> Option<Result<PlistEvent>> {
        if self.finished {
            None
        } else {
            match self.read_next() {
                Ok(Some(event)) => Some(Ok(event)),
                Err(err) => {
                    self.finished = true;
                    Some(Err(err))
                }
                Ok(None) => {
                    self.finished = true;
                    None
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use chrono::{TimeZone, UTC};
    use std::fs::File;
    use std::path::Path;

    use super::*;
    use PlistEvent;

    #[test]
    fn streaming_parser() {
        use PlistEvent::*;

        let reader = File::open(&Path::new("./tests/data/binary.plist")).unwrap();
        let streaming_parser = EventReader::new(reader);
        let events: Vec<PlistEvent> = streaming_parser.map(|e| e.unwrap()).collect();

        let comparison = &[StartDictionary(Some(6)),
                           StringValue("Lines".to_owned()),
                           StartArray(Some(2)),
                           StringValue("It is a tale told by an idiot,".to_owned()),
                           StringValue("Full of sound and fury, signifying nothing.".to_owned()),
                           EndArray,
                           StringValue("Death".to_owned()),
                           IntegerValue(1564),
                           StringValue("Height".to_owned()),
                           RealValue(1.60),
                           StringValue("Birthdate".to_owned()),
                           DateValue(UTC.ymd(1981, 05, 16).and_hms(11, 32, 06)),
                           StringValue("Author".to_owned()),
                           StringValue("William Shakespeare".to_owned()),
                           StringValue("Data".to_owned()),
                           DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]),
                           EndDictionary];

        assert_eq!(events, comparison);
    }

    #[test]
    fn utf16_plist() {
        use PlistEvent::*;

        let reader = File::open(&Path::new("./tests/data/utf16_bplist.plist")).unwrap();
        let streaming_parser = EventReader::new(reader);
        let mut events: Vec<PlistEvent> = streaming_parser.map(|e| e.unwrap()).collect();

        assert_eq!(events[2], StringValue("\u{2605} or better".to_owned()));

        let poem = if let StringValue(ref mut poem) = events[4] {
            poem
        } else {
            panic!("not a string")
        };
        assert_eq!(poem.len(), 643);
        assert_eq!(poem.pop().unwrap(), '\u{2605}');
    }
}
<commit_msg>Handle max_allocation correctly for files over 4GB.<commit_after>use byteorder::{BigEndian, ReadBytesExt};
use chrono::{Duration, TimeZone, UTC};
use std::io::{Read, Seek, SeekFrom};
use std::mem;
use std::string::{FromUtf8Error, FromUtf16Error};

use {Error, Result, PlistEvent, u64_to_usize};

impl From<FromUtf8Error> for Error {
    fn from(_: FromUtf8Error) -> Error {
        Error::InvalidData
    }
}

impl From<FromUtf16Error> for Error {
    fn from(_: FromUtf16Error) -> Error {
        Error::InvalidData
    }
}

struct StackItem {
    object_refs: Vec<u64>,
    ty: StackType,
}

enum StackType {
    Array,
    Dict,
    Root,
}

/// https://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c
/// https://hg.python.org/cpython/file/3.4/Lib/plistlib.py
pub struct EventReader<R> {
    stack: Vec<StackItem>,
    object_offsets: Vec<u64>,
    reader: R,
    ref_size: u8,
    finished: bool,
    // The largest single allocation allowed for this Plist.
    // Equal to the number of bytes in the Plist minus the magic and trailer.
    max_allocation: usize,
}

impl<R: Read + Seek> EventReader<R> {
    pub fn new(reader: R) -> EventReader<R> {
        EventReader {
            stack: Vec::new(),
            object_offsets: Vec::new(),
            reader: reader,
            ref_size: 0,
            finished: false,
            max_allocation: 0
        }
    }

    fn can_allocate<T>(&self, len: u64) -> bool {
        let byte_len = len.saturating_mul(mem::size_of::<T>() as u64);
        byte_len <= self.max_allocation as u64
    }

    fn allocate_vec<T>(&self, len: u64) -> Result<Vec<T>> {
        if self.can_allocate::<T>(len) {
            Ok(Vec::with_capacity(len as usize))
        } else {
            Err(Error::InvalidData)
        }
    }

    fn read_trailer(&mut self) -> Result<()> {
        try!(self.reader.seek(SeekFrom::Start(0)));
        let mut magic = [0; 8];
        try!(self.reader.read(&mut magic));
        if &magic != b"bplist00" {
            return Err(Error::InvalidData);
        }

        // Trailer starts with 6 bytes of padding
        let trailer_start = try!(self.reader.seek(SeekFrom::End(-32 + 6)));

        let offset_size = try!(self.reader.read_u8());
        self.ref_size = try!(self.reader.read_u8());
        let num_objects = try!(self.reader.read_u64::<BigEndian>());
        let top_object = try!(self.reader.read_u64::<BigEndian>());
        let offset_table_offset = try!(self.reader.read_u64::<BigEndian>());

        // File size minus trailer and header
        // Truncated to max(usize)
        self.max_allocation = trailer_start.saturating_sub(6 + 8) as usize;

        // Read offset table
        try!(self.reader.seek(SeekFrom::Start(offset_table_offset)));
        self.object_offsets = try!(self.read_ints(num_objects, offset_size));

        // Seek to top object
        self.stack.push(StackItem {
            object_refs: vec![top_object],
            ty: StackType::Root,
        });

        Ok(())
    }

    fn read_ints(&mut self, len: u64, size: u8) -> Result<Vec<u64>> {
        let mut ints = self.allocate_vec(len)?;
        for _ in 0..len {
            match size {
                1 => ints.push(try!(self.reader.read_u8()) as u64),
                2 => ints.push(try!(self.reader.read_u16::<BigEndian>()) as u64),
                4 => ints.push(try!(self.reader.read_u32::<BigEndian>()) as u64),
                8 => ints.push(try!(self.reader.read_u64::<BigEndian>()) as u64),
                _ => return Err(Error::InvalidData),
            }
        }
        Ok(ints)
    }

    fn read_refs(&mut self, len: u64) -> Result<Vec<u64>> {
        let ref_size = self.ref_size;
        self.read_ints(len, ref_size)
    }

    fn read_object_len(&mut self, len: u8) -> Result<u64> {
        if (len & 0x0f) == 0x0f {
            let len_power_of_two = try!(self.reader.read_u8()) & 0x03;
            Ok(match len_power_of_two {
                0 => try!(self.reader.read_u8()) as u64,
                1 => try!(self.reader.read_u16::<BigEndian>()) as u64,
                2 => try!(self.reader.read_u32::<BigEndian>()) as u64,
                3 => try!(self.reader.read_u64::<BigEndian>()),
                _ => return Err(Error::InvalidData),
            })
        } else {
            Ok(len as u64)
        }
    }

    fn read_data(&mut self, len: u64) -> Result<Vec<u8>> {
        let mut data = self.allocate_vec::<u8>(len)?;
        // Safe as u8 is a Copy type and we have already know len has been allocated.
        unsafe { data.set_len(len as usize) }
        self.reader.read_exact(&mut data)?;
        Ok(data)
    }

    fn seek_to_object(&mut self, object_ref: u64) -> Result<u64> {
        let object_ref = try!(u64_to_usize(object_ref));
        let offset = *self.object_offsets.get(object_ref).ok_or(Error::InvalidData)?;
        let pos = try!(self.reader.seek(SeekFrom::Start(offset)));
        Ok(pos)
    }

    fn read_next(&mut self) -> Result<Option<PlistEvent>> {
        if self.ref_size == 0 {
            // Initialise here rather than in new
            try!(self.read_trailer());
        }

        let object_ref = match self.stack.last_mut() {
            Some(stack_item) => stack_item.object_refs.pop(),
            // Reached the end of the plist
            None => return Ok(None),
        };

        match object_ref {
            Some(object_ref) => {
                try!(self.seek_to_object(object_ref));
            }
            None => {
                // We're at the end of an array or dict. Pop the top stack item and return
                let item = self.stack.pop().unwrap();
                match item.ty {
                    StackType::Array => return Ok(Some(PlistEvent::EndArray)),
                    StackType::Dict => return Ok(Some(PlistEvent::EndDictionary)),
                    // We're at the end of the plist
                    StackType::Root => return Ok(None),
                }
            }
        }

        let token = try!(self.reader.read_u8());
        let ty = (token & 0xf0) >> 4;
        let size = token & 0x0f;

        let result = match (ty, size) {
            (0x0, 0x00) => return Err(Error::InvalidData), // null
            (0x0, 0x08) => Some(PlistEvent::BooleanValue(false)),
            (0x0, 0x09) => Some(PlistEvent::BooleanValue(true)),
            (0x0, 0x0f) => return Err(Error::InvalidData), // fill
            (0x1, 0) => Some(PlistEvent::IntegerValue(try!(self.reader.read_u8()) as i64)),
            (0x1, 1) => {
                Some(PlistEvent::IntegerValue(try!(self.reader.read_u16::<BigEndian>()) as i64))
            }
            (0x1, 2) => {
                Some(PlistEvent::IntegerValue(try!(self.reader.read_u32::<BigEndian>()) as i64))
            }
            (0x1, 3) => Some(PlistEvent::IntegerValue(try!(self.reader.read_i64::<BigEndian>()))),
            (0x1, 4) => return Err(Error::InvalidData), // 128 bit int
            (0x1, _) => return Err(Error::InvalidData), // variable length int
            (0x2, 2) => {
                Some(PlistEvent::RealValue(try!(self.reader.read_f32::<BigEndian>()) as f64))
            }
            (0x2, 3) => Some(PlistEvent::RealValue(try!(self.reader.read_f64::<BigEndian>()))),
            (0x2, _) => return Err(Error::InvalidData), // odd length float
            (0x3, 3) => {;
                // Date
                // Seconds since 1/1/2001 00:00:00.
                let timestamp = try!(self.reader.read_f64::<BigEndian>());

                let millis = timestamp * 1_000.0;
                // Chrono's Duration can only millisecond values between ::std::i64::MIN and
                // ::std::i64::MAX.
                if millis > ::std::i64::MAX as f64 || millis < ::std::i64::MIN as f64 {
                    return Err(Error::InvalidData);
                }

                let whole_millis = millis.floor();
                let submilli_nanos = ((millis - whole_millis) * 1_000_000.0).floor();

                let dur = Duration::milliseconds(whole_millis as i64);
                let dur = dur + Duration::nanoseconds(submilli_nanos as i64);

                let plist_epoch = UTC.ymd(2001, 1, 1).and_hms(0, 0, 0);
                let date = try!(plist_epoch.checked_add(dur).ok_or(Error::InvalidData));

                Some(PlistEvent::DateValue(date))
            }
            (0x4, n) => {
                // Data
                let len = try!(self.read_object_len(n));
                Some(PlistEvent::DataValue(try!(self.read_data(len))))
            }
            (0x5, n) => {
                // ASCII string
                let len = try!(self.read_object_len(n));
                let raw = try!(self.read_data(len));
                let string = try!(String::from_utf8(raw));
                Some(PlistEvent::StringValue(string))
            }
            (0x6, n) => {
                // UTF-16 string
                let len_utf16_codepoints = try!(self.read_object_len(n));
                let mut raw_utf16 = self.allocate_vec(len_utf16_codepoints)?;

                for _ in 0..len_utf16_codepoints {
                    raw_utf16.push(try!(self.reader.read_u16::<BigEndian>()));
                }

                let string = try!(String::from_utf16(&raw_utf16));
                Some(PlistEvent::StringValue(string))
            }
            (0xa, n) => {
                // Array
                let len = try!(self.read_object_len(n));
                let mut object_refs = try!(self.read_refs(len));
                // Reverse so we can pop off the end of the stack in order
                object_refs.reverse();

                self.stack.push(StackItem {
                    ty: StackType::Array,
                    object_refs: object_refs,
                });

                Some(PlistEvent::StartArray(Some(len)))
            }
            (0xd, n) => {
                // Dict
                let len = try!(self.read_object_len(n));
                let key_refs = try!(self.read_refs(len));
                let value_refs = try!(self.read_refs(len));

                let mut object_refs = self.allocate_vec(len * 2)?;
                let len = key_refs.len();
                for i in 1..len + 1 {
                    // Reverse so we can pop off the end of the stack in order
                    object_refs.push(value_refs[len - i]);
                    object_refs.push(key_refs[len - i]);
                }

                self.stack.push(StackItem {
                    ty: StackType::Dict,
                    object_refs: object_refs,
                });

                Some(PlistEvent::StartDictionary(Some(len as u64)))
            }
            (_, _) => return Err(Error::InvalidData),
        };

        Ok(result)
    }
}

impl<R: Read + Seek> Iterator for EventReader<R> {
    type Item = Result<PlistEvent>;

    fn next(&mut self) -> Option<Result<PlistEvent>> {
        if self.finished {
            None
        } else {
            match self.read_next() {
                Ok(Some(event)) => Some(Ok(event)),
                Err(err) => {
                    self.finished = true;
                    Some(Err(err))
                }
                Ok(None) => {
                    self.finished = true;
                    None
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use chrono::{TimeZone, UTC};
    use std::fs::File;
    use std::path::Path;

    use super::*;
    use PlistEvent;

    #[test]
    fn streaming_parser() {
        use PlistEvent::*;

        let reader = File::open(&Path::new("./tests/data/binary.plist")).unwrap();
        let streaming_parser = EventReader::new(reader);
        let events: Vec<PlistEvent> = streaming_parser.map(|e| e.unwrap()).collect();

        let comparison = &[StartDictionary(Some(6)),
                           StringValue("Lines".to_owned()),
                           StartArray(Some(2)),
                           StringValue("It is a tale told by an idiot,".to_owned()),
                           StringValue("Full of sound and fury, signifying nothing.".to_owned()),
                           EndArray,
                           StringValue("Death".to_owned()),
                           IntegerValue(1564),
                           StringValue("Height".to_owned()),
                           RealValue(1.60),
                           StringValue("Birthdate".to_owned()),
                           DateValue(UTC.ymd(1981, 05, 16).and_hms(11, 32, 06)),
                           StringValue("Author".to_owned()),
                           StringValue("William Shakespeare".to_owned()),
                           StringValue("Data".to_owned()),
                           DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]),
                           EndDictionary];

        assert_eq!(events, comparison);
    }

    #[test]
    fn utf16_plist() {
        use PlistEvent::*;

        let reader = File::open(&Path::new("./tests/data/utf16_bplist.plist")).unwrap();
        let streaming_parser = EventReader::new(reader);
        let mut events: Vec<PlistEvent> = streaming_parser.map(|e| e.unwrap()).collect();

        assert_eq!(events[2], StringValue("\u{2605} or better".to_owned()));

        let poem = if let StringValue(ref mut poem) = events[4] {
            poem
        } else {
            panic!("not a string")
        };
        assert_eq!(poem.len(), 643);
        assert_eq!(poem.pop().unwrap(), '\u{2605}');
    }
}
<|endoftext|>


<commit_before>struct Book {
    author: ~str,
    title: ~str,
    year: uint,
}

// & means a reference to a Book, no ownership is taken
fn borrow_book(book: &Book) {
    println!("I borrowed {} {} edition", book.title, book.year);
}

// &mut means a mutable reference, meaning the fields of the struct can be
// modified
fn new_edition(book: &mut Book) {
    book.year = 2014;
}

fn main() {
    // an immutable Book
    let geb = Book {
        author: ~"Douglas Hofstadter",
        title: ~"Gödel, Escher, Bach",
        year: 1979,
    };

    // borrow geb, geb can still be used afterwards
    borrow_book(&geb);

    // geb can be borrowed again, and again, and again ...
    borrow_book(&geb);

    // a mutable Book
    let mut mutable_geb = Book {
        author: ~"Douglas Hofstadter",
        title: ~"Gödel, Escher, Bach",
        year: 1979,
    };

    // Error: can't borrow immutable object as mutable
    //new_edition(&mut geb);

    // Ok: borrow a mutable object as mutable
    new_edition(&mut mutable_geb);

    // Ok: mutable objects can be immutably borrowed
    borrow_book(&mutable_geb);

    // ref can be used to take references when destructuring
    // Here geb_title and geb_author are references to ~str, i.e. &~str
    // geb_year is a copy of the year field
    let Book {
        author: ref geb_author,
        title: ref geb_title,
        year: geb_year
    } = geb;
}
<commit_msg>Added a bit about the effect of borrows on the owning variables.<commit_after>struct Book {
    author: ~str,
    title: ~str,
    year: uint,
}

// & means a reference to a Book, no ownership is taken
fn borrow_book(book: &Book) {
    println!("I borrowed {} {} edition", book.title, book.year);
}

// &mut means a mutable reference, meaning the fields of the struct can be
// modified
fn new_edition(book: &mut Book) {
    book.year = 2014;
}

fn main() {
    // an immutable Book
    let geb = Book {
        author: ~"Douglas Hofstadter",
        title: ~"Gödel, Escher, Bach",
        year: 1979,
    };

    // borrow geb, geb can still be used afterwards
    borrow_book(&geb);

    // geb can be borrowed again, and again, and again ...
    borrow_book(&geb);

    // a mutable Book
    let mut mutable_geb = Book {
        author: ~"Douglas Hofstadter",
        title: ~"Gödel, Escher, Bach",
        year: 1979,
    };

    // Error: can't borrow immutable object as mutable
    //new_edition(&mut geb);

    // Ok: borrow a mutable object as mutable
    new_edition(&mut mutable_geb);

    // Ok: mutable objects can be immutably borrowed
    borrow_book(&mutable_geb);

    // when an object is mutably borrowed, the original can't be used
    // until the end of the borrowed copy's lifetime
    if true {
        let borrowed_geb = &mut mutable_geb;

        // Error: mutable_geb has been mutably borrowed.
        //println!("Can no longer access {}", mutable_geb.title);

        println!("The borrowed copy of {} is available", borrowed_geb.title);
 	    // now borrowed_geb goes out of scope
    }
    println!("Once again, I can access {}", mutable_geb.title);

    // immutable borrows place no restrictions on the original owner
    if true {
        let borrowed_geb = &mutable_geb;
        println!("The original is still accessible: {}", mutable_geb.title);
        println!("and so is the borrowed copy: {}", borrowed_geb.title);
    }

    // ref can be used to take references when destructuring
    // Here geb_title and geb_author are references to ~str, i.e. &~str
    // geb_year is a copy of the year field
    let Book {
        author: ref geb_author,
        title: ref geb_title,
        year: geb_year
    } = geb;
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::{mem, time};
use torrent::{Info, Peer, Bitfield};
use control::cio;

mod rarest;
mod sequential;

#[cfg(test)]
mod tests;

#[derive(Clone, Debug)]
pub struct Picker {
    /// Number of blocks per piece
    scale: u32,
    last_piece_scale: u32,
    last_piece: u32,
    /// Number of detected seeders
    seeders: u16,
    /// Set of pieces which have blocks waiting. These should be prioritized.
    downloading: HashMap<u32, Vec<Downloading>>,
    /// Bitfield of unpicked pieces, not in progress or
    /// completed yet. A set bit is picked, unset is unpicked.
    unpicked: Bitfield,
    /// The current picker in use
    picker: PickerKind,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Block {
    pub index: u32,
    pub offset: u32,
}

/// Pickers act solely as piece picking algorithm.
/// They will select the optimal next piece for a peer,
/// and can be told when a piece is complete(or invalid).
#[derive(Clone, Debug)]
enum PickerKind {
    Rarest(rarest::Picker),
    Sequential(sequential::Picker),
}

/// A downloading block and the peers it has been
/// requested from.
#[derive(Clone, Debug)]
struct Downloading {
    offset: u32,
    completed: bool,
    requested: Vec<Request>,
}

/// A request to a peer and the time it was initiated.
#[derive(Clone, Debug)]
struct Request {
    peer: usize,
    requested_at: time::Instant,
}

const MAX_DUP_REQS: usize = 5;

impl Picker {
    /// Creates a new picker, which will select over
    /// the given pieces. The algorithm used for selection
    /// will vary based on the current swarm state, but
    /// will default to rarest first.
    pub fn new(info: &Info, pieces: &Bitfield) -> Picker {
        let scale = info.piece_len / 16_384;
        let picker = rarest::Picker::new(pieces);
        let last_piece = info.pieces() - 1;
        let lpl = info.piece_len(last_piece);
        let last_piece_scale = if lpl % 16_384 == 0 {
            lpl / 16_384
        } else {
            lpl / 16_384 + 1
        };
        Picker {
            picker: PickerKind::Rarest(picker),
            scale,
            last_piece,
            last_piece_scale,
            seeders: 0,
            unpicked: pieces.clone(),
            downloading: HashMap::new(),
        }
    }

    /// Returns true if the current picker algorithm is sequential
    pub fn is_sequential(&self) -> bool {
        match self.picker {
            PickerKind::Sequential(_) => true,
            _ => false,
        }
    }

    /// Attempts to select a block for a peer.
    pub fn pick<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        if let Some(b) = self.pick_expired(peer) {
            return Some(b);
        }

        let piece = match self.picker {
            PickerKind::Sequential(ref mut p) => p.pick(peer),
            PickerKind::Rarest(ref mut p) => p.pick(peer),
        };
        piece.and_then(|p| self.pick_piece(p, peer.id())).or_else(
            || {
                self.pick_downloading(peer)
            },
        )
    }

    /// Attempts to pick an expired block
    fn pick_expired<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        // TODO: Use some form of heuristic here to say "we expect to have
        // downloaded some pieces by X, hit the picker with a tick which checks
        // that, flags shit as invalid, and then does a double request
        None
    }

    /// Picks a block from a given piece for a peer
    fn pick_piece(&mut self, piece: u32, id: usize) -> Option<Block> {
        self.downloading.entry(piece).or_insert_with(|| vec![]);
        let dl = self.downloading.get_mut(&piece).unwrap();
        let offset = dl.len() as u32 * 16_384;
        dl.push(Downloading {
            offset,
            completed: false,
            requested: vec![Request::new(id)],
        });

        if dl.len() == self.scale as usize ||
            (piece == self.last_piece && dl.len() == self.last_piece_scale as usize)
        {
            match self.picker {
                PickerKind::Sequential(ref mut p) => p.completed(piece),
                PickerKind::Rarest(ref mut p) => p.completed(piece),
            }
            self.unpicked.set_bit(piece as u64);
        }
        Some(Block {
            index: piece,
            offset,
        })
    }

    /// Attempts to pick an already requested block
    fn pick_downloading<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        for (idx, dl) in &mut self.downloading {
            if peer.pieces().has_bit(*idx as u64) {
                let r = dl.iter_mut()
                    .find(|r| {
                        !r.completed && r.requested.len() < MAX_DUP_REQS &&
                            r.requested.iter().all(|req| req.peer != peer.id())
                    })
                    .map(|r| {
                        r.requested.push(Request::new(peer.id()));
                        Block::new(*idx, r.offset)
                    });
                if r.is_some() {
                    return r;
                }
            }
        }
        None
    }

    /// Marks a block as completed. Returns a result indicating if the block
    /// was actually requested, the success value containing a bool indicating
    /// if the block is complete, and a vector of peers from which the block
    /// was requested(for cancellation).
    pub fn completed(&mut self, b: Block) -> Result<(bool, Vec<usize>), ()> {
        // Find the block in our downloading blocks, mark as true,
        // and extract the current peer list for return.
        let res = self.downloading
            .get_mut(&b.index)
            .and_then(|dl| {
                dl.iter_mut().find(|r| r.offset == b.offset).map(
                    |r| r.complete(),
                )
            })
            .map(|r| r.into_iter().map(|e| e.peer).collect());

        // If we've requested every single block for this piece and they're all complete, remove it
        // and report completion
        let scale = self.scale;
        let lp = self.last_piece;
        let lps = self.last_piece_scale;
        let complete = self.downloading
            .get_mut(&b.index)
            .map(|r| {
                (r.len() as u32 == scale || (b.index == lp && r.len() as u32 == lps)) &&
                    r.iter().all(|d| d.completed)
            })
            .unwrap_or(false);

        if complete {
            self.downloading.remove(&b.index);
        }

        res.map(|r| (complete, r)).ok_or(())
    }

    /// Invalidates a piece
    pub fn invalidate_piece(&mut self, idx: u32) {
        match self.picker {
            PickerKind::Sequential(ref mut p) => p.incomplete(idx),
            PickerKind::Rarest(ref mut p) => p.incomplete(idx),
        }
        self.unpicked.unset_bit(idx as u64);
    }

    pub fn piece_available(&mut self, idx: u32) {
        if let PickerKind::Rarest(ref mut p) = self.picker {
            p.piece_available(idx);
        }
    }

    pub fn add_peer<T: cio::CIO>(&mut self, peer: &Peer<T>) {
        if peer.pieces().complete() {
            self.seeders += 1;
        }
        if let PickerKind::Rarest(ref mut p) = self.picker {
            p.add_peer(peer);
        }
    }

    pub fn remove_peer<T: cio::CIO>(&mut self, peer: &Peer<T>) {
        if let PickerKind::Rarest(ref mut p) = self.picker {
            p.remove_peer(peer);
        }

        for piece in self.downloading.values_mut() {
            for block in piece {
                block.requested.retain(|req| req.peer != peer.id())
            }
        }
    }

    /// Alters the picker to sequential/non sequential. If changing
    /// from sequential to non sequential, peer state will need to be loaded
    /// after this.
    pub fn change_picker(&mut self, sequential: bool) {
        self.picker = if sequential {
            PickerKind::Sequential(sequential::Picker::new(&self.unpicked))
        } else {
            PickerKind::Rarest(rarest::Picker::new(&self.unpicked))
        };
        for i in self.downloading.keys() {
            if let PickerKind::Rarest(ref mut p) = self.picker {
                p.dec_avail(*i);
            }
        }
    }

    pub fn refresh_picker(&mut self, pieces: &Bitfield) {
        self.unpicked = pieces.clone();
        self.picker = if self.is_sequential() {
            PickerKind::Sequential(sequential::Picker::new(&self.unpicked))
        } else {
            PickerKind::Rarest(rarest::Picker::new(&self.unpicked))
        };
    }
}

#[cfg(test)]
impl Picker {
    pub fn new_rarest(info: &Info, pieces: &Bitfield) -> Picker {
        let scale = info.piece_len / 16_384;
        let picker = rarest::Picker::new(pieces);
        Picker {
            picker: PickerKind::Rarest(picker),
            scale,
            seeders: 0,
            unpicked: pieces.clone(),
            downloading: HashMap::new(),
        }
    }

    pub fn new_sequential(info: &Info, pieces: &Bitfield) -> Picker {
        let scale = info.piece_len / 16_384;
        let picker = sequential::Picker::new(pieces);
        Picker {
            picker: PickerKind::Sequential(picker),
            scale,
            seeders: 0,
            unpicked: pieces.clone(),
            downloading: HashMap::new(),
        }
    }
}
impl Block {
    pub fn new(index: u32, offset: u32) -> Block {
        Block { index, offset }
    }
}

impl Request {
    fn new(peer: usize) -> Request {
        Request {
            peer,
            requested_at: time::Instant::now(),
        }
    }
}

impl Downloading {
    fn complete(&mut self) -> Vec<Request> {
        self.completed = true;
        mem::replace(&mut self.requested, Vec::with_capacity(0))
    }
}
<commit_msg>Update picker tests<commit_after>use std::collections::HashMap;
use std::{mem, time};
use torrent::{Info, Peer, Bitfield};
use control::cio;

mod rarest;
mod sequential;

#[cfg(test)]
mod tests;

#[derive(Clone, Debug)]
pub struct Picker {
    /// Number of blocks per piece
    scale: u32,
    last_piece_scale: u32,
    last_piece: u32,
    /// Number of detected seeders
    seeders: u16,
    /// Set of pieces which have blocks waiting. These should be prioritized.
    downloading: HashMap<u32, Vec<Downloading>>,
    /// Bitfield of unpicked pieces, not in progress or
    /// completed yet. A set bit is picked, unset is unpicked.
    unpicked: Bitfield,
    /// The current picker in use
    picker: PickerKind,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Block {
    pub index: u32,
    pub offset: u32,
}

/// Pickers act solely as piece picking algorithm.
/// They will select the optimal next piece for a peer,
/// and can be told when a piece is complete(or invalid).
#[derive(Clone, Debug)]
enum PickerKind {
    Rarest(rarest::Picker),
    Sequential(sequential::Picker),
}

/// A downloading block and the peers it has been
/// requested from.
#[derive(Clone, Debug)]
struct Downloading {
    offset: u32,
    completed: bool,
    requested: Vec<Request>,
}

/// A request to a peer and the time it was initiated.
#[derive(Clone, Debug)]
struct Request {
    peer: usize,
    requested_at: time::Instant,
}

const MAX_DUP_REQS: usize = 5;

impl Picker {
    /// Creates a new picker, which will select over
    /// the given pieces. The algorithm used for selection
    /// will vary based on the current swarm state, but
    /// will default to rarest first.
    pub fn new(info: &Info, pieces: &Bitfield) -> Picker {
        let scale = info.piece_len / 16_384;
        let picker = rarest::Picker::new(pieces);
        let last_piece = info.pieces() - 1;
        let lpl = info.piece_len(last_piece);
        let last_piece_scale = if lpl % 16_384 == 0 {
            lpl / 16_384
        } else {
            lpl / 16_384 + 1
        };
        Picker {
            picker: PickerKind::Rarest(picker),
            scale,
            last_piece,
            last_piece_scale,
            seeders: 0,
            unpicked: pieces.clone(),
            downloading: HashMap::new(),
        }
    }

    /// Returns true if the current picker algorithm is sequential
    pub fn is_sequential(&self) -> bool {
        match self.picker {
            PickerKind::Sequential(_) => true,
            _ => false,
        }
    }

    /// Attempts to select a block for a peer.
    pub fn pick<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        if let Some(b) = self.pick_expired(peer) {
            return Some(b);
        }

        let piece = match self.picker {
            PickerKind::Sequential(ref mut p) => p.pick(peer),
            PickerKind::Rarest(ref mut p) => p.pick(peer),
        };
        piece.and_then(|p| self.pick_piece(p, peer.id())).or_else(
            || {
                self.pick_downloading(peer)
            },
        )
    }

    /// Attempts to pick an expired block
    fn pick_expired<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        // TODO: Use some form of heuristic here to say "we expect to have
        // downloaded some pieces by X, hit the picker with a tick which checks
        // that, flags shit as invalid, and then does a double request
        None
    }

    /// Picks a block from a given piece for a peer
    fn pick_piece(&mut self, piece: u32, id: usize) -> Option<Block> {
        self.downloading.entry(piece).or_insert_with(|| vec![]);
        let dl = self.downloading.get_mut(&piece).unwrap();
        let offset = dl.len() as u32 * 16_384;
        dl.push(Downloading {
            offset,
            completed: false,
            requested: vec![Request::new(id)],
        });

        if dl.len() == self.scale as usize ||
            (piece == self.last_piece && dl.len() == self.last_piece_scale as usize)
        {
            match self.picker {
                PickerKind::Sequential(ref mut p) => p.completed(piece),
                PickerKind::Rarest(ref mut p) => p.completed(piece),
            }
            self.unpicked.set_bit(piece as u64);
        }
        Some(Block {
            index: piece,
            offset,
        })
    }

    /// Attempts to pick an already requested block
    fn pick_downloading<T: cio::CIO>(&mut self, peer: &Peer<T>) -> Option<Block> {
        for (idx, dl) in &mut self.downloading {
            if peer.pieces().has_bit(*idx as u64) {
                let r = dl.iter_mut()
                    .find(|r| {
                        !r.completed && r.requested.len() < MAX_DUP_REQS &&
                            r.requested.iter().all(|req| req.peer != peer.id())
                    })
                    .map(|r| {
                        r.requested.push(Request::new(peer.id()));
                        Block::new(*idx, r.offset)
                    });
                if r.is_some() {
                    return r;
                }
            }
        }
        None
    }

    /// Marks a block as completed. Returns a result indicating if the block
    /// was actually requested, the success value containing a bool indicating
    /// if the block is complete, and a vector of peers from which the block
    /// was requested(for cancellation).
    pub fn completed(&mut self, b: Block) -> Result<(bool, Vec<usize>), ()> {
        // Find the block in our downloading blocks, mark as true,
        // and extract the current peer list for return.
        let res = self.downloading
            .get_mut(&b.index)
            .and_then(|dl| {
                dl.iter_mut().find(|r| r.offset == b.offset).map(
                    |r| r.complete(),
                )
            })
            .map(|r| r.into_iter().map(|e| e.peer).collect());

        // If we've requested every single block for this piece and they're all complete, remove it
        // and report completion
        let scale = self.scale;
        let lp = self.last_piece;
        let lps = self.last_piece_scale;
        let complete = self.downloading
            .get_mut(&b.index)
            .map(|r| {
                (r.len() as u32 == scale || (b.index == lp && r.len() as u32 == lps)) &&
                    r.iter().all(|d| d.completed)
            })
            .unwrap_or(false);

        if complete {
            self.downloading.remove(&b.index);
        }

        res.map(|r| (complete, r)).ok_or(())
    }

    /// Invalidates a piece
    pub fn invalidate_piece(&mut self, idx: u32) {
        match self.picker {
            PickerKind::Sequential(ref mut p) => p.incomplete(idx),
            PickerKind::Rarest(ref mut p) => p.incomplete(idx),
        }
        self.unpicked.unset_bit(idx as u64);
    }

    pub fn piece_available(&mut self, idx: u32) {
        if let PickerKind::Rarest(ref mut p) = self.picker {
            p.piece_available(idx);
        }
    }

    pub fn add_peer<T: cio::CIO>(&mut self, peer: &Peer<T>) {
        if peer.pieces().complete() {
            self.seeders += 1;
        }
        if let PickerKind::Rarest(ref mut p) = self.picker {
            p.add_peer(peer);
        }
    }

    pub fn remove_peer<T: cio::CIO>(&mut self, peer: &Peer<T>) {
        if let PickerKind::Rarest(ref mut p) = self.picker {
            p.remove_peer(peer);
        }

        for piece in self.downloading.values_mut() {
            for block in piece {
                block.requested.retain(|req| req.peer != peer.id())
            }
        }
    }

    /// Alters the picker to sequential/non sequential. If changing
    /// from sequential to non sequential, peer state will need to be loaded
    /// after this.
    pub fn change_picker(&mut self, sequential: bool) {
        self.picker = if sequential {
            PickerKind::Sequential(sequential::Picker::new(&self.unpicked))
        } else {
            PickerKind::Rarest(rarest::Picker::new(&self.unpicked))
        };
        for i in self.downloading.keys() {
            if let PickerKind::Rarest(ref mut p) = self.picker {
                p.dec_avail(*i);
            }
        }
    }

    pub fn refresh_picker(&mut self, pieces: &Bitfield) {
        self.unpicked = pieces.clone();
        self.picker = if self.is_sequential() {
            PickerKind::Sequential(sequential::Picker::new(&self.unpicked))
        } else {
            PickerKind::Rarest(rarest::Picker::new(&self.unpicked))
        };
    }
}

#[cfg(test)]
impl Picker {
    pub fn new_rarest(info: &Info, pieces: &Bitfield) -> Picker {
        Picker::new(info, pieces)
    }

    pub fn new_sequential(info: &Info, pieces: &Bitfield) -> Picker {
        let mut p = Picker::new(info, pieces);
        p.change_picker(true);
        p
    }
}
impl Block {
    pub fn new(index: u32, offset: u32) -> Block {
        Block { index, offset }
    }
}

impl Request {
    fn new(peer: usize) -> Request {
        Request {
            peer,
            requested_at: time::Instant::now(),
        }
    }
}

impl Downloading {
    fn complete(&mut self) -> Vec<Request> {
        self.completed = true;
        mem::replace(&mut self.requested, Vec::with_capacity(0))
    }
}
<|endoftext|>


<commit_before>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{App, Arg};
use std::fs;
use std::path::Path;

static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "Remove the DIRECTORY(ies), if they are empty.";
static OPT_IGNORE_FAIL_NON_EMPTY: &str = "ignore-fail-on-non-empty";
static OPT_PARENTS: &str = "parents";
static OPT_VERBOSE: &str = "verbose";

static ARG_DIRS: &str = "dirs";

static ENOTDIR: i32 = 20;

fn get_usage() -> String {
    format!("{0} [OPTION]... DIRECTORY...", executable!())
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(OPT_IGNORE_FAIL_NON_EMPTY)
                .long(OPT_IGNORE_FAIL_NON_EMPTY)
                .help("ignore each failure that is solely because a directory is non-empty"),
        )
        .arg(
            Arg::with_name(OPT_PARENTS)
                .short("p")
                .long(OPT_PARENTS)
                .help(
                    "remove DIRECTORY and its ancestors; e.g.,
                  'rmdir -p a/b/c' is similar to rmdir a/b/c a/b a",
                ),
        )
        .arg(
            Arg::with_name(OPT_VERBOSE)
                .short("v")
                .long(OPT_VERBOSE)
                .help("output a diagnostic for every directory processed"),
        )
        .arg(
            Arg::with_name(ARG_DIRS)
                .multiple(true)
                .takes_value(true)
                .min_values(1)
                .required(true),
        )
        .get_matches_from(args);

    let dirs: Vec<String> = matches
        .values_of(ARG_DIRS)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    let ignore = matches.is_present(OPT_IGNORE_FAIL_NON_EMPTY);
    let parents = matches.is_present(OPT_PARENTS);
    let verbose = matches.is_present(OPT_VERBOSE);

    match remove(dirs, ignore, parents, verbose) {
        Ok(()) => ( /* pass */ ),
        Err(e) => return e,
    }

    0
}

fn remove(dirs: Vec<String>, ignore: bool, parents: bool, verbose: bool) -> Result<(), i32> {
    let mut r = Ok(());

    for dir in &dirs {
        let path = Path::new(&dir[..]);
        r = remove_dir(&path, ignore, verbose).and(r);
        if parents {
            let mut p = path;
            while let Some(new_p) = p.parent() {
                p = new_p;
                match p.as_os_str().to_str() {
                    None => break,
                    Some(s) => match s {
                        "" | "." | "/" => break,
                        _ => (),
                    },
                };
                r = remove_dir(p, ignore, verbose).and(r);
            }
        }
    }

    r
}

fn remove_dir(path: &Path, ignore: bool, verbose: bool) -> Result<(), i32> {
    let mut read_dir = match fs::read_dir(path) {
        Ok(m) => m,
        Err(e) if e.raw_os_error() == Some(ENOTDIR) => {
            show_error!("failed to remove '{}': Not a directory", path.display());
            return Err(1);
        }
        Err(e) => {
            show_error!("reading directory '{}': {}", path.display(), e);
            return Err(1);
        }
    };

    let mut r = Ok(());

    if read_dir.next().is_none() {
        match fs::remove_dir(path) {
            Err(e) => {
                show_error!("removing directory '{}': {}", path.display(), e);
                r = Err(1);
            }
            Ok(_) if verbose => println!("removing directory, '{}'", path.display()),
            _ => (),
        }
    } else if !ignore {
        show_error!("failed to remove '{}': Directory not empty", path.display());
        r = Err(1);
    }

    r
}
<commit_msg>add a comment to explain the why<commit_after>//  * This file is part of the uutils coreutils package.
//  *
//  * (c) Alex Lyon <arcterus@mail.com>
//  *
//  * For the full copyright and license information, please view the LICENSE
//  * file that was distributed with this source code.

#[macro_use]
extern crate uucore;

use clap::{App, Arg};
use std::fs;
use std::path::Path;

static VERSION: &str = env!("CARGO_PKG_VERSION");
static ABOUT: &str = "Remove the DIRECTORY(ies), if they are empty.";
static OPT_IGNORE_FAIL_NON_EMPTY: &str = "ignore-fail-on-non-empty";
static OPT_PARENTS: &str = "parents";
static OPT_VERBOSE: &str = "verbose";

static ARG_DIRS: &str = "dirs";

static ENOTDIR: i32 = 20;

fn get_usage() -> String {
    format!("{0} [OPTION]... DIRECTORY...", executable!())
}

pub fn uumain(args: impl uucore::Args) -> i32 {
    let usage = get_usage();

    let matches = App::new(executable!())
        .version(VERSION)
        .about(ABOUT)
        .usage(&usage[..])
        .arg(
            Arg::with_name(OPT_IGNORE_FAIL_NON_EMPTY)
                .long(OPT_IGNORE_FAIL_NON_EMPTY)
                .help("ignore each failure that is solely because a directory is non-empty"),
        )
        .arg(
            Arg::with_name(OPT_PARENTS)
                .short("p")
                .long(OPT_PARENTS)
                .help(
                    "remove DIRECTORY and its ancestors; e.g.,
                  'rmdir -p a/b/c' is similar to rmdir a/b/c a/b a",
                ),
        )
        .arg(
            Arg::with_name(OPT_VERBOSE)
                .short("v")
                .long(OPT_VERBOSE)
                .help("output a diagnostic for every directory processed"),
        )
        .arg(
            Arg::with_name(ARG_DIRS)
                .multiple(true)
                .takes_value(true)
                .min_values(1)
                .required(true),
        )
        .get_matches_from(args);

    let dirs: Vec<String> = matches
        .values_of(ARG_DIRS)
        .map(|v| v.map(ToString::to_string).collect())
        .unwrap_or_default();

    let ignore = matches.is_present(OPT_IGNORE_FAIL_NON_EMPTY);
    let parents = matches.is_present(OPT_PARENTS);
    let verbose = matches.is_present(OPT_VERBOSE);

    match remove(dirs, ignore, parents, verbose) {
        Ok(()) => ( /* pass */ ),
        Err(e) => return e,
    }

    0
}

fn remove(dirs: Vec<String>, ignore: bool, parents: bool, verbose: bool) -> Result<(), i32> {
    let mut r = Ok(());

    for dir in &dirs {
        let path = Path::new(&dir[..]);
        r = remove_dir(&path, ignore, verbose).and(r);
        if parents {
            let mut p = path;
            while let Some(new_p) = p.parent() {
                p = new_p;
                match p.as_os_str().to_str() {
                    None => break,
                    Some(s) => match s {
                        "" | "." | "/" => break,
                        _ => (),
                    },
                };
                r = remove_dir(p, ignore, verbose).and(r);
            }
        }
    }

    r
}

fn remove_dir(path: &Path, ignore: bool, verbose: bool) -> Result<(), i32> {
    let mut read_dir = match fs::read_dir(path) {
        Ok(m) => m,
        Err(e) if e.raw_os_error() == Some(ENOTDIR) => {
        // To match the GNU output
            show_error!("failed to remove '{}': Not a directory", path.display());
            return Err(1);
        }
        Err(e) => {
            show_error!("reading directory '{}': {}", path.display(), e);
            return Err(1);
        }
    };

    let mut r = Ok(());

    if read_dir.next().is_none() {
        match fs::remove_dir(path) {
            Err(e) => {
                show_error!("removing directory '{}': {}", path.display(), e);
                r = Err(1);
            }
            Ok(_) if verbose => println!("removing directory, '{}'", path.display()),
            _ => (),
        }
    } else if !ignore {
        show_error!("failed to remove '{}': Directory not empty", path.display());
        r = Err(1);
    }

    r
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    cargo::Cargo,
    config::{CargoConfig, CargoInstallation},
};
use log::{error, info, warn};
use std::process::Command;

pub struct Installer {
    cargo_config: CargoConfig,
    cargo_installations: Vec<(String, CargoInstallation)>,
    rust_installation: Vec<String>,
}

impl Installer {
    pub fn new(
        cargo_config: CargoConfig,
        cargo_installations: Vec<(String, CargoInstallation)>,
        rust_installation: Vec<String>,
    ) -> Installer {
        Self {
            cargo_config,
            cargo_installations,
            rust_installation,
        }
    }

    // Given the name of a tool in the tools list, return the version.
    fn cargo_installation(&self, name: &str) -> Option<&CargoInstallation> {
        self.cargo_installations
            .as_slice()
            .iter()
            .find_map(|(x, y)| if x.eq(&name) { Some(y) } else { None })
    }

    pub fn install_via_cargo_if_needed(&self, name: &str) -> bool {
        match &self.cargo_installation(name) {
            Some(cargo_installation) => {
                install_cargo_component_if_needed(&self.cargo_config, name, &cargo_installation)
            }
            None => {
                info!("No version of tool {} is specified ", name);
                false
            }
        }
    }

    pub fn install_via_rustup_if_needed(&self, name: &str) -> bool {
        install_rustup_component_if_needed(name)
    }

    #[allow(dead_code)]
    fn check_cargo_component(&self, name: &str) -> bool {
        match &self.cargo_installation(name) {
            Some(cargo_installation) => {
                check_installed_cargo_component(name, &cargo_installation.version)
            }
            None => {
                info!("No version of tool {} is specified ", name);
                false
            }
        }
    }

    #[allow(dead_code)]
    fn install_rustup_component(&self, name: &str) -> bool {
        install_rustup_component_if_needed(name)
    }

    pub fn check_all(&self) -> bool {
        let iter = self
            .cargo_installations
            .as_slice()
            .iter()
            .map(|(name, installation)| (name, &installation.version))
            .collect::<Vec<(&String, &String)>>();
        check_all_cargo_components(iter.as_slice())
    }

    pub fn install_all(&self) -> bool {
        let mut result =
            install_all_cargo_components(&self.cargo_config, &self.cargo_installations.as_slice());
        result &= install_all_rustup_components(&self.rust_installation.as_slice());
        result
    }
}

pub fn install_rustup_component_if_needed(name: &str) -> bool {
    let mut cmd = Command::new("rustup");
    cmd.args(&["component", "list", "--installed"]);
    let result = cmd.output();

    let installed = if let Ok(output) = result {
        let bytes = output.stdout.as_slice();
        let installed_components = String::from_utf8_lossy(bytes);
        installed_components.contains(name)
    } else {
        false
    };
    if !installed {
        info!("installing rustup component: {}", name);
        let mut cmd = Command::new("rustup");
        cmd.args(&["component", "add", name]);
        if cmd.output().is_ok() {
            info!("rustup component {} has been installed", name);
        } else {
            warn!("rustup component {} failed to install", name);
        }
        cmd.output().is_ok()
    } else {
        info!("rustup component {} is already installed", name);
        true
    }
}

fn install_all_rustup_components(names: &[String]) -> bool {
    let mut result = true;
    for name in names {
        result &= install_rustup_component_if_needed(name);
    }
    result
}

pub fn install_cargo_component_if_needed(
    cargo_config: &CargoConfig,
    name: &str,
    installation: &CargoInstallation,
) -> bool {
    if !check_installed_cargo_component(name, &installation.version) {
        info!("Installing {} {}", name, installation.version);
        //prevent recursive install attempts of sccache.
        let mut cmd = Cargo::new(&cargo_config, "install", true);
        if let Some(features) = &installation.features {
            if !features.is_empty() {
                cmd.arg("--features");
                cmd.args(features);
            }
        }
        if let Some(git_url) = &installation.git {
            cmd.arg("--git");
            cmd.arg(git_url);
            if let Some(git_rev) = &installation.git_rev {
                cmd.arg("--rev");
                cmd.arg(git_rev);
            }
        } else {
            cmd.arg("--version").arg(&installation.version);
        }
        cmd.arg(name);

        let result = cmd.run();
        if result.is_err() {
            error!(
                "Could not install {} {}, check x.toml to ensure tool exists and is not yanked, or provide a git-rev if your x.toml specifies a git-url.",
                name, installation.version
            );
        }
        result.is_ok()
    } else {
        true
    }
}

//TODO check installed features for sccache?
fn check_installed_cargo_component(name: &str, version: &str) -> bool {
    let result = Command::new(name).arg("--version").output();
    let found = match result {
        Ok(output) => format!("{} {}", name, version)
            .eq(String::from_utf8_lossy(&output.stdout.as_slice()).trim()),
        _ => false,
    };
    info!(
        "{} of version {} is{} installed",
        name,
        version,
        if !found { " not" } else { "" }
    );
    found
}

fn install_all_cargo_components(
    config: &CargoConfig,
    tools: &[(String, CargoInstallation)],
) -> bool {
    let mut success: bool = true;
    for (name, installation) in tools {
        success &= install_cargo_component_if_needed(config, name, installation);
    }
    success
}

fn check_all_cargo_components(tools: &[(&String, &String)]) -> bool {
    let mut success: bool = true;
    for (key, value) in tools {
        success &= check_installed_cargo_component(key, value);
    }
    success
}
<commit_msg>force install<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    cargo::Cargo,
    config::{CargoConfig, CargoInstallation},
};
use log::{error, info, warn};
use std::process::Command;

pub struct Installer {
    cargo_config: CargoConfig,
    cargo_installations: Vec<(String, CargoInstallation)>,
    rust_installation: Vec<String>,
}

impl Installer {
    pub fn new(
        cargo_config: CargoConfig,
        cargo_installations: Vec<(String, CargoInstallation)>,
        rust_installation: Vec<String>,
    ) -> Installer {
        Self {
            cargo_config,
            cargo_installations,
            rust_installation,
        }
    }

    // Given the name of a tool in the tools list, return the version.
    fn cargo_installation(&self, name: &str) -> Option<&CargoInstallation> {
        self.cargo_installations
            .as_slice()
            .iter()
            .find_map(|(x, y)| if x.eq(&name) { Some(y) } else { None })
    }

    pub fn install_via_cargo_if_needed(&self, name: &str) -> bool {
        match &self.cargo_installation(name) {
            Some(cargo_installation) => {
                install_cargo_component_if_needed(&self.cargo_config, name, &cargo_installation)
            }
            None => {
                info!("No version of tool {} is specified ", name);
                false
            }
        }
    }

    pub fn install_via_rustup_if_needed(&self, name: &str) -> bool {
        install_rustup_component_if_needed(name)
    }

    #[allow(dead_code)]
    fn check_cargo_component(&self, name: &str) -> bool {
        match &self.cargo_installation(name) {
            Some(cargo_installation) => {
                check_installed_cargo_component(name, &cargo_installation.version)
            }
            None => {
                info!("No version of tool {} is specified ", name);
                false
            }
        }
    }

    #[allow(dead_code)]
    fn install_rustup_component(&self, name: &str) -> bool {
        install_rustup_component_if_needed(name)
    }

    pub fn check_all(&self) -> bool {
        let iter = self
            .cargo_installations
            .as_slice()
            .iter()
            .map(|(name, installation)| (name, &installation.version))
            .collect::<Vec<(&String, &String)>>();
        check_all_cargo_components(iter.as_slice())
    }

    pub fn install_all(&self) -> bool {
        let mut result =
            install_all_cargo_components(&self.cargo_config, &self.cargo_installations.as_slice());
        result &= install_all_rustup_components(&self.rust_installation.as_slice());
        result
    }
}

pub fn install_rustup_component_if_needed(name: &str) -> bool {
    let mut cmd = Command::new("rustup");
    cmd.args(&["component", "list", "--installed"]);
    let result = cmd.output();

    let installed = if let Ok(output) = result {
        let bytes = output.stdout.as_slice();
        let installed_components = String::from_utf8_lossy(bytes);
        installed_components.contains(name)
    } else {
        false
    };
    if !installed {
        info!("installing rustup component: {}", name);
        let mut cmd = Command::new("rustup");
        cmd.args(&["component", "add", name]);
        if cmd.output().is_ok() {
            info!("rustup component {} has been installed", name);
        } else {
            warn!("rustup component {} failed to install", name);
        }
        cmd.output().is_ok()
    } else {
        info!("rustup component {} is already installed", name);
        true
    }
}

fn install_all_rustup_components(names: &[String]) -> bool {
    let mut result = true;
    for name in names {
        result &= install_rustup_component_if_needed(name);
    }
    result
}

pub fn install_cargo_component_if_needed(
    cargo_config: &CargoConfig,
    name: &str,
    installation: &CargoInstallation,
) -> bool {
    if !check_installed_cargo_component(name, &installation.version) {
        info!("Installing {} {}", name, installation.version);
        //prevent recursive install attempts of sccache.
        let mut cmd = Cargo::new(&cargo_config, "install", true);
        cmd.arg("--force");
        if let Some(features) = &installation.features {
            if !features.is_empty() {
                cmd.arg("--features");
                cmd.args(features);
            }
        }
        if let Some(git_url) = &installation.git {
            cmd.arg("--git");
            cmd.arg(git_url);
            if let Some(git_rev) = &installation.git_rev {
                cmd.arg("--rev");
                cmd.arg(git_rev);
            }
        } else {
            cmd.arg("--version").arg(&installation.version);
        }
        cmd.arg(name);

        let result = cmd.run();
        if result.is_err() {
            error!(
                "Could not install {} {}, check x.toml to ensure tool exists and is not yanked, or provide a git-rev if your x.toml specifies a git-url.",
                name, installation.version
            );
        }
        result.is_ok()
    } else {
        true
    }
}

//TODO check installed features for sccache?
fn check_installed_cargo_component(name: &str, version: &str) -> bool {
    let result = Command::new(name).arg("--version").output();
    let found = match result {
        Ok(output) => format!("{} {}", name, version)
            .eq(String::from_utf8_lossy(&output.stdout.as_slice()).trim()),
        _ => false,
    };
    info!(
        "{} of version {} is{} installed",
        name,
        version,
        if !found { " not" } else { "" }
    );
    found
}

fn install_all_cargo_components(
    config: &CargoConfig,
    tools: &[(String, CargoInstallation)],
) -> bool {
    let mut success: bool = true;
    for (name, installation) in tools {
        success &= install_cargo_component_if_needed(config, name, installation);
    }
    success
}

fn check_all_cargo_components(tools: &[(&String, &String)]) -> bool {
    let mut success: bool = true;
    for (key, value) in tools {
        success &= check_installed_cargo_component(key, value);
    }
    success
}
<|endoftext|>


<commit_before>extern crate threadpool;

use threadpool::ThreadPool;

fn main() {
    let blah = ThreadPool::new(4);
    for i in 0..10000000 {
        blah.execute(move || {
            println!("Hello from parallel thread {}!", i);
        });
    }

    // for i in 0..10000000 {
    //     println!("Hello from linear thread {}!", i);
    // }
}
<commit_msg>add description to task_sched.rs<commit_after>//! Experiments with the threadpool crate.

extern crate threadpool;

use threadpool::ThreadPool;

fn main() {
    let blah = ThreadPool::new(4);
    for i in 0..10000000 {
        blah.execute(move || {
            println!("Hello from parallel thread {}!", i);
        });
    }

    // for i in 0..10000000 {
    //     println!("Hello from linear thread {}!", i);
    // }
}
<|endoftext|>


<commit_before>// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub trait Channel: Num {
    pub fn from<T:Channel>(chan: T) -> Self;
    pub fn to_channel<T:Channel>(&self) -> T;
    pub fn to_channel_u8(&self)  -> u8;
    pub fn to_channel_u16(&self) -> u16;
    pub fn to_channel_f32(&self) -> f32;
    pub fn to_channel_f64(&self) -> f64;
}

impl Channel for u8 {
    #[inline] pub fn from<T:Channel>(chan: T) -> u8 { chan.to_channel_u8() }
    #[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
    #[inline] pub fn to_channel_u8(&self)  -> u8  { (*self) }
    #[inline] pub fn to_channel_u16(&self) -> u16 { (*self as u16 << 8) | (*self) as u16 }
    #[inline] pub fn to_channel_f32(&self) -> f32 { (*self as f32) / (0xFF as f32) }
    #[inline] pub fn to_channel_f64(&self) -> f64 { (*self as f64) / (0xFF as f64) }
}

impl Channel for u16 {
    #[inline] pub fn from<T:Channel>(chan: T) -> u16 { chan.to_channel_u16() }
    #[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
    #[inline] pub fn to_channel_u8(&self)  -> u8  { (*self >> 8) as u8 }
    #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) }
    #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) / 0xFFFF as f32 }
    #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) / 0xFFFF as f64 }
}

impl Channel for f32 {
    #[inline] pub fn from<T:Channel>(chan: T) -> f32 { chan.to_channel_f32() }
    #[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
    #[inline] pub fn to_channel_u8(&self)  -> u8  { (*self) * (0xFF_u8 as f32) as u8 }
    #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF_u16 as f32) as u16 }
    #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) }
    #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) as f64 }
}

impl Channel for f64 {
    #[inline] pub fn from<T:Channel>(chan: T) -> f64 { chan.to_channel_f64() }
    #[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
    #[inline] pub fn to_channel_u8(&self)  -> u8  { (*self) * (0xFF_u8 as f64) as u8 }
    #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF_u16 as f64) as u16 }
    #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) as f32 }
    #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) }
}

#[cfg(test)]
mod tests {
    use color::Channel;

    #[test]
    fn test_channel_u8() {
        assert_eq!(0x00_u8.to_channel_u8(), 0x00_u8);
        assert_eq!(0x30_u8.to_channel_u8(), 0x30_u8);
        assert_eq!(0x66_u8.to_channel_u8(), 0x66_u8);
        assert_eq!(0xA0_u8.to_channel_u8(), 0xA0_u8);
        assert_eq!(0xFF_u8.to_channel_u8(), 0xFF_u8);

        assert_eq!(0x00_u8.to_channel_u16(), 0x0000_u16);
        assert_eq!(0x30_u8.to_channel_u16(), 0x3030_u16);
        assert_eq!(0x66_u8.to_channel_u16(), 0x6666_u16);
        assert_eq!(0xA0_u8.to_channel_u16(), 0xA0A0_u16);
        assert_eq!(0xFF_u8.to_channel_u16(), 0xFFFF_u16);

        assert_eq!(0x00_u8.to_channel_f32(), 0f32);
        assert_eq!(0xFF_u8.to_channel_f32(), 1f32);

        assert_eq!(0x00_u8.to_channel_f64(), 0f64);
        assert_eq!(0xFF_u8.to_channel_f64(), 1f64);
    }

    #[test]
    fn test_channel_u16() {
        assert_eq!(0x0000_u16.to_channel_u8(), 0x00_u8);
        assert_eq!(0x3300_u16.to_channel_u8(), 0x33_u8);
        assert_eq!(0x6666_u16.to_channel_u8(), 0x66_u8);
        assert_eq!(0xAA00_u16.to_channel_u8(), 0xAA_u8);
        assert_eq!(0xFFFF_u16.to_channel_u8(), 0xFF_u8);

        assert_eq!(0x0000_u16.to_channel_u16(), 0x0000_u16);
        assert_eq!(0x3300_u16.to_channel_u16(), 0x3300_u16);
        assert_eq!(0x6666_u16.to_channel_u16(), 0x6666_u16);
        assert_eq!(0xAA00_u16.to_channel_u16(), 0xAA00_u16);
        assert_eq!(0xFFFF_u16.to_channel_u16(), 0xFFFF_u16);

        assert_eq!(0x0000_u16.to_channel_f32(), 0f32);
        assert_eq!(0xFFFF_u16.to_channel_f32(), 1f32);

        assert_eq!(0x0000_u16.to_channel_f64(), 0f64);
        assert_eq!(0xFFFF_u16.to_channel_f64(), 1f64);
    }

    #[test]
    fn test_channel_f32() {
        assert_eq!(0.00f32.to_channel_u8(), 0x00);
        assert_eq!(0.25f32.to_channel_u8(), 0x3F);
        assert_eq!(0.50f32.to_channel_u8(), 0x7F);
        assert_eq!(0.75f32.to_channel_u8(), 0xBF);
        assert_eq!(1.00f32.to_channel_u8(), 0xFF);

        assert_eq!(0.00f32.to_channel_u16(), 0x0000);
        assert_eq!(0.25f32.to_channel_u16(), 0x3FFF);
        assert_eq!(0.50f32.to_channel_u16(), 0x7FFF);
        assert_eq!(0.75f32.to_channel_u16(), 0xBFFF);
        assert_eq!(1.00f32.to_channel_u16(), 0xFFFF);

        assert_eq!(0.00f32.to_channel_f32(), 0.00f32);
        assert_eq!(1.00f32.to_channel_f32(), 1.00f32);

        assert_eq!(0.00f32.to_channel_f64(), 0.00f64);
        assert_eq!(1.00f32.to_channel_f64(), 1.00f64);
    }

    #[test]
    fn test_channel_f64() {
        assert_eq!(0.00f64.to_channel_u8(), 0x00);
        assert_eq!(0.25f64.to_channel_u8(), 0x3F);
        assert_eq!(0.50f64.to_channel_u8(), 0x7F);
        assert_eq!(0.75f64.to_channel_u8(), 0xBF);
        assert_eq!(1.00f64.to_channel_u8(), 0xFF);

        assert_eq!(0.00f64.to_channel_u16(), 0x0000);
        assert_eq!(0.25f64.to_channel_u16(), 0x3FFF);
        assert_eq!(0.50f64.to_channel_u16(), 0x7FFF);
        assert_eq!(0.75f64.to_channel_u16(), 0xBFFF);
        assert_eq!(1.00f64.to_channel_u16(), 0xFFFF);

        assert_eq!(0.00f64.to_channel_f32(), 0.00f32);
        assert_eq!(1.00f64.to_channel_f32(), 1.00f32);

        assert_eq!(0.00f64.to_channel_f64(), 0.00f64);
        assert_eq!(1.00f64.to_channel_f64(), 1.00f64);
    }
}
<commit_msg>Make Channel::from private<commit_after>// Copyright 2013 The Lmath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub trait Channel: Num {
    priv fn from<T:Channel>(chan: T) -> Self;
    pub fn to_channel<T:Channel>(&self) -> T;
    pub fn to_channel_u8(&self)  -> u8;
    pub fn to_channel_u16(&self) -> u16;
    pub fn to_channel_f32(&self) -> f32;
    pub fn to_channel_f64(&self) -> f64;
}

impl Channel for u8 {
    #[inline] priv fn from<T:Channel>(chan: T) -> u8 { chan.to_channel_u8() }
    #[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
    #[inline] pub fn to_channel_u8(&self)  -> u8  { (*self) }
    #[inline] pub fn to_channel_u16(&self) -> u16 { (*self as u16 << 8) | (*self) as u16 }
    #[inline] pub fn to_channel_f32(&self) -> f32 { (*self as f32) / (0xFF as f32) }
    #[inline] pub fn to_channel_f64(&self) -> f64 { (*self as f64) / (0xFF as f64) }
}

impl Channel for u16 {
    #[inline] priv fn from<T:Channel>(chan: T) -> u16 { chan.to_channel_u16() }
    #[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
    #[inline] pub fn to_channel_u8(&self)  -> u8  { (*self >> 8) as u8 }
    #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) }
    #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) / 0xFFFF as f32 }
    #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) / 0xFFFF as f64 }
}

impl Channel for f32 {
    #[inline] priv fn from<T:Channel>(chan: T) -> f32 { chan.to_channel_f32() }
    #[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
    #[inline] pub fn to_channel_u8(&self)  -> u8  { (*self) * (0xFF_u8 as f32) as u8 }
    #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF_u16 as f32) as u16 }
    #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) }
    #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) as f64 }
}

impl Channel for f64 {
    #[inline] priv fn from<T:Channel>(chan: T) -> f64 { chan.to_channel_f64() }
    #[inlune] pub fn to_channel<T:Channel>(&self) -> T { Channel::from(*self) }
    #[inline] pub fn to_channel_u8(&self)  -> u8  { (*self) * (0xFF_u8 as f64) as u8 }
    #[inline] pub fn to_channel_u16(&self) -> u16 { (*self) * (0xFFFF_u16 as f64) as u16 }
    #[inline] pub fn to_channel_f32(&self) -> f32 { (*self) as f32 }
    #[inline] pub fn to_channel_f64(&self) -> f64 { (*self) }
}

#[cfg(test)]
mod tests {
    use color::Channel;

    #[test]
    fn test_channel_u8() {
        assert_eq!(0x00_u8.to_channel_u8(), 0x00_u8);
        assert_eq!(0x30_u8.to_channel_u8(), 0x30_u8);
        assert_eq!(0x66_u8.to_channel_u8(), 0x66_u8);
        assert_eq!(0xA0_u8.to_channel_u8(), 0xA0_u8);
        assert_eq!(0xFF_u8.to_channel_u8(), 0xFF_u8);

        assert_eq!(0x00_u8.to_channel_u16(), 0x0000_u16);
        assert_eq!(0x30_u8.to_channel_u16(), 0x3030_u16);
        assert_eq!(0x66_u8.to_channel_u16(), 0x6666_u16);
        assert_eq!(0xA0_u8.to_channel_u16(), 0xA0A0_u16);
        assert_eq!(0xFF_u8.to_channel_u16(), 0xFFFF_u16);

        assert_eq!(0x00_u8.to_channel_f32(), 0f32);
        assert_eq!(0xFF_u8.to_channel_f32(), 1f32);

        assert_eq!(0x00_u8.to_channel_f64(), 0f64);
        assert_eq!(0xFF_u8.to_channel_f64(), 1f64);
    }

    #[test]
    fn test_channel_u16() {
        assert_eq!(0x0000_u16.to_channel_u8(), 0x00_u8);
        assert_eq!(0x3300_u16.to_channel_u8(), 0x33_u8);
        assert_eq!(0x6666_u16.to_channel_u8(), 0x66_u8);
        assert_eq!(0xAA00_u16.to_channel_u8(), 0xAA_u8);
        assert_eq!(0xFFFF_u16.to_channel_u8(), 0xFF_u8);

        assert_eq!(0x0000_u16.to_channel_u16(), 0x0000_u16);
        assert_eq!(0x3300_u16.to_channel_u16(), 0x3300_u16);
        assert_eq!(0x6666_u16.to_channel_u16(), 0x6666_u16);
        assert_eq!(0xAA00_u16.to_channel_u16(), 0xAA00_u16);
        assert_eq!(0xFFFF_u16.to_channel_u16(), 0xFFFF_u16);

        assert_eq!(0x0000_u16.to_channel_f32(), 0f32);
        assert_eq!(0xFFFF_u16.to_channel_f32(), 1f32);

        assert_eq!(0x0000_u16.to_channel_f64(), 0f64);
        assert_eq!(0xFFFF_u16.to_channel_f64(), 1f64);
    }

    #[test]
    fn test_channel_f32() {
        assert_eq!(0.00f32.to_channel_u8(), 0x00);
        assert_eq!(0.25f32.to_channel_u8(), 0x3F);
        assert_eq!(0.50f32.to_channel_u8(), 0x7F);
        assert_eq!(0.75f32.to_channel_u8(), 0xBF);
        assert_eq!(1.00f32.to_channel_u8(), 0xFF);

        assert_eq!(0.00f32.to_channel_u16(), 0x0000);
        assert_eq!(0.25f32.to_channel_u16(), 0x3FFF);
        assert_eq!(0.50f32.to_channel_u16(), 0x7FFF);
        assert_eq!(0.75f32.to_channel_u16(), 0xBFFF);
        assert_eq!(1.00f32.to_channel_u16(), 0xFFFF);

        assert_eq!(0.00f32.to_channel_f32(), 0.00f32);
        assert_eq!(1.00f32.to_channel_f32(), 1.00f32);

        assert_eq!(0.00f32.to_channel_f64(), 0.00f64);
        assert_eq!(1.00f32.to_channel_f64(), 1.00f64);
    }

    #[test]
    fn test_channel_f64() {
        assert_eq!(0.00f64.to_channel_u8(), 0x00);
        assert_eq!(0.25f64.to_channel_u8(), 0x3F);
        assert_eq!(0.50f64.to_channel_u8(), 0x7F);
        assert_eq!(0.75f64.to_channel_u8(), 0xBF);
        assert_eq!(1.00f64.to_channel_u8(), 0xFF);

        assert_eq!(0.00f64.to_channel_u16(), 0x0000);
        assert_eq!(0.25f64.to_channel_u16(), 0x3FFF);
        assert_eq!(0.50f64.to_channel_u16(), 0x7FFF);
        assert_eq!(0.75f64.to_channel_u16(), 0xBFFF);
        assert_eq!(1.00f64.to_channel_u16(), 0xFFFF);

        assert_eq!(0.00f64.to_channel_f32(), 0.00f32);
        assert_eq!(1.00f64.to_channel_f32(), 1.00f32);

        assert_eq!(0.00f64.to_channel_f64(), 0.00f64);
        assert_eq!(1.00f64.to_channel_f64(), 1.00f64);
    }
}
<|endoftext|>


<commit_before>// Tests that `?` is a Kleene op and not a macro separator in the 2015 edition.

// edition:2018

macro_rules! foo {
    ($(a)?) => {};
}

// The Kleene op `?` does not admit a separator before it.
macro_rules! baz {
    ($(a),?) => {}; //~ERROR the `?` macro repetition operator
}

macro_rules! barplus {
    ($(a)?+) => {}; // ok. matches "a+" and "+"
}

macro_rules! barstar {
    ($(a)?*) => {}; // ok. matches "a*" and "*"
}

pub fn main() {
    foo!();
    foo!(a);
    foo!(a?); //~ ERROR no rules expected the token `?`
    foo!(a?a); //~ ERROR no rules expected the token `?`
    foo!(a?a?a); //~ ERROR no rules expected the token `?`

    barplus!(); //~ERROR unexpected end of macro invocation
    barplus!(a); //~ERROR unexpected end of macro invocation
    barplus!(a?); //~ ERROR no rules expected the token `?`
    barplus!(a?a); //~ ERROR no rules expected the token `?`
    barplus!(a+);
    barplus!(+);

    barstar!(); //~ERROR unexpected end of macro invocation
    barstar!(a); //~ERROR unexpected end of macro invocation
    barstar!(a?); //~ ERROR no rules expected the token `?`
    barstar!(a?a); //~ ERROR no rules expected the token `?`
    barstar!(a*);
    barstar!(*);
}
<commit_msg>Fix typo in comment.<commit_after>// Tests that `?` is a Kleene op and not a macro separator in the 2018 edition.

// edition:2018

macro_rules! foo {
    ($(a)?) => {};
}

// The Kleene op `?` does not admit a separator before it.
macro_rules! baz {
    ($(a),?) => {}; //~ERROR the `?` macro repetition operator
}

macro_rules! barplus {
    ($(a)?+) => {}; // ok. matches "a+" and "+"
}

macro_rules! barstar {
    ($(a)?*) => {}; // ok. matches "a*" and "*"
}

pub fn main() {
    foo!();
    foo!(a);
    foo!(a?); //~ ERROR no rules expected the token `?`
    foo!(a?a); //~ ERROR no rules expected the token `?`
    foo!(a?a?a); //~ ERROR no rules expected the token `?`

    barplus!(); //~ERROR unexpected end of macro invocation
    barplus!(a); //~ERROR unexpected end of macro invocation
    barplus!(a?); //~ ERROR no rules expected the token `?`
    barplus!(a?a); //~ ERROR no rules expected the token `?`
    barplus!(a+);
    barplus!(+);

    barstar!(); //~ERROR unexpected end of macro invocation
    barstar!(a); //~ERROR unexpected end of macro invocation
    barstar!(a?); //~ ERROR no rules expected the token `?`
    barstar!(a?a); //~ ERROR no rules expected the token `?`
    barstar!(a*);
    barstar!(*);
}
<|endoftext|>


<commit_before>use Result;
use config::Config;
use temperature::{self, Simulator};
use temperature::circuit::ThreeDICE;
use threed_ice::{StackElement, System};

pub struct Platform {
    pub elements: Vec<Element>,
    pub temperature: Simulator,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Element {
    Core,
    L3,
}

impl Platform {
    pub fn new(config: &Config) -> Result<Platform> {
        let path = path!(config, "a stack description");

        info!(target: "platform", "Reading {:?}...", &path);
        let system = ok!(System::new(&path));

        let mut elements = vec![];
        for element in system.stack.elements.iter().rev() {
            if let &StackElement::Die(ref die) = element {
                for element in die.floorplan.elements.iter() {
                    let id = element.id.to_lowercase();
                    if id.starts_with("core") {
                        elements.push(Element::Core);
                    } else if id.starts_with("l3") {
                        elements.push(Element::L3);
                    } else {
                        raise!("found an unknown id {:?}", &element.id);
                    }
                }
            }
        }

        info!(target: "platform", "Constructing a thermal circuit...");
        let temperature = {
            let config = some!(config.branch("temperature"),
                               "a temperature configuration is required");
            ok!(Simulator::new(&ok!(ThreeDICE::from(&system)),
                               &try!(new_temperature_config(&config))))
        };

        Ok(Platform { elements: elements, temperature: temperature })
    }
}

fn new_temperature_config(config: &Config) -> Result<temperature::Config> {
    Ok(temperature::Config {
        ambience: *some!(config.get::<f64>("ambience"), "an ambient temperature is required"),
        time_step: *some!(config.get::<f64>("time_step"), "a time step is required"),
    })
}

#[cfg(test)]
mod tests {
    use config::Config;
    use super::Element::{Core, L3};
    use super::Platform;

    #[test]
    fn new() {
        let config = Config::new("tests/fixtures/streamer.toml").unwrap()
                            .branch("platform").unwrap();
        let platform = Platform::new(&config).unwrap();
        assert_eq!(&platform.elements, &[Core, Core, Core, Core, L3]);
    }
}
<commit_msg>Add IDs to a platform’s elements<commit_after>use Result;
use config::Config;
use id::ID;
use temperature::circuit::ThreeDICE;
use temperature::{self, Simulator};
use threed_ice::{StackElement, System};

pub struct Platform {
    pub elements: Vec<Element>,
    pub temperature: Simulator,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Element {
    pub id: ID,
    pub kind: ElementKind,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ElementKind {
    Core,
    L3,
}

impl Platform {
    pub fn new(config: &Config) -> Result<Platform> {
        let path = path!(config, "a stack description");

        info!(target: "platform", "Reading {:?}...", &path);
        let system = ok!(System::new(&path));

        let mut elements = vec![];
        for element in system.stack.elements.iter().rev() {
            let die = match element {
                &StackElement::Die(ref die) => die,
                _ => continue,
            };
            for element in die.floorplan.elements.iter() {
                let id = element.id.to_lowercase();
                if id.starts_with("core") {
                    elements.push(Element {
                        id: ID::new("core"),
                        kind: ElementKind::Core,
                    });
                } else if id.starts_with("l3") {
                    elements.push(Element {
                        id: ID::new("l3"),
                        kind: ElementKind::L3,
                    });
                } else {
                    raise!("found an unknown id {:?}", &element.id);
                }
            }
        }

        info!(target: "platform", "Constructing a thermal circuit...");
        let temperature = {
            let config = some!(config.branch("temperature"),
                               "a temperature configuration is required");
            ok!(Simulator::new(&ok!(ThreeDICE::from(&system)),
                               &try!(new_temperature_config(&config))))
        };

        Ok(Platform { elements: elements, temperature: temperature })
    }
}

fn new_temperature_config(config: &Config) -> Result<temperature::Config> {
    Ok(temperature::Config {
        ambience: *some!(config.get::<f64>("ambience"), "an ambient temperature is required"),
        time_step: *some!(config.get::<f64>("time_step"), "a time step is required"),
    })
}

#[cfg(test)]
mod tests {
    use config::Config;
    use super::ElementKind::{Core, L3};
    use super::Platform;

    #[test]
    fn new() {
        let config = Config::new("tests/fixtures/streamer.toml").unwrap()
                            .branch("platform").unwrap();
        let platform = Platform::new(&config).unwrap();
        assert_eq!(&platform.elements.iter().map(|element| element.kind).collect::<Vec<_>>(),
                   &[Core, Core, Core, Core, L3]);
    }
}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![crate_id = "vmit#0.1"]

use std::os::getcwd;

pub struct Workspace {
    dir: ~Path
}

impl Workspace {

    pub fn new(dir: &Path) -> Workspace {
        Workspace { dir: ~dir.clone()}
    }

    pub fn from_pwd() -> Workspace {
        Workspace::new(&std::os::getcwd())
    }
}

impl std::fmt::Show for Workspace {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f.buf, "Hi: {}", self.dir.display())
    }
}

#[cfg(test)]
mod test {

    use std::io::TempDir;
    use super::Workspace;

    #[test]
    fn test_workspace() {
        match TempDir::new("vmit") {
            Some(tmpdir) => {
                println!("{}", tmpdir.path().display());
                let ws = Workspace::new(tmpdir.path());

            }
            None => {
              println!("ups!");
            }
        }
        assert_eq!(1, 3);
    }
}

<commit_msg>updates for rust nightly (pre 0.11)<commit_after>#![crate_type = "lib"]
#![crate_id = "vmit#0.1"]

use std::os::getcwd;
use std::owned::Box;

pub struct Workspace {
    dir: Box<Path>
}

impl Workspace {

    pub fn new(dir: &Path) -> Workspace {
        Workspace { dir: box dir.clone()}
    }

    pub fn from_pwd() -> Workspace {
        Workspace::new(&std::os::getcwd())
    }
}

impl std::fmt::Show for Workspace {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "Hi: {}", self.dir.display())
    }
}

#[cfg(test)]
mod test {

    use std::io::TempDir;
    use super::Workspace;

    #[test]
    fn test_workspace() {
        match TempDir::new("vmit") {
            Some(tmpdir) => {
                println!("{}", tmpdir.path().display());
                let ws = Workspace::new(tmpdir.path());

            }
            None => {
              println!("ups!");
            }
        }
        assert_eq!(1, 3);
    }
}

<|endoftext|>


<commit_before><commit_msg>refactor(Patches): Reduces verbosity of log message<commit_after><|endoftext|>