<commit_before>use rustc_serialize;
use quick_csv::Csv;
use csv;
use std::clone::Clone;
use std::cmp::Eq;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::hash::Hash;
use rand::{thread_rng, Rng};
use distance::manhattan_dist;
use utilities::abs_standard_deviation;

pub trait Record<U>
    where U: Clone + Eq + Debug + Hash
{
    fn record_len() -> usize;
    fn data_at(&self, index: usize) -> f32;
    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32));
    fn values(&self) -> Vec<f32>;
    fn set_values(&mut self, Vec<f32>);
    fn get_class(&self) -> U;
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct MpgRecord<U> {
    class: U,
    values: [f32; 5],
}

impl<U> Clone for MpgRecord<U>
    where U: Clone
{
    fn clone(&self) -> MpgRecord<U> {
        MpgRecord::<U> {
            class: self.class.clone(),
            values: self.values.clone()
        }
    }
}

impl<U> Record<U> for MpgRecord<U>
    where U: Clone + Eq + Debug + Hash
{
    fn record_len() -> usize {
        5
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }

    fn get_class(&self) -> U {
        self.class.clone()
    }

    fn set_values(&mut self, values: Vec<f32>) {
        for i in 0..self.values.len() {
            self.values[i] = values[i];
        }
    }
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct IrisRecord<U> {
    class: U,
    values: [f32; 4],
}

impl<U> Clone for IrisRecord<U>
    where U: Clone
{
    fn clone(&self) -> IrisRecord<U> {
        IrisRecord::<U> {
            class: self.class.clone(),
            values: self.values.clone()
        }
    }
}

impl<U> Record<U> for IrisRecord<U>
    where U: Clone + Eq + Debug + Hash
{
    fn record_len() -> usize {
        4
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }

    fn get_class(&self) -> U {
        self.class.clone()
    }

    fn set_values(&mut self, values: Vec<f32>) {
        for i in 0..self.values.len() {
            self.values[i] = values[i];
        }
    }
}

#[derive(Debug)]
pub struct Database<T, U>
    where T: Record<U> + Clone + rustc_serialize::Encodable,
          U: Clone + Eq + Debug + Hash
{
    data: Vec<T>,
    abs_sd: Vec<(f32, f32)>,
    phantom: PhantomData<U>,
}

impl<T, U> Database<T, U>
    where T: rustc_serialize::Decodable + ::std::fmt::Debug + Record<U> + Clone + rustc_serialize::Encodable,
          U: Clone + Eq + Debug + Hash
{
    pub fn new() -> Database<T, U> {
        Database {
            data: Vec::new(),
            abs_sd: Vec::new(),
            phantom: PhantomData,
        }
    }

    pub fn from_file(path: &str) -> Database<T, U> {
        let rdr = Csv::from_file(path).unwrap().has_header(true);
        let mut data: Vec<T> = Vec::new();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => data.push(cols),
                Err(error) => println!("{}", error),
            }
        }

        Database {
            data: data,
            abs_sd: Vec::new(),
            phantom: PhantomData,
        }
    }

    pub fn add_file(&mut self, path: &str) {
        let rdr = Csv::from_file(path).unwrap();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => self.data.push(cols),
                Err(error) => println!("{}", error),
            }
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        let record_len = T::record_len();
        let mut mult_feat_vec = vec![Vec::<f32>::new(); record_len];

        for rcrd in self.data.iter() {
            for i in 0..record_len {
                mult_feat_vec[i].push(rcrd.data_at(i));
            }
        }

        let mut i = 0;
        for feat_vec in mult_feat_vec.iter() {
            let asd_median_tup = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}",
                     i,
                     asd_median_tup.0,
                     asd_median_tup.1);

            for rcrd in self.data.iter_mut() {
                rcrd.standarize_field(i, &asd_median_tup);
            }

            self.abs_sd.push(asd_median_tup);
            i += 1;
        }
    }

    fn nearest_neighbors(&self, rcrd: &T, func: fn(&Vec<f32>, &Vec<f32>) -> f32) -> Vec<usize> {
        let mut distances: Vec<(f32, usize)> = Vec::new();
        let mut i = 0;
        for record in self.data.iter() {
            distances.push((func(&rcrd.values(), &record.values()), i));
            i += 1;
        }
        distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

        let indexes = distances.into_iter().map(|x| x.1).collect();
        indexes
    }

    pub fn standarize_record(&self, record: &mut T) {
        for i in 0..T::record_len() {
            record.standarize_field(i, &self.abs_sd[i]);
        }
    }

    pub fn predict_nn(&self, record: &T, k: usize) -> U {
        let mut counts: HashMap<U, usize> = HashMap::new();
        for i in 0..k {
            let counter = counts.entry(self.data[self.nearest_neighbors(&record, manhattan_dist)[i]].get_class()).or_insert(0);
            *counter += 1;
        }

        let mut p_class = self.data[self.nearest_neighbors(&record, manhattan_dist)[0]].get_class();
        let mut gtr_count = 1;

        for (class, count) in &counts {
            if *count > gtr_count {
                p_class = class.clone();
            }
        }

        p_class
    }

    pub fn count_classes(&self) -> HashMap<U, usize> {
        let mut counts: HashMap<U, usize> = HashMap::new();
        for record in self.data.iter() {
            let counter = counts.entry(record.get_class()).or_insert(0);
            *counter += 1;
        }
        counts
    }

    pub fn segment(&self, n: usize, prefix: &str) {
            // let class_count = db.count_classes();
            // let mut class_transfers_totals: Vec<HashMap<U, usize>> = vec![Vec::new(); n];
            // let mut class_transfers_count: Vec<HashMap<U, usize>> = vec![HashMap::new(); n];
            let mut record_transfers: Vec<Vec<usize>> = vec![Vec::new(); n];
            // for (class, count) in &class_count {
            //     let num_of_class = count / n;

            // }
            let mut rng = thread_rng();
            let mut i = 0;
            for record in self.data.iter() {
                record_transfers[rng.gen_range(0, n)].push(i);
                i += 1;
            }

            i = 1;
            for item in record_transfers.iter() {
                let path = format!("../../data/cross-validation/{}-{number:>0width$}",
                                                             prefix,
                                                             number = i,
                                                             width = 2);
                let str_path: &str = path.as_ref();
                let mut wtr = csv::Writer::from_file(str_path).unwrap();
                for record in item {
                    wtr.encode(self.data[*record].clone());
                }
                i += 1;
            }
    }

    pub fn cross_validation(training_path: &str, n: usize, prefix: &str) {
        /*******SEGMENTATION******/
        {
            let mut db = Database::<T, U>::from_file(training_path);
            db.segment(n, prefix);
        }
        /*************************/
        let mut precision = 0.0;
        for j in 1..n + 1 {
            let mut db = Database::<T, U>::new();
            for i in 1..n + 1 {
                if i != j {
                    db.add_file(format!("../../data/cross-validation/{}-{number:>0width$}",
                                        prefix,
                                        number = i,
                                        width = 2)
                                        .as_ref());
                }
            }
            db.standarize();

            let path = format!("../../data/cross-validation/{}-{number:>0width$}",
                               prefix,
                               number = j,
                               width = 2);
            let mut test_db = Database::<T, U>::from_file(path.as_ref());
            let mut confusion_counts: HashMap<U, HashMap<U, usize>> = HashMap::new();

            let mut n_correct = 0;
            let mut n_incorrect = 0;
            let mut count = 0;

            for mut record in test_db.data.iter_mut() {
                db.standarize_record(&mut record);
                let class = record.get_class();
                let pred = db.predict_nn(&record, 3);

                if class == pred {
                    n_correct += 1;
                } else {
                    n_incorrect += 1;
                }

                match confusion_counts.entry(class) {
                    Vacant(entry) => {
                        let mut class_count = HashMap::new();
                        class_count.insert(pred, 1);
                        entry.insert(class_count);
                    }
                    Occupied(mut entry) => {
                        let counter = entry.get_mut().entry(pred).or_insert(1);
                        *counter += 1;
                    }
                }

                count += 1;
            }

            println!("\nTestings for: {}\n\
                      Accuracy: {}%\n\
                      Confusion Matrix===========", path, n_correct as f32 * 100.0 / count as f32);
            for (act_class, counts) in &confusion_counts {
                print!("  {:?} >", act_class);
                for (pred_class, count) in counts {
                    print!("\t{:?}: {}", pred_class, count);
                }
                println!("");
            }
            println!("===========================\n");
            precision += n_correct as f32 * 100.0 / count as f32;
        }
        precision /= n as f32;
        println!("Avg accuracy: {}%", precision);
    }
}
<commit_msg>Some changes<commit_after>use rustc_serialize;
use quick_csv::Csv;
use csv;
use std::clone::Clone;
use std::cmp::Eq;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::fmt::Debug;
use std::marker::PhantomData;
use std::hash::Hash;
use rand::{thread_rng, Rng};
use distance::manhattan_dist;
use utilities::abs_standard_deviation;

pub trait Record<U>
    where U: Clone + Eq + Debug + Hash
{
    fn record_len() -> usize;
    fn data_at(&self, index: usize) -> f32;
    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32));
    fn values(&self) -> Vec<f32>;
    fn set_values(&mut self, Vec<f32>);
    fn get_class(&self) -> U;
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct MpgRecord<U> {
    class: U,
    values: [f32; 5],
}

impl<U> Clone for MpgRecord<U>
    where U: Clone
{
    fn clone(&self) -> MpgRecord<U> {
        MpgRecord::<U> {
            class: self.class.clone(),
            values: self.values.clone()
        }
    }
}

impl<U> Record<U> for MpgRecord<U>
    where U: Clone + Eq + Debug + Hash
{
    fn record_len() -> usize {
        5
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }

    fn get_class(&self) -> U {
        self.class.clone()
    }

    fn set_values(&mut self, values: Vec<f32>) {
        for i in 0..self.values.len() {
            self.values[i] = values[i];
        }
    }
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct IrisRecord<U> {
    class: U,
    values: [f32; 4],
}

impl<U> Clone for IrisRecord<U>
    where U: Clone
{
    fn clone(&self) -> IrisRecord<U> {
        IrisRecord::<U> {
            class: self.class.clone(),
            values: self.values.clone()
        }
    }
}

impl<U> Record<U> for IrisRecord<U>
    where U: Clone + Eq + Debug + Hash
{
    fn record_len() -> usize {
        4
    }

    fn data_at(&self, index: usize) -> f32 {
        self.values[index]
    }

    fn standarize_field(&mut self, index: usize, asd_median: &(f32, f32)) {
        self.values[index] = (self.values[index] - asd_median.1) / asd_median.0;
    }

    fn values(&self) -> Vec<f32> {
        self.values.to_vec()
    }

    fn get_class(&self) -> U {
        self.class.clone()
    }

    fn set_values(&mut self, values: Vec<f32>) {
        for i in 0..self.values.len() {
            self.values[i] = values[i];
        }
    }
}

#[derive(Debug)]
pub struct Database<T, U>
    where T: Record<U> + Clone + rustc_serialize::Encodable,
          U: Clone + Eq + Debug + Hash
{
    data: Vec<T>,
    abs_sd: Vec<(f32, f32)>,
    phantom: PhantomData<U>,
}

impl<T, U> Database<T, U>
    where T: rustc_serialize::Decodable + ::std::fmt::Debug + Record<U> + Clone + rustc_serialize::Encodable,
          U: Clone + Eq + Debug + Hash
{
    pub fn new() -> Database<T, U> {
        Database {
            data: Vec::new(),
            abs_sd: Vec::new(),
            phantom: PhantomData,
        }
    }

    pub fn from_file(path: &str) -> Database<T, U> {
        let rdr = Csv::from_file(path).unwrap().has_header(true);
        let mut data: Vec<T> = Vec::new();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => data.push(cols),
                Err(error) => println!("{}", error),
            }
        }

        Database {
            data: data,
            abs_sd: Vec::new(),
            phantom: PhantomData,
        }
    }

    pub fn add_file(&mut self, path: &str) {
        let rdr = Csv::from_file(path).unwrap();
        for row in rdr.into_iter() {
            match row.unwrap().decode::<T>() {
                Ok(cols) => self.data.push(cols),
                Err(error) => println!("{}", error),
            }
        }
    }

    pub fn standarize(&mut self) {
        println!("Standarizing DB...");
        let record_len = T::record_len();
        let mut mult_feat_vec = vec![Vec::<f32>::new(); record_len];

        for rcrd in self.data.iter() {
            for i in 0..record_len {
                mult_feat_vec[i].push(rcrd.data_at(i));
            }
        }

        let mut i = 0;
        for feat_vec in mult_feat_vec.iter() {
            let asd_median_tup = abs_standard_deviation(&feat_vec);
            println!("\t{}> asd: {}\tmedian: {}",
                     i,
                     asd_median_tup.0,
                     asd_median_tup.1);

            for rcrd in self.data.iter_mut() {
                rcrd.standarize_field(i, &asd_median_tup);
            }

            self.abs_sd.push(asd_median_tup);
            i += 1;
        }
    }

    fn nearest_neighbors(&self, rcrd: &T, func: fn(&Vec<f32>, &Vec<f32>) -> f32) -> Vec<usize> {
        let mut distances: Vec<(f32, usize)> = Vec::new();
        let mut i = 0;
        for record in self.data.iter() {
            distances.push((func(&rcrd.values(), &record.values()), i));
            i += 1;
        }
        distances.sort_by(|a, b| a.0.partial_cmp(&b.0).unwrap());

        let indexes = distances.into_iter().map(|x| x.1).collect();
        indexes
    }

    pub fn standarize_record(&self, record: &mut T) {
        for i in 0..T::record_len() {
            record.standarize_field(i, &self.abs_sd[i]);
        }
    }

    pub fn predict_knn(&self, record: &T, k: usize) -> U {
        let mut counts: HashMap<U, usize> = HashMap::new();
        for i in 0..k {
            let counter = counts.entry(self.data[self.nearest_neighbors(&record, manhattan_dist)[i]].get_class()).or_insert(0);
            *counter += 1;
        }

        let mut p_class = self.data[self.nearest_neighbors(&record, manhattan_dist)[0]].get_class();
        let mut gtr_count = 1;

        for (class, count) in &counts {
            if *count > gtr_count {
                p_class = class.clone();
            }
        }

        p_class
    }

    pub fn predict_nn(&self, record: &T) -> U {
        unimplemented!()
    }

    pub fn predict_svm(&self, record: &T) -> U {
        unimplemented!()
    }

    pub fn count_classes(&self) -> HashMap<U, usize> {
        let mut counts: HashMap<U, usize> = HashMap::new();
        for record in self.data.iter() {
            let counter = counts.entry(record.get_class()).or_insert(0);
            *counter += 1;
        }
        counts
    }

    pub fn segment(&self, n: usize, prefix: &str) {
            let mut record_transfers: Vec<Vec<usize>> = vec![Vec::new(); n];
            let mut rng = thread_rng();
            let mut i = 0;
            for record in self.data.iter() {
                record_transfers[rng.gen_range(0, n)].push(i);
                i += 1;
            }

            i = 1;
            for item in record_transfers.iter() {
                let path = format!("../../data/cross-validation/{}-{number:>0width$}",
                                                             prefix,
                                                             number = i,
                                                             width = 2);
                let str_path: &str = path.as_ref();
                let mut wtr = csv::Writer::from_file(str_path).unwrap();
                for record in item {
                    wtr.encode(self.data[*record].clone());
                }
                i += 1;
            }
    }

    pub fn cross_validation(training_path: &str, n: usize, prefix: &str) {
        /*******SEGMENTATION******/
        {
            let mut db = Database::<T, U>::from_file(training_path);
            db.segment(n, prefix);
        }
        /*************************/
        let mut precision = 0.0;
        for j in 1..n + 1 {
            let mut db = Database::<T, U>::new();
            for i in 1..n + 1 {
                if i != j {
                    db.add_file(format!("../../data/cross-validation/{}-{number:>0width$}",
                                        prefix,
                                        number = i,
                                        width = 2)
                                        .as_ref());
                }
            }
            db.standarize();

            let path = format!("../../data/cross-validation/{}-{number:>0width$}",
                               prefix,
                               number = j,
                               width = 2);
            let mut test_db = Database::<T, U>::from_file(path.as_ref());
            let mut confusion_counts: HashMap<U, HashMap<U, usize>> = HashMap::new();

            let mut n_correct = 0;
            let mut n_incorrect = 0;
            let mut count = 0;

            for mut record in test_db.data.iter_mut() {
                db.standarize_record(&mut record);
                let class = record.get_class();
                let pred = db.predict_knn(&record, 3);

                if class == pred {
                    n_correct += 1;
                } else {
                    n_incorrect += 1;
                }

                match confusion_counts.entry(class) {
                    Vacant(entry) => {
                        let mut class_count = HashMap::new();
                        class_count.insert(pred, 1);
                        entry.insert(class_count);
                    }
                    Occupied(mut entry) => {
                        let counter = entry.get_mut().entry(pred).or_insert(1);
                        *counter += 1;
                    }
                }

                count += 1;
            }

            println!("\nTestings for: {}\n\
                      Accuracy: {}%\n\
                      Confusion Matrix===========", path, n_correct as f32 * 100.0 / count as f32);
            for (act_class, counts) in &confusion_counts {
                print!("  {:?} >", act_class);
                for (pred_class, count) in counts {
                    print!("\t{:?}: {}", pred_class, count);
                }
                println!("");
            }
            println!("===========================\n");
            precision += n_correct as f32 * 100.0 / count as f32;
        }
        precision /= n as f32;
        println!("Avg accuracy: {}%", precision);
    }
}
<|endoftext|>


<commit_before>extern crate flate2;
extern crate hyper;
extern crate swell;
extern crate toml;
extern crate time;

#[macro_use]
extern crate log;

#[macro_use]
extern crate lazy_static;

use std::env;
use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::io::{Read, Write};
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;

use hyper::Get;
use hyper::header::Encoding;
use hyper::header::{AcceptEncoding, ContentLength, ContentType, ContentEncoding};
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;

use flate2::Compression;
use flate2::write::GzEncoder;

// Allows for dynamic static variable creation at runtime.
lazy_static! {
    static ref ARGS: Vec<String> = env::args().collect();
    static ref CONFIG: toml::Table =
        swell::config::parse_config(&ARGS[1].as_ref());
}

/// A macro I borrowed from Hyper to help unwrap a Result<T> enum.
macro_rules! try_return(
    ($e:expr) => {{
        match $e {
            Ok(v) => v,
            Err(e) => { error!("Error: {}", e); return; }
        }
    }}
);

/// A GZIP encoding writer for requests that accept it as a means of
/// compression.
fn gzip_encoded_read(file: File, mut res: Response) {
    let mut ce_vec = Vec::new();
    ce_vec.push(Encoding::Gzip);
    res.headers_mut().set(ContentEncoding(ce_vec));

    let mut response = try_return!(res.start());
    let mut reader = BufReader::new(file);
    let mut buffer = Vec::new();
    reader.read_to_end(&mut buffer).unwrap();

    let mut gzip_enc = GzEncoder::new(Vec::new(), Compression::Best);
    let _ = gzip_enc.write_all(&buffer.as_ref());
    let compressed_bytes = gzip_enc.finish();

    try_return!(response.write_all(compressed_bytes.unwrap().as_ref()));
    try_return!(response.end());
}

fn accepts_gzip_encoding(ae: &AcceptEncoding) -> bool {
    for encoding in ae.iter() {
        if encoding.item == Encoding::Gzip {
            return true;
        }
    }
    false
}

/// Take a file object and create a buffered reader to read from and send back
/// to the client. It ends the Hyper response as well since the resource will
/// have been successfully returned.
fn buffered_file_read(file: File, res: Response) {
    let mut response = try_return!(res.start());
    let mut reader = BufReader::new(file);
    let mut buffer = Vec::new();
    reader.read_to_end(&mut buffer).unwrap();

    try_return!(response.write_all(&buffer.as_ref()));
    try_return!(response.end());
}

/// This method takes a file path extension and returns a Hyper Mime structure.
/// It gives us a type-safe structure that Hyper will correctly encode in the
/// response. The options are empty for now, as this rarely needs to be set.
fn get_content_type(extension: &str) -> Mime {
    let opts = Vec::new(); // This is empty as we don't use options.

    match extension {
        "html" => Mime(TopLevel::Text, SubLevel::Html, opts),
        "css" => Mime(TopLevel::Text, SubLevel::Css, opts),
        "js" => Mime(TopLevel::Application, SubLevel::Javascript, opts),
        "jpeg" | "jpg" => Mime(TopLevel::Image, SubLevel::Jpeg, opts),
        "png" => Mime(TopLevel::Image, SubLevel::Png, opts),
        "gif" => Mime(TopLevel::Image, SubLevel::Gif, opts),
        _ => Mime(TopLevel::Text, SubLevel::Plain, opts)
    }
}

/// This function simply returns a string representation of the current time.
/// It is used for logging requests.
fn cur_time_string() -> String {
    let cur_time = time::now();
    let timestamp = time::strftime("%F %T", &cur_time).unwrap();

    timestamp
}

/// This is a generic method that helps us write a file (resource) back to a
/// client. It checks for the default index and builds a path accordingly. It
/// is also responsible for getting the resources extension so that it can set
/// the MIME type accordingly. By default it gets the file size as well to set
/// Content-Length for the browser's response headers. It handles a 404 case by
/// responding with a generic 404 file.
fn send_file(req: &Request, path: &str, mut res: Response) {
    let server_table = CONFIG.get(&"server".to_string()).unwrap();
    let root = server_table.lookup("document_root").unwrap().as_str().unwrap();
    let root_path = Path::new(root);
    let mut file_reading_path = PathBuf::from(root_path);

    // Let everyone know what cool server sent them this response.
    res.headers_mut().set(hyper::header::Server("swell".to_string()));

    // By default, try and send the index.
    let _ = match path {
        "/" => file_reading_path.push("index.html"),
        _ => {
            // We have to trim the root suffix to return the entire path.
            // See the PathBuf documentation for push.
            let trim = path.trim_left_matches('/');
            file_reading_path.push(trim);
        }
    };

    // Get the file extension so we can set the MIME type.
    let ext = match file_reading_path.as_path().extension() {
        Some(v) => v,
        None => OsStr::new("None")
    };
    let ext_str = ext.to_str().unwrap();

    // We send a 404 response in the error case here, 203 is the size of
    // the file since it will not change.
    let file_to_send = match File::open(&file_reading_path) {
        Ok(file_to_send) => file_to_send,
        Err(e) => {
            error!("Could not perform stat on file: {}", e);
            info!("{} {} {} 404 {}",
                  cur_time_string(), req.method, path, req.remote_addr);

            *res.status_mut() = hyper::NotFound;
            let mut error_file = PathBuf::from(root_path);
            error_file.push("404.html");
            let file = try_return!(File::open(&error_file.as_path()));

            res.headers_mut().set(ContentLength(203)); // This is constant.
            res.headers_mut().set(
                ContentType(get_content_type("html".as_ref())));
            buffered_file_read(file, res);
            return;
        }
    };

    info!("{} {} {} 200 {}",
          cur_time_string(), req.method, path, req.remote_addr);

    // We know the file exists if we just opened it.
    let file_metadata = file_to_send.metadata().unwrap();

    res.headers_mut().set(ContentType(get_content_type(ext_str)));

    let accept_encoding = req.headers.get::<AcceptEncoding>();
    match accept_encoding {
        Some(ae) => {
            match accepts_gzip_encoding(ae) {
                true => { gzip_encoded_read(file_to_send, res); },
                // GZIP not supported, send normally.
                false => {
                    res.headers_mut().set(ContentLength(file_metadata.len()));
                    buffered_file_read(file_to_send, res);
                }
            }
        },
        // No encoding accepted, so send normally.
        None => {
            res.headers_mut().set(ContentLength(file_metadata.len()));
            buffered_file_read(file_to_send, res);
        }
    }
}

/// This is the entry method for the Hyper server. It unwraps a request
/// structure and ensures that we handle each one correctly. The response
/// object helps us set headers and other HTTP information safely.
fn base(req: Request, mut res: Response) {
    match req.uri {
        AbsolutePath(ref path) => match (&req.method, path) {
            (&Get, _) => {
                send_file(&req, path.as_ref(), res);
                return;
            },
            _ => {
                *res.status_mut() = hyper::NotFound;
                try_return!(res.start().and_then(|res| res.end()));
                return;
            }
        },
        _ => {
            try_return!(res.start().and_then(|res| res.end()));
            return;
        }
    };
}

/// The main method that makes a new hyper Server on the port specified in the
/// configuration file.
/// It starts listening and loops until we send the kill signal.
fn main() {
    let server_table = CONFIG.get(&"server".to_string()).unwrap();
    let num_threads: usize = server_table.lookup("num_threads").unwrap().as_integer().unwrap() as
        usize;
    let port: u16 = server_table.lookup("port").unwrap().as_integer().unwrap() as u16;
    let server = Server::http(base);
    let mut _listener = server.listen_threads(("0.0.0.0", port), num_threads).unwrap();

    // Initialize our logging library to standard out.
    let _logger_error = swell::logger::init();

    info!("Listening on port 42007...");
}

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

    use hyper::mime::{Mime, TopLevel, SubLevel};

    #[test]
    fn testing_check() {
        assert!(true);
    }

    #[test]
    fn check_jpeg_content_type() {
        let jpeg_mime = Mime(TopLevel::Image, SubLevel::Jpeg, Vec::new());
        assert_eq!(jpeg_mime, get_content_type("jpeg".as_slice()));
        assert_eq!(jpeg_mime, get_content_type("jpg".as_slice()));
    }

    #[test]
    fn check_js_content_type() {
        let js_mime = Mime(TopLevel::Application, SubLevel::Javascript, Vec::new());
        assert_eq!(js_mime, get_content_type("js".as_slice()));
    }
}
<commit_msg>changed port printing message<commit_after>extern crate flate2;
extern crate hyper;
extern crate swell;
extern crate toml;
extern crate time;

#[macro_use]
extern crate log;

#[macro_use]
extern crate lazy_static;

use std::env;
use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::io::{Read, Write};
use std::path::Path;
use std::path::PathBuf;
use std::vec::Vec;

use hyper::Get;
use hyper::header::Encoding;
use hyper::header::{AcceptEncoding, ContentLength, ContentType, ContentEncoding};
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri::AbsolutePath;

use flate2::Compression;
use flate2::write::GzEncoder;

// Allows for dynamic static variable creation at runtime.
lazy_static! {
    static ref ARGS: Vec<String> = env::args().collect();
    static ref CONFIG: toml::Table =
        swell::config::parse_config(&ARGS[1].as_ref());
}

/// A macro I borrowed from Hyper to help unwrap a Result<T> enum.
macro_rules! try_return(
    ($e:expr) => {{
        match $e {
            Ok(v) => v,
            Err(e) => { error!("Error: {}", e); return; }
        }
    }}
);

/// A GZIP encoding writer for requests that accept it as a means of
/// compression.
fn gzip_encoded_read(file: File, mut res: Response) {
    let mut ce_vec = Vec::new();
    ce_vec.push(Encoding::Gzip);
    res.headers_mut().set(ContentEncoding(ce_vec));

    let mut response = try_return!(res.start());
    let mut reader = BufReader::new(file);
    let mut buffer = Vec::new();
    reader.read_to_end(&mut buffer).unwrap();

    let mut gzip_enc = GzEncoder::new(Vec::new(), Compression::Best);
    let _ = gzip_enc.write_all(&buffer.as_ref());
    let compressed_bytes = gzip_enc.finish();

    try_return!(response.write_all(compressed_bytes.unwrap().as_ref()));
    try_return!(response.end());
}

fn accepts_gzip_encoding(ae: &AcceptEncoding) -> bool {
    for encoding in ae.iter() {
        if encoding.item == Encoding::Gzip {
            return true;
        }
    }
    false
}

/// Take a file object and create a buffered reader to read from and send back
/// to the client. It ends the Hyper response as well since the resource will
/// have been successfully returned.
fn buffered_file_read(file: File, res: Response) {
    let mut response = try_return!(res.start());
    let mut reader = BufReader::new(file);
    let mut buffer = Vec::new();
    reader.read_to_end(&mut buffer).unwrap();

    try_return!(response.write_all(&buffer.as_ref()));
    try_return!(response.end());
}

/// This method takes a file path extension and returns a Hyper Mime structure.
/// It gives us a type-safe structure that Hyper will correctly encode in the
/// response. The options are empty for now, as this rarely needs to be set.
fn get_content_type(extension: &str) -> Mime {
    let opts = Vec::new(); // This is empty as we don't use options.

    match extension {
        "html" => Mime(TopLevel::Text, SubLevel::Html, opts),
        "css" => Mime(TopLevel::Text, SubLevel::Css, opts),
        "js" => Mime(TopLevel::Application, SubLevel::Javascript, opts),
        "jpeg" | "jpg" => Mime(TopLevel::Image, SubLevel::Jpeg, opts),
        "png" => Mime(TopLevel::Image, SubLevel::Png, opts),
        "gif" => Mime(TopLevel::Image, SubLevel::Gif, opts),
        _ => Mime(TopLevel::Text, SubLevel::Plain, opts)
    }
}

/// This function simply returns a string representation of the current time.
/// It is used for logging requests.
fn cur_time_string() -> String {
    let cur_time = time::now();
    let timestamp = time::strftime("%F %T", &cur_time).unwrap();

    timestamp
}

/// This is a generic method that helps us write a file (resource) back to a
/// client. It checks for the default index and builds a path accordingly. It
/// is also responsible for getting the resources extension so that it can set
/// the MIME type accordingly. By default it gets the file size as well to set
/// Content-Length for the browser's response headers. It handles a 404 case by
/// responding with a generic 404 file.
fn send_file(req: &Request, path: &str, mut res: Response) {
    let server_table = CONFIG.get(&"server".to_string()).unwrap();
    let root = server_table.lookup("document_root").unwrap().as_str().unwrap();
    let root_path = Path::new(root);
    let mut file_reading_path = PathBuf::from(root_path);

    // Let everyone know what cool server sent them this response.
    res.headers_mut().set(hyper::header::Server("swell".to_string()));

    // By default, try and send the index.
    let _ = match path {
        "/" => file_reading_path.push("index.html"),
        _ => {
            // We have to trim the root suffix to return the entire path.
            // See the PathBuf documentation for push.
            let trim = path.trim_left_matches('/');
            file_reading_path.push(trim);
        }
    };

    // Get the file extension so we can set the MIME type.
    let ext = match file_reading_path.as_path().extension() {
        Some(v) => v,
        None => OsStr::new("None")
    };
    let ext_str = ext.to_str().unwrap();

    // We send a 404 response in the error case here, 203 is the size of
    // the file since it will not change.
    let file_to_send = match File::open(&file_reading_path) {
        Ok(file_to_send) => file_to_send,
        Err(e) => {
            error!("Could not perform stat on file: {}", e);
            info!("{} {} {} 404 {}",
                  cur_time_string(), req.method, path, req.remote_addr);

            *res.status_mut() = hyper::NotFound;
            let mut error_file = PathBuf::from(root_path);
            error_file.push("404.html");
            let file = try_return!(File::open(&error_file.as_path()));

            res.headers_mut().set(ContentLength(203)); // This is constant.
            res.headers_mut().set(
                ContentType(get_content_type("html".as_ref())));
            buffered_file_read(file, res);
            return;
        }
    };

    info!("{} {} {} 200 {}",
          cur_time_string(), req.method, path, req.remote_addr);

    // We know the file exists if we just opened it.
    let file_metadata = file_to_send.metadata().unwrap();

    res.headers_mut().set(ContentType(get_content_type(ext_str)));

    let accept_encoding = req.headers.get::<AcceptEncoding>();
    match accept_encoding {
        Some(ae) => {
            match accepts_gzip_encoding(ae) {
                true => { gzip_encoded_read(file_to_send, res); },
                // GZIP not supported, send normally.
                false => {
                    res.headers_mut().set(ContentLength(file_metadata.len()));
                    buffered_file_read(file_to_send, res);
                }
            }
        },
        // No encoding accepted, so send normally.
        None => {
            res.headers_mut().set(ContentLength(file_metadata.len()));
            buffered_file_read(file_to_send, res);
        }
    }
}

/// This is the entry method for the Hyper server. It unwraps a request
/// structure and ensures that we handle each one correctly. The response
/// object helps us set headers and other HTTP information safely.
fn base(req: Request, mut res: Response) {
    match req.uri {
        AbsolutePath(ref path) => match (&req.method, path) {
            (&Get, _) => {
                send_file(&req, path.as_ref(), res);
                return;
            },
            _ => {
                *res.status_mut() = hyper::NotFound;
                try_return!(res.start().and_then(|res| res.end()));
                return;
            }
        },
        _ => {
            try_return!(res.start().and_then(|res| res.end()));
            return;
        }
    };
}

/// The main method that makes a new hyper Server on the port specified in the
/// configuration file.
/// It starts listening and loops until we send the kill signal.
fn main() {
    let server_table = CONFIG.get(&"server".to_string()).unwrap();
    let num_threads: usize = server_table.lookup("num_threads").unwrap().as_integer().unwrap() as
        usize;
    let port: u16 = server_table.lookup("port").unwrap().as_integer().unwrap() as u16;
    let server = Server::http(base);
    let mut _listener = server.listen_threads(("0.0.0.0", port), num_threads).unwrap();

    // Initialize our logging library to standard out.
    let _logger_error = swell::logger::init();

    info!("Listening on port {}...", port);
}

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

    use hyper::mime::{Mime, TopLevel, SubLevel};

    #[test]
    fn testing_check() {
        assert!(true);
    }

    #[test]
    fn check_jpeg_content_type() {
        let jpeg_mime = Mime(TopLevel::Image, SubLevel::Jpeg, Vec::new());
        assert_eq!(jpeg_mime, get_content_type("jpeg".as_slice()));
        assert_eq!(jpeg_mime, get_content_type("jpg".as_slice()));
    }

    #[test]
    fn check_js_content_type() {
        let js_mime = Mime(TopLevel::Application, SubLevel::Javascript, Vec::new());
        assert_eq!(js_mime, get_content_type("js".as_slice()));
    }
}
<|endoftext|>


<commit_before><commit_msg>add docs to ListID + trait derivations for ListID<commit_after><|endoftext|>


<commit_before><commit_msg>Change implementation of PartialEq for Response<commit_after><|endoftext|>


<commit_before><commit_msg>shapeops cleanup: Remove Segment2; remove expensive debug output<commit_after><|endoftext|>


<commit_before><commit_msg>Add quickcheck tests to stackvec<commit_after><|endoftext|>


<commit_before>#[macro_use]
extern crate enum_map;

use enum_map::{EnumMap, Internal, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;
use std::marker::PhantomData;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_option_bool() {
    let mut map = enum_map! { None => 1, Some(false) => 2, Some(true) => 3};
    assert_eq!(map[None], 1);
    assert_eq!(map[Some(false)], 2);
    assert_eq!(map[Some(true)], 3);
    map[None] = 4;
    map[Some(false)] = 5;
    map[Some(true)] = 6;
    assert_eq!(map[None], 4);
    assert_eq!(map[Some(false)], 5);
    assert_eq!(map[Some(true)], 6);
    assert_eq!(map.as_slice(), [4, 5, 6]);
    let expected = [(None, 4), (Some(false), 5), (Some(true), 6)];
    assert_eq!(map.into_iter().collect::<Vec<_>>(), expected);
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iter_mut_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter_mut()
            .len(),
        3
    );
}

#[test]
fn into_iter_len() {
    assert_eq!(enum_map! { Example::A | _ => 0 }.into_iter().len(), 3);
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn iter_mut_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter_mut()
            .next_back(),
        Some((Example::C, &mut 3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn test_u8() {
    let mut map = enum_map! { b'a' => 4, _ => 0 };
    map[b'c'] = 3;
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
    assert_eq!(map[b'c'], 3);
    assert_eq!(map.iter().next(), Some((0, &0)));
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}

#[derive(Clone, Copy)]
enum X {
    A(PhantomData<*const ()>),
}

impl<V> Internal<V> for X {
    type Array = [V; 1];

    fn slice(array: &[V; 1]) -> &[V] {
        array
    }

    fn slice_mut(array: &mut [V; 1]) -> &mut [V] {
        array
    }

    fn from_usize(arg: usize) -> X {
        assert_eq!(arg, 0);
        X::A(PhantomData)
    }

    fn to_usize(self) -> usize {
        0
    }

    fn from_function<F: FnMut(Self) -> V>(mut f: F) -> [V; 1] {
        [f(X::A(PhantomData))]
    }
}

fn assert_sync_send<T: Sync + Send>(_: T) {}

#[test]
fn assert_enum_map_does_not_copy_sync_send_dependency_of_keys() {
    let mut map = enum_map! { X::A(PhantomData) => true };
    assert_sync_send(map);
    assert_sync_send(&map);
    assert_sync_send(&mut map);
    assert_sync_send(map.iter());
    assert_sync_send(map.iter_mut());
    assert_sync_send(map.into_iter());
    assert_eq!(map[X::A(PhantomData)], true);
}
<commit_msg>Test into_iter for u8 type<commit_after>#[macro_use]
extern crate enum_map;

use enum_map::{EnumMap, Internal, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;
use std::marker::PhantomData;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_option_bool() {
    let mut map = enum_map! { None => 1, Some(false) => 2, Some(true) => 3};
    assert_eq!(map[None], 1);
    assert_eq!(map[Some(false)], 2);
    assert_eq!(map[Some(true)], 3);
    map[None] = 4;
    map[Some(false)] = 5;
    map[Some(true)] = 6;
    assert_eq!(map[None], 4);
    assert_eq!(map[Some(false)], 5);
    assert_eq!(map[Some(true)], 6);
    assert_eq!(map.as_slice(), [4, 5, 6]);
    let expected = [(None, 4), (Some(false), 5), (Some(true), 6)];
    assert_eq!(map.into_iter().collect::<Vec<_>>(), expected);
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iter_mut_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter_mut()
            .len(),
        3
    );
}

#[test]
fn into_iter_len() {
    assert_eq!(enum_map! { Example::A | _ => 0 }.into_iter().len(), 3);
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

#[test]
fn iter_mut_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter_mut()
            .next_back(),
        Some((Example::C, &mut 3))
    );
}

#[test]
fn into_iter() {
    let mut iter = enum_map! { true => 5, false => 7 }.into_iter();
    assert_eq!(iter.next(), Some((false, 7)));
    assert_eq!(iter.next(), Some((true, 5)));
    assert_eq!(iter.next(), None);
    assert_eq!(iter.next(), None);
}

#[test]
fn into_iter_u8() {
    assert_eq!(
        EnumMap::from(|i: u8| i).into_iter().collect::<Vec<_>>(),
        (0..256).map(|x| (x as u8, x as u8)).collect::<Vec<_>>()
    );
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn test_u8() {
    let mut map = enum_map! { b'a' => 4, _ => 0 };
    map[b'c'] = 3;
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
    assert_eq!(map[b'c'], 3);
    assert_eq!(map.iter().next(), Some((0, &0)));
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}

#[derive(Clone, Copy)]
enum X {
    A(PhantomData<*const ()>),
}

impl<V> Internal<V> for X {
    type Array = [V; 1];

    fn slice(array: &[V; 1]) -> &[V] {
        array
    }

    fn slice_mut(array: &mut [V; 1]) -> &mut [V] {
        array
    }

    fn from_usize(arg: usize) -> X {
        assert_eq!(arg, 0);
        X::A(PhantomData)
    }

    fn to_usize(self) -> usize {
        0
    }

    fn from_function<F: FnMut(Self) -> V>(mut f: F) -> [V; 1] {
        [f(X::A(PhantomData))]
    }
}

fn assert_sync_send<T: Sync + Send>(_: T) {}

#[test]
fn assert_enum_map_does_not_copy_sync_send_dependency_of_keys() {
    let mut map = enum_map! { X::A(PhantomData) => true };
    assert_sync_send(map);
    assert_sync_send(&map);
    assert_sync_send(&mut map);
    assert_sync_send(map.iter());
    assert_sync_send(map.iter_mut());
    assert_sync_send(map.into_iter());
    assert_eq!(map[X::A(PhantomData)], true);
}
<|endoftext|>


<commit_before>mod object;
mod pointer;

pub use self::{
    object::{
        Builtin, ChannelId, Closure, Data, Int, Object, ReceivePort, SendPort, Struct, Symbol, Text,
    },
    pointer::Pointer,
};
use crate::builtin_functions::BuiltinFunction;
use itertools::Itertools;
use num_bigint::BigInt;
use std::{
    cmp::Ordering,
    collections::{HashMap, HashSet},
};

const TRACE: bool = false;

macro_rules! trace {
    ($format_string:tt, $($args:expr,)+) => {
        if TRACE {
            tracing::trace!($format_string, $($args),+)
        }
    };
    ($format_string:tt, $($args:expr),+) => {
        if TRACE {
            tracing::trace!($format_string, $($args),+)
        }
    };
    ($format_string:tt) => {
        if TRACE {
            tracing::trace!($format_string)
        }
    };
}

#[derive(Clone)]
pub struct Heap {
    objects: HashMap<Pointer, Object>,
    next_address: Pointer,
}

impl std::fmt::Debug for Heap {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut objects = self.objects.iter().collect_vec();
        objects.sort_by_key(|(address, _)| address.raw());

        writeln!(f, "{{")?;
        for (address, object) in objects {
            writeln!(
                f,
                "{address}: {} {}",
                object.reference_count,
                object.format(self),
            )?;
        }
        write!(f, "}}")
    }
}

impl Default for Heap {
    fn default() -> Self {
        Self {
            objects: HashMap::new(),
            next_address: Pointer::from_raw(1),
        }
    }
}
impl Heap {
    pub fn get(&self, address: Pointer) -> &Object {
        self.objects
            .get(&address)
            .unwrap_or_else(|| panic!("Couldn't get object {address}."))
    }
    pub fn get_mut(&mut self, address: Pointer) -> &mut Object {
        self.objects
            .get_mut(&address)
            .unwrap_or_else(|| panic!("Couldn't get object {address}."))
    }

    pub fn dup(&mut self, address: Pointer) {
        self.get_mut(address).reference_count += 1;

        let object = self.get(address);
        trace!(
            "RefCount of {address} increased to {}. Value: {}",
            object.reference_count,
            object.format(self),
        );
    }
    pub fn drop(&mut self, address: Pointer) {
        trace!(
            "RefCount of {address} reduced to {}. Value: {}",
            self.get(address).reference_count - 1,
            address.format(self),
        );

        let object = self.get_mut(address);
        object.reference_count -= 1;
        if object.reference_count == 0 {
            self.free(address);
        }
    }

    pub fn create(&mut self, object: Data) -> Pointer {
        let address = self.reserve_address();
        let object = Object {
            reference_count: 1,
            data: object,
        };
        trace!("Creating object {} at {address}.", object.format(self));
        self.objects.insert(address, object);
        address
    }
    fn reserve_address(&mut self) -> Pointer {
        let address = self.next_address;
        self.next_address = Pointer::from_raw(self.next_address.raw() + 1);
        address
    }
    fn free(&mut self, address: Pointer) {
        let object = self.objects.remove(&address).unwrap();
        trace!("Freeing object at {address}.");
        assert_eq!(object.reference_count, 0);
        for child in object.children() {
            self.drop(child);
        }
    }

    /// Clones all objects at the `root_addresses` into the `other` heap and
    /// returns a list of their addresses in the other heap.
    pub fn clone_multiple_to_other_heap_with_existing_mapping(
        &self,
        other: &mut Heap,
        addresses: &[Pointer],
        address_map: &mut HashMap<Pointer, Pointer>,
    ) -> Vec<Pointer> {
        let mut objects_to_refcounts = HashMap::new();
        for address in addresses {
            self.gather_objects_to_clone(&mut objects_to_refcounts, *address);
        }

        for object in objects_to_refcounts.keys() {
            address_map
                .entry(*object)
                .or_insert_with(|| other.reserve_address());
        }

        for (address, refcount) in objects_to_refcounts {
            other.objects.insert(
                address_map[&address],
                Object {
                    reference_count: refcount,
                    data: Self::map_data(address_map, &self.get(address).data),
                },
            );
        }

        addresses
            .iter()
            .map(|address| address_map[address])
            .collect()
    }
    fn gather_objects_to_clone(
        &self,
        objects_to_refcounts: &mut HashMap<Pointer, usize>,
        address: Pointer,
    ) {
        *objects_to_refcounts.entry(address).or_default() += 1;
        for child in self.get(address).children() {
            self.gather_objects_to_clone(objects_to_refcounts, child);
        }
    }
    fn map_data(address_map: &HashMap<Pointer, Pointer>, data: &Data) -> Data {
        match data {
            Data::Int(int) => Data::Int(int.clone()),
            Data::Text(text) => Data::Text(text.clone()),
            Data::Symbol(symbol) => Data::Symbol(symbol.clone()),
            Data::Struct(struct_) => Data::Struct(Struct {
                fields: struct_
                    .fields
                    .iter()
                    .map(|(hash, key, value)| (*hash, address_map[key], address_map[value]))
                    .collect(),
            }),
            Data::Closure(closure) => Data::Closure(Closure {
                captured: closure
                    .captured
                    .iter()
                    .map(|address| address_map[address])
                    .collect(),
                num_args: closure.num_args,
                body: closure.body.clone(),
            }),
            Data::Builtin(builtin) => Data::Builtin(builtin.clone()),
            Data::SendPort(port) => Data::SendPort(SendPort::new(port.channel)),
            Data::ReceivePort(port) => Data::ReceivePort(ReceivePort::new(port.channel)),
        }
    }
    pub fn clone_single_to_other_heap_with_existing_mapping(
        &self,
        other: &mut Heap,
        address: Pointer,
        address_map: &mut HashMap<Pointer, Pointer>,
    ) -> Pointer {
        self.clone_multiple_to_other_heap_with_existing_mapping(other, &[address], address_map)
            .pop()
            .unwrap()
    }
    pub fn clone_multiple_to_other_heap(
        &self,
        other: &mut Heap,
        addresses: &[Pointer],
    ) -> Vec<Pointer> {
        self.clone_multiple_to_other_heap_with_existing_mapping(
            other,
            addresses,
            &mut HashMap::new(),
        )
    }
    pub fn clone_single_to_other_heap(&self, other: &mut Heap, address: Pointer) -> Pointer {
        self.clone_single_to_other_heap_with_existing_mapping(other, address, &mut HashMap::new())
    }

    pub fn known_channels(&self) -> HashSet<ChannelId> {
        let mut known = HashSet::new();
        for object in self.objects.values() {
            if let Some(channel) = object.data.channel() {
                known.insert(channel);
            }
        }
        known
    }

    pub fn create_int(&mut self, int: BigInt) -> Pointer {
        self.create(Data::Int(Int { value: int }))
    }
    pub fn create_text(&mut self, text: String) -> Pointer {
        self.create(Data::Text(Text { value: text }))
    }
    pub fn create_symbol(&mut self, symbol: String) -> Pointer {
        self.create(Data::Symbol(Symbol { value: symbol }))
    }
    pub fn create_struct(&mut self, fields: HashMap<Pointer, Pointer>) -> Pointer {
        self.create(Data::Struct(Struct::from_fields(self, fields)))
    }
    pub fn create_closure(&mut self, closure: Closure) -> Pointer {
        self.create(Data::Closure(closure))
    }
    pub fn create_builtin(&mut self, builtin: BuiltinFunction) -> Pointer {
        self.create(Data::Builtin(Builtin { function: builtin }))
    }
    pub fn create_send_port(&mut self, channel: ChannelId) -> Pointer {
        self.create(Data::SendPort(SendPort::new(channel)))
    }
    pub fn create_receive_port(&mut self, channel: ChannelId) -> Pointer {
        self.create(Data::ReceivePort(ReceivePort::new(channel)))
    }
    pub fn create_nothing(&mut self) -> Pointer {
        self.create_symbol("Nothing".to_string())
    }
    pub fn create_list(&mut self, items: &[Pointer]) -> Pointer {
        let mut fields = vec![];
        for (index, item) in items.iter().enumerate() {
            fields.push((self.create_int(index.into()), *item));
        }
        self.create_struct(fields.into_iter().collect())
    }
    pub fn create_bool(&mut self, value: bool) -> Pointer {
        self.create_symbol(if value { "True" } else { "False" }.to_string())
    }
    pub fn create_result(&mut self, result: Result<Pointer, Pointer>) -> Pointer {
        let (type_, value) = match result {
            Ok(it) => ("Ok".to_string(), it),
            Err(it) => ("Error".to_string(), it),
        };
        let fields = HashMap::from([
            (
                self.create_symbol("Type".to_string()),
                self.create_symbol(type_),
            ),
            (self.create_symbol("Value".to_string()), value),
        ]);
        self.create_struct(fields)
    }
    pub fn create_ordering(&mut self, ordering: Ordering) -> Pointer {
        self.create_symbol(
            match ordering {
                Ordering::Less => "Less",
                Ordering::Equal => "Equal",
                Ordering::Greater => "Greater",
            }
            .to_string(),
        )
    }
}
<commit_msg>Make cloning to other heap cheaper<commit_after>mod object;
mod pointer;

pub use self::{
    object::{
        Builtin, ChannelId, Closure, Data, Int, Object, ReceivePort, SendPort, Struct, Symbol, Text,
    },
    pointer::Pointer,
};
use crate::builtin_functions::BuiltinFunction;
use itertools::Itertools;
use num_bigint::BigInt;
use std::{
    cmp::Ordering,
    collections::{HashMap, HashSet},
};

const TRACE: bool = false;

macro_rules! trace {
    ($format_string:tt, $($args:expr,)+) => {
        if TRACE {
            tracing::trace!($format_string, $($args),+)
        }
    };
    ($format_string:tt, $($args:expr),+) => {
        if TRACE {
            tracing::trace!($format_string, $($args),+)
        }
    };
    ($format_string:tt) => {
        if TRACE {
            tracing::trace!($format_string)
        }
    };
}

#[derive(Clone)]
pub struct Heap {
    objects: HashMap<Pointer, Object>,
    next_address: Pointer,
}

impl std::fmt::Debug for Heap {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut objects = self.objects.iter().collect_vec();
        objects.sort_by_key(|(address, _)| address.raw());

        writeln!(f, "{{")?;
        for (address, object) in objects {
            writeln!(
                f,
                "{address}: {} {}",
                object.reference_count,
                object.format(self),
            )?;
        }
        write!(f, "}}")
    }
}

impl Default for Heap {
    fn default() -> Self {
        Self {
            objects: HashMap::new(),
            next_address: Pointer::from_raw(1),
        }
    }
}
impl Heap {
    pub fn get(&self, address: Pointer) -> &Object {
        self.objects
            .get(&address)
            .unwrap_or_else(|| panic!("Couldn't get object {address}."))
    }
    pub fn get_mut(&mut self, address: Pointer) -> &mut Object {
        self.objects
            .get_mut(&address)
            .unwrap_or_else(|| panic!("Couldn't get object {address}."))
    }

    pub fn dup(&mut self, address: Pointer) {
        self.get_mut(address).reference_count += 1;

        let object = self.get(address);
        trace!(
            "RefCount of {address} increased to {}. Value: {}",
            object.reference_count,
            object.format(self),
        );
    }
    pub fn drop(&mut self, address: Pointer) {
        trace!(
            "RefCount of {address} reduced to {}. Value: {}",
            self.get(address).reference_count - 1,
            address.format(self),
        );

        let object = self.get_mut(address);
        object.reference_count -= 1;
        if object.reference_count == 0 {
            self.free(address);
        }
    }

    pub fn create(&mut self, object: Data) -> Pointer {
        let address = self.reserve_address();
        let object = Object {
            reference_count: 1,
            data: object,
        };
        trace!("Creating object {} at {address}.", object.format(self));
        self.objects.insert(address, object);
        address
    }
    fn reserve_address(&mut self) -> Pointer {
        let address = self.next_address;
        self.next_address = Pointer::from_raw(self.next_address.raw() + 1);
        address
    }
    fn free(&mut self, address: Pointer) {
        let object = self.objects.remove(&address).unwrap();
        trace!("Freeing object at {address}.");
        assert_eq!(object.reference_count, 0);
        for child in object.children() {
            self.drop(child);
        }
    }

    /// Clones all objects at the `root_addresses` into the `other` heap and
    /// returns a list of their addresses in the other heap.
    pub fn clone_multiple_to_other_heap_with_existing_mapping(
        &self,
        other: &mut Heap,
        addresses: &[Pointer],
        address_map: &mut HashMap<Pointer, Pointer>,
    ) -> Vec<Pointer> {
        let mut additional_refcounts = HashMap::new();
        for address in addresses {
            self.prepare_object_cloning(address_map, &mut additional_refcounts, other, *address);
        }

        for object in additional_refcounts.keys() {
            address_map
                .entry(*object)
                .or_insert_with(|| other.reserve_address());
        }

        for (address, refcount) in additional_refcounts {
            other
                .objects
                .entry(address_map[&address])
                .or_insert_with(|| Object {
                    reference_count: 0,
                    data: Self::map_data(address_map, &self.get(address).data),
                })
                .reference_count += refcount;
        }

        addresses
            .iter()
            .map(|address| address_map[address])
            .collect()
    }
    fn prepare_object_cloning(
        &self,
        address_map: &mut HashMap<Pointer, Pointer>,
        additional_refcounts: &mut HashMap<Pointer, usize>,
        other: &mut Heap,
        address: Pointer,
    ) {
        *additional_refcounts.entry(address).or_default() += 1;

        let is_new = !address_map.contains_key(&address);
        if is_new {
            address_map.insert(address, other.reserve_address());
            for child in self.get(address).children() {
                self.prepare_object_cloning(address_map, additional_refcounts, other, child);
            }
        }
    }
    fn map_data(address_map: &HashMap<Pointer, Pointer>, data: &Data) -> Data {
        match data {
            Data::Int(int) => Data::Int(int.clone()),
            Data::Text(text) => Data::Text(text.clone()),
            Data::Symbol(symbol) => Data::Symbol(symbol.clone()),
            Data::Struct(struct_) => Data::Struct(Struct {
                fields: struct_
                    .fields
                    .iter()
                    .map(|(hash, key, value)| (*hash, address_map[key], address_map[value]))
                    .collect(),
            }),
            Data::Closure(closure) => Data::Closure(Closure {
                captured: closure
                    .captured
                    .iter()
                    .map(|address| address_map[address])
                    .collect(),
                num_args: closure.num_args,
                body: closure.body.clone(),
            }),
            Data::Builtin(builtin) => Data::Builtin(builtin.clone()),
            Data::SendPort(port) => Data::SendPort(SendPort::new(port.channel)),
            Data::ReceivePort(port) => Data::ReceivePort(ReceivePort::new(port.channel)),
        }
    }
    pub fn clone_single_to_other_heap_with_existing_mapping(
        &self,
        other: &mut Heap,
        address: Pointer,
        address_map: &mut HashMap<Pointer, Pointer>,
    ) -> Pointer {
        self.clone_multiple_to_other_heap_with_existing_mapping(other, &[address], address_map)
            .pop()
            .unwrap()
    }
    pub fn clone_single_to_other_heap(&self, other: &mut Heap, address: Pointer) -> Pointer {
        self.clone_single_to_other_heap_with_existing_mapping(other, address, &mut HashMap::new())
    }

    pub fn known_channels(&self) -> HashSet<ChannelId> {
        let mut known = HashSet::new();
        for object in self.objects.values() {
            if let Some(channel) = object.data.channel() {
                known.insert(channel);
            }
        }
        known
    }

    pub fn create_int(&mut self, int: BigInt) -> Pointer {
        self.create(Data::Int(Int { value: int }))
    }
    pub fn create_text(&mut self, text: String) -> Pointer {
        self.create(Data::Text(Text { value: text }))
    }
    pub fn create_symbol(&mut self, symbol: String) -> Pointer {
        self.create(Data::Symbol(Symbol { value: symbol }))
    }
    pub fn create_struct(&mut self, fields: HashMap<Pointer, Pointer>) -> Pointer {
        self.create(Data::Struct(Struct::from_fields(self, fields)))
    }
    pub fn create_closure(&mut self, closure: Closure) -> Pointer {
        self.create(Data::Closure(closure))
    }
    pub fn create_builtin(&mut self, builtin: BuiltinFunction) -> Pointer {
        self.create(Data::Builtin(Builtin { function: builtin }))
    }
    pub fn create_send_port(&mut self, channel: ChannelId) -> Pointer {
        self.create(Data::SendPort(SendPort::new(channel)))
    }
    pub fn create_receive_port(&mut self, channel: ChannelId) -> Pointer {
        self.create(Data::ReceivePort(ReceivePort::new(channel)))
    }
    pub fn create_nothing(&mut self) -> Pointer {
        self.create_symbol("Nothing".to_string())
    }
    pub fn create_list(&mut self, items: &[Pointer]) -> Pointer {
        let mut fields = vec![];
        for (index, item) in items.iter().enumerate() {
            fields.push((self.create_int(index.into()), *item));
        }
        self.create_struct(fields.into_iter().collect())
    }
    pub fn create_bool(&mut self, value: bool) -> Pointer {
        self.create_symbol(if value { "True" } else { "False" }.to_string())
    }
    pub fn create_result(&mut self, result: Result<Pointer, Pointer>) -> Pointer {
        let (type_, value) = match result {
            Ok(it) => ("Ok".to_string(), it),
            Err(it) => ("Error".to_string(), it),
        };
        let fields = HashMap::from([
            (
                self.create_symbol("Type".to_string()),
                self.create_symbol(type_),
            ),
            (self.create_symbol("Value".to_string()), value),
        ]);
        self.create_struct(fields)
    }
    pub fn create_ordering(&mut self, ordering: Ordering) -> Pointer {
        self.create_symbol(
            match ordering {
                Ordering::Less => "Less",
                Ordering::Equal => "Equal",
                Ordering::Greater => "Greater",
            }
            .to_string(),
        )
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use common::ptr_sub;
use message;

pub type SegmentId = u32;

pub struct SegmentReader<'a> {
    arena : ArenaPtr<'a>,
    ptr : * Word,
    size : WordCount
}

impl <'a> SegmentReader<'a> {

    pub unsafe fn get_start_ptr(&self) -> *Word {
        self.ptr.offset(0)
    }

    pub unsafe fn contains_interval(&self, from : *Word, to : *Word) -> bool {
        let fromAddr : uint = std::cast::transmute(from);
        let toAddr : uint = std::cast::transmute(to);
        let thisBegin : uint = std::cast::transmute(self.ptr);
        let thisEnd : uint = std::cast::transmute(self.ptr.offset(self.size as int));
        return (fromAddr >= thisBegin && toAddr <= thisEnd);
        // TODO readLimiter
    }
}

pub struct SegmentBuilder<'a> {
    reader : SegmentReader<'a>,
    id : SegmentId,
    pos : *mut Word,
}

impl <'a> SegmentBuilder<'a> {

    pub fn new<'b>(arena : *mut BuilderArena<'b>,
                   id : SegmentId,
                   ptr : *mut Word,
                   size : WordCount) -> SegmentBuilder<'b> {
        SegmentBuilder {
            reader : SegmentReader {
                arena : BuilderArenaPtr(arena),
                ptr : unsafe {std::cast::transmute(ptr)},
                size : size
            },
            id : id,
            pos : ptr,
        }
    }

    pub fn get_word_offset_to(&mut self, ptr : *mut Word) -> WordCount {
        let thisAddr : uint = self.reader.ptr.to_uint();
        let ptrAddr : uint = ptr.to_uint();
        assert!(ptrAddr >= thisAddr);
        let result = (ptrAddr - thisAddr) / BYTES_PER_WORD;
        return result;
    }

    pub fn current_size(&self) -> WordCount {
        ptr_sub(self.pos, self.reader.ptr)
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<*mut Word> {
        if (amount > self.reader.size - self.current_size()) {
            return None;
        } else {
            let result = self.pos;
            self.pos = unsafe { self.pos.offset(amount as int) };
            return Some(result);
        }
    }

    pub fn available(&self) -> WordCount {
        self.reader.size - ptr_sub(self.pos, self.reader.ptr)
    }

    #[inline]
    pub unsafe fn get_ptr_unchecked(&mut self, offset : WordCount) -> *mut Word {
        std::cast::transmute_mut_unsafe(self.reader.ptr.offset(offset as int))
    }

    #[inline]
    pub fn get_segment_id(&self) -> SegmentId { self.id }

    pub fn get_arena(&self) -> *mut BuilderArena<'a> {
        match self.reader.arena {
            BuilderArenaPtr(b) => b,
            _ => fail!()
        }
    }
}

pub struct ReaderArena<'a> {
//    message : *message::MessageReader<'a>,
    segment0 : SegmentReader<'a>,

    more_segments : Option<~[SegmentReader<'a>]>
    //XXX should this be a map as in capnproto-c++?
}

pub struct BuilderArena<'a> {
    message : *mut message::MessageBuilder<'a>,
    segment0 : SegmentBuilder<'a>,
    more_segments : Option<~[~SegmentBuilder<'a>]>,
}

impl <'a> BuilderArena<'a> {

    #[inline]
    pub fn allocate(&mut self, amount : WordCount) -> (*mut SegmentBuilder<'a>, *mut Word) {
        unsafe {
            match self.segment0.allocate(amount) {
                Some(result) => { return (std::ptr::to_mut_unsafe_ptr(&mut self.segment0), result) }
                None => {}
            }

            //# Need to fall back to additional segments.

            let id = match self.more_segments {
                None => {
                    self.more_segments = Some(~[]);
                    1
                }
                Some(ref mut msegs) => {
                    let len = msegs.len();
                    let result_ptr = std::ptr::to_mut_unsafe_ptr(msegs[len-1]);
                    match msegs[len - 1].allocate(amount) {
                        Some(result) => { return (result_ptr, result) }
                        None => { len + 1 }
                    }
                }
            };

            let (words, size) = (*self.message).allocate_segment(amount);
            let mut new_builder = ~SegmentBuilder::new(std::ptr::to_mut_unsafe_ptr(self), id as u32, words, size);
            let builder_ptr = std::ptr::to_mut_unsafe_ptr(new_builder);

            match self.more_segments {
                None => fail!("impossible"),
                Some(ref mut msegs) => {
                    msegs.push(new_builder);
                }
            }

            (builder_ptr, (*builder_ptr).allocate(amount).unwrap() )
        }
    }

    pub fn get_segment(&mut self, id : SegmentId) -> *mut SegmentBuilder<'a> {
        if (id == 0) {
            std::ptr::to_mut_unsafe_ptr(&mut self.segment0)
        } else {
            match self.more_segments {
                None => fail!("invalide segment id {}", id),
                Some(ref mut msegs) => {
                    std::ptr::to_mut_unsafe_ptr(msegs[id - 1])
                }
            }
        }
    }

    pub fn get_segments_for_output<T>(&self, cont : |&[&[Word]]| -> T) -> T {
        unsafe {
            match self.more_segments {
                None => {
                    std::vec::raw::buf_as_slice::<Word, T>(
                        self.segment0.reader.ptr,
                        self.segment0.current_size(),
                        |v| cont([v]) )
                }
                Some(ref msegs) => {
                    let mut result = ~[];
                    result.push(std::cast::transmute(
                            std::unstable::raw::Slice { data : self.segment0.reader.ptr,
                                                       len : self.segment0.current_size()}));

                    for seg in msegs.iter() {
                        result.push(std::cast::transmute(
                            std::unstable::raw::Slice { data : seg.reader.ptr,
                                                        len : seg.current_size()}));
                    }
                    cont(result)
                }
            }
        }
    }
}

pub enum ArenaPtr<'a> {
    ReaderArenaPtr(*ReaderArena<'a>),
    BuilderArenaPtr(*mut BuilderArena<'a>),
    Null
}

impl <'a> ArenaPtr<'a>  {
    pub fn try_get_segment(&self, id : SegmentId) -> *SegmentReader<'a> {
        unsafe {
            match self {
                &ReaderArenaPtr(reader) => {
                    if (id == 0) {
                        return std::ptr::to_unsafe_ptr(&(*reader).segment0);
                    } else {
                        match (*reader).more_segments {
                            None => {fail!("no segments!")}
                            Some(ref segs) => {
                                segs.unsafe_ref(id as uint - 1)
                            }
                        }
                    }
                }
                &BuilderArenaPtr(builder) => {
                    if (id == 0) {
                        std::ptr::to_unsafe_ptr(&(*builder).segment0.reader)
                    } else {
                        match (*builder).more_segments {
                            None => {fail!("no more segments!")}
                            Some(ref segs) => {
                               std::ptr::to_unsafe_ptr(&segs[id as uint - 1].reader)
                            }
                        }
                    }
                }
                &Null => {
                    fail!()
                }
            }
        }
    }
}
<commit_msg>improve contains_interval()<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use common::ptr_sub;
use message;

pub type SegmentId = u32;

pub struct SegmentReader<'a> {
    arena : ArenaPtr<'a>,
    ptr : * Word,
    size : WordCount
}

impl <'a> SegmentReader<'a> {

    pub unsafe fn get_start_ptr(&self) -> *Word {
        self.ptr.offset(0)
    }

    pub unsafe fn contains_interval(&self, from : *Word, to : *Word) -> bool {
        let fromAddr : uint = std::cast::transmute(from);
        let toAddr : uint = std::cast::transmute(to);
        let thisBegin : uint = std::cast::transmute(self.ptr);
        let thisEnd : uint = std::cast::transmute(self.ptr.offset(self.size as int));
        return (fromAddr >= thisBegin && toAddr <= thisEnd && fromAddr <= toAddr);
        // TODO readLimiter
    }
}

pub struct SegmentBuilder<'a> {
    reader : SegmentReader<'a>,
    id : SegmentId,
    pos : *mut Word,
}

impl <'a> SegmentBuilder<'a> {

    pub fn new<'b>(arena : *mut BuilderArena<'b>,
                   id : SegmentId,
                   ptr : *mut Word,
                   size : WordCount) -> SegmentBuilder<'b> {
        SegmentBuilder {
            reader : SegmentReader {
                arena : BuilderArenaPtr(arena),
                ptr : unsafe {std::cast::transmute(ptr)},
                size : size
            },
            id : id,
            pos : ptr,
        }
    }

    pub fn get_word_offset_to(&mut self, ptr : *mut Word) -> WordCount {
        let thisAddr : uint = self.reader.ptr.to_uint();
        let ptrAddr : uint = ptr.to_uint();
        assert!(ptrAddr >= thisAddr);
        let result = (ptrAddr - thisAddr) / BYTES_PER_WORD;
        return result;
    }

    pub fn current_size(&self) -> WordCount {
        ptr_sub(self.pos, self.reader.ptr)
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<*mut Word> {
        if (amount > self.reader.size - self.current_size()) {
            return None;
        } else {
            let result = self.pos;
            self.pos = unsafe { self.pos.offset(amount as int) };
            return Some(result);
        }
    }

    pub fn available(&self) -> WordCount {
        self.reader.size - ptr_sub(self.pos, self.reader.ptr)
    }

    #[inline]
    pub unsafe fn get_ptr_unchecked(&mut self, offset : WordCount) -> *mut Word {
        std::cast::transmute_mut_unsafe(self.reader.ptr.offset(offset as int))
    }

    #[inline]
    pub fn get_segment_id(&self) -> SegmentId { self.id }

    pub fn get_arena(&self) -> *mut BuilderArena<'a> {
        match self.reader.arena {
            BuilderArenaPtr(b) => b,
            _ => fail!()
        }
    }
}

pub struct ReaderArena<'a> {
//    message : *message::MessageReader<'a>,
    segment0 : SegmentReader<'a>,

    more_segments : Option<~[SegmentReader<'a>]>
    //XXX should this be a map as in capnproto-c++?
}

pub struct BuilderArena<'a> {
    message : *mut message::MessageBuilder<'a>,
    segment0 : SegmentBuilder<'a>,
    more_segments : Option<~[~SegmentBuilder<'a>]>,
}

impl <'a> BuilderArena<'a> {

    #[inline]
    pub fn allocate(&mut self, amount : WordCount) -> (*mut SegmentBuilder<'a>, *mut Word) {
        unsafe {
            match self.segment0.allocate(amount) {
                Some(result) => { return (std::ptr::to_mut_unsafe_ptr(&mut self.segment0), result) }
                None => {}
            }

            //# Need to fall back to additional segments.

            let id = match self.more_segments {
                None => {
                    self.more_segments = Some(~[]);
                    1
                }
                Some(ref mut msegs) => {
                    let len = msegs.len();
                    let result_ptr = std::ptr::to_mut_unsafe_ptr(msegs[len-1]);
                    match msegs[len - 1].allocate(amount) {
                        Some(result) => { return (result_ptr, result) }
                        None => { len + 1 }
                    }
                }
            };

            let (words, size) = (*self.message).allocate_segment(amount);
            let mut new_builder = ~SegmentBuilder::new(std::ptr::to_mut_unsafe_ptr(self), id as u32, words, size);
            let builder_ptr = std::ptr::to_mut_unsafe_ptr(new_builder);

            match self.more_segments {
                None => fail!("impossible"),
                Some(ref mut msegs) => {
                    msegs.push(new_builder);
                }
            }

            (builder_ptr, (*builder_ptr).allocate(amount).unwrap() )
        }
    }

    pub fn get_segment(&mut self, id : SegmentId) -> *mut SegmentBuilder<'a> {
        if (id == 0) {
            std::ptr::to_mut_unsafe_ptr(&mut self.segment0)
        } else {
            match self.more_segments {
                None => fail!("invalide segment id {}", id),
                Some(ref mut msegs) => {
                    std::ptr::to_mut_unsafe_ptr(msegs[id - 1])
                }
            }
        }
    }

    pub fn get_segments_for_output<T>(&self, cont : |&[&[Word]]| -> T) -> T {
        unsafe {
            match self.more_segments {
                None => {
                    std::vec::raw::buf_as_slice::<Word, T>(
                        self.segment0.reader.ptr,
                        self.segment0.current_size(),
                        |v| cont([v]) )
                }
                Some(ref msegs) => {
                    let mut result = ~[];
                    result.push(std::cast::transmute(
                            std::unstable::raw::Slice { data : self.segment0.reader.ptr,
                                                       len : self.segment0.current_size()}));

                    for seg in msegs.iter() {
                        result.push(std::cast::transmute(
                            std::unstable::raw::Slice { data : seg.reader.ptr,
                                                        len : seg.current_size()}));
                    }
                    cont(result)
                }
            }
        }
    }
}

pub enum ArenaPtr<'a> {
    ReaderArenaPtr(*ReaderArena<'a>),
    BuilderArenaPtr(*mut BuilderArena<'a>),
    Null
}

impl <'a> ArenaPtr<'a>  {
    pub fn try_get_segment(&self, id : SegmentId) -> *SegmentReader<'a> {
        unsafe {
            match self {
                &ReaderArenaPtr(reader) => {
                    if (id == 0) {
                        return std::ptr::to_unsafe_ptr(&(*reader).segment0);
                    } else {
                        match (*reader).more_segments {
                            None => {fail!("no segments!")}
                            Some(ref segs) => {
                                segs.unsafe_ref(id as uint - 1)
                            }
                        }
                    }
                }
                &BuilderArenaPtr(builder) => {
                    if (id == 0) {
                        std::ptr::to_unsafe_ptr(&(*builder).segment0.reader)
                    } else {
                        match (*builder).more_segments {
                            None => {fail!("no more segments!")}
                            Some(ref segs) => {
                               std::ptr::to_unsafe_ptr(&segs[id as uint - 1].reader)
                            }
                        }
                    }
                }
                &Null => {
                    fail!()
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod frame_payload_enum;
mod header_enum;
mod method_enum;

use std::iter::ExactSizeIterator;
use std::io;

use WriteRust;
use common::Spec;

use self::frame_payload_enum::FramePayloadEnumWriter;
use self::header_enum::HeaderEnumWriter;
use self::method_enum::MethodEnumWriter;

pub struct SpecModuleWriter<'a> {
    spec: &'a Spec,
}

impl<'a> WriteRust for SpecModuleWriter<'a> {
    fn write_rust_to<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        if self.spec.classes().len() == 0 {
            return Ok(());
        }

        for class in self.spec.classes() {
            try!(writeln!(writer, "pub mod {};", class.snake_case()));
        }

        try!(self.write_class_constants(writer));
        try!(self.write_method_constants(writer));

        let header_enum = HeaderEnumWriter::new(&self.spec);
        try!(header_enum.write_rust_to(writer));
        try!(self.write_frame_struct(writer));

        let frame_payload_enum = FramePayloadEnumWriter::new(&self.spec);
        try!(frame_payload_enum.write_rust_to(writer));

        // aliases
        try!(writeln!(writer, "\n// Class methods"));
        for class in self.spec.classes() {
            try!(writeln!(writer, "pub use self::{}::ClassMethod as {}Method;", class.snake_case(), class.pascal_case()));
        }

        try!(writeln!(writer, "\n// Class headers"));
        for class in self.spec.classes() {
            if class.fields().is_empty() {
                continue;
            }
            try!(writeln!(writer, "pub use self::{}::Header as {}Header;", class.snake_case(), class.pascal_case()));
        }

        let method_enum = MethodEnumWriter::new(&self.spec);
        try!(method_enum.write_rust_to(writer));

        Ok(())
    }
}

impl<'a> SpecModuleWriter<'a> {
    pub fn new(spec: &'a Spec) -> Self {
        SpecModuleWriter {
            spec: spec,
        }
    }

    pub fn write_class_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(writer, "// Class Constants"));
        try!(writeln!(writer, "// Generated by primalgen::codegen::spec_module::SpecModuleWriter"));
        for (_, class_names) in self.spec.class_indexes() {
            for class_name in class_names {
                let class = self.spec.class(class_name).unwrap();
                let constant_class = class.constant_case();
                try!(writeln!(writer, "pub const CLASS_{}: u16 = {};", constant_class, class.index()));
            }
        }

        Ok(())
    }

    /// Write the correct frame strucutre
    /// 0.8.x had a "cycle" in each frame, 0.9.x doesn't
    pub fn write_frame_struct<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        let version = self.spec.version();

        let (cycle_prop, cycle_getter, cycle_arg, cycle_create) = if version.minor() == 8 {
            (
                "cycle: u8,\n",
                "\n\
                    pub fn cycle(&self) -> u8 {{\n\
                        self.cycle\n\
                    }} // fn cycle()\n\
                 \n",
                "cycle: u8,\n",
                "cycle: cycle,\n",
            )
        } else {
            ("", "", "", "")
        };

        // struct Frame
        try!(writeln!(writer, "\n\
                // Generated by primalgen::codegen::spec_module::SpecModuleWriter
                #[derive(Debug)]
                pub struct Frame<'a> {{\n\
                    channel: u16,\n\
                    {}\
                    payload: FramePayload<'a>,\n\
                }} // struct Frame\n\
                \n\
                impl<'a> Frame<'a> {{\n\
                    pub fn new<P>(channel: u16, {}payload: P) -> Self\n\
                        where P: Into<FramePayload<'a>>\n\
                    {{\n\
                        Frame {{\n\
                            channel: channel,\n\
                            {}\
                            payload: payload.into(),\n\
                        }} // Frame\n\
                    }} // fn new()\n\
                    \n\
                    pub fn channel(&self) -> u16 {{\n\
                        self.channel\n\
                    }} // fn channel()\n\
                    \n\
                    pub fn payload(&self) -> &FramePayload<'a> {{\n\
                        &self.payload\n\
                    }} // fn payload()\n\
                    {}\n\
                 }} // impl Frame<'a>
                    ",
                      cycle_prop, // struct Frame<'a>...
                      cycle_arg, // fn new()...
                      cycle_create, // Frame { cycle: ... }
                      cycle_getter, // fn cycle() -> u8
        ));

        Ok(())
    }

    pub fn write_method_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(writer, "\n// Class Methods"));
        try!(write!(writer, "// Generated by codegen::spec_module::SpecModuleWriter"));
        for class in self.spec.classes() {
            try!(writeln!(writer, ""));
            for (_, method_names) in class.method_indexes() {
                for method_name in method_names {
                    let method = class.method(method_name).unwrap();
                    try!(writeln!(
                        writer,
                        "pub const METHOD_{}_{}: u16 = {};",
                        class.constant_case(),
                        method.constant_case(),
                        method.index()
                    ));
                }
            }
        }

        Ok(())
    }
}<commit_msg>[primalgen] Remove redundant reference symbols.<commit_after>// Copyright 2016 Alexander Reece
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

mod frame_payload_enum;
mod header_enum;
mod method_enum;

use std::iter::ExactSizeIterator;
use std::io;

use WriteRust;
use common::Spec;

use self::frame_payload_enum::FramePayloadEnumWriter;
use self::header_enum::HeaderEnumWriter;
use self::method_enum::MethodEnumWriter;

pub struct SpecModuleWriter<'a> {
    spec: &'a Spec,
}

impl<'a> WriteRust for SpecModuleWriter<'a> {
    fn write_rust_to<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        if self.spec.classes().len() == 0 {
            return Ok(());
        }

        for class in self.spec.classes() {
            try!(writeln!(writer, "pub mod {};", class.snake_case()));
        }

        try!(self.write_class_constants(writer));
        try!(self.write_method_constants(writer));

        let header_enum = HeaderEnumWriter::new(self.spec);
        try!(header_enum.write_rust_to(writer));
        try!(self.write_frame_struct(writer));

        let frame_payload_enum = FramePayloadEnumWriter::new(self.spec);
        try!(frame_payload_enum.write_rust_to(writer));

        // aliases
        try!(writeln!(writer, "\n// Class methods"));
        for class in self.spec.classes() {
            try!(writeln!(writer, "pub use self::{}::ClassMethod as {}Method;", class.snake_case(), class.pascal_case()));
        }

        try!(writeln!(writer, "\n// Class headers"));
        for class in self.spec.classes() {
            if class.fields().is_empty() {
                continue;
            }
            try!(writeln!(writer, "pub use self::{}::Header as {}Header;", class.snake_case(), class.pascal_case()));
        }

        let method_enum = MethodEnumWriter::new(self.spec);
        try!(method_enum.write_rust_to(writer));

        Ok(())
    }
}

impl<'a> SpecModuleWriter<'a> {
    pub fn new(spec: &'a Spec) -> Self {
        SpecModuleWriter {
            spec: spec,
        }
    }

    pub fn write_class_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(writer, "// Class Constants"));
        try!(writeln!(writer, "// Generated by primalgen::codegen::spec_module::SpecModuleWriter"));
        for (_, class_names) in self.spec.class_indexes() {
            for class_name in class_names {
                let class = self.spec.class(class_name).unwrap();
                let constant_class = class.constant_case();
                try!(writeln!(writer, "pub const CLASS_{}: u16 = {};", constant_class, class.index()));
            }
        }

        Ok(())
    }

    /// Write the correct frame strucutre
    /// 0.8.x had a "cycle" in each frame, 0.9.x doesn't
    pub fn write_frame_struct<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        let version = self.spec.version();

        let (cycle_prop, cycle_getter, cycle_arg, cycle_create) = if version.minor() == 8 {
            (
                "cycle: u8,\n",
                "\n\
                    pub fn cycle(&self) -> u8 {{\n\
                        self.cycle\n\
                    }} // fn cycle()\n\
                 \n",
                "cycle: u8,\n",
                "cycle: cycle,\n",
            )
        } else {
            ("", "", "", "")
        };

        // struct Frame
        try!(writeln!(writer, "\n\
                // Generated by primalgen::codegen::spec_module::SpecModuleWriter
                #[derive(Debug)]
                pub struct Frame<'a> {{\n\
                    channel: u16,\n\
                    {}\
                    payload: FramePayload<'a>,\n\
                }} // struct Frame\n\
                \n\
                impl<'a> Frame<'a> {{\n\
                    pub fn new<P>(channel: u16, {}payload: P) -> Self\n\
                        where P: Into<FramePayload<'a>>\n\
                    {{\n\
                        Frame {{\n\
                            channel: channel,\n\
                            {}\
                            payload: payload.into(),\n\
                        }} // Frame\n\
                    }} // fn new()\n\
                    \n\
                    pub fn channel(&self) -> u16 {{\n\
                        self.channel\n\
                    }} // fn channel()\n\
                    \n\
                    pub fn payload(&self) -> &FramePayload<'a> {{\n\
                        &self.payload\n\
                    }} // fn payload()\n\
                    {}\n\
                 }} // impl Frame<'a>
                    ",
                      cycle_prop, // struct Frame<'a>...
                      cycle_arg, // fn new()...
                      cycle_create, // Frame { cycle: ... }
                      cycle_getter, // fn cycle() -> u8
        ));

        Ok(())
    }

    pub fn write_method_constants<W>(&self, writer: &mut W) -> io::Result<()>
        where W: io::Write
    {
        try!(writeln!(writer, "\n// Class Methods"));
        try!(write!(writer, "// Generated by codegen::spec_module::SpecModuleWriter"));
        for class in self.spec.classes() {
            try!(writeln!(writer, ""));
            for (_, method_names) in class.method_indexes() {
                for method_name in method_names {
                    let method = class.method(method_name).unwrap();
                    try!(writeln!(
                        writer,
                        "pub const METHOD_{}_{}: u16 = {};",
                        class.constant_case(),
                        method.constant_case(),
                        method.index()
                    ));
                }
            }
        }

        Ok(())
    }
}<|endoftext|>