<commit_before>use std::fs::File;
use std::io::{SeekFrom, Seek, Read, Write};
use std::fs::OpenOptions;
use std::fmt;
use num::iter::range_step_inclusive;
use std::cell::RefCell;
use std::io::Error;

extern crate libc;
use self::libc::funcs::posix01::unistd::ftruncate;
use std::os::unix::prelude::AsRawFd;

use super::header::{ Header, read_header };
use super::write_op::WriteOp;
use super::archive_info::{ ArchiveInfo };
use super::metadata::{Metadata, AggregationType};
use whisper::schema::Schema;

use whisper::point;

pub struct WhisperFile<'a> {
    pub path: &'a str,
    pub handle: RefCell<File>,
    pub header: Header
}

impl<'a> fmt::Debug for WhisperFile<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "path:  {:?}, header: {:?}", self.path, self.header)
    }
}

impl<'a> fmt::Display for WhisperFile<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ref metadata = self.header.metadata;

        write!(f,
"whisper file ({path})
  metadata:
    aggregation method: {aggregation_type:?}
    max retention: {max_retention}
    xff: {x_files_factor}
  archives:
{archives:?}
",
        // Arguments
        path = self.path,
        aggregation_type = metadata.aggregation_type,
        max_retention = metadata.max_retention,
        x_files_factor = metadata.x_files_factor,
        archives = self.header.archive_infos )
    }
}

pub fn open(path: &str) -> Result<WhisperFile, Error> {
    let file = try!(OpenOptions::new().read(true).write(true).create(false).open(path));
    let header = try!(read_header(&file));
    let whisper_file = WhisperFile { path: path, header: header, handle: RefCell::new(file) };
    Ok(whisper_file)
}

impl<'a> WhisperFile<'a> {

    pub fn new(path: &str, schema: Schema /* , _: Metadata */) -> Result<WhisperFile, Error> {
        let size_needed = schema.size_on_disk();
        let opened_file = try!(OpenOptions::new().read(true).write(true).create(true).open(path));

        // Allocate the room necessary
        debug!("allocating...");
        {
            let raw_fd = opened_file.as_raw_fd();
            let retval = unsafe {
                // TODO skip to fallocate-like behavior. Will need wrapper for OSX.
                ftruncate(raw_fd, size_needed as i64)
            };
            if retval != 0 {
                return Err(Error::last_os_error());
            }
        }
        debug!("done allocating");

        let metadata = {
            // TODO make agg_t, max_r options from the command line.
            let aggregation_type = AggregationType::Average;
            let x_files_factor = 0.5;
            Metadata {
                aggregation_type: aggregation_type,
                max_retention: schema.max_retention() as u32,
                x_files_factor: x_files_factor,
                archive_count: schema.retention_policies.len() as u32
            }
        };

        // Piggy back on moving file write forward
        metadata.write(&opened_file);

        let initial_archive_offset = schema.header_size_on_disk();
        schema.retention_policies.iter().fold(initial_archive_offset, |offset, &rp| {
            debug!("sup");
            rp.write(&opened_file, offset);
            offset + rp.size_on_disk()
        });

        let new_whisper_file = WhisperFile {
            path: path,
            handle: RefCell::new(opened_file),
            header: Header {
                metadata: metadata,
                archive_infos: vec![]
            }
        };
        Ok(new_whisper_file)
    }

    // TODO: Result<usize> return how many write ops were done
    pub fn write(&mut self, current_time: u64, point: point::Point) {

        match self.split(current_time, point.timestamp) {
            Some( (high_precision_archive, rest) ) => {
                let base_point = self.read_point(high_precision_archive.offset);
                let base_timestamp = base_point.timestamp;

                self.write_archives(
                    (high_precision_archive, rest),
                    point,
                    base_timestamp
                );
            },
            None => {
                panic!("no archives satisfy current time")
            }
        }

    }

    fn perform_write_op(&self, write_op: &WriteOp) {
        let mut handle = self.handle.borrow_mut();
        handle.seek(write_op.seek).unwrap();
        handle.write_all(&(write_op.bytes)).unwrap();
    }

    fn read_point(&self, offset: u64) -> point::Point {
        let mut file = self.handle.borrow_mut();
        file.seek(SeekFrom::Start(offset)).unwrap();

        let mut points_buf : [u8; 12] = [0; 12];
        let mut buf_ref : &mut [u8] = &mut points_buf;
        file.read(buf_ref).unwrap();

        point::buf_to_point(buf_ref)
    }

    pub fn write_archives(&self, (ai,rest): (&ArchiveInfo, Vec<&ArchiveInfo>), point: point::Point, base_timestamp: u64) {
        {
            let write_op = build_write_op( ai, &point, base_timestamp );
            self.perform_write_op(&write_op);
        }

        if rest.len() > 1 {
            self.downsample(ai, rest[0], point.timestamp).map(|write_op| self.perform_write_op(&write_op) );

            let high_res_iter = rest[0..rest.len()-1].into_iter();
            let low_res_iter = rest[1..].into_iter();
            let _ : Vec<()> = high_res_iter.
                zip(low_res_iter).
                take_while(|&(h,l)| {
                    match self.downsample(h, l, point.timestamp) {
                        Some(write_op) => {
                            self.perform_write_op(&write_op);
                            true
                        },
                        None => false
                    }
                }).
                map(|_| ()).
                collect();
        }
    }

    // The most expensive IO functionality
    // Reads many samples from high-res archive and
    // aggregates to lower-res archive. Schemas could do well to avoid
    // aggregation unless disk space is truly at a premium.
    //
    // A cache for each archive would do well here. `memmap` would be awesomesauce.
    fn downsample(&self, h_res_archive: &ArchiveInfo, l_res_archive: &ArchiveInfo, base_timestamp: u64) -> Option<WriteOp> {
        assert!(h_res_archive.seconds_per_point < l_res_archive.seconds_per_point);

        let l_interval_start = l_res_archive.interval_ceiling(base_timestamp);
        // debug!("base_timestamp: {}, l_interval_start: {}", base_timestamp, l_interval_start);

        let h_base_timestamp = self.read_point(h_res_archive.offset).timestamp;
        let h_res_start_offset : u64 = if h_base_timestamp == 0 {
            h_res_archive.offset
        } else {
            // TODO: this can be negative. Does that change timestamp understanding?
            let timespan  = l_interval_start as i64 - h_base_timestamp as i64;
            // debug!("timespan {}", timespan);
            let points = timespan / h_res_archive.seconds_per_point as i64;
            // debug!("points {}", points);
            let bytes = points * point::POINT_SIZE as i64;

            // TODO: OMG, move this craziness somewhere else
            let wrapped_index = {
                let remainder = bytes % h_res_archive.size_in_bytes as i64;
                if remainder < 0 {
                    h_res_archive.size_in_bytes as i64 + remainder
                } else {
                    remainder
                }
            };
            // debug!("offset: {}, wrapped_index: {}, bytes: {}, points: {}", h_res_archive.offset, wrapped_index, bytes, points);
            (h_res_archive.offset as i64 + wrapped_index) as u64
        };

        let h_res_points_needed = l_res_archive.seconds_per_point / h_res_archive.seconds_per_point;
        let h_res_bytes_needed = h_res_points_needed * point::POINT_SIZE as u64;

        let h_res_end_offset = {
            let rel_first_offset = h_res_start_offset - h_res_archive.offset;
            let rel_second_offset = (rel_first_offset + h_res_bytes_needed) % h_res_archive.size_in_bytes;
            h_res_archive.offset + rel_second_offset
        };

        let mut h_res_read_buf : Vec<u8> = Vec::with_capacity(h_res_bytes_needed as usize);

        // Subroutine for filling in the buffer
        {
            let mut handle = self.handle.borrow_mut();

            // TODO: must be a better way of zeroing out a buffer to fill in the vector
            for _ in 0..h_res_bytes_needed {
                h_res_read_buf.push(0);
            }

            // TODO: refactor in to function which
            // returns ((Seek,BytesRead),Option<(Seek,BytesRead)>)
            // so this code can be refactored and unit tested...
            if h_res_start_offset < h_res_end_offset {
                // No wrap situation
                let seek = SeekFrom::Start(h_res_start_offset);

                let mut read_buf : &mut [u8] = &mut h_res_read_buf[..];
                handle.seek(seek).unwrap();
                // debug!("READ FROM {} to {} (contiguous read)", h_res_start_offset, h_res_start_offset + read_buf.len() as u64);
                handle.read(read_buf).unwrap();
            } else {
                let high_res_abs_end = h_res_archive.offset + h_res_archive.size_in_bytes;
                let first_seek = SeekFrom::Start(h_res_start_offset);
                let first_seek_bytes = high_res_abs_end - h_res_start_offset;

                // debug!("READ FROM {} to {} (wrap-around read 1)", h_res_start_offset, h_res_start_offset+first_seek_bytes);

                let (first_buf, second_buf) = h_res_read_buf.split_at_mut(first_seek_bytes as usize);

                handle.seek(first_seek).unwrap();
                handle.read(first_buf).unwrap();

                let second_seek = SeekFrom::Start(h_res_archive.offset);
                // debug!("READ FROM {} to {} (wrap-around read 2)", h_res_archive.offset, h_res_archive.offset + second_buf.len() as u64);

                handle.seek(second_seek).unwrap();
                handle.read(second_buf).unwrap();
            }

        }

        let low_res_aggregate = {
            let points : Vec<point::Point> = h_res_read_buf.chunks(point::POINT_SIZE).map(|chunk| {
                point::buf_to_point(chunk)

            }).collect();

            let timestamp_start = l_interval_start;
            let timestamp_stop = l_interval_start + (h_res_points_needed as u64)*h_res_archive.seconds_per_point;
            let step = h_res_archive.seconds_per_point;

            let expected_timestamps = range_step_inclusive(timestamp_start, timestamp_stop, step);
            let valid_points : Vec<&point::Point> = expected_timestamps.
                zip(points.iter()).
                map(|(ts, p)| {
                    if p.timestamp == ts {
                        // debug!("comparing {} and {}/{} (MATCH!)", ts, p.timestamp, p.value);
                        Some(p)
                    } else {
                        // debug!("comparing {} and {}/{}", ts, p.timestamp, p.value);
                        None
                    }
                }).filter(|agg| !agg.is_none()).map(|agg| agg.unwrap()).collect();
            self.aggregate_samples(valid_points, h_res_points_needed)
        };

        low_res_aggregate.map(|aggregate| {
            let l_res_base_point = self.read_point(l_res_archive.offset);
            let l_res_point = point::Point{ timestamp: l_interval_start, value: aggregate };
            build_write_op(l_res_archive, &l_res_point, l_res_base_point.timestamp)
        })
    }

    fn aggregate_samples(&self, points: Vec<&point::Point>, points_possible: u64) -> Option<f64>{
        // debug!("points: {:?}", points);
        let valid_points : Vec<&&point::Point> = points.iter().filter(|p| p.timestamp != 0).map(|p| p).collect();

        let ratio : f32 = valid_points.len() as f32 / points_possible as f32;
        // debug!("valid_points: {}, len: {}, ratio {} vs xff {}", valid_points.len(), points.len(), ratio, self.header.metadata.x_files_factor);
        if ratio < self.header.metadata.x_files_factor {
            // debug!("not enough data to propagate");
            return None;
        }

        // TODO: we only do aggregation right now!
        match self.header.metadata.aggregation_type {
            AggregationType::Average => {
                let sum = points.iter().map(|p| p.value).fold(0.0, |l, r| l + r);
                Some(sum / points.len() as f64)
            },
            _ => { Some(0.0) }
        }
    }

    fn split(&self, current_time: u64, point_timestamp: u64) -> Option<(&ArchiveInfo, Vec<&ArchiveInfo>)>  {
        let mut archive_iter = self.header.archive_infos.iter();

        let high_precision_archive_option = archive_iter.find(|ai|
            ai.retention > (current_time - point_timestamp)
        );

        match high_precision_archive_option {
            Some(ai) => {
                let rest_of_archives = archive_iter;
                let low_res_archives : Vec<&ArchiveInfo> = rest_of_archives.collect();

                Some((ai, low_res_archives))
            },
            None => {
                None
            }
        }
    }
}

fn build_write_op(archive_info: &ArchiveInfo, point: &point::Point, base_timestamp: u64) -> WriteOp {
    let mut output_data = [0; 12];
    let interval_ceiling = archive_info.interval_ceiling(point.timestamp);
    // debug!("interval_ceiling: {}", interval_ceiling);

    {
        let point_value = point.value;
        let buf : &mut [u8] = &mut output_data;
        point::fill_buf(buf, interval_ceiling, point_value);
    }

    let seek_info = archive_info.calculate_seek(&point,  base_timestamp);

    return WriteOp {
        seek: seek_info,
        bytes: output_data
    }
}
<commit_msg>Attractive pretty print<commit_after>use std::fs::File;
use std::io::{SeekFrom, Seek, Read, Write};
use std::fs::OpenOptions;
use std::fmt;
use num::iter::range_step_inclusive;
use std::cell::RefCell;
use std::io::Error;

extern crate libc;
use self::libc::funcs::posix01::unistd::ftruncate;
use std::os::unix::prelude::AsRawFd;

use super::header::{ Header, read_header };
use super::write_op::WriteOp;
use super::archive_info::{ ArchiveInfo };
use super::metadata::{Metadata, AggregationType};
use whisper::schema::Schema;

use whisper::point;

pub struct WhisperFile<'a> {
    pub path: &'a str,
    pub handle: RefCell<File>,
    pub header: Header
}

impl<'a> fmt::Debug for WhisperFile<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "path:  {:?}, header: {:?}", self.path, self.header)
    }
}

impl<'a> fmt::Display for WhisperFile<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let ref metadata = self.header.metadata;
        let ref archive_infos = self.header.archive_infos;

        try!(write!(f, "whisper file ({})\n", self.path));
        try!(write!(f, "  metadata\n"));
        try!(write!(f, "    aggregation method: {:?}\n", metadata.aggregation_type));
        try!(write!(f, "    max retention: {:?}\n", metadata.max_retention));
        try!(write!(f, "    xff: {:?}\n", metadata.x_files_factor));
        let mut index = 0;
        for archive_info in archive_infos.iter() {
        try!(write!(f, "  archive {}\n", index));
        try!(write!(f, "    seconds per point: {}\n", archive_info.seconds_per_point));
        try!(write!(f, "    points: {}\n", archive_info.points));
        try!(write!(f, "    retention: {} (s)\n", archive_info.retention));
        try!(write!(f, "    size: {} (bytes)\n", archive_info.size_in_bytes));

            index = index+1;
        };
        write!(f,"") // make the types happy
    }
}

pub fn open(path: &str) -> Result<WhisperFile, Error> {
    let file = try!(OpenOptions::new().read(true).write(true).create(false).open(path));
    let header = try!(read_header(&file));
    let whisper_file = WhisperFile { path: path, header: header, handle: RefCell::new(file) };
    Ok(whisper_file)
}

impl<'a> WhisperFile<'a> {

    pub fn new(path: &str, schema: Schema /* , _: Metadata */) -> Result<WhisperFile, Error> {
        let size_needed = schema.size_on_disk();
        let opened_file = try!(OpenOptions::new().read(true).write(true).create(true).open(path));

        // Allocate the room necessary
        debug!("allocating...");
        {
            let raw_fd = opened_file.as_raw_fd();
            let retval = unsafe {
                // TODO skip to fallocate-like behavior. Will need wrapper for OSX.
                ftruncate(raw_fd, size_needed as i64)
            };
            if retval != 0 {
                return Err(Error::last_os_error());
            }
        }
        debug!("done allocating");

        let metadata = {
            // TODO make agg_t, max_r options from the command line.
            let aggregation_type = AggregationType::Average;
            let x_files_factor = 0.5;
            Metadata {
                aggregation_type: aggregation_type,
                max_retention: schema.max_retention() as u32,
                x_files_factor: x_files_factor,
                archive_count: schema.retention_policies.len() as u32
            }
        };

        // Piggy back on moving file write forward
        metadata.write(&opened_file);

        let initial_archive_offset = schema.header_size_on_disk();
        schema.retention_policies.iter().fold(initial_archive_offset, |offset, &rp| {
            debug!("sup");
            rp.write(&opened_file, offset);
            offset + rp.size_on_disk()
        });

        let new_whisper_file = WhisperFile {
            path: path,
            handle: RefCell::new(opened_file),
            header: Header {
                metadata: metadata,
                archive_infos: vec![]
            }
        };
        Ok(new_whisper_file)
    }

    // TODO: Result<usize> return how many write ops were done
    pub fn write(&mut self, current_time: u64, point: point::Point) {

        match self.split(current_time, point.timestamp) {
            Some( (high_precision_archive, rest) ) => {
                let base_point = self.read_point(high_precision_archive.offset);
                let base_timestamp = base_point.timestamp;

                self.write_archives(
                    (high_precision_archive, rest),
                    point,
                    base_timestamp
                );
            },
            None => {
                panic!("no archives satisfy current time")
            }
        }

    }

    fn perform_write_op(&self, write_op: &WriteOp) {
        let mut handle = self.handle.borrow_mut();
        handle.seek(write_op.seek).unwrap();
        handle.write_all(&(write_op.bytes)).unwrap();
    }

    fn read_point(&self, offset: u64) -> point::Point {
        let mut file = self.handle.borrow_mut();
        file.seek(SeekFrom::Start(offset)).unwrap();

        let mut points_buf : [u8; 12] = [0; 12];
        let mut buf_ref : &mut [u8] = &mut points_buf;
        file.read(buf_ref).unwrap();

        point::buf_to_point(buf_ref)
    }

    pub fn write_archives(&self, (ai,rest): (&ArchiveInfo, Vec<&ArchiveInfo>), point: point::Point, base_timestamp: u64) {
        {
            let write_op = build_write_op( ai, &point, base_timestamp );
            self.perform_write_op(&write_op);
        }

        if rest.len() > 1 {
            self.downsample(ai, rest[0], point.timestamp).map(|write_op| self.perform_write_op(&write_op) );

            let high_res_iter = rest[0..rest.len()-1].into_iter();
            let low_res_iter = rest[1..].into_iter();
            let _ : Vec<()> = high_res_iter.
                zip(low_res_iter).
                take_while(|&(h,l)| {
                    match self.downsample(h, l, point.timestamp) {
                        Some(write_op) => {
                            self.perform_write_op(&write_op);
                            true
                        },
                        None => false
                    }
                }).
                map(|_| ()).
                collect();
        }
    }

    // The most expensive IO functionality
    // Reads many samples from high-res archive and
    // aggregates to lower-res archive. Schemas could do well to avoid
    // aggregation unless disk space is truly at a premium.
    //
    // A cache for each archive would do well here. `memmap` would be awesomesauce.
    fn downsample(&self, h_res_archive: &ArchiveInfo, l_res_archive: &ArchiveInfo, base_timestamp: u64) -> Option<WriteOp> {
        assert!(h_res_archive.seconds_per_point < l_res_archive.seconds_per_point);

        let l_interval_start = l_res_archive.interval_ceiling(base_timestamp);
        // debug!("base_timestamp: {}, l_interval_start: {}", base_timestamp, l_interval_start);

        let h_base_timestamp = self.read_point(h_res_archive.offset).timestamp;
        let h_res_start_offset : u64 = if h_base_timestamp == 0 {
            h_res_archive.offset
        } else {
            // TODO: this can be negative. Does that change timestamp understanding?
            let timespan  = l_interval_start as i64 - h_base_timestamp as i64;
            // debug!("timespan {}", timespan);
            let points = timespan / h_res_archive.seconds_per_point as i64;
            // debug!("points {}", points);
            let bytes = points * point::POINT_SIZE as i64;

            // TODO: OMG, move this craziness somewhere else
            let wrapped_index = {
                let remainder = bytes % h_res_archive.size_in_bytes as i64;
                if remainder < 0 {
                    h_res_archive.size_in_bytes as i64 + remainder
                } else {
                    remainder
                }
            };
            // debug!("offset: {}, wrapped_index: {}, bytes: {}, points: {}", h_res_archive.offset, wrapped_index, bytes, points);
            (h_res_archive.offset as i64 + wrapped_index) as u64
        };

        let h_res_points_needed = l_res_archive.seconds_per_point / h_res_archive.seconds_per_point;
        let h_res_bytes_needed = h_res_points_needed * point::POINT_SIZE as u64;

        let h_res_end_offset = {
            let rel_first_offset = h_res_start_offset - h_res_archive.offset;
            let rel_second_offset = (rel_first_offset + h_res_bytes_needed) % h_res_archive.size_in_bytes;
            h_res_archive.offset + rel_second_offset
        };

        let mut h_res_read_buf : Vec<u8> = Vec::with_capacity(h_res_bytes_needed as usize);

        // Subroutine for filling in the buffer
        {
            let mut handle = self.handle.borrow_mut();

            // TODO: must be a better way of zeroing out a buffer to fill in the vector
            for _ in 0..h_res_bytes_needed {
                h_res_read_buf.push(0);
            }

            // TODO: refactor in to function which
            // returns ((Seek,BytesRead),Option<(Seek,BytesRead)>)
            // so this code can be refactored and unit tested...
            if h_res_start_offset < h_res_end_offset {
                // No wrap situation
                let seek = SeekFrom::Start(h_res_start_offset);

                let mut read_buf : &mut [u8] = &mut h_res_read_buf[..];
                handle.seek(seek).unwrap();
                // debug!("READ FROM {} to {} (contiguous read)", h_res_start_offset, h_res_start_offset + read_buf.len() as u64);
                handle.read(read_buf).unwrap();
            } else {
                let high_res_abs_end = h_res_archive.offset + h_res_archive.size_in_bytes;
                let first_seek = SeekFrom::Start(h_res_start_offset);
                let first_seek_bytes = high_res_abs_end - h_res_start_offset;

                // debug!("READ FROM {} to {} (wrap-around read 1)", h_res_start_offset, h_res_start_offset+first_seek_bytes);

                let (first_buf, second_buf) = h_res_read_buf.split_at_mut(first_seek_bytes as usize);

                handle.seek(first_seek).unwrap();
                handle.read(first_buf).unwrap();

                let second_seek = SeekFrom::Start(h_res_archive.offset);
                // debug!("READ FROM {} to {} (wrap-around read 2)", h_res_archive.offset, h_res_archive.offset + second_buf.len() as u64);

                handle.seek(second_seek).unwrap();
                handle.read(second_buf).unwrap();
            }

        }

        let low_res_aggregate = {
            let points : Vec<point::Point> = h_res_read_buf.chunks(point::POINT_SIZE).map(|chunk| {
                point::buf_to_point(chunk)

            }).collect();

            let timestamp_start = l_interval_start;
            let timestamp_stop = l_interval_start + (h_res_points_needed as u64)*h_res_archive.seconds_per_point;
            let step = h_res_archive.seconds_per_point;

            let expected_timestamps = range_step_inclusive(timestamp_start, timestamp_stop, step);
            let valid_points : Vec<&point::Point> = expected_timestamps.
                zip(points.iter()).
                map(|(ts, p)| {
                    if p.timestamp == ts {
                        // debug!("comparing {} and {}/{} (MATCH!)", ts, p.timestamp, p.value);
                        Some(p)
                    } else {
                        // debug!("comparing {} and {}/{}", ts, p.timestamp, p.value);
                        None
                    }
                }).filter(|agg| !agg.is_none()).map(|agg| agg.unwrap()).collect();
            self.aggregate_samples(valid_points, h_res_points_needed)
        };

        low_res_aggregate.map(|aggregate| {
            let l_res_base_point = self.read_point(l_res_archive.offset);
            let l_res_point = point::Point{ timestamp: l_interval_start, value: aggregate };
            build_write_op(l_res_archive, &l_res_point, l_res_base_point.timestamp)
        })
    }

    fn aggregate_samples(&self, points: Vec<&point::Point>, points_possible: u64) -> Option<f64>{
        // debug!("points: {:?}", points);
        let valid_points : Vec<&&point::Point> = points.iter().filter(|p| p.timestamp != 0).map(|p| p).collect();

        let ratio : f32 = valid_points.len() as f32 / points_possible as f32;
        // debug!("valid_points: {}, len: {}, ratio {} vs xff {}", valid_points.len(), points.len(), ratio, self.header.metadata.x_files_factor);
        if ratio < self.header.metadata.x_files_factor {
            // debug!("not enough data to propagate");
            return None;
        }

        // TODO: we only do aggregation right now!
        match self.header.metadata.aggregation_type {
            AggregationType::Average => {
                let sum = points.iter().map(|p| p.value).fold(0.0, |l, r| l + r);
                Some(sum / points.len() as f64)
            },
            _ => { Some(0.0) }
        }
    }

    fn split(&self, current_time: u64, point_timestamp: u64) -> Option<(&ArchiveInfo, Vec<&ArchiveInfo>)>  {
        let mut archive_iter = self.header.archive_infos.iter();

        let high_precision_archive_option = archive_iter.find(|ai|
            ai.retention > (current_time - point_timestamp)
        );

        match high_precision_archive_option {
            Some(ai) => {
                let rest_of_archives = archive_iter;
                let low_res_archives : Vec<&ArchiveInfo> = rest_of_archives.collect();

                Some((ai, low_res_archives))
            },
            None => {
                None
            }
        }
    }
}

fn build_write_op(archive_info: &ArchiveInfo, point: &point::Point, base_timestamp: u64) -> WriteOp {
    let mut output_data = [0; 12];
    let interval_ceiling = archive_info.interval_ceiling(point.timestamp);
    // debug!("interval_ceiling: {}", interval_ceiling);

    {
        let point_value = point.value;
        let buf : &mut [u8] = &mut output_data;
        point::fill_buf(buf, interval_ceiling, point_value);
    }

    let seek_info = archive_info.calculate_seek(&point,  base_timestamp);

    return WriteOp {
        seek: seek_info,
        bytes: output_data
    }
}
<|endoftext|>


<commit_before>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.1

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use std::comm::*;

use std::rt::io::net::tcp::TcpStream;

static PORT: int = 4414;
//static IPV4_LOOPBACK: &'static str = "127.0.0.1";

static IPV4_LOOPBACK: &'static str = "0.0.0.0";  // @@@@@

//static mut visitor_count: uint = 0;

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

fn main() {

    // @@@@@@@@@@@@@@@@@@@@@@@@@@

    let ip = match FromStr::from_str(IPV4_LOOPBACK) { Some(ip) => ip,
					   	      None     => {println(fmt!("Error: Invalid IP address <%s>", IPV4_LOOPBACK));
						      		   return;}
 					 	    };

    let visitor_count: uint = 0; // @@@@@@@

    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    // add file requests into queue.
    do spawn {
        while(true) {
            do add_vec.write |vec| {
                let tf:sched_msg = port.recv();
                (*vec).push(tf);
                println("add to queue");
            }
        }
    }

    // take file requests from queue, and send a response.
    do spawn {
        while(true) {
            do take_vec.write |vec| {
                let mut tf = (*vec).pop();

                match io::read_whole_file(tf.filepath) {
                    Ok(file_data) => {
                        tf.stream.write(file_data);
                    }
                    Err(err) => {
                        println(err);
                    }
                }
            }
        }
    }

    //let socket = net::tcp::TcpListener::bind(SocketAddr {ip: Ipv4Addr(127,0,0,1), port: PORT as u16});
    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16}); //@@@@@@@@@@

    println(fmt!("Listening on tcp port %d ...", PORT));
    let mut acceptor = socket.listen().unwrap();

    let shared_count = arc::RWArc::new( visitor_count ); // @@@@@@

    // we can limit the incoming connection count.
    //for stream in acceptor.incoming().take(10 as uint) {

    for stream in acceptor.incoming() {
	let mut stream = stream; // @@@@@@

	match stream {
		Some(ref mut s) =>
		{
			match s.peer_name()
			{	Some(pn) => { println( fmt!("Peer address: %s \n", pn.to_str() ));},
				None => ()
			}
		}
		None => ()
	} 			// @@@@@

	let stream = Cell::new(stream);

	let (count_port, count_chan): (Port< extra::arc::RWArc<uint> >, Chan< extra::arc::RWArc<uint> >) = std::comm::stream(); // @@@@@@
        let count_chan = SharedChan::new(count_chan); // @@@@@@
        count_chan.send(shared_count.clone() ); // @@@@@@

        // Start a new task to handle the connection
        let child_chan = chan.clone();

        do spawn {

            // unsafe {visitor_count += 1;}

	    let shared_count_copy = count_port.recv(); // @@@@@@

	    /* Get Write Access */
	    do shared_count_copy.write |count|{
			*count = *count + 1;
			println( fmt!("count: %? \n", *count as int) );
    	    }

            let mut stream = stream.take();

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));

                if !os::path_exists(file_path) || os::path_is_dir(file_path)
		{
                    println(fmt!("Request received:\n%s", request_str));

		    /*
                    let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			<doctype !html>
			<title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			\r\n", unsafe{visitor_count});
		     */

		    /* Get Read Access */
		    do shared_count_copy.read |count|
		    {
   			let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			<doctype !html>
			<title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			\r\n", *count);

			stream.write(response.as_bytes());
    	    	    }

                }
                else {
                    // may do scheduling here

                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    child_chan.send(msg);

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates")
        }
    }
}

<commit_msg>update existing code to work with starting code v0.2, but MAKE SURE you read the comment about adding file requests in queue. Also, deleted commented code<commit_after>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.2

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::arc;
use std::comm::*;

use std::rt::io::net::tcp::TcpStream;

static PORT: int = 4414;
static IP: &'static str = "0.0.0.0";

struct sched_msg {
    stream: Option<std::rt::io::net::tcp::TcpStream>,
    filepath: ~std::path::PosixPath
}

fn main() {

    let visitor_count: uint = 0; // @@@@@@@

    let req_vec: ~[sched_msg] = ~[];
    let shared_req_vec = arc::RWArc::new(req_vec);
    let add_vec = shared_req_vec.clone();
    let take_vec = shared_req_vec.clone();

    let (port, chan) = stream();
    let chan = SharedChan::new(chan);

    /* IMPORTANT NOTE: 	Weilin's new code for this adding file requests ('do spawn' part) is buggy.
			So don't change the code right below !
    */

    // add file requests into queue.
    do spawn {
        while(true) {
            do add_vec.write |vec| {
                let tf:sched_msg = port.recv();
                (*vec).push(tf);
                println("add to queue");
            }
        }
    }

    // take file requests from queue, and send a response.
    // FIFO
    do spawn {
        loop {
            do take_vec.write |vec| {
                if ((*vec).len() > 0) {
                    // FILO didn't make sense in service scheduling, so we modify it as FIFO by using shift_opt() rather than pop().
                    let tf_opt: Option<sched_msg> = (*vec).shift_opt();
                    let mut tf = tf_opt.unwrap();
                    println(fmt!("shift from queue, size: %ud", (*vec).len()));

                    match io::read_whole_file(tf.filepath) { // killed if file size is larger than memory size.
                        Ok(file_data) => {
                            println(fmt!("begin serving file [%?]", tf.filepath));
                            // A web server should always reply a HTTP header for any legal HTTP request.
                            tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream; charset=UTF-8\r\n\r\n".as_bytes());
                            tf.stream.write(file_data);
                            println(fmt!("finish file [%?]", tf.filepath));
                        }
                        Err(err) => {
                            println(err);
                        }
                    }
                }
            }
        }
    }

    let ip = match FromStr::from_str(IP) { Some(ip) => ip,
					   None     => {println(fmt!("Error: Invalid IP address <%s>", IP));
						        return;}
 					 };

    let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});

    println(fmt!("Listening on tcp port %d ...", PORT));
    let mut acceptor = socket.listen().unwrap();

    let shared_count = arc::RWArc::new( visitor_count ); // @@@@@@

    // we can limit the incoming connection count.
    //for stream in acceptor.incoming().take(10 as uint) {

    for stream in acceptor.incoming() {
	let mut stream = stream; // @@@@@@

	match stream {
		Some(ref mut s) =>
		{
			match s.peer_name()
			{	Some(pn) => { println( fmt!("\nPeer address: %s", pn.to_str() ));},
				None 	 => ()
			}
		}
		None => ()
	} 			// @@@@@

	let stream = Cell::new(stream);

	let (count_port, count_chan): (Port< extra::arc::RWArc<uint> >, Chan< extra::arc::RWArc<uint> >) = std::comm::stream(); // @@@@@@
        let count_chan = SharedChan::new(count_chan); // @@@@@@
        count_chan.send(shared_count.clone() ); // @@@@@@

        // Start a new task to handle the connection
        let child_chan = chan.clone();

        do spawn {

	    let shared_count_copy = count_port.recv(); // @@@@@@

	    /* Get Write Access */
	    do shared_count_copy.write |count|{
			*count = *count + 1;
			println( fmt!("\ncount: %? \n", *count as int) );
    	    }

            let mut stream = stream.take();

            let mut buf = [0, ..500];
            stream.read(buf);
            let request_str = str::from_utf8(buf);

            let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
            if req_group.len() > 2 {
                let path = req_group[1];
                println(fmt!("Request for path: \n%?", path));

                let file_path = ~os::getcwd().push(path.replace("/../", ""));

                if !os::path_exists(file_path) || os::path_is_dir(file_path)
		{
                    println(fmt!("Request received:\n%s", request_str));

		    /* Get Read Access */
		    do shared_count_copy.read |count|
		    {
   			let response: ~str = fmt!(
                        "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			<doctype !html>
			<title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			\r\n", *count);

			stream.write(response.as_bytes());
    	    	    }

                }
                else {
                    // may do scheduling here

                    let msg: sched_msg = sched_msg{stream: stream, filepath: file_path.clone()};
                    child_chan.send(msg);

                    println(fmt!("get file request: %?", file_path));
                }
            }
            println!("connection terminates\n")
        }
    }
}

<|endoftext|>


<commit_before>use toml::Value;

use libimagerror::into::IntoError;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

use git2::Repository;

pub fn commit_interactive(config: &Value) -> bool {
    match config.lookup("commit.interactive") {
        Some(&Value::Boolean(b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_update.commit.interactive' must be a Boolean.");
            warn!("Defaulting to commit.interactive = false");
            false
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_update.commit.interactive'");
            warn!("Defaulting to false");
            false
        }
    }
}

fn commit_with_editor(config: &Value) -> bool {
    match config.lookup("commit.interactive_editor") {
        Some(&Value::Boolean(b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_update.commit.interactive_editor' must be a Boolean.");
            warn!("Defaulting to commit.interactive_editor = false");
            false
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_update.commit.interactive_editor'");
            warn!("Defaulting to false");
            false
        }
    }
}

fn commit_default_msg<'a>(config: &'a Value) -> &'a str {
    match config.lookup("commit.message") {
        Some(&Value::String(ref b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_update.commit.message' must be a String.");
            warn!("Defaulting to commit.message = 'Update'");
            "Update"
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_update.commit.message'");
            warn!("Defaulting to commit.message = 'Update'");
            "Update"
        }
    }
}

fn commit_template() -> &'static str {
    "Commit template"
}

pub fn commit_message(repo: &Repository, config: &Value, action: StoreAction) -> Result<String> {
    use libimaginteraction::ask::ask_string;
    use libimagutil::edit::edit_in_tmpfile_with_command;
    use std::process::Command;

    if commit_interactive(config) {
        if commit_with_editor(config) {
            repo.config()
                .map_err_into(GHEK::GitConfigFetchError)
                .and_then(|c| c.get_string("core.editor").map_err_into(GHEK::GitConfigEditorFetchError))
                .map_err_into(GHEK::ConfigError)
                .map(Command::new)
                .and_then(|cmd| {
                    let mut s = String::from(commit_template());
                    edit_in_tmpfile_with_command(cmd, &mut s).map(|_| s)
                        .map_err_into(GHEK::EditorError)
                })
        } else {
            Ok(ask_string("Commit Message", None, false, false, None, "> "))
        }
    } else {
        Ok(String::from(commit_default_msg(config)))
    }
}

pub fn abort_on_repo_init_err(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "abort_on_repo_init_failure", true, true)
}

pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

pub fn do_checkout_ensure_branch(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "try_checkout_ensure_branch", true, true)
}

fn get_bool_cfg(cfg: Option<&Value>, name: &str, on_fail: bool, on_unavail: bool) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup(name) {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, '{}' must be a Boolean (true|false).", name);
                warn!("Assuming '{}' now.", on_fail);
                on_fail
            },
            None => {
                debug!("No key '{}' - Assuming '{}'", name, on_unavail);
                on_unavail
            },
        }
    })
    .unwrap_or(on_unavail)
}

<commit_msg>Add documentation for the configuration utilities<commit_after>use toml::Value;

use libimagerror::into::IntoError;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

use git2::Repository;

/// Check the configuration whether we should commit interactively
pub fn commit_interactive(config: &Value) -> bool {
    match config.lookup("commit.interactive") {
        Some(&Value::Boolean(b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_update.commit.interactive' must be a Boolean.");
            warn!("Defaulting to commit.interactive = false");
            false
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_update.commit.interactive'");
            warn!("Defaulting to false");
            false
        }
    }
}

/// Check the configuration whether we should commit with the editor
fn commit_with_editor(config: &Value) -> bool {
    match config.lookup("commit.interactive_editor") {
        Some(&Value::Boolean(b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_update.commit.interactive_editor' must be a Boolean.");
            warn!("Defaulting to commit.interactive_editor = false");
            false
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_update.commit.interactive_editor'");
            warn!("Defaulting to false");
            false
        }
    }
}

/// Get the commit default message
fn commit_default_msg<'a>(config: &'a Value) -> &'a str {
    match config.lookup("commit.message") {
        Some(&Value::String(ref b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_update.commit.message' must be a String.");
            warn!("Defaulting to commit.message = 'Update'");
            "Update"
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_update.commit.message'");
            warn!("Defaulting to commit.message = 'Update'");
            "Update"
        }
    }
}

/// Get the commit template
///
/// TODO: Implement good template string
fn commit_template() -> &'static str {
    "Commit template"
}

/// Generate a commit message
///
/// Uses the functions `commit_interactive()` and `commit_with_editor()`
/// or reads one from the commandline or uses the `commit_default_msg()` string to create a commit
/// message.
pub fn commit_message(repo: &Repository, config: &Value, action: StoreAction) -> Result<String> {
    use libimaginteraction::ask::ask_string;
    use libimagutil::edit::edit_in_tmpfile_with_command;
    use std::process::Command;

    if commit_interactive(config) {
        if commit_with_editor(config) {
            repo.config()
                .map_err_into(GHEK::GitConfigFetchError)
                .and_then(|c| c.get_string("core.editor").map_err_into(GHEK::GitConfigEditorFetchError))
                .map_err_into(GHEK::ConfigError)
                .map(Command::new)
                .and_then(|cmd| {
                    let mut s = String::from(commit_template());
                    edit_in_tmpfile_with_command(cmd, &mut s).map(|_| s)
                        .map_err_into(GHEK::EditorError)
                })
        } else {
            Ok(ask_string("Commit Message", None, false, false, None, "> "))
        }
    } else {
        Ok(String::from(commit_default_msg(config)))
    }
}

/// Check whether the hook should abort if the repository cannot be initialized
pub fn abort_on_repo_init_err(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "abort_on_repo_init_failure", true, true)
}

/// Get the branch which must be checked out before running the hook (if any).
///
/// If there is no configuration for this, this is `Ok(None)`, otherwise we try to find the
/// configuration `String`.
pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

/// Check whether we should check out a branch before committing.
pub fn do_checkout_ensure_branch(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "try_checkout_ensure_branch", true, true)
}

/// Helper to get a boolean value from the configuration.
fn get_bool_cfg(cfg: Option<&Value>, name: &str, on_fail: bool, on_unavail: bool) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup(name) {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, '{}' must be a Boolean (true|false).", name);
                warn!("Assuming '{}' now.", on_fail);
                on_fail
            },
            None => {
                debug!("No key '{}' - Assuming '{}'", name, on_unavail);
                on_unavail
            },
        }
    })
    .unwrap_or(on_unavail)
}

<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;
use git2::{Reference as GitReference, Repository, Error as Git2Error};

use libimagstore::storeid::StoreId;
use libimagstore::hook::Hook;
use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::error::CustomData as HECD;
use libimagstore::hook::result::HookResult;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagerror::trace::trace_error;
use libimagerror::into::IntoError;

use vcs::git::result::Result;
use vcs::git::error::MapErrInto;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::GitHookError as GHE;
use vcs::git::runtime::Runtime;

pub struct CreateHook<'a> {
    storepath: &'a PathBuf,

    runtime: Runtime,

    position: HookPosition,
}

impl<'a> CreateHook<'a> {

    pub fn new(storepath: &'a PathBuf, p: HookPosition) -> CreateHook<'a> {
        CreateHook {
            storepath: storepath,
            runtime: Runtime::new(storepath),
            position: p,
        }
    }

}

impl<'a> Debug for CreateHook<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "CreateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl<'a> Hook for CreateHook<'a> {

    fn name(&self) -> &'static str {
        "stdhook_git_create"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl<'a> HookDataAccessorProvider for CreateHook<'a> {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl<'a> StoreIdAccessor for CreateHook<'a> {

    fn access(&self, id: &StoreId) -> HookResult<()> {
        debug!("[GIT CREATE HOOK]: {:?}", id);
        try!(self
             .runtime
             .ensure_cfg_branch_is_checked_out()
             .map_err(Box::new)
             .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e)));
        let repository = try!(self.runtime.repository());

        // Now to the create() hook action

        unimplemented!()

        Ok(())
    }

}

<commit_msg>Implement CreateHook::access()<commit_after>use std::path::PathBuf;
use std::fmt::{Debug, Formatter, Error as FmtError};
use std::result::Result as RResult;

use toml::Value;
use git2::{Reference as GitReference, Repository, Error as Git2Error};

use libimagstore::storeid::StoreId;
use libimagstore::hook::Hook;
use libimagstore::hook::error::HookError as HE;
use libimagstore::hook::error::HookErrorKind as HEK;
use libimagstore::hook::error::CustomData as HECD;
use libimagstore::hook::result::HookResult;
use libimagstore::hook::position::HookPosition;
use libimagstore::hook::accessor::{HookDataAccessor, HookDataAccessorProvider};
use libimagstore::hook::accessor::StoreIdAccessor;
use libimagerror::trace::trace_error;
use libimagerror::into::IntoError;

use vcs::git::result::Result;
use vcs::git::error::MapErrInto;
use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::GitHookError as GHE;
use vcs::git::runtime::Runtime;

pub struct CreateHook<'a> {
    storepath: &'a PathBuf,

    runtime: Runtime,

    position: HookPosition,
}

impl<'a> CreateHook<'a> {

    pub fn new(storepath: &'a PathBuf, p: HookPosition) -> CreateHook<'a> {
        CreateHook {
            storepath: storepath,
            runtime: Runtime::new(storepath),
            position: p,
        }
    }

}

impl<'a> Debug for CreateHook<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "CreateHook(storepath={:?}, repository={}, pos={:?}, cfg={:?}",
               self.storepath,
               (if self.runtime.has_repository() { "Some(_)" } else { "None" }),
               self.position,
               self.runtime.has_config())
    }
}

impl<'a> Hook for CreateHook<'a> {

    fn name(&self) -> &'static str {
        "stdhook_git_create"
    }

    fn set_config(&mut self, config: &Value) {
        if let Err(e) = self.runtime.set_config(config) {
            trace_error(&e);
        }
    }

}

impl<'a> HookDataAccessorProvider for CreateHook<'a> {

    fn accessor(&self) -> HookDataAccessor {
        HookDataAccessor::StoreIdAccess(self)
    }
}

impl<'a> StoreIdAccessor for CreateHook<'a> {

    fn access(&self, id: &StoreId) -> HookResult<()> {
        use vcs::git::action::StoreAction;
        use vcs::git::config::commit_message;

        debug!("[GIT CREATE HOOK]: {:?}", id);
        try!(self
             .runtime
             .ensure_cfg_branch_is_checked_out()
             .map_err(Box::new)
             .map_err(|e| HEK::HookExecutionError.into_error_with_cause(e)));

        self.runtime
            .config_value_or_err()
            .and_then(|cfg| {
                self.runtime
                    .repository()
                    .map(|r| (r, cfg))
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg)| {
                repo.signature()
                    .map(|s| (repo, cfg, s))
                    .map_err_into(GHEK::RepositorySignatureFetchingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig)| {
                repo.index()
                    .map(|idx| (repo, cfg, sig, idx))
                    .map_err_into(GHEK::RepositoryIndexFetchingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig, mut idx)| {
                idx.add_path(id)
                    .map(|_| (repo, cfg, sig, idx))
                    .map_err_into(GHEK::RepositoryPathAddingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig, mut idx)| {
                idx.write_tree()
                    .map(|oid| (repo, cfg, sig, idx, oid))
                    .map_err_into(GHEK::RepositoryTreeWritingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig, idx, oid)| {
                repo.find_tree(oid)
                    .map(|tree| (repo, cfg, sig, idx, oid, tree))
                    .map_err_into(GHEK::RepositoryTreeFindingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, cfg, sig, idx, oid, tree)| {
                let cmtmsg = commit_message(cfg, StoreAction::Create);
                repo.find_commit(oid)
                    .map(|cmt| (repo, sig, tree, cmt, cmtmsg))
                    .map_err_into(GHEK::RepositoryCommitFindingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .and_then(|(repo, sig, tree, cmt, commitmsg)| {
                repo.commit(Some("HEAD"), &sig, &sig, &commitmsg[..], &tree, &[&cmt])
                    .map_err_into(GHEK::RepositoryCommittingError)
                    .map_err_into(GHEK::RepositoryError)
                    .map_err(|e| e.into())
            })
            .map(|_| ())
    }

}

<|endoftext|>


<commit_before>use level::Level;

use na::Vec2;

use rand::os::OsRng;
use rand::XorShiftRng;
use rand::Rand;
use rand::Rng;

pub struct MazeGen {
    pos: Vec2<usize>,
    rand: XorShiftRng,
}

impl MazeGen {
    pub fn new(x: usize, y: usize) -> MazeGen {
        MazeGen{
            pos: Vec2::new(x,y),
            rand: XorShiftRng::rand(&mut OsRng::new().unwrap()),
        }
    }

    pub fn get_start_pos(&self) -> &Vec2 {
        self.pos
    }

    pub fn set_start_pos(&mut self, pos: &Vec2) {
        self.pos = pos.clone();
    }

    pub fn generate(&self, level: &mut Level) {
        let mut stack: Vec<&Vec2<usize>> = Vec::new();
        stack.push(self.pos);
        'mainloop while let Some(cur) = stack.pop() {
            let mut tile = level.get_mut_tile_with_vec(cur);

        }
    }

    fn get_neighbours() -> Vec<&Vec2<usize>> {

    }

}
<commit_msg>maze_gen advanced a bit<commit_after>use level::Level;

use na::Vec2;

use rand::os::OsRng;
use rand::XorShiftRng;
use rand::Rand;
use rand::Rng;

pub struct MazeGen {
    pos: Vec2<usize>,
    rand: XorShiftRng,
}

impl MazeGen {
    pub fn new(x: usize, y: usize) -> MazeGen {
        MazeGen{
            pos: Vec2::new(x,y),
            rand: XorShiftRng::rand(&mut OsRng::new().unwrap()),
        }
    }

    pub fn get_start_pos(&self) -> &Vec2 {
        self.pos
    }

    pub fn set_start_pos(&mut self, pos: &Vec2) {
        self.pos = pos.clone();
    }

    pub fn generate(&self, level: &mut Level) {
        let mut stack: Vec<&Vec2<usize>> = Vec::new();
        stack.push(self.pos);
        'mainloop while let Some(cur) = stack.pop() {
            match level.get_mut_tile_with_vec(cur) {
                Some(tile) => {
                    if tile == Tile::Void || tile == Tile::Floor {
                        continue 'mainloop
                    }
                    let mut neighbours = self.get_neighbours();
                    if neighbours
                },
                None => continue 'mainloop
            }

        }
    }

    fn get_neighbours(pos: &Vec2) -> Vec<&Vec2<usize>> {

    }

}
<|endoftext|>


<commit_before>#![allow(unused_mut, unused_variables)]

use truetype::GlyphID;

use {Result, Tape, Value, Walue};
use layout::Coverage;

/// A table.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Table {
    SingleSubstibution(SingleSubstibution),
    MultipleSubstibution(MultipleSubstibution),
    AlternateSubstibution(AlternateSubstibution),
    LigatureSubstibution(LigatureSubstibution),
    ContextSubstibution(ContextSubstibution),
    ChainedContextSubstibution(ChainedContextSubstibution),
    ExtensionSubstibution(ExtensionSubstibution),
    ReverseChainedContextSubstibution(ReverseChainedContextSubstibution),
}

/// A table for substituting one glyph with one glyph.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SingleSubstibution {
    /// Format 1.
    Format1(SingleSubstibution1),
    /// Format 2.
    Format2(SingleSubstibution2),
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one glyph in format 1."]
    pub SingleSubstibution1 {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        delta_glyph_id  (i16), // DeltaGlyphID

        coverage (Coverage) |this, tape, position| {
            try!(tape.jump(position + this.coverage_offset as u64));
            tape.take()
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one glyph in format 2."]
    pub SingleSubstibution2 {
        format          (u16) = { 2 }, // SubstFormat
        coverage_offset (u16), // Coverage
        glyph_count     (u16), // GlyphCount

        glyph_ids (Vec<GlyphID>) |this, tape, _| { // Substitute
            tape.take_given(this.glyph_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            try!(tape.jump(position + this.coverage_offset as u64));
            tape.take()
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with more than one glyph."]
    pub MultipleSubstibution {
        format           (u16) = { 1 }, // SubstFormat
        coverage_offset  (u16), // Coverage
        sequence_count   (u16), // SequenceCount

        sequence_offsets (Vec<u16>) |this, tape, _| { // Sequence
            tape.take_given(this.sequence_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            try!(tape.jump(position + this.coverage_offset as u64));
            tape.take()
        },

        sequences (Vec<Sequence>) |this, tape, position| {
            let mut values = Vec::with_capacity(this.sequence_count as usize);
            for i in 0..(this.sequence_count as usize) {
                try!(tape.jump(position + this.sequence_offsets[i] as u64));
                values.push(try!(tape.take()));
            }
            Ok(values)
        },
    }
}

table! {
    #[doc = "A table for substituting one glyph with one of many glyphs."]
    pub AlternateSubstibution {
    }
}

table! {
    @position
    #[doc = "A table for substituting multiple glyphs with one glyph."]
    pub LigatureSubstibution {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        set_count       (u16), // LigSetCount

        set_offsets (Vec<u16>) |this, tape, _| { // LigatureSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            try!(tape.jump(position + this.coverage_offset as u64));
            tape.take()
        },

        sets (Vec<LigatureSet>) |this, tape, position| {
            let mut values = Vec::with_capacity(this.set_count as usize);
            for i in 0..(this.set_count as usize) {
                try!(tape.jump(position + this.set_offsets[i] as u64));
                values.push(try!(tape.take()));
            }
            Ok(values)
        },
    }
}

table! {
    #[doc = "A table for substituting glyphs in a context."]
    pub ContextSubstibution {
    }
}

table! {
    #[doc = "A table for substituting glyphs in a chained context."]
    pub ChainedContextSubstibution {
    }
}

table! {
    #[doc = "A table for other types of substitution."]
    pub ExtensionSubstibution {
    }
}

table! {
    #[doc = "A table for substituting glyphs in reverse order in a chained context."]
    pub ReverseChainedContextSubstibution {
    }
}

table! {
    #[doc = "A ligature record."]
    pub Ligature {
        glyph_id        (GlyphID), // LigGlyph
        component_count (u16    ), // CompCount

        component_ids (Vec<GlyphID>) |this, tape| { // Component
            if this.component_count == 0 {
                raise!("found a malformed ligature record");
            }
            tape.take_given(this.component_count as usize - 1)
        },
    }
}

table! {
    @position
    #[doc = "A set of ligature records."]
    pub LigatureSet {
        count (u16), // LigatureCount

        offsets (Vec<u16>) |this, tape, _| { // Ligature
            tape.take_given(this.count as usize)
        },

        records (Vec<Ligature>) |this, tape, position| {
            let mut values = Vec::with_capacity(this.count as usize);
            for i in 0..(this.count as usize) {
                try!(tape.jump(position + this.offsets[i] as u64));
                values.push(try!(tape.take()));
            }
            Ok(values)
        },
    }
}

table! {
    #[doc = "A sequence of glyphs."]
    pub Sequence {
        count (u16), // GlyphCount

        glyph_ids (Vec<GlyphID>) |this, tape| { // Substitute
            tape.take_given(this.count as usize)
        },
    }
}

impl Walue<u16> for Table {
    fn read<T: Tape>(tape: &mut T, kind: u16) -> Result<Self> {
        Ok(match kind {
            1 => Table::SingleSubstibution(try!(tape.take())),
            2 => Table::MultipleSubstibution(try!(tape.take())),
            3 => Table::AlternateSubstibution(try!(tape.take())),
            4 => Table::LigatureSubstibution(try!(tape.take())),
            5 => Table::ContextSubstibution(try!(tape.take())),
            6 => Table::ChainedContextSubstibution(try!(tape.take())),
            7 => Table::ExtensionSubstibution(try!(tape.take())),
            8 => Table::ReverseChainedContextSubstibution(try!(tape.take())),
            _ => raise!("found an unknown glyph-substitution type"),
        })
    }
}

impl Value for SingleSubstibution {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u16>()) {
            1 => SingleSubstibution::Format1(try!(tape.take())),
            2 => SingleSubstibution::Format2(try!(tape.take())),
            _ => raise!("found an unknown format of the single-substitution table"),
        })
    }
}
<commit_msg>Read the alternate-substitution table<commit_after>#![allow(unused_mut, unused_variables)]

use truetype::GlyphID;

use {Result, Tape, Value, Walue};
use layout::Coverage;

/// A table.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Table {
    SingleSubstibution(SingleSubstibution),
    MultipleSubstibution(MultipleSubstibution),
    AlternateSubstibution(AlternateSubstibution),
    LigatureSubstibution(LigatureSubstibution),
    ContextSubstibution(ContextSubstibution),
    ChainedContextSubstibution(ChainedContextSubstibution),
    ExtensionSubstibution(ExtensionSubstibution),
    ReverseChainedContextSubstibution(ReverseChainedContextSubstibution),
}

/// A table for substituting one glyph with one glyph.
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum SingleSubstibution {
    /// Format 1.
    Format1(SingleSubstibution1),
    /// Format 2.
    Format2(SingleSubstibution2),
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one glyph in format 1."]
    pub SingleSubstibution1 {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        delta_glyph_id  (i16), // DeltaGlyphID

        coverage (Coverage) |this, tape, position| {
            try!(tape.jump(position + this.coverage_offset as u64));
            tape.take()
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one glyph in format 2."]
    pub SingleSubstibution2 {
        format          (u16) = { 2 }, // SubstFormat
        coverage_offset (u16), // Coverage
        glyph_count     (u16), // GlyphCount

        glyph_ids (Vec<GlyphID>) |this, tape, _| { // Substitute
            tape.take_given(this.glyph_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            try!(tape.jump(position + this.coverage_offset as u64));
            tape.take()
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with more than one glyph."]
    pub MultipleSubstibution {
        format           (u16) = { 1 }, // SubstFormat
        coverage_offset  (u16), // Coverage
        sequence_count   (u16), // SequenceCount

        sequence_offsets (Vec<u16>) |this, tape, _| { // Sequence
            tape.take_given(this.sequence_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            try!(tape.jump(position + this.coverage_offset as u64));
            tape.take()
        },

        sequences (Vec<Sequence>) |this, tape, position| {
            let mut values = Vec::with_capacity(this.sequence_count as usize);
            for i in 0..(this.sequence_count as usize) {
                try!(tape.jump(position + this.sequence_offsets[i] as u64));
                values.push(try!(tape.take()));
            }
            Ok(values)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting one glyph with one of many glyphs."]
    pub AlternateSubstibution {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        set_count       (u16), // AlternateSetCount

        set_offsets (Vec<u16>) |this, tape, _| { // AlternateSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            try!(tape.jump(position + this.coverage_offset as u64));
            tape.take()
        },

        sets (Vec<AlternateSet>) |this, tape, position| {
            let mut values = Vec::with_capacity(this.set_count as usize);
            for i in 0..(this.set_count as usize) {
                try!(tape.jump(position + this.set_offsets[i] as u64));
                values.push(try!(tape.take()));
            }
            Ok(values)
        },
    }
}

table! {
    @position
    #[doc = "A table for substituting multiple glyphs with one glyph."]
    pub LigatureSubstibution {
        format          (u16) = { 1 }, // SubstFormat
        coverage_offset (u16), // Coverage
        set_count       (u16), // LigSetCount

        set_offsets (Vec<u16>) |this, tape, _| { // LigatureSet
            tape.take_given(this.set_count as usize)
        },

        coverage (Coverage) |this, tape, position| {
            try!(tape.jump(position + this.coverage_offset as u64));
            tape.take()
        },

        sets (Vec<LigatureSet>) |this, tape, position| {
            let mut values = Vec::with_capacity(this.set_count as usize);
            for i in 0..(this.set_count as usize) {
                try!(tape.jump(position + this.set_offsets[i] as u64));
                values.push(try!(tape.take()));
            }
            Ok(values)
        },
    }
}

table! {
    #[doc = "A table for substituting glyphs in a context."]
    pub ContextSubstibution {
    }
}

table! {
    #[doc = "A table for substituting glyphs in a chained context."]
    pub ChainedContextSubstibution {
    }
}

table! {
    #[doc = "A table for other types of substitution."]
    pub ExtensionSubstibution {
    }
}

table! {
    #[doc = "A table for substituting glyphs in reverse order in a chained context."]
    pub ReverseChainedContextSubstibution {
    }
}

table! {
    #[doc = "A set of alternate glyphs."]
    pub AlternateSet {
        count (u16), // GlyphCount

        glyph_ids (Vec<GlyphID>) |this, tape| { // Alternate
            tape.take_given(this.count as usize)
        },
    }
}

table! {
    #[doc = "A ligature."]
    pub Ligature {
        glyph_id        (GlyphID), // LigGlyph
        component_count (u16    ), // CompCount

        component_ids (Vec<GlyphID>) |this, tape| { // Component
            if this.component_count == 0 {
                raise!("found a malformed ligature record");
            }
            tape.take_given(this.component_count as usize - 1)
        },
    }
}

table! {
    @position
    #[doc = "A set of ligatures."]
    pub LigatureSet {
        count (u16), // LigatureCount

        offsets (Vec<u16>) |this, tape, _| { // Ligature
            tape.take_given(this.count as usize)
        },

        records (Vec<Ligature>) |this, tape, position| {
            let mut values = Vec::with_capacity(this.count as usize);
            for i in 0..(this.count as usize) {
                try!(tape.jump(position + this.offsets[i] as u64));
                values.push(try!(tape.take()));
            }
            Ok(values)
        },
    }
}

table! {
    #[doc = "A sequence of glyphs."]
    pub Sequence {
        count (u16), // GlyphCount

        glyph_ids (Vec<GlyphID>) |this, tape| { // Substitute
            tape.take_given(this.count as usize)
        },
    }
}

impl Walue<u16> for Table {
    fn read<T: Tape>(tape: &mut T, kind: u16) -> Result<Self> {
        Ok(match kind {
            1 => Table::SingleSubstibution(try!(tape.take())),
            2 => Table::MultipleSubstibution(try!(tape.take())),
            3 => Table::AlternateSubstibution(try!(tape.take())),
            4 => Table::LigatureSubstibution(try!(tape.take())),
            5 => Table::ContextSubstibution(try!(tape.take())),
            6 => Table::ChainedContextSubstibution(try!(tape.take())),
            7 => Table::ExtensionSubstibution(try!(tape.take())),
            8 => Table::ReverseChainedContextSubstibution(try!(tape.take())),
            _ => raise!("found an unknown glyph-substitution type"),
        })
    }
}

impl Value for SingleSubstibution {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u16>()) {
            1 => SingleSubstibution::Format1(try!(tape.take())),
            2 => SingleSubstibution::Format2(try!(tape.take())),
            _ => raise!("found an unknown format of the single-substitution table"),
        })
    }
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(rustc_private, plugin_registrar, quote)]

extern crate platformtree;
extern crate rustc;
extern crate serialize;
extern crate syntax;
extern crate rustc_plugin;

use std::clone::Clone;
use std::ops::Deref;

use rustc_plugin::Registry;
use syntax::ast;
use syntax::codemap::DUMMY_SP;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MultiModifier, Annotatable};
use syntax::ext::build::AstBuilder;
use syntax::print::pprust;
use syntax::util::small_vector::SmallVector;
use syntax::ptr::P;

use platformtree::parser::Parser;
use platformtree::builder::Builder;
use platformtree::builder::meta_args::ToTyHash;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
  reg.register_macro("platformtree", macro_platformtree);
  reg.register_macro("platformtree_verbose", macro_platformtree_verbose);
  reg.register_syntax_extension(syntax::parse::token::intern("zinc_task"),
      MultiModifier(Box::new(macro_zinc_task)));
}

pub fn macro_platformtree(cx: &mut ExtCtxt, _: Span, tts: &[ast::TokenTree])
    -> Box<MacResult+'static> {
  let pt = Parser::new(cx, tts).parse_platformtree();
  let items = Builder::build(cx, pt.unwrap())
    .expect(format!("Unexpected failure on {}", line!()).as_str())
    .emit_items(cx);
  MacItems::new(items)
}

pub fn macro_platformtree_verbose(cx: &mut ExtCtxt, sp: Span,
    tts: &[ast::TokenTree]) -> Box<MacResult+'static> {
  let result = macro_platformtree(cx, sp, tts);
  println!("Platform Tree dump:");
  for i in result.make_items().unwrap().as_slice().iter() {
    println!("{}", pprust::item_to_string(i.deref()));
  }

  macro_platformtree(cx, sp, tts)
}

fn macro_zinc_task(cx: &mut ExtCtxt, _: Span, _: &ast::MetaItem,
    ann: Annotatable) -> Annotatable {
  match ann {
    Annotatable::Item(it) => {Annotatable::Item(macro_zinc_task_item(cx, it))}
    other     => {other}
  }
}

fn macro_zinc_task_item(cx: &mut ExtCtxt, it: P<ast::Item>) -> P<ast::Item> {
  match it.node {
    ast::ItemKind::Fn(ref decl, style, constness, abi, _, ref block) => {
      let istr = it.ident.name.as_str();
      let fn_name = &*istr;
      let ty_params = platformtree::builder::meta_args::get_ty_params_for_task(cx, fn_name);

      let params = ty_params.iter().map(|ty| {
        cx.typaram(
            DUMMY_SP,
            cx.ident_of(ty.to_tyhash().as_str()),
            P::from_vec(vec!(cx.typarambound(
                cx.path(DUMMY_SP, ty.as_str().split("::").map(|t| cx.ident_of(t)).collect())))),
            None)
      }).collect();

      let new_arg = cx.arg(DUMMY_SP, cx.ident_of("args"), cx.ty_rptr(
          DUMMY_SP,
          cx.ty_path(
              cx.path_all(
                  DUMMY_SP,
                  false,
                  ["pt".to_string(), fn_name.to_string() + "_args"].iter().map(|t| cx.ident_of(t.as_str())).collect(),
                  vec!(),
                  ty_params.iter().map(|ty| {
                    cx.ty_path(cx.path_ident(DUMMY_SP, cx.ident_of(ty.to_tyhash().as_str())))
                  }).collect(),
                  vec!())),
          None,
          ast::Mutability::Immutable));
      let new_decl = P(ast::FnDecl {
        inputs: vec!(new_arg),
        ..decl.deref().clone()
      });

      let new_generics = ast::Generics {
        lifetimes: vec!(),
        ty_params: P::from_vec(params),
        where_clause: ast::WhereClause {
          id: ast::DUMMY_NODE_ID,
          predicates: vec!(),
        }
      };
      let new_node = ast::ItemKind::Fn(new_decl, style, constness, abi, new_generics, block.clone());

      P(ast::Item {node: new_node, ..it.deref().clone() })
    },
    _ => panic!(),
  }
}

pub struct MacItems {
  items: Vec<P<ast::Item>>
}

impl MacItems {
  pub fn new(items: Vec<P<ast::Item>>) -> Box<MacResult+'static> {
    Box::new(MacItems { items: items })
  }
}
impl MacResult for MacItems {
  fn make_items(self: Box<MacItems>) -> Option<SmallVector<P<ast::Item>>> {
    Some(SmallVector::many(self.items.clone()))
  }
}
<commit_msg>Fixed tokens in macro_platformtree<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(rustc_private, plugin_registrar, quote)]

extern crate platformtree;
extern crate rustc;
extern crate serialize;
extern crate syntax;
extern crate rustc_plugin;

use std::clone::Clone;
use std::ops::Deref;

use rustc_plugin::Registry;
use syntax::ast;
use syntax::tokenstream;
use syntax::codemap::DUMMY_SP;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult, MultiModifier, Annotatable};
use syntax::ext::build::AstBuilder;
use syntax::print::pprust;
use syntax::util::small_vector::SmallVector;
use syntax::ptr::P;

use platformtree::parser::Parser;
use platformtree::builder::Builder;
use platformtree::builder::meta_args::ToTyHash;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
  reg.register_macro("platformtree", macro_platformtree);
  reg.register_macro("platformtree_verbose", macro_platformtree_verbose);
  reg.register_syntax_extension(syntax::parse::token::intern("zinc_task"),
      MultiModifier(Box::new(macro_zinc_task)));
}

pub fn macro_platformtree(cx: &mut ExtCtxt, _: Span, tts: &[tokenstream::TokenTree])
    -> Box<MacResult+'static> {
  let pt = Parser::new(cx, tts).parse_platformtree();
  let items = Builder::build(cx, pt.unwrap())
    .expect(format!("Unexpected failure on {}", line!()).as_str())
    .emit_items(cx);
  MacItems::new(items)
}

pub fn macro_platformtree_verbose(cx: &mut ExtCtxt, sp: Span,
    tts: &[tokenstream::TokenTree]) -> Box<MacResult+'static> {
  let result = macro_platformtree(cx, sp, tts);
  println!("Platform Tree dump:");
  for i in result.make_items().unwrap().as_slice().iter() {
    println!("{}", pprust::item_to_string(i.deref()));
  }

  macro_platformtree(cx, sp, tts)
}

fn macro_zinc_task(cx: &mut ExtCtxt, _: Span, _: &ast::MetaItem,
    ann: Annotatable) -> Annotatable {
  match ann {
    Annotatable::Item(it) => {Annotatable::Item(macro_zinc_task_item(cx, it))}
    other     => {other}
  }
}

fn macro_zinc_task_item(cx: &mut ExtCtxt, it: P<ast::Item>) -> P<ast::Item> {
  match it.node {
    ast::ItemKind::Fn(ref decl, style, constness, abi, _, ref block) => {
      let istr = it.ident.name.as_str();
      let fn_name = &*istr;
      let ty_params = platformtree::builder::meta_args::get_ty_params_for_task(cx, fn_name);

      let params = ty_params.iter().map(|ty| {
        cx.typaram(
            DUMMY_SP,
            cx.ident_of(ty.to_tyhash().as_str()),
            P::from_vec(vec!(cx.typarambound(
                cx.path(DUMMY_SP, ty.as_str().split("::").map(|t| cx.ident_of(t)).collect())))),
            None)
      }).collect();

      let new_arg = cx.arg(DUMMY_SP, cx.ident_of("args"), cx.ty_rptr(
          DUMMY_SP,
          cx.ty_path(
              cx.path_all(
                  DUMMY_SP,
                  false,
                  ["pt".to_string(), fn_name.to_string() + "_args"].iter().map(|t| cx.ident_of(t.as_str())).collect(),
                  vec!(),
                  ty_params.iter().map(|ty| {
                    cx.ty_path(cx.path_ident(DUMMY_SP, cx.ident_of(ty.to_tyhash().as_str())))
                  }).collect(),
                  vec!())),
          None,
          ast::Mutability::Immutable));
      let new_decl = P(ast::FnDecl {
        inputs: vec!(new_arg),
        ..decl.deref().clone()
      });

      let new_generics = ast::Generics {
        lifetimes: vec!(),
        ty_params: P::from_vec(params),
        where_clause: ast::WhereClause {
          id: ast::DUMMY_NODE_ID,
          predicates: vec!(),
        }
      };
      let new_node = ast::ItemKind::Fn(new_decl, style, constness, abi, new_generics, block.clone());

      P(ast::Item {node: new_node, ..it.deref().clone() })
    },
    _ => panic!(),
  }
}

pub struct MacItems {
  items: Vec<P<ast::Item>>
}

impl MacItems {
  pub fn new(items: Vec<P<ast::Item>>) -> Box<MacResult+'static> {
    Box::new(MacItems { items: items })
  }
}
impl MacResult for MacItems {
  fn make_items(self: Box<MacItems>) -> Option<SmallVector<P<ast::Item>>> {
    Some(SmallVector::many(self.items.clone()))
  }
}
<|endoftext|>


<commit_before>mod codec;
mod handshake;

pub use self::codec::APCodec;
pub use self::handshake::handshake;

use futures::{Future, Sink, Stream};
use protobuf::{self, Message};
use std::io;
use std::net::ToSocketAddrs;
use tokio_core::net::TcpStream;
use tokio_core::reactor::Handle;
use tokio_io::codec::Framed;

use authentication::Credentials;
use version;

pub type Transport = Framed<TcpStream, APCodec>;

pub fn connect<A: ToSocketAddrs>(
    addr: A,
    handle: &Handle,
) -> Box<Future<Item = Transport, Error = io::Error>> {
    let addr = addr.to_socket_addrs().unwrap().next().unwrap();
    let socket = TcpStream::connect(&addr, handle);
    let connection = socket.and_then(|socket| handshake(socket));

    Box::new(connection)
}

pub fn authenticate(
    transport: Transport,
    credentials: Credentials,
    device_id: String,
) -> Box<Future<Item = (Transport, Credentials), Error = io::Error>> {
    use protocol::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os};
    use protocol::keyexchange::APLoginFailed;

    let mut packet = ClientResponseEncrypted::new();
    packet
        .mut_login_credentials()
        .set_username(credentials.username);
    packet
        .mut_login_credentials()
        .set_typ(credentials.auth_type);
    packet
        .mut_login_credentials()
        .set_auth_data(credentials.auth_data);
    packet
        .mut_system_info()
        .set_cpu_family(CpuFamily::CPU_UNKNOWN);
    packet.mut_system_info().set_os(Os::OS_UNKNOWN);
    packet
        .mut_system_info()
        .set_system_information_string(format!(
            "librespot_{}_{}",
            version::short_sha(),
            version::build_id()
        ));
    packet.mut_system_info().set_device_id(device_id);
    packet.set_version_string(version::version_string());

    let cmd = 0xab;
    let data = packet.write_to_bytes().unwrap();

    Box::new(
        transport
            .send((cmd, data))
            .and_then(|transport| transport.into_future().map_err(|(err, _stream)| err))
            .and_then(|(packet, transport)| match packet {
                Some((0xac, data)) => {
                    let welcome_data: APWelcome = protobuf::parse_from_bytes(data.as_ref()).unwrap();

                    let reusable_credentials = Credentials {
                        username: welcome_data.get_canonical_username().to_owned(),
                        auth_type: welcome_data.get_reusable_auth_credentials_type(),
                        auth_data: welcome_data.get_reusable_auth_credentials().to_owned(),
                    };

                    Ok((transport, reusable_credentials))
                }

                Some((0xad, data)) => {
                    let error_data: APLoginFailed = protobuf::parse_from_bytes(data.as_ref()).unwrap();
                    panic!("Authentication failed with reason: {:?}", error_data.get_error_code())
                }

                Some((cmd, _)) => panic!("Unexpected packet {:?}", cmd),
                None => panic!("EOF"),
            }),
    )
}
<commit_msg>Update for rust format<commit_after>mod codec;
mod handshake;

pub use self::codec::APCodec;
pub use self::handshake::handshake;

use futures::{Future, Sink, Stream};
use protobuf::{self, Message};
use std::io;
use std::net::ToSocketAddrs;
use tokio_core::net::TcpStream;
use tokio_core::reactor::Handle;
use tokio_io::codec::Framed;

use authentication::Credentials;
use version;

pub type Transport = Framed<TcpStream, APCodec>;

pub fn connect<A: ToSocketAddrs>(
    addr: A,
    handle: &Handle,
) -> Box<Future<Item = Transport, Error = io::Error>> {
    let addr = addr.to_socket_addrs().unwrap().next().unwrap();
    let socket = TcpStream::connect(&addr, handle);
    let connection = socket.and_then(|socket| handshake(socket));

    Box::new(connection)
}

pub fn authenticate(
    transport: Transport,
    credentials: Credentials,
    device_id: String,
) -> Box<Future<Item = (Transport, Credentials), Error = io::Error>> {
    use protocol::authentication::{APWelcome, ClientResponseEncrypted, CpuFamily, Os};
    use protocol::keyexchange::APLoginFailed;

    let mut packet = ClientResponseEncrypted::new();
    packet
        .mut_login_credentials()
        .set_username(credentials.username);
    packet
        .mut_login_credentials()
        .set_typ(credentials.auth_type);
    packet
        .mut_login_credentials()
        .set_auth_data(credentials.auth_data);
    packet
        .mut_system_info()
        .set_cpu_family(CpuFamily::CPU_UNKNOWN);
    packet.mut_system_info().set_os(Os::OS_UNKNOWN);
    packet
        .mut_system_info()
        .set_system_information_string(format!(
            "librespot_{}_{}",
            version::short_sha(),
            version::build_id()
        ));
    packet.mut_system_info().set_device_id(device_id);
    packet.set_version_string(version::version_string());

    let cmd = 0xab;
    let data = packet.write_to_bytes().unwrap();

    Box::new(
        transport
            .send((cmd, data))
            .and_then(|transport| transport.into_future().map_err(|(err, _stream)| err))
            .and_then(|(packet, transport)| match packet {
                Some((0xac, data)) => {
                    let welcome_data: APWelcome = protobuf::parse_from_bytes(data.as_ref()).unwrap();

                    let reusable_credentials = Credentials {
                        username: welcome_data.get_canonical_username().to_owned(),
                        auth_type: welcome_data.get_reusable_auth_credentials_type(),
                        auth_data: welcome_data.get_reusable_auth_credentials().to_owned(),
                    };

                    Ok((transport, reusable_credentials))
                }

                Some((0xad, data)) => {
                    let error_data: APLoginFailed = protobuf::parse_from_bytes(data.as_ref()).unwrap();
                    panic!(
                        "Authentication failed with reason: {:?}",
                        error_data.get_error_code()
                    )
                }

                Some((cmd, _)) => panic!("Unexpected packet {:?}", cmd),
                None => panic!("EOF"),
            }),
    )
}
<|endoftext|>


<commit_before>use super::{ ASTNode
           , SymbolTable
           , SymbolAnnotation
           };
use ::position::Position;

use std::rc::Rc;

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Type {
    /// Reference types
    Ref(Reference),
    /// Primitive types
    Prim(Primitive),
    /// An algebraic data type.
    ///
    /// Represented as a vector of variants.
    Algebraic(Vec<Type>),
    /// A function.
    ///
    /// Represented as a vector of parameters and a return type.
    Function { params: Vec<Type>
             , rt: Rc<Type> },
    /// A unique symbol type (`'symbol` syntax)
    Symbol(String)
}

/// Reference types (pointers)
///
/// TODO: how will lifetime analysis actually work?
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Reference {
    /// A reference borrowed from another scope.
    ///
    /// Semantically similar to Rust's `&`-pointers.
    ///
    /// TODO: should this track where it was borrowed from?
    /// (can we even perform this analysis at this stage?)
    Borrowed(Rc<Type>),
    /// A moved reference from another scope
    ///
    /// TODO: should this track where it was moved from?
    /// (can we even perform this analysis at this stage?)
    Moved(Rc<Type>),
    /// A unique (i.e. boxed) reference.
    Unique(Rc<Type>),
    /// A raw (unsafe) reference.
    ///
    /// Unfortunately we have to have this because of
    /// reasons (i.e, FFI).
    Raw(Rc<Type>)
}

/// Language primitive types
///
/// TODO: add some form of provable-refinement (i.e. we know that some value
/// is not just a bool at compile time but that it's true/false, or we know
/// some value is not just a number but the number 1382, or whatever).
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Primitive { Int
                   , Uint
                   , Byte
                   , Char
                   , Str
                   , Bool
                   , Float
                   , Double
                   // TODO: finish
                   }
<commit_msg>Remove unused imports<commit_after>use std::rc::Rc;

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Type {
    /// Reference types
    Ref(Reference),
    /// Primitive types
    Prim(Primitive),
    /// An algebraic data type.
    ///
    /// Represented as a vector of variants.
    Algebraic(Vec<Type>),
    /// A function.
    ///
    /// Represented as a vector of parameters and a return type.
    Function { params: Vec<Type>
             , rt: Rc<Type>
             },
    /// A unique symbol type (`'symbol` syntax)
    Symbol(String)
}

/// Reference types (pointers)
///
/// TODO: how will lifetime analysis actually work?
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Reference {
    /// A reference borrowed from another scope.
    ///
    /// Semantically similar to Rust's `&`-pointers.
    ///
    /// TODO: should this track where it was borrowed from?
    /// (can we even perform this analysis at this stage?)
    Borrowed(Rc<Type>),
    /// A moved reference from another scope
    ///
    /// TODO: should this track where it was moved from?
    /// (can we even perform this analysis at this stage?)
    Moved(Rc<Type>),
    /// A unique (i.e. boxed) reference.
    Unique(Rc<Type>),
    /// A raw (unsafe) reference.
    ///
    /// Unfortunately we have to have this because of
    /// reasons (i.e, FFI).
    Raw(Rc<Type>)
}

/// Language primitive types
///
/// TODO: add some form of provable-refinement (i.e. we know that some value
/// is not just a bool at compile time but that it's true/false, or we know
/// some value is not just a number but the number 1382, or whatever).
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Primitive { Int
                   , Uint
                   , Byte
                   , Char
                   , Str
                   , Bool
                   , Float
                   , Double
                   // TODO: finish
                   }
<|endoftext|>


<commit_before>use core::mem::ManuallyDrop;

#[test]
fn smoke() {
    struct TypeWithDrop;
    impl Drop for TypeWithDrop {
        fn drop(&mut self) {
            unreachable!("Should not get dropped");
        }
    }

    let x = ManuallyDrop::new(TypeWithDrop);
    drop(x);

    // also test unsizing
    let x: Box<ManuallyDrop<[TypeWithDrop]>> =
        Box::new(ManuallyDrop::new([TypeWithDrop, TypeWithDrop]));
    drop(x);
}
<commit_msg>Rollup merge of #86880 - m-ou-se:test-manuallydrop-clone-from, r=Mark-Simulacrum<commit_after>use core::mem::ManuallyDrop;

#[test]
fn smoke() {
    #[derive(Clone)]
    struct TypeWithDrop;
    impl Drop for TypeWithDrop {
        fn drop(&mut self) {
            unreachable!("Should not get dropped");
        }
    }

    let x = ManuallyDrop::new(TypeWithDrop);
    drop(x);

    // also test unsizing
    let x: Box<ManuallyDrop<[TypeWithDrop]>> =
        Box::new(ManuallyDrop::new([TypeWithDrop, TypeWithDrop]));
    drop(x);

    // test clone and clone_from implementations
    let mut x = ManuallyDrop::new(TypeWithDrop);
    let y = x.clone();
    x.clone_from(&y);
    drop(x);
    drop(y);
}
<|endoftext|>


<commit_before>fn add_strings(nums1:) -> i32 {}
<commit_msg>finish<commit_after>use std::collections::HashMap;

fn exponent(exp: i32) -> i32 {
    let mut result = 1;
    for _ in 0..exp {
        result *= 10;
    }
    result
}

fn add_strings(nums1: &str, nums2: &str, dict: &HashMap<char, i32>) -> i32 {
    let length1 = nums1.len() as i32;
    let length2 = nums2.len() as i32;
    let mut sum = 0;
    let mut count = 1;

    for c in nums1.chars() {
        //:= MARK: well, (expression) wont take ownship
        sum += *dict.get(&c).unwrap() * exponent((length1 - count));
        count += 1;
        //println!("{}", &sum);
    }

    count = 1;
    for c in nums2.chars() {
        sum += *dict.get(&c).unwrap() * exponent((length2 - count));
        count += 1;
        //println!("{}", &sum);
    }

    sum
}

fn main() {
    let mut dict = HashMap::new();
    let mut temp_num = 0;

    for c in "0123456789".chars() {
        dict.insert(c, temp_num);
        temp_num += 1;
    }

    println!("{}", add_strings(&"102", &"20", &dict));
}
<|endoftext|>


<commit_before>extern crate cc;

fn main() {
    let asm_path = if cfg!(target_arch = "x86") {
        "src/x86.S"
    } else if cfg!(target_arch = "x86_64") {
        "src/x64.S"
    } else {
        "src/generic.c"
    };
    cc::Build::new()
        .flag("-c")
        .file(asm_path)
        .opt_level(3)
        .compile("sha1-round");
}
<commit_msg>Remove flag from sha1 asm build<commit_after>extern crate cc;

fn main() {
    let asm_path = if cfg!(target_arch = "x86") {
        "src/x86.S"
    } else if cfg!(target_arch = "x86_64") {
        "src/x64.S"
    } else {
        "src/generic.c"
    };
    cc::Build::new()
        .file(asm_path)
        .opt_level(3)
        .compile("sha1-round");
}
<|endoftext|>