<commit_before>use std::collections::BTreeMap;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;

mod from_str;
// mod relabel;

pub mod cli;

/// Variable or terminal symbol in an MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum VarT<T> {
    /// `Var(i, j)` represents the `j`th component of the `i`th successor.
    /// Indexing starts from `0`.
    Var(usize, usize),
    T(T),
}

/// Composition function in an MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub struct Composition<T> {
    pub composition: Vec<Vec<VarT<T>>>,
}

impl<T> From<Vec<Vec<VarT<T>>>> for Composition<T> {
    fn from(encapsulated_value: Vec<Vec<VarT<T>>>) -> Self {
        Composition { composition: encapsulated_value }
    }
}

/// Rule of a weighted MCFG.
#[derive(Debug, PartialOrd, Ord, Clone)]
pub struct PMCFGRule<N, T, W> {
    pub head: N,
    pub tail: Vec<N>,
    pub composition: Composition<T>,
    pub weight: W,
}

impl<N, T, W> PMCFGRule<N, T, W>
    where T: Clone,
          W: Clone,
{
    pub fn map_nonterminals<F, M>(&self, f: F) -> PMCFGRule<M, T, W>
        where F: Fn(&N) -> M,
    {
        PMCFGRule {
            head: f(&self.head),
            tail: self.tail.iter().map(f).collect(),
            composition: self.composition.clone(),
            weight: self.weight.clone()
        }
    }
}

/// A weighted MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct PMCFG<N, T, W> {
    pub _dummy: PhantomData<T>,
    pub initial: Vec<N>,
    pub rules: Vec<PMCFGRule<N, T, W>>,
}

impl<N: Hash, T: Hash, W> Hash for PMCFGRule<N, T, W> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.head.hash(state);
        self.tail.hash(state);
        self.composition.hash(state);
    }
}

impl<N: PartialEq, T: PartialEq, W> PartialEq for PMCFGRule<N, T, W> {
    fn eq(&self, other: &Self) -> bool {
        self.head == other.head && self.tail == other.tail && self.composition == other.composition
    }
}

impl<N: Eq, T: Eq, W> Eq for PMCFGRule<N, T, W> {}

impl<T: fmt::Display> fmt::Display for Composition<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = "".to_string();

        let mut iter0 = self.composition.iter().peekable();
        let mut iter1;

        buffer.push_str("[");
        while let Some(proj) = iter0.next() {
            iter1 = proj.into_iter().peekable();
            buffer.push_str("[");
            while let Some(vart) = iter1.next() {
                buffer.push_str(format!("{}", vart).as_str());
                if iter1.peek().is_some() {
                    buffer.push_str(", ");
                }
            }
            buffer.push_str("]");
            if iter0.peek().is_some() {
                buffer.push_str(", ");
            }
        }
        buffer.push_str("]");

        write!(f, "{}", buffer)
    }
}

impl<T: fmt::Display> fmt::Display for VarT<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            VarT::Var(i, j) => {
                write!(f, "Var {} {}", i, j)
            },
            VarT::T(ref x) => {
                write!(f, "T \"{}\"", x)
            },
        }
    }
}

impl<N: fmt::Display, T: fmt::Display, W: fmt::Display> fmt::Display for PMCFGRule<N, T, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
           let mut buffer = "".to_string();

           let mut iter = self.tail.iter().peekable();

           buffer.push_str("(");
           while let Some(nt) = iter.next() {
               buffer.push_str(format!("\"{}\"", nt).as_str());
               if iter.peek().is_some() {
                   buffer.push_str(", ");
               }
           }
           buffer.push_str(")");

        write!(f, "\"{}\" → {} {}  # {}", self.head, self.composition, buffer, self.weight)
        // write!(f, "\"{}\" → {}", self.head, self.composition)
    }
}

impl<N: fmt::Display, T: fmt::Display, W: fmt::Display> fmt::Display for PMCFG<N, T, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = "".to_string();

        let mut iter = self.initial.iter().peekable();

        buffer.push_str("initial: [");
        while let Some(nt) = iter.next() {
            buffer.push_str(format!("\"{}\"", nt).as_str());
            if iter.peek().is_some() {
                buffer.push_str(", ");
            }
        }
        buffer.push_str("]\n\n");

        for r in &self.rules {
            buffer.push_str(format!("{}\n", r).as_str());
        }

        write!(f, "{}", buffer)
    }
}

pub fn evaluate<T: Clone + fmt::Debug>(term_map: &BTreeMap<Vec<usize>, Composition<T>>) -> Composition<T> {
    evaluate_pos(term_map, vec![])
}

pub fn evaluate_pos<T: Clone + fmt::Debug>(term_map: &BTreeMap<Vec<usize>, Composition<T>>, address: Vec<usize>) -> Composition<T> {
    let unexpanded_composition = &term_map.get(&address).unwrap().composition;
    let mut expanded_nonterminals: BTreeMap<_, Vec<Vec<VarT<T>>>> = BTreeMap::new();
    let mut expanded_composition = Vec::new();

    for component in unexpanded_composition {
        let mut expanded_component = Vec::new();

        for variable in component {
            match variable {
                &VarT::Var(num_nonter, num_compon) => {
                    if !expanded_nonterminals.contains_key(&num_nonter) {
                        let mut child_address = address.clone();
                        child_address.push(num_nonter);
                        let nonter_compos = evaluate_pos(term_map, child_address).composition;
                        expanded_nonterminals.insert(num_nonter, nonter_compos);
                    }

                    let nonter_compos = expanded_nonterminals.get(&num_nonter).unwrap();

                    if let Some(compon) = nonter_compos.get(num_compon) {
                        for terminal in compon {
                            expanded_component.push(terminal.clone());
                        }
                    } else {
                        panic!("{:?}: use of {}-th component of nonterminal {} that has only {} components!",
                               unexpanded_composition, num_compon, num_nonter, nonter_compos.len());
                    }

                },
                &VarT::T(ref terminal) => {
                    expanded_component.push(VarT::T(terminal.clone()));
                },
            }
        }

        expanded_composition.push(expanded_component);
    }

    Composition::from(expanded_composition)
}

#[cfg(test)]
mod tests {
    use super::*;
    use VarT::{Var, T};

    #[test]
    fn test_evaluate() {
        let mut term_map: BTreeMap<Vec<usize>, _> = BTreeMap::new();
        term_map.insert(vec![], Composition::from(vec![
                vec![Var(0,0), Var(1,0), Var(0,1), Var(1,1)]
        ]));
        term_map.insert(vec![0], Composition::from(vec![
                vec![Var(1,0), Var(0,0)],
                vec![Var(2,0), Var(0,1)]
        ]));
        term_map.insert(vec![0,0], Composition::from(vec![
                vec![Var(1,0), Var(0,0)],
                vec![Var(2,0), Var(0,1)]
        ]));
        term_map.insert(vec![0,0,0], Composition::from(vec![
                vec![],
                vec![]
        ]));
        term_map.insert(vec![0,0,1], Composition::from(vec![
                vec![T('a')]
        ]));
        term_map.insert(vec![0,0,2], Composition::from(vec![
                vec![T('c')]
        ]));
        term_map.insert(vec![0,1], Composition::from(vec![
                vec![T('a')]
        ]));
        term_map.insert(vec![0,2], Composition::from(vec![
                vec![T('c')]
        ]));
        term_map.insert(vec![1], Composition::from(vec![
                vec![Var(1,0), Var(0,0)],
                vec![Var(2,0), Var(0,1)]
        ]));
        term_map.insert(vec![1,0], Composition::from(vec![
                vec![],
                vec![]
        ]));
        term_map.insert(vec![1,1], Composition::from(vec![
                vec![T('b')]
        ]));
        term_map.insert(vec![1,2], Composition::from(vec![
                vec![T('d')]
        ]));

        let expanded_compos = Composition::from(vec![
            vec![T('a'), T('a'), T('b'), T('c'), T('c'), T('d')]
        ]);

        assert_eq!(expanded_compos, evaluate(&term_map));
    }

    #[test]
    #[should_panic(expected =
        "[[Var(0, 0), Var(0, 1)]]: use of 1-th component of nonterminal 0 that has only 1 components!"
    )]
    fn test_evaluate_invalid_composition() {
        let mut term_map: BTreeMap<Vec<usize>, _> = BTreeMap::new();
        term_map.insert(vec![], Composition::from(vec![
                vec![Var(0,0), Var(0,1)]
        ]));
        term_map.insert(vec![0], Composition::from(vec![
                vec![T('a')]
        ]));

        evaluate(&term_map);
    }
}
<commit_msg>src/pmcfg/mod.rs: added identify_terminals()<commit_after>use std::collections::BTreeMap;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;

mod from_str;
// mod relabel;

pub mod cli;

/// Variable or terminal symbol in an MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum VarT<T> {
    /// `Var(i, j)` represents the `j`th component of the `i`th successor.
    /// Indexing starts from `0`.
    Var(usize, usize),
    T(T),
}

/// Composition function in an MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub struct Composition<T> {
    pub composition: Vec<Vec<VarT<T>>>,
}

impl<T> From<Vec<Vec<VarT<T>>>> for Composition<T> {
    fn from(encapsulated_value: Vec<Vec<VarT<T>>>) -> Self {
        Composition { composition: encapsulated_value }
    }
}

/// Rule of a weighted MCFG.
#[derive(Debug, PartialOrd, Ord, Clone)]
pub struct PMCFGRule<N, T, W> {
    pub head: N,
    pub tail: Vec<N>,
    pub composition: Composition<T>,
    pub weight: W,
}

impl<N, T, W> PMCFGRule<N, T, W>
    where T: Clone,
          W: Clone,
{
    pub fn map_nonterminals<F, M>(&self, f: F) -> PMCFGRule<M, T, W>
        where F: Fn(&N) -> M,
    {
        PMCFGRule {
            head: f(&self.head),
            tail: self.tail.iter().map(f).collect(),
            composition: self.composition.clone(),
            weight: self.weight.clone()
        }
    }
}

/// A weighted MCFG.
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct PMCFG<N, T, W> {
    pub _dummy: PhantomData<T>,
    pub initial: Vec<N>,
    pub rules: Vec<PMCFGRule<N, T, W>>,
}

impl<N: Hash, T: Hash, W> Hash for PMCFGRule<N, T, W> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.head.hash(state);
        self.tail.hash(state);
        self.composition.hash(state);
    }
}

impl<N: PartialEq, T: PartialEq, W> PartialEq for PMCFGRule<N, T, W> {
    fn eq(&self, other: &Self) -> bool {
        self.head == other.head && self.tail == other.tail && self.composition == other.composition
    }
}

impl<N: Eq, T: Eq, W> Eq for PMCFGRule<N, T, W> {}

impl<T: fmt::Display> fmt::Display for Composition<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = "".to_string();

        let mut iter0 = self.composition.iter().peekable();
        let mut iter1;

        buffer.push_str("[");
        while let Some(proj) = iter0.next() {
            iter1 = proj.into_iter().peekable();
            buffer.push_str("[");
            while let Some(vart) = iter1.next() {
                buffer.push_str(format!("{}", vart).as_str());
                if iter1.peek().is_some() {
                    buffer.push_str(", ");
                }
            }
            buffer.push_str("]");
            if iter0.peek().is_some() {
                buffer.push_str(", ");
            }
        }
        buffer.push_str("]");

        write!(f, "{}", buffer)
    }
}

impl<T: fmt::Display> fmt::Display for VarT<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            VarT::Var(i, j) => {
                write!(f, "Var {} {}", i, j)
            },
            VarT::T(ref x) => {
                write!(f, "T \"{}\"", x)
            },
        }
    }
}

impl<N: fmt::Display, T: fmt::Display, W: fmt::Display> fmt::Display for PMCFGRule<N, T, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
           let mut buffer = "".to_string();

           let mut iter = self.tail.iter().peekable();

           buffer.push_str("(");
           while let Some(nt) = iter.next() {
               buffer.push_str(format!("\"{}\"", nt).as_str());
               if iter.peek().is_some() {
                   buffer.push_str(", ");
               }
           }
           buffer.push_str(")");

        write!(f, "\"{}\" → {} {}  # {}", self.head, self.composition, buffer, self.weight)
        // write!(f, "\"{}\" → {}", self.head, self.composition)
    }
}

impl<N: fmt::Display, T: fmt::Display, W: fmt::Display> fmt::Display for PMCFG<N, T, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut buffer = "".to_string();

        let mut iter = self.initial.iter().peekable();

        buffer.push_str("initial: [");
        while let Some(nt) = iter.next() {
            buffer.push_str(format!("\"{}\"", nt).as_str());
            if iter.peek().is_some() {
                buffer.push_str(", ");
            }
        }
        buffer.push_str("]\n\n");

        for r in &self.rules {
            buffer.push_str(format!("{}\n", r).as_str());
        }

        write!(f, "{}", buffer)
    }
}

pub fn evaluate<T: Clone + fmt::Debug>(term_map: &BTreeMap<Vec<usize>, Composition<T>>) -> Composition<T> {
    evaluate_pos(term_map, vec![])
}

pub fn evaluate_pos<T: Clone + fmt::Debug>(term_map: &BTreeMap<Vec<usize>, Composition<T>>, address: Vec<usize>) -> Composition<T> {
    let unexpanded_composition = &term_map.get(&address).unwrap().composition;
    let mut expanded_nonterminals: BTreeMap<_, Vec<Vec<VarT<T>>>> = BTreeMap::new();
    let mut expanded_composition = Vec::new();

    for component in unexpanded_composition {
        let mut expanded_component = Vec::new();

        for variable in component {
            match variable {
                &VarT::Var(num_nonter, num_compon) => {
                    if !expanded_nonterminals.contains_key(&num_nonter) {
                        let mut child_address = address.clone();
                        child_address.push(num_nonter);
                        let nonter_compos = evaluate_pos(term_map, child_address).composition;
                        expanded_nonterminals.insert(num_nonter, nonter_compos);
                    }

                    let nonter_compos = expanded_nonterminals.get(&num_nonter).unwrap();

                    if let Some(compon) = nonter_compos.get(num_compon) {
                        for terminal in compon {
                            expanded_component.push(terminal.clone());
                        }
                    } else {
                        panic!("{:?}: use of {}-th component of nonterminal {} that has only {} components!",
                               unexpanded_composition, num_compon, num_nonter, nonter_compos.len());
                    }

                },
                &VarT::T(ref terminal) => {
                    expanded_component.push(VarT::T(terminal.clone()));
                },
            }
        }

        expanded_composition.push(expanded_component);
    }

    Composition::from(expanded_composition)
}

pub fn identify_terminals<A: Clone>(tree_map: &BTreeMap<Vec<usize>, Composition<A>>) -> (BTreeMap<Vec<usize>, Composition<(Vec<usize>, usize)>>, BTreeMap<(Vec<usize>, usize), A>) {
    let mut identified_tree_map = BTreeMap::new();
    let mut terminal_map = BTreeMap::new();

    for (address, composition) in tree_map {
        let vec_compos = &composition.composition;
        let mut identified_compos = Vec::new();
        let mut compos_var_pos = 0;

        for component in vec_compos {
            let mut identified_compon = Vec::new();

            for variable in component {
                match variable {
                    &VarT::Var(x, y) => {
                        identified_compon.push(VarT::Var(x, y));
                    },
                    &VarT::T(ref terminal) => {
                        let terminal_id = (address.clone(), compos_var_pos);
                        identified_compon.push(VarT::T(terminal_id.clone()));
                        terminal_map.insert(terminal_id, terminal.clone());
                    },
                };

                compos_var_pos += 1;
            }

            identified_compos.push(identified_compon);
        }

        identified_tree_map.insert(address.clone(), Composition::from(identified_compos));
    }

    (identified_tree_map, terminal_map)
}

#[cfg(test)]
mod tests {
    use super::*;
    use VarT::{Var, T};

    #[test]
    fn test_evaluate() {
        let mut term_map: BTreeMap<Vec<usize>, _> = BTreeMap::new();
        term_map.insert(vec![], Composition::from(vec![
                vec![Var(0,0), Var(1,0), Var(0,1), Var(1,1)]
        ]));
        term_map.insert(vec![0], Composition::from(vec![
                vec![Var(1,0), Var(0,0)],
                vec![Var(2,0), Var(0,1)]
        ]));
        term_map.insert(vec![0,0], Composition::from(vec![
                vec![Var(1,0), Var(0,0)],
                vec![Var(2,0), Var(0,1)]
        ]));
        term_map.insert(vec![0,0,0], Composition::from(vec![
                vec![],
                vec![]
        ]));
        term_map.insert(vec![0,0,1], Composition::from(vec![
                vec![T('a')]
        ]));
        term_map.insert(vec![0,0,2], Composition::from(vec![
                vec![T('c')]
        ]));
        term_map.insert(vec![0,1], Composition::from(vec![
                vec![T('a')]
        ]));
        term_map.insert(vec![0,2], Composition::from(vec![
                vec![T('c')]
        ]));
        term_map.insert(vec![1], Composition::from(vec![
                vec![Var(1,0), Var(0,0)],
                vec![Var(2,0), Var(0,1)]
        ]));
        term_map.insert(vec![1,0], Composition::from(vec![
                vec![],
                vec![]
        ]));
        term_map.insert(vec![1,1], Composition::from(vec![
                vec![T('b')]
        ]));
        term_map.insert(vec![1,2], Composition::from(vec![
                vec![T('d')]
        ]));

        let expanded_compos = Composition::from(vec![
            vec![T('a'), T('a'), T('b'), T('c'), T('c'), T('d')]
        ]);

        assert_eq!(expanded_compos, evaluate(&term_map));
    }

    #[test]
    #[should_panic(expected =
        "[[Var(0, 0), Var(0, 1)]]: use of 1-th component of nonterminal 0 that has only 1 components!"
    )]
    fn test_evaluate_invalid_composition() {
        let mut term_map: BTreeMap<Vec<usize>, _> = BTreeMap::new();
        term_map.insert(vec![], Composition::from(vec![
                vec![Var(0,0), Var(0,1)]
        ]));
        term_map.insert(vec![0], Composition::from(vec![
                vec![T('a')]
        ]));

        evaluate(&term_map);
    }
}
<|endoftext|>


<commit_before>//! Features and intervals for gene annotations.

use std::collections::HashMap;

use bio::io::Strand;

/// Builder for exons, transcripts, or genes.
///
/// Use this struct to initialize annotation features with the default values.
pub struct Feature;

impl Feature {

    /// Creates a gene interval with default values.
    ///
    /// A gene interval is a container for transcript intervals.
    ///
    /// # Examples
    ///
    /// ```
    /// let gene = Feature::gene();
    ///
    /// assert_eq!(gene.transcript().len(), 0);
    /// assert_eq!(gene.start(), 0);
    /// assert_eq!(gene.end(), 0);
    /// assert_eq!(gene.name(), None);
    /// ```
    pub fn gene() -> Gene {
        Gene::default()
    }

    /// Creates a transcript interval with default values.
    ///
    /// A transcript interval is a container for exon intervals.
    ///
    /// # Examples
    ///
    /// ```
    /// use bio::io::Strand;
    ///
    /// let transcript = Feature::transcript();
    ///
    /// assert_eq!(transcript.exons().len(), 0);
    /// assert_eq!(transcript.strand(), &Strand::Unknown)
    /// assert_eq!(transcript.start(), 0);
    /// assert_eq!(transcript.end(), 0);
    /// assert_eq!(transcript.name(), None);
    /// ```
    pub fn transcript() -> Transcript {
        Transcript::default()
    }

    /// Creates an exon interval with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// let exon = Feature::exon();
    ///
    /// assert_eq!(exon.start(), 0);
    /// assert_eq!(exon.end(), 0);
    /// assert_eq!(exon.name(), None);
    /// ```
    pub fn exon() -> Exon {
        Exon::default()
    }

    /// Performs validation of the interval values.
    ///
    /// If the validation fails, an error message is returned within
    /// the `Result` type.
    pub fn validate_interval<T: Interval>(ival: T) -> Result<T, &'static str> {
        if ival.start() > ival.end() {
            return Err("interval start coordinate larger than its end coordinate")
        }

        Ok(ival)
    }
}

/// Interface for features with start and end coordinates.
///
/// The intervals represented here are zero-based, half open intervals.
/// Coordinates start from zero and start coordinates must be less than
/// or equal to the end coordinates.
pub trait Interval: Sized {

    /// Start coordinate of the interval.
    fn start(&self) -> u64;

    /// End coordinate of the interval.
    fn end(&self) -> u64;

    /// Performs various validation of the interval.
    fn validate(self) -> Result<Self, &'static str>;

    /// The number of bases covered by the interval.
    fn span(&self) -> u64 {
        self.end() - self.start()
    }

    /// Whether two intervals have an intersection or not.
    fn overlaps(&self, other: &Self) -> bool {
        (other.start() <= self.start() && self.start() <= other.end()) ||
        (other.start() <= self.end() && self.end() <= other.end())
    }

    /// Whether one interval completely contains the other.
    fn envelops(&self, other: &Self) -> bool {
        self.start() <= other.start() && self.end() >= other.end()
    }

    /// Whether two intervals cover a contiguous region without any overlaps.
    fn adjacent(&self, other: &Self) -> bool {
        self.end() == other.start() || self.start() == other.end()
    }
}

/// Gene annotation.
#[derive(Debug, Default)]
pub struct Gene {
    name: Option<String>,
    start: u64,
    end: u64,
    transcripts: HashMap<String, Transcript>,
}

impl Gene {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn transcripts(&self) -> &HashMap<String, Transcript> {
        &self.transcripts
    }
}

impl Interval for Gene {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        Feature::validate_interval(self)
    }
}

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

    #[test]
    fn default() {
        let gene = Feature::gene();
        assert_eq!(gene.start(), 0);
        assert_eq!(gene.end(), 0);
        assert_eq!(gene.name(), None);
        assert_eq!(gene.transcripts().len(), 0);
    }
}

/// Transcript annotation.
#[derive(Debug)]
pub struct Transcript {
    name: Option<String>,
    strand: Strand,
    start: u64,
    end: u64,
    cds_start: Option<u64>,
    cds_end: Option<u64>,
    exons: Vec<Exon>,
}

impl Default for Transcript {

    fn default() -> Transcript {
        Transcript {
            name: None,
            strand: Strand::Unknown,
            start: 0,
            end: 0,
            cds_start: None,
            cds_end: None,
            exons: Vec::new(),
        }
    }
}

impl Transcript {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn strand(&self) -> &Strand {
        &self.strand
    }

    pub fn cds_start(&self) -> Option<u64> {
        self.cds_start
    }

    pub fn cds_end(&self) -> Option<u64> {
        self.cds_end
    }

    pub fn exons(&self) -> &Vec<Exon> {
        &self.exons
    }
}

impl Interval for Transcript {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        Feature::validate_interval(self)
    }
}

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

    #[test]
    fn default() {
        let trx = Feature::transcript();
        assert_eq!(trx.start(), 0);
        assert_eq!(trx.end(), 0);
        assert_eq!(trx.name(), None);
        assert_eq!(trx.strand(), &Strand::Unknown);
        assert_eq!(trx.cds_start(), None);
        assert_eq!(trx.cds_end(), None);
        assert_eq!(trx.exons().len(), 0);
    }
}

/// Exon annotation.
#[derive(Debug, Default)]
pub struct Exon {
    name: Option<String>,
    start: u64,
    end: u64,
}

impl Exon {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn with_name<T>(mut self, n: T) -> Exon
        where T: Into<String>
    {
        self.name = Some(n.into());
        self
    }
}

impl Interval for Exon {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        Feature::validate_interval(self)
    }
}

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

    #[test]
    fn default() {
        let exon = Feature::exon();
        assert_eq!(exon.start(), 0);
        assert_eq!(exon.end(), 0);
        assert_eq!(exon.name(), None);
    }

    #[test]
    fn with_name() {
        let exon1 = Feature::exon().with_name("ex1");
        assert_eq!(exon1.start(), 0);
        assert_eq!(exon1.end(), 0);
        assert_eq!(exon1.name(), Some("ex1"));

        let exon2 = Feature::exon().with_name("ex2".to_owned());
        assert_eq!(exon2.start(), 0);
        assert_eq!(exon2.end(), 0);
        assert_eq!(exon2.name(), Some("ex2"));
    }
}
<commit_msg>Move coords validation function as trait function<commit_after>//! Features and intervals for gene annotations.

use std::collections::HashMap;

use bio::io::Strand;

/// Builder for exons, transcripts, or genes.
///
/// Use this struct to initialize annotation features with the default values.
pub struct Feature;

impl Feature {

    /// Creates a gene interval with default values.
    ///
    /// A gene interval is a container for transcript intervals.
    ///
    /// # Examples
    ///
    /// ```
    /// let gene = Feature::gene();
    ///
    /// assert_eq!(gene.transcript().len(), 0);
    /// assert_eq!(gene.start(), 0);
    /// assert_eq!(gene.end(), 0);
    /// assert_eq!(gene.name(), None);
    /// ```
    pub fn gene() -> Gene {
        Gene::default()
    }

    /// Creates a transcript interval with default values.
    ///
    /// A transcript interval is a container for exon intervals.
    ///
    /// # Examples
    ///
    /// ```
    /// use bio::io::Strand;
    ///
    /// let transcript = Feature::transcript();
    ///
    /// assert_eq!(transcript.exons().len(), 0);
    /// assert_eq!(transcript.strand(), &Strand::Unknown)
    /// assert_eq!(transcript.start(), 0);
    /// assert_eq!(transcript.end(), 0);
    /// assert_eq!(transcript.name(), None);
    /// ```
    pub fn transcript() -> Transcript {
        Transcript::default()
    }

    /// Creates an exon interval with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// let exon = Feature::exon();
    ///
    /// assert_eq!(exon.start(), 0);
    /// assert_eq!(exon.end(), 0);
    /// assert_eq!(exon.name(), None);
    /// ```
    pub fn exon() -> Exon {
        Exon::default()
    }
}

/// Interface for features with start and end coordinates.
///
/// The intervals represented here are zero-based, half open intervals.
/// Coordinates start from zero and start coordinates must be less than
/// or equal to the end coordinates.
pub trait Interval: Sized {

    /// Start coordinate of the interval.
    fn start(&self) -> u64;

    /// End coordinate of the interval.
    fn end(&self) -> u64;

    /// Performs various validation of the interval.
    fn validate(self) -> Result<Self, &'static str>;

    /// The number of bases covered by the interval.
    fn span(&self) -> u64 {
        self.end() - self.start()
    }

    /// Whether two intervals have an intersection or not.
    fn overlaps(&self, other: &Self) -> bool {
        (other.start() <= self.start() && self.start() <= other.end()) ||
        (other.start() <= self.end() && self.end() <= other.end())
    }

    /// Whether one interval completely contains the other.
    fn envelops(&self, other: &Self) -> bool {
        self.start() <= other.start() && self.end() >= other.end()
    }

    /// Whether two intervals cover a contiguous region without any overlaps.
    fn adjacent(&self, other: &Self) -> bool {
        self.end() == other.start() || self.start() == other.end()
    }

    /// Performs validation of the interval coordinates.
    ///
    /// If the validation fails, an error message is returned within
    /// the `Result` type.
    fn validate_coords(self) -> Result<Self, &'static str> {
        if self.start() > self.end() {
            return Err("interval start coordinate larger than its end coordinate")
        }

        Ok(self)
    }
}

/// Gene annotation.
#[derive(Debug, Default)]
pub struct Gene {
    name: Option<String>,
    start: u64,
    end: u64,
    transcripts: HashMap<String, Transcript>,
}

impl Gene {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn transcripts(&self) -> &HashMap<String, Transcript> {
        &self.transcripts
    }
}

impl Interval for Gene {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let gene = Feature::gene();
        assert_eq!(gene.start(), 0);
        assert_eq!(gene.end(), 0);
        assert_eq!(gene.name(), None);
        assert_eq!(gene.transcripts().len(), 0);
    }
}

/// Transcript annotation.
#[derive(Debug)]
pub struct Transcript {
    name: Option<String>,
    strand: Strand,
    start: u64,
    end: u64,
    cds_start: Option<u64>,
    cds_end: Option<u64>,
    exons: Vec<Exon>,
}

impl Default for Transcript {

    fn default() -> Transcript {
        Transcript {
            name: None,
            strand: Strand::Unknown,
            start: 0,
            end: 0,
            cds_start: None,
            cds_end: None,
            exons: Vec::new(),
        }
    }
}

impl Transcript {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn strand(&self) -> &Strand {
        &self.strand
    }

    pub fn cds_start(&self) -> Option<u64> {
        self.cds_start
    }

    pub fn cds_end(&self) -> Option<u64> {
        self.cds_end
    }

    pub fn exons(&self) -> &Vec<Exon> {
        &self.exons
    }
}

impl Interval for Transcript {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let trx = Feature::transcript();
        assert_eq!(trx.start(), 0);
        assert_eq!(trx.end(), 0);
        assert_eq!(trx.name(), None);
        assert_eq!(trx.strand(), &Strand::Unknown);
        assert_eq!(trx.cds_start(), None);
        assert_eq!(trx.cds_end(), None);
        assert_eq!(trx.exons().len(), 0);
    }
}

/// Exon annotation.
#[derive(Debug, Default)]
pub struct Exon {
    name: Option<String>,
    start: u64,
    end: u64,
}

impl Exon {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn with_name<T>(mut self, n: T) -> Exon
        where T: Into<String>
    {
        self.name = Some(n.into());
        self
    }
}

impl Interval for Exon {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let exon = Feature::exon();
        assert_eq!(exon.start(), 0);
        assert_eq!(exon.end(), 0);
        assert_eq!(exon.name(), None);
    }

    #[test]
    fn with_name() {
        let exon1 = Feature::exon().with_name("ex1");
        assert_eq!(exon1.start(), 0);
        assert_eq!(exon1.end(), 0);
        assert_eq!(exon1.name(), Some("ex1"));

        let exon2 = Feature::exon().with_name("ex2".to_owned());
        assert_eq!(exon2.start(), 0);
        assert_eq!(exon2.end(), 0);
        assert_eq!(exon2.name(), Some("ex2"));
    }
}
<|endoftext|>


<commit_before>//! Unix-specific utilities for working with the filesystem.

use std::ffi::{OsStr, OsString};
use std::path::Path;

use log::warn;

/// An extended attribute of a file.
///
/// On Linux, extended attributes can be obtained using `getfattr` and set with
/// `setfattr` utilities. On macOS, they can be manipulated through `getxattr`
/// and `setxattr` utilities.
///
/// See the [Wikipedia] article for more details.
///
/// [Wikipedia]: https://en.wikipedia.org/wiki/Extended_file_attributes
pub struct ExtAttr {
    /// A name of the extended attribute.
    pub name: OsString,
    /// A value of the extended attribute.
    pub value: Option<Vec<u8>>,
}

/// Returns an iterator over extended attributes of the specified file.
///
/// # Errors
///
/// The function will fail if a list of extended attributes of the file cannot
/// be obtained (e.g. when the file doesn't exist). However, all errors when
/// that can occur when inspecting values for particular attribute are logged
/// and forgotten.
///
/// # Examples
///
/// ```no_run
/// let attrs = rrg::fs::unix::ext_attrs(&"/tmp/foo")
///     .expect("failed to collect extended attributes");
///
/// for attr in attrs {
///     let name = attr.name.to_string_lossy();
///     match attr.value {
///         Some(value) => {
///             let value = std::str::from_utf8(&value)
///                 .expect("failed to convert attribute value");
///
///             println!("{}: {}", name, value);
///         },
///         None => println!("{}", name),
///     }
/// }
/// ```
pub fn ext_attrs<'p, P>(path: &'p P) -> std::io::Result<ExtAttrs<'p>>
where
    P: AsRef<Path>,
{
    let iter = xattr::list(&path)?;

    Ok(ExtAttrs {
        path: path.as_ref(),
        iter: iter,
    })
}

/// Iterator over extended attributes of a file.
///
/// Note that this iterator always returns an attribute. All errors that can
/// occur when obtaining values for particular attributes are swallowed.
///
/// The iterator can be constructed with the [`ext_attrs`] function.
///
/// [`ext_attrs`]: fn.ext_attrs.html
pub struct ExtAttrs<'p> {
    path: &'p Path,
    iter: xattr::XAttrs,
}

impl<'p> Iterator for ExtAttrs<'p> {

    type Item = ExtAttr;

    fn next(&mut self) -> Option<ExtAttr> {
        for name in &mut self.iter {
            let value = match ext_attr_value(self.path, &name) {
                Ok(value) => value,
                Err(()) => continue,
            };

            return Some(ExtAttr {
                name: name,
                value: value,
            });
        }

        None
    }
}

/// Collects value of an extended attribute with the specified name.
///
/// This is a tiny wrapper around `xattr::get`, but logs and forgets the error
/// (if occurs).
fn ext_attr_value<P>(path: P, name: &OsStr) -> Result<Option<Vec<u8>>, ()>
where
    P: AsRef<Path>,
{
    xattr::get(&path, name).map_err(|error| {
        warn! {
            "failed to collect attribute '{:?}' of '{path}': {cause}",
            name = name,
            path = path.as_ref().display(),
            cause = error,
        };
    })
}
<commit_msg>Use more idiomatic type for attribute values.<commit_after>//! Unix-specific utilities for working with the filesystem.

use std::ffi::{OsStr, OsString};
use std::path::Path;

use log::warn;

/// An extended attribute of a file.
///
/// On Linux, extended attributes can be obtained using `getfattr` and set with
/// `setfattr` utilities. On macOS, they can be manipulated through `getxattr`
/// and `setxattr` utilities.
///
/// See the [Wikipedia] article for more details.
///
/// [Wikipedia]: https://en.wikipedia.org/wiki/Extended_file_attributes
pub struct ExtAttr {
    /// A name of the extended attribute.
    pub name: OsString,
    /// A value of the extended attribute.
    pub value: Option<OsString>,
}

/// Returns an iterator over extended attributes of the specified file.
///
/// # Errors
///
/// The function will fail if a list of extended attributes of the file cannot
/// be obtained (e.g. when the file doesn't exist). However, all errors when
/// that can occur when inspecting values for particular attribute are logged
/// and forgotten.
///
/// # Examples
///
/// ```no_run
/// let attrs = rrg::fs::unix::ext_attrs(&"/tmp/foo")
///     .expect("failed to collect extended attributes");
///
/// for attr in attrs {
///     let name = attr.name.to_string_lossy();
///     match attr.value {
///         Some(value) => println!("{}: {}", name, value.to_string_lossy()),
///         None => println!("{}", name),
///     }
/// }
/// ```
pub fn ext_attrs<'p, P>(path: &'p P) -> std::io::Result<ExtAttrs<'p>>
where
    P: AsRef<Path>,
{
    let iter = xattr::list(&path)?;

    Ok(ExtAttrs {
        path: path.as_ref(),
        iter: iter,
    })
}

/// Iterator over extended attributes of a file.
///
/// Note that this iterator always returns an attribute. All errors that can
/// occur when obtaining values for particular attributes are swallowed.
///
/// The iterator can be constructed with the [`ext_attrs`] function.
///
/// [`ext_attrs`]: fn.ext_attrs.html
pub struct ExtAttrs<'p> {
    path: &'p Path,
    iter: xattr::XAttrs,
}

impl<'p> Iterator for ExtAttrs<'p> {

    type Item = ExtAttr;

    fn next(&mut self) -> Option<ExtAttr> {
        for name in &mut self.iter {
            let value = match ext_attr_value(self.path, &name) {
                Ok(value) => value,
                Err(()) => continue,
            };

            return Some(ExtAttr {
                name: name,
                value: value,
            });
        }

        None
    }
}

/// Collects value of an extended attribute with the specified name.
///
/// This is a tiny wrapper around `xattr::get`, but logs and forgets the error
/// (if occurs).
fn ext_attr_value<P>(path: P, name: &OsStr) -> Result<Option<OsString>, ()>
where
    P: AsRef<Path>,
{
    match xattr::get(&path, name) {
        Ok(value) => Ok(value.map(std::os::unix::ffi::OsStringExt::from_vec)),
        Err(error) => Err(warn! {
            "failed to collect attribute '{:?}' of '{path}': {cause}",
            name = name,
            path = path.as_ref().display(),
            cause = error,
        }),
    }
}
<|endoftext|>


<commit_before>#![allow(unused)]

//! Implements a map from integer indices to data.
//! Rather than storing data for every index, internally, this maps entire ranges to the data.
//! To this end, the APIs all work on ranges, not on individual integers. Ranges are split as
//! necessary (e.g. when [0,5) is first associated with X, and then [1,2) is mutated).
//! Users must not depend on whether a range is coalesced or not, even though this is observable
//! via the iteration APIs.

use std::ops;
use std::num::NonZeroU64;

use rustc::ty::layout::Size;

#[derive(Clone, Debug)]
struct Elem<T> {
    range: ops::Range<u64>, // the range covered by this element, never empty
    data: T,
}
#[derive(Clone, Debug)]
pub struct RangeMap<T> {
    v: Vec<Elem<T>>,
}

impl<T> RangeMap<T> {
    /// Create a new RangeMap for the given size, and with the given initial value used for
    /// the entire range.
    #[inline(always)]
    pub fn new(size: Size, init: T) -> RangeMap<T> {
        let size = size.bytes();
        let mut map = RangeMap { v: Vec::new() };
        if size > 0 {
            map.v.push(Elem {
                range: 0..size,
                data: init
            });
        }
        map
    }

    /// Find the index containing the given offset.
    fn find_offset(&self, offset: u64) -> usize {
        // We do a binary search
        let mut left = 0usize; // inclusive
        let mut right = self.v.len(); // exclusive
        loop {
            debug_assert!(left < right, "find_offset: offset {} is out-of-bounds", offset);
            let candidate = left.checked_add(right).unwrap() / 2;
            let elem = &self.v[candidate];
            if offset < elem.range.start {
                // we are too far right (offset is further left)
                debug_assert!(candidate < right); // we are making progress
                right = candidate;
            } else if offset >= elem.range.end {
                // we are too far left (offset is further right)
                debug_assert!(candidate >= left); // we are making progress
                left = candidate+1;
            } else {
                // This is it!
                return candidate;
            }
        }
    }

    /// Provide read-only iteration over everything in the given range.  This does
    /// *not* split items if they overlap with the edges.  Do not use this to mutate
    /// through interior mutability.
    pub fn iter<'a>(&'a self, offset: Size, len: Size) -> impl Iterator<Item = &'a T> + 'a {
        let offset = offset.bytes();
        let len = len.bytes();
        // Compute a slice starting with the elements we care about
        let slice: &[Elem<T>] = if len == 0 {
                // We just need any empty iterator.  We don't even want to
                // yield the element that surrounds this position.
                &[]
            } else {
                let first_idx = self.find_offset(offset);
                &self.v[first_idx..]
            };
        let end = offset + len; // the first offset that is not included any more
        slice.iter()
            .take_while(move |elem| elem.range.start < end)
            .map(|elem| &elem.data)
    }

    pub fn iter_mut_all<'a>(&'a mut self) -> impl Iterator<Item = &'a mut T> + 'a {
        self.v.iter_mut().map(|elem| &mut elem.data)
    }

    // Split the element situated at the given `index`, such that the 2nd one starts at offset `split_offset`.
    // Do nothing if the element already starts there.
    // Return whether a split was necessary.
    fn split_index(&mut self, index: usize, split_offset: u64) -> bool
    where
        T: Clone,
    {
        let elem = &mut self.v[index];
        if split_offset == elem.range.start || split_offset == elem.range.end {
            // Nothing to do
            return false;
        }
        debug_assert!(elem.range.contains(&split_offset),
            "The split_offset is not in the element to be split");

        // Now we really have to split.  Reduce length of first element.
        let second_range = split_offset..elem.range.end;
        elem.range.end = split_offset;
        // Copy the data, and insert 2nd element
        let second = Elem {
            range: second_range,
            data: elem.data.clone(),
        };
        self.v.insert(index+1, second);
        return true;
    }

    /// Provide mutable iteration over everything in the given range.  As a side-effect,
    /// this will split entries in the map that are only partially hit by the given range,
    /// to make sure that when they are mutated, the effect is constrained to the given range.
    pub fn iter_mut<'a>(
        &'a mut self,
        offset: Size,
        len: Size,
    ) -> impl Iterator<Item = &'a mut T> + 'a
    where
        T: Clone + PartialEq,
    {
        let offset = offset.bytes();
        let len = len.bytes();
        // Compute a slice containing exactly the elements we care about
        let slice: &mut [Elem<T>] = if len == 0 {
                // We just need any empty iterator.  We don't even want to
                // yield the element that surrounds this position, nor do
                // any splitting.
                &mut []
            } else {
                // Make sure we got a clear beginning
                let mut first_idx = self.find_offset(offset);
                if self.split_index(first_idx, offset) {
                    // The newly created 2nd element is ours
                    first_idx += 1;
                }
                let first_idx = first_idx; // no more mutation
                // Find our end.  Linear scan, but that's okay because the iteration
                // is doing the same linear scan anyway -- no increase in complexity.
                // We combine this scan with a scan for duplicates that we can merge, to reduce
                // the number of elements.
                let mut equal_since_idx = first_idx;
                let mut end_idx = first_idx; // when the loop is done, this is the first excluded element.
                loop {
                    // Compute if `end` is the last element we need to look at.
                    let done = (self.v[end_idx].range.end >= offset+len);
                    // We definitely need to include `end`, so move the index.
                    end_idx += 1;
                    debug_assert!(done || end_idx < self.v.len(), "iter_mut: end-offset {} is out-of-bounds", offset+len);
                    // see if we want to merge everything in `equal_since..end` (exclusive at the end!)
                    if done || self.v[end_idx].data != self.v[equal_since_idx].data {
                        // Everything in `equal_since..end` was equal.  Make them just one element covering
                        // the entire range.
                        let equal_elems = end_idx - equal_since_idx; // number of equal elements
                        if equal_elems > 1 {
                            // Adjust the range of the first element to cover all of them.
                            let equal_until = self.v[end_idx - 1].range.end; // end of range of last of the equal elements
                            self.v[equal_since_idx].range.end = equal_until;
                            // Delete the rest of them.
                            self.v.splice(equal_since_idx+1..end_idx, std::iter::empty());
                            // Adjust `end_idx` because we made the list shorter.
                            end_idx -= (equal_elems - 1);
                        }
                        // Go on scanning.
                        equal_since_idx = end_idx;
                    }
                    // Leave loop if this is the last element.
                    if done {
                        break;
                    }
                }
                let end_idx = end_idx-1; // Move to last included instead of first excluded index.
                // We need to split the end as well.  Even if this performs a
                // split, we don't have to adjust our index as we only care about
                // the first part of the split.
                self.split_index(end_idx, offset+len);
                // Now we yield the slice. `end` is inclusive.
                &mut self.v[first_idx..=end_idx]
            };
        slice.iter_mut().map(|elem| &mut elem.data)
    }
}

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

    /// Query the map at every offset in the range and collect the results.
    fn to_vec<T: Copy>(map: &RangeMap<T>, offset: u64, len: u64) -> Vec<T> {
        (offset..offset + len)
            .into_iter()
            .map(|i| map
                .iter(Size::from_bytes(i), Size::from_bytes(1))
                .next()
                .map(|&t| t)
                .unwrap()
            )
            .collect()
    }

    #[test]
    fn basic_insert() {
        let mut map = RangeMap::<i32>::new(Size::from_bytes(20), -1);
        // Insert
        for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(1)) {
            *x = 42;
        }
        // Check
        assert_eq!(to_vec(&map, 10, 1), vec![42]);
        assert_eq!(map.v.len(), 3);

        // Insert with size 0
        for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(0)) {
            *x = 19;
        }
        for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(0)) {
            *x = 19;
        }
        assert_eq!(to_vec(&map, 10, 2), vec![42, -1]);
        assert_eq!(map.v.len(), 3);
    }

    #[test]
    fn gaps() {
        let mut map = RangeMap::<i32>::new(Size::from_bytes(20), -1);
        for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(1)) {
            *x = 42;
        }
        for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(1)) {
            *x = 43;
        }
        assert_eq!(map.v.len(), 5);
        assert_eq!(
            to_vec(&map, 10, 10),
            vec![-1, 42, -1, -1, -1, 43, -1, -1, -1, -1]
        );

        for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(10)) {
            if *x < 42 {
                *x = 23;
            }
        }
        assert_eq!(map.v.len(), 6);
        assert_eq!(
            to_vec(&map, 10, 10),
            vec![23, 42, 23, 23, 23, 43, 23, 23, 23, 23]
        );
        assert_eq!(to_vec(&map, 13, 5), vec![23, 23, 43, 23, 23]);

        for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(5)) {
            *x = 19;
        }
        assert_eq!(map.v.len(), 6);
        assert_eq!(
            to_vec(&map, 10, 10),
            vec![23, 42, 23, 23, 23, 19, 19, 19, 19, 19]
        );
        // Should be seeing two blocks with 19
        assert_eq!(map.iter(Size::from_bytes(15), Size::from_bytes(2))
            .map(|&t| t).collect::<Vec<_>>(), vec![19, 19]);

        // a NOP iter_mut should trigger merging
        for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(5)) { }
        assert_eq!(map.v.len(), 5);
        assert_eq!(
            to_vec(&map, 10, 10),
            vec![23, 42, 23, 23, 23, 19, 19, 19, 19, 19]
        );
    }
}
<commit_msg>tweak merging to give up if we don't make any progress<commit_after>#![allow(unused)]

//! Implements a map from integer indices to data.
//! Rather than storing data for every index, internally, this maps entire ranges to the data.
//! To this end, the APIs all work on ranges, not on individual integers. Ranges are split as
//! necessary (e.g. when [0,5) is first associated with X, and then [1,2) is mutated).
//! Users must not depend on whether a range is coalesced or not, even though this is observable
//! via the iteration APIs.

use std::ops;
use std::num::NonZeroU64;

use rustc::ty::layout::Size;

#[derive(Clone, Debug)]
struct Elem<T> {
    range: ops::Range<u64>, // the range covered by this element, never empty
    data: T,
}
#[derive(Clone, Debug)]
pub struct RangeMap<T> {
    v: Vec<Elem<T>>,
}

impl<T> RangeMap<T> {
    /// Create a new RangeMap for the given size, and with the given initial value used for
    /// the entire range.
    #[inline(always)]
    pub fn new(size: Size, init: T) -> RangeMap<T> {
        let size = size.bytes();
        let mut map = RangeMap { v: Vec::new() };
        if size > 0 {
            map.v.push(Elem {
                range: 0..size,
                data: init
            });
        }
        map
    }

    /// Find the index containing the given offset.
    fn find_offset(&self, offset: u64) -> usize {
        // We do a binary search
        let mut left = 0usize; // inclusive
        let mut right = self.v.len(); // exclusive
        loop {
            debug_assert!(left < right, "find_offset: offset {} is out-of-bounds", offset);
            let candidate = left.checked_add(right).unwrap() / 2;
            let elem = &self.v[candidate];
            if offset < elem.range.start {
                // we are too far right (offset is further left)
                debug_assert!(candidate < right); // we are making progress
                right = candidate;
            } else if offset >= elem.range.end {
                // we are too far left (offset is further right)
                debug_assert!(candidate >= left); // we are making progress
                left = candidate+1;
            } else {
                // This is it!
                return candidate;
            }
        }
    }

    /// Provide read-only iteration over everything in the given range.  This does
    /// *not* split items if they overlap with the edges.  Do not use this to mutate
    /// through interior mutability.
    pub fn iter<'a>(&'a self, offset: Size, len: Size) -> impl Iterator<Item = &'a T> + 'a {
        let offset = offset.bytes();
        let len = len.bytes();
        // Compute a slice starting with the elements we care about
        let slice: &[Elem<T>] = if len == 0 {
                // We just need any empty iterator.  We don't even want to
                // yield the element that surrounds this position.
                &[]
            } else {
                let first_idx = self.find_offset(offset);
                &self.v[first_idx..]
            };
        let end = offset + len; // the first offset that is not included any more
        slice.iter()
            .take_while(move |elem| elem.range.start < end)
            .map(|elem| &elem.data)
    }

    pub fn iter_mut_all<'a>(&'a mut self) -> impl Iterator<Item = &'a mut T> + 'a {
        self.v.iter_mut().map(|elem| &mut elem.data)
    }

    // Split the element situated at the given `index`, such that the 2nd one starts at offset `split_offset`.
    // Do nothing if the element already starts there.
    // Return whether a split was necessary.
    fn split_index(&mut self, index: usize, split_offset: u64) -> bool
    where
        T: Clone,
    {
        let elem = &mut self.v[index];
        if split_offset == elem.range.start || split_offset == elem.range.end {
            // Nothing to do
            return false;
        }
        debug_assert!(elem.range.contains(&split_offset),
            "The split_offset is not in the element to be split");

        // Now we really have to split.  Reduce length of first element.
        let second_range = split_offset..elem.range.end;
        elem.range.end = split_offset;
        // Copy the data, and insert 2nd element
        let second = Elem {
            range: second_range,
            data: elem.data.clone(),
        };
        self.v.insert(index+1, second);
        return true;
    }

    /// Provide mutable iteration over everything in the given range.  As a side-effect,
    /// this will split entries in the map that are only partially hit by the given range,
    /// to make sure that when they are mutated, the effect is constrained to the given range.
    pub fn iter_mut<'a>(
        &'a mut self,
        offset: Size,
        len: Size,
    ) -> impl Iterator<Item = &'a mut T> + 'a
    where
        T: Clone + PartialEq,
    {
        let offset = offset.bytes();
        let len = len.bytes();
        // Compute a slice containing exactly the elements we care about
        let slice: &mut [Elem<T>] = if len == 0 {
                // We just need any empty iterator.  We don't even want to
                // yield the element that surrounds this position, nor do
                // any splitting.
                &mut []
            } else {
                // Make sure we got a clear beginning
                let mut first_idx = self.find_offset(offset);
                if self.split_index(first_idx, offset) {
                    // The newly created 2nd element is ours
                    first_idx += 1;
                }
                let first_idx = first_idx; // no more mutation
                // Find our end.  Linear scan, but that's okay because the iteration
                // is doing the same linear scan anyway -- no increase in complexity.
                // We combine this scan with a scan for duplicates that we can merge, to reduce
                // the number of elements.
                // We stop searching after the first "block" of size 1, to avoid spending excessive
                // amounts of time on the merging.
                let mut equal_since_idx = first_idx;
                // Once we see too many non-mergeable blocks, we stop.
                // The initial value is chosen via... magic.  Benchmarking and magic.
                let mut successful_merge_count = 3usize;
                let mut end_idx = first_idx; // when the loop is done, this is the first excluded element.
                loop {
                    // Compute if `end` is the last element we need to look at.
                    let done = (self.v[end_idx].range.end >= offset+len);
                    // We definitely need to include `end`, so move the index.
                    end_idx += 1;
                    debug_assert!(done || end_idx < self.v.len(), "iter_mut: end-offset {} is out-of-bounds", offset+len);
                    // see if we want to merge everything in `equal_since..end` (exclusive at the end!)
                    if successful_merge_count > 0 {
                        if done || self.v[end_idx].data != self.v[equal_since_idx].data {
                            // Everything in `equal_since..end` was equal.  Make them just one element covering
                            // the entire range.
                            let removed_elems = end_idx - equal_since_idx - 1; // number of elements that we would remove
                            if removed_elems > 0 {
                                // Adjust the range of the first element to cover all of them.
                                let equal_until = self.v[end_idx - 1].range.end; // end of range of last of the equal elements
                                self.v[equal_since_idx].range.end = equal_until;
                                // Delete the rest of them.
                                self.v.splice(equal_since_idx+1..end_idx, std::iter::empty());
                                // Adjust `end_idx` because we made the list shorter.
                                end_idx -= removed_elems;
                                // adjust the count for the cutoff
                                successful_merge_count += removed_elems;
                            } else {
                                // adjust the count for the cutoff
                                successful_merge_count -= 1;
                            }
                            // Go on scanning for the next block starting here.
                            equal_since_idx = end_idx;
                        }
                    }
                    // Leave loop if this is the last element.
                    if done {
                        break;
                    }
                }
                let end_idx = end_idx-1; // Move to last included instead of first excluded index.
                // We need to split the end as well.  Even if this performs a
                // split, we don't have to adjust our index as we only care about
                // the first part of the split.
                self.split_index(end_idx, offset+len);
                // Now we yield the slice. `end` is inclusive.
                &mut self.v[first_idx..=end_idx]
            };
        slice.iter_mut().map(|elem| &mut elem.data)
    }
}

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

    /// Query the map at every offset in the range and collect the results.
    fn to_vec<T: Copy>(map: &RangeMap<T>, offset: u64, len: u64) -> Vec<T> {
        (offset..offset + len)
            .into_iter()
            .map(|i| map
                .iter(Size::from_bytes(i), Size::from_bytes(1))
                .next()
                .map(|&t| t)
                .unwrap()
            )
            .collect()
    }

    #[test]
    fn basic_insert() {
        let mut map = RangeMap::<i32>::new(Size::from_bytes(20), -1);
        // Insert
        for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(1)) {
            *x = 42;
        }
        // Check
        assert_eq!(to_vec(&map, 10, 1), vec![42]);
        assert_eq!(map.v.len(), 3);

        // Insert with size 0
        for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(0)) {
            *x = 19;
        }
        for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(0)) {
            *x = 19;
        }
        assert_eq!(to_vec(&map, 10, 2), vec![42, -1]);
        assert_eq!(map.v.len(), 3);
    }

    #[test]
    fn gaps() {
        let mut map = RangeMap::<i32>::new(Size::from_bytes(20), -1);
        for x in map.iter_mut(Size::from_bytes(11), Size::from_bytes(1)) {
            *x = 42;
        }
        for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(1)) {
            *x = 43;
        }
        assert_eq!(map.v.len(), 5);
        assert_eq!(
            to_vec(&map, 10, 10),
            vec![-1, 42, -1, -1, -1, 43, -1, -1, -1, -1]
        );

        for x in map.iter_mut(Size::from_bytes(10), Size::from_bytes(10)) {
            if *x < 42 {
                *x = 23;
            }
        }
        assert_eq!(map.v.len(), 6);
        assert_eq!(
            to_vec(&map, 10, 10),
            vec![23, 42, 23, 23, 23, 43, 23, 23, 23, 23]
        );
        assert_eq!(to_vec(&map, 13, 5), vec![23, 23, 43, 23, 23]);

        for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(5)) {
            *x = 19;
        }
        assert_eq!(map.v.len(), 6);
        assert_eq!(
            to_vec(&map, 10, 10),
            vec![23, 42, 23, 23, 23, 19, 19, 19, 19, 19]
        );
        // Should be seeing two blocks with 19
        assert_eq!(map.iter(Size::from_bytes(15), Size::from_bytes(2))
            .map(|&t| t).collect::<Vec<_>>(), vec![19, 19]);

        // a NOP iter_mut should trigger merging
        for x in map.iter_mut(Size::from_bytes(15), Size::from_bytes(5)) { }
        assert_eq!(map.v.len(), 5);
        assert_eq!(
            to_vec(&map, 10, 10),
            vec![23, 42, 23, 23, 23, 19, 19, 19, 19, 19]
        );
    }
}
<|endoftext|>


<commit_before>
use parsers::*;
use regex::{Captures, Regex};
use std::fmt::Show;

#[deriving(Show)]
#[deriving(Clone)]
#[deriving(PartialEq)]
pub enum AddOp {
  Add,
  Subtract,
}

#[deriving(Show)]
#[deriving(Clone)]
#[deriving(PartialEq)]
pub enum MultOp {
  Multiply,
  Divide,
}

#[deriving(Clone)]
#[deriving(Show)]
#[deriving(PartialEq)]
pub struct AddTerm(pub AddOp, pub Expr);

#[deriving(Clone)]
#[deriving(Show)]
#[deriving(PartialEq)]
pub struct MultTerm(pub MultOp, pub Expr);

#[deriving(Show)]
#[deriving(Clone)]
#[deriving(PartialEq)]
pub enum Expr {
  Variable(String),
  Num(int),
  AddSub(Vec<AddTerm>), //a + b - c + d becomes [(+ a) (+ b) (- c) (+ d)]
  MultDiv(Vec<MultTerm>),
}

#[deriving(Show)]
#[deriving(Clone)]
#[deriving(PartialEq)]
pub enum Statement {
  Assign(String, Expr),
  Output(Expr),
}

#[deriving(Show)]
#[deriving(Eq)]
#[deriving(PartialEq)]
#[deriving(Clone)]
pub enum Token {
  Equals,
  Ident(String),
  Number(int),
  PlusSign,
  MinusSign,
  MultSign,
  DivideSign,
  OutputCmd,
  NewLine,
  OpenParen,
  CloseParen,
}

//coercion fn needed for unboxed closures
//without this all kinds of weird errors show up
fn p<'a, I, O>(l: Box<Parser<'a, I, O> + 'a>) -> Box<Parser<'a, I, O> + 'a> {
  l
}

pub macro_rules! or {
  ($a: expr, $b: expr) => {
    p(box OrParser{
      a: box |&:| $a ,
      b: box |&:| $b ,
    })
 };
  ($a: expr, $b: expr $(, $c: expr)* ) => {
    p(box OrParser{
      a: box |&:| $a,
      b: box |&:| or!($b, $($c),*),
    })
  };
}
pub macro_rules! seq {
  ($a: expr, $b: expr ) => {
    box DualParser{
      first: $a,
      second: $b,
    }
 };
  ($a: expr, $b: expr $(, $c: expr)* ) => {
    box DualParser{
      first: $a,
      second: seq!($b, $($c),* ),
    }
  };
}

pub macro_rules! map {
  ($a: expr, $b: expr) => {
    box MapParser{
      parser: $a,
      mapper: box $b
    }
  }
}

pub macro_rules! link {
  ($a: expr, $b: expr) => {
    box DualParser{
      first: $a,
      second: $b,
    }
  }
}

pub macro_rules! repsep {
  ($rep: expr, $sep: expr, $min: expr) => {
    box RepSepParser{
      rep: $rep,
      sep: $sep,
      min_reps: $min,
    }
  }
}

pub macro_rules! rep {
  ($rep: expr) => {
    box RepParser{
      parser: $rep,
    }
  }
}

type Lexer<'a> = Box<Parser<'a, &'a str, Token> + 'a>;

pub fn token<'a>() -> Box<Parser<'a, &'a str, Vec<Token>> + 'a> {

  macro_rules! literal {
    ($reg: expr, $tok: expr) => {
      p(map!(
        box RegexLiteralParser{regex : Regex::new($reg).unwrap()},
        |&: ()| $tok
      ))
    }
  }

  //changing these to values creates weird conflicting lifetime errors
  fn ident<'a>() -> Lexer<'a> { map!(
    box RegexCapturesParser{regex : Regex::new(r"^[ \t]*([a-z]+)[ \t]*").unwrap()},
    |&: caps: Captures<'a>| Ident(from_str(caps.at(1)).unwrap())
  )}

  fn number<'a>() -> Lexer<'a> { map!(
    box RegexCapturesParser{regex : Regex::new(r"^[ \t]*(\d+)[ \t]*").unwrap()},
    |&: caps: Captures<'a>| Number(from_str(caps.at(1)).unwrap())
  )}

  rep!(or!(
    literal!(r"^[ \t]*out", OutputCmd),
    literal!(r"^[ \t]*\r?\n\s*", NewLine),
    literal!(r"^[ \t]*\(", OpenParen),
    literal!(r"^[ \t]*\)", CloseParen),
    literal!(r"^[ \t]*\+", PlusSign),
    literal!(r"^[ \t]*-", MinusSign),
    literal!(r"^[ \t]*=", Equals),
    literal!(r"^[ \t]*\*", MultSign),
    literal!(r"^[ \t]*/", DivideSign),
    number(),
    ident()
  ))

}

pub type LParser<'a, T> = Box<Parser<'a, &'a [Token], T> + 'a>;

fn assign<'a>() -> LParser<'a, Statement> {
  map!(
    seq!(variable(), literal(Equals), expr()),
    |&: (var,( _, expr))| match var{
      Variable(name) => Assign(name, expr),
      _ => unreachable!()
    }
  )
}

fn output<'a>() -> LParser<'a, Statement> {
  map!(
    seq!(literal(OutputCmd), expr()),
    |&: (_, var): (Token, Expr)| Output(var)
  )
}

pub fn statement<'a>() -> LParser<'a, Vec<Statement>> {
  rep!(
    map!(
      seq!(
        or!(output(), assign()),
        literal(NewLine)
      ),
      |&: (stmt, _)| stmt
    )
  )
}

fn variable<'a>() -> LParser<'a, Expr> {
  box MatchParser{
    matcher: box |&: input: &Token| match input {
      &Ident(ref str) => Ok(Variable(str.clone())),
      other => Err(format!("Expected variable, got {}", other))
    }
  }
}

type EParser<'a> = LParser<'a, Expr>;

fn expr<'a>() -> EParser<'a> {

  fn number<'a>() -> EParser<'a> {
    box MatchParser{matcher: box |&: input: &Token| -> Result<Expr, String> match input {
      &Number(num) => Ok(Num(num)),
      other => Err(format!("wrong type, expected number, got {}", other))
    }}
  }

  fn term<'a>() -> EParser<'a> {
    or!(paren_expr(), variable(), number())
  }

  fn mult<'a>() -> EParser<'a> {
    map!(
      seq!(
        term(),
        rep!(seq!(or!(literal(MultSign), literal(DivideSign)), term()))
      ),
      |&: (first, rest): (Expr, Vec<(Token, Expr)>)| {
        let mut f = Vec::new();
        f.push(MultTerm(Multiply, first));
        for &(ref sign, ref value) in rest.iter() {
          let s = match *sign {
            MultSign => Multiply,
            DivideSign => Divide,
            _ => panic!("not allowed")
          };
          f.push(MultTerm(s, value.clone())); //maybe box the value instead
        }
        MultDiv(f)
      }
    )
  }

  fn simple_expr<'a>() -> EParser<'a> {
    or!(mult(), term())
  }

  fn plus<'a>() -> EParser<'a> {
    map!(
      seq!(
        simple_expr(),
        rep!(seq!(or!(literal(PlusSign), literal(MinusSign)), simple_expr()))
      ),
      |&: (first, rest): (Expr, Vec<(Token, Expr)>)| {
        let mut f = Vec::new();
        f.push(AddTerm(Add, first));
        for &(ref sign, ref value) in rest.iter() {
          let s = match *sign {
            PlusSign => Add,
            MinusSign => Subtract,
            _ => panic!("not allowed")
          };
          f.push(AddTerm(s, value.clone()));
        }
        AddSub(f)
      }
    )
  }

  fn paren_expr<'a>() -> EParser<'a> {
    map!(
      seq!(literal(OpenParen), expr(), literal(CloseParen)),
      |&: (_, (expr, _))| expr
    )
  }

  plus()
}

macro_rules! assert_pat {
  ($actual: expr, $expected: pat) => {
    match $actual{
      $expected => {}
      other => panic!(format!("Assert match failed: got '{}'", other))
    }
  }
}

fn test_parser<'a, I, O: PartialEq + Show>(input: I, parser: &Parser<'a, I, O>, expected: O) {
  match parser.parse(input) {
    Ok((output, rest)) => {
      assert_eq!(output, expected);
    },
    Err(err) => panic!(err)
  }
}

#[test]
fn test_term() {
  let parser = expr();
  let input = [Number(5)];
  let expected = AddSub(vec![AddTerm(Add, Num(5))]);
  test_parser(input.as_slice(), &*parser, expected);
}

#[test]
fn test_plus_sequence() {
  let parser = expr();
  let input = [Number(5), PlusSign, Number(3)];
  let expected = AddSub(vec![AddTerm(Add, Num(5)), AddTerm(Add, Num(3))]);
  test_parser(input.as_slice(), &*parser, expected);
}

#[test]
fn test_simple_assign() {
  let parser = assign();
  let input = [Ident(from_str("x").unwrap()), Equals, Number(7)];
  let expected = Assign(from_str("x").unwrap(), AddSub(vec![AddTerm(Add, Num(7))]));
  test_parser(input.as_slice(), &*parser, expected);
}

#[test]
fn test_simple_output() {
  let parser = output();
  let input = [OutputCmd, Number(4)];
  let expected = Output(AddSub(vec![AddTerm(Add, Num(4))]));
  test_parser(input.as_slice(), &*parser, expected);
}

<commit_msg>plus/mult sequences of 1 are reduced to just the expression<commit_after>
use parsers::*;
use regex::{Captures, Regex};
use std::fmt::Show;

#[deriving(Show)]
#[deriving(Clone)]
#[deriving(PartialEq)]
pub enum AddOp {
  Add,
  Subtract,
}

#[deriving(Show)]
#[deriving(Clone)]
#[deriving(PartialEq)]
pub enum MultOp {
  Multiply,
  Divide,
}

#[deriving(Clone)]
#[deriving(Show)]
#[deriving(PartialEq)]
pub struct AddTerm(pub AddOp, pub Expr);

#[deriving(Clone)]
#[deriving(Show)]
#[deriving(PartialEq)]
pub struct MultTerm(pub MultOp, pub Expr);

#[deriving(Show)]
#[deriving(Clone)]
#[deriving(PartialEq)]
pub enum Expr {
  Variable(String),
  Num(int),
  AddSub(Vec<AddTerm>), //a + b - c + d becomes [(+ a) (+ b) (- c) (+ d)]
  MultDiv(Vec<MultTerm>),
}

#[deriving(Show)]
#[deriving(Clone)]
#[deriving(PartialEq)]
pub enum Statement {
  Assign(String, Expr),
  Output(Expr),
}

#[deriving(Show)]
#[deriving(Eq)]
#[deriving(PartialEq)]
#[deriving(Clone)]
pub enum Token {
  Equals,
  Ident(String),
  Number(int),
  PlusSign,
  MinusSign,
  MultSign,
  DivideSign,
  OutputCmd,
  NewLine,
  OpenParen,
  CloseParen,
}

//coercion fn needed for unboxed closures
//without this all kinds of weird errors show up
fn p<'a, I, O>(l: Box<Parser<'a, I, O> + 'a>) -> Box<Parser<'a, I, O> + 'a> {
  l
}

pub macro_rules! or {
  ($a: expr, $b: expr) => {
    p(box OrParser{
      a: box |&:| $a ,
      b: box |&:| $b ,
    })
 };
  ($a: expr, $b: expr $(, $c: expr)* ) => {
    p(box OrParser{
      a: box |&:| $a,
      b: box |&:| or!($b, $($c),*),
    })
  };
}
pub macro_rules! seq {
  ($a: expr, $b: expr ) => {
    box DualParser{
      first: $a,
      second: $b,
    }
 };
  ($a: expr, $b: expr $(, $c: expr)* ) => {
    box DualParser{
      first: $a,
      second: seq!($b, $($c),* ),
    }
  };
}

pub macro_rules! map {
  ($a: expr, $b: expr) => {
    box MapParser{
      parser: $a,
      mapper: box $b
    }
  }
}

pub macro_rules! repsep {
  ($rep: expr, $sep: expr, $min: expr) => {
    box RepSepParser{
      rep: $rep,
      sep: $sep,
      min_reps: $min,
    }
  }
}

pub macro_rules! rep {
  ($rep: expr) => {
    box RepParser{
      parser: $rep,
    }
  }
}

type Lexer<'a> = Box<Parser<'a, &'a str, Token> + 'a>;

pub fn token<'a>() -> Box<Parser<'a, &'a str, Vec<Token>> + 'a> {

  macro_rules! literal {
    ($reg: expr, $tok: expr) => {
      p(map!(
        box RegexLiteralParser{regex : Regex::new($reg).unwrap()},
        |&: ()| $tok
      ))
    }
  }

  //changing these to values creates weird conflicting lifetime errors
  fn ident<'a>() -> Lexer<'a> { map!(
    box RegexCapturesParser{regex : Regex::new(r"^[ \t]*([a-z]+)[ \t]*").unwrap()},
    |&: caps: Captures<'a>| Ident(from_str(caps.at(1)).unwrap())
  )}

  fn number<'a>() -> Lexer<'a> { map!(
    box RegexCapturesParser{regex : Regex::new(r"^[ \t]*(\d+)[ \t]*").unwrap()},
    |&: caps: Captures<'a>| Number(from_str(caps.at(1)).unwrap())
  )}

  rep!(or!(
    literal!(r"^[ \t]*out", OutputCmd),
    literal!(r"^[ \t]*\r?\n\s*", NewLine),
    literal!(r"^[ \t]*\(", OpenParen),
    literal!(r"^[ \t]*\)", CloseParen),
    literal!(r"^[ \t]*\+", PlusSign),
    literal!(r"^[ \t]*-", MinusSign),
    literal!(r"^[ \t]*=", Equals),
    literal!(r"^[ \t]*\*", MultSign),
    literal!(r"^[ \t]*/", DivideSign),
    number(),
    ident()
  ))

}

pub type LParser<'a, T> = Box<Parser<'a, &'a [Token], T> + 'a>;

fn assign<'a>() -> LParser<'a, Statement> {
  map!(
    seq!(variable(), literal(Equals), expr()),
    |&: (var,( _, expr))| match var{
      Variable(name) => Assign(name, expr),
      _ => unreachable!()
    }
  )
}

fn output<'a>() -> LParser<'a, Statement> {
  map!(
    seq!(literal(OutputCmd), expr()),
    |&: (_, var): (Token, Expr)| Output(var)
  )
}

pub fn statement<'a>() -> LParser<'a, Vec<Statement>> {
  rep!(
    map!(
      seq!(
        or!(output(), assign()),
        literal(NewLine)
      ),
      |&: (stmt, _)| stmt
    )
  )
}

fn variable<'a>() -> LParser<'a, Expr> {
  box MatchParser{
    matcher: box |&: input: &Token| match input {
      &Ident(ref str) => Ok(Variable(str.clone())),
      other => Err(format!("Expected variable, got {}", other))
    }
  }
}

type EParser<'a> = LParser<'a, Expr>;

fn expr<'a>() -> EParser<'a> {

  fn number<'a>() -> EParser<'a> {
    box MatchParser{matcher: box |&: input: &Token| -> Result<Expr, String> match *input {
      Number(num) => Ok(Num(num)),
      ref other => Err(format!("wrong type, expected number, got {}", other))
    }}
  }

  fn term<'a>() -> EParser<'a> {
    or!(paren_expr(), variable(), number())
  }

  fn mult<'a>() -> EParser<'a> {
    map!(
      seq!(
        term(),
        rep!(seq!(or!(literal(MultSign), literal(DivideSign)), term()))
      ),
      |&: (first, rest): (Expr, Vec<(Token, Expr)>)| {
        if (rest.len() == 0) {
          first
        } else {
          let mut f = Vec::new();
          f.push(MultTerm(Multiply, first));
          for &(ref sign, ref value) in rest.iter() {
            let s = match *sign {
              MultSign => Multiply,
              DivideSign => Divide,
              _ => panic!("not allowed")
            };
            f.push(MultTerm(s, value.clone())); //maybe box the value instead
          }
          MultDiv(f)
        }
      }
    )
  }

  fn simple_expr<'a>() -> EParser<'a> {
    or!(mult(), term())
  }

  fn plus<'a>() -> EParser<'a> {
    map!(
      seq!(
        simple_expr(),
        rep!(seq!(or!(literal(PlusSign), literal(MinusSign)), simple_expr()))
      ),
      |&: (first, rest): (Expr, Vec<(Token, Expr)>)| {
        if (rest.len() == 0) {
          first
        } else {
          let mut f = Vec::new();
          f.push(AddTerm(Add, first));
          for &(ref sign, ref value) in rest.iter() {
            let s = match *sign {
              PlusSign => Add,
              MinusSign => Subtract,
              _ => panic!("not allowed")
            };
            f.push(AddTerm(s, value.clone()));
          }
          AddSub(f)
        }
      }
    )
  }

  fn paren_expr<'a>() -> EParser<'a> {
    map!(
      seq!(literal(OpenParen), expr(), literal(CloseParen)),
      |&: (_, (expr, _))| expr
    )
  }

  plus()
}

macro_rules! assert_pat {
  ($actual: expr, $expected: pat) => {
    match $actual{
      $expected => {}
      other => panic!(format!("Assert match failed: got '{}'", other))
    }
  }
}

fn test_parser<'a, I, O: PartialEq + Show>(input: I, parser: &Parser<'a, I, O>, expected: O) {
  match parser.parse(input) {
    Ok((output, rest)) => {
      assert_eq!(output, expected);
    },
    Err(err) => panic!(err)
  }
}

#[test]
fn test_term() {
  let parser = expr();
  let input = [Number(5)];
  let expected = Num(5);
  test_parser(input.as_slice(), &*parser, expected);
}

#[test]
fn test_plus_sequence() {
  let parser = expr();
  let input = [Number(5), PlusSign, Number(3)];
  let expected = AddSub(vec![AddTerm(Add, Num(5)), AddTerm(Add, Num(3))]);
  test_parser(input.as_slice(), &*parser, expected);
}

#[test]
fn test_plus_mult_sequence() {
  let parser = expr();
  let input = [Number(3), PlusSign, Number(4), MultSign, Number(5)];
  let expected = AddSub(vec![AddTerm(Add, Num(3)), AddTerm(Add, MultDiv(vec![MultTerm(Multiply, Num(4)), MultTerm(Multiply, Num(5))]))]);
  test_parser(input.as_slice(), &*parser, expected);
}

#[test]
fn test_simple_assign() {
  let parser = assign();
  let input = [Ident(from_str("x").unwrap()), Equals, Number(7)];
  let expected = Assign(from_str("x").unwrap(), Num(7));
  test_parser(input.as_slice(), &*parser, expected);
}

#[test]
fn test_simple_output() {
  let parser = output();
  let input = [OutputCmd, Number(4)];
  let expected = Output(Num(4));
  test_parser(input.as_slice(), &*parser, expected);
}

<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use bootstrap::{Action, EventHandler, EventSig, MouseButton};
use color::ColorAlpha;
use overlay::{Disc, Quad, Renderer, RenderInput, Text, Texture2D, Triangle, Vert};
use scene::Scene;

type Time = f32;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Viewport {
  pub x: f32,
  pub y: f32,
  pub w: f32,
  pub h: f32
}

pub struct GUI<'a> {
  // common
  renderer: Renderer,

  widgets: HashMap<String, Box<Widget<'a> + 'a>>,

  // event stuff
  last_cursor: Option<[f64; 2]>,
  last_mouse_left_down: Option<[f64; 2]>,
  last_mouse_left_up: Option<[f64; 2]>,
  focused_widgets: HashMap<Focus, String>
}

impl<'a> GUI<'a> {
  pub fn new(viewport: Viewport, scene: &mut Scene) -> Self {
    GUI {
      renderer: Renderer::new(viewport.w.ceil() as u32, viewport.h.ceil() as u32, 1024, 1024, 1024, scene),
      widgets: HashMap::new(),
      last_cursor: None,
      last_mouse_left_down: None,
      last_mouse_left_up: None,
      focused_widgets: HashMap::new(),
    }
  }

  pub fn add_widget<W>(&mut self, id: &str, widget: &W) where W: 'a + Clone + Widget<'a> {
    self.widgets.insert(id.to_owned(), Box::new(widget.clone()));
  }

  pub fn remove_widget(&mut self, id: &str) {
    self.widgets.remove(id);
  }

  pub fn render(&self) -> &Texture2D {
    let mut tris = Vec::new();
    let mut quads = Vec::new();
    let mut discs = Vec::new();
    let mut texts = Vec::new();

    for widget in self.widgets.values() {
      for prim in widget.unwidget() {
        match prim {
          WidgetPrim::Triangle(ref tri) => tris.push(*tri),
          WidgetPrim::Quad(ref quad) => quads.push(*quad),
          WidgetPrim::Disc(ref disc) => discs.push(*disc),
          WidgetPrim::Text(ref text) => texts.push(*text)
        }
      }
    }

    let render_input = RenderInput::new()
      .triangles(&tris)
      .quads(&quads)
      .discs(&discs)
      .texts(&texts, 1.);

    self.renderer.render(render_input)
  }
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
enum Focus {
  MouseButton(MouseButton, Action),
  Drag
}

impl<'a> EventHandler for GUI<'a> {
  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> EventSig {
    if let MouseButton::Button1 = button {
      let last_cursor = self.last_cursor.unwrap();

      match action {
        Action::Press => {
          self.last_mouse_left_down = Some(last_cursor);
          self.last_mouse_left_up = None;

          for (key, widget) in &mut self.widgets {
            if widget.on_mouse_button(button, action) == EventSig::Focused {
              self.focused_widgets.insert(Focus::MouseButton(button, action), key.clone());
              break;
            }
          }
        },
        Action::Release => {
          // check whether it’s a click
          if px_dist(self.last_mouse_left_down.unwrap(), last_cursor) <= 5. {
            // it’s a click
            for widget in self.widgets.values() {
              widget.on_click(last_cursor);
            }
          }

          self.last_mouse_left_down = None;
          self.last_mouse_left_up = Some(last_cursor);

          self.focused_widgets.remove(&Focus::MouseButton(button, Action::Press));
          self.focused_widgets.remove(&Focus::Drag);
        },
        _ => ()
      }
    }

    EventSig::Handled
  }

  // TODO: change the implementation to take into account widget focus
  fn on_cursor_move(&mut self, cursor: [f64; 2]) -> EventSig {
    self.last_cursor = Some(cursor);

    if let Some(key) = self.focused_widgets.get(&Focus::Drag).cloned() {
      let focused = self.widgets.get(&key).unwrap();
      let down_cursor = self.last_mouse_left_down.unwrap();
      focused.on_drag(cursor, down_cursor);
    } else if let Some(key) = self.focused_widgets.get(&Focus::MouseButton(MouseButton::Button1, Action::Press)).cloned() {
      let focused = self.widgets.get(&key).unwrap();
      let down_cursor = self.last_mouse_left_down.unwrap();

      if px_dist(down_cursor, cursor) > 5. {
        self.focused_widgets.insert(Focus::Drag, key);
        focused.on_drag(cursor, down_cursor);
      }
    }

    EventSig::Handled
  }
}

/// Widget primitives.
///
/// A widget primitive is used as primary a tool to build up widgets. A widget is basically just a
/// sum of widget primitives used to represent it.
pub enum WidgetPrim<'a> {
  Triangle(Triangle),
  Quad(Quad),
  Disc(Disc),
  Text(Text<'a>)
}

pub trait Widget<'a>: EventHandler {
  fn unwidget(&self) -> Vec<WidgetPrim<'a>>;
  fn on_click(&self, _: [f64; 2]) {}
  fn on_drag(&self, _: [f64; 2], _: [f64; 2]) {}
}

pub struct ProgressBar {
  w: f32,
  progress_quad: Quad,
  inactive_quad: Quad,
  recip_dur_sec: f32,
  listeners: HashMap<String, Rc<RefCell<ProgressBarListener>>>
}

pub trait ProgressBarListener {
  fn on_set(&mut self, t: Time) -> bool;
}

impl ProgressBar {
  pub fn new(w: f32, h: f32, progress_color: ColorAlpha, inactive_color: ColorAlpha, dur_sec: f32) -> Rc<RefCell<Self>> {
    let pcol = *progress_color.as_ref();
    let icol = *inactive_color.as_ref();

    let progress_quad = Quad(
      Vert::new([0., 0., 0.], pcol),
      Vert::new([0., h, 0.], pcol),
      Vert::new([0., 0., 0.], pcol),
      Vert::new([0., h, 0.], pcol)
    );

    let inactive_quad = Quad(
      Vert::new([w, 0., 0.], icol),
      Vert::new([w, h, 0.], icol),
      Vert::new([0., 0., 0.], icol),
      Vert::new([0., h, 0.], icol)
    );

    Rc::new(RefCell::new(ProgressBar {
      w: w,
      progress_quad: progress_quad,
      inactive_quad: inactive_quad,
      recip_dur_sec: 1. / dur_sec,
      listeners: HashMap::new()
    }))
  }

  /// Add a listener.
  pub fn add_listener(&mut self, key: &str, listener: &Rc<RefCell<ProgressBarListener>>) {
    self.listeners.insert(key.to_owned(), listener.clone());
  }

  /// Remove a listener.
  pub fn remove_listener(&mut self, key: &str) {
    self.listeners.remove(key);
  }

  /// Set the cursor (seconds).
  pub fn set(&mut self, cursor: f32) {
    let c = cursor * self.recip_dur_sec * self.w;

    // update the quads
    self.progress_quad.0.pos[0] = c;
    self.progress_quad.1.pos[0] = c;
    self.inactive_quad.2.pos[0] = c;
    self.inactive_quad.3.pos[0] = c;

    for l in self.listeners.values() {
      l.borrow_mut().on_set(cursor);
    }
  }

  pub fn on_cursor_change(&mut self, cursor: [f64; 2]) {
    let c = cursor[0] as f32;

    // update the quads
    self.progress_quad.0.pos[0] = c;
    self.progress_quad.1.pos[0] = c;
    self.inactive_quad.2.pos[0] = c;
    self.inactive_quad.3.pos[0] = c;

    for l in self.listeners.values() {
      l.borrow_mut().on_set(c / (self.recip_dur_sec * self.w));
    }
  }
}

impl EventHandler for Rc<RefCell<ProgressBar>> {
  fn on_mouse_button(&mut self, _: MouseButton, action: Action) -> EventSig {
    if action == Action::Press {
      EventSig::Focused
    } else {
      EventSig::Ignored
    }
  }
}

impl<'a> Widget<'a> for Rc<RefCell<ProgressBar>> {
  fn unwidget(&self) -> Vec<WidgetPrim<'a>> {
    let bar = &self.borrow();
    vec![WidgetPrim::Quad(bar.progress_quad), WidgetPrim::Quad(bar.inactive_quad)]
  }

  fn on_click(&self, cursor: [f64; 2]) {
    self.borrow_mut().on_cursor_change(cursor);
  }

  fn on_drag(&self, cursor: [f64; 2], down_cursor: [f64; 2]) {
    self.borrow_mut().on_cursor_change([cursor[0], down_cursor[1]]);
  }
}

/// Pixel distance between two points.
fn px_dist(a: [f64; 2], b: [f64; 2]) -> f64 {
  let x = b[0] - a[0];
  let y = b[1] - a[1];

  f64::sqrt(x*x + y*y)
}
<commit_msg>Removed pub.<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use bootstrap::{Action, EventHandler, EventSig, MouseButton};
use color::ColorAlpha;
use overlay::{Disc, Quad, Renderer, RenderInput, Text, Texture2D, Triangle, Vert};
use scene::Scene;

type Time = f32;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Viewport {
  pub x: f32,
  pub y: f32,
  pub w: f32,
  pub h: f32
}

pub struct GUI<'a> {
  // common
  renderer: Renderer,

  widgets: HashMap<String, Box<Widget<'a> + 'a>>,

  // event stuff
  last_cursor: Option<[f64; 2]>,
  last_mouse_left_down: Option<[f64; 2]>,
  last_mouse_left_up: Option<[f64; 2]>,
  focused_widgets: HashMap<Focus, String>
}

impl<'a> GUI<'a> {
  pub fn new(viewport: Viewport, scene: &mut Scene) -> Self {
    GUI {
      renderer: Renderer::new(viewport.w.ceil() as u32, viewport.h.ceil() as u32, 1024, 1024, 1024, scene),
      widgets: HashMap::new(),
      last_cursor: None,
      last_mouse_left_down: None,
      last_mouse_left_up: None,
      focused_widgets: HashMap::new(),
    }
  }

  pub fn add_widget<W>(&mut self, id: &str, widget: &W) where W: 'a + Clone + Widget<'a> {
    self.widgets.insert(id.to_owned(), Box::new(widget.clone()));
  }

  pub fn remove_widget(&mut self, id: &str) {
    self.widgets.remove(id);
  }

  pub fn render(&self) -> &Texture2D {
    let mut tris = Vec::new();
    let mut quads = Vec::new();
    let mut discs = Vec::new();
    let mut texts = Vec::new();

    for widget in self.widgets.values() {
      for prim in widget.unwidget() {
        match prim {
          WidgetPrim::Triangle(ref tri) => tris.push(*tri),
          WidgetPrim::Quad(ref quad) => quads.push(*quad),
          WidgetPrim::Disc(ref disc) => discs.push(*disc),
          WidgetPrim::Text(ref text) => texts.push(*text)
        }
      }
    }

    let render_input = RenderInput::new()
      .triangles(&tris)
      .quads(&quads)
      .discs(&discs)
      .texts(&texts, 1.);

    self.renderer.render(render_input)
  }
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
enum Focus {
  MouseButton(MouseButton, Action),
  Drag
}

impl<'a> EventHandler for GUI<'a> {
  fn on_mouse_button(&mut self, button: MouseButton, action: Action) -> EventSig {
    if let MouseButton::Button1 = button {
      let last_cursor = self.last_cursor.unwrap();

      match action {
        Action::Press => {
          self.last_mouse_left_down = Some(last_cursor);
          self.last_mouse_left_up = None;

          for (key, widget) in &mut self.widgets {
            if widget.on_mouse_button(button, action) == EventSig::Focused {
              self.focused_widgets.insert(Focus::MouseButton(button, action), key.clone());
              break;
            }
          }
        },
        Action::Release => {
          // check whether it’s a click
          if px_dist(self.last_mouse_left_down.unwrap(), last_cursor) <= 5. {
            // it’s a click
            for widget in self.widgets.values() {
              widget.on_click(last_cursor);
            }
          }

          self.last_mouse_left_down = None;
          self.last_mouse_left_up = Some(last_cursor);

          self.focused_widgets.remove(&Focus::MouseButton(button, Action::Press));
          self.focused_widgets.remove(&Focus::Drag);
        },
        _ => ()
      }
    }

    EventSig::Handled
  }

  // TODO: change the implementation to take into account widget focus
  fn on_cursor_move(&mut self, cursor: [f64; 2]) -> EventSig {
    self.last_cursor = Some(cursor);

    if let Some(key) = self.focused_widgets.get(&Focus::Drag).cloned() {
      let focused = self.widgets.get(&key).unwrap();
      let down_cursor = self.last_mouse_left_down.unwrap();
      focused.on_drag(cursor, down_cursor);
    } else if let Some(key) = self.focused_widgets.get(&Focus::MouseButton(MouseButton::Button1, Action::Press)).cloned() {
      let focused = self.widgets.get(&key).unwrap();
      let down_cursor = self.last_mouse_left_down.unwrap();

      if px_dist(down_cursor, cursor) > 5. {
        self.focused_widgets.insert(Focus::Drag, key);
        focused.on_drag(cursor, down_cursor);
      }
    }

    EventSig::Handled
  }
}

/// Widget primitives.
///
/// A widget primitive is used as primary a tool to build up widgets. A widget is basically just a
/// sum of widget primitives used to represent it.
pub enum WidgetPrim<'a> {
  Triangle(Triangle),
  Quad(Quad),
  Disc(Disc),
  Text(Text<'a>)
}

pub trait Widget<'a>: EventHandler {
  fn unwidget(&self) -> Vec<WidgetPrim<'a>>;
  fn on_click(&self, _: [f64; 2]) {}
  fn on_drag(&self, _: [f64; 2], _: [f64; 2]) {}
}

pub struct ProgressBar {
  w: f32,
  progress_quad: Quad,
  inactive_quad: Quad,
  recip_dur_sec: f32,
  listeners: HashMap<String, Rc<RefCell<ProgressBarListener>>>
}

pub trait ProgressBarListener {
  fn on_set(&mut self, t: Time) -> bool;
}

impl ProgressBar {
  pub fn new(w: f32, h: f32, progress_color: ColorAlpha, inactive_color: ColorAlpha, dur_sec: f32) -> Rc<RefCell<Self>> {
    let pcol = *progress_color.as_ref();
    let icol = *inactive_color.as_ref();

    let progress_quad = Quad(
      Vert::new([0., 0., 0.], pcol),
      Vert::new([0., h, 0.], pcol),
      Vert::new([0., 0., 0.], pcol),
      Vert::new([0., h, 0.], pcol)
    );

    let inactive_quad = Quad(
      Vert::new([w, 0., 0.], icol),
      Vert::new([w, h, 0.], icol),
      Vert::new([0., 0., 0.], icol),
      Vert::new([0., h, 0.], icol)
    );

    Rc::new(RefCell::new(ProgressBar {
      w: w,
      progress_quad: progress_quad,
      inactive_quad: inactive_quad,
      recip_dur_sec: 1. / dur_sec,
      listeners: HashMap::new()
    }))
  }

  /// Add a listener.
  pub fn add_listener(&mut self, key: &str, listener: &Rc<RefCell<ProgressBarListener>>) {
    self.listeners.insert(key.to_owned(), listener.clone());
  }

  /// Remove a listener.
  pub fn remove_listener(&mut self, key: &str) {
    self.listeners.remove(key);
  }

  /// Set the cursor (seconds).
  pub fn set(&mut self, cursor: f32) {
    let c = cursor * self.recip_dur_sec * self.w;

    // update the quads
    self.progress_quad.0.pos[0] = c;
    self.progress_quad.1.pos[0] = c;
    self.inactive_quad.2.pos[0] = c;
    self.inactive_quad.3.pos[0] = c;

    for l in self.listeners.values() {
      l.borrow_mut().on_set(cursor);
    }
  }

  fn on_cursor_change(&mut self, cursor: [f64; 2]) {
    let c = cursor[0] as f32;

    // update the quads
    self.progress_quad.0.pos[0] = c;
    self.progress_quad.1.pos[0] = c;
    self.inactive_quad.2.pos[0] = c;
    self.inactive_quad.3.pos[0] = c;

    for l in self.listeners.values() {
      l.borrow_mut().on_set(c / (self.recip_dur_sec * self.w));
    }
  }
}

impl EventHandler for Rc<RefCell<ProgressBar>> {
  fn on_mouse_button(&mut self, _: MouseButton, action: Action) -> EventSig {
    if action == Action::Press {
      EventSig::Focused
    } else {
      EventSig::Ignored
    }
  }
}

impl<'a> Widget<'a> for Rc<RefCell<ProgressBar>> {
  fn unwidget(&self) -> Vec<WidgetPrim<'a>> {
    let bar = &self.borrow();
    vec![WidgetPrim::Quad(bar.progress_quad), WidgetPrim::Quad(bar.inactive_quad)]
  }

  fn on_click(&self, cursor: [f64; 2]) {
    self.borrow_mut().on_cursor_change(cursor);
  }

  fn on_drag(&self, cursor: [f64; 2], down_cursor: [f64; 2]) {
    self.borrow_mut().on_cursor_change([cursor[0], down_cursor[1]]);
  }
}

/// Pixel distance between two points.
fn px_dist(a: [f64; 2], b: [f64; 2]) -> f64 {
  let x = b[0] - a[0];
  let y = b[1] - a[1];

  f64::sqrt(x*x + y*y)
}
<|endoftext|>