<commit_before>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

// TODO define trait for commonalities between tsv::Record and binary::Record
pub trait MerfishRecord {
    fn get_cell_id(&self) -> u32;
}

pub mod tsv {
    use std::io;
    use std::fs;
    use std::path::Path;

    use csv;
    use io::merfishdata::MerfishRecord;

    /// A 2D position in the microscope.
    #[derive(Serialize, Deserialize, Debug)]
    pub struct Position {
        #[serde(rename = "Position_X")]
        pub x: f32,
        #[serde(rename = "Position_Y")]
        pub y: f32,
    }

    /// A MERFISH raw data record.
    /// // "Cell_ID	Gene_Name	Hamming_Distance	Cell_Position_X	Cell_Position_Y	RNA_Position_X	RNA_Position_Y
    #[derive(Serialize, Deserialize, Debug)]
    pub struct Record {
        #[serde(rename = "Cell_ID")]
        pub cell_id: String,
        #[serde(rename = "Gene_Name")]
        pub feature: String,
        #[serde(rename = "Hamming_Distance")]
        pub hamming_dist: u8,
        #[serde(flatten, with = "prefix_cell")]
        pub cell_position: Position,
        #[serde(flatten, with = "prefix_rna")]
        pub rna_position: Position,
    }

    with_prefix!(prefix_cell "Cell_");
    with_prefix!(prefix_rna "RNA_");

    impl MerfishRecord for Record {
        fn get_cell_id(&self) -> u32 {
            self.cell_id.parse().expect("Failed parsing cell_id")
        }
    }

    /// A reader for MERFISH raw data.
    pub struct Reader<R: io::Read> {
        inner: csv::Reader<R>
    }

    impl Reader<fs::File> {
        /// Read from a given file path.
        pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
            fs::File::open(path).map(Reader::from_reader)
        }
    }

    impl<R: io::Read> Reader<R> {
        pub fn from_reader(rdr: R) -> Self {
            Reader {
                inner: csv::ReaderBuilder::new().delimiter(b'\t').from_reader(rdr)
            }
        }

        pub fn records(&mut self) -> csv::DeserializeRecordsIter<R, Record> {
            self.inner.deserialize()
        }
    }
}

pub mod binary {
    use std::io;
    use std::io::Read;
    use std::fs;
    use bincode;
    use std::path::Path;
    use io::merfishdata::MerfishRecord;

    /// Header of a binary merfish file.
    #[derive(Serialize, Deserialize, Debug)]
    pub struct Header {
        version: u8,
        #[serde(rename = "isCorrupt")]
        is_corrupt: u8,
        #[serde(rename = "numEntries")]
        num_entries: u32,
        #[serde(rename = "headerLength")]
        header_length: u32,
    }

    impl Header {
        pub fn version(&self) -> u8 { self.version }
        pub fn is_corrupt(&self) -> u8 {
            self.is_corrupt
        }
        pub fn num_entries(&self) -> u32 {
            self.num_entries
        }
        /// Length of the line giving the field names of a record
        pub fn header_length(&self) -> u32 {
            self.header_length
        }
    }

    /// A `Record` represents a single entry of a merfish binary file.
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    pub struct Record {
        /// An integer representation of the 16-bit barcode associated with each RNA.
        pub barcode: u64,
        /// The specific codebook entry to which this barcode corresponds, e.g. '1' corresponds to the first RNA listed in the codebook ('Blank-1'), '2' corresponds to the second ('Blank-10'), etc.
        pub barcode_id: u16,
        /// The id associated with the field-of-view in which this RNA was imaged.
        pub fov_id: u16,
        /// The sum of the normalized intensity associated with each pixel assigned to a given RNA.
        pub total_magnitude: f32,
        /// The center of the pixels associated with a given RNA in the coordinate system of each field-of-view in units of pixels.
        pub pixel_centroid: [u16; 2],
        /// The center of an RNA, weighted by the intensity of each pixel, in the coordinate system of each field-of-view in units of pixels.
        pub weighted_pixel_centroid: [f32; 2],
        /// The center of an RNA in the absolute coordinate system of the sample in microns. This quantity is calculated from the weighted_pixel_centroid.
        pub abs_position: [f32; 2],
        /// The number of pixels associated with an RNA.
        pub area: u16,
        /// The normalized intensity of each pixel for each bit in the barcode, average across all pixels assigned to an RNA.
        pub pixel_trace_mean: [f32; 16],
        /// The standard deviation of the normalized intensity for each bit in the barcode taken across all pixels assigned to an RNA.
        pub pixel_trace_std: [f32; 16],
        /// A boolean flag representing whether or not (TRUE/FALSE) the measured pixel trace for an RNA matched exactly to a barcode or required error correction at one bit.
        pub is_exact: u8,
        /// The bit at which error correction was applied. (0 if it was not applied).
        pub error_bit: u8,
        /// A boolean representing the type of error (0 corresponds to a '0' to '1' error; 1 corresponds to a '1' to '0' error).
        pub error_dir: u8,
        /// The average Euclidean distance between the pixel trace for a given RNA and the barcode to which it was matched.
        pub av_distance: f32,
        /// An integer representing the cell to which an RNA was assigned. This value corresponds to the index in the corresponding cellBoundaries.mat file.
        #[serde(rename = "cellID")]
        pub cell_id: u32,
        /// A boolean flag representing whether or not (TRUE/FALSE) an RNA was found within the nucleus of the cell.
        #[serde(rename = "inNucleus")]
        pub in_nucleus: u8,
        /// The distance (in microns) from the RNA to the closest edge of the nucleus.
        #[serde(rename = "distNucleus")]
        pub dist_nucleus: f64,
        /// The distance (in microns) from the RNA to the closest boundary of the cell.
        #[serde(rename = "distPeriphery")]
        pub dist_periphery: f64,
    }

    impl MerfishRecord for Record {
        fn get_cell_id(&self) -> u32 {
            self.cell_id
        }
    }

    pub struct Reader<R: io::Read> {
        reader: io::BufReader<R>,
        header: Header,
        item: usize,
    }

    impl<R: io::Read> Reader<R> {
        /// Constructs a new `merfish::Reader<R>` where `R: io::Read`.
        ///
        /// This will read the header in order to check if the version matches.
        pub fn new(reader: R) -> Result<Self, &'static str> {
            let mut reader = io::BufReader::new(reader);
            let header: Result<Header, _> = bincode::deserialize_from(&mut reader);
            match header {
                Ok(ref header) if header.version != 1 => Err("Unsupported version {}"),
                Ok(ref header) if header.is_corrupt != 0 => Err("Header is corrupt, i.e. might not have been written properly (while in append mode)"),
                Ok(header) => {
                    // Read (discard) table header
                    let mut header_buf = vec![0u8; header.header_length as usize];
                    let r = reader.read_exact(&mut header_buf);
                    match r {
                        Err(_) => Err("Failed reading table header"),
                        Ok(()) => Ok(Reader {
                            reader,
                            header,
                            item: 0,
                        })
                    }
                }
                Err(_) => Err("Failed reading header")
            }
        }

        pub fn header(&self) -> &Header {
            &self.header
        }
    }

    impl Reader<fs::File> {
        /// Constructs a new `merfish::Reader<fs::File>` from given file.
        ///
        /// This delegates work to `merfish::Reader::new`.
        pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
            fs::File::open(path).map(|r| { Reader::new(r).unwrap() })
        }
    }

    impl<R: io::Read> Iterator for Reader<R> {
        type Item = io::Result<Record>;

        /// Reads a single `merfish::Record` from the file, advancing the iterator.
        fn next(&mut self) -> Option<<Self as Iterator>::Item> {
            let (l, _) = self.size_hint();
            if l == 0 {
                None
            } else {
                match bincode::deserialize_from::<_, Record>(&mut self.reader) {
                    Ok(record) => {
                        self.item += 1;
                        Some(Ok(record))
                    }
                    // TODO: propagate bincode's Error
                    Err(_) => Some(Err(io::Error::new(io::ErrorKind::Other,
                                                      "Failed deserializing record from reader.")))
                }
            }
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            (self.header.num_entries as usize - self.item, Some(self.header.num_entries as usize - self.item))
        }
    }
}

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

    #[test]
    fn test_tsv_records() {
        let data = b"Cell_ID	Gene_Name	Hamming_Distance	Cell_Position_X	Cell_Position_Y	RNA_Position_X	RNA_Position_Y
0	SCUBE3	1	475.5	630.6	13146.86026973	25793.5656964
0	SCUBE3	1	475.5	630.6	13576.7356895	38396.4273422
";
        let mut reader = tsv::Reader::from_reader(io::Cursor::new(&data[..]));
        for r in reader.records() {
            match r {
                Ok(rec) => {
                    assert_eq!(rec.feature, "SCUBE3");
                    assert_eq!(rec.cell_position.x, 475.5);
                }
                Err(e) => panic!("{:?}", e)
            }
        }
    }

    #[test]
    fn test_binary_records() {
        let data = b"\x01\x00\x01\x00\x00\x00\xad\x01\x00\x00\
        barcode,1  1,uint64,barcode_id,1  1,uint16,fov_id,1  1,uint16,\
        total_magnitude,1  1,single,pixel_centroid,1  2,uint16,weighted_pixel_centroid,1  2,\
        single,abs_position,1  2,single,area,1  1,uint16,pixel_trace_mean,1  16,\
        single,pixel_trace_std,1  16,single,is_exact,1  1,uint8,error_bit,1  1,uint8,\
        error_dir,1  1,uint8,av_distance,1  1,single,cellID,1  1,uint32,inNucleus,1  1,uint8,\
        distNucleus,1  1,double,distPeriphery,1  1,double\
        \x1c\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xdb\x1e\xb4A\xae\x00\xe9\x05\x14\x87.C\xe2\x17\xbdD\x9b\xe7\xaf\xc4\x10*8\xc5\x03\x00\xdf>\x1b;\x943\x06><\xee\xeb>\x8b\x97\x95>z\x05C?j\x9c\xe6;lw]=\x1fWp;\xa5\xbfz8\x00\x00\x00\x00 _@<\x87\xff\x8f<\x0c\x11\x88>3\xb1\xdc=_\x03\x8c<\xcd\xee\x99=\xe8\x8c[;AN2=v\x0b\x1d=#S\xd5<\xed\x8a<;\xcf\x81<;wYL=\xf3\xb8;;YN\xb18\x00\x00\x00\x00\x89\x03\xa1;Xh\xc7<zwD=u\xfa:=L\xe9O<\xb7\xe3\x1a=\x01\x00\x00\xcc&\xef>\x02\x00\x00\x00\x01\x00\x00\x00\x80a\xaf\x08@\x00\x00\x00\x809\xfc(@";

        let reader = binary::Reader::new(io::Cursor::new(&data[..])).unwrap();
        let expected_record = binary::Record {
            barcode: 4124,
            barcode_id: 1,
            fov_id: 0,
            total_magnitude: 22.515066,
            pixel_centroid: [174, 1513],
            weighted_pixel_centroid: [174.52765, 1512.7463],
            abs_position: [-1407.2377, -2946.629],
            area: 3,
            pixel_trace_mean: [0.0023688597, 0.13105613, 0.46080196, 0.2921718, 0.7618023, 0.007037689, 0.054068968, 0.0036673022, 0.000059783128, 0.0, 0.01174143, 0.0175779, 0.26575506, 0.107759856, 0.017091451, 0.07516251],
            pixel_trace_std: [0.0033500735, 0.04353166, 0.038341008, 0.02604062, 0.002876933, 0.0028763895, 0.049890008, 0.0028644174, 0.00008454611, 0.0, 0.0049137515, 0.024341747, 0.047965504, 0.04564901, 0.0126899, 0.037814822],
            is_exact: 1,
            error_bit: 0,
            error_dir: 0,
            av_distance: 0.46709287,
            cell_id: 2,
            in_nucleus: 1,
            dist_nucleus: 3.085635185241699,
            dist_periphery: 12.492626190185547,
        };
        for record in reader {
            match record {
                Ok(r) => {
                    assert_eq!(r, expected_record);
                    break;
                }
                Err(_) => panic!(),
            }
        }
    }
}
<commit_msg>properly rename serde fields (second try)<commit_after>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

// TODO define trait for commonalities between tsv::Record and binary::Record
pub trait MerfishRecord {
    fn get_cell_id(&self) -> u32;
}

pub mod tsv {
    use std::io;
    use std::fs;
    use std::path::Path;

    use csv;
    use io::merfishdata::MerfishRecord;

    /// A 2D position in the microscope.
    #[derive(Serialize, Deserialize, Debug)]
    pub struct Position {
        pub x: f32,
        pub y: f32,
    }

    /// A MERFISH raw data record.
    /// // "Cell_ID	Gene_Name	Hamming_Distance	Cell_Position_X	Cell_Position_Y	RNA_Position_X	RNA_Position_Y
    #[derive(Serialize, Deserialize, Debug)]
    pub struct Record {
        #[serde(rename = "cell")]
        pub cell_id: String,
        #[serde(rename = "feat")]
        pub feature: String,
        #[serde(rename = "dist")]
        pub hamming_dist: u8,
        #[serde(flatten, with = "prefix_cell")]
        pub cell_position: Position,
        #[serde(flatten, with = "prefix_none")]
        pub rna_position: Position,
    }

    with_prefix!(prefix_cell "cell_");
    with_prefix!(prefix_none "");

    impl MerfishRecord for Record {
        fn get_cell_id(&self) -> u32 {
            self.cell_id.parse().expect("Failed parsing cell_id")
        }
    }

    /// A reader for MERFISH raw data.
    pub struct Reader<R: io::Read> {
        inner: csv::Reader<R>
    }

    impl Reader<fs::File> {
        /// Read from a given file path.
        pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
            fs::File::open(path).map(Reader::from_reader)
        }
    }

    impl<R: io::Read> Reader<R> {
        pub fn from_reader(rdr: R) -> Self {
            Reader {
                inner: csv::ReaderBuilder::new().delimiter(b'\t').from_reader(rdr)
            }
        }

        pub fn records(&mut self) -> csv::DeserializeRecordsIter<R, Record> {
            self.inner.deserialize()
        }
    }
}

pub mod binary {
    use std::io;
    use std::io::Read;
    use std::fs;
    use bincode;
    use std::path::Path;
    use io::merfishdata::MerfishRecord;

    /// Header of a binary merfish file.
    #[derive(Serialize, Deserialize, Debug)]
    pub struct Header {
        version: u8,
        #[serde(rename = "isCorrupt")]
        is_corrupt: u8,
        #[serde(rename = "numEntries")]
        num_entries: u32,
        #[serde(rename = "headerLength")]
        header_length: u32,
    }

    impl Header {
        pub fn version(&self) -> u8 { self.version }
        pub fn is_corrupt(&self) -> u8 {
            self.is_corrupt
        }
        pub fn num_entries(&self) -> u32 {
            self.num_entries
        }
        /// Length of the line giving the field names of a record
        pub fn header_length(&self) -> u32 {
            self.header_length
        }
    }

    /// A `Record` represents a single entry of a merfish binary file.
    #[derive(Serialize, Deserialize, Debug, PartialEq)]
    pub struct Record {
        /// An integer representation of the 16-bit barcode associated with each RNA.
        pub barcode: u64,
        /// The specific codebook entry to which this barcode corresponds, e.g. '1' corresponds to the first RNA listed in the codebook ('Blank-1'), '2' corresponds to the second ('Blank-10'), etc.
        pub barcode_id: u16,
        /// The id associated with the field-of-view in which this RNA was imaged.
        pub fov_id: u16,
        /// The sum of the normalized intensity associated with each pixel assigned to a given RNA.
        pub total_magnitude: f32,
        /// The center of the pixels associated with a given RNA in the coordinate system of each field-of-view in units of pixels.
        pub pixel_centroid: [u16; 2],
        /// The center of an RNA, weighted by the intensity of each pixel, in the coordinate system of each field-of-view in units of pixels.
        pub weighted_pixel_centroid: [f32; 2],
        /// The center of an RNA in the absolute coordinate system of the sample in microns. This quantity is calculated from the weighted_pixel_centroid.
        pub abs_position: [f32; 2],
        /// The number of pixels associated with an RNA.
        pub area: u16,
        /// The normalized intensity of each pixel for each bit in the barcode, average across all pixels assigned to an RNA.
        pub pixel_trace_mean: [f32; 16],
        /// The standard deviation of the normalized intensity for each bit in the barcode taken across all pixels assigned to an RNA.
        pub pixel_trace_std: [f32; 16],
        /// A boolean flag representing whether or not (TRUE/FALSE) the measured pixel trace for an RNA matched exactly to a barcode or required error correction at one bit.
        pub is_exact: u8,
        /// The bit at which error correction was applied. (0 if it was not applied).
        pub error_bit: u8,
        /// A boolean representing the type of error (0 corresponds to a '0' to '1' error; 1 corresponds to a '1' to '0' error).
        pub error_dir: u8,
        /// The average Euclidean distance between the pixel trace for a given RNA and the barcode to which it was matched.
        pub av_distance: f32,
        /// An integer representing the cell to which an RNA was assigned. This value corresponds to the index in the corresponding cellBoundaries.mat file.
        #[serde(rename = "cellID")]
        pub cell_id: u32,
        /// A boolean flag representing whether or not (TRUE/FALSE) an RNA was found within the nucleus of the cell.
        #[serde(rename = "inNucleus")]
        pub in_nucleus: u8,
        /// The distance (in microns) from the RNA to the closest edge of the nucleus.
        #[serde(rename = "distNucleus")]
        pub dist_nucleus: f64,
        /// The distance (in microns) from the RNA to the closest boundary of the cell.
        #[serde(rename = "distPeriphery")]
        pub dist_periphery: f64,
    }

    impl MerfishRecord for Record {
        fn get_cell_id(&self) -> u32 {
            self.cell_id
        }
    }

    pub struct Reader<R: io::Read> {
        reader: io::BufReader<R>,
        header: Header,
        item: usize,
    }

    impl<R: io::Read> Reader<R> {
        /// Constructs a new `merfish::Reader<R>` where `R: io::Read`.
        ///
        /// This will read the header in order to check if the version matches.
        pub fn new(reader: R) -> Result<Self, &'static str> {
            let mut reader = io::BufReader::new(reader);
            let header: Result<Header, _> = bincode::deserialize_from(&mut reader);
            match header {
                Ok(ref header) if header.version != 1 => Err("Unsupported version {}"),
                Ok(ref header) if header.is_corrupt != 0 => Err("Header is corrupt, i.e. might not have been written properly (while in append mode)"),
                Ok(header) => {
                    // Read (discard) table header
                    let mut header_buf = vec![0u8; header.header_length as usize];
                    let r = reader.read_exact(&mut header_buf);
                    match r {
                        Err(_) => Err("Failed reading table header"),
                        Ok(()) => Ok(Reader {
                            reader,
                            header,
                            item: 0,
                        })
                    }
                }
                Err(_) => Err("Failed reading header")
            }
        }

        pub fn header(&self) -> &Header {
            &self.header
        }
    }

    impl Reader<fs::File> {
        /// Constructs a new `merfish::Reader<fs::File>` from given file.
        ///
        /// This delegates work to `merfish::Reader::new`.
        pub fn from_file<P: AsRef<Path>>(path: P) -> io::Result<Self> {
            fs::File::open(path).map(|r| { Reader::new(r).unwrap() })
        }
    }

    impl<R: io::Read> Iterator for Reader<R> {
        type Item = io::Result<Record>;

        /// Reads a single `merfish::Record` from the file, advancing the iterator.
        fn next(&mut self) -> Option<<Self as Iterator>::Item> {
            let (l, _) = self.size_hint();
            if l == 0 {
                None
            } else {
                match bincode::deserialize_from::<_, Record>(&mut self.reader) {
                    Ok(record) => {
                        self.item += 1;
                        Some(Ok(record))
                    }
                    // TODO: propagate bincode's Error
                    Err(_) => Some(Err(io::Error::new(io::ErrorKind::Other,
                                                      "Failed deserializing record from reader.")))
                }
            }
        }

        fn size_hint(&self) -> (usize, Option<usize>) {
            (self.header.num_entries as usize - self.item, Some(self.header.num_entries as usize - self.item))
        }
    }
}

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

    #[test]
    fn test_tsv_records() {
        let data = b"cell	feat	dist	cell_x	cell_y	x	y
0	SCUBE3	1	475.5	630.6	13146.86026973	25793.5656964
0	SCUBE3	1	475.5	630.6	13576.7356895	38396.4273422
";
        let mut reader = tsv::Reader::from_reader(io::Cursor::new(&data[..]));
        for r in reader.records() {
            match r {
                Ok(rec) => {
                    assert_eq!(rec.feature, "SCUBE3");
                    assert_eq!(rec.cell_position.x, 475.5);
                }
                Err(e) => panic!("{:?}", e)
            }
        }
    }

    #[test]
    fn test_binary_records() {
        let data = b"\x01\x00\x01\x00\x00\x00\xad\x01\x00\x00\
        barcode,1  1,uint64,barcode_id,1  1,uint16,fov_id,1  1,uint16,\
        total_magnitude,1  1,single,pixel_centroid,1  2,uint16,weighted_pixel_centroid,1  2,\
        single,abs_position,1  2,single,area,1  1,uint16,pixel_trace_mean,1  16,\
        single,pixel_trace_std,1  16,single,is_exact,1  1,uint8,error_bit,1  1,uint8,\
        error_dir,1  1,uint8,av_distance,1  1,single,cellID,1  1,uint32,inNucleus,1  1,uint8,\
        distNucleus,1  1,double,distPeriphery,1  1,double\
        \x1c\x10\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xdb\x1e\xb4A\xae\x00\xe9\x05\x14\x87.C\xe2\x17\xbdD\x9b\xe7\xaf\xc4\x10*8\xc5\x03\x00\xdf>\x1b;\x943\x06><\xee\xeb>\x8b\x97\x95>z\x05C?j\x9c\xe6;lw]=\x1fWp;\xa5\xbfz8\x00\x00\x00\x00 _@<\x87\xff\x8f<\x0c\x11\x88>3\xb1\xdc=_\x03\x8c<\xcd\xee\x99=\xe8\x8c[;AN2=v\x0b\x1d=#S\xd5<\xed\x8a<;\xcf\x81<;wYL=\xf3\xb8;;YN\xb18\x00\x00\x00\x00\x89\x03\xa1;Xh\xc7<zwD=u\xfa:=L\xe9O<\xb7\xe3\x1a=\x01\x00\x00\xcc&\xef>\x02\x00\x00\x00\x01\x00\x00\x00\x80a\xaf\x08@\x00\x00\x00\x809\xfc(@";

        let reader = binary::Reader::new(io::Cursor::new(&data[..])).unwrap();
        let expected_record = binary::Record {
            barcode: 4124,
            barcode_id: 1,
            fov_id: 0,
            total_magnitude: 22.515066,
            pixel_centroid: [174, 1513],
            weighted_pixel_centroid: [174.52765, 1512.7463],
            abs_position: [-1407.2377, -2946.629],
            area: 3,
            pixel_trace_mean: [0.0023688597, 0.13105613, 0.46080196, 0.2921718, 0.7618023, 0.007037689, 0.054068968, 0.0036673022, 0.000059783128, 0.0, 0.01174143, 0.0175779, 0.26575506, 0.107759856, 0.017091451, 0.07516251],
            pixel_trace_std: [0.0033500735, 0.04353166, 0.038341008, 0.02604062, 0.002876933, 0.0028763895, 0.049890008, 0.0028644174, 0.00008454611, 0.0, 0.0049137515, 0.024341747, 0.047965504, 0.04564901, 0.0126899, 0.037814822],
            is_exact: 1,
            error_bit: 0,
            error_dir: 0,
            av_distance: 0.46709287,
            cell_id: 2,
            in_nucleus: 1,
            dist_nucleus: 3.085635185241699,
            dist_periphery: 12.492626190185547,
        };
        for record in reader {
            match record {
                Ok(r) => {
                    assert_eq!(r, expected_record);
                    break;
                }
                Err(_) => panic!(),
            }
        }
    }
}
<|endoftext|>


<commit_before>

// xfail-stage0
// xfail-stage1
// xfail-stage2
// xfail-stage3
use std;
import std::_task;

fn main() { _task::sleep(1000000u); }<commit_msg>Add tests for unsupervise<commit_after>

// xfail-stage0

use std;
import std::task;

fn test_sleep() { task::sleep(1000000u); }

fn test_unsupervise() {
  fn f() {
    task::unsupervise();
    fail;
  }
  spawn f();
}

fn main() {
  // FIXME: Why aren't we running this?
  //test_sleep();
  test_unsupervise();
}<|endoftext|>


<commit_before>//! The models crate handles instantiating and using documents and indexes.

/// Document contains information pertaining to a document such as a webpage.
/// Documents have many indexes.
pub struct Document {
    id: i32,
    url: String,
    title: String,
    content: String,
}

impl Document {
    /// new creates a new instantiation of a Document.
    ///
    /// # Examples
    ///
    /// new Document
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    pub fn new(id: i32, url: String, title: String, content: String) -> Document {
        Document {
            id: id,
            url: url,
            title: title,
            content: content,
        }
    }

    /// id() is a getter for the private field id
    ///
    /// # Examples
    ///
    /// Get id
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    /// let id: i32 = d.id();
    /// ```
    pub fn id(&self) -> i32 {
        return self.id;
    }

    /// url() is a getter for the private field url
    ///
    /// # Examples
    ///
    /// Get url
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    /// let url: String = d.url();
    /// ```
    pub fn url(&self) -> String {
        return self.url.to_string();
    }

    /// title() is a getter for the private field title
    ///
    /// # Examples
    ///
    /// Get title
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    /// let title: String = d.title();
    /// ```
    pub fn title(&self) -> String {
        return self.title.to_string();
    }

    /// content() is a getter for the private field content
    ///
    /// # Examples
    ///
    /// Get content
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    /// let content: String = d.content();
    /// ```
    pub fn content(&self) -> String {
        return self.content.to_string();
    }
}

/// Index contains information about a particular word in a document. A document
/// can only contain unique indexes. The locations field should hold all
/// occurences of the word in the document and their location in the document.
pub struct Index<'a> {
    id: i32,
    word: String,
    locations: &'a mut Vec<i32>,
}

impl<'a> Index<'a> {
    /// new() creates a new instantiation of an Index.
    ///
    /// # Examples
    ///
    /// Create Index
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// ```
    pub fn new(id: i32, word: String, locations: &mut Vec<i32>) -> Index {
        Index {
            id: id,
            word: word,
            locations: locations,
        }
    }

    /// id() is a getter for the private field id
    ///
    /// # Examples
    ///
    /// Get id
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// let id: i32 = i.id();
    /// ```
    pub fn id(&self) -> i32 {
        return self.id;
    }

    /// word() is a getter for the private field word
    ///
    /// # Examples
    ///
    /// Get word
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// let word: String = i.word();
    /// ```
    pub fn word(&self) -> String {
        return self.word.to_string();
    }

    /// locations() is a getter for the private field locations
    ///
    /// # Examples
    ///
    /// Get locations
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// let mut index_locations = i.locations();
    /// ```
    pub fn locations(&self) ->  &Vec<i32> {
        return &self.locations;
    }

    /// set_locations() is a setter for the private field locations
    ///
    /// # Examples
    ///
    /// Set locations
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let mut i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// i.set_locations(4); // i.locations now equals [1,2,3,4]
    /// ```
    pub fn set_locations(&mut self, val: i32) {
        self.locations.push(val);
    }
}

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

    #[test]
    fn test_new_document() {
        let d = Document::new(
            1,
            "http://acme.com/about".to_string(),
            "About Us".to_string(),
            "We are Acme and we make things.".to_string(),
        );

        assert_eq!(1, d.id);
        assert_eq!("http://acme.com/about", d.url);
        assert_eq!("About Us", d.title);
        assert_eq!("We are Acme and we make things.", d.content);
    }

    #[test]
    fn test_new_index() {
        let mut locations = vec![1,2,3];
        let i = Index::new(
            1,
            "acme".to_string(),
            &mut locations,
        );

        assert_eq!(1, i.id());
        assert_eq!("acme", i.word());
        assert_eq!(3, i.locations().len());
    }

    #[test]
    fn test_set_locations() {
        let mut locations = vec![1,2,3];
        let mut i = Index::new(
            1,
            "acme".to_string(),
            &mut locations,
        );

        assert_eq!(3, i.locations().len());

        i.set_locations(4);

        assert_eq!(4, i.locations().len());
    }
}<commit_msg>Split set_locations into push and pop functions<commit_after>//! The models crate handles instantiating and using documents and indexes.

/// Document contains information pertaining to a document such as a webpage.
/// Documents have many indexes.
pub struct Document {
    id: i32,
    url: String,
    title: String,
    content: String,
}

impl Document {
    /// new creates a new instantiation of a Document.
    ///
    /// # Examples
    ///
    /// new Document
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    pub fn new(id: i32, url: String, title: String, content: String) -> Document {
        Document {
            id: id,
            url: url,
            title: title,
            content: content,
        }
    }

    /// id() is a getter for the private field id
    ///
    /// # Examples
    ///
    /// Get id
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    /// let id: i32 = d.id();
    /// ```
    pub fn id(&self) -> i32 {
        return self.id;
    }

    /// url() is a getter for the private field url
    ///
    /// # Examples
    ///
    /// Get url
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    /// let url: String = d.url();
    /// ```
    pub fn url(&self) -> String {
        return self.url.to_string();
    }

    /// title() is a getter for the private field title
    ///
    /// # Examples
    ///
    /// Get title
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    /// let title: String = d.title();
    /// ```
    pub fn title(&self) -> String {
        return self.title.to_string();
    }

    /// content() is a getter for the private field content
    ///
    /// # Examples
    ///
    /// Get content
    ///
    /// ```
    /// use kensaku::models::Document;
    ///
    /// let d = Document::new(
    ///     1,
    ///     "http://acme.com/about".to_string(),
    ///     "About Us".to_string(),
    ///     "We are Acme and we make things.".to_string(),
    /// );
    /// let content: String = d.content();
    /// ```
    pub fn content(&self) -> String {
        return self.content.to_string();
    }
}

/// Index contains information about a particular word in a document. A document
/// can only contain unique indexes. The locations field should hold all
/// occurences of the word in the document and their location in the document.
pub struct Index<'a> {
    id: i32,
    word: String,
    locations: &'a mut Vec<i32>,
}

impl<'a> Index<'a> {
    /// new() creates a new instantiation of an Index.
    ///
    /// # Examples
    ///
    /// Create Index
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// ```
    pub fn new(id: i32, word: String, locations: &mut Vec<i32>) -> Index {
        Index {
            id: id,
            word: word,
            locations: locations,
        }
    }

    /// id() is a getter for the private field id
    ///
    /// # Examples
    ///
    /// Get id
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// let id: i32 = i.id();
    /// ```
    pub fn id(&self) -> i32 {
        return self.id;
    }

    /// word() is a getter for the private field word
    ///
    /// # Examples
    ///
    /// Get word
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// let word: String = i.word();
    /// ```
    pub fn word(&self) -> String {
        return self.word.to_string();
    }

    /// locations() is a getter for the private field locations
    ///
    /// # Examples
    ///
    /// Get locations
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// let mut index_locations = i.locations();
    /// ```
    pub fn locations(&self) ->  &Vec<i32> {
        return &self.locations;
    }

    /// push_locations() adds a value to the locations vector
    ///
    /// # Examples
    ///
    /// Push an i32 into locations
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let mut i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// i.push_locations(4); // i.locations now equals [1,2,3,4]
    /// ```
    pub fn push_locations(&mut self, val: i32) {
        self.locations.push(val);
    }

    /// pop_locations() removes a value from the locations vector
    ///
    /// # Examples
    ///
    /// Pop an i32 from locations
    ///
    /// ```
    /// use kensaku::models::Index;
    ///
    /// let mut locations = vec![1,2,3];
    /// let mut i = Index::new(
    ///     1,
    ///     "acme".to_string(),
    ///     &mut locations,
    /// );
    /// let new_locations = i.pop_locations(); // i.locations now equals [1,2] and 3 is returned.
    /// ```
    pub fn pop_locations(&mut self) -> i32 {
        return self.locations.pop().unwrap();
    }
}

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

    #[test]
    fn test_new_document() {
        let d = Document::new(
            1,
            "http://acme.com/about".to_string(),
            "About Us".to_string(),
            "We are Acme and we make things.".to_string(),
        );

        assert_eq!(1, d.id);
        assert_eq!("http://acme.com/about", d.url);
        assert_eq!("About Us", d.title);
        assert_eq!("We are Acme and we make things.", d.content);
    }

    #[test]
    fn test_new_index() {
        let mut locations = vec![1,2,3];
        let i = Index::new(
            1,
            "acme".to_string(),
            &mut locations,
        );

        assert_eq!(1, i.id());
        assert_eq!("acme", i.word());
        assert_eq!(3, i.locations().len());
    }

    #[test]
    fn test_push_locations() {
        let mut locations = vec![1,2,3];
        let mut i = Index::new(
            1,
            "acme".to_string(),
            &mut locations,
        );

        assert_eq!(3, i.locations().len());

        i.push_locations(4);

        assert_eq!(4, i.locations().len());
    }

    #[test]
    fn test_pop_locations() {
        let mut locations = vec![1,2,3];
        let mut i = Index::new(
            1,
            "acme".to_string(),
            &mut locations,
        );

        assert_eq!(3, i.locations().len());

        let new_locations = i.pop_locations();
        assert_eq!(2, i.locations().len());
        assert_eq!(3, new_locations);

        let newer_locations = i.pop_locations();
        assert_eq!(1, i.locations().len());
        assert_eq!(2, newer_locations);
    }
}<|endoftext|>


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

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(unix)]
mod imp {
    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    #[cfg(unix)]
    pub struct OsRng {
        inner: ReaderRng<File>
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: reader_rng })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use core_collections::Collection;
    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use rt::stack;
    use self::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
    use slice::MutableVector;

    type HCRYPTPROV = c_ulong;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
    static NTE_BAD_SIGNATURE: DWORD = 0x80090006;

    #[allow(non_snake_case_functions)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let mut ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            // FIXME #13259:
            // It turns out that if we can't acquire a context with the
            // NTE_BAD_SIGNATURE error code, the documentation states:
            //
            //     The provider DLL signature could not be verified. Either the
            //     DLL or the digital signature has been tampered with.
            //
            // Sounds fishy, no? As it turns out, our signature can be bad
            // because our Thread Information Block (TIB) isn't exactly what it
            // expects. As to why, I have no idea. The only data we store in the
            // TIB is the stack limit for each thread, but apparently that's
            // enough to make the signature valid.
            //
            // Furthermore, this error only happens the *first* time we call
            // CryptAcquireContext, so we don't have to worry about future
            // calls.
            //
            // Anyway, the fix employed here is that if we see this error, we
            // pray that we're not close to the end of the stack, temporarily
            // set the stack limit to 0 (what the TIB originally was), acquire a
            // context, and then reset the stack limit.
            //
            // Again, I'm not sure why this is the fix, nor why we're getting
            // this error. All I can say is that this seems to allow libnative
            // to progress where it otherwise would be hindered. Who knew?
            if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
                unsafe {
                    let limit = stack::get_sp_limit();
                    stack::record_sp_limit(0);
                    ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                               PROV_RSA_FULL,
                                               CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
                    stack::record_sp_limit(limit);
                }
            }

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>Basic iOS support<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(unix, not(target_os = "ios"))]
mod imp {
    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::{Ok, Err};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    #[cfg(unix)]
    pub struct OsRng {
        inner: ReaderRng<File>
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: reader_rng })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            self.inner.next_u32()
        }
        fn next_u64(&mut self) -> u64 {
            self.inner.next_u64()
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            self.inner.fill_bytes(v)
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use collections::Collection;
    use io::{IoResult};
    use kinds::marker;
    use mem;
    use os;
    use rand::Rng;
    use result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::MutableVector;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
    /// This does not block.
    pub struct OsRng {
        marker: marker::NoCopy
    }

    struct SecRandom;

    static kSecRandomDefault: *SecRandom = 0 as *SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *SecRandom, count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng {marker: marker::NoCopy} )
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use core_collections::Collection;
    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::{Ok, Err};
    use rt::stack;
    use self::libc::{c_ulong, DWORD, BYTE, LPCSTR, BOOL};
    use slice::MutableVector;

    type HCRYPTPROV = c_ulong;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;
    static NTE_BAD_SIGNATURE: DWORD = 0x80090006;

    #[allow(non_snake_case_functions)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let mut ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            // FIXME #13259:
            // It turns out that if we can't acquire a context with the
            // NTE_BAD_SIGNATURE error code, the documentation states:
            //
            //     The provider DLL signature could not be verified. Either the
            //     DLL or the digital signature has been tampered with.
            //
            // Sounds fishy, no? As it turns out, our signature can be bad
            // because our Thread Information Block (TIB) isn't exactly what it
            // expects. As to why, I have no idea. The only data we store in the
            // TIB is the stack limit for each thread, but apparently that's
            // enough to make the signature valid.
            //
            // Furthermore, this error only happens the *first* time we call
            // CryptAcquireContext, so we don't have to worry about future
            // calls.
            //
            // Anyway, the fix employed here is that if we see this error, we
            // pray that we're not close to the end of the stack, temporarily
            // set the stack limit to 0 (what the TIB originally was), acquire a
            // context, and then reset the stack limit.
            //
            // Again, I'm not sure why this is the fix, nor why we're getting
            // this error. All I can say is that this seems to allow libnative
            // to progress where it otherwise would be hindered. Who knew?
            if ret == 0 && os::errno() as DWORD == NTE_BAD_SIGNATURE {
                unsafe {
                    let limit = stack::get_sp_limit();
                    stack::record_sp_limit(0);
                    ret = CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                               PROV_RSA_FULL,
                                               CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
                    stack::record_sp_limit(limit);
                }
            }

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 8];
            self.fill_bytes(v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                fail!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                fail!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use task;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8, .. 1000];
        r.fill_bytes(v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0, 20) {
            let (tx, rx) = channel();
            txs.push(tx);
            task::spawn(proc() {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                task::deschedule();
                let mut v = [0u8, .. 1000];

                for _ in range(0, 100) {
                    r.next_u32();
                    task::deschedule();
                    r.next_u64();
                    task::deschedule();
                    r.fill_bytes(v);
                    task::deschedule();
                }
            })
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

use std::collections::{RingBuf, HashSet, VecMap};
use std::mem;
use std::ptr;

use block_allocator::BlockAllocator;
use block_info::BlockInfo;
use constants::{BLOCK_SIZE, LINE_SIZE, NUM_LINES_PER_BLOCK, EVAC_HEADROOM};
use gc_object::{GCRTTI, GCObject, GCObjectRef};

type BlockTuple = (*mut BlockInfo, u16, u16);

pub struct LineAllocator {
    block_allocator: BlockAllocator,
    object_map: HashSet<GCObjectRef>,
    object_map_backup: HashSet<GCObjectRef>,
    mark_histogram: VecMap<u8>,
    unavailable_blocks: RingBuf<*mut BlockInfo>,
    recyclable_blocks: RingBuf<*mut BlockInfo>,
    evac_headroom: RingBuf<*mut BlockInfo>,
    current_block: Option<BlockTuple>,
    overflow_block: Option<BlockTuple>,
    current_live_mark: bool,
}

impl LineAllocator {
    pub fn new(block_allocator: BlockAllocator) -> LineAllocator {
        return LineAllocator {
            block_allocator: block_allocator,
            object_map: HashSet::new(),
            object_map_backup: HashSet::new(),
            mark_histogram: VecMap::with_capacity(NUM_LINES_PER_BLOCK),
            unavailable_blocks: RingBuf::new(),
            recyclable_blocks: RingBuf::new(),
            evac_headroom: RingBuf::new(),
            current_block: None,
            overflow_block: None,
            current_live_mark: false,
        };
    }

    pub fn set_gc_object(&mut self, object: GCObjectRef) {
        self.object_map.insert(object);
    }

    pub fn unset_gc_object(&mut self, object: GCObjectRef) {
        self.object_map.remove(&object);
    }

    pub fn is_gc_object(&self, object: GCObjectRef) -> bool {
        return self.object_map.contains(&object);
    }

    pub fn current_live_mark(&self) -> bool {
        return self.current_live_mark;
    }

    pub fn decrement_lines(&mut self, object: GCObjectRef) {
        unsafe{ (*self.get_block_ptr(object)).decrement_lines(object); }
    }

    pub fn increment_lines(&mut self, object: GCObjectRef) {
        unsafe{ (*self.get_block_ptr(object)).increment_lines(object); }
    }

    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        let size = unsafe{ (*rtti).object_size() };
        debug!("Request to allocate an object of size {}", size);
        if let Some(object) = self.raw_allocate(size) {
            unsafe { ptr::write(object, GCObject::new(rtti, self.current_live_mark)); }
            valgrind_malloclike!(object, size);
            return Some(object);
        }
        return None;
    }

    pub fn prepare_collection(&mut self) -> bool {
        self.unavailable_blocks.extend(self.recyclable_blocks.drain());
        self.unavailable_blocks.extend(self.current_block.take()
                                           .map(|b| b.0).into_iter());

        let perform_cycle_collection = true;
        return perform_cycle_collection;
    }

    pub fn complete_collection(&mut self) {
        self.mark_histogram.clear();
        self.perform_defrag = false;
        self.sweep_unavailable_blocks();
    }

    pub fn prepare_immix_collection(&mut self) {
        for block in self.unavailable_blocks.iter_mut() {
            unsafe{ (**block).clear_line_counts(); }
        }

        if cfg!(feature = "valgrind") {
            self.object_map_backup = self.object_map.clone();
        }
        self.object_map.clear();
    }

    pub fn complete_immix_collection(&mut self) {
        self.current_live_mark = !self.current_live_mark;
        if cfg!(feature = "valgrind") {
            for &object in self.object_map_backup.difference(&self.object_map) {
                valgrind_freelike!(object);
            }
            self.object_map_backup.clear();
        }
    }
}

impl LineAllocator {
    unsafe fn get_block_ptr(&mut self, object: GCObjectRef) -> *mut BlockInfo {
        let block_offset = object as uint % BLOCK_SIZE;
        return mem::transmute((object as *mut u8).offset(-(block_offset as int)));
    }

    fn raw_allocate(&mut self, size: uint) -> Option<GCObjectRef> {
        return if size < LINE_SIZE {
            self.current_block.take()
                              .and_then(|tp| self.scan_for_hole(size, tp))
        } else {
            self.overflow_block.take()
                               .and_then(|tp| self.scan_for_hole(size, tp))
                               .or_else(|| self.get_new_block())
        }.or_else(|| self.scan_recyclables(size))
         .or_else(|| self.get_new_block())
         .map(|tp| self.allocate_from_block(size, tp))
         .map(|(tp, object)| {
             if size < LINE_SIZE { self.current_block = Some(tp);
             } else { self.overflow_block = Some(tp); }
             object
         });
    }

    fn scan_for_hole(&mut self, size: uint, block_tuple: BlockTuple)
        -> Option<BlockTuple> {
            let (block, low, high) = block_tuple;
            return match (high - low) as uint >= size {
                true => {
                    debug!("Found hole in block {:p}", block);
                    Some(block_tuple)
                },
                false => match unsafe{ (*block).scan_block(high) } {
                    None => {
                        debug!("Push block {:p} into unavailable_blocks", block);
                        self.unavailable_blocks.push_back(block);
                        None
                    },
                    Some((low, high)) =>
                        self.scan_for_hole(size, (block, low, high)),
                }
            };
        }

    fn scan_recyclables(&mut self, size: uint) -> Option<BlockTuple> {
        return match self.recyclable_blocks.pop_front() {
            None => None,
            Some(block) => match unsafe{ (*block).scan_block((LINE_SIZE - 1) as u16) } {
                None => {
                    debug!("Push block {:p} into unavailable_blocks", block);
                    self.unavailable_blocks.push_back(block);
                    self.scan_recyclables(size)
                },
                Some((low, high)) => self.scan_for_hole(size, (block, low, high))
                                         .or_else(|| self.scan_recyclables(size)),
            }
        };
    }

    fn allocate_from_block(&mut self, size: uint, block_tuple: BlockTuple)
        -> (BlockTuple, GCObjectRef) {
            let (block, low, high) = block_tuple;
            let object = unsafe { (*block).offset(low as uint) };
            self.set_gc_object(object);
            debug!("Allocated object {} of size {} in {} (object={})",
            object, size, block, size >= LINE_SIZE);
            return ((block, low + size as u16, high), object);
        }

    fn get_new_block(&mut self) -> Option<BlockTuple> {
        return if self.perform_evac {
            debug!("Request new block in evacuation");
            self.evac_headroom.pop_front()
        } else {
            debug!("Request new block");
            self.block_allocator.get_block()
        }.map(|block| (block, LINE_SIZE as u16, (BLOCK_SIZE - 1) as u16));
    }

    fn sweep_unavailable_blocks(&mut self) {
        let mut unavailable_blocks = RingBuf::new();
        for block in self.unavailable_blocks.drain() {
            if unsafe{ (*block).is_empty() } {
                // XXX We should not use a constant here, but something that
                // XXX changes dynamically (see rcimmix: MAX heuristic).
                if self.evac_headroom.len() < EVAC_HEADROOM {
                    debug!("Buffer free block {:p} for evacuation", block);
                    unsafe{ (*block).reset() ;}
                    self.evac_headroom.push_back(block);
                } else {
                    debug!("Return block {:p} to global block allocator", block);
                    self.block_allocator.return_block(block);
                }
            } else {
                unsafe{ (*block).count_holes(); }
                let (holes, marked_lines) = unsafe{ (*block).count_holes_and_marked_lines() };
                if self.mark_histogram.contains_key(&(holes as uint)) {
                    if let Some(val) = self.mark_histogram.get_mut(&(holes as uint)) {
                        *val += marked_lines;
                    }
                } else { self.mark_histogram.insert(holes as uint, marked_lines); }
                debug!("Found {} holes and {} marked lines in block {}",
                       holes, marked_lines, block);
                match holes {
                    0 => {
                        debug!("Push block {:p} into unavailable_blocks", block);
                        unavailable_blocks.push_back(block);
                    },
                    _ => {
                        debug!("Push block {:p} into recyclable_blocks", block);
                        self.recyclable_blocks.push_back(block);
                    }
                }
            }
        }
        self.unavailable_blocks.extend(unavailable_blocks.into_iter());
    }

    fn establish_hole_threshhold(&self) -> u8 {
        let mut available_histogram : VecMap<u8> = VecMap::with_capacity(NUM_LINES_PER_BLOCK);
        for block in self.unavailable_blocks.iter() {
            let (holes, free_lines) = unsafe{ (**block).count_holes_and_available_lines() };
            if available_histogram.contains_key(&(holes as uint)) {
                if let Some(val) = available_histogram.get_mut(&(holes as uint)) {
                    *val += free_lines;
                }
            } else { available_histogram.insert(holes as uint, free_lines); }
        }
        let mut required_lines = 0 as u8;
        let mut available_lines = (self.evac_headroom.len() * (NUM_LINES_PER_BLOCK - 1)) as u8;

        for threshold in range(0, NUM_LINES_PER_BLOCK) {
            required_lines += *self.mark_histogram.get(&threshold).unwrap_or(&0);
            available_lines -= *available_histogram.get(&threshold).unwrap_or(&0);
            if available_lines <= required_lines {
                return threshold as u8;
            }
        }
        return NUM_LINES_PER_BLOCK as u8;
    }
}
<commit_msg>LineAllocator: unify set_gc_object() and malloclike() call<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

use std::collections::{RingBuf, HashSet, VecMap};
use std::mem;
use std::ptr;

use block_allocator::BlockAllocator;
use block_info::BlockInfo;
use constants::{BLOCK_SIZE, LINE_SIZE, NUM_LINES_PER_BLOCK, EVAC_HEADROOM};
use gc_object::{GCRTTI, GCObject, GCObjectRef};

type BlockTuple = (*mut BlockInfo, u16, u16);

pub struct LineAllocator {
    block_allocator: BlockAllocator,
    object_map: HashSet<GCObjectRef>,
    object_map_backup: HashSet<GCObjectRef>,
    mark_histogram: VecMap<u8>,
    unavailable_blocks: RingBuf<*mut BlockInfo>,
    recyclable_blocks: RingBuf<*mut BlockInfo>,
    evac_headroom: RingBuf<*mut BlockInfo>,
    current_block: Option<BlockTuple>,
    overflow_block: Option<BlockTuple>,
    current_live_mark: bool,
}

impl LineAllocator {
    pub fn new(block_allocator: BlockAllocator) -> LineAllocator {
        return LineAllocator {
            block_allocator: block_allocator,
            object_map: HashSet::new(),
            object_map_backup: HashSet::new(),
            mark_histogram: VecMap::with_capacity(NUM_LINES_PER_BLOCK),
            unavailable_blocks: RingBuf::new(),
            recyclable_blocks: RingBuf::new(),
            evac_headroom: RingBuf::new(),
            current_block: None,
            overflow_block: None,
            current_live_mark: false,
        };
    }

    pub fn set_gc_object(&mut self, object: GCObjectRef) {
        self.object_map.insert(object);
    }

    pub fn unset_gc_object(&mut self, object: GCObjectRef) {
        self.object_map.remove(&object);
    }

    pub fn is_gc_object(&self, object: GCObjectRef) -> bool {
        return self.object_map.contains(&object);
    }

    pub fn current_live_mark(&self) -> bool {
        return self.current_live_mark;
    }

    pub fn decrement_lines(&mut self, object: GCObjectRef) {
        unsafe{ (*self.get_block_ptr(object)).decrement_lines(object); }
    }

    pub fn increment_lines(&mut self, object: GCObjectRef) {
        unsafe{ (*self.get_block_ptr(object)).increment_lines(object); }
    }

    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        let size = unsafe{ (*rtti).object_size() };
        debug!("Request to allocate an object of size {}", size);
        if let Some(object) = self.raw_allocate(size) {
            unsafe { ptr::write(object, GCObject::new(rtti, self.current_live_mark)); }
            return Some(object);
        }
        return None;
    }

    pub fn prepare_collection(&mut self) -> bool {
        self.unavailable_blocks.extend(self.recyclable_blocks.drain());
        self.unavailable_blocks.extend(self.current_block.take()
                                           .map(|b| b.0).into_iter());

        let perform_cycle_collection = true;
        return perform_cycle_collection;
    }

    pub fn complete_collection(&mut self) {
        self.mark_histogram.clear();
        self.perform_defrag = false;
        self.sweep_unavailable_blocks();
    }

    pub fn prepare_immix_collection(&mut self) {
        for block in self.unavailable_blocks.iter_mut() {
            unsafe{ (**block).clear_line_counts(); }
        }

        if cfg!(feature = "valgrind") {
            self.object_map_backup = self.object_map.clone();
        }
        self.object_map.clear();
    }

    pub fn complete_immix_collection(&mut self) {
        self.current_live_mark = !self.current_live_mark;
        if cfg!(feature = "valgrind") {
            for &object in self.object_map_backup.difference(&self.object_map) {
                valgrind_freelike!(object);
            }
            self.object_map_backup.clear();
        }
    }
}

impl LineAllocator {
    unsafe fn get_block_ptr(&mut self, object: GCObjectRef) -> *mut BlockInfo {
        let block_offset = object as uint % BLOCK_SIZE;
        return mem::transmute((object as *mut u8).offset(-(block_offset as int)));
    }

    fn raw_allocate(&mut self, size: uint) -> Option<GCObjectRef> {
        return if size < LINE_SIZE {
            self.current_block.take()
                              .and_then(|tp| self.scan_for_hole(size, tp))
        } else {
            self.overflow_block.take()
                               .and_then(|tp| self.scan_for_hole(size, tp))
                               .or_else(|| self.get_new_block())
        }.or_else(|| self.scan_recyclables(size))
         .or_else(|| self.get_new_block())
         .map(|tp| self.allocate_from_block(size, tp))
         .map(|(tp, object)| {
             if size < LINE_SIZE { self.current_block = Some(tp);
             } else { self.overflow_block = Some(tp); }
             valgrind_malloclike!(object, size);
             self.set_gc_object(object);
             object
         });
    }

    fn scan_for_hole(&mut self, size: uint, block_tuple: BlockTuple)
        -> Option<BlockTuple> {
            let (block, low, high) = block_tuple;
            return match (high - low) as uint >= size {
                true => {
                    debug!("Found hole in block {:p}", block);
                    Some(block_tuple)
                },
                false => match unsafe{ (*block).scan_block(high) } {
                    None => {
                        debug!("Push block {:p} into unavailable_blocks", block);
                        self.unavailable_blocks.push_back(block);
                        None
                    },
                    Some((low, high)) =>
                        self.scan_for_hole(size, (block, low, high)),
                }
            };
        }

    fn scan_recyclables(&mut self, size: uint) -> Option<BlockTuple> {
        return match self.recyclable_blocks.pop_front() {
            None => None,
            Some(block) => match unsafe{ (*block).scan_block((LINE_SIZE - 1) as u16) } {
                None => {
                    debug!("Push block {:p} into unavailable_blocks", block);
                    self.unavailable_blocks.push_back(block);
                    self.scan_recyclables(size)
                },
                Some((low, high)) => self.scan_for_hole(size, (block, low, high))
                                         .or_else(|| self.scan_recyclables(size)),
            }
        };
    }

    fn allocate_from_block(&mut self, size: uint, block_tuple: BlockTuple)
        -> (BlockTuple, GCObjectRef) {
            let (block, low, high) = block_tuple;
            let object = unsafe { (*block).offset(low as uint) };
            debug!("Allocated object {} of size {} in {} (object={})",
                   object, size, block, size >= LINE_SIZE);
            return ((block, low + size as u16, high), object);
        }

    fn get_new_block(&mut self) -> Option<BlockTuple> {
        return if self.perform_evac {
            debug!("Request new block in evacuation");
            self.evac_headroom.pop_front()
        } else {
            debug!("Request new block");
            self.block_allocator.get_block()
        }.map(|block| (block, LINE_SIZE as u16, (BLOCK_SIZE - 1) as u16));
    }

    fn sweep_unavailable_blocks(&mut self) {
        let mut unavailable_blocks = RingBuf::new();
        for block in self.unavailable_blocks.drain() {
            if unsafe{ (*block).is_empty() } {
                // XXX We should not use a constant here, but something that
                // XXX changes dynamically (see rcimmix: MAX heuristic).
                if self.evac_headroom.len() < EVAC_HEADROOM {
                    debug!("Buffer free block {:p} for evacuation", block);
                    unsafe{ (*block).reset() ;}
                    self.evac_headroom.push_back(block);
                } else {
                    debug!("Return block {:p} to global block allocator", block);
                    self.block_allocator.return_block(block);
                }
            } else {
                unsafe{ (*block).count_holes(); }
                let (holes, marked_lines) = unsafe{ (*block).count_holes_and_marked_lines() };
                if self.mark_histogram.contains_key(&(holes as uint)) {
                    if let Some(val) = self.mark_histogram.get_mut(&(holes as uint)) {
                        *val += marked_lines;
                    }
                } else { self.mark_histogram.insert(holes as uint, marked_lines); }
                debug!("Found {} holes and {} marked lines in block {}",
                       holes, marked_lines, block);
                match holes {
                    0 => {
                        debug!("Push block {:p} into unavailable_blocks", block);
                        unavailable_blocks.push_back(block);
                    },
                    _ => {
                        debug!("Push block {:p} into recyclable_blocks", block);
                        self.recyclable_blocks.push_back(block);
                    }
                }
            }
        }
        self.unavailable_blocks.extend(unavailable_blocks.into_iter());
    }

    fn establish_hole_threshhold(&self) -> u8 {
        let mut available_histogram : VecMap<u8> = VecMap::with_capacity(NUM_LINES_PER_BLOCK);
        for block in self.unavailable_blocks.iter() {
            let (holes, free_lines) = unsafe{ (**block).count_holes_and_available_lines() };
            if available_histogram.contains_key(&(holes as uint)) {
                if let Some(val) = available_histogram.get_mut(&(holes as uint)) {
                    *val += free_lines;
                }
            } else { available_histogram.insert(holes as uint, free_lines); }
        }
        let mut required_lines = 0 as u8;
        let mut available_lines = (self.evac_headroom.len() * (NUM_LINES_PER_BLOCK - 1)) as u8;

        for threshold in range(0, NUM_LINES_PER_BLOCK) {
            required_lines += *self.mark_histogram.get(&threshold).unwrap_or(&0);
            available_lines -= *available_histogram.get(&threshold).unwrap_or(&0);
            if available_lines <= required_lines {
                return threshold as u8;
            }
        }
        return NUM_LINES_PER_BLOCK as u8;
    }
}
<|endoftext|>


<commit_before>use std::fmt;

#[derive(Debug, Clone)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

/*impl fmt::Display for Tree {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "(this: {:#?}, \nleft: {:#?}, \nright: {:#?})",
            self.enter, self.left, self.right
        )
    }
}*/

//for red-black tree
#[derive(Debug, Clone, PartialEq)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug, Clone)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }

    fn new_black(v: &i32) -> Node {
        let mut n = Node::new(v);
        n.make_black();
        n
    }
    fn new_red(v: &i32) -> Node {
        let mut n = Node::new(v);
        n.make_red();
        n
    }
    fn make_black(&mut self) {
        self.color = Color::Black;
    }

    fn make_red(&mut self) {
        self.color = Color::Red;
    }

    fn change_color(&mut self) {
        if self.color == Color::Black {
            self.color = Color::Red
        } else {
            self.color = Color::Black
        }
    }
}

type ReTr<'a> = Result<&'a mut Tree, String>;

impl Tree {
    fn new(v: &i32) -> Tree {
        let mut root = Node::new(v);
        root.make_black();
        Tree {
            enter: root,
            left: None,
            right: None,
        }
    }

    //fix color at ending of insert method
    fn insert(&mut self, v: &i32) {
        if *v == self.enter.val {
            println!("{}", "duplicate value");
            return;
        }

        {
            //need drop target which hold self ownship..
            //we need this ownship to fix color at endding of this method.
            let target = if *v > self.enter.val {
                &mut self.right
            } else {
                &mut self.left
            };

            match target {
                Some(next) => next.insert(v),
                None => {
                    let mut new_node = Node::new(v);
                    new_node.make_red();
                    let new_tree = Tree {
                        enter: new_node,
                        left: None,
                        right: None,
                    };
                    *target = Some(Box::new(new_tree));
                }
            }
        }

        //self.fix(v);
    }

    fn look_up_recursive(&mut self, v: &i32) -> ReTr {
        if *v == self.enter.val {
            return Ok(self);
        } else if *v > self.enter.val {
            if let Some(_) = self.right {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        } else {
            if let Some(_) = self.left {
                let next = self.left.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        }
    }

    fn look_up(&mut self, v: &i32) -> ReTr {
        let mut this: &mut Self = self;
        loop {
            if *v == this.enter.val {
                return Ok(this);
            } else if *v > this.enter.val {
                if let None = this.right {
                    return Err("not find".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return Err("not find".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    fn look_up_father(&mut self, v: &i32) -> (ReTr, String) {
        let mut this: &mut Self = self;
        loop {
            if *v == this.enter.val {
                return (Err("no father".to_string()), "this".to_string());
            } else if *v == this.right.as_ref().unwrap().enter.val {
                return (Ok(this), "right".to_string());
            } else if *v == this.left.as_ref().unwrap().enter.val {
                return (Ok(this), "left".to_string());
            } else if *v > this.enter.val {
                if let None = this.right {
                    return (Err("not find".to_string()), "Error".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return (Err("not find".to_string()), "Error".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    fn cut_left_tree(&self) -> Option<Box<Self>> {
        self.left.clone()
    }

    fn cut_right_tree(&self) -> Option<Box<Self>> {
        self.right.clone()
    }

    fn left_shift(&mut self, v: &i32) {
        match self.look_up_father(v).0 {
            Ok(r) => {
                let father = r;
                let mut this = father.cut_left_tree().unwrap();
                let mut son = this.cut_right_tree().unwrap();
                let grand_son = son.cut_left_tree().unwrap();

                this.right = Some(grand_son);
                son.left = Some(this);
                father.left = Some(son);
                return;
            }
            _ => (),
        }

        let left = self.cut_left_tree().unwrap();
        let mut new_left = Tree::new(&self.enter.val);
        new_left.left = Some(left);

        let right = self.cut_right_tree().unwrap();
        let right_left = right.cut_left_tree().unwrap();
        let right_right = right.cut_right_tree().unwrap();
        new_left.right = Some(right_left);

        self.enter = Node::new_black(&right.enter.val);

        self.right = Some(right_right);

        self.left = Some(Box::new(new_left));
    }

    fn right_shift(&mut self, v: &i32) {
        match self.look_up_father(v).0 {
            Ok(r) => {
                let father = r;
                let mut this = father.cut_right_tree().unwrap();
                let mut son = this.cut_left_tree().unwrap();
                let grand_son = son.cut_right_tree().unwrap();

                this.left = Some(grand_son);
                son.right = Some(this);
                father.right = Some(son);
                return;
            }
            _ => (),
        }

        let right = self.cut_right_tree().unwrap();
        let left = self.cut_left_tree().unwrap();
        let left_left = left.cut_left_tree().unwrap();
        let left_right = left.cut_left_tree().unwrap();

        let mut new_right = Tree::new(&self.enter.val);
        new_right.left = Some(left_right);
        new_right.right = Some(right);

        self.enter = Node::new_black(&left.enter.val);
        self.left = Some(left_left);
        self.right = Some(Box::new(new_right));
    }
}

fn main() {
    //let mut a = Tree::new(&3);
    //a.insert(&2);
    //a.insert(&1);
    //a.insert(&4);
    //a.insert(&5);

    //println!("{:?}", a);
    //println!("{:?}", a.look_up(&1));
    //println!("{:?}", a.look_up_father(&4));
    //println!("{:?}", a);

    let mut b = Tree::new(&10);
    b.insert(&2);
    b.insert(&1);
    b.insert(&5);
    b.insert(&3);
    b.insert(&6);
    b.insert(&11);

    //println!("{:?}", b);
    //println!("{:?}", b.look_up_father(&2));
    let mut c = b.cut_left_tree().unwrap();
    //println!("{:#?}", c);
    c.left_shift(&2);
    println!("{:#?}", c);

    //let mut c = Tree::new(&2);
    //c.insert(&8);
    //c.insert(&1);
    //c.insert(&5);
    //c.insert(&4);
    //c.insert(&7);
    //c.insert(&9);
    //println!("{:?}", c.look_up_father(&8));
    //c.right_shift(&8);
    //println!("{:#?}", c);
}
<commit_msg>finish look up family<commit_after>use std::fmt;

#[derive(Debug, Clone)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

/*impl fmt::Display for Tree {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "(this: {:#?}, \nleft: {:#?}, \nright: {:#?})",
            self.enter, self.left, self.right
        )
    }
}*/

//for red-black tree
#[derive(Debug, Clone, PartialEq)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug, Clone)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }

    fn new_black(v: &i32) -> Node {
        let mut n = Node::new(v);
        n.make_black();
        n
    }
    fn new_red(v: &i32) -> Node {
        let mut n = Node::new(v);
        n.make_red();
        n
    }
    fn make_black(&mut self) {
        self.color = Color::Black;
    }

    fn make_red(&mut self) {
        self.color = Color::Red;
    }

    fn change_color(&mut self) {
        if self.color == Color::Black {
            self.color = Color::Red
        } else {
            self.color = Color::Black
        }
    }
}

type ReTr<'a> = Result<&'a mut Tree, String>;

impl Tree {
    fn new(v: &i32) -> Tree {
        let mut root = Node::new(v);
        root.make_black();
        Tree {
            enter: root,
            left: None,
            right: None,
        }
    }

    //fix color at ending of insert method
    fn insert(&mut self, v: &i32) {
        if *v == self.enter.val {
            println!("{}", "duplicate value");
            return;
        }

        {
            //need drop target which hold self ownship..
            //we need this ownship to fix color at endding of this method.
            let target = if *v > self.enter.val {
                &mut self.right
            } else {
                &mut self.left
            };

            match target {
                Some(next) => next.insert(v),
                None => {
                    let mut new_node = Node::new(v);
                    new_node.make_red();
                    let new_tree = Tree {
                        enter: new_node,
                        left: None,
                        right: None,
                    };
                    *target = Some(Box::new(new_tree));
                }
            }
        }

        //self.fix(v);
    }

    fn look_up_recursive(&mut self, v: &i32) -> ReTr {
        if *v == self.enter.val {
            return Ok(self);
        } else if *v > self.enter.val {
            if let Some(_) = self.right {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        } else {
            if let Some(_) = self.left {
                let next = self.left.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        }
    }

    fn look_up(&mut self, v: &i32) -> ReTr {
        let mut this: &mut Self = self;
        loop {
            if *v == this.enter.val {
                return Ok(this);
            } else if *v > this.enter.val {
                if let None = this.right {
                    return Err("not find".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return Err("not find".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    fn look_up_father(&mut self, v: &i32) -> (ReTr, &'static str) {
        let mut this: &mut Self = self;
        loop {
            if *v == this.enter.val {
                return (Err("no father".to_string()), "this");
            } else if *v == this.right.as_ref().unwrap().enter.val {
                return (Ok(this), "right");
            } else if *v == this.left.as_ref().unwrap().enter.val {
                return (Ok(this), "left");
            } else if *v > this.enter.val {
                if let None = this.right {
                    return (Err("not find".to_string()), "Error");
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return (Err("not find".to_string()), "Error");
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }

    //find father, grandfather, and uncle
    fn look_up_family(
        &mut self,
        v: &i32,
    ) -> (
        Result<i32, &'static str>,
        Result<i32, &'static str>,
        Result<i32, &'static str>,
    ) {
        let this: &mut Self = self;
        let grandfather: i32;
        let father: i32;

        match this.look_up_father(v).0 {
            Ok(n) => {
                father = n.enter.val;
            }
            Err(_) => {
                return (
                    Err("father not find"),
                    Err("grandfather not find"),
                    Err("uncle not find"),
                )
            }
        }

        let uncle_option: &Option<Box<Tree>>;
        match this.look_up_father(&father) {
            (Ok(n), s) => {
                grandfather = n.enter.val;
                match s {
                    "left" => uncle_option = &n.right,
                    _ => uncle_option = &n.left,
                };
            }
            (Err(_), _) => {
                return (
                    Ok(father),
                    Err("grandfather not find"),
                    Err("uncle not find"),
                )
            }
        }

        match uncle_option {
            Some(un) => return (Ok(father), Ok(grandfather), Ok(un.enter.val)),
            _ => return (Ok(father), Ok(grandfather), Err("uncle not find")),
        }
    }

    fn cut_left_tree(&self) -> Option<Box<Self>> {
        self.left.clone()
    }

    fn cut_right_tree(&self) -> Option<Box<Self>> {
        self.right.clone()
    }

    fn left_shift(&mut self, v: &i32) {
        match self.look_up_father(v).0 {
            Ok(r) => {
                let father = r;
                let mut this = father.cut_left_tree().unwrap();
                let mut son = this.cut_right_tree().unwrap();
                let grand_son = son.cut_left_tree().unwrap();

                this.right = Some(grand_son);
                son.left = Some(this);
                father.left = Some(son);
                return;
            }
            _ => (),
        }

        let left = self.cut_left_tree().unwrap();
        let mut new_left = Tree::new(&self.enter.val);
        new_left.left = Some(left);

        let right = self.cut_right_tree().unwrap();
        let right_left = right.cut_left_tree().unwrap();
        let right_right = right.cut_right_tree().unwrap();
        new_left.right = Some(right_left);

        self.enter = Node::new_black(&right.enter.val);

        self.right = Some(right_right);

        self.left = Some(Box::new(new_left));
    }

    fn right_shift(&mut self, v: &i32) {
        match self.look_up_father(v).0 {
            Ok(r) => {
                let father = r;
                let mut this = father.cut_right_tree().unwrap();
                let mut son = this.cut_left_tree().unwrap();
                let grand_son = son.cut_right_tree().unwrap();

                this.left = Some(grand_son);
                son.right = Some(this);
                father.right = Some(son);
                return;
            }
            _ => (),
        }

        let right = self.cut_right_tree().unwrap();
        let left = self.cut_left_tree().unwrap();
        let left_left = left.cut_left_tree().unwrap();
        let left_right = left.cut_left_tree().unwrap();

        let mut new_right = Tree::new(&self.enter.val);
        new_right.left = Some(left_right);
        new_right.right = Some(right);

        self.enter = Node::new_black(&left.enter.val);
        self.left = Some(left_left);
        self.right = Some(Box::new(new_right));
    }
}

fn main() {
    //let mut a = Tree::new(&3);
    //a.insert(&2);
    //a.insert(&1);
    //a.insert(&4);
    //a.insert(&5);

    //println!("{:?}", a);
    //println!("{:?}", a.look_up(&1));
    //println!("{:?}", a.look_up_father(&4));
    //println!("{:?}", a);

    let mut b = Tree::new(&10);
    b.insert(&2);
    b.insert(&1);
    b.insert(&5);
    b.insert(&3);
    b.insert(&6);
    b.insert(&11);

    //println!("{:?}", b);
    //println!("{:?}", b.look_up_father(&2));
    let mut c = b.cut_left_tree().unwrap();
    //println!("{:#?}", c);
    c.left_shift(&2);
    println!("{:#?}", c);

    //let mut c = Tree::new(&2);
    //c.insert(&8);
    //c.insert(&1);
    //c.insert(&5);
    //c.insert(&4);
    //c.insert(&7);
    //c.insert(&9);
    //println!("{:?}", c.look_up_father(&8));
    //c.right_shift(&8);
    //println!("{:#?}", c);
}
<|endoftext|>