<commit_before>//! `ndarray` compability

use std::ops::Range;
use super::{FitsFile, FitsHdu};
use super::fitsfile::ReadImage;
use super::errors::Result;
use super::types::HduInfo;
use ndarray::{Array, ArrayD};

impl<T> ReadImage for ArrayD<T>
where
    T: Clone,
    Vec<T>: ReadImage,
{
    fn read_section(fits_file: &mut FitsFile, hdu: &FitsHdu, range: Range<usize>) -> Result<Self> {
        match hdu.info {
            HduInfo::ImageInfo { ref shape, .. } => {
                if shape.len() != 2 {
                    return Err("Only 2D images supported for now".into());
                }

                let width = shape[1];

                if range.start % width != 0 {
                    return Err("range must start on row boundary".into());
                }
                let start_pixel = range.start / width;

                let n_pixels_requested = range.end - range.start;
                if n_pixels_requested % width != 0 {
                    return Err(
                        "must request number of pixels exactly divisible by image width".into(),
                    );
                }

                let n_rows = n_pixels_requested / width;
                ReadImage::read_rows(fits_file, hdu, start_pixel, n_rows)
            }
            HduInfo::TableInfo { .. } => {
                return Err("Cannot read image data from a FITS table".into())
            }
            _ => unreachable!(),
        }
    }

    fn read_rows(
        fits_file: &mut FitsFile,
        hdu: &FitsHdu,
        start_row: usize,
        num_rows: usize,
    ) -> Result<Self> {
        let data: Vec<T> = ReadImage::read_rows(fits_file, hdu, start_row, num_rows)?;
        let arr = Array::from_vec(data);
        let row_length = arr.len() / num_rows;
        Ok(arr.into_shape(vec![num_rows, row_length]).unwrap())
    }

    fn read_row(fits_file: &mut FitsFile, hdu: &FitsHdu, row: usize) -> Result<Self> {
        let data: Vec<T> = ReadImage::read_row(fits_file, hdu, row)?;
        let shape = vec![data.len()];
        Ok(Array::from_shape_vec(shape, data).unwrap())
    }

    fn read_region(
        fits_file: &mut FitsFile,
        hdu: &FitsHdu,
        ranges: &[&Range<usize>],
    ) -> Result<Self> {
        let data: Vec<T> = ReadImage::read_region(fits_file, hdu, ranges)?;
        let shape: Vec<usize> = (0..ranges.len())
            .map(|i| ranges[i].end - ranges[i].start)
            .collect();
        let arr = Array::from_shape_vec(shape, data).unwrap();
        Ok(arr)
    }

    fn read_image(fits_file: &mut FitsFile, hdu: &FitsHdu) -> Result<Self> {
        match hdu.info {
            HduInfo::ImageInfo { ref shape, .. } => {
                let data: Vec<T> = ReadImage::read_image(fits_file, hdu)?;
                let shape: Vec<usize> = (0..2).map(|i| shape[i]).collect();
                let arr = Array::from_shape_vec(shape, data).unwrap();
                Ok(arr)
            }
            _ => unreachable!(),
        }
    }
}

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

    #[test]
    fn test_read_image() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        let data: ArrayD<u32> = hdu.read_image(&mut f).unwrap();
        let dim = data.dim();
        assert_eq!(dim[0], 100);
        assert_eq!(dim[1], 100);
        assert_eq!(data[[20, 5]], 152);
    }

    #[test]
    fn test_read_rows() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        let data: ArrayD<u32> = hdu.read_rows(&mut f, 0, 2).unwrap();
        let dim = data.dim();
        assert_eq!(dim[0], 2);
        assert_eq!(dim[1], 100);
        assert_eq!(data[[1, 52]], 184);
    }

    #[test]
    fn test_read_row() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        let data: ArrayD<u32> = hdu.read_row(&mut f, 49).unwrap();
        assert_eq!(data[20], 156);
    }

    #[test]
    fn test_read_region() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        let data: ArrayD<u32> = hdu.read_region(&mut f, &[&(70..80), &(20..50)]).unwrap();
        let dim = data.dim();
        assert_eq!(dim[0], 10);
        assert_eq!(dim[1], 30);
        assert_eq!(data[[5, 10]], 160);
    }

    #[test]
    fn test_read_section() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        match hdu.read_section::<ArrayD<u32>>(&mut f, 0, 250) {
            Err(Error::Message(msg)) => {
                assert_eq!(
                    msg,
                    "must request number of pixels exactly divisible by image width".to_string()
                );
            }
            _ => panic!("invalid result"),
        }

        let data: ArrayD<u32> = hdu.read_section(&mut f, 0, 200).unwrap();
        let dim = data.dim();
        assert_eq!(dim[0], 2);
        assert_eq!(dim[1], 100);
        assert_eq!(data[[0, 10]], 160);
    }
}
<commit_msg>Add assertions on array dimensions<commit_after>//! `ndarray` compability

use std::ops::Range;
use super::{FitsFile, FitsHdu};
use super::fitsfile::ReadImage;
use super::errors::Result;
use super::types::HduInfo;
use ndarray::{Array, ArrayD};

impl<T> ReadImage for ArrayD<T>
where
    T: Clone,
    Vec<T>: ReadImage,
{
    fn read_section(fits_file: &mut FitsFile, hdu: &FitsHdu, range: Range<usize>) -> Result<Self> {
        match hdu.info {
            HduInfo::ImageInfo { ref shape, .. } => {
                if shape.len() != 2 {
                    return Err("Only 2D images supported for now".into());
                }

                let width = shape[1];

                if range.start % width != 0 {
                    return Err("range must start on row boundary".into());
                }
                let start_pixel = range.start / width;

                let n_pixels_requested = range.end - range.start;
                if n_pixels_requested % width != 0 {
                    return Err(
                        "must request number of pixels exactly divisible by image width".into(),
                    );
                }

                let n_rows = n_pixels_requested / width;
                ReadImage::read_rows(fits_file, hdu, start_pixel, n_rows)
            }
            HduInfo::TableInfo { .. } => {
                return Err("Cannot read image data from a FITS table".into())
            }
            _ => unreachable!(),
        }
    }

    fn read_rows(
        fits_file: &mut FitsFile,
        hdu: &FitsHdu,
        start_row: usize,
        num_rows: usize,
    ) -> Result<Self> {
        let data: Vec<T> = ReadImage::read_rows(fits_file, hdu, start_row, num_rows)?;
        let arr = Array::from_vec(data);
        let row_length = arr.len() / num_rows;
        Ok(arr.into_shape(vec![num_rows, row_length]).unwrap())
    }

    fn read_row(fits_file: &mut FitsFile, hdu: &FitsHdu, row: usize) -> Result<Self> {
        let data: Vec<T> = ReadImage::read_row(fits_file, hdu, row)?;
        let shape = vec![data.len()];
        Ok(Array::from_shape_vec(shape, data).unwrap())
    }

    fn read_region(
        fits_file: &mut FitsFile,
        hdu: &FitsHdu,
        ranges: &[&Range<usize>],
    ) -> Result<Self> {
        let data: Vec<T> = ReadImage::read_region(fits_file, hdu, ranges)?;
        let shape: Vec<usize> = (0..ranges.len())
            .map(|i| ranges[i].end - ranges[i].start)
            .collect();
        let arr = Array::from_shape_vec(shape, data).unwrap();
        Ok(arr)
    }

    fn read_image(fits_file: &mut FitsFile, hdu: &FitsHdu) -> Result<Self> {
        match hdu.info {
            HduInfo::ImageInfo { ref shape, .. } => {
                let data: Vec<T> = ReadImage::read_image(fits_file, hdu)?;
                let shape: Vec<usize> = (0..2).map(|i| shape[i]).collect();
                let arr = Array::from_shape_vec(shape, data).unwrap();
                Ok(arr)
            }
            _ => unreachable!(),
        }
    }
}

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

    #[test]
    fn test_read_image() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        let data: ArrayD<u32> = hdu.read_image(&mut f).unwrap();
        let dim = data.dim();
        assert_eq!(data.ndim(), 2);
        assert_eq!(dim[0], 100);
        assert_eq!(dim[1], 100);
        assert_eq!(data[[20, 5]], 152);
    }

    #[test]
    fn test_read_rows() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        let data: ArrayD<u32> = hdu.read_rows(&mut f, 0, 2).unwrap();
        let dim = data.dim();
        assert_eq!(data.ndim(), 2);
        assert_eq!(dim[0], 2);
        assert_eq!(dim[1], 100);
        assert_eq!(data[[1, 52]], 184);
    }

    #[test]
    fn test_read_row() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        let data: ArrayD<u32> = hdu.read_row(&mut f, 49).unwrap();
        assert_eq!(data.ndim(), 1);
        assert_eq!(data[20], 156);
    }

    #[test]
    fn test_read_region() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        let data: ArrayD<u32> = hdu.read_region(&mut f, &[&(70..80), &(20..50)]).unwrap();
        let dim = data.dim();
        assert_eq!(data.ndim(), 2);
        assert_eq!(dim[0], 10);
        assert_eq!(dim[1], 30);
        assert_eq!(data[[5, 10]], 160);
    }

    #[test]
    fn test_read_section() {
        let mut f = FitsFile::open("../testdata/full_example.fits").unwrap();
        let hdu = f.primary_hdu().unwrap();

        match hdu.read_section::<ArrayD<u32>>(&mut f, 0, 250) {
            Err(Error::Message(msg)) => {
                assert_eq!(
                    msg,
                    "must request number of pixels exactly divisible by image width".to_string()
                );
            }
            _ => panic!("invalid result"),
        }

        let data: ArrayD<u32> = hdu.read_section(&mut f, 0, 200).unwrap();
        let dim = data.dim();
        assert_eq!(data.ndim(), 2);
        assert_eq!(dim[0], 2);
        assert_eq!(dim[1], 100);
        assert_eq!(data[[0, 10]], 160);
    }
}
<|endoftext|>


<commit_before>//! Pixel manipulations.

use image::Pixel;
use conv::ValueInto;
use math::cast;
use definitions::Clamp;

/// Adds pixels with the given weights. Results are clamped to prevent arithmetical overflows.
pub fn weighted_sum<P: Pixel>(left: P, right: P, left_weight: f32, right_weight: f32) -> P
where
    P::Subpixel: ValueInto<f32> + Clamp<f32>,
{
    left.map2(&right, |p, q| {
        weighted_channel_sum(p, q, left_weight, right_weight)
    })
}

/// Equivalent to `weighted_sum(left, right, left_weight, 1 - left_weight).
pub fn interpolate<P: Pixel>(left: P, right: P, left_weight: f32) -> P
where
    P::Subpixel: ValueInto<f32> + Clamp<f32>,
{
    weighted_sum(left, right, left_weight, 1.0 - left_weight)
}

#[inline(always)]
fn weighted_channel_sum<C>(left: C, right: C, left_weight: f32, right_weight: f32) -> C
where
    C: ValueInto<f32> + Clamp<f32>,
{
    Clamp::clamp(cast(left) * left_weight + cast(right) * right_weight)
}

#[cfg(test)]
mod test {
    use super::*;
    use image::{Rgb, Luma};
    use test::{Bencher, black_box};

    #[test]
    fn test_weighted_channel_sum() {
        // Midpoint
        assert_eq!(weighted_channel_sum(10u8, 20u8, 0.5, 0.5), 15u8);
        // Mainly left
        assert_eq!(weighted_channel_sum(10u8, 20u8, 0.9, 0.1), 11u8);
        // Clamped
        assert_eq!(weighted_channel_sum(150u8, 150u8, 1.8, 0.8), 255u8);
    }

    #[test]
    fn test_weighted_sum() {
        let left = Rgb([10u8, 20u8, 30u8]);
        let right = Rgb([100u8, 80u8, 60u8]);
        let sum = weighted_sum(left, right, 0.7, 0.3);
        assert_eq!(sum, Rgb([37, 38, 39]));
    }

    #[bench]
    fn bench_weighted_sum_rgb(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Rgb([10u8, 20u8, 33u8]));
            let right = black_box(Rgb([80u8, 70u8, 60u8]));
            let left_weight = black_box(0.3);
            let right_weight = black_box(0.7);
            black_box(weighted_sum(left, right, left_weight, right_weight));
        })
    }

    #[bench]
    fn bench_weighted_sum_gray(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Luma([10u8]));
            let right = black_box(Luma([80u8]));
            let left_weight = black_box(0.3);
            let right_weight = black_box(0.7);
            black_box(weighted_sum(left, right, left_weight, right_weight));
        })
    }

    #[bench]
    fn bench_interpolate_rgb(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Rgb([10u8, 20u8, 33u8]));
            let right = black_box(Rgb([80u8, 70u8, 60u8]));
            let left_weight = black_box(0.3);
            black_box(interpolate(left, right, left_weight));
        })
    }

    #[bench]
    fn bench_interpolate_gray(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Luma([10u8]));
            let right = black_box(Luma([80u8]));
            let left_weight = black_box(0.3);
            black_box(interpolate(left, right, left_weight));
        })
    }
}
<commit_msg>Fix typo in interpolate doc comment<commit_after>//! Pixel manipulations.

use image::Pixel;
use conv::ValueInto;
use math::cast;
use definitions::Clamp;

/// Adds pixels with the given weights. Results are clamped to prevent arithmetical overflows.
pub fn weighted_sum<P: Pixel>(left: P, right: P, left_weight: f32, right_weight: f32) -> P
where
    P::Subpixel: ValueInto<f32> + Clamp<f32>,
{
    left.map2(&right, |p, q| {
        weighted_channel_sum(p, q, left_weight, right_weight)
    })
}

/// Equivalent to `weighted_sum(left, right, left_weight, 1 - left_weight)`.
pub fn interpolate<P: Pixel>(left: P, right: P, left_weight: f32) -> P
where
    P::Subpixel: ValueInto<f32> + Clamp<f32>,
{
    weighted_sum(left, right, left_weight, 1.0 - left_weight)
}

#[inline(always)]
fn weighted_channel_sum<C>(left: C, right: C, left_weight: f32, right_weight: f32) -> C
where
    C: ValueInto<f32> + Clamp<f32>,
{
    Clamp::clamp(cast(left) * left_weight + cast(right) * right_weight)
}

#[cfg(test)]
mod test {
    use super::*;
    use image::{Rgb, Luma};
    use test::{Bencher, black_box};

    #[test]
    fn test_weighted_channel_sum() {
        // Midpoint
        assert_eq!(weighted_channel_sum(10u8, 20u8, 0.5, 0.5), 15u8);
        // Mainly left
        assert_eq!(weighted_channel_sum(10u8, 20u8, 0.9, 0.1), 11u8);
        // Clamped
        assert_eq!(weighted_channel_sum(150u8, 150u8, 1.8, 0.8), 255u8);
    }

    #[test]
    fn test_weighted_sum() {
        let left = Rgb([10u8, 20u8, 30u8]);
        let right = Rgb([100u8, 80u8, 60u8]);
        let sum = weighted_sum(left, right, 0.7, 0.3);
        assert_eq!(sum, Rgb([37, 38, 39]));
    }

    #[bench]
    fn bench_weighted_sum_rgb(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Rgb([10u8, 20u8, 33u8]));
            let right = black_box(Rgb([80u8, 70u8, 60u8]));
            let left_weight = black_box(0.3);
            let right_weight = black_box(0.7);
            black_box(weighted_sum(left, right, left_weight, right_weight));
        })
    }

    #[bench]
    fn bench_weighted_sum_gray(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Luma([10u8]));
            let right = black_box(Luma([80u8]));
            let left_weight = black_box(0.3);
            let right_weight = black_box(0.7);
            black_box(weighted_sum(left, right, left_weight, right_weight));
        })
    }

    #[bench]
    fn bench_interpolate_rgb(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Rgb([10u8, 20u8, 33u8]));
            let right = black_box(Rgb([80u8, 70u8, 60u8]));
            let left_weight = black_box(0.3);
            black_box(interpolate(left, right, left_weight));
        })
    }

    #[bench]
    fn bench_interpolate_gray(b: &mut Bencher) {
        b.iter(|| {
            let left = black_box(Luma([10u8]));
            let right = black_box(Luma([80u8]));
            let left_weight = black_box(0.3);
            black_box(interpolate(left, right, left_weight));
        })
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::io::{self, BufReader, Result};
use std::io::prelude::*;
use std::fs::File;
use std::collections::HashMap;
use std::cmp::{Ord, Ordering};
use std::process::exit;

struct Node {
    sources: Vec<usize>,
    targets: Vec<usize>,
    name: String,
}

struct Link {
    sourceNode: String,
    targetNode: String,
    resistence: u16,
}

impl Node {
    fn new(name: String) -> Node {
        Node { name: name, sources: Vec::new(), targets: Vec::new() }
    }

    fn add_source(&mut self, link: usize) {
        self.sources.push(link);
    }

    fn add_target(&mut self, link: usize) {
        self.targets.push(link);
    }
}

impl Link {
    fn new(resistence: u16, sourceNode: String, targetNode: String) -> Link {
        Link { resistence: resistence, sourceNode: sourceNode, targetNode: targetNode }
    }

    fn set_resistance(&mut self, resistence: u16) {
        self.resistence = resistence;
    }
}

fn create_nodes(line: &String) -> HashMap<String, Node> {
   let mut node_map = HashMap::new();
            let nodes = line.split_whitespace();
            for n in nodes {
                let node_name = n.to_string();
                node_map.insert(node_name.to_string(), Node::new(node_name.to_string()));
                // start = match start.cmp(&node_name) {
                //    Ordering::Less | Ordering::Equal => start,
                //    Ordering::Greater => node_name,
                // };
            }
            return node_map;
}

fn run() -> Result<()> {
    // let mut start = String::from("~");
    let a: Vec<String> = env::args().collect();
    if a.len() != 2 {
        try!(std::io::stderr().write(b"Command must be called with file containing resistance description\n"));
        exit(1);
    }

    let f = try!(File::open(&a[1]));
    let reader = BufReader::new(f);

    let mut i: u8 = 0;
    let mut node_map = HashMap::new();
    let mut link_list = Vec::new();
    for line in reader.lines() {
        let line: String = try!(line);
        println!("[{}] - {}", i, line);
        if i == 0 {
            node_map = create_nodes(&line);
        } else {
            let node_details: Vec<&str> = line.split_whitespace().collect();
            let node1_name = node_details[0].to_string();
            let node2_name = node_details[1].to_string();
            let mut node1: Node;
            let mut node2: Node;
            match node_map.remove(&node1_name) {
                Some(n) => node1 = n,
                None => {
                    try!(write!(std::io::stderr(), "Unable to find node {}!\n", &node1_name));
                    exit(1);
                },
            };
            match node_map.remove(&node2_name) {
                Some(n) => node2 = n,
                None => {
                    try!(write!(std::io::stderr(), "Unable to find node {}!\n", &node2_name));
                    exit(1);
                },
            };
            let resistence = node_details[2].parse::<u16>().unwrap();
            match node1.name.cmp(&node2.name) {
                Ordering::Less | Ordering::Equal => {
                    let l = Link::new(resistence, node1_name.to_owned(), node2_name.to_owned());
                    link_list.push(l);

                    node1.add_target(link_list.len());
                    node2.add_source(link_list.len());
                },
                Ordering::Greater => {
                    let l = Link::new(resistence, node2_name.to_owned(), node1_name.to_owned());
                    link_list.push(l);

                    node2.add_target(link_list.len());
                    node1.add_source(link_list.len());
                },
            }
            node_map.insert(node1_name, node1);
            node_map.insert(node2_name, node2);
        }
        i += 1;
    }
    // println!("Will start with node [{}]", start);
    for (key, value) in node_map {
        println!("{}", key);
    }
    Ok(())
}

fn process_node(node: &mut Node) {
    if node.targets.len() == 1 {
        if node.sources.len() == 1 {
            return;
        } // else if node.targets[0].targetNode.sources.len() == 1 && node.targets[0].targetNode.targets.len() == 1 {
            // let link = Link::new(node.targets[0].resistence + node.targets[0].targetNode.targets[0].resistence, node, node.targets[0].targetNode.targets[0].targetNode);
            // node.targets[0].targetNode.targets[0].targetNode.sources[0] = &link;
            // node.targets[0] = link;
        // }
    }
}

fn main() {
    match run() {
        Ok(_) => exit(0),
        Err(e) => println!("Error! {}", e.to_string()),
    }
}
<commit_msg>Compiles for real.<commit_after>use std::env;
use std::io::{self, BufReader, Result};
use std::io::prelude::*;
use std::fs::File;
use std::collections::HashMap;
use std::cmp::{Ord, Ordering};
use std::process::exit;

struct Grid {
    node_map: HashMap<String, Node>,
    link_list: Vec<Link>,
}

impl Grid {
    fn new(line: String) -> Grid {
        let mut node_map = HashMap::new();
        let nodes = line.split_whitespace();
        for n in nodes {
            node_map.insert(n.to_string(), Node::new(n.to_string()));
        }
        Grid { node_map: node_map, link_list: Vec::new() }
    }

    fn parse_line(&mut self, line: String) -> Result<()> {
        let node_details: Vec<&str> = line.split_whitespace().collect();
        let node1_name = node_details[0].to_string();
        let node2_name = node_details[1].to_string();
        let mut node1: Node;
        let mut node2: Node;
        match self.node_map.remove(&node1_name) {
            Some(n) => node1 = n,
            None => {
                try!(write!(std::io::stderr(), "Unable to find node {}!\n", &node1_name));
                exit(1);
            },
        };
        match self.node_map.remove(&node2_name) {
            Some(n) => node2 = n,
            None => {
                try!(write!(std::io::stderr(), "Unable to find node {}!\n", &node2_name));
                exit(1);
            },
        };
        let resistence = node_details[2].parse::<u16>().unwrap();
        match node1.name.cmp(&node2.name) {
            Ordering::Less | Ordering::Equal => {
                self.link_list.push(Link::new(resistence, node1_name.to_owned(), node2_name.to_owned()));

                node1.add_target(self.link_list.len());
                node2.add_source(self.link_list.len());
            },
            Ordering::Greater => {
                self.link_list.push(Link::new(resistence, node2_name.to_owned(), node1_name.to_owned()));

                node2.add_target(self.link_list.len());
                node1.add_source(self.link_list.len());
            },
        }
        self.node_map.insert(node1_name, node1);
        self.node_map.insert(node2_name, node2);
        Ok(())
    }
}

struct Node {
    sources: Vec<usize>,
    targets: Vec<usize>,
    name: String,
}

struct Link {
    sourceNode: String,
    targetNode: String,
    resistence: u16,
}

impl Node {
    fn new(name: String) -> Node {
        Node { name: name, sources: Vec::new(), targets: Vec::new() }
    }

    fn add_source(&mut self, link: usize) {
        self.sources.push(link);
    }

    fn add_target(&mut self, link: usize) {
        self.targets.push(link);
    }
}

impl Link {
    fn new(resistence: u16, sourceNode: String, targetNode: String) -> Link {
        Link { resistence: resistence, sourceNode: sourceNode, targetNode: targetNode }
    }

    fn set_resistance(&mut self, resistence: u16) {
        self.resistence = resistence;
    }
}

fn run() -> Result<()> {
    let a: Vec<String> = env::args().collect();
    if a.len() != 2 {
        try!(std::io::stderr().write(b"Command must be called with file containing resistance description\n"));
        exit(1);
    }

    let f = try!(File::open(&a[1]));
    let reader = BufReader::new(f);

    let mut i: u8 = 0;
    let mut header;
    let mut lines = Vec::new();
    for line in reader.lines() {
        let line: String = try!(line);
        println!("[{}] - {}", i, line);
        if i == 0 {
            header = line;
        } else {
            lines.push(line);
        }
        i += 1;
    }
    // println!("Will start with node [{}]", start);
//    for (key, value) in node_map {
//        println!("{}", key);
//    }
    Ok(())
}

fn process_node(node: &mut Node) {
//    if node.targets.len() == 1 {
//        if node.sources.len() == 1 {
//            return;
//        } else if node.targets[0].targetNode.sources.len() == 1 && node.targets[0].targetNode.targets.len() == 1 {
//            let link = Link::new(node.targets[0].resistence + node.targets[0].targetNode.targets[0].resistence, node, node.targets[0].targetNode.targets[0].targetNode);
//            node.targets[0].targetNode.targets[0].targetNode.sources[0] = &link;
//            node.targets[0] = link;
//        }
//    }
}

fn main() {
    match run() {
        Ok(_) => exit(0),
        Err(e) => println!("Error! {}", e.to_string()),
    }
}
<|endoftext|>


<commit_before>use log_parser::log_events::HttpError;

#[derive(PartialEq, Debug)]
pub struct ErrorRatesResult {
    pub client_error_4xx: f32,
    pub server_error_5xx: f32,
}

pub trait HttpErrorState {
    fn error(&self) -> Option<HttpError>;
}

pub fn analyze<T>(statuses: &Vec<T>) -> Option<ErrorRatesResult>
    where T: HttpErrorState
{
    if statuses.is_empty() {
        return None;
    }

    let total_count = statuses.len() as f32;

    let client_error_4xx_count = statuses.iter()
        .map(|status| status.error())
        .filter(|status| *status == Some(HttpError::ClientError4xx))
        .count() as f32;

    let server_error_5xx_count = statuses.iter()
        .map(|status| status.error())
        .filter(|status| *status == Some(HttpError::ServerError5xx))
        .count() as f32;

    let client_error_4xx_rate = (client_error_4xx_count / total_count * 10000.0).round() / 10000.0;
    let server_error_4xx_rate = (server_error_5xx_count / total_count * 10000.0).round() / 10000.0;

    Some(ErrorRatesResult {
        client_error_4xx: client_error_4xx_rate,
        server_error_5xx: server_error_4xx_rate,
    })

}

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

    impl HttpErrorState for String {
        fn error(&self) -> Option<HttpError> {
            match self.chars().nth(0) {
                Some('4') => Some(HttpError::ClientError4xx),
                Some('5') => Some(HttpError::ServerError5xx),
                _ => None,
            }
        }
    }

    #[test]
    fn test_analyze_all_ok() {
        let statuses: Vec<String> = vec![String::from("200")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.0,
            server_error_5xx: 0.0,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_50_percent_client_errors() {
        let statuses: Vec<String> = vec![String::from("200"), String::from("403")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.5,
            server_error_5xx: 0.0,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_50_percent_server_errors() {
        let statuses: Vec<String> = vec![String::from("200"), String::from("500")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.0,
            server_error_5xx: 0.5,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_mixed_errors() {
        let statuses: Vec<String> = vec![String::from("404"),
                                         String::from("200"),
                                         String::from("500"),
                                         String::from("204")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.25,
            server_error_5xx: 0.25,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_empty() {
        let statuses: Vec<String> = vec![];

        let result = analyze(&statuses);

        let expected = None;

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_rounding() {
        let statuses: Vec<String> =
            vec![String::from("404"), String::from("200"), String::from("500")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.3333,
            server_error_5xx: 0.3333,
        });

        assert_eq!(result, expected);
    }
}
<commit_msg>Clippy: allow any slice, not only Vec<commit_after>use log_parser::log_events::HttpError;

#[derive(PartialEq, Debug)]
pub struct ErrorRatesResult {
    pub client_error_4xx: f32,
    pub server_error_5xx: f32,
}

pub trait HttpErrorState {
    fn error(&self) -> Option<HttpError>;
}

pub fn analyze<T>(statuses: &[T]) -> Option<ErrorRatesResult>
    where T: HttpErrorState
{
    if statuses.is_empty() {
        return None;
    }

    let total_count = statuses.len() as f32;

    let client_error_4xx_count = statuses.iter()
        .map(|status| status.error())
        .filter(|status| *status == Some(HttpError::ClientError4xx))
        .count() as f32;

    let server_error_5xx_count = statuses.iter()
        .map(|status| status.error())
        .filter(|status| *status == Some(HttpError::ServerError5xx))
        .count() as f32;

    let client_error_4xx_rate = (client_error_4xx_count / total_count * 10000.0).round() / 10000.0;
    let server_error_4xx_rate = (server_error_5xx_count / total_count * 10000.0).round() / 10000.0;

    Some(ErrorRatesResult {
        client_error_4xx: client_error_4xx_rate,
        server_error_5xx: server_error_4xx_rate,
    })

}

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

    impl HttpErrorState for String {
        fn error(&self) -> Option<HttpError> {
            match self.chars().nth(0) {
                Some('4') => Some(HttpError::ClientError4xx),
                Some('5') => Some(HttpError::ServerError5xx),
                _ => None,
            }
        }
    }

    #[test]
    fn test_analyze_all_ok() {
        let statuses: Vec<String> = vec![String::from("200")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.0,
            server_error_5xx: 0.0,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_50_percent_client_errors() {
        let statuses: Vec<String> = vec![String::from("200"), String::from("403")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.5,
            server_error_5xx: 0.0,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_50_percent_server_errors() {
        let statuses: Vec<String> = vec![String::from("200"), String::from("500")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.0,
            server_error_5xx: 0.5,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_mixed_errors() {
        let statuses: Vec<String> = vec![String::from("404"),
                                         String::from("200"),
                                         String::from("500"),
                                         String::from("204")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.25,
            server_error_5xx: 0.25,
        });

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_empty() {
        let statuses: Vec<String> = vec![];

        let result = analyze(&statuses);

        let expected = None;

        assert_eq!(result, expected);
    }

    #[test]
    fn test_analyze_rounding() {
        let statuses: Vec<String> =
            vec![String::from("404"), String::from("200"), String::from("500")];

        let result = analyze(&statuses);

        let expected = Some(ErrorRatesResult {
            client_error_4xx: 0.3333,
            server_error_5xx: 0.3333,
        });

        assert_eq!(result, expected);
    }
}
<|endoftext|>


<commit_before>use super::*;
use crate::types::ToolchainBoundedSpecifier;
use envmnt;

fn get_test_env_toolchain() -> ToolchainSpecifier {
    let channel = envmnt::get_or_panic("CARGO_MAKE_RUST_CHANNEL");
    let version = envmnt::get_or_panic("CARGO_MAKE_RUST_VERSION");

    ToolchainSpecifier::Bounded(ToolchainBoundedSpecifier {
        channel,
        min_version: version,
    })
}

#[test]
#[should_panic]
fn wrap_command_invalid_toolchain() {
    wrap_command(&"invalid-chain".into(), "true", &None);
}

#[test]
#[should_panic]
fn wrap_command_unreachable_version() {
    let toolchain = ToolchainSpecifier::Bounded(ToolchainBoundedSpecifier {
        channel: envmnt::get_or_panic("CARGO_MAKE_RUST_CHANNEL"),
        min_version: "9999.9.9".to_string(), // If we ever reach this version, add another 9
    });
    wrap_command(&toolchain, "true", &None);
}

#[test]
fn wrap_command_none_args() {
    let toolchain = get_test_env_toolchain();
    let output = wrap_command(&toolchain, "true", &None);

    assert_eq!(output.command, "rustup".to_string());

    let args = output.args.unwrap();
    assert_eq!(args.len(), 3);
    assert_eq!(args[0], "run".to_string());
    assert_eq!(args[1], toolchain.channel());
    assert_eq!(args[2], "true".to_string());
}

#[test]
fn wrap_command_empty_args() {
    let toolchain = get_test_env_toolchain();
    let output = wrap_command(&toolchain, "true", &Some(vec![]));

    assert_eq!(output.command, "rustup".to_string());

    let args = output.args.unwrap();
    assert_eq!(args.len(), 3);
    assert_eq!(args[0], "run".to_string());
    assert_eq!(args[1], toolchain.channel());
    assert_eq!(args[2], "true".to_string());
}

#[test]
fn wrap_command_with_args() {
    let toolchain = get_test_env_toolchain();
    let output = wrap_command(
        &toolchain,
        "true",
        &Some(vec!["echo".to_string(), "test".to_string()]),
    );

    assert_eq!(output.command, "rustup".to_string());

    let args = output.args.unwrap();
    assert_eq!(args.len(), 5);
    assert_eq!(args[0], "run".to_string());
    assert_eq!(args[1], toolchain.channel());
    assert_eq!(args[2], "true".to_string());
    assert_eq!(args[3], "echo".to_string());
    assert_eq!(args[4], "test".to_string());
}

#[test]
fn get_cargo_binary_path_valid() {
    let toolchain = get_test_env_toolchain();
    let binary_path = get_cargo_binary_path(&toolchain);

    assert!(binary_path.is_some());
    let binary_path_value = binary_path.unwrap();
    assert!(binary_path_value.find("bin").is_some());
    assert!(binary_path_value.find("cargo").is_some());
}

#[test]
fn remove_rust_env_vars_existed() {
    envmnt::set("RUSTC", "bad1");
    envmnt::set("RUSTDOC", "bad2");
    envmnt::set("RUSTFLAGS", "bad3");

    assert!(envmnt::exists("RUSTC"));
    assert!(envmnt::exists("RUSTDOC"));
    assert!(envmnt::exists("RUSTFLAGS"));

    remove_rust_env_vars();

    assert!(!envmnt::exists("RUSTC"));
    assert!(!envmnt::exists("RUSTDOC"));
    assert!(!envmnt::exists("RUSTFLAGS"));
}
<commit_msg>test stability<commit_after>use super::*;
use crate::types::ToolchainBoundedSpecifier;
use envmnt;

fn get_test_env_toolchain() -> ToolchainSpecifier {
    let channel = envmnt::get_or_panic("CARGO_MAKE_RUST_CHANNEL");
    let version = envmnt::get_or_panic("CARGO_MAKE_RUST_VERSION");

    ToolchainSpecifier::Bounded(ToolchainBoundedSpecifier {
        channel,
        min_version: version,
    })
}

#[test]
#[should_panic]
fn wrap_command_invalid_toolchain() {
    wrap_command(&"invalid-chain".into(), "true", &None);
}

#[test]
#[should_panic]
fn wrap_command_unreachable_version() {
    let toolchain = ToolchainSpecifier::Bounded(ToolchainBoundedSpecifier {
        channel: envmnt::get_or_panic("CARGO_MAKE_RUST_CHANNEL"),
        min_version: "9999.9.9".to_string(), // If we ever reach this version, add another 9
    });
    wrap_command(&toolchain, "true", &None);
}

#[test]
fn wrap_command_none_args() {
    let toolchain = get_test_env_toolchain();
    let output = wrap_command(&toolchain, "true", &None);

    assert_eq!(output.command, "rustup".to_string());

    let args = output.args.unwrap();
    assert_eq!(args.len(), 3);
    assert_eq!(args[0], "run".to_string());
    assert_eq!(args[1], toolchain.channel());
    assert_eq!(args[2], "true".to_string());
}

#[test]
fn wrap_command_empty_args() {
    let toolchain = get_test_env_toolchain();
    let output = wrap_command(&toolchain, "true", &Some(vec![]));

    assert_eq!(output.command, "rustup".to_string());

    let args = output.args.unwrap();
    assert_eq!(args.len(), 3);
    assert_eq!(args[0], "run".to_string());
    assert_eq!(args[1], toolchain.channel());
    assert_eq!(args[2], "true".to_string());
}

#[test]
fn wrap_command_with_args() {
    let toolchain = get_test_env_toolchain();
    let output = wrap_command(
        &toolchain,
        "true",
        &Some(vec!["echo".to_string(), "test".to_string()]),
    );

    assert_eq!(output.command, "rustup".to_string());

    let args = output.args.unwrap();
    assert_eq!(args.len(), 5);
    assert_eq!(args[0], "run".to_string());
    assert_eq!(args[1], toolchain.channel());
    assert_eq!(args[2], "true".to_string());
    assert_eq!(args[3], "echo".to_string());
    assert_eq!(args[4], "test".to_string());
}

#[test]
fn get_cargo_binary_path_valid() {
    let toolchain = get_test_env_toolchain();
    let binary_path = get_cargo_binary_path(&toolchain);

    assert!(binary_path.is_some());
    let binary_path_value = binary_path.unwrap();
    assert!(binary_path_value.find("bin").is_some());
    assert!(binary_path_value.find("cargo").is_some());
}

#[test]
#[ignore]
fn remove_rust_env_vars_existed() {
    envmnt::set("RUSTC", "bad1");
    envmnt::set("RUSTDOC", "bad2");
    envmnt::set("RUSTFLAGS", "bad3");

    assert!(envmnt::exists("RUSTC"));
    assert!(envmnt::exists("RUSTDOC"));
    assert!(envmnt::exists("RUSTFLAGS"));

    remove_rust_env_vars();

    assert!(!envmnt::exists("RUSTC"));
    assert!(!envmnt::exists("RUSTDOC"));
    assert!(!envmnt::exists("RUSTFLAGS"));
}
<|endoftext|>


<commit_before>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use std::ops::{
    Mul,
};
use default::Default;
use vector::Vector;
use matrix_vector::ops::*;
use matrix::Matrix;
use math::Trans;
use math::Mat;

impl<'a, T, V> Mul<&'a V> for &'a Matrix<T>
    where T: Default + Copy + Gemv,
          V: Vector<T>,
{
    type Output = Vec<T>;

    fn mul(self, x: &'a V) -> Vec<T> {
        let n = self.rows() as usize;
        let mut result = Vec::with_capacity(n);
        unsafe { result.set_len(n); }
        let scale = Default::one();
        let clear = Default::zero();

        Gemv::gemv(&scale, self, x, &clear, &mut result);
        result
    }
}

impl<'a, T> Mul<Trans<&'a Vector<T>>> for &'a Vector<T>
    where T: Default + Ger + Gerc + Clone,
{
    type Output = Mat<T>;

    fn mul(self, x: Trans<&'a Vector<T>>) -> Mat<T> {
        let n = self.len() as usize;
        let m = (*x).len() as usize;
        let mut result = Mat::fill(Default::zero(), n, m);
        let scale = Default::one();

        match x {
            Trans::T(v) => Ger::ger(&scale, self, v, &mut result),
            Trans::H(v) => Gerc::gerc(&scale, self, v, &mut result),
        }

        result
    }
}

#[cfg(test)]
mod tests {
    use Vector;
    use Matrix;

    #[test]
    fn mul() {
        let a = (2, 2, vec![2.0, -2.0, 2.0, -4.0]);
        let x = vec![2.0, 1.0];

        let y = {
            let ar = &a as &Matrix<_>;
            ar * &x
        };

        assert_eq!(y, vec![2.0, 0.0]);
    }
}
<commit_msg>Test outer product<commit_after>// Copyright 2015 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

use std::ops::{
    Mul,
};
use default::Default;
use vector::Vector;
use matrix_vector::ops::*;
use matrix::Matrix;
use math::Trans;
use math::Mat;

impl<'a, T, V> Mul<&'a V> for &'a Matrix<T>
    where T: Default + Copy + Gemv,
          V: Vector<T>,
{
    type Output = Vec<T>;

    fn mul(self, x: &'a V) -> Vec<T> {
        let n = self.rows() as usize;
        let mut result = Vec::with_capacity(n);
        unsafe { result.set_len(n); }
        let scale = Default::one();
        let clear = Default::zero();

        Gemv::gemv(&scale, self, x, &clear, &mut result);
        result
    }
}

impl<'a, T> Mul<Trans<&'a Vector<T>>> for &'a Vector<T>
    where T: Default + Ger + Gerc + Clone,
{
    type Output = Mat<T>;

    fn mul(self, x: Trans<&'a Vector<T>>) -> Mat<T> {
        let n = self.len() as usize;
        let m = (*x).len() as usize;
        let mut result = Mat::fill(Default::zero(), n, m);
        let scale = Default::one();

        match x {
            Trans::T(v) => Ger::ger(&scale, self, v, &mut result),
            Trans::H(v) => Gerc::gerc(&scale, self, v, &mut result),
        }

        result
    }
}

#[cfg(test)]
mod tests {
    use Vector;
    use Matrix;
    use math::Mat;
    use math::Marker::T;

    #[test]
    fn mul() {
        let a = (2, 2, vec![2.0, -2.0, 2.0, -4.0]);
        let x = vec![2.0, 1.0];

        let y = {
            let ar = &a as &Matrix<_>;
            ar * &x
        };

        assert_eq!(y, vec![2.0, 0.0]);
    }

    #[test]
    fn outer() {
        let x = vec![2.0, 1.0, 4.0];
        let y = vec![3.0, 6.0, -1.0];

        let a = {
            let xr = &x as &Vector<_>;
            let yr = &y as &Vector<_>;

            xr * (yr ^ T)
        };

        let result = mat![  6.0, 12.0, -2.0;
                            3.0, 6.0, -1.0;
                            12.0, 24.0, -4.0];
        assert_eq!(a, result);
    }
}
<|endoftext|>


<commit_before>use memory::Memory;
use std::boxed::Box;
use std::vec::Vec;

/// Simple slice-based memory implementation.
///
/// # Examples
/// ```
/// use osciemu::memory::Memory;
/// use osciemu::memory::SliceMemory;
///
/// let mut m = SliceMemory::new(16);
/// assert_eq!(m.get(0), 0);
/// m.set(8, 123);
/// assert_eq!(m.get(8), 123);
/// ```
///
/// # Panics
/// Just a slice, `SliceMemory` panics when accessed out of bounds.
///
/// ```
/// # use std::panic;
/// # use osciemu::memory::Memory;
/// # use osciemu::memory::SliceMemory;
/// let mut m = SliceMemory::new(16);
/// let result = panic::catch_unwind(|| {
///     m.get(17); // Out-of-bounds!
/// });
/// assert!(result.is_err());
/// ```
pub struct SliceMemory(Box<[u32]>);

impl SliceMemory {
    pub fn new(size: usize) -> SliceMemory {
        let mut v = Vec::with_capacity(size);
        for _ in 0..size {
            v.push(0)
        }
        SliceMemory(v.into_boxed_slice())
    }
}

impl Memory for SliceMemory {
    fn get(&self, addr: usize) -> u32 {
        let &SliceMemory(ref b) = self;
        b[addr]
    }
    fn set(&mut self, addr: usize, v: u32) {
        let &mut SliceMemory(ref mut b) = self;
        b[addr] = v;
    }
    fn size(&self) -> usize {
        let &SliceMemory(ref b) = self;
        b.len()
    }
}

#[cfg(test)]
mod test {
    use memory::Memory;

    #[test]
    fn slicememory() {
        let mut m = super::SliceMemory::new(16);
        for i in 0..16 {
            m.set(i, i as u32);
        }
        for i in 0..16 {
            assert_eq!(m.get(i), i as u32);
        }
    }
}
<commit_msg>style(slicememory): I learned how to access tuple structs<commit_after>use memory::Memory;
use std::boxed::Box;
use std::vec::Vec;

/// Simple slice-based memory implementation.
///
/// # Examples
/// ```
/// use osciemu::memory::Memory;
/// use osciemu::memory::SliceMemory;
///
/// let mut m = SliceMemory::new(16);
/// assert_eq!(m.get(0), 0);
/// m.set(8, 123);
/// assert_eq!(m.get(8), 123);
/// ```
///
/// # Panics
/// Just a slice, `SliceMemory` panics when accessed out of bounds.
///
/// ```
/// # use std::panic;
/// # use osciemu::memory::Memory;
/// # use osciemu::memory::SliceMemory;
/// let mut m = SliceMemory::new(16);
/// let result = panic::catch_unwind(|| {
///     m.get(17); // Out-of-bounds!
/// });
/// assert!(result.is_err());
/// ```
pub struct SliceMemory(Box<[u32]>);

impl SliceMemory {
    pub fn new(size: usize) -> SliceMemory {
        let mut v = Vec::with_capacity(size);
        for _ in 0..size {
            v.push(0)
        }
        SliceMemory(v.into_boxed_slice())
    }
}

impl Memory for SliceMemory {
    fn get(&self, addr: usize) -> u32 {
        self.0[addr]
    }
    fn set(&mut self, addr: usize, v: u32) {
        self.0[addr] = v;
    }
    fn size(&self) -> usize {
        self.0.len()
    }
}

#[cfg(test)]
mod test {
    use memory::Memory;

    #[test]
    fn get_and_set() {
        let mut m = super::SliceMemory::new(16);
        for i in 0..16 {
            m.set(i, i as u32);
        }
        for i in 0..16 {
            assert_eq!(m.get(i), i as u32);
        }
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use std::sync::mpsc::channel;
use std::thread::spawn;

static NTHREADS: i32 = 4;

// Description: Count how many of N uniform draws from a unit square fall
//              within a unit circle
// Input: number of trials to perform, drawing two floats from [0, 1)
// Output: number of trials that fell within the unit circle
fn monte_carlo_circle(n: i32) -> i32 {
    let mut num_in_circle = 0;
    for _ in 1..n {
        let x = rand::random::<f32>();
        let y = rand::random::<f32>();
        if x * x + y * y < 1. {
            num_in_circle += 1;
        }
    }
    num_in_circle
}

fn main() {
    let n = 10000000;

    // Spawn threads to split up the work. Communicate via a channel, which
    // is a thread-safe, multi-writer, single-reader FIFO.
    let (tx, rx) = channel();
    let chunk_size = n / NTHREADS;
    let mut threads = Vec::with_capacity(NTHREADS as usize);
    for _ in 0..NTHREADS {
        let tx_thread = tx.clone();
        let handle = spawn(move || tx_thread.send(monte_carlo_circle(chunk_size)));
        threads.push(handle);
    }

    // Grab results from the channel and sum them back up.
    let mut total_in_circle = 0;
    for _ in 0..NTHREADS {
        total_in_circle += rx.recv().unwrap();
    }

    // Destroy threads
    while let Some(thread) = threads.pop() {
        thread.join().ok();
    }
    let pi = 4. * total_in_circle as f32 / n as f32;

    println!("π is approximately {}", pi);
}
<commit_msg>don't need explicit thread join, as threads terminate on function return<commit_after>extern crate rand;

use std::sync::mpsc::channel;
use std::thread::spawn;

static NTHREADS: i32 = 4;

// Description: Count how many of N uniform draws from a unit square fall
//              within a unit circle
// Input: number of trials to perform, drawing two floats from [0, 1)
// Output: number of trials that fell within the unit circle
fn monte_carlo_circle(n: i32) -> i32 {
    let mut num_in_circle = 0;
    for _ in 1..n {
        let x = rand::random::<f32>();
        let y = rand::random::<f32>();
        if x * x + y * y < 1. {
            num_in_circle += 1;
        }
    }
    num_in_circle
}

fn main() {
    let n = 10000000;

    // Spawn threads to split up the work. Communicate via a channel, which
    // is a thread-safe, multi-writer, single-reader FIFO.
    let (tx, rx) = channel();
    let chunk_size = n / NTHREADS;
    for _ in 0..NTHREADS {
        let tx_thread = tx.clone();
        spawn(move || tx_thread.send(monte_carlo_circle(chunk_size)));
    }

    // Grab results from the channel and sum them back up.
    let mut total_in_circle = 0;
    for _ in 0..NTHREADS {
        total_in_circle += rx.recv().unwrap();
    }

    let pi = 4. * total_in_circle as f32 / n as f32;
    println!("π is approximately {}", pi);
}
<|endoftext|>


<commit_before>/* Copyright 2016 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#[macro_use]
extern crate clear_coat;
extern crate iup_sys;
extern crate smallvec;

use std::rc::Rc;
use iup_sys::*;
use smallvec::SmallVec;

use clear_coat::*;
use clear_coat::common_attrs_cbs::*;

struct CursorsCanvas {
    canvas: Canvas,
}

impl CursorsCanvas {
    pub fn new() -> Self {
        CursorsCanvas {
            canvas: Canvas::new(),
        }
    }
}

impl CursorAttribute for CursorsCanvas {}

unsafe impl Control for CursorsCanvas {
    fn handle(&self) -> *mut Ihandle {
        self.canvas.handle()
    }
}

fn create_cursors_page() -> Box<Control> {
    let cursors_canvas = Rc::new(CursorsCanvas::new());

    let radios_info = [
        ("None", Cursor::None),
        ("Arrow", Cursor::Arrow),
        ("Busy", Cursor::Busy),
        ("Cross", Cursor::Cross),
        ("Hand", Cursor::Hand),
        ("Help", Cursor::Help),
        ("Move", Cursor::Move),
        ("ResizeN", Cursor::ResizeN),
        ("ResizeS", Cursor::ResizeS),
        ("ResizeNS", Cursor::ResizeNS),
        ("ResizeW", Cursor::ResizeW),
        ("ResizeE", Cursor::ResizeE),
        ("ResizeWE", Cursor::ResizeWE),
        ("ResizeNE", Cursor::ResizeNE),
        ("ResizeSW", Cursor::ResizeSW),
        ("ResizeNW", Cursor::ResizeNW),
        ("ResizeSE", Cursor::ResizeSE),
        ("Text", Cursor::Text),
    ];

    let mut radios = SmallVec::<[Toggle; 32]>::new();
    for &(text, cur) in radios_info.iter() {
        let toggle = Toggle::new();
        toggle.set_title(text);
        let cursors_canvas2 = cursors_canvas.clone();
        toggle.action_event().add(move |checked| {
            if checked { cursors_canvas2.set_cursor(cur); }
        });
        radios.push(toggle);
    }
    // The arrow cursor is the default.
    radios[1].set_on(true);

    let grid = grid_box!(
        &radios[0],
        &radios[1],
        &radios[2],
        &radios[3],
        &radios[4],
        &radios[5],
        &radios[6],
        &radios[7],
        &radios[8],
        &radios[9],
        &radios[10],
        &radios[11],
        &radios[12],
        &radios[13],
        &radios[14],
        &radios[15],
        &radios[16],
        &radios[17],
    );
    grid.set_num_div(NumDiv::Fixed(2));
    grid.fit_all_to_children();
    let page = vbox!(
        &cursors_canvas,
        hbox!(
            fill!(),
            Radio::with_child(&grid),
            fill!(),
        ),
    );
    Box::new(page)
}

fn create_file_dialog_page() -> Box<Control> {
    let type_check_box = Toggle::new();
    type_check_box.set_title("Dialog Type:");

    let open_radio = Toggle::new();
    open_radio.set_title("Open");
    let save_radio = Toggle::new();
    save_radio.set_title("Save");
    let dir_radio = Toggle::new();
    dir_radio.set_title("Directory");
    let type_radio = Radio::with_child(&vbox!(
        &open_radio,
        &save_radio,
        &dir_radio,
    ));

    let dir_check_box = Toggle::new();
    dir_check_box.set_title("Directory:");

    let dir_text_box = Text::new();

    let multiple_files_check_box = Toggle::new();
    multiple_files_check_box.set_title("Multiple Files");

    let show_dialog = Button::with_title("Show Dialog");

    let type_check_box_capt = type_check_box.clone();
    let open_radio_capt = open_radio.clone();
    let save_radio_capt = save_radio.clone();
    let dir_check_box_capt = dir_check_box.clone();
    let dir_text_box_capt = dir_text_box.clone();
    let multiple_files_check_box_capt = multiple_files_check_box.clone();
    show_dialog.action_event().add(move || {
        let dialog = FileDlg::new();
        if type_check_box_capt.is_on() {
            dialog.set_dialog_type(if open_radio_capt.is_on() {
                FileDialogType::Open
            } else if save_radio_capt.is_on() {
                FileDialogType::Save
            } else {
                FileDialogType::Dir
            })
        }
        if dir_check_box_capt.is_on() {
            dialog.set_directory(&dir_text_box_capt.value());
        }
        if multiple_files_check_box_capt.is_on() {
            dialog.set_multiple_files(true);
        }
        dialog.popup(ScreenPosition::CenterParent, ScreenPosition::CenterParent)
              .expect("couldn't show file dialog");
    });

    let grid = grid_box!(
        type_check_box, type_radio,
        dir_check_box, dir_text_box,
        multiple_files_check_box, fill!(),
        fill!(), show_dialog,
    );
    grid.set_alignment_lin_all(VAlignment::Top);
    grid.set_num_div(NumDiv::Fixed(2));
    grid.fit_all_to_children();
    Box::new(grid)
}

fn main() {

    let dialog = Dialog::new();

    let tabs = Tabs::new();

    tabs.append_tabs(&[
        TabInfo::new(&*create_cursors_page()).title("Cursors"),
        TabInfo::new(&*create_file_dialog_page()).title("File Dialog"),
    ]);

    dialog.append(&tabs).expect("failed to build the window");
    dialog.set_title("Showcase");

    dialog.show_xy(ScreenPosition::Center, ScreenPosition::Center)
          .expect("failed to show the window");
    main_loop();
}
<commit_msg>Fix the Type check box being centered vertically (it was stretched)<commit_after>/* Copyright 2016 Jordan Miner
 *
 * Licensed under the MIT license <LICENSE or
 * http://opensource.org/licenses/MIT>. This file may not be copied,
 * modified, or distributed except according to those terms.
 */

#[macro_use]
extern crate clear_coat;
extern crate iup_sys;
extern crate smallvec;

use std::rc::Rc;
use iup_sys::*;
use smallvec::SmallVec;

use clear_coat::*;
use clear_coat::common_attrs_cbs::*;

struct CursorsCanvas {
    canvas: Canvas,
}

impl CursorsCanvas {
    pub fn new() -> Self {
        CursorsCanvas {
            canvas: Canvas::new(),
        }
    }
}

impl CursorAttribute for CursorsCanvas {}

unsafe impl Control for CursorsCanvas {
    fn handle(&self) -> *mut Ihandle {
        self.canvas.handle()
    }
}

fn create_cursors_page() -> Box<Control> {
    let cursors_canvas = Rc::new(CursorsCanvas::new());

    let radios_info = [
        ("None", Cursor::None),
        ("Arrow", Cursor::Arrow),
        ("Busy", Cursor::Busy),
        ("Cross", Cursor::Cross),
        ("Hand", Cursor::Hand),
        ("Help", Cursor::Help),
        ("Move", Cursor::Move),
        ("ResizeN", Cursor::ResizeN),
        ("ResizeS", Cursor::ResizeS),
        ("ResizeNS", Cursor::ResizeNS),
        ("ResizeW", Cursor::ResizeW),
        ("ResizeE", Cursor::ResizeE),
        ("ResizeWE", Cursor::ResizeWE),
        ("ResizeNE", Cursor::ResizeNE),
        ("ResizeSW", Cursor::ResizeSW),
        ("ResizeNW", Cursor::ResizeNW),
        ("ResizeSE", Cursor::ResizeSE),
        ("Text", Cursor::Text),
    ];

    let mut radios = SmallVec::<[Toggle; 32]>::new();
    for &(text, cur) in radios_info.iter() {
        let toggle = Toggle::new();
        toggle.set_title(text);
        let cursors_canvas2 = cursors_canvas.clone();
        toggle.action_event().add(move |checked| {
            if checked { cursors_canvas2.set_cursor(cur); }
        });
        radios.push(toggle);
    }
    // The arrow cursor is the default.
    radios[1].set_on(true);

    let grid = grid_box!(
        &radios[0],
        &radios[1],
        &radios[2],
        &radios[3],
        &radios[4],
        &radios[5],
        &radios[6],
        &radios[7],
        &radios[8],
        &radios[9],
        &radios[10],
        &radios[11],
        &radios[12],
        &radios[13],
        &radios[14],
        &radios[15],
        &radios[16],
        &radios[17],
    );
    grid.set_num_div(NumDiv::Fixed(2));
    grid.fit_all_to_children();
    let page = vbox!(
        &cursors_canvas,
        hbox!(
            fill!(),
            Radio::with_child(&grid),
            fill!(),
        ),
    );
    Box::new(page)
}

fn create_file_dialog_page() -> Box<Control> {
    let type_check_box = Toggle::new();
    type_check_box.set_title("Dialog Type:");

    let open_radio = Toggle::new();
    open_radio.set_title("Open");
    let save_radio = Toggle::new();
    save_radio.set_title("Save");
    let dir_radio = Toggle::new();
    dir_radio.set_title("Directory");
    let type_radio = Radio::with_child(&vbox!(
        &open_radio,
        &save_radio,
        &dir_radio,
    ));

    let dir_check_box = Toggle::new();
    dir_check_box.set_title("Directory:");

    let dir_text_box = Text::new();

    let multiple_files_check_box = Toggle::new();
    multiple_files_check_box.set_title("Multiple Files");

    let show_dialog = Button::with_title("Show Dialog");

    let type_check_box_capt = type_check_box.clone();
    let open_radio_capt = open_radio.clone();
    let save_radio_capt = save_radio.clone();
    let dir_check_box_capt = dir_check_box.clone();
    let dir_text_box_capt = dir_text_box.clone();
    let multiple_files_check_box_capt = multiple_files_check_box.clone();
    show_dialog.action_event().add(move || {
        let dialog = FileDlg::new();
        if type_check_box_capt.is_on() {
            dialog.set_dialog_type(if open_radio_capt.is_on() {
                FileDialogType::Open
            } else if save_radio_capt.is_on() {
                FileDialogType::Save
            } else {
                FileDialogType::Dir
            })
        }
        if dir_check_box_capt.is_on() {
            dialog.set_directory(&dir_text_box_capt.value());
        }
        if multiple_files_check_box_capt.is_on() {
            dialog.set_multiple_files(true);
        }
        dialog.popup(ScreenPosition::CenterParent, ScreenPosition::CenterParent)
              .expect("couldn't show file dialog");
    });

    let grid = grid_box!(
        type_check_box, type_radio,
        dir_check_box, dir_text_box,
        multiple_files_check_box, fill!(),
        fill!(), show_dialog,
    );
    grid.set_num_div(NumDiv::Fixed(2));
    grid.set_size_col(1);
    grid.fit_all_to_children();
    Box::new(grid)
}

fn main() {

    let dialog = Dialog::new();

    let tabs = Tabs::new();

    tabs.append_tabs(&[
        TabInfo::new(&*create_cursors_page()).title("Cursors"),
        TabInfo::new(&*create_file_dialog_page()).title("File Dialog"),
    ]);

    dialog.append(&tabs).expect("failed to build the window");
    dialog.set_title("Showcase");

    dialog.show_xy(ScreenPosition::Center, ScreenPosition::Center)
          .expect("failed to show the window");
    main_loop();
}
<|endoftext|>


<commit_before>use ram::schema::Schema;
use ram::chunk::Chunk;
use std::ptr;
use ram::io::{reader, writer};
use ram::types::{Map, Value, Id};
use std::collections::HashMap;
use std::sync::Arc;
use serde::Serialize;

const MAX_CELL_SIZE :usize = 1 * 1024 * 1024;

pub type DataValue = Value;
pub type DataMap = Map;

#[repr(C, packed)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Header {
    pub version: u64,
    pub size: u32,
    pub schema: u32,
    pub partition: u64,
    pub hash: u64,
}

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub enum WriteError {
    SchemaDoesNotExisted(u32),
    CannotAllocateSpace,
    CellIsTooLarge(usize),
    CellAlreadyExisted,
    CellDoesNotExisted,
    ReadError(ReadError),
    UserCanceledUpdate,
    DeletionPredictionFailed,
    NetworkingError,
    DataMismatchSchema,
}

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub enum ReadError {
    SchemaDoesNotExisted(u32),
    CellDoesNotExisted,
    NetworkingError,
}

impl Header {
    pub fn new(size: u32, schema: u32, id: &Id) -> Header {
        Header {
            version: 1,
            size: size,
            schema: schema,
            partition: id.higher,
            hash: id.lower,
        }
    }
    fn write(&self, location: usize) {
        unsafe {
            ptr::copy_nonoverlapping(self as *const Header, location as *mut Header, HEADER_SIZE);
        }
    }
    pub fn reserve(location: usize, size: usize) {
        Header {
            version: 0, // default a tombstone
            size: size as u32,
            schema: 0,
            hash: 0,
            partition: 0,
        }.write(location);
    }
    pub fn id(&self) -> Id {
        Id {
            higher: self.partition,
            lower: self.hash,
        }
    }
    pub fn set_id(&mut self, id: &Id) {
        self.partition = id.higher;
        self.hash = id.lower;
    }
}

pub const HEADER_SIZE :usize = 32;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Cell {
    pub header: Header,
    pub data: DataValue
}

impl Cell {

    pub fn new_with_id(schema_id: u32, id: &Id, value: Value) -> Cell {
        Cell {
            header: Header::new(0, schema_id, id),
            data: value
        }
    }

    fn encode_cell_key<V>(schema_id: u32, value: &V) -> Id
        where V: Serialize{
        Id::from_obj(&(schema_id, value))
    }

    pub fn new(schema: &Arc<Schema>, value: Value) -> Option<Cell> {
        let schema_id = schema.id;
        let id = if let Value::Map(ref data) = value {
            match schema.key_field {
                Some(ref keys) => {
                    let value = data.get_in_by_ids(keys.iter());
                    match value {
                        &Value::Null => return None,
                        _ => Cell::encode_cell_key(schema_id, value)
                    }
                },
                None => {
                    Id::rand()
                }
            }
        } else {
            Id::rand()
        };
        Some(Cell::new_with_id(schema_id, &id, value))
    }

    pub fn header_from_chunk_raw(ptr: usize) -> Result<Header, ReadError> {
        if ptr == 0 {return Err(ReadError::CellDoesNotExisted)}
        Ok(unsafe {(*(ptr as *const Header))})
    }
    pub fn from_chunk_raw(ptr: usize, chunk: &Chunk) -> Result<Cell, ReadError> {
        let header = Cell::header_from_chunk_raw(ptr)?;
        let data_ptr = ptr + HEADER_SIZE;
        let schema_id = &header.schema;
        if let Some(schema) = chunk.meta.schemas.get(schema_id) {
            Ok(Cell {
                header: header,
                data: reader::read_by_schema(data_ptr, &schema)
            })
        } else {
            error!("Schema {} does not existed to read", schema_id);
            return Err(ReadError::SchemaDoesNotExisted(*schema_id));
        }
    }
    pub fn write_to_chunk(&mut self, chunk: &Chunk) -> Result<usize, WriteError> {
        let schema_id = self.header.schema;
        if let Some(schema) = chunk.meta.schemas.get(&schema_id) {
            return self.write_to_chunk_with_schema(chunk, &schema)
        } else {
            error!("Schema {} does not existed to write", schema_id);
            return Err(WriteError::SchemaDoesNotExisted(schema_id));
        }
    }
    pub fn write_to_chunk_with_schema(&mut self, chunk: &Chunk, schema: &Schema) -> Result<usize, WriteError> {
        let mut offset: usize = 0;
        let mut instructions = Vec::<writer::Instruction>::new();
        writer::plan_write_field(&mut offset, &schema.fields, &self.data, &mut instructions)?;
        let total_size = offset + HEADER_SIZE;
        if total_size > MAX_CELL_SIZE {return Err(WriteError::CellIsTooLarge(total_size))}
        let addr_opt = chunk.try_acquire(total_size);
        self.header.size = total_size as u32;
        self.header.version += 1;
        match addr_opt {
            None => {
                error!("Cannot allocate new spaces in chunk");
                return Err(WriteError::CannotAllocateSpace);
            },
            Some((addr, _lock)) => {
                self.header.write(addr);
                writer::execute_plan(addr + HEADER_SIZE, instructions);
                return Ok(addr);
            }
        }
    }
    pub fn id(&self) -> Id {
        self.header.id()
    }
    pub fn set_id(&mut self, id: &Id) {
        self.header.set_id(id)
    }
}<commit_msg>expose cell key encoder<commit_after>use ram::schema::Schema;
use ram::chunk::Chunk;
use std::ptr;
use ram::io::{reader, writer};
use ram::types::{Map, Value, Id};
use std::collections::HashMap;
use std::sync::Arc;
use serde::Serialize;

const MAX_CELL_SIZE :usize = 1 * 1024 * 1024;

pub type DataValue = Value;
pub type DataMap = Map;

#[repr(C, packed)]
#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
pub struct Header {
    pub version: u64,
    pub size: u32,
    pub schema: u32,
    pub partition: u64,
    pub hash: u64,
}

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub enum WriteError {
    SchemaDoesNotExisted(u32),
    CannotAllocateSpace,
    CellIsTooLarge(usize),
    CellAlreadyExisted,
    CellDoesNotExisted,
    ReadError(ReadError),
    UserCanceledUpdate,
    DeletionPredictionFailed,
    NetworkingError,
    DataMismatchSchema,
}

#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
pub enum ReadError {
    SchemaDoesNotExisted(u32),
    CellDoesNotExisted,
    NetworkingError,
}

impl Header {
    pub fn new(size: u32, schema: u32, id: &Id) -> Header {
        Header {
            version: 1,
            size: size,
            schema: schema,
            partition: id.higher,
            hash: id.lower,
        }
    }
    fn write(&self, location: usize) {
        unsafe {
            ptr::copy_nonoverlapping(self as *const Header, location as *mut Header, HEADER_SIZE);
        }
    }
    pub fn reserve(location: usize, size: usize) {
        Header {
            version: 0, // default a tombstone
            size: size as u32,
            schema: 0,
            hash: 0,
            partition: 0,
        }.write(location);
    }
    pub fn id(&self) -> Id {
        Id {
            higher: self.partition,
            lower: self.hash,
        }
    }
    pub fn set_id(&mut self, id: &Id) {
        self.partition = id.higher;
        self.hash = id.lower;
    }
}

pub const HEADER_SIZE :usize = 32;

#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Cell {
    pub header: Header,
    pub data: DataValue
}

impl Cell {

    pub fn new_with_id(schema_id: u32, id: &Id, value: Value) -> Cell {
        Cell {
            header: Header::new(0, schema_id, id),
            data: value
        }
    }

    pub fn encode_cell_key<V>(schema_id: u32, value: &V) -> Id
        where V: Serialize{
        Id::from_obj(&(schema_id, value))
    }

    pub fn new(schema: &Arc<Schema>, value: Value) -> Option<Cell> {
        let schema_id = schema.id;
        let id = if let Value::Map(ref data) = value {
            match schema.key_field {
                Some(ref keys) => {
                    let value = data.get_in_by_ids(keys.iter());
                    match value {
                        &Value::Null => return None,
                        _ => Cell::encode_cell_key(schema_id, value)
                    }
                },
                None => {
                    Id::rand()
                }
            }
        } else {
            Id::rand()
        };
        Some(Cell::new_with_id(schema_id, &id, value))
    }

    pub fn header_from_chunk_raw(ptr: usize) -> Result<Header, ReadError> {
        if ptr == 0 {return Err(ReadError::CellDoesNotExisted)}
        Ok(unsafe {(*(ptr as *const Header))})
    }
    pub fn from_chunk_raw(ptr: usize, chunk: &Chunk) -> Result<Cell, ReadError> {
        let header = Cell::header_from_chunk_raw(ptr)?;
        let data_ptr = ptr + HEADER_SIZE;
        let schema_id = &header.schema;
        if let Some(schema) = chunk.meta.schemas.get(schema_id) {
            Ok(Cell {
                header: header,
                data: reader::read_by_schema(data_ptr, &schema)
            })
        } else {
            error!("Schema {} does not existed to read", schema_id);
            return Err(ReadError::SchemaDoesNotExisted(*schema_id));
        }
    }
    pub fn write_to_chunk(&mut self, chunk: &Chunk) -> Result<usize, WriteError> {
        let schema_id = self.header.schema;
        if let Some(schema) = chunk.meta.schemas.get(&schema_id) {
            return self.write_to_chunk_with_schema(chunk, &schema)
        } else {
            error!("Schema {} does not existed to write", schema_id);
            return Err(WriteError::SchemaDoesNotExisted(schema_id));
        }
    }
    pub fn write_to_chunk_with_schema(&mut self, chunk: &Chunk, schema: &Schema) -> Result<usize, WriteError> {
        let mut offset: usize = 0;
        let mut instructions = Vec::<writer::Instruction>::new();
        writer::plan_write_field(&mut offset, &schema.fields, &self.data, &mut instructions)?;
        let total_size = offset + HEADER_SIZE;
        if total_size > MAX_CELL_SIZE {return Err(WriteError::CellIsTooLarge(total_size))}
        let addr_opt = chunk.try_acquire(total_size);
        self.header.size = total_size as u32;
        self.header.version += 1;
        match addr_opt {
            None => {
                error!("Cannot allocate new spaces in chunk");
                return Err(WriteError::CannotAllocateSpace);
            },
            Some((addr, _lock)) => {
                self.header.write(addr);
                writer::execute_plan(addr + HEADER_SIZE, instructions);
                return Ok(addr);
            }
        }
    }
    pub fn id(&self) -> Id {
        self.header.id()
    }
    pub fn set_id(&mut self, id: &Id) {
        self.header.set_id(id)
    }
}<|endoftext|>


<commit_before>// Portion that builds and runs tests.  Assumes that this can be
// done via a call to `make build` and `make test`.  Compiler failure
// is assumed to be communicated by return value.  Tests are assumed
// to have the following output format:
//
// some test name: <PASS|FAIL>
//
// ...where each test result is on its own line.  If multiple tests
// have the same name, then only the last test is recorded.

use std::collections::HashMap;
use std::io::{BufferedReader, RefReader, IoResult, IoError, OtherIoError};
use std::io::pipe::PipeStream;
use std::io::process::{Command, Process, ExitStatus, ExitSignal,
                       ProcessExit};

fn spawn_with_timeout(c: &Command, timeout: Option<u64>) -> IoResult<Process> {
    match c.spawn() {
        Ok(mut p) => {
            p.set_timeout(timeout);
            Ok(p)
        },
        Err(e) => Err(e)
    }
}

/// Runs the given command with the given timeout, ignoring the output.
/// If it returns non-zero, then it's a failure, as with a signal.
/// Takes what it should return on success.
pub fn run_command<A>(c: &Command, timeout: Option<u64>, on_success: A) -> IoResult<A> {
    // would like to use `and_then` here, but we get problems with capturing
    // on_success, seemingly because the compiler cannot enforce that
    // the closure passed to `and_then` only calls it once
    match spawn_with_timeout(c, timeout) {
        Ok(mut p) => {
            match p.wait() {
                Ok(res) => res.if_ok(on_success),
                Err(e) => Err(e)
            }
        },
        Err(e) => Err(e)
    }
}

trait ErrorSimplifier {
    fn if_ok<A>(&self, ret_this: A) -> IoResult<A>;
}

impl ErrorSimplifier for ProcessExit {
    fn if_ok<A>(&self, ret_this: A) -> IoResult<A> {
        match *self {
            ExitStatus(0) => Ok(ret_this),
            ExitStatus(x) => Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Non-zero exit code",
                    detail: Some(x.to_string())
                }),
            ExitSignal(x) => Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Exit signal",
                    detail: Some(x.to_string())
                })
        }
    }
}

#[deriving(Show, PartialEq)]
pub enum TestResult {
    Pass,
    Fail
}

struct ProcessReader {
    p: Process
}

impl ProcessReader {
    fn new(cmd: &Command, timeout: Option<u64>) -> IoResult<ProcessReader> {
        spawn_with_timeout(cmd, timeout).map(|p| ProcessReader { p: p })
    }

    fn output_reader<'a>(&'a mut self) -> BufferedReader<RefReader<'a, PipeStream>> {
        // unwrap should be ok - the documentation says `Some` is the default,
        // and we are not messing with any of the defaults
        BufferedReader::new(
            Reader::by_ref(
                self.p.stdout.as_mut().unwrap()))
    }
}

fn parse_test_result(line: &str) -> IoResult<TestResult> {
    match line {
        "PASS" => Ok(Pass),
        "FAIL" => Ok(Fail),
        _ => Err(
            IoError {
                kind: OtherIoError,
                desc: "Malformed test result",
                detail: Some(line.to_string())
            })
    }
}

fn parse_line(line: &str) -> IoResult<(String, TestResult)> {
    let results: Vec<&str> = line.split_str(":").collect();
    if results.len() == 2 {
        parse_test_result(results[1]).map(|res| {
            (results[0].to_string(), res)
        })
    } else {
        Err(
            IoError {
                kind: OtherIoError,
                desc: "Malformed test string",
                detail: Some(line.to_string())
            })
    }
}

pub enum BuildResult {
    SetupEnvFailure(IoError),
    BuildFailure(IoError),
    TestFailure(IoError),
    TestSuccess(HashMap<String, TestResult>)
}

pub trait WholeBuildable {
    fn env_timeout(&self) -> Option<u64>;

    fn env_command(&self) -> Command;

    /// Gets everything in order for testing to be performed.
    /// After calling this, it is assumed that we are ready
    /// to call make
    fn setup_env(&self) -> IoResult<()> {
        run_command(&self.env_command(), self.env_timeout(), ())
    }

    fn build_timeout(&self) -> Option<u64>;

    fn build_command(&self) -> Command;

    fn do_build(&self) -> IoResult<()> {
        run_command(&self.build_command(), self.build_timeout(), ())
    }

    fn test_timeout(&self) -> Option<u64>;

    fn test_command(&self) -> Command;

    fn do_testing(&self) -> IoResult<HashMap<String, TestResult>> {
        // TODO: without do syntax this becomes nightmarish in
        // functional style, and I had issues with closures capturing
        // too much
        match ProcessReader::new(&self.test_command(), self.test_timeout()) {
            Ok(mut reader) => {
                let mut map = HashMap::new();
                for op_line in reader.output_reader().lines() {
                    match op_line {
                        Ok(line) => {
                            match parse_line(line.as_slice().trim()) {
                                Ok((k, v)) => {
                                    map.insert(k, v);
                                }
                                Err(s) => { return Err(s); }
                            }
                        }
                        Err(s) => { return Err(s); }
                    }
                }
                Ok(map)

            }
            Err(s) => { return Err(s); }
        }
    }

    fn whole_build(self) -> BuildResult {
        match self.setup_env() {
            Ok(_) => {
                match self.do_build() {
                    Ok(_) => {
                        match self.do_testing() {
                            Ok(res) => TestSuccess(res),
                            Err(e) => TestFailure(e)
                        }
                    },
                    Err(e) => BuildFailure(e)
                }
            },
            Err(e) => SetupEnvFailure(e)
        }
    }
}

#[cfg(test)]
mod process_tests {
    use std::io::process::Command;
    use super::{run_command, ProcessReader};

    #[test]
    fn echo_ok() {
        assert!(run_command(&*Command::new("echo").arg("foobar"), None, ()).is_ok());
    }

    #[test]
    fn false_ok() {
        assert!(run_command(&Command::new("false"), None, ()).is_err());
    }

    fn output_from_command(cmd: &Command) -> Vec<String> {
        let pr = ProcessReader::new(cmd, None);
        assert!(pr.is_ok());
        pr.unwrap().output_reader().lines()
            .map(|line| {
                assert!(line.is_ok());
                line.unwrap().as_slice().trim().to_string()
            }).collect()
    }

    #[test]
    fn output_single_line_read() {
        let lines = output_from_command(
            &*Command::new("sh").arg("-c").arg("echo foobar"));
        assert_eq!(lines.len(), 1);
        assert_eq!(lines[0].as_slice(), "foobar");
    }

    #[test]
    fn output_multi_line_read() {
        let lines = output_from_command(
            &*Command::new("sh").arg("-c").arg("echo foo; echo bar"));
        assert_eq!(lines.len(), 2);
        assert_eq!(lines[0].as_slice(), "foo");
        assert_eq!(lines[1].as_slice(), "bar");
    }
}

#[cfg(test)]
mod parse_tests {
    use super::{parse_test_result, Pass, Fail, parse_line};

    #[test]
    fn parse_test_pass() {
        let res = parse_test_result("PASS");
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), Pass);
    }

    #[test]
    fn parse_test_fail() {
        let res = parse_test_result("FAIL");
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), Fail);
    }

    #[test]
    fn parse_test_bad_test() {
        let res = parse_test_result("foobar");
        assert!(res.is_err());
    }

    #[test]
    fn parse_valid_test_line() {
        let res = parse_line("my test:PASS");
        assert!(res.is_ok());
        let (key, result) = res.unwrap();
        assert_eq!(key.as_slice(), "my test");
        assert_eq!(result, Pass);
    }

    #[test]
    fn parse_invalid_test_line() {
        assert!(parse_line("this:is:PASS").is_err());
    }
}

#[cfg(test)]
mod build_tests {
    use std::io::process::Command;
    use super::{run_command, TestSuccess, Pass, Fail, WholeBuildable};

    struct TestingRequest {
        dir: Path, // directory where the build is to be performed
        makefile_loc: Path // where the makefile is located
    }

    fn req(name: &str) -> TestingRequest {
        TestingRequest {
            dir: Path::new(format!("test/{}", name)),
            makefile_loc: Path::new("test/makefile")
        }
    }

    impl TestingRequest {
        fn make_with_arg<A : ToCStr>(&self, arg: A) -> Command {
            let mut c = Command::new("make");
            c.arg("-s").arg(arg).cwd(&self.dir);
            c
        }
    }

    impl Drop for TestingRequest {
        /// Automatically deletes the copied-over makefile on test end,
        /// along with any applicable executables (namely `a.out`)
        #[allow(unused_must_use)]
        fn drop(&mut self) {
            let dir = self.dir.as_str().unwrap();
            run_command(
                &*Command::new("rm")
                    .arg(format!("{}/makefile", dir))
                    .arg(format!("{}/a.out", dir)),
                None,
                ());
        }
    }

    impl WholeBuildable for TestingRequest {
        fn env_timeout(&self) -> Option<u64> { None }

        fn env_command(&self) -> Command {
            let mut c = Command::new("cp");
            c.arg(self.makefile_loc.as_str().unwrap());
            c.arg(self.dir.as_str().unwrap());
            c
        }

        fn build_timeout(&self) -> Option<u64> { None }

        fn build_command(&self) -> Command {
            self.make_with_arg("build")
        }

        fn test_timeout(&self) -> Option<u64> { None }

        fn test_command(&self) -> Command {
            self.make_with_arg("test")
        }
    }

    #[test]
    fn makefile_copy_ok() {
        assert!(req("compile_error").setup_env().is_ok());
    }

    #[test]
    fn expected_compile_failure() {
        let r = req("compile_error");
        assert!(r.setup_env().is_ok());
        assert!(r.do_build().is_err());
    }

    #[test]
    fn expected_compile_success() {
        let r = req("compile_success");
        assert!(r.setup_env().is_ok());
        assert!(r.do_build().is_ok());
    }

    #[test]
    fn testing_parsing_empty_success() {
        let r = req("testing_parsing_empty_success");
        assert!(r.setup_env().is_ok());
        assert!(r.do_build().is_ok());
        let res = r.do_testing();
        assert!(res.is_ok());
        assert_eq!(res.unwrap().len(), 0);
    }

    #[test]
    fn testing_parsing_nonempty_success() {
        let r = req("testing_parsing_nonempty_success");
        assert!(r.setup_env().is_ok());
        assert!(r.do_build().is_ok());
        let res = r.do_testing();

        assert!(res.is_ok());
        let u = res.unwrap();
        assert_eq!(u.len(), 2);

        let t1 = u.find_equiv(&"test1".to_string());
        assert!(t1.is_some());
        assert_eq!(t1.unwrap(), &Pass);

        let t2 = u.find_equiv(&"test2".to_string());
        assert!(t2.is_some());
        assert_eq!(t2.unwrap(), &Fail);
    }

    #[test]
    fn test_whole_build() {
        match req("test_whole_build").whole_build() {
            TestSuccess(u) => {
                let t1 = u.find_equiv(&"test1".to_string());
                assert!(t1.is_some());
                assert_eq!(t1.unwrap(), &Pass);

                let t2 = u.find_equiv(&"test2".to_string());
                assert!(t2.is_some());
                assert_eq!(t2.unwrap(), &Fail);
            },
            _ => { assert!(false); }
        };
    }
}
<commit_msg>Moved functions to implement for WholeBuildable into one place.<commit_after>// Portion that builds and runs tests.  Assumes that this can be
// done via a call to `make build` and `make test`.  Compiler failure
// is assumed to be communicated by return value.  Tests are assumed
// to have the following output format:
//
// some test name: <PASS|FAIL>
//
// ...where each test result is on its own line.  If multiple tests
// have the same name, then only the last test is recorded.

use std::collections::HashMap;
use std::io::{BufferedReader, RefReader, IoResult, IoError, OtherIoError};
use std::io::pipe::PipeStream;
use std::io::process::{Command, Process, ExitStatus, ExitSignal,
                       ProcessExit};

fn spawn_with_timeout(c: &Command, timeout: Option<u64>) -> IoResult<Process> {
    match c.spawn() {
        Ok(mut p) => {
            p.set_timeout(timeout);
            Ok(p)
        },
        Err(e) => Err(e)
    }
}

/// Runs the given command with the given timeout, ignoring the output.
/// If it returns non-zero, then it's a failure, as with a signal.
/// Takes what it should return on success.
pub fn run_command<A>(c: &Command, timeout: Option<u64>, on_success: A) -> IoResult<A> {
    // would like to use `and_then` here, but we get problems with capturing
    // on_success, seemingly because the compiler cannot enforce that
    // the closure passed to `and_then` only calls it once
    match spawn_with_timeout(c, timeout) {
        Ok(mut p) => {
            match p.wait() {
                Ok(res) => res.if_ok(on_success),
                Err(e) => Err(e)
            }
        },
        Err(e) => Err(e)
    }
}

trait ErrorSimplifier {
    fn if_ok<A>(&self, ret_this: A) -> IoResult<A>;
}

impl ErrorSimplifier for ProcessExit {
    fn if_ok<A>(&self, ret_this: A) -> IoResult<A> {
        match *self {
            ExitStatus(0) => Ok(ret_this),
            ExitStatus(x) => Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Non-zero exit code",
                    detail: Some(x.to_string())
                }),
            ExitSignal(x) => Err(
                IoError {
                    kind: OtherIoError,
                    desc: "Exit signal",
                    detail: Some(x.to_string())
                })
        }
    }
}

#[deriving(Show, PartialEq)]
pub enum TestResult {
    Pass,
    Fail
}

struct ProcessReader {
    p: Process
}

impl ProcessReader {
    fn new(cmd: &Command, timeout: Option<u64>) -> IoResult<ProcessReader> {
        spawn_with_timeout(cmd, timeout).map(|p| ProcessReader { p: p })
    }

    fn output_reader<'a>(&'a mut self) -> BufferedReader<RefReader<'a, PipeStream>> {
        // unwrap should be ok - the documentation says `Some` is the default,
        // and we are not messing with any of the defaults
        BufferedReader::new(
            Reader::by_ref(
                self.p.stdout.as_mut().unwrap()))
    }
}

fn parse_test_result(line: &str) -> IoResult<TestResult> {
    match line {
        "PASS" => Ok(Pass),
        "FAIL" => Ok(Fail),
        _ => Err(
            IoError {
                kind: OtherIoError,
                desc: "Malformed test result",
                detail: Some(line.to_string())
            })
    }
}

fn parse_line(line: &str) -> IoResult<(String, TestResult)> {
    let results: Vec<&str> = line.split_str(":").collect();
    if results.len() == 2 {
        parse_test_result(results[1]).map(|res| {
            (results[0].to_string(), res)
        })
    } else {
        Err(
            IoError {
                kind: OtherIoError,
                desc: "Malformed test string",
                detail: Some(line.to_string())
            })
    }
}

pub enum BuildResult {
    SetupEnvFailure(IoError),
    BuildFailure(IoError),
    TestFailure(IoError),
    TestSuccess(HashMap<String, TestResult>)
}

pub trait WholeBuildable {
    // BEGIN FUNCTIONS TO IMPLEMENT
    fn env_timeout(&self) -> Option<u64>;
    fn env_command(&self) -> Command;

    fn build_timeout(&self) -> Option<u64>;
    fn build_command(&self) -> Command;

    fn test_timeout(&self) -> Option<u64>;
    fn test_command(&self) -> Command;
    // END FUNCTIONS TO IMPLEMENT

    /// Gets everything in order for testing to be performed.
    /// After calling this, it is assumed that we are ready
    /// to call make
    fn setup_env(&self) -> IoResult<()> {
        run_command(&self.env_command(), self.env_timeout(), ())
    }

    fn do_build(&self) -> IoResult<()> {
        run_command(&self.build_command(), self.build_timeout(), ())
    }

    fn do_testing(&self) -> IoResult<HashMap<String, TestResult>> {
        // TODO: without do syntax this becomes nightmarish in
        // functional style, and I had issues with closures capturing
        // too much
        match ProcessReader::new(&self.test_command(), self.test_timeout()) {
            Ok(mut reader) => {
                let mut map = HashMap::new();
                for op_line in reader.output_reader().lines() {
                    match op_line {
                        Ok(line) => {
                            match parse_line(line.as_slice().trim()) {
                                Ok((k, v)) => {
                                    map.insert(k, v);
                                }
                                Err(s) => { return Err(s); }
                            }
                        }
                        Err(s) => { return Err(s); }
                    }
                }
                Ok(map)

            }
            Err(s) => { return Err(s); }
        }
    }

    fn whole_build(self) -> BuildResult {
        match self.setup_env() {
            Ok(_) => {
                match self.do_build() {
                    Ok(_) => {
                        match self.do_testing() {
                            Ok(res) => TestSuccess(res),
                            Err(e) => TestFailure(e)
                        }
                    },
                    Err(e) => BuildFailure(e)
                }
            },
            Err(e) => SetupEnvFailure(e)
        }
    }
}

#[cfg(test)]
mod process_tests {
    use std::io::process::Command;
    use super::{run_command, ProcessReader};

    #[test]
    fn echo_ok() {
        assert!(run_command(&*Command::new("echo").arg("foobar"), None, ()).is_ok());
    }

    #[test]
    fn false_ok() {
        assert!(run_command(&Command::new("false"), None, ()).is_err());
    }

    fn output_from_command(cmd: &Command) -> Vec<String> {
        let pr = ProcessReader::new(cmd, None);
        assert!(pr.is_ok());
        pr.unwrap().output_reader().lines()
            .map(|line| {
                assert!(line.is_ok());
                line.unwrap().as_slice().trim().to_string()
            }).collect()
    }

    #[test]
    fn output_single_line_read() {
        let lines = output_from_command(
            &*Command::new("sh").arg("-c").arg("echo foobar"));
        assert_eq!(lines.len(), 1);
        assert_eq!(lines[0].as_slice(), "foobar");
    }

    #[test]
    fn output_multi_line_read() {
        let lines = output_from_command(
            &*Command::new("sh").arg("-c").arg("echo foo; echo bar"));
        assert_eq!(lines.len(), 2);
        assert_eq!(lines[0].as_slice(), "foo");
        assert_eq!(lines[1].as_slice(), "bar");
    }
}

#[cfg(test)]
mod parse_tests {
    use super::{parse_test_result, Pass, Fail, parse_line};

    #[test]
    fn parse_test_pass() {
        let res = parse_test_result("PASS");
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), Pass);
    }

    #[test]
    fn parse_test_fail() {
        let res = parse_test_result("FAIL");
        assert!(res.is_ok());
        assert_eq!(res.unwrap(), Fail);
    }

    #[test]
    fn parse_test_bad_test() {
        let res = parse_test_result("foobar");
        assert!(res.is_err());
    }

    #[test]
    fn parse_valid_test_line() {
        let res = parse_line("my test:PASS");
        assert!(res.is_ok());
        let (key, result) = res.unwrap();
        assert_eq!(key.as_slice(), "my test");
        assert_eq!(result, Pass);
    }

    #[test]
    fn parse_invalid_test_line() {
        assert!(parse_line("this:is:PASS").is_err());
    }
}

#[cfg(test)]
mod build_tests {
    use std::io::process::Command;
    use super::{run_command, TestSuccess, Pass, Fail, WholeBuildable};

    struct TestingRequest {
        dir: Path, // directory where the build is to be performed
        makefile_loc: Path // where the makefile is located
    }

    fn req(name: &str) -> TestingRequest {
        TestingRequest {
            dir: Path::new(format!("test/{}", name)),
            makefile_loc: Path::new("test/makefile")
        }
    }

    impl TestingRequest {
        fn make_with_arg<A : ToCStr>(&self, arg: A) -> Command {
            let mut c = Command::new("make");
            c.arg("-s").arg(arg).cwd(&self.dir);
            c
        }
    }

    impl Drop for TestingRequest {
        /// Automatically deletes the copied-over makefile on test end,
        /// along with any applicable executables (namely `a.out`)
        #[allow(unused_must_use)]
        fn drop(&mut self) {
            let dir = self.dir.as_str().unwrap();
            run_command(
                &*Command::new("rm")
                    .arg(format!("{}/makefile", dir))
                    .arg(format!("{}/a.out", dir)),
                None,
                ());
        }
    }

    impl WholeBuildable for TestingRequest {
        fn env_timeout(&self) -> Option<u64> { None }

        fn env_command(&self) -> Command {
            let mut c = Command::new("cp");
            c.arg(self.makefile_loc.as_str().unwrap());
            c.arg(self.dir.as_str().unwrap());
            c
        }

        fn build_timeout(&self) -> Option<u64> { None }

        fn build_command(&self) -> Command {
            self.make_with_arg("build")
        }

        fn test_timeout(&self) -> Option<u64> { None }

        fn test_command(&self) -> Command {
            self.make_with_arg("test")
        }
    }

    #[test]
    fn makefile_copy_ok() {
        assert!(req("compile_error").setup_env().is_ok());
    }

    #[test]
    fn expected_compile_failure() {
        let r = req("compile_error");
        assert!(r.setup_env().is_ok());
        assert!(r.do_build().is_err());
    }

    #[test]
    fn expected_compile_success() {
        let r = req("compile_success");
        assert!(r.setup_env().is_ok());
        assert!(r.do_build().is_ok());
    }

    #[test]
    fn testing_parsing_empty_success() {
        let r = req("testing_parsing_empty_success");
        assert!(r.setup_env().is_ok());
        assert!(r.do_build().is_ok());
        let res = r.do_testing();
        assert!(res.is_ok());
        assert_eq!(res.unwrap().len(), 0);
    }

    #[test]
    fn testing_parsing_nonempty_success() {
        let r = req("testing_parsing_nonempty_success");
        assert!(r.setup_env().is_ok());
        assert!(r.do_build().is_ok());
        let res = r.do_testing();

        assert!(res.is_ok());
        let u = res.unwrap();
        assert_eq!(u.len(), 2);

        let t1 = u.find_equiv(&"test1".to_string());
        assert!(t1.is_some());
        assert_eq!(t1.unwrap(), &Pass);

        let t2 = u.find_equiv(&"test2".to_string());
        assert!(t2.is_some());
        assert_eq!(t2.unwrap(), &Fail);
    }

    #[test]
    fn test_whole_build() {
        match req("test_whole_build").whole_build() {
            TestSuccess(u) => {
                let t1 = u.find_equiv(&"test1".to_string());
                assert!(t1.is_some());
                assert_eq!(t1.unwrap(), &Pass);

                let t2 = u.find_equiv(&"test2".to_string());
                assert!(t2.is_some());
                assert_eq!(t2.unwrap(), &Fail);
            },
            _ => { assert!(false); }
        };
    }
}
<|endoftext|>