<commit_before>//! The pedigree module implements functionality for tracking which Unify and Operation structures were used to derive a new Unify.

use itertools::Itertools;
use serde_json;
use std;
use std::collections::btree_map::BTreeMap;
use std::collections::btree_set::BTreeSet;

// Describes how a given inference tree should be rendered
#[derive(Clone, Copy, Debug)]
pub enum RenderType {
    // Render all inferences that were derived in the process of deriving the specified inference
    Full,
    // Just render the direct ancestry for the specified inference
    Pedigree,
}

/// Represent the origin of a particular Unify
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Origin {
    /// What Actor does this Origin correspond to
    pub source_id: String,
    /// What data did the source use to construct the entity that this Origin corresponds to
    pub args: Vec<String>,
}

impl std::fmt::Display for Origin {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", serde_json::to_string(&self).unwrap())
    }
}

impl Origin {
    pub fn new() -> Self {
        Origin {
            source_id: String::new(),
            args: Vec::new(),
        }
    }

    pub fn with_source(source: String) -> Self {
        Origin {
            source_id: source,
            args: Vec::new(),
        }
    }

    pub fn ancestors(&self) -> Vec<&String> {
        self.args.iter().chain(std::iter::once(&self.source_id)).collect()
    }
}

/// Used for iterating through the ancestry for a given inference
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InferenceGraphBackwardIterator<'a> {
    inf_graph: &'a InferenceGraph,
    next_generation: Option<usize>,
}

impl<'a> Iterator for InferenceGraphBackwardIterator<'a> {
    type Item = (Vec<(&'a String, Option<&'a Origin>)>, Vec<&'a BTreeSet<String>>);

    fn next(&mut self) -> Option<(Vec<(&'a String, Option<&'a Origin>)>, Vec<&'a BTreeSet<String>>)> {
        let current_generation = self.next_generation;

        self.next_generation = self.next_generation.and_then(|idx| if idx == 0 { None } else { Some(idx - 1) });

        let construct_id_origin_tuple = |current_id| {
            (current_id,
             self.inf_graph
                 .pedigree
                 .get_ancestor(current_id))
        };

        let construct_id_origin_tuples_for_generation = |generation: &'a BTreeSet<String>| {
            generation.iter()
                .map(construct_id_origin_tuple)
                .collect()
        };

        current_generation.and_then(|generation_idx| {
            self.inf_graph.entries_by_generation.get(generation_idx).and_then(|generation| {
                Some((construct_id_origin_tuples_for_generation(generation), self.inf_graph.subsequent_inferences((generation_idx + 1))))
            })
        })
    }
}

/// Provide a convenient interface to a particular inference graph.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InferenceGraph {
    pedigree: Pedigree,
    /// Track which generation each unify was created in; the root ocurrs in the last generation
    entries_by_generation: Vec<BTreeSet<String>>,
    /// Inverse of entries_by_generation; map each id into the generation it was introduced in
    entries_to_generation: BTreeMap<String, usize>,
    /// The endpoint data for the inference graph
    /// For forward chaining, this is the initial data used in the inference.
    /// For backward chaining, this is the final grounded results.
    leaves: BTreeSet<String>,
    /// The goal of the infernece
    root: String,
}

impl<'a> InferenceGraph {
    pub fn new(root: String) -> Self {
        InferenceGraph {
            pedigree: Pedigree::new(),
            entries_by_generation: Vec::new(),
            entries_to_generation: BTreeMap::new(),
            leaves: BTreeSet::new(),
            root: root,
        }
    }

    pub fn back_iter(&self) -> InferenceGraphBackwardIterator {
        InferenceGraphBackwardIterator {
            inf_graph: self,
            next_generation: Some(self.entries_by_generation.len() - 1),
        }
    }

    pub fn root(&self) -> &String {
        &self.root
    }

    pub fn leaves(&'a self) -> &'a BTreeSet<String> {
        &self.leaves
    }

    pub fn ancestor(&self, id: &String) -> Option<&Origin> {
        self.pedigree.get_ancestor(id)
    }

    pub fn descendent_inferences(&'a self, id: &String) -> Option<&'a BTreeSet<String>> {
        /// Return unify derived from this one
        self.pedigree.get_descendents(id)
    }

    pub fn subsequent_inferences(&'a self, generation: usize) -> Vec<&'a BTreeSet<String>> {
        /// Return all unify derived in and after the specified generation
        let mut subsequent_inferences = Vec::new();

        for entries in self.entries_by_generation
            .iter()
            .skip(generation) {
            subsequent_inferences.push(entries);
        }

        subsequent_inferences
    }

    pub fn all_ids(&'a self) -> BTreeSet<&'a String> {
        self.entries_to_generation.keys().collect()
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InferenceGraphBuilder {
    pedigree: Pedigree,
    entries_by_generation: Vec<BTreeSet<String>>,
    entries_to_generation: BTreeMap<String, usize>,
    leaves: BTreeSet<String>,
    root: String,
}

impl InferenceGraphBuilder {
    pub fn new() -> Self {
        InferenceGraphBuilder {
            pedigree: Pedigree::new(),
            entries_by_generation: Vec::new(),
            entries_to_generation: BTreeMap::new(),
            leaves: BTreeSet::new(),
            root: String::new(),
        }
    }

    pub fn finalize(self) -> InferenceGraph {
        InferenceGraph {
            pedigree: self.pedigree,
            entries_by_generation: self.entries_by_generation,
            entries_to_generation: self.entries_to_generation,
            leaves: self.leaves,
            root: self.root,
        }
    }

    pub fn pedigree(self, pedigree: Pedigree) -> Self {
        let mut igraph = self.clone();
        igraph.pedigree = pedigree;
        igraph
    }

    pub fn update_pedigree(self, id: String, origin: Origin) -> Self {
        let mut igraph = self.clone();
        igraph.pedigree = igraph.pedigree.insert(id, origin);
        igraph
    }

    pub fn entries_by_generation(self, entries_by_generation: Vec<BTreeSet<String>>) -> Self {
        let mut igraph = self.clone();
        igraph.entries_by_generation = entries_by_generation;
        igraph
    }

    pub fn extend_entries_by_generation(self, generation_idx: usize, entries: Vec<String>) -> Self {
        let mut entries_by_generation = self.entries_by_generation.clone();
        let new_entries: BTreeSet<String> = entries.into_iter().collect();

        if entries_by_generation.len() <= generation_idx {
            entries_by_generation.push(new_entries);
        } else {
            if let Some(generation) = entries_by_generation.get_mut(generation_idx) {
                generation.extend(new_entries);
            }
        }

        let mut igraph = self.clone();
        igraph.entries_by_generation = entries_by_generation;
        igraph
    }

    pub fn entries_to_generation(self, entries_to_generation: BTreeMap<String, usize>) -> Self {
        let mut igraph = self.clone();
        igraph.entries_to_generation = entries_to_generation;
        igraph
    }

    pub fn leaves(self, leaves: BTreeSet<String>) -> Self {
        let mut igraph = self.clone();
        igraph.leaves = leaves;
        igraph
    }

    pub fn update_leaves(self, id: String) -> Self {
        let mut igraph = self.clone();
        igraph.leaves.insert(id);
        igraph
    }

    pub fn root(self, root: String) -> Self {
        let mut igraph = self.clone();
        igraph.root = root;
        igraph
    }
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct InferenceChain {
    pub elements: Vec<(Vec<(String, Option<Origin>)>)>,
}

impl std::fmt::Display for InferenceChain {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", serde_json::to_string(&self).unwrap())
    }
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Pedigree {
    ancestors: BTreeMap<String, Origin>,
    descendents: BTreeMap<String, BTreeSet<String>>,
}

impl Pedigree {
    pub fn new() -> Self {
        Pedigree {
            ancestors: BTreeMap::new(),
            descendents: BTreeMap::new(),
        }
    }

    pub fn insert(&self, id: String, org: Origin) -> Self {
        let mut pedigree = self.clone();
        pedigree.insert_mut(id, org);
        pedigree
    }

    pub fn insert_mut(&mut self, id: String, org: Origin) {
        let source_id = org.source_id.clone();
        self.ancestors.insert(id.clone(), org);

        if !self.descendents.contains_key(&source_id) {
            self.descendents.insert(source_id.clone(), BTreeSet::new());
        }
        let mut inner_descendents = self.descendents.get_mut(&source_id).unwrap();
        inner_descendents.insert(id);
    }

    pub fn get_ancestor(&self, id: &String) -> Option<&Origin> {
        self.ancestors.get(id)
    }

    pub fn get_descendents(&self, id: &String) -> Option<&BTreeSet<String>> {
        self.descendents.get(id)
    }

    /// Remove all reference to the specified id
    pub fn purge(&self, id: &String) -> Self {
        let mut pedigree = self.clone();
        pedigree.purge_mut(id);
        pedigree
    }

    pub fn purge_mut(&mut self, id: &String) {
        self.ancestors.remove(id);

        let mut descendents = self.descendents.clone();

        for (ancestor_id, these_descendents) in self.descendents.iter() {
            if these_descendents.contains(id) {
                let mut these_descendents = these_descendents.clone();
                these_descendents.remove(id);
                descendents.insert(ancestor_id.clone(), these_descendents);
            }
        }

        self.descendents = descendents;
    }

    pub fn extract_inference_chain(&self, root: &String) -> InferenceChain {
        InferenceChain {
            elements: self.extract_inference_graph(root)
                .back_iter()
                .map(|(generation, _subsequent_generations)| {
                    generation.into_iter().map(|(ref id, ref origin)| ((*id).clone(), (*origin).cloned())).collect()
                })
                .collect(),
        }
    }

    pub fn extract_inference_graph(&self, root: &String) -> InferenceGraph {
        let builder = InferenceGraphBuilder::new().root(root.clone());

        // Note: we construct the entries_by_generation vector in reverse since we don't know in advance the how big it will be
        let mut builder = self.extract_inference_graph_helper(builder, vec![root], 0);

        // Reverse the order of the entries_by_generation so initial inferences are first and the root is last
        builder.entries_by_generation.reverse();
        let mut entries_to_generation: BTreeMap<String, usize> = BTreeMap::new();
        for (idx, entries) in builder.entries_by_generation.iter().enumerate() {
            for entry in entries.iter() {
                entries_to_generation.insert(entry.clone(), idx);
            }
        }
        builder.entries_to_generation = entries_to_generation;
        builder.finalize()
    }

    fn extract_inference_graph_helper(&self,
                                      builder: InferenceGraphBuilder,
                                      current_generation: Vec<&String>,
                                      generations_from_root: usize)
                                      -> InferenceGraphBuilder {
        if current_generation.len() > 0 {
            let builder = builder.extend_entries_by_generation(generations_from_root,
                                                               current_generation.iter().cloned().cloned().collect());
            current_generation.into_iter().fold(builder,
                                                |builder, current_id| match self.get_ancestor(current_id).cloned() {
                                                    None => builder,
                                                    Some(ref origin) => {
                                                        let builder = builder.update_pedigree(current_id.clone(), origin.clone());
                                                        let builder = if origin.args.is_empty() {
                                                            builder.update_leaves(current_id.clone())
                                                        } else {
                                                            builder
                                                        };
                                                        self.extract_inference_graph_helper(builder,
                                                                                origin.ancestors()
                                                                                .iter()
                                                                                .cloned()
                                                                                .collect(),
                                                                                generations_from_root + 1)
                                                    }
                                                })
        } else {
            builder
        }
    }

    pub fn render_inference_tree(&self,
                                 d_id: &String,
                                 root_renderer: &Fn(String) -> String,
                                 node_renderer: &Fn(String) -> String,
                                 relation_renderder: &Fn(String, String) -> String,
                                 render_type: RenderType)
                                 -> String {
        let s = match render_type {
            RenderType::Pedigree => self.render_inference_tree_pedigree(d_id, node_renderer),
            RenderType::Full => self.render_inference_tree_full(d_id, node_renderer, relation_renderder),
        };
        format!("graph \"inference chain for {}\" {{\n{}\n}}",
                root_renderer(d_id.clone()),
                s)
    }

    pub fn render_inference_tree_full(&self,
                                      d_id: &String,
                                      node_renderer: &Fn(String) -> String,
                                      relation_renderder: &Fn(String, String) -> String)
                                      -> String {
        let inf_graph = self.extract_inference_graph(d_id);
        let mut relationships: Vec<String> = Vec::new();

        for (current_generation, future_generations) in inf_graph.back_iter() {
            // For each generation
            for future_generation in future_generations.iter() {
                // For each following generation
                for (&(ref current_id, ref _origin), descendent_id) in
                    current_generation.iter()
                        .cartesian_product(future_generation.iter()) {
                    // For each pairing of current generation
                    relationships.push(format!("\"{}\" -- \"{}\" \"{}\"",
                                               node_renderer((*current_id).clone()),
                                               node_renderer(descendent_id.clone()),
                                               relation_renderder((*current_id).clone(), (*descendent_id).clone())));
                }
            }
        }
        relationships.iter().join(";\n")
    }

    pub fn render_inference_tree_pedigree(&self, d_id: &String, node_renderer: &Fn(String) -> String) -> String {
        let mut relationships: Vec<String> = Vec::new();
        if let Some(origin) = self.ancestors.get(d_id) {
            // Render the relationship to the parent actor
            relationships.push(format!(r#""{}" -- "{}""#,
                                       node_renderer(d_id.clone()),
                                       node_renderer(origin.source_id.clone())));
            for arg in origin.args.iter() {
                // Render the relationship to each parent actor argument
                relationships.push(format!(r#""{}" -- "{}""#,
                                           node_renderer(d_id.clone()),
                                           node_renderer(arg.clone())));
                // Render each parent actor argument's relationships
                relationships.push(self.render_inference_tree_pedigree(arg, node_renderer));
            }
        }
        relationships.iter().join(";\n")
    }
}

#[cfg(test)]
mod tests;
<commit_msg>Fixed typo<commit_after>//! The pedigree module implements functionality for tracking which Unify and Operation structures were used to derive a new Unify.

use itertools::Itertools;
use serde_json;
use std;
use std::collections::btree_map::BTreeMap;
use std::collections::btree_set::BTreeSet;

// Describes how a given inference tree should be rendered
#[derive(Clone, Copy, Debug)]
pub enum RenderType {
    // Render all inferences that were derived in the process of deriving the specified inference
    Full,
    // Just render the direct ancestry for the specified inference
    Pedigree,
}

/// Represent the origin of a particular Unify
#[derive(Clone, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
pub struct Origin {
    /// What Operation does this Origin correspond to
    pub source_id: String,
    /// What data did the source use to construct the entity that this Origin corresponds to
    pub args: Vec<String>,
}

impl std::fmt::Display for Origin {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", serde_json::to_string(&self).unwrap())
    }
}

impl Origin {
    pub fn new() -> Self {
        Origin {
            source_id: String::new(),
            args: Vec::new(),
        }
    }

    pub fn with_source(source: String) -> Self {
        Origin {
            source_id: source,
            args: Vec::new(),
        }
    }

    pub fn ancestors(&self) -> Vec<&String> {
        self.args.iter().chain(std::iter::once(&self.source_id)).collect()
    }
}

/// Used for iterating through the ancestry for a given inference
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InferenceGraphBackwardIterator<'a> {
    inf_graph: &'a InferenceGraph,
    next_generation: Option<usize>,
}

impl<'a> Iterator for InferenceGraphBackwardIterator<'a> {
    type Item = (Vec<(&'a String, Option<&'a Origin>)>, Vec<&'a BTreeSet<String>>);

    fn next(&mut self) -> Option<(Vec<(&'a String, Option<&'a Origin>)>, Vec<&'a BTreeSet<String>>)> {
        let current_generation = self.next_generation;

        self.next_generation = self.next_generation.and_then(|idx| if idx == 0 { None } else { Some(idx - 1) });

        let construct_id_origin_tuple = |current_id| {
            (current_id,
             self.inf_graph
                 .pedigree
                 .get_ancestor(current_id))
        };

        let construct_id_origin_tuples_for_generation = |generation: &'a BTreeSet<String>| {
            generation.iter()
                .map(construct_id_origin_tuple)
                .collect()
        };

        current_generation.and_then(|generation_idx| {
            self.inf_graph.entries_by_generation.get(generation_idx).and_then(|generation| {
                Some((construct_id_origin_tuples_for_generation(generation), self.inf_graph.subsequent_inferences((generation_idx + 1))))
            })
        })
    }
}

/// Provide a convenient interface to a particular inference graph.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InferenceGraph {
    pedigree: Pedigree,
    /// Track which generation each unify was created in; the root ocurrs in the last generation
    entries_by_generation: Vec<BTreeSet<String>>,
    /// Inverse of entries_by_generation; map each id into the generation it was introduced in
    entries_to_generation: BTreeMap<String, usize>,
    /// The endpoint data for the inference graph
    /// For forward chaining, this is the initial data used in the inference.
    /// For backward chaining, this is the final grounded results.
    leaves: BTreeSet<String>,
    /// The goal of the infernece
    root: String,
}

impl<'a> InferenceGraph {
    pub fn new(root: String) -> Self {
        InferenceGraph {
            pedigree: Pedigree::new(),
            entries_by_generation: Vec::new(),
            entries_to_generation: BTreeMap::new(),
            leaves: BTreeSet::new(),
            root: root,
        }
    }

    pub fn back_iter(&self) -> InferenceGraphBackwardIterator {
        InferenceGraphBackwardIterator {
            inf_graph: self,
            next_generation: Some(self.entries_by_generation.len() - 1),
        }
    }

    pub fn root(&self) -> &String {
        &self.root
    }

    pub fn leaves(&'a self) -> &'a BTreeSet<String> {
        &self.leaves
    }

    pub fn ancestor(&self, id: &String) -> Option<&Origin> {
        self.pedigree.get_ancestor(id)
    }

    pub fn descendent_inferences(&'a self, id: &String) -> Option<&'a BTreeSet<String>> {
        /// Return unify derived from this one
        self.pedigree.get_descendents(id)
    }

    pub fn subsequent_inferences(&'a self, generation: usize) -> Vec<&'a BTreeSet<String>> {
        /// Return all unify derived in and after the specified generation
        let mut subsequent_inferences = Vec::new();

        for entries in self.entries_by_generation
            .iter()
            .skip(generation) {
            subsequent_inferences.push(entries);
        }

        subsequent_inferences
    }

    pub fn all_ids(&'a self) -> BTreeSet<&'a String> {
        self.entries_to_generation.keys().collect()
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InferenceGraphBuilder {
    pedigree: Pedigree,
    entries_by_generation: Vec<BTreeSet<String>>,
    entries_to_generation: BTreeMap<String, usize>,
    leaves: BTreeSet<String>,
    root: String,
}

impl InferenceGraphBuilder {
    pub fn new() -> Self {
        InferenceGraphBuilder {
            pedigree: Pedigree::new(),
            entries_by_generation: Vec::new(),
            entries_to_generation: BTreeMap::new(),
            leaves: BTreeSet::new(),
            root: String::new(),
        }
    }

    pub fn finalize(self) -> InferenceGraph {
        InferenceGraph {
            pedigree: self.pedigree,
            entries_by_generation: self.entries_by_generation,
            entries_to_generation: self.entries_to_generation,
            leaves: self.leaves,
            root: self.root,
        }
    }

    pub fn pedigree(self, pedigree: Pedigree) -> Self {
        let mut igraph = self.clone();
        igraph.pedigree = pedigree;
        igraph
    }

    pub fn update_pedigree(self, id: String, origin: Origin) -> Self {
        let mut igraph = self.clone();
        igraph.pedigree = igraph.pedigree.insert(id, origin);
        igraph
    }

    pub fn entries_by_generation(self, entries_by_generation: Vec<BTreeSet<String>>) -> Self {
        let mut igraph = self.clone();
        igraph.entries_by_generation = entries_by_generation;
        igraph
    }

    pub fn extend_entries_by_generation(self, generation_idx: usize, entries: Vec<String>) -> Self {
        let mut entries_by_generation = self.entries_by_generation.clone();
        let new_entries: BTreeSet<String> = entries.into_iter().collect();

        if entries_by_generation.len() <= generation_idx {
            entries_by_generation.push(new_entries);
        } else {
            if let Some(generation) = entries_by_generation.get_mut(generation_idx) {
                generation.extend(new_entries);
            }
        }

        let mut igraph = self.clone();
        igraph.entries_by_generation = entries_by_generation;
        igraph
    }

    pub fn entries_to_generation(self, entries_to_generation: BTreeMap<String, usize>) -> Self {
        let mut igraph = self.clone();
        igraph.entries_to_generation = entries_to_generation;
        igraph
    }

    pub fn leaves(self, leaves: BTreeSet<String>) -> Self {
        let mut igraph = self.clone();
        igraph.leaves = leaves;
        igraph
    }

    pub fn update_leaves(self, id: String) -> Self {
        let mut igraph = self.clone();
        igraph.leaves.insert(id);
        igraph
    }

    pub fn root(self, root: String) -> Self {
        let mut igraph = self.clone();
        igraph.root = root;
        igraph
    }
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct InferenceChain {
    pub elements: Vec<(Vec<(String, Option<Origin>)>)>,
}

impl std::fmt::Display for InferenceChain {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "{}", serde_json::to_string(&self).unwrap())
    }
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Pedigree {
    ancestors: BTreeMap<String, Origin>,
    descendents: BTreeMap<String, BTreeSet<String>>,
}

impl Pedigree {
    pub fn new() -> Self {
        Pedigree {
            ancestors: BTreeMap::new(),
            descendents: BTreeMap::new(),
        }
    }

    pub fn insert(&self, id: String, org: Origin) -> Self {
        let mut pedigree = self.clone();
        pedigree.insert_mut(id, org);
        pedigree
    }

    pub fn insert_mut(&mut self, id: String, org: Origin) {
        let source_id = org.source_id.clone();
        self.ancestors.insert(id.clone(), org);

        if !self.descendents.contains_key(&source_id) {
            self.descendents.insert(source_id.clone(), BTreeSet::new());
        }
        let mut inner_descendents = self.descendents.get_mut(&source_id).unwrap();
        inner_descendents.insert(id);
    }

    pub fn get_ancestor(&self, id: &String) -> Option<&Origin> {
        self.ancestors.get(id)
    }

    pub fn get_descendents(&self, id: &String) -> Option<&BTreeSet<String>> {
        self.descendents.get(id)
    }

    /// Remove all reference to the specified id
    pub fn purge(&self, id: &String) -> Self {
        let mut pedigree = self.clone();
        pedigree.purge_mut(id);
        pedigree
    }

    pub fn purge_mut(&mut self, id: &String) {
        self.ancestors.remove(id);

        let mut descendents = self.descendents.clone();

        for (ancestor_id, these_descendents) in self.descendents.iter() {
            if these_descendents.contains(id) {
                let mut these_descendents = these_descendents.clone();
                these_descendents.remove(id);
                descendents.insert(ancestor_id.clone(), these_descendents);
            }
        }

        self.descendents = descendents;
    }

    pub fn extract_inference_chain(&self, root: &String) -> InferenceChain {
        InferenceChain {
            elements: self.extract_inference_graph(root)
                .back_iter()
                .map(|(generation, _subsequent_generations)| {
                    generation.into_iter().map(|(ref id, ref origin)| ((*id).clone(), (*origin).cloned())).collect()
                })
                .collect(),
        }
    }

    pub fn extract_inference_graph(&self, root: &String) -> InferenceGraph {
        let builder = InferenceGraphBuilder::new().root(root.clone());

        // Note: we construct the entries_by_generation vector in reverse since we don't know in advance the how big it will be
        let mut builder = self.extract_inference_graph_helper(builder, vec![root], 0);

        // Reverse the order of the entries_by_generation so initial inferences are first and the root is last
        builder.entries_by_generation.reverse();
        let mut entries_to_generation: BTreeMap<String, usize> = BTreeMap::new();
        for (idx, entries) in builder.entries_by_generation.iter().enumerate() {
            for entry in entries.iter() {
                entries_to_generation.insert(entry.clone(), idx);
            }
        }
        builder.entries_to_generation = entries_to_generation;
        builder.finalize()
    }

    fn extract_inference_graph_helper(&self,
                                      builder: InferenceGraphBuilder,
                                      current_generation: Vec<&String>,
                                      generations_from_root: usize)
                                      -> InferenceGraphBuilder {
        if current_generation.len() > 0 {
            let builder = builder.extend_entries_by_generation(generations_from_root,
                                                               current_generation.iter().cloned().cloned().collect());
            current_generation.into_iter().fold(builder,
                                                |builder, current_id| match self.get_ancestor(current_id).cloned() {
                                                    None => builder,
                                                    Some(ref origin) => {
                                                        let builder = builder.update_pedigree(current_id.clone(), origin.clone());
                                                        let builder = if origin.args.is_empty() {
                                                            builder.update_leaves(current_id.clone())
                                                        } else {
                                                            builder
                                                        };
                                                        self.extract_inference_graph_helper(builder,
                                                                                origin.ancestors()
                                                                                .iter()
                                                                                .cloned()
                                                                                .collect(),
                                                                                generations_from_root + 1)
                                                    }
                                                })
        } else {
            builder
        }
    }

    pub fn render_inference_tree(&self,
                                 d_id: &String,
                                 root_renderer: &Fn(String) -> String,
                                 node_renderer: &Fn(String) -> String,
                                 relation_renderder: &Fn(String, String) -> String,
                                 render_type: RenderType)
                                 -> String {
        let s = match render_type {
            RenderType::Pedigree => self.render_inference_tree_pedigree(d_id, node_renderer),
            RenderType::Full => self.render_inference_tree_full(d_id, node_renderer, relation_renderder),
        };
        format!("graph \"inference chain for {}\" {{\n{}\n}}",
                root_renderer(d_id.clone()),
                s)
    }

    pub fn render_inference_tree_full(&self,
                                      d_id: &String,
                                      node_renderer: &Fn(String) -> String,
                                      relation_renderder: &Fn(String, String) -> String)
                                      -> String {
        let inf_graph = self.extract_inference_graph(d_id);
        let mut relationships: Vec<String> = Vec::new();

        for (current_generation, future_generations) in inf_graph.back_iter() {
            // For each generation
            for future_generation in future_generations.iter() {
                // For each following generation
                for (&(ref current_id, ref _origin), descendent_id) in
                    current_generation.iter()
                        .cartesian_product(future_generation.iter()) {
                    // For each pairing of current generation
                    relationships.push(format!("\"{}\" -- \"{}\" \"{}\"",
                                               node_renderer((*current_id).clone()),
                                               node_renderer(descendent_id.clone()),
                                               relation_renderder((*current_id).clone(), (*descendent_id).clone())));
                }
            }
        }
        relationships.iter().join(";\n")
    }

    pub fn render_inference_tree_pedigree(&self, d_id: &String, node_renderer: &Fn(String) -> String) -> String {
        let mut relationships: Vec<String> = Vec::new();
        if let Some(origin) = self.ancestors.get(d_id) {
            // Render the relationship to the parent actor
            relationships.push(format!(r#""{}" -- "{}""#,
                                       node_renderer(d_id.clone()),
                                       node_renderer(origin.source_id.clone())));
            for arg in origin.args.iter() {
                // Render the relationship to each parent actor argument
                relationships.push(format!(r#""{}" -- "{}""#,
                                           node_renderer(d_id.clone()),
                                           node_renderer(arg.clone())));
                // Render each parent actor argument's relationships
                relationships.push(self.render_inference_tree_pedigree(arg, node_renderer));
            }
        }
        relationships.iter().join(";\n")
    }
}

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>use bytes::Buf;
use futures::{Async, Future, Poll};
use h2::{Reason, SendStream};
use http::header::{
    HeaderName, CONNECTION, PROXY_AUTHENTICATE, PROXY_AUTHORIZATION, TE, TRAILER,
    TRANSFER_ENCODING, UPGRADE,
};
use http::HeaderMap;

use body::Payload;

mod client;
mod server;

pub(crate) use self::client::Client;
pub(crate) use self::server::Server;

fn strip_connection_headers(headers: &mut HeaderMap) {
    // List of connection headers from:
    // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection
    let connection_headers = [
        HeaderName::from_lowercase(b"keep-alive").unwrap(),
        HeaderName::from_lowercase(b"proxy-connection").unwrap(),
        PROXY_AUTHENTICATE,
        PROXY_AUTHORIZATION,
        TE,
        TRAILER,
        TRANSFER_ENCODING,
        UPGRADE,
    ];

    for header in connection_headers.iter() {
        if headers.remove(header).is_some() {
            warn!("Connection header illegal in HTTP/2: {}", header.as_str());
        }
    }

    if let Some(header) = headers.remove(CONNECTION) {
        warn!(
            "Connection header illegal in HTTP/2: {}",
            CONNECTION.as_str()
        );
        let header_contents = header.to_str().unwrap();

        // A `Connection` header may have a comma-separated list of names of other headers that
        // are meant for only this specific connection.
        //
        // Iterate these names and remove them as headers. Connection-specific headers are
        // forbidden in HTTP2, as that information has been moved into frame types of the h2
        // protocol.
        for name in header_contents.split(',') {
            let name = name.trim();
            headers.remove(name);
        }
    }
}

// body adapters used by both Client and Server

struct PipeToSendStream<S>
where
    S: Payload,
{
    body_tx: SendStream<SendBuf<S::Data>>,
    data_done: bool,
    stream: S,
}

impl<S> PipeToSendStream<S>
where
    S: Payload,
{
    fn new(stream: S, tx: SendStream<SendBuf<S::Data>>) -> PipeToSendStream<S> {
        PipeToSendStream {
            body_tx: tx,
            data_done: false,
            stream: stream,
        }
    }

    fn on_err(&mut self, err: S::Error) -> ::Error {
        let err = ::Error::new_user_body(err);
        trace!("send body user stream error: {}", err);
        self.body_tx.send_reset(Reason::INTERNAL_ERROR);
        err
    }

    fn send_eos_frame(&mut self) -> ::Result<()> {
        trace!("send body eos");
        self.body_tx
            .send_data(SendBuf(None), true)
            .map_err(::Error::new_body_write)
    }
}

impl<S> Future for PipeToSendStream<S>
where
    S: Payload,
{
    type Item = ();
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if !self.data_done {
                // TODO: make use of flow control on SendStream
                // If you're looking at this and thinking of trying to fix this TODO,
                // you may want to look at:
                // https://docs.rs/h2/0.1.*/h2/struct.SendStream.html
                //
                // With that doc open, we'd want to do these things:
                // - check self.body_tx.capacity() to see if we can send *any* data
                // - if > 0:
                // -   poll self.stream
                // -   reserve chunk.len() more capacity (because its about to be used)?
                // -   send the chunk
                // - else:
                // -   try reserve a smallish amount of capacity
                // -   call self.body_tx.poll_capacity(), return if NotReady
                match try_ready!(self.stream.poll_data().map_err(|e| self.on_err(e))) {
                    Some(chunk) => {
                        let is_eos = self.stream.is_end_stream();
                        trace!(
                            "send body chunk: {} bytes, eos={}",
                            chunk.remaining(),
                            is_eos,
                        );

                        let buf = SendBuf(Some(chunk));
                        self.body_tx
                            .send_data(buf, is_eos)
                            .map_err(::Error::new_body_write)?;

                        if is_eos {
                            return Ok(Async::Ready(()));
                        }
                    }
                    None => {
                        let is_eos = self.stream.is_end_stream();
                        if is_eos {
                            return self.send_eos_frame().map(Async::Ready);
                        } else {
                            self.data_done = true;
                            // loop again to poll_trailers
                        }
                    }
                }
            } else {
                match try_ready!(self.stream.poll_trailers().map_err(|e| self.on_err(e))) {
                    Some(trailers) => {
                        self.body_tx
                            .send_trailers(trailers)
                            .map_err(::Error::new_body_write)?;
                        return Ok(Async::Ready(()));
                    }
                    None => {
                        // There were no trailers, so send an empty DATA frame...
                        return self.send_eos_frame().map(Async::Ready);
                    }
                }
            }
        }
    }
}

struct SendBuf<B>(Option<B>);

impl<B: Buf> Buf for SendBuf<B> {
    #[inline]
    fn remaining(&self) -> usize {
        self.0.as_ref().map(|b| b.remaining()).unwrap_or(0)
    }

    #[inline]
    fn bytes(&self) -> &[u8] {
        self.0.as_ref().map(|b| b.bytes()).unwrap_or(&[])
    }

    #[inline]
    fn advance(&mut self, cnt: usize) {
        self.0.as_mut().map(|b| b.advance(cnt));
    }
}
<commit_msg>feat(h2): implement flow control for h2 bodies<commit_after>use bytes::Buf;
use futures::{Async, Future, Poll};
use h2::{Reason, SendStream};
use http::header::{
    HeaderName, CONNECTION, PROXY_AUTHENTICATE, PROXY_AUTHORIZATION, TE, TRAILER,
    TRANSFER_ENCODING, UPGRADE,
};
use http::HeaderMap;

use body::Payload;

mod client;
mod server;

pub(crate) use self::client::Client;
pub(crate) use self::server::Server;

fn strip_connection_headers(headers: &mut HeaderMap) {
    // List of connection headers from:
    // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Connection
    let connection_headers = [
        HeaderName::from_lowercase(b"keep-alive").unwrap(),
        HeaderName::from_lowercase(b"proxy-connection").unwrap(),
        PROXY_AUTHENTICATE,
        PROXY_AUTHORIZATION,
        TE,
        TRAILER,
        TRANSFER_ENCODING,
        UPGRADE,
    ];

    for header in connection_headers.iter() {
        if headers.remove(header).is_some() {
            warn!("Connection header illegal in HTTP/2: {}", header.as_str());
        }
    }

    if let Some(header) = headers.remove(CONNECTION) {
        warn!(
            "Connection header illegal in HTTP/2: {}",
            CONNECTION.as_str()
        );
        let header_contents = header.to_str().unwrap();

        // A `Connection` header may have a comma-separated list of names of other headers that
        // are meant for only this specific connection.
        //
        // Iterate these names and remove them as headers. Connection-specific headers are
        // forbidden in HTTP2, as that information has been moved into frame types of the h2
        // protocol.
        for name in header_contents.split(',') {
            let name = name.trim();
            headers.remove(name);
        }
    }
}

// body adapters used by both Client and Server

struct PipeToSendStream<S>
where
    S: Payload,
{
    body_tx: SendStream<SendBuf<S::Data>>,
    data_done: bool,
    stream: S,
}

impl<S> PipeToSendStream<S>
where
    S: Payload,
{
    fn new(stream: S, tx: SendStream<SendBuf<S::Data>>) -> PipeToSendStream<S> {
        PipeToSendStream {
            body_tx: tx,
            data_done: false,
            stream: stream,
        }
    }

    fn on_err(&mut self, err: S::Error) -> ::Error {
        let err = ::Error::new_user_body(err);
        trace!("send body user stream error: {}", err);
        self.body_tx.send_reset(Reason::INTERNAL_ERROR);
        err
    }

    fn send_eos_frame(&mut self) -> ::Result<()> {
        trace!("send body eos");
        self.body_tx
            .send_data(SendBuf(None), true)
            .map_err(::Error::new_body_write)
    }
}

impl<S> Future for PipeToSendStream<S>
where
    S: Payload,
{
    type Item = ();
    type Error = ::Error;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        loop {
            if !self.data_done {
                // we don't have the next chunk of data yet, so just reserve 1 byte to make
                // sure there's some capacity available. h2 will handle the capacity management
                // for the actual body chunk.
                self.body_tx.reserve_capacity(1);

                if self.body_tx.capacity() == 0 {
                    loop {
                        match try_ready!(self.body_tx.poll_capacity().map_err(::Error::new_h2)) {
                            Some(0) => {}
                            Some(_) => break,
                            None => return Err(::Error::new_canceled(None::<::Error>)),
                        }
                    }
                }

                match try_ready!(self.stream.poll_data().map_err(|e| self.on_err(e))) {
                    Some(chunk) => {
                        let is_eos = self.stream.is_end_stream();
                        trace!(
                            "send body chunk: {} bytes, eos={}",
                            chunk.remaining(),
                            is_eos,
                        );

                        let buf = SendBuf(Some(chunk));
                        self.body_tx
                            .send_data(buf, is_eos)
                            .map_err(::Error::new_body_write)?;

                        if is_eos {
                            return Ok(Async::Ready(()));
                        }
                    }
                    None => {
                        self.body_tx.reserve_capacity(0);
                        let is_eos = self.stream.is_end_stream();
                        if is_eos {
                            return self.send_eos_frame().map(Async::Ready);
                        } else {
                            self.data_done = true;
                            // loop again to poll_trailers
                        }
                    }
                }
            } else {
                match try_ready!(self.stream.poll_trailers().map_err(|e| self.on_err(e))) {
                    Some(trailers) => {
                        self.body_tx
                            .send_trailers(trailers)
                            .map_err(::Error::new_body_write)?;
                        return Ok(Async::Ready(()));
                    }
                    None => {
                        // There were no trailers, so send an empty DATA frame...
                        return self.send_eos_frame().map(Async::Ready);
                    }
                }
            }
        }
    }
}

struct SendBuf<B>(Option<B>);

impl<B: Buf> Buf for SendBuf<B> {
    #[inline]
    fn remaining(&self) -> usize {
        self.0.as_ref().map(|b| b.remaining()).unwrap_or(0)
    }

    #[inline]
    fn bytes(&self) -> &[u8] {
        self.0.as_ref().map(|b| b.bytes()).unwrap_or(&[])
    }

    #[inline]
    fn advance(&mut self, cnt: usize) {
        self.0.as_mut().map(|b| b.advance(cnt));
    }
}
<|endoftext|>


<commit_before>
#![allow(dead_code)]
#![allow(deprecated)]
use protobuf;
use proto::raftpb::{HardState, ConfState, Entry, Snapshot};
use raft::errors::{Result, Error, StorageError};

#[derive(Debug, Clone)]
pub struct RaftState {
    hard_state: HardState,
    conf_state: ConfState,
}

pub trait Storage {
    fn initial_state(&self) -> Result<RaftState>;
    fn entries(&self, low: u64, high: u64, max_size: u64) -> Result<&[Entry]>;
    fn term(&self, idx: u64) -> Result<u64>;
    fn first_index(&self) -> Result<u64>;
    fn last_index(&self) -> Result<u64>;
    fn snapshot(&self) -> Result<&Snapshot>;
}

pub struct MemStorage {
    hard_state: HardState,
    snapshot: Snapshot,
    // TODO: maybe vec_deque
    entries: Vec<Entry>,
}

impl MemStorage {
    pub fn new() -> MemStorage {
        MemStorage {
            // When starting from scratch populate the list with a dummy entry at term zero.
            entries: vec![Entry::new()],
            hard_state: HardState::new(),
            snapshot: Snapshot::new(),
        }
    }

    pub fn set_hardstate(&mut self, hs: HardState) {
        self.hard_state = hs;
    }

    fn inner_last_index(&self) -> u64 {
        return self.entries[0].get_Index() + self.entries.len() as u64 - 1;
    }

    fn limit_size(entries: &[Entry], max: u64) -> Result<&[Entry]> {
        if entries.len() == 0 {
            return Ok(entries);
        }

        let mut size = protobuf::Message::compute_size(&entries[0]) as u64;
        let mut limit = 1u64;
        while limit < entries.len() as u64 {
            size += protobuf::Message::compute_size(&entries[limit as usize]) as u64;
            if size > max {
                break;
            }
            limit += 1;
        }
        let ents = &entries[..limit as usize];
        Ok(ents)
    }

    pub fn apply_snapshot(&mut self, snapshot: Snapshot) -> Result<()> {
        let mut e = Entry::new();
        e.set_Term(snapshot.get_metadata().get_term());
        e.set_Index(snapshot.get_metadata().get_index());
        self.entries = vec![e];
        self.snapshot = snapshot;
        Ok(())
    }

    fn create_snapshot(&mut self,
                       idx: u64,
                       cs: Option<ConfState>,
                       data: Vec<u8>)
                       -> Result<&Snapshot> {
        if idx <= self.snapshot.get_metadata().get_index() {
            return Err(Error::Store(StorageError::SnapshotOutOfDate));
        }

        let offset = self.entries[0].get_Index();
        if idx > self.last_index().unwrap() {
            panic!("snapshot {} is out of bound lastindex({})",
                   idx,
                   self.last_index().unwrap())
        }
        self.snapshot.mut_metadata().set_index(idx);
        self.snapshot.mut_metadata().set_term(self.entries[(idx - offset) as usize].get_Term());
        match cs {
            Some(cs) => self.snapshot.mut_metadata().set_conf_state(cs),
            None => {}
        }
        self.snapshot.set_data(data);
        Ok(&self.snapshot)
    }

    pub fn compact(&mut self, compact_index: u64) -> Result<()> {
        let offset = self.entries[0].get_Index();
        if compact_index <= offset {
            return Err(Error::Store(StorageError::Compacted));
        }
        if compact_index > self.last_index().unwrap() {
            panic!("compact {} is out of bound lastindex({})",
                   compact_index,
                   self.last_index().unwrap())
        }

        let i = (compact_index - offset) as usize;
        let entries = self.entries.drain(i..).collect();
        self.entries = entries;
        Ok(())
    }

    pub fn append(&mut self, ents: &[Entry]) -> Result<()> {
        if ents.len() == 0 {
            return Ok(());
        }
        let first: u64 = self.entries[0].get_Index() + 1;
        let last: u64 = ents[0].get_Index() + ents.len() as u64 - 1;

        if last < first {
            return Ok(());
        }
        // truncate compacted entries
        let mut te: &[Entry] = ents;
        if first > ents[0].get_Index() {
            let start = (first - ents[0].get_Index()) as usize;
            te = &ents[start..ents.len()];
        }

        let offset = te[0].get_Index() - self.entries[0].get_Index();
        if self.entries.len() as u64 > offset {
            let mut new_entries: Vec<Entry> = vec![];
            new_entries.extend_from_slice(&self.entries[..offset as usize]);
            new_entries.extend_from_slice(te);
            self.entries = new_entries;
        } else if self.entries.len() as u64 == offset {
            self.entries.extend_from_slice(te);
        } else {
            panic!("missing log entry [last: {}, append at: {}]",
                   self.last_index().unwrap(),
                   te[0].get_Index())
        }

        Ok(())
    }
}

impl Storage for MemStorage {
    fn initial_state(&self) -> Result<RaftState> {
        Ok(RaftState {
            hard_state: self.hard_state.clone(),
            conf_state: self.snapshot.get_metadata().get_conf_state().clone(),
        })
    }

    fn entries(&self, low: u64, high: u64, max_size: u64) -> Result<&[Entry]> {
        let offset = self.entries[0].get_Index();
        if low <= offset {
            return Err(Error::Store(StorageError::Compacted));
        }

        if high > self.inner_last_index() + 1 {
            panic!("index out of bound")
        }
        // only contains dummy entries.
        if self.entries.len() == 1 {
            return Err(Error::Store(StorageError::Unavailable));
        }

        let lo = (low - offset) as usize;
        let hi = (high - offset) as usize;
        let ents: &[Entry] = &self.entries[lo..hi];
        return MemStorage::limit_size(ents, max_size);
    }

    fn term(&self, idx: u64) -> Result<u64> {
        let offset = self.entries[0].get_Index();
        if idx < offset {
            return Err(Error::Store(StorageError::Compacted));
        }
        Ok(self.entries[(idx - offset) as usize].get_Term())
    }

    fn first_index(&self) -> Result<u64> {
        Ok(self.entries[0].get_Index() + 1)
    }

    fn last_index(&self) -> Result<u64> {
        Ok(self.inner_last_index())
    }

    fn snapshot(&self) -> Result<&Snapshot> {
        Ok(&self.snapshot)
    }
}

/// TODO: make MemStorage become actually sync.
/// Currently MemStore is only used for single-thread testing.
unsafe impl Sync for MemStorage {}
<commit_msg>raft: export fields for outer use.<commit_after>
#![allow(dead_code)]
#![allow(deprecated)]
use protobuf;
use proto::raftpb::{HardState, ConfState, Entry, Snapshot};
use raft::errors::{Result, Error, StorageError};

#[derive(Debug, Clone)]
pub struct RaftState {
    pub hard_state: HardState,
    pub conf_state: ConfState,
}

pub trait Storage {
    fn initial_state(&self) -> Result<RaftState>;
    fn entries(&self, low: u64, high: u64, max_size: u64) -> Result<&[Entry]>;
    fn term(&self, idx: u64) -> Result<u64>;
    fn first_index(&self) -> Result<u64>;
    fn last_index(&self) -> Result<u64>;
    fn snapshot(&self) -> Result<&Snapshot>;
}

pub struct MemStorage {
    hard_state: HardState,
    snapshot: Snapshot,
    // TODO: maybe vec_deque
    entries: Vec<Entry>,
}

impl MemStorage {
    pub fn new() -> MemStorage {
        MemStorage {
            // When starting from scratch populate the list with a dummy entry at term zero.
            entries: vec![Entry::new()],
            hard_state: HardState::new(),
            snapshot: Snapshot::new(),
        }
    }

    pub fn set_hardstate(&mut self, hs: HardState) {
        self.hard_state = hs;
    }

    fn inner_last_index(&self) -> u64 {
        return self.entries[0].get_Index() + self.entries.len() as u64 - 1;
    }

    fn limit_size(entries: &[Entry], max: u64) -> Result<&[Entry]> {
        if entries.len() == 0 {
            return Ok(entries);
        }

        let mut size = protobuf::Message::compute_size(&entries[0]) as u64;
        let mut limit = 1u64;
        while limit < entries.len() as u64 {
            size += protobuf::Message::compute_size(&entries[limit as usize]) as u64;
            if size > max {
                break;
            }
            limit += 1;
        }
        let ents = &entries[..limit as usize];
        Ok(ents)
    }

    pub fn apply_snapshot(&mut self, snapshot: Snapshot) -> Result<()> {
        let mut e = Entry::new();
        e.set_Term(snapshot.get_metadata().get_term());
        e.set_Index(snapshot.get_metadata().get_index());
        self.entries = vec![e];
        self.snapshot = snapshot;
        Ok(())
    }

    fn create_snapshot(&mut self,
                       idx: u64,
                       cs: Option<ConfState>,
                       data: Vec<u8>)
                       -> Result<&Snapshot> {
        if idx <= self.snapshot.get_metadata().get_index() {
            return Err(Error::Store(StorageError::SnapshotOutOfDate));
        }

        let offset = self.entries[0].get_Index();
        if idx > self.last_index().unwrap() {
            panic!("snapshot {} is out of bound lastindex({})",
                   idx,
                   self.last_index().unwrap())
        }
        self.snapshot.mut_metadata().set_index(idx);
        self.snapshot.mut_metadata().set_term(self.entries[(idx - offset) as usize].get_Term());
        match cs {
            Some(cs) => self.snapshot.mut_metadata().set_conf_state(cs),
            None => {}
        }
        self.snapshot.set_data(data);
        Ok(&self.snapshot)
    }

    pub fn compact(&mut self, compact_index: u64) -> Result<()> {
        let offset = self.entries[0].get_Index();
        if compact_index <= offset {
            return Err(Error::Store(StorageError::Compacted));
        }
        if compact_index > self.last_index().unwrap() {
            panic!("compact {} is out of bound lastindex({})",
                   compact_index,
                   self.last_index().unwrap())
        }

        let i = (compact_index - offset) as usize;
        let entries = self.entries.drain(i..).collect();
        self.entries = entries;
        Ok(())
    }

    pub fn append(&mut self, ents: &[Entry]) -> Result<()> {
        if ents.len() == 0 {
            return Ok(());
        }
        let first: u64 = self.entries[0].get_Index() + 1;
        let last: u64 = ents[0].get_Index() + ents.len() as u64 - 1;

        if last < first {
            return Ok(());
        }
        // truncate compacted entries
        let mut te: &[Entry] = ents;
        if first > ents[0].get_Index() {
            let start = (first - ents[0].get_Index()) as usize;
            te = &ents[start..ents.len()];
        }

        let offset = te[0].get_Index() - self.entries[0].get_Index();
        if self.entries.len() as u64 > offset {
            let mut new_entries: Vec<Entry> = vec![];
            new_entries.extend_from_slice(&self.entries[..offset as usize]);
            new_entries.extend_from_slice(te);
            self.entries = new_entries;
        } else if self.entries.len() as u64 == offset {
            self.entries.extend_from_slice(te);
        } else {
            panic!("missing log entry [last: {}, append at: {}]",
                   self.last_index().unwrap(),
                   te[0].get_Index())
        }

        Ok(())
    }
}

impl Storage for MemStorage {
    fn initial_state(&self) -> Result<RaftState> {
        Ok(RaftState {
            hard_state: self.hard_state.clone(),
            conf_state: self.snapshot.get_metadata().get_conf_state().clone(),
        })
    }

    fn entries(&self, low: u64, high: u64, max_size: u64) -> Result<&[Entry]> {
        let offset = self.entries[0].get_Index();
        if low <= offset {
            return Err(Error::Store(StorageError::Compacted));
        }

        if high > self.inner_last_index() + 1 {
            panic!("index out of bound")
        }
        // only contains dummy entries.
        if self.entries.len() == 1 {
            return Err(Error::Store(StorageError::Unavailable));
        }

        let lo = (low - offset) as usize;
        let hi = (high - offset) as usize;
        let ents: &[Entry] = &self.entries[lo..hi];
        return MemStorage::limit_size(ents, max_size);
    }

    fn term(&self, idx: u64) -> Result<u64> {
        let offset = self.entries[0].get_Index();
        if idx < offset {
            return Err(Error::Store(StorageError::Compacted));
        }
        Ok(self.entries[(idx - offset) as usize].get_Term())
    }

    fn first_index(&self) -> Result<u64> {
        Ok(self.entries[0].get_Index() + 1)
    }

    fn last_index(&self) -> Result<u64> {
        Ok(self.inner_last_index())
    }

    fn snapshot(&self) -> Result<&Snapshot> {
        Ok(&self.snapshot)
    }
}

/// TODO: make MemStorage become actually sync.
/// Currently MemStore is only used for single-thread testing.
unsafe impl Sync for MemStorage {}
<|endoftext|>


<commit_before>pub const RUNTIME: &'static str = r#"
#include "ruby.h"
#include <stdbool.h>
#include <string.h>

static const char *DOT = ".";

static ID id_escape_html;
static ID id_key_p;
static ID id_to_s;

static VALUE cCGI;

struct path {
    char *keys[16];
    int length;
};

static VALUE fetch(VALUE context, const char *key) {
    if (strlen(key) == 1 && strncmp(key, DOT, 1) == 0) {
        return context;
    }

    switch (rb_type(context)) {
        case T_HASH: {
            VALUE key_str = rb_str_new_cstr(key);
            if (RTEST(rb_funcall(context, id_key_p, 1, key_str))) {
                return rb_hash_aref(context, key_str);
            } else {
                VALUE sym = ID2SYM(rb_intern(key));
                if (RTEST(rb_funcall(context, id_key_p, 1, sym))) {
                    return rb_hash_aref(context, sym);
                } else {
                    return Qundef;
                }
            }
        }
        case T_FALSE:
            return Qfalse;
        case T_NIL:
        case T_UNDEF:
            return Qundef;
        default: {
            ID method = rb_intern(key);
            if (rb_respond_to(context, method)) {
                return rb_funcall(context, method, 0);
            } else {
                return Qundef;
            }
        }
    }
}

static VALUE context_fetch(VALUE stack, const char *key) {
    for (long i = RARRAY_LEN(stack) - 1; i >= 0; i--) {
        VALUE context = RARRAY_AREF(stack, i);
        VALUE value = fetch(context, key);
        if (value != Qundef) {
            return value;
        }
    }
    return Qundef;
}

static VALUE fetch_path(VALUE stack, const struct path *path) {
    VALUE value = context_fetch(stack, path->keys[0]);
    for (long i = 1; i < path->length; i++) {
        value = fetch(value, path->keys[i]);
    }
    return value;
}

static void append_value(VALUE buf, VALUE stack, const struct path *path, bool escape) {
    VALUE value = fetch_path(stack, path);
    switch (rb_type(value)) {
        case T_NIL:
        case T_UNDEF:
            return;
        case T_STRING:
            break;
        default:
            value = rb_funcall(value, id_to_s, 0);
            break;
    }
    rb_str_buf_append(buf, escape ? rb_funcall(cCGI, id_escape_html, 1, value) : value);
}

static void section(VALUE buf, VALUE stack, const struct path *path, void (*block)(VALUE, VALUE)) {
    VALUE value = fetch_path(stack, path);
    switch (rb_type(value)) {
        case T_ARRAY:
            for (long i = 0; i < RARRAY_LEN(value); i++) {
                rb_ary_push(stack, RARRAY_AREF(value, i));
                block(buf, stack);
                rb_ary_pop(stack);
            }
            break;
        case T_NIL:
        case T_UNDEF:
        case T_FALSE:
            break;
        case T_TRUE:
            block(buf, stack);
            break;
        default:
            rb_ary_push(stack, value);
            block(buf, stack);
            rb_ary_pop(stack);
            break;
    }
}

static void inverted(VALUE buf, VALUE stack, const struct path *path, void (*block)(VALUE, VALUE)) {
    VALUE value = fetch_path(stack, path);
    switch (rb_type(value)) {
        case T_ARRAY:
            if (RARRAY_LEN(value) == 0) {
                block(buf, stack);
            }
            break;
        case T_NIL:
        case T_UNDEF:
        case T_FALSE:
            block(buf, stack);
            break;
    }
}

static VALUE render(VALUE self, VALUE name, VALUE context);
static void initialize();

void Init_stache() {
    VALUE Stache = rb_define_module("Stache");
    VALUE Templates = rb_define_class_under(Stache, "Templates", rb_cObject);
    rb_define_singleton_method(Templates, "render", render, 2);

    rb_require("cgi");
    cCGI = rb_const_get(rb_cObject, rb_intern("CGI"));
    id_escape_html = rb_intern("escapeHTML");
    id_key_p = rb_intern("key?");
    id_to_s = rb_intern("to_s");
    initialize();
}
"#;
<commit_msg>Inline CGI escape code<commit_after>pub const RUNTIME: &'static str = r#"
#include "ruby.h"
#include <stdbool.h>
#include <string.h>

static void html_escaped_cat(VALUE str, char c) {
    switch (c) {
        case '\'':
            rb_str_cat_cstr(str, "'");
            break;
        case '&':
            rb_str_cat_cstr(str, "&");
            break;
        case '"':
            rb_str_cat_cstr(str, """);
            break;
        case '<':
            rb_str_cat_cstr(str, "<");
            break;
        case '>':
            rb_str_cat_cstr(str, ">");
            break;
    }
}

static VALUE optimized_escape_html(VALUE str) {
    long beg = 0;
    VALUE dest = 0;

    const long len = RSTRING_LEN(str);
    const char *cstr = RSTRING_PTR(str);

    for (long i = 0; i < len; i++) {
        switch (cstr[i]) {
          case '\'':
          case '&':
          case '"':
          case '<':
          case '>':
            if (!dest) {
                dest = rb_str_buf_new(len);
            }

            rb_str_cat(dest, cstr + beg, i - beg);
            beg = i + 1;

            html_escaped_cat(dest, cstr[i]);
            break;
        }
    }

    if (dest) {
        rb_str_cat(dest, cstr + beg, len - beg);
        return dest;
    } else {
        return str;
    }
}

static const char *DOT = ".";

static ID id_key_p;
static ID id_to_s;

static VALUE cCGI;

struct path {
    char *keys[16];
    int length;
};

static VALUE fetch(VALUE context, const char *key) {
    if (strlen(key) == 1 && strncmp(key, DOT, 1) == 0) {
        return context;
    }

    switch (rb_type(context)) {
        case T_HASH: {
            VALUE key_str = rb_str_new_cstr(key);
            if (RTEST(rb_funcall(context, id_key_p, 1, key_str))) {
                return rb_hash_aref(context, key_str);
            } else {
                VALUE sym = ID2SYM(rb_intern(key));
                if (RTEST(rb_funcall(context, id_key_p, 1, sym))) {
                    return rb_hash_aref(context, sym);
                } else {
                    return Qundef;
                }
            }
        }
        case T_FALSE:
            return Qfalse;
        case T_NIL:
        case T_UNDEF:
            return Qundef;
        default: {
            ID method = rb_intern(key);
            if (rb_respond_to(context, method)) {
                return rb_funcall(context, method, 0);
            } else {
                return Qundef;
            }
        }
    }
}

static VALUE context_fetch(VALUE stack, const char *key) {
    for (long i = RARRAY_LEN(stack) - 1; i >= 0; i--) {
        VALUE context = RARRAY_AREF(stack, i);
        VALUE value = fetch(context, key);
        if (value != Qundef) {
            return value;
        }
    }
    return Qundef;
}

static VALUE fetch_path(VALUE stack, const struct path *path) {
    VALUE value = context_fetch(stack, path->keys[0]);
    for (long i = 1; i < path->length; i++) {
        value = fetch(value, path->keys[i]);
    }
    return value;
}

static void append_value(VALUE buf, VALUE stack, const struct path *path, bool escape) {
    VALUE value = fetch_path(stack, path);
    switch (rb_type(value)) {
        case T_NIL:
        case T_UNDEF:
            return;
        case T_STRING:
            break;
        default:
            value = rb_funcall(value, id_to_s, 0);
            break;
    }
    rb_str_buf_append(buf, escape ? optimized_escape_html(value) : value);
}

static void section(VALUE buf, VALUE stack, const struct path *path, void (*block)(VALUE, VALUE)) {
    VALUE value = fetch_path(stack, path);
    switch (rb_type(value)) {
        case T_ARRAY:
            for (long i = 0; i < RARRAY_LEN(value); i++) {
                rb_ary_push(stack, RARRAY_AREF(value, i));
                block(buf, stack);
                rb_ary_pop(stack);
            }
            break;
        case T_NIL:
        case T_UNDEF:
        case T_FALSE:
            break;
        case T_TRUE:
            block(buf, stack);
            break;
        default:
            rb_ary_push(stack, value);
            block(buf, stack);
            rb_ary_pop(stack);
            break;
    }
}

static void inverted(VALUE buf, VALUE stack, const struct path *path, void (*block)(VALUE, VALUE)) {
    VALUE value = fetch_path(stack, path);
    switch (rb_type(value)) {
        case T_ARRAY:
            if (RARRAY_LEN(value) == 0) {
                block(buf, stack);
            }
            break;
        case T_NIL:
        case T_UNDEF:
        case T_FALSE:
            block(buf, stack);
            break;
    }
}

static VALUE render(VALUE self, VALUE name, VALUE context);
static void initialize();

void Init_stache() {
    VALUE Stache = rb_define_module("Stache");
    VALUE Templates = rb_define_class_under(Stache, "Templates", rb_cObject);
    rb_define_singleton_method(Templates, "render", render, 2);

    rb_require("cgi");
    id_key_p = rb_intern("key?");
    id_to_s = rb_intern("to_s");
    initialize();
}
"#;
<|endoftext|>


<commit_before>//! Defines the `TimeManager` trait.

use uci::SetOption;
use hash_table::Variation;
use search::*;

/// Describes the remaining time on the clocks.
#[derive(Clone, Debug)]
pub struct RemainingTime {
    /// The remaining time in milliseconds for white.
    pub white_millis: u64,

    /// The remaining time in milliseconds for black.
    pub black_millis: u64,

    /// The number of milliseconds with which white's remaining time
    /// is incremented on each move.
    pub winc_millis: u64,

    /// The number of milliseconds with which black's remaining time
    /// is incremented on each move.
    pub binc_millis: u64,

    /// The number of moves to the next time control.
    ///
    /// Can not be zero.
    pub movestogo: Option<u64>,
}

/// A trait for deciding when the search must be terminated and the
/// best move played.
pub trait TimeManager<T: DeepeningSearch<ReportData = Vec<Variation>>>
    : SetOption {
    /// Creates a new instance.
    ///
    /// * `position` gives the current position.
    ///
    /// * `time` gives the remaining time on the clocks.
    fn new(position: &T::SearchNode, time: &RemainingTime) -> Self;

    /// Returns `true` if the search must be terminated and the best
    /// move played.
    ///
    /// * `search_instance` is a mutable reference to the managed
    ///   search instance. The time manager should be careful when
    ///   calling methods on the managed search instance, so as not to
    ///   disturb its normal working. In particular, `start_search`
    ///   and `try_recv_report` methods must not be called, and a
    ///   `"TERMINATE"` message must not be sent.
    ///
    /// * `report`, when supplied, gives a reference to an incoming
    ///   search progress report. `must_play` will be called exactly
    ///   once for each progress report generated by the search,
    ///   following the order in which the reports have been
    ///   generated.
    fn must_play(&mut self,
                 search_instance: &mut T,
                 report: Option<&SearchReport<Vec<Variation>>>)
                 -> bool;
}
<commit_msg>Revert "improve docs"<commit_after>//! Defines the `TimeManager` trait.

use uci::SetOption;
use hash_table::Variation;
use search::*;

/// Describes the remaining time on the clocks.
#[derive(Clone, Debug)]
pub struct RemainingTime {
    /// The remaining time in milliseconds for white.
    pub white_millis: u64,

    /// The remaining time in milliseconds for black.
    pub black_millis: u64,

    /// The number of milliseconds with which white's remaining time
    /// is incremented on each move.
    pub winc_millis: u64,

    /// The number of milliseconds with which black's remaining time
    /// is incremented on each move.
    pub binc_millis: u64,

    /// The number of moves to the next time control.
    ///
    /// Can not be zero.
    pub movestogo: Option<u64>,
}

/// A trait for deciding when the search must be terminated and the
/// best move played.
pub trait TimeManager<T: DeepeningSearch<ReportData = Vec<Variation>>>
    : SetOption {
    /// Creates a new instance.
    ///
    /// * `position` gives the current position.
    ///
    /// * `time` gives the remaining time on the clocks.
    fn new(position: &T::SearchNode, time: &RemainingTime) -> Self;

    /// Returns `true` if the search must be terminated and the best
    /// move played.
    ///
    /// * `search_instance` is a mutable reference to the running
    ///   search instance. The time manager should be careful when
    ///   calling methods on the currently running search instance, so
    ///   as not to disturb its normal working. In particular,
    ///   `start_search` and `try_recv_report` methods must not be
    ///   called, and a `"TERMINATE"` message must not be sent.
    ///
    /// * `report`, when supplied, gives a reference to an incoming
    ///   search progress report. `must_play` will be called exactly
    ///   once for each progress report generated by the search,
    ///   following the order in which the reports have been
    ///   generated.
    fn must_play(&mut self,
                 search_instance: &mut T,
                 report: Option<&SearchReport<Vec<Variation>>>)
                 -> bool;
}
<|endoftext|>