<commit_before>use std::fmt;
use std::io::{Cursor, Read, Write};
use std::collections::HashMap;
use std::rc::Rc;

use kite::schema::{FieldRef, SchemaRead};
use kite::query::Query;
use kite::query::term_scorer::TermScorer;
use kite::collectors::{Collector, DocumentMatch};
use rocksdb::DBVector;
use byteorder::{ByteOrder, BigEndian};

use key_builder::KeyBuilder;
use term_dictionary::TermRef;
use document_index::DocRef;
use super::super::RocksDBIndexReader;

pub enum DocIdSet {
    Owned(Vec<u8>),
    FromRDB(DBVector),
}

impl DocIdSet {
    pub fn new_filled(num_docs: u16) -> DocIdSet {
        let mut data: Vec<u8> = Vec::new();

        for doc_id in 0..num_docs {
            let mut doc_id_bytes = [0; 2];
            BigEndian::write_u16(&mut doc_id_bytes, doc_id);

            data.push(doc_id_bytes[0]);
            data.push(doc_id_bytes[1]);
        }

        DocIdSet::Owned(data)
    }

    pub fn iter<'a>(&'a self) -> DocIdSetIterator<'a> {
        let data = match *self {
            DocIdSet::Owned(ref data) => {
                &data[..]
            }
            DocIdSet::FromRDB(ref data) => {
                &data[..]
            }
        };

        DocIdSetIterator {
            cursor: Cursor::new(data),
        }
    }

    pub fn contains_doc(&self, doc_id: u16) -> bool {
        // TODO: optimise
        for d in self.iter() {
            if d == doc_id {
                return true;
            }
        }

        false
    }

    pub fn union(&self, other: &DocIdSet) -> DocIdSet {
        // TODO: optimise
        let mut data: Vec<u8> = Vec::new();

        let mut a = self.iter().peekable();
        let mut b = other.iter().peekable();

        loop {
            let mut next_a = false;
            let mut next_b = false;

            match (a.peek(), b.peek()) {
                (Some(a_doc), Some(b_doc)) => {
                    let mut doc_id_bytes = [0; 2];
                    BigEndian::write_u16(&mut doc_id_bytes, *a_doc);

                    data.push(doc_id_bytes[0]);
                    data.push(doc_id_bytes[1]);

                    if a_doc == b_doc {
                        next_a = true;
                        next_b = true;
                    } else if a_doc > b_doc {
                        next_b = true;
                    } else if a_doc < b_doc {
                        next_a = true;
                    }
                }
                (Some(a_doc), None) => {
                    let mut doc_id_bytes = [0; 2];
                    BigEndian::write_u16(&mut doc_id_bytes, *a_doc);

                    data.push(doc_id_bytes[0]);
                    data.push(doc_id_bytes[1]);

                    next_a = true;
                }
                (None, Some(b_doc)) => {
                    let mut doc_id_bytes = [0; 2];
                    BigEndian::write_u16(&mut doc_id_bytes, *b_doc);

                    data.push(doc_id_bytes[0]);
                    data.push(doc_id_bytes[1]);

                    next_b = true;
                }
                (None, None) => break
            }

            if next_a {
                a.next();
            }

            if next_b {
                b.next();
            }
        }

        DocIdSet::Owned(data)
    }

    pub fn intersection(&self, other: &DocIdSet) -> DocIdSet {
        // TODO: optimise
        let mut data: Vec<u8> = Vec::new();

        let mut a = self.iter().peekable();
        let mut b = other.iter().peekable();

        loop {
            let a_doc = match a.peek() {
                Some(a) => *a,
                None => break,
            };
            let b_doc = match b.peek() {
                Some(b) => *b,
                None => break,
            };

            if a_doc == b_doc {
                let mut doc_id_bytes = [0; 2];
                BigEndian::write_u16(&mut doc_id_bytes, a_doc);

                data.push(doc_id_bytes[0]);
                data.push(doc_id_bytes[1]);

                a.next();
                b.next();
            } else if a_doc > b_doc {
                b.next();
            } else if a_doc < b_doc {
                a.next();
            }
        }

        DocIdSet::Owned(data)
    }

    pub fn exclusion(&self, other: &DocIdSet) -> DocIdSet {
        // TODO: optimise
        let mut data: Vec<u8> = Vec::new();

        let mut a = self.iter().peekable();
        let mut b = other.iter().peekable();

        loop {
            let a_doc = match a.peek() {
                Some(a) => *a,
                None => break,
            };
            let b_doc = match b.peek() {
                Some(b) => *b,
                None => {
                    let mut doc_id_bytes = [0; 2];
                    BigEndian::write_u16(&mut doc_id_bytes, a_doc);

                    data.push(doc_id_bytes[0]);
                    data.push(doc_id_bytes[1]);

                    a.next();

                    continue;
                },
            };

            if a_doc == b_doc {
                a.next();
                b.next();
            } else if a_doc > b_doc {
                b.next();
            } else if a_doc < b_doc {
                let mut doc_id_bytes = [0; 2];
                BigEndian::write_u16(&mut doc_id_bytes, a_doc);

                data.push(doc_id_bytes[0]);
                data.push(doc_id_bytes[1]);

                a.next();
            }
        }

        DocIdSet::Owned(data)
    }
}

impl Clone for DocIdSet {
    fn clone(&self) -> DocIdSet {
        match *self {
            DocIdSet::Owned(ref data) => {
                DocIdSet::Owned(data.clone())
            }
            DocIdSet::FromRDB(ref data) => {
                let mut new_data = Vec::with_capacity(data.len());
                new_data.write_all(data);
                DocIdSet::Owned(new_data)
            }
        }
    }
}

impl fmt::Debug for DocIdSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut iterator = self.iter();

        try!(write!(f, "["));

        let first_item = iterator.next();
        if let Some(first_item) = first_item {
            try!(write!(f, "{:?}", first_item));
        }

        for item in iterator {
            try!(write!(f, ", {:?}", item));
        }

        write!(f, "]")
    }
}

pub struct DocIdSetIterator<'a> {
    cursor: Cursor<&'a [u8]>,
}

impl<'a> Iterator for DocIdSetIterator<'a> {
    type Item = u16;

    fn next(&mut self) -> Option<u16> {
        let mut buf = [0, 2];
        match self.cursor.read_exact(&mut buf) {
            Ok(()) => {
                Some(BigEndian::read_u16(&buf))
            }
            Err(_) => None
        }
    }
}
<commit_msg>Fixed DocIdSet.union<commit_after>use std::fmt;
use std::io::{Cursor, Read, Write};
use std::collections::HashMap;
use std::rc::Rc;

use kite::schema::{FieldRef, SchemaRead};
use kite::query::Query;
use kite::query::term_scorer::TermScorer;
use kite::collectors::{Collector, DocumentMatch};
use rocksdb::DBVector;
use byteorder::{ByteOrder, BigEndian};

use key_builder::KeyBuilder;
use term_dictionary::TermRef;
use document_index::DocRef;
use super::super::RocksDBIndexReader;

pub enum DocIdSet {
    Owned(Vec<u8>),
    FromRDB(DBVector),
}

impl DocIdSet {
    pub fn new_filled(num_docs: u16) -> DocIdSet {
        let mut data: Vec<u8> = Vec::new();

        for doc_id in 0..num_docs {
            let mut doc_id_bytes = [0; 2];
            BigEndian::write_u16(&mut doc_id_bytes, doc_id);

            data.push(doc_id_bytes[0]);
            data.push(doc_id_bytes[1]);
        }

        DocIdSet::Owned(data)
    }

    pub fn iter<'a>(&'a self) -> DocIdSetIterator<'a> {
        let data = match *self {
            DocIdSet::Owned(ref data) => {
                &data[..]
            }
            DocIdSet::FromRDB(ref data) => {
                &data[..]
            }
        };

        DocIdSetIterator {
            cursor: Cursor::new(data),
        }
    }

    pub fn contains_doc(&self, doc_id: u16) -> bool {
        // TODO: optimise
        for d in self.iter() {
            if d == doc_id {
                return true;
            }
        }

        false
    }

    pub fn union(&self, other: &DocIdSet) -> DocIdSet {
        // TODO: optimise
        let mut data: Vec<u8> = Vec::new();

        let mut a = self.iter().peekable();
        let mut b = other.iter().peekable();

        loop {
            let mut next_a = false;
            let mut next_b = false;

            match (a.peek(), b.peek()) {
                (Some(a_doc), Some(b_doc)) => {
                    let mut doc_id_bytes = [0; 2];

                    if a_doc == b_doc {
                        BigEndian::write_u16(&mut doc_id_bytes, *a_doc);

                        next_a = true;
                        next_b = true;
                    } else if a_doc > b_doc {
                        BigEndian::write_u16(&mut doc_id_bytes, *b_doc);

                        next_b = true;
                    } else if a_doc < b_doc {
                        BigEndian::write_u16(&mut doc_id_bytes, *a_doc);

                        next_a = true;
                    }

                    data.push(doc_id_bytes[0]);
                    data.push(doc_id_bytes[1]);
                }
                (Some(a_doc), None) => {
                    let mut doc_id_bytes = [0; 2];
                    BigEndian::write_u16(&mut doc_id_bytes, *a_doc);

                    data.push(doc_id_bytes[0]);
                    data.push(doc_id_bytes[1]);

                    next_a = true;
                }
                (None, Some(b_doc)) => {
                    let mut doc_id_bytes = [0; 2];
                    BigEndian::write_u16(&mut doc_id_bytes, *b_doc);

                    data.push(doc_id_bytes[0]);
                    data.push(doc_id_bytes[1]);

                    next_b = true;
                }
                (None, None) => break
            }

            if next_a {
                a.next();
            }

            if next_b {
                b.next();
            }
        }

        DocIdSet::Owned(data)
    }

    pub fn intersection(&self, other: &DocIdSet) -> DocIdSet {
        // TODO: optimise
        let mut data: Vec<u8> = Vec::new();

        let mut a = self.iter().peekable();
        let mut b = other.iter().peekable();

        loop {
            let a_doc = match a.peek() {
                Some(a) => *a,
                None => break,
            };
            let b_doc = match b.peek() {
                Some(b) => *b,
                None => break,
            };

            if a_doc == b_doc {
                let mut doc_id_bytes = [0; 2];
                BigEndian::write_u16(&mut doc_id_bytes, a_doc);

                data.push(doc_id_bytes[0]);
                data.push(doc_id_bytes[1]);

                a.next();
                b.next();
            } else if a_doc > b_doc {
                b.next();
            } else if a_doc < b_doc {
                a.next();
            }
        }

        DocIdSet::Owned(data)
    }

    pub fn exclusion(&self, other: &DocIdSet) -> DocIdSet {
        // TODO: optimise
        let mut data: Vec<u8> = Vec::new();

        let mut a = self.iter().peekable();
        let mut b = other.iter().peekable();

        loop {
            let a_doc = match a.peek() {
                Some(a) => *a,
                None => break,
            };
            let b_doc = match b.peek() {
                Some(b) => *b,
                None => {
                    let mut doc_id_bytes = [0; 2];
                    BigEndian::write_u16(&mut doc_id_bytes, a_doc);

                    data.push(doc_id_bytes[0]);
                    data.push(doc_id_bytes[1]);

                    a.next();

                    continue;
                },
            };

            if a_doc == b_doc {
                a.next();
                b.next();
            } else if a_doc > b_doc {
                b.next();
            } else if a_doc < b_doc {
                let mut doc_id_bytes = [0; 2];
                BigEndian::write_u16(&mut doc_id_bytes, a_doc);

                data.push(doc_id_bytes[0]);
                data.push(doc_id_bytes[1]);

                a.next();
            }
        }

        DocIdSet::Owned(data)
    }
}

impl Clone for DocIdSet {
    fn clone(&self) -> DocIdSet {
        match *self {
            DocIdSet::Owned(ref data) => {
                DocIdSet::Owned(data.clone())
            }
            DocIdSet::FromRDB(ref data) => {
                let mut new_data = Vec::with_capacity(data.len());
                new_data.write_all(data);
                DocIdSet::Owned(new_data)
            }
        }
    }
}

impl fmt::Debug for DocIdSet {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut iterator = self.iter();

        try!(write!(f, "["));

        let first_item = iterator.next();
        if let Some(first_item) = first_item {
            try!(write!(f, "{:?}", first_item));
        }

        for item in iterator {
            try!(write!(f, ", {:?}", item));
        }

        write!(f, "]")
    }
}

pub struct DocIdSetIterator<'a> {
    cursor: Cursor<&'a [u8]>,
}

impl<'a> Iterator for DocIdSetIterator<'a> {
    type Item = u16;

    fn next(&mut self) -> Option<u16> {
        let mut buf = [0, 2];
        match self.cursor.read_exact(&mut buf) {
            Ok(()) => {
                Some(BigEndian::read_u16(&buf))
            }
            Err(_) => None
        }
    }
}
<|endoftext|>


<commit_before>use std::path::Path;

use anyhow::{
    anyhow,
    Result,
};

use sorted_iter::{
    assume::*,
    SortedPairIterator,
};

use itertools::Itertools;

pub mod accession;
pub mod basic;
pub mod crs;
pub mod entry;
pub mod feedback;
pub mod go_annotation;
pub mod interacting_protein;
pub mod interacting_rna;
pub mod precompute;
pub mod qa_status;
pub mod r2dt;
pub mod rfam_hit;
pub mod so_tree;

use rnc_core::psql::JsonlIterator;

pub fn write_merge(
    base_file: &Path,
    crs_file: &Path,
    feedback_file: &Path,
    go_annotations_file: &Path,
    interacting_proteins_file: &Path,
    interacting_rnas_file: &Path,
    precompute_file: &Path,
    qa_status_file: &Path,
    r2dt_hits_file: &Path,
    rfam_hits_file: &Path,
    so_term_tree_file: &Path,
    output_file: &Path,
) -> Result<()> {
    let so_info = so_tree::load(&so_term_tree_file)?;
    let mut writer = rnc_utils::buf_writer(output_file)?;

    let base = JsonlIterator::from_path(base_file)?;
    let base = base.map(|b: basic::Basic| (b.id, b));
    let base = base.into_iter().assume_sorted_by_key();

    let crs = JsonlIterator::from_path(crs_file)?;
    let crs = crs.group_by(|c: &crs::Crs| c.id);
    let crs = crs.into_iter().assume_sorted_by_key();

    let feedback = JsonlIterator::from_path(feedback_file)?;
    let feedback = feedback.group_by(|f: &feedback::Feedback| f.id);
    let feedback = feedback.into_iter().assume_sorted_by_key();

    let go_annotations = JsonlIterator::from_path(go_annotations_file)?;
    let go_annotations = go_annotations.group_by(|f: &go_annotation::GoAnnotation| f.id);
    let go_annotations = go_annotations.into_iter().assume_sorted_by_key();

    let interacting_proteins = JsonlIterator::from_path(interacting_proteins_file)?;
    let interacting_proteins =
        interacting_proteins.group_by(|i: &interacting_protein::InteractingProtein| i.id);
    let interacting_proteins = interacting_proteins.into_iter().assume_sorted_by_key();

    let interacting_rnas = JsonlIterator::from_path(interacting_rnas_file)?;
    let interacting_rnas =
        interacting_rnas.group_by(|i: &interacting_rna::InteractingRna| i.id);
    let interacting_rnas = interacting_rnas.into_iter().assume_sorted_by_key();

    let precompute = JsonlIterator::from_path(precompute_file)?;
    let precompute = precompute.map(|p: precompute::Precompute| (p.id, p));
    let precompute = precompute.into_iter().assume_sorted_by_key();

    let qa_status = JsonlIterator::from_path(qa_status_file)?;
    let qa_status = qa_status.map(|q: qa_status::QaStatus| (q.id, q));
    let qa_status = qa_status.into_iter().assume_sorted_by_key();

    let r2dt_hits = JsonlIterator::from_path(r2dt_hits_file)?;
    let r2dt_hits = r2dt_hits.map(|h: r2dt::R2dt| (h.id, h));
    let r2dt_hits = r2dt_hits.into_iter().assume_sorted_by_key();

    let rfam_hits = JsonlIterator::from_path(rfam_hits_file)?;
    let rfam_hits = rfam_hits.group_by(|i: &rfam_hit::RfamHit| i.id);
    let rfam_hits = rfam_hits.into_iter().assume_sorted_by_key();

    let merged = base
        .join(precompute)
        .join(qa_status)
        .left_join(crs)
        .left_join(feedback)
        .left_join(go_annotations)
        .left_join(interacting_proteins)
        .left_join(interacting_rnas)
        .left_join(r2dt_hits)
        .left_join(rfam_hits);

    for (id, entry) in merged {
        let (
            (
                (
                    (
                        (((((basic, precompute), qa_status), crs), feedback), go_annotations),
                        interacting_proteins,
                    ),
                    interacting_rnas,
                ),
                r2dt_hits,
            ),
            rfam_hits,
        ) = entry;

        let so_rna_type_tree = so_info[precompute.so_rna_type()].clone();

        let raw = entry::Raw {
            id,
            base: basic,
            precompute,
            qa_status,
            crs: crs.into_iter().map(|g| g.into_iter()).flatten().collect(),
            feedback: feedback.into_iter().map(|g| g.into_iter()).flatten().collect(),
            go_annotations: go_annotations.into_iter().map(|g| g.into_iter()).flatten().collect(),
            interacting_proteins: interacting_proteins
                .into_iter()
                .map(|g| g.into_iter())
                .flatten()
                .collect(),
            interacting_rnas: interacting_rnas
                .into_iter()
                .map(|g| g.into_iter())
                .flatten()
                .collect(),
            r2dt: r2dt_hits,
            rfam_hits: rfam_hits.into_iter().map(|g| g.into_iter()).flatten().collect(),
            so_tree: so_rna_type_tree,
        };

        serde_json::to_writer(&mut writer, &raw)?;
        writeln!(&mut writer)?;
    }

    Ok(())
}

pub fn write(accession_file: &Path, metadata_file: &Path, output_file: &Path) -> Result<()> {
    let mut writer = rnc_utils::buf_writer(output_file)?;

    let metadata = JsonlIterator::from_path(metadata_file)?;
    let metadata = metadata.map(|r: entry::Raw| (r.id, r));
    let metadata = metadata.into_iter().assume_sorted_by_key();

    let accessions = JsonlIterator::from_path(accession_file)?;
    let accessions = accessions.group_by(|a: &accession::RawAccession| a.id);
    let accessions = accessions.into_iter().assume_sorted_by_key();

    let merged = accessions.join(metadata);

    let mut seen = false;
    for (_id, entry) in merged {
        let (accessions, metadata) = entry;
        let normalized = entry::Normalized::new(metadata, accessions.collect())?;
        serde_json::to_writer(&mut writer, &normalized)?;
        writeln!(&mut writer)?;
        seen = true;
    }

    if !seen {
        return Err(anyhow!("Failed to find any normalized data"));
    }

    Ok(())
}
<commit_msg>Error and message for missing SO terms<commit_after>use std::path::Path;

use anyhow::{
    anyhow,
    Result,
};

use sorted_iter::{
    assume::*,
    SortedPairIterator,
};

use itertools::Itertools;

pub mod accession;
pub mod basic;
pub mod crs;
pub mod entry;
pub mod feedback;
pub mod go_annotation;
pub mod interacting_protein;
pub mod interacting_rna;
pub mod precompute;
pub mod qa_status;
pub mod r2dt;
pub mod rfam_hit;
pub mod so_tree;

use rnc_core::psql::JsonlIterator;

pub fn write_merge(
    base_file: &Path,
    crs_file: &Path,
    feedback_file: &Path,
    go_annotations_file: &Path,
    interacting_proteins_file: &Path,
    interacting_rnas_file: &Path,
    precompute_file: &Path,
    qa_status_file: &Path,
    r2dt_hits_file: &Path,
    rfam_hits_file: &Path,
    so_term_tree_file: &Path,
    output_file: &Path,
) -> Result<()> {
    let so_info = so_tree::load(&so_term_tree_file)?;
    let mut writer = rnc_utils::buf_writer(output_file)?;

    let base = JsonlIterator::from_path(base_file)?;
    let base = base.map(|b: basic::Basic| (b.id, b));
    let base = base.into_iter().assume_sorted_by_key();

    let crs = JsonlIterator::from_path(crs_file)?;
    let crs = crs.group_by(|c: &crs::Crs| c.id);
    let crs = crs.into_iter().assume_sorted_by_key();

    let feedback = JsonlIterator::from_path(feedback_file)?;
    let feedback = feedback.group_by(|f: &feedback::Feedback| f.id);
    let feedback = feedback.into_iter().assume_sorted_by_key();

    let go_annotations = JsonlIterator::from_path(go_annotations_file)?;
    let go_annotations = go_annotations.group_by(|f: &go_annotation::GoAnnotation| f.id);
    let go_annotations = go_annotations.into_iter().assume_sorted_by_key();

    let interacting_proteins = JsonlIterator::from_path(interacting_proteins_file)?;
    let interacting_proteins =
        interacting_proteins.group_by(|i: &interacting_protein::InteractingProtein| i.id);
    let interacting_proteins = interacting_proteins.into_iter().assume_sorted_by_key();

    let interacting_rnas = JsonlIterator::from_path(interacting_rnas_file)?;
    let interacting_rnas = interacting_rnas.group_by(|i: &interacting_rna::InteractingRna| i.id);
    let interacting_rnas = interacting_rnas.into_iter().assume_sorted_by_key();

    let precompute = JsonlIterator::from_path(precompute_file)?;
    let precompute = precompute.map(|p: precompute::Precompute| (p.id, p));
    let precompute = precompute.into_iter().assume_sorted_by_key();

    let qa_status = JsonlIterator::from_path(qa_status_file)?;
    let qa_status = qa_status.map(|q: qa_status::QaStatus| (q.id, q));
    let qa_status = qa_status.into_iter().assume_sorted_by_key();

    let r2dt_hits = JsonlIterator::from_path(r2dt_hits_file)?;
    let r2dt_hits = r2dt_hits.map(|h: r2dt::R2dt| (h.id, h));
    let r2dt_hits = r2dt_hits.into_iter().assume_sorted_by_key();

    let rfam_hits = JsonlIterator::from_path(rfam_hits_file)?;
    let rfam_hits = rfam_hits.group_by(|i: &rfam_hit::RfamHit| i.id);
    let rfam_hits = rfam_hits.into_iter().assume_sorted_by_key();

    let merged = base
        .join(precompute)
        .join(qa_status)
        .left_join(crs)
        .left_join(feedback)
        .left_join(go_annotations)
        .left_join(interacting_proteins)
        .left_join(interacting_rnas)
        .left_join(r2dt_hits)
        .left_join(rfam_hits);

    for (id, entry) in merged {
        let (
            (
                (
                    (
                        (((((basic, precompute), qa_status), crs), feedback), go_annotations),
                        interacting_proteins,
                    ),
                    interacting_rnas,
                ),
                r2dt_hits,
            ),
            rfam_hits,
        ) = entry;

        let pre_so_type = precompute.so_rna_type();
        if !so_info.contains_key(pre_so_type) {
            return Err(anyhow!("Could not find SeqOnt info for {}", &pre_so_type));
        }
        let so_rna_type_tree = so_info[pre_so_type].clone();

        let raw = entry::Raw {
            id,
            base: basic,
            precompute,
            qa_status,
            crs: crs.into_iter().map(|g| g.into_iter()).flatten().collect(),
            feedback: feedback.into_iter().map(|g| g.into_iter()).flatten().collect(),
            go_annotations: go_annotations.into_iter().map(|g| g.into_iter()).flatten().collect(),
            interacting_proteins: interacting_proteins
                .into_iter()
                .map(|g| g.into_iter())
                .flatten()
                .collect(),
            interacting_rnas: interacting_rnas
                .into_iter()
                .map(|g| g.into_iter())
                .flatten()
                .collect(),
            r2dt: r2dt_hits,
            rfam_hits: rfam_hits.into_iter().map(|g| g.into_iter()).flatten().collect(),
            so_tree: so_rna_type_tree,
        };

        serde_json::to_writer(&mut writer, &raw)?;
        writeln!(&mut writer)?;
    }

    Ok(())
}

pub fn write(accession_file: &Path, metadata_file: &Path, output_file: &Path) -> Result<()> {
    let mut writer = rnc_utils::buf_writer(output_file)?;

    let metadata = JsonlIterator::from_path(metadata_file)?;
    let metadata = metadata.map(|r: entry::Raw| (r.id, r));
    let metadata = metadata.into_iter().assume_sorted_by_key();

    let accessions = JsonlIterator::from_path(accession_file)?;
    let accessions = accessions.group_by(|a: &accession::RawAccession| a.id);
    let accessions = accessions.into_iter().assume_sorted_by_key();

    let merged = accessions.join(metadata);

    let mut seen = false;
    for (_id, entry) in merged {
        let (accessions, metadata) = entry;
        let normalized = entry::Normalized::new(metadata, accessions.collect())?;
        serde_json::to_writer(&mut writer, &normalized)?;
        writeln!(&mut writer)?;
        seen = true;
    }

    if !seen {
        return Err(anyhow!("Failed to find any normalized data"));
    }

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use bytecode::{
    borrow_analysis::BorrowAnalysisProcessor, clean_and_optimize::CleanAndOptimizeProcessor,
    eliminate_imm_refs::EliminateImmRefsProcessor, eliminate_mut_refs::EliminateMutRefsProcessor,
    function_target_pipeline::FunctionTargetProcessor, livevar_analysis::LiveVarAnalysisProcessor,
    memory_instrumentation::MemoryInstrumentationProcessor,
    reaching_def_analysis::ReachingDefProcessor, usage_analysis::UsageProcessor,
    verification_analysis::VerificationAnalysisProcessor,
};

/// Allows client to decide between one of two pipelines for ease of benchmarking
pub fn pipelines(experimental_pipeline: bool) -> Vec<Box<dyn FunctionTargetProcessor + 'static>> {
    println!("option is {}", experimental_pipeline);
    let vec: Vec<Box<dyn FunctionTargetProcessor + 'static>> = if experimental_pipeline == false {
        vec![
            EliminateImmRefsProcessor::new(),
            EliminateMutRefsProcessor::new(),
            ReachingDefProcessor::new(),
            LiveVarAnalysisProcessor::new(),
            BorrowAnalysisProcessor::new(),
            MemoryInstrumentationProcessor::new(),
            CleanAndOptimizeProcessor::new(),
            UsageProcessor::new(),
            VerificationAnalysisProcessor::new(),
        ]
    }
    // Enter your pipeline here
    else {
        panic!("No experimental pipeline set");
    };
    vec
}
<commit_msg>[move-prove] removed println accidentally left in; reformat to pass lint test<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![forbid(unsafe_code)]

use bytecode::{
    borrow_analysis::BorrowAnalysisProcessor, clean_and_optimize::CleanAndOptimizeProcessor,
    eliminate_imm_refs::EliminateImmRefsProcessor, eliminate_mut_refs::EliminateMutRefsProcessor,
    function_target_pipeline::FunctionTargetProcessor, livevar_analysis::LiveVarAnalysisProcessor,
    memory_instrumentation::MemoryInstrumentationProcessor,
    reaching_def_analysis::ReachingDefProcessor, usage_analysis::UsageProcessor,
    verification_analysis::VerificationAnalysisProcessor,
};

/// Allows client to decide between one of two pipelines for ease of benchmarking
pub fn pipelines(experimental_pipeline: bool) -> Vec<Box<dyn FunctionTargetProcessor + 'static>> {
    let vec: Vec<Box<dyn FunctionTargetProcessor + 'static>> = if !experimental_pipeline {
        vec![
            EliminateImmRefsProcessor::new(),
            EliminateMutRefsProcessor::new(),
            ReachingDefProcessor::new(),
            LiveVarAnalysisProcessor::new(),
            BorrowAnalysisProcessor::new(),
            MemoryInstrumentationProcessor::new(),
            CleanAndOptimizeProcessor::new(),
            UsageProcessor::new(),
            VerificationAnalysisProcessor::new(),
        ]
    }
    // Enter your pipeline here
    else {
        panic!("No experimental pipeline set");
    };
    vec
}
<|endoftext|>


<commit_before>use rustc_serialize::json::{self, Json, Object};
use rustc_serialize::base64::{self, ToBase64};
use amqp::protocol::basic::{Deliver, BasicProperties};
use amqp::TableEntry;
use error::RbtError;

#[derive(RustcEncodable)]
struct MsgDeliver {
    consumer_tag: String,
    delivery_tag: u64,
    redelivered: bool,
    exchange: String,
    routing_key: String,
}

#[derive(RustcEncodable)]
struct MsgProps {
    content_type: String,
    headers: Object,
}

#[derive(RustcEncodable)]
struct Msg {
    deliver: MsgDeliver,
    props: MsgProps,
    data: Json,
}

pub fn build_output(info:bool, deliver:&Deliver,
                    props:&BasicProperties, body:Vec<u8>) -> Result<Vec<u8>,RbtError> {
    if info {

        // delivery info
        let mdel = MsgDeliver {
            consumer_tag:deliver.consumer_tag.clone(),
            delivery_tag:deliver.delivery_tag.clone(),
            redelivered:deliver.redelivered.clone(),
            exchange:deliver.exchange.clone(),
            routing_key:deliver.routing_key.clone(),
        };

        let content_type = props.content_type.clone().unwrap_or(String::from(""));

        // properties
        let mut mprops = MsgProps {
            content_type:content_type.clone(),
            headers: Object::new(),
        };

        if let Some(table) = props.headers.clone() {
            for (skey, entry) in table {
                let key = skey.to_owned();
                let val = entry_to_json(entry)?;
                mprops.headers.insert(key, val);
            }
        }

        // the body
        let data = figure_out_body(content_type, body)?;

        // and put it together
        let msg = Msg {
            deliver:mdel,
            props:mprops,
            data:data,
        };

        // encode
        let js = json::as_pretty_json(&msg);

        // convert to bytes
        Ok(js.to_string().as_bytes().to_owned())

    } else {

        let content_type = props.content_type.clone().unwrap_or(String::from(""));

        match content_type.as_ref() {
            "application/json" => {
                // interpret body so we can pretty print it
                let body = figure_out_body(content_type, body)?;

                // encode back as pretty
                let js = json::as_pretty_json(&body);

                // convert to bytes
                Ok(js.to_string().as_bytes().to_owned())
            },

            // just return untranslated bytes
            _ => Ok(body)
        }

    }
}

fn figure_out_body(content_type:String, body:Vec<u8>) -> Result<Json,RbtError> {

    // depending on content type, do something
    match content_type.as_ref() {
        "application/json" => Ok(Json::from_str(&String::from_utf8(body)?)?),
        _ => Ok(match content_type.find("text/") {
            Some(_) => Json::String(String::from_utf8(body)?),
            _ => Json::String(body.to_base64(base64::STANDARD))
        })
    }

}

fn entry_to_json(entry:TableEntry) -> Result<Json,String> {
    match entry {
        TableEntry::Bool(v)           => Ok(Json::Boolean(v)),
        TableEntry::ShortShortInt(v)  => Ok(Json::I64(v as i64)),
        TableEntry::ShortShortUint(v) => Ok(Json::U64(v as u64)),
        TableEntry::ShortInt(v)       => Ok(Json::I64(v as i64)),
        TableEntry::ShortUint(v)      => Ok(Json::U64(v as u64)),
        TableEntry::LongInt(v)        => Ok(Json::I64(v as i64)),
        TableEntry::LongUint(v)       => Ok(Json::U64(v as u64)),
        TableEntry::LongLongInt(v)    => Ok(Json::I64(v)),
        TableEntry::LongLongUint(v)   => Ok(Json::U64(v)),
        TableEntry::Float(v)          => Ok(Json::F64(v as f64)),
        TableEntry::Double(v)         => Ok(Json::F64(v)),
        TableEntry::LongString(v)     => Ok(Json::String(v)),
        TableEntry::Void              => Ok(Json::Null),
        _                             => Err(format!("Cant translate {:?}", entry)),
        // ShortString(String),
        // TableEntry::FieldTable(Table) =>
        // TableEntry::Timestamp(u64) =>
        // TableEntry::FieldArray(Vec<TableEntry>) =>
        // TableEntry::DecimalValue(u8, u32) => mprops.headers.insert(key, v),
    }
}
<commit_msg>ensure we can translate nested tables/arrays<commit_after>use rustc_serialize::json::{self, Json, Object};
use rustc_serialize::base64::{self, ToBase64};
use amqp::protocol::basic::{Deliver, BasicProperties};
use amqp::{Table, TableEntry};
use error::RbtError;

#[derive(RustcEncodable)]
struct MsgDeliver {
    consumer_tag: String,
    delivery_tag: u64,
    redelivered: bool,
    exchange: String,
    routing_key: String,
}

#[derive(RustcEncodable)]
struct MsgProps {
    content_type: String,
    headers: Object,
}

#[derive(RustcEncodable)]
struct Msg {
    deliver: MsgDeliver,
    props: MsgProps,
    data: Json,
}

pub fn build_output(info:bool, deliver:&Deliver,
                    props:&BasicProperties, body:Vec<u8>) -> Result<Vec<u8>,RbtError> {
    if info {

        // delivery info
        let mdel = MsgDeliver {
            consumer_tag:deliver.consumer_tag.clone(),
            delivery_tag:deliver.delivery_tag.clone(),
            redelivered:deliver.redelivered.clone(),
            exchange:deliver.exchange.clone(),
            routing_key:deliver.routing_key.clone(),
        };

        let content_type = props.content_type.clone().unwrap_or(String::from(""));

        // properties
        let mut mprops = MsgProps {
            content_type:content_type.clone(),
            headers: Object::new(),
        };

        if let Some(ref table) = props.headers {
            mprops.headers = table_to_json(table)?;
        }

        // the body
        let data = figure_out_body(content_type, body)?;

        // and put it together
        let msg = Msg {
            deliver:mdel,
            props:mprops,
            data:data,
        };

        // encode
        let js = json::as_pretty_json(&msg);

        // convert to bytes
        Ok(js.to_string().as_bytes().to_owned())

    } else {

        let content_type = props.content_type.clone().unwrap_or(String::from(""));

        match content_type.as_ref() {
            "application/json" => {
                // interpret body so we can pretty print it
                let body = figure_out_body(content_type, body)?;

                // encode back as pretty
                let js = json::as_pretty_json(&body);

                // convert to bytes
                Ok(js.to_string().as_bytes().to_owned())
            },

            // just return untranslated bytes
            _ => Ok(body)
        }

    }
}

fn figure_out_body(content_type:String, body:Vec<u8>) -> Result<Json,RbtError> {

    // depending on content type, do something
    match content_type.as_ref() {
        "application/json" => Ok(Json::from_str(&String::from_utf8(body)?)?),
        _ => Ok(match content_type.find("text/") {
            Some(_) => Json::String(String::from_utf8(body)?),
            _ => Json::String(body.to_base64(base64::STANDARD))
        })
    }

}

fn table_to_json(table:&Table) -> Result<Object,String> {
    let mut ret = Object::new();
    for (skey, entry) in table {
        let key = skey.clone().to_string();
        let val = entry_to_json(&entry)?;
        ret.insert(key, val);
    }
    Ok(ret)
}

fn entry_to_json(entry:&TableEntry) -> Result<Json,String> {
    match *entry {
        TableEntry::Bool(v)           => Ok(Json::Boolean(v)),
        TableEntry::ShortShortInt(v)  => Ok(Json::I64(v as i64)),
        TableEntry::ShortShortUint(v) => Ok(Json::U64(v as u64)),
        TableEntry::ShortInt(v)       => Ok(Json::I64(v as i64)),
        TableEntry::ShortUint(v)      => Ok(Json::U64(v as u64)),
        TableEntry::LongInt(v)        => Ok(Json::I64(v as i64)),
        TableEntry::LongUint(v)       => Ok(Json::U64(v as u64)),
        TableEntry::LongLongInt(v)    => Ok(Json::I64(v)),
        TableEntry::LongLongUint(v)   => Ok(Json::U64(v)),
        TableEntry::Float(v)          => Ok(Json::F64(v as f64)),
        TableEntry::Double(v)         => Ok(Json::F64(v)),
        TableEntry::LongString(ref v) => Ok(Json::String(v.clone())),
        TableEntry::Void              => Ok(Json::Null),
        TableEntry::FieldTable(ref v) => Ok(Json::Object(table_to_json(&v)?)),
        TableEntry::FieldArray(ref vs) => {
            let mut ret:Vec<Json> = Vec::new();
            for v in vs { ret.push(entry_to_json(v)?) }
            Ok(Json::Array(ret))
        },
        TableEntry::Timestamp(v)      => Ok(Json::U64(v as u64)), // maybe string date?
        TableEntry::DecimalValue(decimals, v) => {
            let ten:f64 = (10 as u64).pow(decimals as u32) as f64;
            let dec:f64 = (v as f64) / ten;
            Ok(Json::F64(dec))
        },
        //_                             => Err(format!("Cant translate {:?}", entry)),
        // TableEntry::ShortString(ref v) => Ok(Json::String(v.clone())),
    }
}
<|endoftext|>


<commit_before>//! Author : Thibault Barbie
//!
//! A simple evolutionary algorithm written in Rust.

extern crate rand;

use std::collections::HashMap;
use rand::Rng;

fn main() {
    let target: String = String::from("METHINKS IT IS LIKE A WEASEL");
    let mut parent: String = String::new();
    let nb_copy = 400;
    let mutation_rate: f64 = 0.05;
    let mut counter = 0;

    generate_first_sentence(&mut parent);

    println!("{}", target);
    println!("{}", parent);
    while fitness(&target, &parent) != 0 {
        let mut sentences: HashMap<u32, String> = HashMap::new();
        let mut f_min: u32 = 30;

        counter += 1;

        for _ in 0..nb_copy {
            let sentence = mutate(&parent, mutation_rate);
            let f = fitness(&target, &sentence);

            sentences.insert(f, sentence);

            if f < f_min {
                f_min = f
            }
        }

        if fitness(&target, &parent) > f_min {
            match sentences.get(&f_min) {
                Some(s) => {
                    parent = s.clone();
                    println!("{} : {}", parent, counter);
                }
                None => panic!("Error, fitness minimum but no sentence."),
            }
        }
    }
}

/// Computes the fitness of a sentence against a target string.
fn fitness(target: &str, sentence: &str) -> u32 {
    target.chars()
        .zip(sentence.chars())
        .fold(0, |acc, (c1, c2)| {
            if c1 != c2 {
                acc + 1
            } else {
                acc
            }
        })
}

/// Mutation algorithm.
///
/// It mutates each character of a string, according to a `mutation_rate`.
/// Please note that for full usefulness, `mutation_rate` should be between
/// 0 and 1.
fn mutate(sentence: &str, mutation_rate: f64) -> String {
    let mut rng = rand::thread_rng();
    let mut mutation = String::new();
    for c in sentence.chars() {
        if mutation_rate > rng.gen_range(0.0, 1.0) {
            mutation.push(random_char());
        } else {
            mutation.push(c);
        }
    }

    mutation
}

/// Generates a random sentence of length 28 from completely random chars.

fn generate_first_sentence(parent: &mut String) {
    for _ in 0..28 {
        parent.push(random_char());
    }
}

/// Generates a random char (between 'A' and '\\').
fn random_char() -> char {
    match rand::thread_rng().gen_range(b'A', b'\\') as char {
        '[' => ' ',
        c => c,
    }
}
<commit_msg>update Evolutionary algorithm<commit_after>//! Author : Thibault Barbie
//!
//! A simple evolutionary algorithm written in Rust.

extern crate rand;

use rand::Rng;

fn main() {
    let target = "methinks it is like a weasel"; // lowercase for readability
    let copies = 100;
    let mutation_rate = 20; // 1/20 = 0.05 = 5%

    let mut rng = rand::weak_rng();

    // Generate first sentence, mutating each character
    let start = mutate(&mut rng, target, 1); // 1/1 = 1 = 100%

    println!("{}", target);
    println!("{}", start);

    evolve(&mut rng, target, start, copies, mutation_rate);
}

/// Evolution algorithm
///
/// Evolves `parent` to match `target`.  Returns the number of evolutions performed.
fn evolve<R: Rng>(
    rng: &mut R,
    target: &str,
    mut parent: String,
    copies: usize,
    mutation_rate: u32,
) -> usize {
    let mut counter = 0;
    let mut parent_fitness = target.len() + 1;

    loop {
        counter += 1;

        let (best_fitness, best_sentence) = (0..copies)
            .map(|_| {
                // Copy and mutate a new sentence.
                let sentence = mutate(rng, &parent, mutation_rate);
                // Find the fitness of the new mutation
                (fitness(target, &sentence), sentence)
            })
            .min_by_key(|&(f, _)| f) // find the closest mutation to the target
            .unwrap(); // fails if `copies == 0`

        // If the best mutation of this generation is better than `parent` then "the fittest
        // survives" and the next parent becomes the best of this generation.
        if best_fitness < parent_fitness {
            parent = best_sentence;
            parent_fitness = best_fitness;
            println!(
                "{} : generation {} with fitness {}",
                parent, counter, best_fitness
            );

            if best_fitness == 0 {
                return counter;
            }
        }
    }
}

/// Computes the fitness of a sentence against a target string, returning the number of
/// incorrect characters.
fn fitness(target: &str, sentence: &str) -> usize {
    let zip = sentence.chars().zip(target.chars());
    zip.filter(|&(c1, c2)| c1 != c2).count()
}

/// Mutation algorithm.
///
/// It mutates each character of a string, according to a `mutation_rate`.
fn mutate<R: Rng>(rng: &mut R, sentence: &str, mutation_rate: u32) -> String {
    let maybe_mutate = |c| {
        if rng.gen_weighted_bool(mutation_rate) {
            random_char(rng)
        } else {
            c
        }
    };
    sentence.chars().map(maybe_mutate).collect()
}

/// Generates a random lowercase letter or space.
fn random_char<R: Rng>(rng: &mut R) -> char {
    // Returns a value in the range [a, z] + an extra slot for the space character.  '|' is the
    // exclusive upper bound.  (The `u8` values could be cast to larger integers for a better
    // chance of the RNG hitting the proper range).
    match rng.gen_range(b'a', b'|') as char {
        '{' => ' ', // the `char` after 'z'
        c => c,
    }
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::io::IoResult;

/// Wraps a `Reader` to facilitate reading that is not byte-aligned.
pub struct Bitstream<'r> {
    /// The source where bits are read from.
    reader: &'r mut (Reader + 'r),
    /// Data read from the reader, but not yet fully consumed.
    data: u8,
    /// The number of bits of `data` that have not been consumed.
    bits_left: u8
}

impl<'r> Bitstream<'r> {
    /// Wraps the reader with a reader that facilitates reading individual bits.
    pub fn new(reader: &'r mut Reader) -> Bitstream<'r> {
        Bitstream { reader: reader, data: 0, bits_left: 0 }
    }

    /// Generates a bitmask with 1s in the `bits` most significant bits.
    fn mask_u8(bits: u8) -> u8 {
        debug_assert!(bits <= 8);
        0xffu8 << (8 - bits) as uint
    }

    /// Skips bits such that the next read will be byte-aligned.
    pub fn align_to_byte(&mut self) {
        self.bits_left = 0;
    }

    /// Reads at most eight bits.
    pub fn read_leq_u8(&mut self, bits: u8) -> IoResult<u8> {
        // Of course we can read no more than 8 bits, but we do not want the
        // performance overhead of the assertion, so only do it in debug mode.
        debug_assert!(bits <= 8);

        // If not enough bits left, we will need to read the next byte.
        let result = if self.bits_left < bits {
            // Most significant bits are shifted to the right position already.
            let msb = self.data;

            // From the next byte, we take the additional bits that we need.
            // Those start at the most significant bit, so we need to shift so
            // that it does not overlap with what we have already.
            self.data = try!(self.reader.read_byte());
            let lsb = (self.data & Bitstream::mask_u8(bits - self.bits_left))
                    >> self.bits_left as uint;

            // Shift out the bits that we have consumed.
            self.data = self.data << (bits - self.bits_left) as uint;
            self.bits_left = 8 - (bits - self.bits_left);

            msb | lsb
        } else {
            let result = self.data & Bitstream::mask_u8(bits);

            // Shift out the bits that we have consumed.
            self.data = self.data << bits as uint;
            self.bits_left = self.bits_left - bits;

            result
        };

        // If there are more than 8 bits left, we read too far.
        debug_assert!(self.bits_left < 8);

        // The resulting data is padded with zeroes in the least significant
        // bits, but we want to pad in the most significant bits, so shift.
        Ok(result >> (8 - bits) as uint)
    }

    /// Reads at most 16 bits.
    pub fn read_leq_u16(&mut self, bits: u8) -> IoResult<u16> {
        // As with read_leq_u8, this only makes sense if we read <= 16 bits.
        debug_assert!(bits <= 16);

        // Note: the following is not the most efficient implementation
        // possible, but it avoids duplicating the complexity of `read_leq_u8`.

        if bits <= 8 {
            let result = try!(self.read_leq_u8(bits));
            Ok(result as u16)
        } else {
            // First read the 8 most significant bits, then read what is left.
            let msb = try!(self.read_leq_u8(8)) as u16;
            let lsb = try!(self.read_leq_u8(bits - 8)) as u16;
            Ok((msb << (bits - 8) as uint) | lsb)
        }
    }

    /// Reads at most 32 bits.
    pub fn read_leq_u32(&mut self, bits: u8) -> IoResult<u32> {
        // As with read_leq_u8, this only makes sense if we read <= 32 bits.
        debug_assert!(bits <= 32);

        // Note: the following is not the most efficient implementation
        // possible, but it avoids duplicating the complexity of `read_leq_u8`.

        if bits <= 16 {
            let result = try!(self.read_leq_u16(bits));
            Ok(result as u32)
        } else {
            // First read the 16 most significant bits, then read what is left.
            let msb = try!(self.read_leq_u16(16)) as u32;
            let lsb = try!(self.read_leq_u16(bits - 16)) as u32;
            Ok((msb << (bits - 16) as uint) | lsb)
        }
    }
}

#[test]
fn verify_read_leq_u8() {
    use std::io::MemReader;

    let mut data = MemReader::new(vec!(0b1010_0101, 0b1110_0001,
                                       0b1101_0010, 0b0101_0101,
                                       0b0111_0011, 0b0011_1111,
                                       0b1010_1010, 0b0000_1100));
    let mut bits = Bitstream::new(&mut data);

    assert_eq!(bits.read_leq_u8(0).unwrap(), 0);
    assert_eq!(bits.read_leq_u8(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u8(1).unwrap(), 0);
    assert_eq!(bits.read_leq_u8(2).unwrap(), 0b10);
    assert_eq!(bits.read_leq_u8(2).unwrap(), 0b01);
    assert_eq!(bits.read_leq_u8(3).unwrap(), 0b011);
    assert_eq!(bits.read_leq_u8(3).unwrap(), 0b110);
    assert_eq!(bits.read_leq_u8(4).unwrap(), 0b0001);
    assert_eq!(bits.read_leq_u8(5).unwrap(), 0b11010);
    assert_eq!(bits.read_leq_u8(6).unwrap(), 0b010010);
    assert_eq!(bits.read_leq_u8(7).unwrap(), 0b1010101);
    assert_eq!(bits.read_leq_u8(8).unwrap(), 0b11001100);
    assert_eq!(bits.read_leq_u8(6).unwrap(), 0b111111);
    assert_eq!(bits.read_leq_u8(8).unwrap(), 0b10101010);
    assert_eq!(bits.read_leq_u8(4).unwrap(), 0b0000);
    assert_eq!(bits.read_leq_u8(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u8(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u8(2).unwrap(), 0b00);
}

#[test]
fn verify_read_leq_u16() {
    use std::io::MemReader;

    let mut data = MemReader::new(vec!(0b1010_0101, 0b1110_0001,
                                       0b1101_0010, 0b0101_0101));
    let mut bits = Bitstream::new(&mut data);

    assert_eq!(bits.read_leq_u16(0).unwrap(), 0);
    assert_eq!(bits.read_leq_u16(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u16(13).unwrap(), 0b010_0101_1110_00);
    assert_eq!(bits.read_leq_u16(9).unwrap(), 0b01_1101_001);
}

#[test]
fn verify_read_leq_u32() {
    use std::io::MemReader;

    let mut data = MemReader::new(vec!(0b1010_0101, 0b1110_0001,
                                       0b1101_0010, 0b0101_0101));
    let mut bits = Bitstream::new(&mut data);

    assert_eq!(bits.read_leq_u32(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u32(17).unwrap(), 0b010_0101_1110_0001_11);
    assert_eq!(bits.read_leq_u32(14).unwrap(), 0b01_0010_0101_0101);
}

#[test]
fn verify_align() {
    use std::io::MemReader;

    let mut data = MemReader::new(vec!(0x00, 0xff));
    let mut bits = Bitstream::new(&mut data);

    assert_eq!(bits.read_leq_u8(5).unwrap(), 0);
    bits.align_to_byte();
    assert_eq!(bits.read_leq_u8(3).unwrap(), 7);
}
<commit_msg>revise usage of uint in bitstream<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use std::io::IoResult;

/// Wraps a `Reader` to facilitate reading that is not byte-aligned.
pub struct Bitstream<'r> {
    /// The source where bits are read from.
    reader: &'r mut (Reader + 'r),
    /// Data read from the reader, but not yet fully consumed.
    data: u8,
    /// The number of bits of `data` that have not been consumed.
    bits_left: u8
}

impl<'r> Bitstream<'r> {
    /// Wraps the reader with a reader that facilitates reading individual bits.
    pub fn new(reader: &'r mut Reader) -> Bitstream<'r> {
        Bitstream { reader: reader, data: 0, bits_left: 0 }
    }

    /// Generates a bitmask with 1s in the `bits` most significant bits.
    fn mask_u8(bits: u8) -> u8 {
        debug_assert!(bits <= 8);
        0xffu8 << (8 - bits) as usize
    }

    /// Skips bits such that the next read will be byte-aligned.
    pub fn align_to_byte(&mut self) {
        self.bits_left = 0;
    }

    /// Reads at most eight bits.
    pub fn read_leq_u8(&mut self, bits: u8) -> IoResult<u8> {
        // Of course we can read no more than 8 bits, but we do not want the
        // performance overhead of the assertion, so only do it in debug mode.
        debug_assert!(bits <= 8);

        // If not enough bits left, we will need to read the next byte.
        let result = if self.bits_left < bits {
            // Most significant bits are shifted to the right position already.
            let msb = self.data;

            // From the next byte, we take the additional bits that we need.
            // Those start at the most significant bit, so we need to shift so
            // that it does not overlap with what we have already.
            self.data = try!(self.reader.read_byte());
            let lsb = (self.data & Bitstream::mask_u8(bits - self.bits_left))
                    >> self.bits_left as usize;

            // Shift out the bits that we have consumed.
            self.data = self.data << (bits - self.bits_left) as usize;
            self.bits_left = 8 - (bits - self.bits_left);

            msb | lsb
        } else {
            let result = self.data & Bitstream::mask_u8(bits);

            // Shift out the bits that we have consumed.
            self.data = self.data << bits as usize;
            self.bits_left = self.bits_left - bits;

            result
        };

        // If there are more than 8 bits left, we read too far.
        debug_assert!(self.bits_left < 8);

        // The resulting data is padded with zeroes in the least significant
        // bits, but we want to pad in the most significant bits, so shift.
        Ok(result >> (8 - bits) as usize)
    }

    /// Reads at most 16 bits.
    pub fn read_leq_u16(&mut self, bits: u8) -> IoResult<u16> {
        // As with read_leq_u8, this only makes sense if we read <= 16 bits.
        debug_assert!(bits <= 16);

        // Note: the following is not the most efficient implementation
        // possible, but it avoids duplicating the complexity of `read_leq_u8`.

        if bits <= 8 {
            let result = try!(self.read_leq_u8(bits));
            Ok(result as u16)
        } else {
            // First read the 8 most significant bits, then read what is left.
            let msb = try!(self.read_leq_u8(8)) as u16;
            let lsb = try!(self.read_leq_u8(bits - 8)) as u16;
            Ok((msb << (bits - 8) as usize) | lsb)
        }
    }

    /// Reads at most 32 bits.
    pub fn read_leq_u32(&mut self, bits: u8) -> IoResult<u32> {
        // As with read_leq_u8, this only makes sense if we read <= 32 bits.
        debug_assert!(bits <= 32);

        // Note: the following is not the most efficient implementation
        // possible, but it avoids duplicating the complexity of `read_leq_u8`.

        if bits <= 16 {
            let result = try!(self.read_leq_u16(bits));
            Ok(result as u32)
        } else {
            // First read the 16 most significant bits, then read what is left.
            let msb = try!(self.read_leq_u16(16)) as u32;
            let lsb = try!(self.read_leq_u16(bits - 16)) as u32;
            Ok((msb << (bits - 16) as usize) | lsb)
        }
    }
}

#[test]
fn verify_read_leq_u8() {
    use std::io::MemReader;

    let mut data = MemReader::new(vec!(0b1010_0101, 0b1110_0001,
                                       0b1101_0010, 0b0101_0101,
                                       0b0111_0011, 0b0011_1111,
                                       0b1010_1010, 0b0000_1100));
    let mut bits = Bitstream::new(&mut data);

    assert_eq!(bits.read_leq_u8(0).unwrap(), 0);
    assert_eq!(bits.read_leq_u8(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u8(1).unwrap(), 0);
    assert_eq!(bits.read_leq_u8(2).unwrap(), 0b10);
    assert_eq!(bits.read_leq_u8(2).unwrap(), 0b01);
    assert_eq!(bits.read_leq_u8(3).unwrap(), 0b011);
    assert_eq!(bits.read_leq_u8(3).unwrap(), 0b110);
    assert_eq!(bits.read_leq_u8(4).unwrap(), 0b0001);
    assert_eq!(bits.read_leq_u8(5).unwrap(), 0b11010);
    assert_eq!(bits.read_leq_u8(6).unwrap(), 0b010010);
    assert_eq!(bits.read_leq_u8(7).unwrap(), 0b1010101);
    assert_eq!(bits.read_leq_u8(8).unwrap(), 0b11001100);
    assert_eq!(bits.read_leq_u8(6).unwrap(), 0b111111);
    assert_eq!(bits.read_leq_u8(8).unwrap(), 0b10101010);
    assert_eq!(bits.read_leq_u8(4).unwrap(), 0b0000);
    assert_eq!(bits.read_leq_u8(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u8(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u8(2).unwrap(), 0b00);
}

#[test]
fn verify_read_leq_u16() {
    use std::io::MemReader;

    let mut data = MemReader::new(vec!(0b1010_0101, 0b1110_0001,
                                       0b1101_0010, 0b0101_0101));
    let mut bits = Bitstream::new(&mut data);

    assert_eq!(bits.read_leq_u16(0).unwrap(), 0);
    assert_eq!(bits.read_leq_u16(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u16(13).unwrap(), 0b010_0101_1110_00);
    assert_eq!(bits.read_leq_u16(9).unwrap(), 0b01_1101_001);
}

#[test]
fn verify_read_leq_u32() {
    use std::io::MemReader;

    let mut data = MemReader::new(vec!(0b1010_0101, 0b1110_0001,
                                       0b1101_0010, 0b0101_0101));
    let mut bits = Bitstream::new(&mut data);

    assert_eq!(bits.read_leq_u32(1).unwrap(), 1);
    assert_eq!(bits.read_leq_u32(17).unwrap(), 0b010_0101_1110_0001_11);
    assert_eq!(bits.read_leq_u32(14).unwrap(), 0b01_0010_0101_0101);
}

#[test]
fn verify_align() {
    use std::io::MemReader;

    let mut data = MemReader::new(vec!(0x00, 0xff));
    let mut bits = Bitstream::new(&mut data);

    assert_eq!(bits.read_leq_u8(5).unwrap(), 0);
    bits.align_to_byte();
    assert_eq!(bits.read_leq_u8(3).unwrap(), 7);
}
<|endoftext|>


<commit_before>//! Facilities for implementing static position evaluation and move
//! generation.
//!
//! # Static position evaluation
//!
//! An evaluation function is used to heuristically determine the
//! relative value of a position, i.e. the chances of winning. If we
//! could see to the end of the game in every line, the evaluation
//! would only have values of "loss", "draw", and "win". In practice,
//! however, we do not know the exact value of a position, so we must
//! make an approximation. Beginning chess players learn to do this
//! starting with the value of the pieces themselves. Computer
//! evaluation functions also use the value of the material as the
//! most significant aspect and then add other considerations.
//!
//! Static evaluation is an evaluation that considers only the static
//! material and positional properties of the current position,
//! without analyzing any tactical variations. Therefore, if the
//! position has pending tactical threats, the static evaluation will
//! be grossly incorrect.
//!
//! Writing a new static evaluator is as simple as defining a type
//! that implements the `BoardEvaluator` trait.
//!
//! # Move generation
//!
//! TODO

pub mod tables;
pub mod bitsets;
pub mod evaluators;
pub mod generators;
pub mod notation;

use chesstypes::*;
use uci::SetOption;
use self::notation::{parse_fen, NotationError};

/// Holds a chess position.
#[derive(Clone)]
pub struct Board {
    /// The placement of the pieces on the board.
    pub pieces: PiecesPlacement,

    /// The side to move.
    pub to_move: Color,

    /// The castling rights for both players.
    pub castling_rights: CastlingRights,

    /// If the previous move was a double pawn push, contains pushed
    /// pawn's file (a value between 0 and 7). Otherwise contains `8`.
    pub enpassant_file: usize,

    /// The set of all occupied squares on the board.
    ///
    /// Always equals `self.pieces.color[WHITE] |
    /// self.pieces.color[BLACK]`. Deserves a field on its own because
    /// it is very frequently needed.
    pub occupied: Bitboard,
}

impl Board {
    /// Creates a new instance from a Forsyth–Edwards Notation (FEN)
    /// string.
    pub fn from_fen(fen: &str) -> Result<Board, NotationError> {
        parse_fen(fen).map(|x| x.0)
    }
}

/// A trait for adding moves to move containers.
pub trait AddMove {
    /// Adds a move to the move container.
    fn add_move(&mut self, m: Move);
}

impl AddMove for Vec<Move> {
    #[inline(always)]
    fn add_move(&mut self, m: Move) {
        self.push(m);
    }
}

/// A trait used to statically evaluate positions.
pub trait BoardEvaluator: Clone + Send + SetOption {
    /// Creates a new instance and binds it to a given position.
    ///
    /// When a new instance is created, it is bound to a particular
    /// chess position (given by the `board` parameter). And for a
    /// moment, this is the only position that can be correctly
    /// evaluated. The instance then can be re-bound to the next (or
    /// the previous) position in the line of play by issuing calls to
    /// `will_do_move` and `done_move` methods (or respectively,
    /// `will_undo_move` and `undone_move` methods) .
    fn new(board: &Board) -> Self;

    /// Evaluates the the position to which the instance is bound.
    ///
    /// `board` points to the position to which the instance is bound.
    /// `halfmove_clock` gives the number of half-moves since the last
    /// piece capture or pawn advance.
    ///
    /// The returned value must be between `VALUE_EVAL_MIN` and
    /// `VALUE_EVAL_MAX`.
    fn evaluate(&self, board: &Board, halfmove_clock: u8) -> Value;

    /// Returns whether the position is zugzwangy.
    ///
    /// In many endgame positions there is a relatively high
    /// probability of zugzwang occurring. For such positions, this
    /// method returns `true`.
    fn is_zugzwangy(&self, board: &Board, halfmove_clock: u8) -> bool;

    /// Updates evaluator's state to keep up with a move that will be
    /// played.
    ///
    /// `board` points to the position to which the instance is bound.
    ///
    /// `m` is a legal move, or (if not in check) a "null move".
    #[inline]
    #[allow(unused_variables)]
    fn will_do_move(&mut self, board: &Board, m: Move) {}

    /// Updates evaluator's state to keep up with a move that was
    /// played.
    ///
    /// `board` points to the new position to which the instance is
    /// bound.
    #[inline]
    #[allow(unused_variables)]
    fn done_move(&mut self, board: &Board, m: Move) {}

    /// Updates evaluator's state to keep up with a move that will be
    /// taken back.
    ///
    /// `board` points to the position to which the instance is bound.
    #[inline]
    #[allow(unused_variables)]
    fn will_undo_move(&mut self, board: &Board, m: Move) {}

    /// Updates evaluator's state in accordance with a move that was
    /// taken back.
    ///
    /// `board` points to the new position to which the instance is
    /// bound.
    #[inline]
    #[allow(unused_variables)]
    fn undone_move(&mut self, board: &Board, m: Move) {}
}

/// A trait for move generators.
///
/// A `MoveGenerator` can generate all legal moves in the current
/// position, play a selected move, and take it back. It provides a
/// position evaluator, and can calculate Zobrist hashes.
///
/// **Important note:** `MoveGenerator` is unaware of repeating
/// positions and the fifty-move rule.
pub trait MoveGenerator: Sized + Send + Clone + SetOption {
    /// The type of static evaluator that the implementation works
    /// with.
    type BoardEvaluator: BoardEvaluator;

    /// Creates a new instance, consuming the supplied `Board`
    /// instance.
    ///
    /// Returns `None` if the position is illegal.
    fn from_board(board: Board) -> Option<Self>;

    /// Returns a reference to the underlying `Board` instance.
    #[inline(always)]
    fn board(&self) -> &Board;

    /// Returns the Zobrist hash value for the underlying `Board`
    /// instance.
    ///
    /// Zobrist hashing is a technique to transform a board position
    /// into a number of a fixed length, with an equal distribution
    /// over all possible numbers, invented by Albert Zobrist. The key
    /// property of this method is that two similar positions generate
    /// entirely different hash numbers.
    ///
    /// **Important note:** This method calculates the hash value
    /// "from scratch", which can be too slow for some cases. (See
    /// `do_move`.)
    fn board_hash(&self) -> u64;

    /// Returns a reference to a static evaluator bound to the current
    /// position.
    fn evaluator(&self) -> &Self::BoardEvaluator;

    /// Returns a bitboard with all pieces and pawns of color `us`
    /// that attack `square`.
    fn attacks_to(&self, us: Color, square: Square) -> Bitboard;

    /// Returns a bitboard with all enemy pieces and pawns that attack
    /// the king.
    fn checkers(&self) -> Bitboard;

    /// Generates all legal moves, possibly including some
    /// pseudo-legal moves too.
    ///
    /// The moves are added to `moves`. All generated moves with
    /// pieces other than the king will be legal. Some of the
    /// generated king's moves may be illegal because the destination
    /// square is under attack. This arrangement has two important
    /// advantages:
    ///
    /// * `do_move` can do its work without knowing the set of
    ///   checkers and pinned pieces, so there is no need to keep
    ///   those around.
    /// * A beta cut-off may make the verification that king's
    ///   destination square is not under attack unnecessary, thus
    ///   saving time.
    ///
    /// The initial move scores for the generated moves are:
    ///
    /// * `0` for pawn promotions to pieces other than queen (including
    ///   captures).
    /// * `u32::MAX` for captures and pawn promotions to queen.
    /// * `0` for all other moves.
    ///
    /// **Note:** A pseudo-legal move is a move that is otherwise
    /// legal, except it might leave the king in check.
    fn generate_all<T: AddMove>(&self, moves: &mut T);

    /// Generates moves for the quiescence search.
    ///
    /// The moves are added to `moves`. This method always generates a
    /// **subset** of the moves generated by `generate_all`.
    ///
    /// All legal captures and, when in check, all legal check
    /// evasions will be included. Optionally, other moves might be
    /// included too. For example: moves that give check, or pawn
    /// promotions to queen. This is done carefully though, to avoid
    /// creating an infinitely large search tree. In order to be able
    /// to decide whether to include other moves or not,
    /// `generate_focing` should be supplied with some information
    /// about the currently running quiescence search:
    ///
    /// * `ply` specifies the number of moves in the current line of
    ///   play (half-moves).
    /// * `checks` specifies how many of the moves in the current line
    ///   of play gave check (`checks` <= `ply`).
    fn generate_forcing<T: AddMove>(&self, ply: u8, checks: u8, moves: &mut T);

    /// Checks if `move_digest` represents a pseudo-legal move.
    ///
    /// If a move `m` exists that would be generated by
    /// `generate_all` if called for the current position on the
    /// board, and for that move `m.digest() == move_digest`, this
    /// method will return `Some(m)`. Otherwise it will return
    /// `None`. This is useful when playing moves from the
    /// transposition table, without calling `generate_all`.
    fn try_move_digest(&self, move_digest: MoveDigest) -> Option<Move>;

    /// Returns a null move.
    ///
    /// "Null move" is a pseudo-move that changes nothing on the board
    /// except the side to move. It is sometimes useful to include a
    /// speculative null move in the search tree so as to achieve more
    /// aggressive pruning.
    fn null_move(&self) -> Move;

    /// Plays a move on the board.
    ///
    /// It verifies if the move is legal. If the move is legal, the
    /// board is updated and an `u64` value is returned, which should
    /// be XOR-ed with old board's hash value to obtain new board's
    /// hash value. If the move is illegal, `None` is returned without
    /// updating the board. The move passed to this method **must**
    /// have been generated by `generate_all`, `generate_forcing`,
    /// `try_move_digest`, or `null_move` methods for the current
    /// position on the board.
    ///
    /// The moves generated by the `null_move` method are
    /// exceptions. For them `do_move` will return `None` if and only
    /// if the king is in check.
    fn do_move(&mut self, m: Move) -> Option<u64>;

    /// Takes back last played move.
    ///
    /// The move passed to this method **must** be the last move passed
    /// to `do_move`.
    fn undo_move(&mut self, m: Move);
}
<commit_msg>document checkers() saving the value<commit_after>//! Facilities for implementing static position evaluation and move
//! generation.
//!
//! # Static position evaluation
//!
//! An evaluation function is used to heuristically determine the
//! relative value of a position, i.e. the chances of winning. If we
//! could see to the end of the game in every line, the evaluation
//! would only have values of "loss", "draw", and "win". In practice,
//! however, we do not know the exact value of a position, so we must
//! make an approximation. Beginning chess players learn to do this
//! starting with the value of the pieces themselves. Computer
//! evaluation functions also use the value of the material as the
//! most significant aspect and then add other considerations.
//!
//! Static evaluation is an evaluation that considers only the static
//! material and positional properties of the current position,
//! without analyzing any tactical variations. Therefore, if the
//! position has pending tactical threats, the static evaluation will
//! be grossly incorrect.
//!
//! Writing a new static evaluator is as simple as defining a type
//! that implements the `BoardEvaluator` trait.
//!
//! # Move generation
//!
//! TODO

pub mod tables;
pub mod bitsets;
pub mod evaluators;
pub mod generators;
pub mod notation;

use chesstypes::*;
use uci::SetOption;
use self::notation::{parse_fen, NotationError};

/// Holds a chess position.
#[derive(Clone)]
pub struct Board {
    /// The placement of the pieces on the board.
    pub pieces: PiecesPlacement,

    /// The side to move.
    pub to_move: Color,

    /// The castling rights for both players.
    pub castling_rights: CastlingRights,

    /// If the previous move was a double pawn push, contains pushed
    /// pawn's file (a value between 0 and 7). Otherwise contains `8`.
    pub enpassant_file: usize,

    /// The set of all occupied squares on the board.
    ///
    /// Always equals `self.pieces.color[WHITE] |
    /// self.pieces.color[BLACK]`. Deserves a field on its own because
    /// it is very frequently needed.
    pub occupied: Bitboard,
}

impl Board {
    /// Creates a new instance from a Forsyth–Edwards Notation (FEN)
    /// string.
    pub fn from_fen(fen: &str) -> Result<Board, NotationError> {
        parse_fen(fen).map(|x| x.0)
    }
}

/// A trait for adding moves to move containers.
pub trait AddMove {
    /// Adds a move to the move container.
    fn add_move(&mut self, m: Move);
}

impl AddMove for Vec<Move> {
    #[inline(always)]
    fn add_move(&mut self, m: Move) {
        self.push(m);
    }
}

/// A trait used to statically evaluate positions.
pub trait BoardEvaluator: Clone + Send + SetOption {
    /// Creates a new instance and binds it to a given position.
    ///
    /// When a new instance is created, it is bound to a particular
    /// chess position (given by the `board` parameter). And for a
    /// moment, this is the only position that can be correctly
    /// evaluated. The instance then can be re-bound to the next (or
    /// the previous) position in the line of play by issuing calls to
    /// `will_do_move` and `done_move` methods (or respectively,
    /// `will_undo_move` and `undone_move` methods) .
    fn new(board: &Board) -> Self;

    /// Evaluates the the position to which the instance is bound.
    ///
    /// `board` points to the position to which the instance is bound.
    /// `halfmove_clock` gives the number of half-moves since the last
    /// piece capture or pawn advance.
    ///
    /// The returned value must be between `VALUE_EVAL_MIN` and
    /// `VALUE_EVAL_MAX`.
    fn evaluate(&self, board: &Board, halfmove_clock: u8) -> Value;

    /// Returns whether the position is zugzwangy.
    ///
    /// In many endgame positions there is a relatively high
    /// probability of zugzwang occurring. For such positions, this
    /// method returns `true`.
    fn is_zugzwangy(&self, board: &Board, halfmove_clock: u8) -> bool;

    /// Updates evaluator's state to keep up with a move that will be
    /// played.
    ///
    /// `board` points to the position to which the instance is bound.
    ///
    /// `m` is a legal move, or (if not in check) a "null move".
    #[inline]
    #[allow(unused_variables)]
    fn will_do_move(&mut self, board: &Board, m: Move) {}

    /// Updates evaluator's state to keep up with a move that was
    /// played.
    ///
    /// `board` points to the new position to which the instance is
    /// bound.
    #[inline]
    #[allow(unused_variables)]
    fn done_move(&mut self, board: &Board, m: Move) {}

    /// Updates evaluator's state to keep up with a move that will be
    /// taken back.
    ///
    /// `board` points to the position to which the instance is bound.
    #[inline]
    #[allow(unused_variables)]
    fn will_undo_move(&mut self, board: &Board, m: Move) {}

    /// Updates evaluator's state in accordance with a move that was
    /// taken back.
    ///
    /// `board` points to the new position to which the instance is
    /// bound.
    #[inline]
    #[allow(unused_variables)]
    fn undone_move(&mut self, board: &Board, m: Move) {}
}

/// A trait for move generators.
///
/// A `MoveGenerator` can generate all legal moves in the current
/// position, play a selected move, and take it back. It provides a
/// position evaluator, and can calculate Zobrist hashes.
///
/// **Important note:** `MoveGenerator` is unaware of repeating
/// positions and the fifty-move rule.
pub trait MoveGenerator: Sized + Send + Clone + SetOption {
    /// The type of static evaluator that the implementation works
    /// with.
    type BoardEvaluator: BoardEvaluator;

    /// Creates a new instance, consuming the supplied `Board`
    /// instance.
    ///
    /// Returns `None` if the position is illegal.
    fn from_board(board: Board) -> Option<Self>;

    /// Returns a reference to the underlying `Board` instance.
    #[inline(always)]
    fn board(&self) -> &Board;

    /// Returns the Zobrist hash value for the underlying `Board`
    /// instance.
    ///
    /// Zobrist hashing is a technique to transform a board position
    /// into a number of a fixed length, with an equal distribution
    /// over all possible numbers, invented by Albert Zobrist. The key
    /// property of this method is that two similar positions generate
    /// entirely different hash numbers.
    ///
    /// **Important note:** This method calculates the hash value
    /// "from scratch", which can be too slow for some cases. (See
    /// `do_move`.)
    fn board_hash(&self) -> u64;

    /// Returns a reference to a static evaluator bound to the current
    /// position.
    fn evaluator(&self) -> &Self::BoardEvaluator;

    /// Returns a bitboard with all pieces and pawns of color `us`
    /// that attack `square`.
    fn attacks_to(&self, us: Color, square: Square) -> Bitboard;

    /// Returns a bitboard with all enemy pieces and pawns that attack
    /// the king.
    ///
    /// **Important note:** The bitboard of checkers is calculated on
    /// the first call to `checkers`, and is saved in case another
    /// call is made before doing/undoing any moves. In that case
    /// `checkers` returns the saved bitboard instead of
    /// re-calculating it, thus saving time.
    fn checkers(&self) -> Bitboard;

    /// Generates all legal moves, possibly including some
    /// pseudo-legal moves too.
    ///
    /// The moves are added to `moves`. All generated moves with
    /// pieces other than the king will be legal. Some of the
    /// generated king's moves may be illegal because the destination
    /// square is under attack. This arrangement has two important
    /// advantages:
    ///
    /// * `do_move` can do its work without knowing the set of
    ///   checkers and pinned pieces, so there is no need to keep
    ///   those around.
    /// * A beta cut-off may make the verification that king's
    ///   destination square is not under attack unnecessary, thus
    ///   saving time.
    ///
    /// The initial move scores for the generated moves are:
    ///
    /// * `0` for pawn promotions to pieces other than queen (including
    ///   captures).
    /// * `u32::MAX` for captures and pawn promotions to queen.
    /// * `0` for all other moves.
    ///
    /// **Note:** A pseudo-legal move is a move that is otherwise
    /// legal, except it might leave the king in check.
    fn generate_all<T: AddMove>(&self, moves: &mut T);

    /// Generates moves for the quiescence search.
    ///
    /// The moves are added to `moves`. This method always generates a
    /// **subset** of the moves generated by `generate_all`.
    ///
    /// All legal captures and, when in check, all legal check
    /// evasions will be included. Optionally, other moves might be
    /// included too. For example: moves that give check, or pawn
    /// promotions to queen. This is done carefully though, to avoid
    /// creating an infinitely large search tree. In order to be able
    /// to decide whether to include other moves or not,
    /// `generate_focing` should be supplied with some information
    /// about the currently running quiescence search:
    ///
    /// * `ply` specifies the number of moves in the current line of
    ///   play (half-moves).
    /// * `checks` specifies how many of the moves in the current line
    ///   of play gave check (`checks` <= `ply`).
    fn generate_forcing<T: AddMove>(&self, ply: u8, checks: u8, moves: &mut T);

    /// Checks if `move_digest` represents a pseudo-legal move.
    ///
    /// If a move `m` exists that would be generated by
    /// `generate_all` if called for the current position on the
    /// board, and for that move `m.digest() == move_digest`, this
    /// method will return `Some(m)`. Otherwise it will return
    /// `None`. This is useful when playing moves from the
    /// transposition table, without calling `generate_all`.
    fn try_move_digest(&self, move_digest: MoveDigest) -> Option<Move>;

    /// Returns a null move.
    ///
    /// "Null move" is a pseudo-move that changes nothing on the board
    /// except the side to move. It is sometimes useful to include a
    /// speculative null move in the search tree so as to achieve more
    /// aggressive pruning.
    fn null_move(&self) -> Move;

    /// Plays a move on the board.
    ///
    /// It verifies if the move is legal. If the move is legal, the
    /// board is updated and an `u64` value is returned, which should
    /// be XOR-ed with old board's hash value to obtain new board's
    /// hash value. If the move is illegal, `None` is returned without
    /// updating the board. The move passed to this method **must**
    /// have been generated by `generate_all`, `generate_forcing`,
    /// `try_move_digest`, or `null_move` methods for the current
    /// position on the board.
    ///
    /// The moves generated by the `null_move` method are
    /// exceptions. For them `do_move` will return `None` if and only
    /// if the king is in check.
    fn do_move(&mut self, m: Move) -> Option<u64>;

    /// Takes back last played move.
    ///
    /// The move passed to this method **must** be the last move passed
    /// to `do_move`.
    fn undo_move(&mut self, m: Move);
}
<|endoftext|>


<commit_before>//! Types for the *m.room.third_party_invite* event.

<commit_msg>Add ThirdPartyInviteEvent.<commit_after>//! Types for the *m.room.third_party_invite* event.

use core::{Event, EventType, RoomEvent, StateEvent};

/// An invitation to a room issued to a third party identifier, rather than a matrix user ID.
///
/// Acts as an *m.room.member* invite event, where there isn't a target user_id to invite. This
/// event contains a token and a public key whose private key must be used to sign the token. Any
/// user who can present that signature may use this invitation to join the target room.
pub struct ThirdPartyInviteEvent<'a, 'b> {
    content: ThirdPartyInviteEventContent<'a>,
    event_id: &'a str,
    prev_content: Option<ThirdPartyInviteEventContent<'b>>,
    room_id: &'a str,
    state_key: &'a str,
    user_id: &'a str,
}

impl<'a, 'b> Event<'a, ThirdPartyInviteEventContent<'a>> for ThirdPartyInviteEvent<'a, 'b> {
    fn content(&'a self) -> &'a ThirdPartyInviteEventContent<'a> {
        &self.content
    }

    fn event_type(&self) -> EventType {
        EventType::RoomThirdPartyInvite
    }
}

impl<'a, 'b> RoomEvent<'a, ThirdPartyInviteEventContent<'a>> for ThirdPartyInviteEvent<'a, 'b> {
    fn event_id(&'a self) -> &'a str {
        &self.event_id
    }

    fn room_id(&'a self) -> &'a str {
        &self.room_id
    }

    fn user_id(&'a self) -> &'a str {
        &self.user_id
    }
}

impl<'a, 'b> StateEvent<'a, 'b, ThirdPartyInviteEventContent<'a>> for ThirdPartyInviteEvent<'a, 'b> {
    fn prev_content(&'a self) -> Option<&'b ThirdPartyInviteEventContent> {
        match self.prev_content {
            Some(ref prev_content) => Some(prev_content),
            None => None,
        }
    }

    fn state_key(&self) -> &'a str {
        &self.state_key
    }
}

/// The payload of a `ThirdPartyInviteEvent`.
pub struct ThirdPartyInviteEventContent<'a> {
    display_name: &'a str,
    key_validity_url: &'a str,
    public_key: &'a str,
}
<|endoftext|>


<commit_before>#![deny(unused)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit="128"]

#[macro_use] extern crate failure;
#[macro_use] extern crate log;
#[macro_use] extern crate scoped_tls;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate serde_json;
extern crate atty;
extern crate crates_io as registry;
extern crate crossbeam;
extern crate curl;
extern crate docopt;
extern crate filetime;
extern crate flate2;
extern crate fs2;
extern crate git2;
extern crate glob;
extern crate hex;
extern crate home;
extern crate ignore;
extern crate jobserver;
extern crate lazycell;
extern crate libc;
extern crate libgit2_sys;
extern crate num_cpus;
extern crate same_file;
extern crate semver;
extern crate serde;
extern crate serde_ignored;
extern crate shell_escape;
extern crate tar;
extern crate tempdir;
extern crate termcolor;
extern crate toml;
extern crate url;
#[cfg(target_os = "macos")]
extern crate core_foundation;

use std::fmt;

use serde::de::DeserializeOwned;
use serde::ser;
use docopt::Docopt;
use failure::Error;

use core::Shell;
use core::shell::Verbosity::Verbose;

pub use util::{CargoError, CargoResult, CliError, CliResult, Config};
pub use util::errors::Internal;

pub const CARGO_ENV: &'static str = "CARGO";

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

pub struct CommitInfo {
    pub short_commit_hash: String,
    pub commit_hash: String,
    pub commit_date: String,
}

pub struct CfgInfo {
    // Information about the git repository we may have been built from.
    pub commit_info: Option<CommitInfo>,
    // The release channel we were built for.
    pub release_channel: String,
}

pub struct VersionInfo {
    pub major: String,
    pub minor: String,
    pub patch: String,
    pub pre_release: Option<String>,
    // Information that's only available when we were built with
    // configure/make, rather than cargo itself.
    pub cfg_info: Option<CfgInfo>,
}

impl fmt::Display for VersionInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "cargo {}.{}.{}",
               self.major, self.minor, self.patch)?;
        if let Some(channel) = self.cfg_info.as_ref().map(|ci| &ci.release_channel) {
            if channel != "stable" {
                write!(f, "-{}", channel)?;
                let empty = String::from("");
                write!(f, "{}", self.pre_release.as_ref().unwrap_or(&empty))?;
            }
        };

        if let Some(ref cfg) = self.cfg_info {
            if let Some(ref ci) = cfg.commit_info {
                write!(f, " ({} {})",
                       ci.short_commit_hash, ci.commit_date)?;
            }
        };
        Ok(())
    }
}

pub fn call_main_without_stdin<Flags: DeserializeOwned>(
            exec: fn(Flags, &mut Config) -> CliResult,
            config: &mut Config,
            usage: &str,
            args: &[String],
            options_first: bool) -> CliResult
{
    let docopt = Docopt::new(usage).unwrap()
        .options_first(options_first)
        .argv(args.iter().map(|s| &s[..]))
        .help(true);

    let flags = docopt.deserialize().map_err(|e| {
        let code = if e.fatal() {1} else {0};
        CliError::new(e.into(), code)
    })?;

    exec(flags, config)
}

pub fn print_json<T: ser::Serialize>(obj: &T) {
    let encoded = serde_json::to_string(&obj).unwrap();
    println!("{}", encoded);
}

pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {
    debug!("exit_with_error; err={:?}", err);

    let CliError { error, exit_code, unknown } = err;
    // exit_code == 0 is non-fatal error, e.g. docopt version info
    let fatal = exit_code != 0;

    let hide = unknown && shell.verbosity() != Verbose;

    if let Some(error) = error {
        if hide {
            drop(shell.error("An unknown error occurred"))
        } else if fatal {
            drop(shell.error(&error))
        } else {
            println!("{}", error);
        }

        if !handle_cause(&error, shell) || hide {
            drop(writeln!(shell.err(), "\nTo learn more, run the command again \
                                        with --verbose."));
        }
    }

    std::process::exit(exit_code)
}

pub fn handle_error(err: CargoError, shell: &mut Shell) {
    debug!("handle_error; err={:?}", &err);

    let _ignored_result = shell.error(&err);
    handle_cause(&err, shell);
}

fn handle_cause(cargo_err: &Error, shell: &mut Shell) -> bool {
    fn print(error: String, shell: &mut Shell) {
        drop(writeln!(shell.err(), "\nCaused by:"));
        drop(writeln!(shell.err(), "  {}", error));
    }

    let verbose = shell.verbosity();

    if verbose == Verbose {
        // The first error has already been printed to the shell
        // Print all remaining errors
        for err in cargo_err.causes().skip(1) {
            print(err.to_string(), shell);
        }
    } else {
        // The first error has already been printed to the shell
        // Print remaining errors until one marked as Internal appears
        for err in cargo_err.causes().skip(1) {
            if err.downcast_ref::<Internal>().is_some() {
                return false;
            }

            print(err.to_string(), shell);
        }
    }

    true
}

pub fn version() -> VersionInfo {
    macro_rules! env_str {
        ($name:expr) => { env!($name).to_string() }
    }
    macro_rules! option_env_str {
        ($name:expr) => { option_env!($name).map(|s| s.to_string()) }
    }
    match option_env!("CFG_RELEASE_CHANNEL") {
        // We have environment variables set up from configure/make.
        Some(_) => {
            let commit_info =
                option_env!("CFG_COMMIT_HASH").map(|s| {
                    CommitInfo {
                        commit_hash: s.to_string(),
                        short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
                        commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
                    }
                });
            VersionInfo {
                major: env_str!("CARGO_PKG_VERSION_MAJOR"),
                minor: env_str!("CARGO_PKG_VERSION_MINOR"),
                patch: env_str!("CARGO_PKG_VERSION_PATCH"),
                pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
                cfg_info: Some(CfgInfo {
                    release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
                    commit_info: commit_info,
                }),
            }
        },
        // We are being compiled by Cargo itself.
        None => {
            VersionInfo {
                major: env_str!("CARGO_PKG_VERSION_MAJOR"),
                minor: env_str!("CARGO_PKG_VERSION_MINOR"),
                patch: env_str!("CARGO_PKG_VERSION_PATCH"),
                pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
                cfg_info: None,
            }
        }
    }
}
<commit_msg>Make cargo-the-binary version the same as the Rust version<commit_after>#![deny(unused)]
#![cfg_attr(test, deny(warnings))]
#![recursion_limit="128"]

#[macro_use] extern crate failure;
#[macro_use] extern crate log;
#[macro_use] extern crate scoped_tls;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate serde_json;
extern crate atty;
extern crate crates_io as registry;
extern crate crossbeam;
extern crate curl;
extern crate docopt;
extern crate filetime;
extern crate flate2;
extern crate fs2;
extern crate git2;
extern crate glob;
extern crate hex;
extern crate home;
extern crate ignore;
extern crate jobserver;
extern crate lazycell;
extern crate libc;
extern crate libgit2_sys;
extern crate num_cpus;
extern crate same_file;
extern crate semver;
extern crate serde;
extern crate serde_ignored;
extern crate shell_escape;
extern crate tar;
extern crate tempdir;
extern crate termcolor;
extern crate toml;
extern crate url;
#[cfg(target_os = "macos")]
extern crate core_foundation;

use std::fmt;

use serde::de::DeserializeOwned;
use serde::ser;
use docopt::Docopt;
use failure::Error;

use core::Shell;
use core::shell::Verbosity::Verbose;

pub use util::{CargoError, CargoResult, CliError, CliResult, Config};
pub use util::errors::Internal;

pub const CARGO_ENV: &'static str = "CARGO";

pub mod core;
pub mod ops;
pub mod sources;
pub mod util;

pub struct CommitInfo {
    pub short_commit_hash: String,
    pub commit_hash: String,
    pub commit_date: String,
}

pub struct CfgInfo {
    // Information about the git repository we may have been built from.
    pub commit_info: Option<CommitInfo>,
    // The release channel we were built for.
    pub release_channel: String,
}

pub struct VersionInfo {
    pub major: u8,
    pub minor: u8,
    pub patch: u8,
    pub pre_release: Option<String>,
    // Information that's only available when we were built with
    // configure/make, rather than cargo itself.
    pub cfg_info: Option<CfgInfo>,
}

impl fmt::Display for VersionInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "cargo {}.{}.{}",
               self.major, self.minor, self.patch)?;
        if let Some(channel) = self.cfg_info.as_ref().map(|ci| &ci.release_channel) {
            if channel != "stable" {
                write!(f, "-{}", channel)?;
                let empty = String::from("");
                write!(f, "{}", self.pre_release.as_ref().unwrap_or(&empty))?;
            }
        };

        if let Some(ref cfg) = self.cfg_info {
            if let Some(ref ci) = cfg.commit_info {
                write!(f, " ({} {})",
                       ci.short_commit_hash, ci.commit_date)?;
            }
        };
        Ok(())
    }
}

pub fn call_main_without_stdin<Flags: DeserializeOwned>(
            exec: fn(Flags, &mut Config) -> CliResult,
            config: &mut Config,
            usage: &str,
            args: &[String],
            options_first: bool) -> CliResult
{
    let docopt = Docopt::new(usage).unwrap()
        .options_first(options_first)
        .argv(args.iter().map(|s| &s[..]))
        .help(true);

    let flags = docopt.deserialize().map_err(|e| {
        let code = if e.fatal() {1} else {0};
        CliError::new(e.into(), code)
    })?;

    exec(flags, config)
}

pub fn print_json<T: ser::Serialize>(obj: &T) {
    let encoded = serde_json::to_string(&obj).unwrap();
    println!("{}", encoded);
}

pub fn exit_with_error(err: CliError, shell: &mut Shell) -> ! {
    debug!("exit_with_error; err={:?}", err);

    let CliError { error, exit_code, unknown } = err;
    // exit_code == 0 is non-fatal error, e.g. docopt version info
    let fatal = exit_code != 0;

    let hide = unknown && shell.verbosity() != Verbose;

    if let Some(error) = error {
        if hide {
            drop(shell.error("An unknown error occurred"))
        } else if fatal {
            drop(shell.error(&error))
        } else {
            println!("{}", error);
        }

        if !handle_cause(&error, shell) || hide {
            drop(writeln!(shell.err(), "\nTo learn more, run the command again \
                                        with --verbose."));
        }
    }

    std::process::exit(exit_code)
}

pub fn handle_error(err: CargoError, shell: &mut Shell) {
    debug!("handle_error; err={:?}", &err);

    let _ignored_result = shell.error(&err);
    handle_cause(&err, shell);
}

fn handle_cause(cargo_err: &Error, shell: &mut Shell) -> bool {
    fn print(error: String, shell: &mut Shell) {
        drop(writeln!(shell.err(), "\nCaused by:"));
        drop(writeln!(shell.err(), "  {}", error));
    }

    let verbose = shell.verbosity();

    if verbose == Verbose {
        // The first error has already been printed to the shell
        // Print all remaining errors
        for err in cargo_err.causes().skip(1) {
            print(err.to_string(), shell);
        }
    } else {
        // The first error has already been printed to the shell
        // Print remaining errors until one marked as Internal appears
        for err in cargo_err.causes().skip(1) {
            if err.downcast_ref::<Internal>().is_some() {
                return false;
            }

            print(err.to_string(), shell);
        }
    }

    true
}

pub fn version() -> VersionInfo {
    macro_rules! option_env_str {
        ($name:expr) => { option_env!($name).map(|s| s.to_string()) }
    }

    // So this is pretty horrible...
    // There are two versions at play here:
    //   - version of cargo-the-binary, which you see when you type `cargo --version`
    //   - version of cargo-the-library, which you download from crates.io for use
    //     in your projects.
    //
    // We want to make the `binary` version the same as the corresponding Rust/rustc release.
    // At the same time, we want to keep the library version at `0.x`, because Cargo as
    // a library is (and probably will always be) unstable.
    //
    // Historically, Cargo used the same version number for both the binary and the library.
    // Specifically, rustc 1.x.z was paired with cargo 0.x+1.w.
    // We continue to use this scheme for the library, but transform it to 1.x.w for the purposes
    // of `cargo --version`.
    let major = 1;
    let minor = env!("CARGO_PKG_VERSION_MINOR").parse::<u8>().unwrap() - 1;
    let patch = env!("CARGO_PKG_VERSION_PATCH").parse::<u8>().unwrap();

    match option_env!("CFG_RELEASE_CHANNEL") {
        // We have environment variables set up from configure/make.
        Some(_) => {
            let commit_info =
                option_env!("CFG_COMMIT_HASH").map(|s| {
                    CommitInfo {
                        commit_hash: s.to_string(),
                        short_commit_hash: option_env_str!("CFG_SHORT_COMMIT_HASH").unwrap(),
                        commit_date: option_env_str!("CFG_COMMIT_DATE").unwrap(),
                    }
                });
            VersionInfo {
                major,
                minor,
                patch,
                pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
                cfg_info: Some(CfgInfo {
                    release_channel: option_env_str!("CFG_RELEASE_CHANNEL").unwrap(),
                    commit_info: commit_info,
                }),
            }
        },
        // We are being compiled by Cargo itself.
        None => {
            VersionInfo {
                major,
                minor,
                patch,
                pre_release: option_env_str!("CARGO_PKG_VERSION_PRE"),
                cfg_info: None,
            }
        }
    }
}
<|endoftext|>