<commit_before>//! Functions for manipulating the contrast of images.

use image::{
    GenericImage,
    GrayImage,
    ImageBuffer,
    Luma
};

/// Returns the Otsu threshold level of an 8bpp image.
/// This threshold will optimally binarize an image that
/// meets certain criteria.
pub fn otsu_level<I>(image: &I) -> u8
    where I: GenericImage<Pixel=Luma<u8>> {
    let hist = histogram(image);
    let levels = hist.len();
    let mut histc = [0i32; 256];
    let mut meanc = [0.0f64; 256];
    let mut pixel_count = hist[0] as f64;

    histc[0] = hist[0];

    for i in 1..levels {
        pixel_count += hist[i] as f64;
        histc[i] = histc[i-1] + hist[i];
        meanc[i] = meanc[i-1] + (hist[i] as f64)*(i as f64);
    }

    let mut sigma_max:f64 = -1.0;
    let mut otsu:f64 = 0.0;
    let mut otsu2:f64 = 0.0;

    for i in 0..levels {
        meanc[i] /= pixel_count;

        let p0 = (histc[i] as f64)/pixel_count;
        let p1 = 1.0f64 - p0;
        let mu0 = meanc[i]/p0;
        let mu1 = (meanc[levels-1]/pixel_count - meanc[i])/p1;

        let sigma = p0*p1*(mu0-mu1).powi(2);
        if sigma >= sigma_max {
            if sigma > sigma_max {
                otsu = i as f64;
                sigma_max = sigma;
            } else {
                otsu2 = i as f64;
            }
        }
    }
    ( (otsu + otsu2) / 2.0 ).ceil() as u8
}

/// Returns a binarized image from an input 8bpp grayscale image
/// obtained by applying the given image
pub fn threshold<I>(image: &I, thresh: u8) -> GrayImage
    where I: GenericImage<Pixel=Luma<u8>> {
    let mut out: GrayImage = ImageBuffer::new(image.width(), image.height());
     for y in 0..image.height() {
            for x in 0..image.width() {
                if image.get_pixel(x, y)[0] as u8 <= thresh {
                    out.put_pixel(x, y, Luma([0 as u8]));
                } else {
                    out.put_pixel(x, y, Luma([255 as u8]));
                }
            }
        }
    out
}

/// Mutates given image to form a binarized version produced by applying
/// the given threshold
pub fn threshold_mut<I>(image: &mut I, thresh: u8)
    where I: GenericImage<Pixel=Luma<u8>>  {
     for y in 0..image.height() {
            for x in 0..image.width() {
                if image.get_pixel(x, y)[0] as u8 <= thresh {
                    image.put_pixel(x, y, Luma([0 as u8]));
                } else {
                    image.put_pixel(x, y, Luma([255 as u8]));
                }
            }
        }
}

/// Returns the histogram of grayscale values in an 8pp
/// grayscale image.
pub fn histogram<I>(image: &I) -> [i32;256]
    where I: GenericImage<Pixel=Luma<u8>> {

    let mut hist = [0i32;256];

    for pix in image.pixels() {
        hist[pix.2[0] as usize] += 1;
    }

    hist
}

/// Returns the cumulative histogram of grayscale values in an 8bpp
/// grayscale image.
pub fn cumulative_histogram<I>(image: &I) -> [i32;256]
    where I: GenericImage<Pixel=Luma<u8>> {

    let mut hist = histogram(image);

    for i in 1..hist.len() {
        hist[i] += hist[i - 1];
    }

    hist
}

/// Equalises the histogram of an 8bpp grayscale image in place.
/// https://en.wikipedia.org/wiki/Histogram_equalization
pub fn equalize_histogram_mut<I>(image: &mut I)
    where I: GenericImage<Pixel=Luma<u8>> {

    let hist = cumulative_histogram(image);
    let total = hist[255] as f32;

    for y in 0..image.height() {
        for x in 0..image.width() {
            let original = image.get_pixel(x, y)[0] as usize;
            let fraction = hist[original] as f32 / total;
            let out = f32::min(255f32, 255f32 * fraction);
            image.put_pixel(x, y, Luma([out as u8]));
        }
    }
}

/// Equalises the histogram of an 8bpp grayscale image.
/// https://en.wikipedia.org/wiki/Histogram_equalization
pub fn equalize_histogram<I>(image: &I) -> GrayImage
    where I: GenericImage<Pixel=Luma<u8>> {

    let mut out: GrayImage = ImageBuffer::new(image.width(), image.height());
    out.copy_from(image, 0, 0);
    equalize_histogram_mut(&mut out);
    out
}

#[cfg(test)]
mod test {

    use super::{
        cumulative_histogram,
        equalize_histogram,
        histogram,
        otsu_level,
        threshold
    };
    use utils::{
        gray_bench_image
    };
    use image::{
        GrayImage,
        ImageBuffer
    };
    use test;

    #[test]
    fn test_cumulative_histogram() {
        let image: GrayImage = ImageBuffer::from_raw(5, 1, vec![
            1u8, 2u8, 3u8, 2u8, 1u8]).unwrap();

        let hist = cumulative_histogram(&image);

        assert_eq!(hist[0], 0);
        assert_eq!(hist[1], 2);
        assert_eq!(hist[2], 4);
        assert_eq!(hist[3], 5);
        assert!(hist.iter().skip(4).all(|x| *x == 5));
    }
    #[test]
    fn test_histogram(){
        let image: GrayImage = ImageBuffer::from_raw(5, 1, vec![
            1u8, 2u8, 3u8, 2u8, 1u8]).unwrap();

        let hist = histogram(&image);

        assert_eq!(hist[0], 0);
        assert_eq!(hist[1], 2);
        assert_eq!(hist[2], 2);
        assert_eq!(hist[3], 1);
    }
    #[test]
    fn test_otsu_level(){
        let image: GrayImage = ImageBuffer::from_raw(26, 1,
            vec![0u8, 10u8, 20u8, 30u8, 40u8, 50u8, 60u8, 70u8,
                80u8, 90u8, 100u8, 110u8, 120u8, 130u8, 140u8,
                150u8, 160u8, 170u8, 180u8, 190u8, 200u8,  210u8,
                220u8,  230u8,  240u8,  250u8]).unwrap();
        let level = otsu_level(&image);
        assert_eq!(level, 125);
    }
    #[test]
    fn test_threshold(){
        let before: GrayImage = ImageBuffer::from_raw(26, 1,
            vec![0u8, 10u8, 20u8, 30u8, 40u8, 50u8, 60u8, 70u8,
                80u8, 90u8, 100u8, 110u8, 120u8, 130u8, 140u8,
                150u8, 160u8, 170u8, 180u8, 190u8, 200u8,  210u8,
                220u8,  230u8,  240u8,  250u8]).unwrap();
        let after: GrayImage = ImageBuffer::from_raw(26, 1,
            vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                0u8, 0u8, 0u8, 0u8, 0u8, 255u8, 255u8,
                255u8, 255u8, 255u8, 255u8, 255u8, 255u8,  255u8,
                255u8,  255u8,  255u8,  255u8]).unwrap();

        let test = threshold(&before, 125u8);

        for y in 0..after.height() {
            for x in 0..after.width() {
                let check = after.get_pixel(x, y)[0] as usize;
                let test_pixel = test.get_pixel(x, y)[0] as usize;
                assert_eq!(test_pixel, check);
            }
        }
    }

    #[bench]
    fn bench_equalize_histogram(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let equalized = equalize_histogram(&image);
            test::black_box(equalized);
            });
    }
}<commit_msg>made suggested changes to threshold functions<commit_after>//! Functions for manipulating the contrast of images.

use image::{
    GenericImage,
    GrayImage,
    ImageBuffer,
    Luma
};

/// Returns the Otsu threshold level of an 8bpp image.
/// This threshold will optimally binarize an image that
/// contains two classes of pixels which have distributions
/// with equal variances. For details see:
/// Xu, X., et al. Pattern recognition letters 32.7 (2011)
pub fn otsu_level<I>(image: &I) -> u8
    where I: GenericImage<Pixel=Luma<u8>> {
    let hist = histogram(image);
    let levels = hist.len();
    let mut histc = [0i32; 256];
    let mut meanc = [0.0f64; 256];
    let mut pixel_count = hist[0] as f64;

    histc[0] = hist[0];

    for i in 1..levels {
        pixel_count += hist[i] as f64;
        histc[i] = histc[i-1] + hist[i];
        meanc[i] = meanc[i-1] + (hist[i] as f64)*(i as f64);
    }

    let mut sigma_max:f64 = -1.0;
    let mut otsu = 0f64;
    let mut otsu2 = 0f64;

    for i in 0..levels {
        meanc[i] /= pixel_count;

        let p0 = (histc[i] as f64)/pixel_count;
        let p1 = 1.0f64 - p0;
        let mu0 = meanc[i]/p0;
        let mu1 = (meanc[levels-1]/pixel_count - meanc[i])/p1;

        let sigma = p0*p1*(mu0-mu1).powi(2);
        if sigma >= sigma_max {
            if sigma > sigma_max {
                otsu = i as f64;
                sigma_max = sigma;
            } else {
                otsu2 = i as f64;
            }
        }
    }
    ( (otsu + otsu2) / 2.0 ).ceil() as u8
}

/// Returns a binarized image from an input 8bpp grayscale image
/// obtained by applying the given image
pub fn threshold<I>(image: &I, thresh: u8) -> GrayImage
    where I: GenericImage<Pixel=Luma<u8>> {

    let mut out: GrayImage = ImageBuffer::new(image.width(), image.height());
    out.copy_from(image, 0, 0);
    threshold_mut(&mut out, thresh);

    out
}

/// Mutates given image to form a binarized version produced by applying
/// the given threshold
pub fn threshold_mut<I>(image: &mut I, thresh: u8)
    where I: GenericImage<Pixel=Luma<u8>>  {
     for y in 0..image.height() {
            for x in 0..image.width() {
                if image.get_pixel(x, y)[0] as u8 <= thresh {
                    image.put_pixel(x, y, Luma([0]));
                } else {
                    image.put_pixel(x, y, Luma([255]));
                }
            }
        }
}

/// Returns the histogram of grayscale values in an 8pp
/// grayscale image.
pub fn histogram<I>(image: &I) -> [i32;256]
    where I: GenericImage<Pixel=Luma<u8>> {

    let mut hist = [0i32;256];

    for pix in image.pixels() {
        hist[pix.2[0] as usize] += 1;
    }

    hist
}

/// Returns the cumulative histogram of grayscale values in an 8bpp
/// grayscale image.
pub fn cumulative_histogram<I>(image: &I) -> [i32;256]
    where I: GenericImage<Pixel=Luma<u8>> {

    let mut hist = histogram(image);

    for i in 1..hist.len() {
        hist[i] += hist[i - 1];
    }

    hist
}

/// Equalises the histogram of an 8bpp grayscale image in place.
/// https://en.wikipedia.org/wiki/Histogram_equalization
pub fn equalize_histogram_mut<I>(image: &mut I)
    where I: GenericImage<Pixel=Luma<u8>> {

    let hist = cumulative_histogram(image);
    let total = hist[255] as f32;

    for y in 0..image.height() {
        for x in 0..image.width() {
            let original = image.get_pixel(x, y)[0] as usize;
            let fraction = hist[original] as f32 / total;
            let out = f32::min(255f32, 255f32 * fraction);
            image.put_pixel(x, y, Luma([out as u8]));
        }
    }
}

/// Equalises the histogram of an 8bpp grayscale image.
/// https://en.wikipedia.org/wiki/Histogram_equalization
pub fn equalize_histogram<I>(image: &I) -> GrayImage
    where I: GenericImage<Pixel=Luma<u8>> {

    let mut out: GrayImage = ImageBuffer::new(image.width(), image.height());
    out.copy_from(image, 0, 0);
    equalize_histogram_mut(&mut out);
    out
}

#[cfg(test)]
mod test {

    use super::{
        cumulative_histogram,
        equalize_histogram,
        histogram,
        otsu_level,
        threshold
    };
    use utils::{
        gray_bench_image
    };
    use image::{
        GrayImage,
        ImageBuffer
    };
    use test;

    #[test]
    fn test_cumulative_histogram() {
        let image: GrayImage = ImageBuffer::from_raw(5, 1, vec![
            1u8, 2u8, 3u8, 2u8, 1u8]).unwrap();

        let hist = cumulative_histogram(&image);

        assert_eq!(hist[0], 0);
        assert_eq!(hist[1], 2);
        assert_eq!(hist[2], 4);
        assert_eq!(hist[3], 5);
        assert!(hist.iter().skip(4).all(|x| *x == 5));
    }
    #[test]
    fn test_histogram(){
        let image: GrayImage = ImageBuffer::from_raw(5, 1, vec![
            1u8, 2u8, 3u8, 2u8, 1u8]).unwrap();

        let hist = histogram(&image);

        assert_eq!(hist[0], 0);
        assert_eq!(hist[1], 2);
        assert_eq!(hist[2], 2);
        assert_eq!(hist[3], 1);
    }
    #[test]
    fn test_otsu_level(){
        let image: GrayImage = ImageBuffer::from_raw(26, 1,
            vec![0u8, 10u8, 20u8, 30u8, 40u8, 50u8, 60u8, 70u8,
                80u8, 90u8, 100u8, 110u8, 120u8, 130u8, 140u8,
                150u8, 160u8, 170u8, 180u8, 190u8, 200u8,  210u8,
                220u8,  230u8,  240u8,  250u8]).unwrap();
        let level = otsu_level(&image);
        assert_eq!(level, 125);
    }
    #[test]
    fn test_threshold(){
        let original: GrayImage = ImageBuffer::from_raw(26, 1,
            vec![0u8, 10u8, 20u8, 30u8, 40u8, 50u8, 60u8, 70u8,
                80u8, 90u8, 100u8, 110u8, 120u8, 130u8, 140u8,
                150u8, 160u8, 170u8, 180u8, 190u8, 200u8,  210u8,
                220u8,  230u8,  240u8,  250u8]).unwrap();
        let expected: GrayImage = ImageBuffer::from_raw(26, 1,
            vec![0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8,
                0u8, 0u8, 0u8, 0u8, 0u8, 255u8, 255u8,
                255u8, 255u8, 255u8, 255u8, 255u8, 255u8,  255u8,
                255u8,  255u8,  255u8,  255u8]).unwrap();

        let actual = threshold(&original, 125u8);

        assert_pixels_eq!(expected, actual);
    }

    #[bench]
    fn bench_equalize_histogram(b: &mut test::Bencher) {
        let image = gray_bench_image(500, 500);
        b.iter(|| {
            let equalized = equalize_histogram(&image);
            test::black_box(equalized);
            });
    }
}<|endoftext|>


<commit_before>use std::process;
use std::fs::File;
use std::io::{Read, BufReader};

use serde_json;
use std::collections::HashMap;
use std::collections::HashSet;

use web::data::{APIMaps, IdGeneSubsetMap, APIGeneSummary, APIAlleleDetails,
                GeneDetails, TermDetails, GenotypeDetails, ReferenceDetails,
                InteractionType, OntAnnotationMap, IdOntAnnotationDetailMap,
                TermShort, TermShortOptionMap,
                ReferenceShort, ReferenceShortOptionMap,
                GeneShort, GeneShortOptionMap, GeneQueryData};
use web::config::Config;
use api::query::{SingleOrMultiAllele, QueryExpressionFilter};

use flate2::read::GzDecoder;

use types::GeneUniquename;

pub struct ServerData {
    config_file_name: String,
    maps: APIMaps,
    search_maps_file_name: String,
    gene_subsets: IdGeneSubsetMap,
    gene_subsets_file_name: String,
}

fn load(config: &Config, search_maps_file_name: &str, gene_subsets_file_name: &str)
        -> (APIMaps, IdGeneSubsetMap)
{
    let file = match File::open(search_maps_file_name) {
        Ok(file) => file,
        Err(err) => {
            print!("Failed to read {}: {}\n", search_maps_file_name, err);
            process::exit(1);
        }
    };
    let reader = BufReader::new(file);

    let mut decoder = GzDecoder::new(reader);
    let mut decoded_json = String::new();
    decoder.read_to_string(&mut decoded_json).unwrap();

    let query_api_maps: APIMaps =
        match serde_json::from_str(&decoded_json) {
            Ok(results) => results,
            Err(err) => {
                print!("failed to parse {}: {}", search_maps_file_name, err);
                process::exit(1);
            },
        };

    let file = match File::open(gene_subsets_file_name) {
        Ok(file) => file,
        Err(err) => {
            print!("Failed to read {}: {}\n", gene_subsets_file_name, err);
            process::exit(1);
        }
    };
    let reader = BufReader::new(file);

    let mut gene_subsets: IdGeneSubsetMap =
        match serde_json::from_reader(reader) {
            Ok(results) => results,
            Err(err) => {
                print!("failed to parse {}: {}", gene_subsets_file_name, err);
                process::exit(1);
            },
        };

    let mut new_entries: IdGeneSubsetMap = HashMap::new();

    let prefixes_to_remove: Vec<String> =
        config.server.subsets.prefixes_to_remove
        .iter().map(|prefix| prefix.clone() + ":").collect();

    // strip prefixes and add to map
    for (subset_name, subset_details) in &gene_subsets {
        for prefix in &prefixes_to_remove {
            if subset_name.starts_with(prefix) {
                let new_subset_name = &subset_name[prefix.len()..];
                new_entries.insert(String::from(new_subset_name), subset_details.clone());
            }
        }
    }

    gene_subsets.extend(new_entries);

    (query_api_maps, gene_subsets)
}

impl ServerData {
    pub fn new(config_file_name: &str, search_maps_file_name: &str,
               gene_subsets_file_name: &str)
               -> ServerData
    {
        let config = Config::read(config_file_name);

        let (maps, gene_subsets) =
            load(&config, search_maps_file_name, gene_subsets_file_name);
        ServerData {
            config_file_name: config_file_name.into(),
            search_maps_file_name: search_maps_file_name.into(),
            maps,
            gene_subsets_file_name: gene_subsets_file_name.into(),
            gene_subsets,
        }
    }

    pub fn gene_uniquename_of_id(&self, id: &str) -> Option<GeneUniquename> {
        if self.maps.gene_summaries.contains_key(id) {
            Some(id.to_owned())
        } else {
            if let Some(gene_uniquename) =
                self.maps.gene_name_gene_map.get(id) {
                    Some(gene_uniquename.clone())
                } else {
                    let lower_case_id = id.to_lowercase();
                    for gene_uniquename in self.maps.gene_summaries.keys() {
                        if gene_uniquename.to_lowercase() == lower_case_id {
                            return Some(gene_uniquename.clone());
                        }
                    }
                    None
                }
        }
    }

    pub fn get_gene_summary(&self, gene_uniquename: &str) -> Option<&APIGeneSummary> {
        self.maps.gene_summaries.get(gene_uniquename)
    }

    pub fn get_gene_details(&self, gene_uniquename: &str) -> Option<&GeneDetails> {
        self.maps.genes.get(gene_uniquename)
    }

    pub fn get_gene_query_data(&self, gene_uniquename: &str) -> Option<&GeneQueryData> {
        self.maps.gene_query_data_map.get(gene_uniquename)
    }

    pub fn genes_of_termid(&self, term_id: &str) -> Vec<GeneUniquename> {
        match self.maps.termid_genes.get(term_id) {
            Some(gene_uniquenames) => {
                gene_uniquenames.iter().cloned().collect::<Vec<_>>()
            },
            None => vec![],
        }
    }

    pub fn genes_of_subset(&self, search_name: &str) -> Vec<GeneUniquename> {
        if search_name.starts_with('!') || search_name.ends_with('*') {
            let mut trimmed_search_name = search_name.to_owned();
            let invert_search = search_name.starts_with('!');
            let wildcard = search_name.ends_with('*');
            if invert_search {
                trimmed_search_name.remove(0);
            }
            if wildcard {
                trimmed_search_name.pop();
            }
            let mut genes = HashSet::new();
            for (subset_name, subset_details) in &self.gene_subsets {
                let name_matches =
                    wildcard && subset_name.starts_with(&trimmed_search_name) ||
                    trimmed_search_name.eq(subset_name);

                if !invert_search && name_matches || invert_search && !name_matches {
                    genes.extend(subset_details.elements.iter().cloned());
                }
            }
            genes.iter().cloned().collect::<Vec<_>>()
        } else {
            match self.gene_subsets.get(search_name) {
                Some(subset_details) => {
                    subset_details.elements.iter().cloned().collect::<Vec<_>>()
                },
                None => vec![],
            }
        }
    }

    pub fn genes_of_genotypes(&self, term_id: &str,
                              single_or_multi_allele: &SingleOrMultiAllele,
                              expression_filter: &Option<QueryExpressionFilter>)
                              -> Vec<GeneUniquename>
    {
        if let Some(annotations) = self.maps.termid_genotype_annotation.get(term_id) {
            let mut genes: HashSet<GeneUniquename> = HashSet::new();
            for annotation in annotations {

                let mut add_single = false;
                let mut add_multi = false;

                match *single_or_multi_allele {
                    SingleOrMultiAllele::Single => add_single = true,
                    SingleOrMultiAllele::Multi => add_multi = true,
                    SingleOrMultiAllele::Both => {
                        add_single = true;
                        add_multi = true;
                    },
                }

                let expression_matches =
                    |allele_details: &APIAlleleDetails| {
                        let expression = &allele_details.expression;
                        let allele_type = &allele_details.allele_type;
                        if let Some(ref expression_filter) = *expression_filter {
                            if *expression_filter == QueryExpressionFilter::Any {
                                return true;
                            }
                            if *expression_filter == QueryExpressionFilter::Null {
                                if allele_type == "deletion" {
                                    return true;
                                }
                                if let Some(ref expression) = *expression {
                                    expression == "Null"
                                } else {
                                    false
                                }
                            } else {
                                if *expression_filter == QueryExpressionFilter::WtOverexpressed {
                                    if let Some(ref expression) = *expression {
                                        expression == "Overexpression" &&
                                            allele_type == "wild_type"
                                    } else {
                                        false
                                    }
                                } else {
                                    false
                                }
                            }
                        } else {
                            true
                        }
                    };

                if annotation.is_multi && add_multi ||
                    !annotation.is_multi && add_single &&
                    expression_matches(&annotation.alleles[0]) {
                        for allele_details in &annotation.alleles {
                            genes.insert(allele_details.gene.clone());
                        }
                }
            }
            genes.into_iter().collect::<Vec<_>>()
        } else {
            vec![]
        }
    }

    pub fn filter_genes(&self, p: &Fn(&APIGeneSummary) -> bool)
                        -> Vec<GeneUniquename>
    {
        self.maps.gene_summaries.values()
            .filter(|summ| p(summ))
            .map(|summ| summ.uniquename.clone())
            .collect()
    }

    fn detail_map_of_cv_annotations(&self, ont_annotation_map: &OntAnnotationMap)
                                    -> IdOntAnnotationDetailMap
    {
        let mut details_map = HashMap::new();

        for term_annotations in ont_annotation_map.values() {
            for term_annotation in term_annotations {
                for annotation_detail_id in &term_annotation.annotations {
                    let details =
                        &self.maps.annotation_details[annotation_detail_id];
                    details_map.insert(*annotation_detail_id, details.clone());
                }
            }
        }

        details_map
    }

    fn fill_term_map(&self, term_map: &TermShortOptionMap) -> TermShortOptionMap {
        let mut ret = term_map.clone();
        for termid in term_map.keys() {
            let term_details = &self.maps.terms[termid];
            let term_short = TermShort::from_term_details(&term_details);
            ret.insert(termid.clone(), Some(term_short));
        }
        ret
    }

    fn fill_gene_map(&self, gene_map: &GeneShortOptionMap) -> GeneShortOptionMap {
        let mut ret = gene_map.clone();
        for gene_uniquename in gene_map.keys() {
            let gene_details = &self.maps.genes[gene_uniquename];
            let gene_short = GeneShort::from_gene_details(gene_details);
            ret.insert(gene_uniquename.clone(), Some(gene_short));
        }
        ret
    }

    fn fill_reference_map(&self, reference_map: &ReferenceShortOptionMap) -> ReferenceShortOptionMap {
        let mut ret = reference_map.clone();
        for reference_uniquename in reference_map.keys() {
            let reference_details = &self.maps.references[reference_uniquename];
            let reference_short = ReferenceShort::from_reference_details(reference_details);
            ret.insert(reference_uniquename.clone(), Some(reference_short));
        }
        ret
    }

    // return a GeneDetails object with the term, genes and references maps filled in
    pub fn get_full_gene_details(&self, gene_uniquename: &str) -> Option<GeneDetails> {
        if let Some(gene_ref) = self.maps.genes.get(gene_uniquename) {
            let mut gene = gene_ref.clone();
            let details_map = self.detail_map_of_cv_annotations(&gene.cv_annotations);
            gene.annotation_details = details_map;
            gene.terms_by_termid = self.fill_term_map(&gene.terms_by_termid);
            gene.genes_by_uniquename = self.fill_gene_map(&gene.genes_by_uniquename);
            gene.references_by_uniquename =
                self.fill_reference_map(&gene.references_by_uniquename);
            Some(gene)
        } else {
            None
        }
    }

    pub fn get_genotype_details(&self, genotype_uniquename: &str) -> Option<GenotypeDetails> {
        if let Some(genotype_ref) = self.maps.genotypes.get(genotype_uniquename) {
            let mut genotype = genotype_ref.clone();
            let details_map = self.detail_map_of_cv_annotations(&genotype.cv_annotations);
            genotype.annotation_details = details_map;
            genotype.terms_by_termid = self.fill_term_map(&genotype.terms_by_termid);
            genotype.genes_by_uniquename = self.fill_gene_map(&genotype.genes_by_uniquename);
            genotype.references_by_uniquename =
                self.fill_reference_map(&genotype.references_by_uniquename);
            Some(genotype)
        } else {
            None
        }
    }

    pub fn get_term_details(&self, termid: &str) -> Option<TermDetails> {
        if let Some(term_ref) = self.maps.terms.get(termid) {
            let mut term = term_ref.clone();
            let details_map = self.detail_map_of_cv_annotations(&term.cv_annotations);
            term.annotation_details = details_map;
            term.terms_by_termid = self.fill_term_map(&term.terms_by_termid);
            term.genes_by_uniquename = self.fill_gene_map(&term.genes_by_uniquename);
            term.references_by_uniquename =
                self.fill_reference_map(&term.references_by_uniquename);
            Some(term)
        } else {
            None
        }
    }

    pub fn get_reference_details(&self, reference_uniquename: &str) -> Option<ReferenceDetails> {
        if let Some(reference_ref) = self.maps.references.get(reference_uniquename) {
            let mut reference = reference_ref.clone();
            let details_map = self.detail_map_of_cv_annotations(&reference.cv_annotations);
            reference.annotation_details = details_map;
            reference.terms_by_termid = self.fill_term_map(&reference.terms_by_termid);
            reference.genes_by_uniquename = self.fill_gene_map(&reference.genes_by_uniquename);
            Some(reference)
        } else {
            None
        }
    }

    pub fn interactors_of_genes(&self, gene_uniquename: &GeneUniquename,
                                interaction_type: InteractionType)
                                -> Vec<GeneUniquename> {
        if let Some(interactors) = self.maps.interactors_of_genes.get(gene_uniquename) {
            interactors.iter()
                .filter(|interactor| {
                    interactor.interaction_type == interaction_type
                })
                .map(|interactor| interactor.interactor_uniquename.clone())
                .collect::<Vec<_>>()
        } else {
            vec![]
        }
    }

    pub fn reload(&mut self) {
        let config = Config::read(&self.config_file_name);
        let (maps, gene_subsets) =
            load(&config, &self.search_maps_file_name,
                 &self.gene_subsets_file_name);
        self.maps = maps;
        self.gene_subsets = gene_subsets;
    }
}
<commit_msg>Warn, don't panic!() if term is missing from map<commit_after>use std::process;
use std::fs::File;
use std::io::{Read, BufReader};

use serde_json;
use std::collections::HashMap;
use std::collections::HashSet;

use web::data::{APIMaps, IdGeneSubsetMap, APIGeneSummary, APIAlleleDetails,
                GeneDetails, TermDetails, GenotypeDetails, ReferenceDetails,
                InteractionType, OntAnnotationMap, IdOntAnnotationDetailMap,
                TermShort, TermShortOptionMap,
                ReferenceShort, ReferenceShortOptionMap,
                GeneShort, GeneShortOptionMap, GeneQueryData};
use web::config::Config;
use api::query::{SingleOrMultiAllele, QueryExpressionFilter};

use flate2::read::GzDecoder;

use types::GeneUniquename;

pub struct ServerData {
    config_file_name: String,
    maps: APIMaps,
    search_maps_file_name: String,
    gene_subsets: IdGeneSubsetMap,
    gene_subsets_file_name: String,
}

fn load(config: &Config, search_maps_file_name: &str, gene_subsets_file_name: &str)
        -> (APIMaps, IdGeneSubsetMap)
{
    let file = match File::open(search_maps_file_name) {
        Ok(file) => file,
        Err(err) => {
            print!("Failed to read {}: {}\n", search_maps_file_name, err);
            process::exit(1);
        }
    };
    let reader = BufReader::new(file);

    let mut decoder = GzDecoder::new(reader);
    let mut decoded_json = String::new();
    decoder.read_to_string(&mut decoded_json).unwrap();

    let query_api_maps: APIMaps =
        match serde_json::from_str(&decoded_json) {
            Ok(results) => results,
            Err(err) => {
                print!("failed to parse {}: {}", search_maps_file_name, err);
                process::exit(1);
            },
        };

    let file = match File::open(gene_subsets_file_name) {
        Ok(file) => file,
        Err(err) => {
            print!("Failed to read {}: {}\n", gene_subsets_file_name, err);
            process::exit(1);
        }
    };
    let reader = BufReader::new(file);

    let mut gene_subsets: IdGeneSubsetMap =
        match serde_json::from_reader(reader) {
            Ok(results) => results,
            Err(err) => {
                print!("failed to parse {}: {}", gene_subsets_file_name, err);
                process::exit(1);
            },
        };

    let mut new_entries: IdGeneSubsetMap = HashMap::new();

    let prefixes_to_remove: Vec<String> =
        config.server.subsets.prefixes_to_remove
        .iter().map(|prefix| prefix.clone() + ":").collect();

    // strip prefixes and add to map
    for (subset_name, subset_details) in &gene_subsets {
        for prefix in &prefixes_to_remove {
            if subset_name.starts_with(prefix) {
                let new_subset_name = &subset_name[prefix.len()..];
                new_entries.insert(String::from(new_subset_name), subset_details.clone());
            }
        }
    }

    gene_subsets.extend(new_entries);

    (query_api_maps, gene_subsets)
}

impl ServerData {
    pub fn new(config_file_name: &str, search_maps_file_name: &str,
               gene_subsets_file_name: &str)
               -> ServerData
    {
        let config = Config::read(config_file_name);

        let (maps, gene_subsets) =
            load(&config, search_maps_file_name, gene_subsets_file_name);
        ServerData {
            config_file_name: config_file_name.into(),
            search_maps_file_name: search_maps_file_name.into(),
            maps,
            gene_subsets_file_name: gene_subsets_file_name.into(),
            gene_subsets,
        }
    }

    pub fn gene_uniquename_of_id(&self, id: &str) -> Option<GeneUniquename> {
        if self.maps.gene_summaries.contains_key(id) {
            Some(id.to_owned())
        } else {
            if let Some(gene_uniquename) =
                self.maps.gene_name_gene_map.get(id) {
                    Some(gene_uniquename.clone())
                } else {
                    let lower_case_id = id.to_lowercase();
                    for gene_uniquename in self.maps.gene_summaries.keys() {
                        if gene_uniquename.to_lowercase() == lower_case_id {
                            return Some(gene_uniquename.clone());
                        }
                    }
                    None
                }
        }
    }

    pub fn get_gene_summary(&self, gene_uniquename: &str) -> Option<&APIGeneSummary> {
        self.maps.gene_summaries.get(gene_uniquename)
    }

    pub fn get_gene_details(&self, gene_uniquename: &str) -> Option<&GeneDetails> {
        self.maps.genes.get(gene_uniquename)
    }

    pub fn get_gene_query_data(&self, gene_uniquename: &str) -> Option<&GeneQueryData> {
        self.maps.gene_query_data_map.get(gene_uniquename)
    }

    pub fn genes_of_termid(&self, term_id: &str) -> Vec<GeneUniquename> {
        match self.maps.termid_genes.get(term_id) {
            Some(gene_uniquenames) => {
                gene_uniquenames.iter().cloned().collect::<Vec<_>>()
            },
            None => vec![],
        }
    }

    pub fn genes_of_subset(&self, search_name: &str) -> Vec<GeneUniquename> {
        if search_name.starts_with('!') || search_name.ends_with('*') {
            let mut trimmed_search_name = search_name.to_owned();
            let invert_search = search_name.starts_with('!');
            let wildcard = search_name.ends_with('*');
            if invert_search {
                trimmed_search_name.remove(0);
            }
            if wildcard {
                trimmed_search_name.pop();
            }
            let mut genes = HashSet::new();
            for (subset_name, subset_details) in &self.gene_subsets {
                let name_matches =
                    wildcard && subset_name.starts_with(&trimmed_search_name) ||
                    trimmed_search_name.eq(subset_name);

                if !invert_search && name_matches || invert_search && !name_matches {
                    genes.extend(subset_details.elements.iter().cloned());
                }
            }
            genes.iter().cloned().collect::<Vec<_>>()
        } else {
            match self.gene_subsets.get(search_name) {
                Some(subset_details) => {
                    subset_details.elements.iter().cloned().collect::<Vec<_>>()
                },
                None => vec![],
            }
        }
    }

    pub fn genes_of_genotypes(&self, term_id: &str,
                              single_or_multi_allele: &SingleOrMultiAllele,
                              expression_filter: &Option<QueryExpressionFilter>)
                              -> Vec<GeneUniquename>
    {
        if let Some(annotations) = self.maps.termid_genotype_annotation.get(term_id) {
            let mut genes: HashSet<GeneUniquename> = HashSet::new();
            for annotation in annotations {

                let mut add_single = false;
                let mut add_multi = false;

                match *single_or_multi_allele {
                    SingleOrMultiAllele::Single => add_single = true,
                    SingleOrMultiAllele::Multi => add_multi = true,
                    SingleOrMultiAllele::Both => {
                        add_single = true;
                        add_multi = true;
                    },
                }

                let expression_matches =
                    |allele_details: &APIAlleleDetails| {
                        let expression = &allele_details.expression;
                        let allele_type = &allele_details.allele_type;
                        if let Some(ref expression_filter) = *expression_filter {
                            if *expression_filter == QueryExpressionFilter::Any {
                                return true;
                            }
                            if *expression_filter == QueryExpressionFilter::Null {
                                if allele_type == "deletion" {
                                    return true;
                                }
                                if let Some(ref expression) = *expression {
                                    expression == "Null"
                                } else {
                                    false
                                }
                            } else {
                                if *expression_filter == QueryExpressionFilter::WtOverexpressed {
                                    if let Some(ref expression) = *expression {
                                        expression == "Overexpression" &&
                                            allele_type == "wild_type"
                                    } else {
                                        false
                                    }
                                } else {
                                    false
                                }
                            }
                        } else {
                            true
                        }
                    };

                if annotation.is_multi && add_multi ||
                    !annotation.is_multi && add_single &&
                    expression_matches(&annotation.alleles[0]) {
                        for allele_details in &annotation.alleles {
                            genes.insert(allele_details.gene.clone());
                        }
                }
            }
            genes.into_iter().collect::<Vec<_>>()
        } else {
            vec![]
        }
    }

    pub fn filter_genes(&self, p: &Fn(&APIGeneSummary) -> bool)
                        -> Vec<GeneUniquename>
    {
        self.maps.gene_summaries.values()
            .filter(|summ| p(summ))
            .map(|summ| summ.uniquename.clone())
            .collect()
    }

    fn detail_map_of_cv_annotations(&self, ont_annotation_map: &OntAnnotationMap)
                                    -> IdOntAnnotationDetailMap
    {
        let mut details_map = HashMap::new();

        for term_annotations in ont_annotation_map.values() {
            for term_annotation in term_annotations {
                for annotation_detail_id in &term_annotation.annotations {
                    let details =
                        &self.maps.annotation_details[annotation_detail_id];
                    details_map.insert(*annotation_detail_id, details.clone());
                }
            }
        }

        details_map
    }

    fn fill_term_map(&self, term_map: &TermShortOptionMap) -> TermShortOptionMap {
        let mut ret = term_map.clone();
        for termid in term_map.keys() {
            if let Some(term_details) = self.maps.terms.get(termid) {
                let term_short = TermShort::from_term_details(term_details);
                ret.insert(termid.clone(), Some(term_short));
            } else {
                eprint!("WARNING missing short info for: {}\n", termid);
                ret.insert(termid.clone(), None);
            }
        }
        ret
    }

    fn fill_gene_map(&self, gene_map: &GeneShortOptionMap) -> GeneShortOptionMap {
        let mut ret = gene_map.clone();
        for gene_uniquename in gene_map.keys() {
            let gene_details = &self.maps.genes[gene_uniquename];
            let gene_short = GeneShort::from_gene_details(gene_details);
            ret.insert(gene_uniquename.clone(), Some(gene_short));
        }
        ret
    }

    fn fill_reference_map(&self, reference_map: &ReferenceShortOptionMap) -> ReferenceShortOptionMap {
        let mut ret = reference_map.clone();
        for reference_uniquename in reference_map.keys() {
            let reference_details = &self.maps.references[reference_uniquename];
            let reference_short = ReferenceShort::from_reference_details(reference_details);
            ret.insert(reference_uniquename.clone(), Some(reference_short));
        }
        ret
    }

    // return a GeneDetails object with the term, genes and references maps filled in
    pub fn get_full_gene_details(&self, gene_uniquename: &str) -> Option<GeneDetails> {
        if let Some(gene_ref) = self.maps.genes.get(gene_uniquename) {
            let mut gene = gene_ref.clone();
            let details_map = self.detail_map_of_cv_annotations(&gene.cv_annotations);
            gene.annotation_details = details_map;
            gene.terms_by_termid = self.fill_term_map(&gene.terms_by_termid);
            gene.genes_by_uniquename = self.fill_gene_map(&gene.genes_by_uniquename);
            gene.references_by_uniquename =
                self.fill_reference_map(&gene.references_by_uniquename);
            Some(gene)
        } else {
            None
        }
    }

    pub fn get_genotype_details(&self, genotype_uniquename: &str) -> Option<GenotypeDetails> {
        if let Some(genotype_ref) = self.maps.genotypes.get(genotype_uniquename) {
            let mut genotype = genotype_ref.clone();
            let details_map = self.detail_map_of_cv_annotations(&genotype.cv_annotations);
            genotype.annotation_details = details_map;
            genotype.terms_by_termid = self.fill_term_map(&genotype.terms_by_termid);
            genotype.genes_by_uniquename = self.fill_gene_map(&genotype.genes_by_uniquename);
            genotype.references_by_uniquename =
                self.fill_reference_map(&genotype.references_by_uniquename);
            Some(genotype)
        } else {
            None
        }
    }

    pub fn get_term_details(&self, termid: &str) -> Option<TermDetails> {
        if let Some(term_ref) = self.maps.terms.get(termid) {
            let mut term = term_ref.clone();
            let details_map = self.detail_map_of_cv_annotations(&term.cv_annotations);
            term.annotation_details = details_map;
            term.terms_by_termid = self.fill_term_map(&term.terms_by_termid);
            term.genes_by_uniquename = self.fill_gene_map(&term.genes_by_uniquename);
            term.references_by_uniquename =
                self.fill_reference_map(&term.references_by_uniquename);
            Some(term)
        } else {
            None
        }
    }

    pub fn get_reference_details(&self, reference_uniquename: &str) -> Option<ReferenceDetails> {
        if let Some(reference_ref) = self.maps.references.get(reference_uniquename) {
            let mut reference = reference_ref.clone();
            let details_map = self.detail_map_of_cv_annotations(&reference.cv_annotations);
            reference.annotation_details = details_map;
            reference.terms_by_termid = self.fill_term_map(&reference.terms_by_termid);
            reference.genes_by_uniquename = self.fill_gene_map(&reference.genes_by_uniquename);
            Some(reference)
        } else {
            None
        }
    }

    pub fn interactors_of_genes(&self, gene_uniquename: &GeneUniquename,
                                interaction_type: InteractionType)
                                -> Vec<GeneUniquename> {
        if let Some(interactors) = self.maps.interactors_of_genes.get(gene_uniquename) {
            interactors.iter()
                .filter(|interactor| {
                    interactor.interaction_type == interaction_type
                })
                .map(|interactor| interactor.interactor_uniquename.clone())
                .collect::<Vec<_>>()
        } else {
            vec![]
        }
    }

    pub fn reload(&mut self) {
        let config = Config::read(&self.config_file_name);
        let (maps, gene_subsets) =
            load(&config, &self.search_maps_file_name,
                 &self.gene_subsets_file_name);
        self.maps = maps;
        self.gene_subsets = gene_subsets;
    }
}
<|endoftext|>


<commit_before>//! Compositor: wm state including the layout, helm, and interactions
//! state machines.

use std::sync::RwLock;

use rustwlc;
use rustwlc::*;
use layout::try_lock_tree;

lazy_static! {
    static ref COMPOSITOR: RwLock<Compositor> = RwLock::new(Compositor::new());
}

const ERR_LOCK: &'static str = "Unable to lock compositor!";
const ERR_TREE: &'static str = "Unable to lock tree!";

#[derive(Debug, PartialEq)]
pub struct Compositor {
    pub view: Option<WlcView>,
    pub grab: Point,
    pub edges: ResizeEdge,
    //pub actions: ClientState
}

impl Compositor {
    fn new() -> Compositor {
        Compositor {
            view: None,
            grab: Point {x: 0, y: 0},
            edges: ResizeEdge::empty()
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct ClientState {
    view_action: ViewAction,
    next_action: ClickAction
}

impl Default for ClientState {
    fn default() -> ClientState {
        ClientState {
            view_action: ViewAction::None,
            next_action: ClickAction::None
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[allow(dead_code)]
pub enum ViewAction {
    None,
    Resize,
    Move
}

impl ViewAction {
    /// Is this ViewAction set
    #[allow(dead_code)]
    pub fn is_some(&self) -> bool {
        *self != ViewAction::None
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
/// Actions that the user may set before clicking on a window
#[allow(dead_code)]
enum ClickAction {
    None,
    CloseWindow,
    BeginMoving,
    BeginResizing,
    SelectWindow,

}

/// Makes the compositor no longer track the node to be used in some interaction
pub fn stop_interactive_action() {
    if let Ok(mut comp) = COMPOSITOR.write() {
        match comp.view {
            None => return,
            Some(ref view) => view.set_state(VIEW_RESIZING, false)
        }

        comp.view = None;
        comp.edges = ResizeEdge::empty();
    }
}

/// Automatically adds the view as the object of interest if there is no other
/// action currently being performed on some view
pub fn start_interactive_resize(view: &WlcView, edges: ResizeEdge, origin: &Point) {
    let geometry = match view.get_geometry() {
        None => { return; }
        Some(g) => g,
    };

    if start_interactive_action(view, origin).is_err() {
        return;
    }
    let halfw = geometry.origin.x + geometry.size.w as i32 / 2;
    let halfh = geometry.origin.y + geometry.size.h as i32 / 2;

    if let Ok(mut comp) = COMPOSITOR.write() {
        comp.edges = edges.clone();
        if comp.edges.bits() == 0 {
            let flag_x = if origin.x < halfw {
                RESIZE_LEFT
            } else if origin.x > halfw {
                RESIZE_RIGHT
            } else {
                ResizeEdge::empty()
            };

            let flag_y = if origin.y < halfh {
                RESIZE_TOP
            } else if origin.y > halfh {
                RESIZE_BOTTOM
            } else {
                ResizeEdge::empty()
            };

            comp.edges = flag_x | flag_y;
        }
    }
    view.set_state(VIEW_RESIZING, true);
}

/// Begin using the given view as the object of interest in an interactive
/// move. If another action is currently being performed,
/// this function returns false
pub fn start_interactive_move(view: &WlcView, origin: &Point) -> bool {
    if let Ok(mut comp) = COMPOSITOR.write() {
        if comp.view != None {
            return false;
        }
        comp.grab = origin.clone();
        comp.view = Some(view.clone());
        {
            let mut tree = try_lock_tree().expect(ERR_TREE);
            tree.set_active_container(view.clone());
        }
        true
    } else {
        false
    }

}

/// Performs an operation on a pointer button, to be used in the callback
pub fn on_pointer_button(view: WlcView, _time: u32, _mods: &KeyboardModifiers,
                         _button: u32, state: ButtonState, _point: &Point)
                         -> bool {
    if state == ButtonState::Pressed {
        if !view.is_root() {
            let mut tree = try_lock_tree().expect(ERR_TREE);
            tree.set_active_container(view.clone());
        }
    }
    else {
        stop_interactive_action();
    }

    let comp = COMPOSITOR.read().expect(ERR_LOCK);
    return comp.view.is_some()
}

/// Performs an operation on a pointer motion, to be used in the callback
pub fn on_pointer_motion(_view: WlcView, _time: u32, point: &Point) -> bool {
    rustwlc::input::pointer::set_position(point);
    if let Ok(mut comp) = COMPOSITOR.write() {
        comp.grab = point.clone();
        comp.view.is_some()
    } else {
        false
    }
}

/// Sets the given view to be the object of interest in some interactive action.
/// If another view is currently being used as the object of interest, an Err
/// is returned.
fn start_interactive_action(view: &WlcView, origin: &Point) -> Result<(), &'static str> {
    if let Ok(mut comp) = COMPOSITOR.write() {
        if comp.view != None {
            return Err("Compositor already interacting with another view");
        }
        comp.grab = origin.clone();
        comp.view = Some(view.clone());
        {
            let mut tree = try_lock_tree().expect(ERR_TREE);
            tree.set_active_container(view.clone());
        }
    }

    Ok(())
}

<commit_msg>Replaced compostior funcs with commands<commit_after>//! Compositor: wm state including the layout, helm, and interactions
//! state machines.

use std::sync::RwLock;

use rustwlc;
use rustwlc::*;
use layout::{try_lock_tree, commands as layout_cmds};

lazy_static! {
    static ref COMPOSITOR: RwLock<Compositor> = RwLock::new(Compositor::new());
}

const ERR_LOCK: &'static str = "Unable to lock compositor!";
const ERR_TREE: &'static str = "Unable to lock tree!";

#[derive(Debug, PartialEq)]
pub struct Compositor {
    pub view: Option<WlcView>,
    pub grab: Point,
    pub edges: ResizeEdge,
    //pub actions: ClientState
}

impl Compositor {
    fn new() -> Compositor {
        Compositor {
            view: None,
            grab: Point {x: 0, y: 0},
            edges: ResizeEdge::empty()
        }
    }
}

#[derive(Debug, PartialEq, Clone)]
pub struct ClientState {
    view_action: ViewAction,
    next_action: ClickAction
}

impl Default for ClientState {
    fn default() -> ClientState {
        ClientState {
            view_action: ViewAction::None,
            next_action: ClickAction::None
        }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
#[allow(dead_code)]
pub enum ViewAction {
    None,
    Resize,
    Move
}

impl ViewAction {
    /// Is this ViewAction set
    #[allow(dead_code)]
    pub fn is_some(&self) -> bool {
        *self != ViewAction::None
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
/// Actions that the user may set before clicking on a window
#[allow(dead_code)]
enum ClickAction {
    None,
    CloseWindow,
    BeginMoving,
    BeginResizing,
    SelectWindow,

}

/// Makes the compositor no longer track the node to be used in some interaction
pub fn stop_interactive_action() {
    if let Ok(mut comp) = COMPOSITOR.write() {
        match comp.view {
            None => return,
            Some(ref view) => view.set_state(VIEW_RESIZING, false)
        }

        comp.view = None;
        comp.edges = ResizeEdge::empty();
    }
}

/// Automatically adds the view as the object of interest if there is no other
/// action currently being performed on some view
pub fn start_interactive_resize(view: &WlcView, edges: ResizeEdge, origin: &Point) {
    let geometry = match view.get_geometry() {
        None => { return; }
        Some(g) => g,
    };

    if start_interactive_action(view, origin).is_err() {
        return;
    }
    let halfw = geometry.origin.x + geometry.size.w as i32 / 2;
    let halfh = geometry.origin.y + geometry.size.h as i32 / 2;

    if let Ok(mut comp) = COMPOSITOR.write() {
        comp.edges = edges.clone();
        if comp.edges.bits() == 0 {
            let flag_x = if origin.x < halfw {
                RESIZE_LEFT
            } else if origin.x > halfw {
                RESIZE_RIGHT
            } else {
                ResizeEdge::empty()
            };

            let flag_y = if origin.y < halfh {
                RESIZE_TOP
            } else if origin.y > halfh {
                RESIZE_BOTTOM
            } else {
                ResizeEdge::empty()
            };

            comp.edges = flag_x | flag_y;
        }
    }
    view.set_state(VIEW_RESIZING, true);
}

/// Begin using the given view as the object of interest in an interactive
/// move. If another action is currently being performed,
/// this function returns false
pub fn start_interactive_move(view: &WlcView, origin: &Point) -> bool {
    if let Ok(mut comp) = COMPOSITOR.write() {
        if comp.view != None {
            return false;
        }
        comp.grab = origin.clone();
        comp.view = Some(view.clone());
        if let Ok(mut tree) = try_lock_tree() {
            if let Err(err) = layout_cmds::set_active_view(&mut tree, view.clone()) {
                error!("start_interactive_move error: {}", err);
                return false
            } else {
                return true
            }
        }
    }
    return false
}

/// Performs an operation on a pointer button, to be used in the callback
pub fn on_pointer_button(view: WlcView, _time: u32, _mods: &KeyboardModifiers,
                         _button: u32, state: ButtonState, _point: &Point)
                         -> bool {
    if state == ButtonState::Pressed {
        if !view.is_root() {
            let mut tree = try_lock_tree().expect(ERR_TREE);
            tree.set_active_container(view.clone());
        }
    }
    else {
        stop_interactive_action();
    }

    let comp = COMPOSITOR.read().expect(ERR_LOCK);
    return comp.view.is_some()
}

/// Performs an operation on a pointer motion, to be used in the callback
pub fn on_pointer_motion(_view: WlcView, _time: u32, point: &Point) -> bool {
    rustwlc::input::pointer::set_position(point);
    if let Ok(mut comp) = COMPOSITOR.write() {
        comp.grab = point.clone();
        comp.view.is_some()
    } else {
        false
    }
}

/// Sets the given view to be the object of interest in some interactive action.
/// If another view is currently being used as the object of interest, an Err
/// is returned.
fn start_interactive_action(view: &WlcView, origin: &Point) -> Result<(), &'static str> {
    if let Ok(mut comp) = COMPOSITOR.write() {
        if comp.view != None {
            return Err("Compositor already interacting with another view");
        }
        comp.grab = origin.clone();
        comp.view = Some(view.clone());
        if let Ok(mut tree) = try_lock_tree() {
            return Ok(try!(layout_cmds::set_active_view(&mut tree, view.clone()).map_err(|_| {
                "start_interactive_action: Could not start move"
            })));
        }
    }
    Ok(())
}

<|endoftext|>


<commit_before>use regex::Regex;

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum TokenType {
    Number,
    ListStart,
    ListEnd,
    VectorStart,
    VectorEnd,
    HashMapStart,
    HashMapEnd,
    Symbol,
    Keyword
}

pub type Token = (TokenType, String);

pub struct Tokenizer {
    input: String,
    pos: usize
}

impl Tokenizer {
    pub fn new(input: &str) -> Tokenizer {
        Tokenizer { input: input.to_string(), pos: 0 }
    }
}

impl Iterator for Tokenizer {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        let input = &self.input[self.pos..];

        // Skip white space
        let input_trimmed = input.trim_left();
        self.pos += input.len() - input_trimmed.len();
        let input = input_trimmed;

        if input.starts_with('(') {
            self.pos += 1;
            return Some(token(TokenType::ListStart, "("))
        }

        if input.starts_with(')') {
            self.pos += 1;
            return Some(token(TokenType::ListEnd, ")"))
        }

        if input.starts_with('[') {
            self.pos += 1;
            return Some(token(TokenType::VectorStart, "["))
        }

        if input.starts_with(']') {
            self.pos += 1;
            return Some(token(TokenType::VectorEnd, "]"));
        }

        if input.starts_with('{') {
            self.pos += 1;
            return Some(token(TokenType::HashMapStart, "{"))
        }

        if input.starts_with('}') {
            self.pos += 1;
            return Some(token(TokenType::HashMapEnd, "}"));
        }

        let number_regexp = Regex::new(r"^-?\d+").unwrap();
        if let Some(cap) = number_regexp.captures(input) {
            self.pos += cap[0].len();
            return Some(token(TokenType::Number, cap[0].to_string()))
        }

        let symbol_regexp = Regex::new(r"^\S+").unwrap();
        if let Some(cap) = symbol_regexp.captures(input) {
            self.pos += cap[0].len();
            let cap_string = cap[0].to_string();
            if cap_string.starts_with(":") {
                return Some((TokenType::Keyword, cap_string))
            } else {
                return Some((TokenType::Symbol, cap_string))
            }
        }

        None
    }
}

fn token<S: Into<String>>(token_type: TokenType, s: S) -> Token {
    (token_type, s.into())
}

/* ------------------------------ Tests ----------------------------------------------- */

#[allow(dead_code)]
fn tokenize(input: &str) -> Vec<Token> {
    Tokenizer::new(input).collect()
}

#[test]
fn test_tokenizer() {
    assert_eq!(tokenize("42"), vec![(TokenType::Number, "42".to_string())]);
    assert_eq!(tokenize("("), vec![(TokenType::ListStart, "(".to_string())]);
    assert_eq!(tokenize(")"), vec![(TokenType::ListEnd, ")".to_string())]);
    assert_eq!(tokenize("( )"), vec![
        (TokenType::ListStart, "(".to_string()),
        (TokenType::ListEnd, ")".to_string())
    ]);
    assert_eq!(tokenize("(\n)"), vec![
        (TokenType::ListStart, "(".to_string()),
        (TokenType::ListEnd, ")".to_string())
    ]);
    assert_eq!(tokenize("(42)"), vec![
        (TokenType::ListStart, "(".to_string()),
        (TokenType::Number, "42".to_string()),
        (TokenType::ListEnd, ")".to_string())
    ]);
}

#[test]
fn test_tokenizer_symbol() {
    assert_eq!(tokenize("symbol"), vec![(TokenType::Symbol, "symbol".to_string())]);
    assert_eq!(tokenize("(+ 42)"), vec![
        (TokenType::ListStart, "(".to_string()),
        (TokenType::Symbol, "+".to_string()),
        (TokenType::Number, "42".to_string()),
        (TokenType::ListEnd, ")".to_string())
    ]);
}

#[test]
fn test_tokenizer_vector() {
    assert_eq!(tokenize("[]"), vec![
        token(TokenType::VectorStart, "["),
        token(TokenType::VectorEnd, "]")
    ]);
    assert_eq!(tokenize("[23 42]"), vec![
        token(TokenType::VectorStart, "["),
        token(TokenType::Number, "23"),
        token(TokenType::Number, "42"),
        token(TokenType::VectorEnd, "]")
    ]);
}

#[test]
fn test_empty_hashmap() {
    assert_eq!(tokenize("{}"), vec![
        token(TokenType::HashMapStart, "{"),
        token(TokenType::HashMapEnd, "}")
    ]);
}

#[test]
fn test_hashmap() {
    assert_eq!(tokenize("{:keyword 123}"), vec![
        token(TokenType::HashMapStart, "{"),
        token(TokenType::Keyword, ":keyword"),
        token(TokenType::Number, "123"),
        token(TokenType::HashMapEnd, "}")
    ]);
}<commit_msg>Fixed clippy warnings<commit_after>use regex::Regex;

#[derive(Debug, PartialEq, Copy, Clone)]
pub enum TokenType {
    Number,
    ListStart,
    ListEnd,
    VectorStart,
    VectorEnd,
    HashMapStart,
    HashMapEnd,
    Symbol,
    Keyword
}

pub type Token = (TokenType, String);

pub struct Tokenizer {
    input: String,
    pos: usize
}

impl Tokenizer {
    pub fn new(input: &str) -> Tokenizer {
        Tokenizer { input: input.to_string(), pos: 0 }
    }
}

impl Iterator for Tokenizer {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        let input = &self.input[self.pos..];

        // Skip white space
        let input_trimmed = input.trim_left();
        self.pos += input.len() - input_trimmed.len();
        let input = input_trimmed;

        if input.starts_with('(') {
            self.pos += 1;
            return Some(token(TokenType::ListStart, "("))
        }

        if input.starts_with(')') {
            self.pos += 1;
            return Some(token(TokenType::ListEnd, ")"))
        }

        if input.starts_with('[') {
            self.pos += 1;
            return Some(token(TokenType::VectorStart, "["))
        }

        if input.starts_with(']') {
            self.pos += 1;
            return Some(token(TokenType::VectorEnd, "]"));
        }

        if input.starts_with('{') {
            self.pos += 1;
            return Some(token(TokenType::HashMapStart, "{"))
        }

        if input.starts_with('}') {
            self.pos += 1;
            return Some(token(TokenType::HashMapEnd, "}"));
        }

        let number_regexp = Regex::new(r"^-?\d+").unwrap();
        if let Some(cap) = number_regexp.captures(input) {
            self.pos += cap[0].len();
            return Some(token(TokenType::Number, cap[0].to_string()))
        }

        let symbol_regexp = Regex::new(r"^\S+").unwrap();
        if let Some(cap) = symbol_regexp.captures(input) {
            self.pos += cap[0].len();
            let cap_string = cap[0].to_string();
            if cap_string.starts_with(':') {
                return Some((TokenType::Keyword, cap_string))
            } else {
                return Some((TokenType::Symbol, cap_string))
            }
        }

        None
    }
}

fn token<S: Into<String>>(token_type: TokenType, s: S) -> Token {
    (token_type, s.into())
}

/* ------------------------------ Tests ----------------------------------------------- */

#[allow(dead_code)]
fn tokenize(input: &str) -> Vec<Token> {
    Tokenizer::new(input).collect()
}

#[test]
fn test_tokenizer() {
    assert_eq!(tokenize("42"), vec![(TokenType::Number, "42".to_string())]);
    assert_eq!(tokenize("("), vec![(TokenType::ListStart, "(".to_string())]);
    assert_eq!(tokenize(")"), vec![(TokenType::ListEnd, ")".to_string())]);
    assert_eq!(tokenize("( )"), vec![
        (TokenType::ListStart, "(".to_string()),
        (TokenType::ListEnd, ")".to_string())
    ]);
    assert_eq!(tokenize("(\n)"), vec![
        (TokenType::ListStart, "(".to_string()),
        (TokenType::ListEnd, ")".to_string())
    ]);
    assert_eq!(tokenize("(42)"), vec![
        (TokenType::ListStart, "(".to_string()),
        (TokenType::Number, "42".to_string()),
        (TokenType::ListEnd, ")".to_string())
    ]);
}

#[test]
fn test_tokenizer_symbol() {
    assert_eq!(tokenize("symbol"), vec![(TokenType::Symbol, "symbol".to_string())]);
    assert_eq!(tokenize("(+ 42)"), vec![
        (TokenType::ListStart, "(".to_string()),
        (TokenType::Symbol, "+".to_string()),
        (TokenType::Number, "42".to_string()),
        (TokenType::ListEnd, ")".to_string())
    ]);
}

#[test]
fn test_tokenizer_vector() {
    assert_eq!(tokenize("[]"), vec![
        token(TokenType::VectorStart, "["),
        token(TokenType::VectorEnd, "]")
    ]);
    assert_eq!(tokenize("[23 42]"), vec![
        token(TokenType::VectorStart, "["),
        token(TokenType::Number, "23"),
        token(TokenType::Number, "42"),
        token(TokenType::VectorEnd, "]")
    ]);
}

#[test]
fn test_empty_hashmap() {
    assert_eq!(tokenize("{}"), vec![
        token(TokenType::HashMapStart, "{"),
        token(TokenType::HashMapEnd, "}")
    ]);
}

#[test]
fn test_hashmap() {
    assert_eq!(tokenize("{:keyword 123}"), vec![
        token(TokenType::HashMapStart, "{"),
        token(TokenType::Keyword, ":keyword"),
        token(TokenType::Number, "123"),
        token(TokenType::HashMapEnd, "}")
    ]);
}<|endoftext|>


<commit_before>use tokio_core::io::EasyBuf;

use protocol::Response;

#[test]
fn test_response_get_from_easybuf() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x00,
        0x04, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x09,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0xde, 0xad, 0xbe, 0xef,
        0x57, 0x6f, 0x72, 0x6c,
        0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);

    assert_eq!(response.extras().unwrap(), [0xde, 0xad, 0xbe, 0xef]);
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"World");
}

#[test]
fn test_response_getk_from_easybuf() {
    // I dunno why, but memcached doc have a mistake here,
    // it says that instead of `0x0e` "total body length" byte
    // there should be a `0x09` which is looks totally wrong.
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x05,
        0x04, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x0e,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0xde, 0xad, 0xbe, 0xef,
        0x48, 0x65, 0x6c, 0x6c,
        0x6f, 0x57, 0x6f, 0x72,
        0x6c, 0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);

    assert_eq!(response.extras().unwrap(), [0xde, 0xad, 0xbe, 0xef]);
    assert_eq!(response.key().unwrap(), b"Hello");
    assert_eq!(response.value().unwrap(), b"World");
}

#[test]
fn test_response_cas() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x02, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x02);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);
    assert_eq!(*response.cas(), 0x0000000000000001);

    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert!(response.value().is_none());
}

#[test]
fn test_response_incr_not_exists() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x05, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x05);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);
    assert_eq!(*response.cas(), 0x0000000000000005);

    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
}

#[test]
fn test_response_version() {
    /*
    Byte/     0       |       1       |       2       |       3       |
        /              |               |               |               |
       |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|
       +---------------+---------------+---------------+---------------+
      0| 0x81          | 0x0b          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
      4| 0x00          | 0x00          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
      8| 0x00          | 0x00          | 0x00          | 0x05          |
       +---------------+---------------+---------------+---------------+
     12| 0x00          | 0x00          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
     16| 0x00          | 0x00          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
     20| 0x00          | 0x00          | 0x00          | 0x00          |
       +---------------+---------------+---------------+---------------+
     24| 0x31 ('1')    | 0x2e ('.')    | 0x33 ('3')    | 0x2e ('.')    |
       +---------------+---------------+---------------+---------------+
     28| 0x31 ('1')    |
       +---------------+
       Total 29 bytes (24 byte header, 5 byte body)

   Field        (offset) (value)
   Magic        (0)    : 0x81
   Opcode       (1)    : 0x0b
   Key length   (2,3)  : 0x0000
   Extra length (4)    : 0x00
   Data type    (5)    : 0x00
   Status       (6,7)  : 0x0000
   Total body   (8-11) : 0x00000005
   Opaque       (12-15): 0x00000000
   CAS          (16-23): 0x0000000000000000
   Extras              : None
   Key                 : None
   Value               : Textual string "1.3.1"
    */
    let mut buf = EasyBuf::from(vec![
        0x81, 0x0b, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x31, 0x2e, 0x33, 0x2e,
        0x31,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x0b);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);
    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"1.3.1");
}

#[test]
fn test_response_error_not_found() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x09,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x4e, 0x6f, 0x74, 0x20,
        0x66, 0x6f, 0x75, 0x6e,
        0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0001);
    assert_eq!(*response.data_type(), 0x00);
    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"Not found");
}<commit_msg>Cleanup a little<commit_after>use tokio_core::io::EasyBuf;

use protocol::Response;

#[test]
fn test_response_get_from_easybuf() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x00,
        0x04, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x09,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0xde, 0xad, 0xbe, 0xef,
        0x57, 0x6f, 0x72, 0x6c,
        0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);

    assert_eq!(response.extras().unwrap(), [0xde, 0xad, 0xbe, 0xef]);
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"World");
}

#[test]
fn test_response_getk_from_easybuf() {
    // I dunno why, but memcached doc have a mistake here,
    // it says that instead of `0x0e` "total body length" byte
    // there should be a `0x09` which is looks totally wrong.
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x05,
        0x04, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x0e,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0xde, 0xad, 0xbe, 0xef,
        0x48, 0x65, 0x6c, 0x6c,
        0x6f, 0x57, 0x6f, 0x72,
        0x6c, 0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);

    assert_eq!(response.extras().unwrap(), [0xde, 0xad, 0xbe, 0xef]);
    assert_eq!(response.key().unwrap(), b"Hello");
    assert_eq!(response.value().unwrap(), b"World");
}

#[test]
fn test_response_cas() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x02, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x02);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);
    assert_eq!(*response.cas(), 0x0000000000000001);

    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert!(response.value().is_none());
}

#[test]
fn test_response_incr_not_exists() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x05, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x08,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x05);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);
    assert_eq!(*response.cas(), 0x0000000000000005);

    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
}

#[test]
fn test_response_version() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x0b, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x05,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x31, 0x2e, 0x33, 0x2e,
        0x31,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x0b);
    assert_eq!(*response.status(), 0x0000);
    assert_eq!(*response.data_type(), 0x00);
    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"1.3.1");
}

#[test]
fn test_response_error_not_found() {
    let mut buf = EasyBuf::from(vec![
        0x81, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x09,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x4e, 0x6f, 0x74, 0x20,
        0x66, 0x6f, 0x75, 0x6e,
        0x64,
    ]);

    let response = Response::try_from(&mut buf).unwrap().unwrap();

    assert_eq!(*response.command(), 0x00);
    assert_eq!(*response.status(), 0x0001);
    assert_eq!(*response.data_type(), 0x00);
    assert!(response.extras().is_none());
    assert!(response.key().is_none());
    assert_eq!(response.value().unwrap(), b"Not found");
}<|endoftext|>


<commit_before>use std::io::{IoResult};
use std::io::net::tcp::TcpStream;
use framing::Frame;

#[deriving(Clone)]
pub struct Connection {
    socket: TcpStream,
    pub frame_max_limit: u32
}

impl Connection {
    pub fn open(host: &str, port: u16) -> IoResult<Connection> {
        let mut socket = try!(TcpStream::connect(host, port));
        try!(socket.write([b'A', b'M', b'Q', b'P', 0, 0, 9, 1]));
        let connection = Connection { socket: socket, frame_max_limit: 131072 };
        Ok(connection)
    }

    pub fn close(&mut self) {
        self.socket.close_write().unwrap();
        self.socket.close_read().unwrap();
        //TODO: Need to drop socket somehow (Maybe have an Option<Socket>)
    }

    pub fn write(&mut self, frame: Frame) -> IoResult<()>{
        self.socket.write(frame.encode().as_slice())
    }

    pub fn read(&mut self) -> IoResult<Frame> {
        Frame::decode(&mut self.socket)
    }

}

<commit_msg>Update to recent rust.<commit_after>use std::io::{IoResult};
use std::io::net::tcp::TcpStream;
use framing::Frame;

#[deriving(Clone)]
pub struct Connection {
    socket: TcpStream,
    pub frame_max_limit: u32
}

impl Connection {
    pub fn open(host: &str, port: u16) -> IoResult<Connection> {
        let mut socket = try!(TcpStream::connect((host, port)));
        try!(socket.write([b'A', b'M', b'Q', b'P', 0, 0, 9, 1]));
        let connection = Connection { socket: socket, frame_max_limit: 131072 };
        Ok(connection)
    }

    pub fn close(&mut self) {
        self.socket.close_write().unwrap();
        self.socket.close_read().unwrap();
        //TODO: Need to drop socket somehow (Maybe have an Option<Socket>)
    }

    pub fn write(&mut self, frame: Frame) -> IoResult<()>{
        self.socket.write(frame.encode().as_slice())
    }

    pub fn read(&mut self) -> IoResult<Frame> {
        Frame::decode(&mut self.socket)
    }

}

<|endoftext|>