<commit_before>extern crate tempfile;

use std::fmt::{ Display, Formatter, Error };
use std::iter::Iterator;
use std::collections::HashMap;
use std::vec::Vec;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

use std::clone::Clone;

/**
 * test can be deleted.
 * clauses will house all clauses, key is int so that we can use occurrences
 * ID for simplifications later
 * occurrences tracks which clauses literals are used in
 */
#[derive(Debug)]
pub struct CNF {
    nvar        : i32,
    nclause     : i32,
    clauses     : HashMap<i32, Vec<i32>>,
    occurrences : HashMap<i32, Vec<i32>>
}

impl CNF {
    pub fn new(nvar: i32, nclause: i32) -> CNF {
        CNF {
            nvar        : nvar,
            nclause     : nclause,
            clauses     : HashMap::new(),
            occurrences : HashMap::new()
        }
    }

    // Add a clause, return the ID of the inserted clause
    fn add_clause(&mut self, clause : Vec<i32>) -> i32 {
        let id : i32 = self.clauses.len() as i32;
        for var in &clause {
            let occ = self.occurrences.entry(*var).or_insert(Vec::new());
            occ.push(id);
        }
        self.clauses.insert(id, clause);
        id
    }

    pub fn to_string(self) -> String {
        format!("Nvar: {:?} Nclause: {:?}\nClauses: {:?}\nOccurrrences: {:?}",
                self.nvar, self.nclause,
                self.clauses, self.occurrences)
    }
}

impl Clone for CNF {
    fn clone(&self) -> CNF {
        CNF {
            nvar : self.nvar,
            nclause : self.nclause,
            clauses : self.clauses.clone(),
            occurrences : self.occurrences.clone(),
        }
    }
}

impl Display for CNF {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let mut comma_separated = String::new();
        comma_separated.push_str("Need to implement formatter");
        write!(f, "{}", comma_separated)
    }
}

// End CNF

// Begin Parsing

#[derive(Debug)]
pub enum SatError {
    InvalidSyntax,
    InvalidProblem
}

fn parse_dimacs(reader: &mut BufReader<File>) -> Result<CNF, SatError> {
    let mut line_iterator = reader.lines();

    let mut nvar: i32 = -1;
    let mut nclause: i32 = -1;
    // DIMACS file must have a problem statement before other lines.
    // This first loop searches for the problem statement.
    for line in &mut line_iterator {
        let line = line.expect("Could not read file");  // Unwrap result
        let words: Vec<&str> = line.split_whitespace().collect();
        match words[0] {
            "c" => { }
            "p" => { // Problem statement
                // Must have format "p cnf nvar nclause"
                if words.len() != 4 || words[1] != "cnf" {
                    return Err(SatError::InvalidSyntax);
                }
                nvar = words[2].parse()
                    .expect(&format!("Invalid number of variables {}", words[2]));
                nclause = words[3].parse()
                    .expect(&format!("Invalid number of clauses {}", words[3]));
                break;
            }
            _ => { return Err(SatError::InvalidSyntax); }
        }
    }
    // Then nvar, nclause were never initialized
    if nvar == -1 || nclause == -1 {
       return Err(SatError::InvalidProblem);
    }
    // TODO: Different errors for different descriptions (hence why I've split up this if
    // statement)
    if nvar == 0 || nclause == 0 {
        return Err(SatError::InvalidProblem)
    }

    // Initialize CNF and parse the rest of the file
    let mut cnf = CNF::new(nvar, nclause);
    for line in &mut line_iterator {
        let line = line.expect("Could not read filce");
        let words: Vec<&str> = line.split_whitespace().collect();
        match words[0] {
            "c" => { }
            _   => {
                let tokens: Vec<i32> = words.iter()
                    .filter_map(|s| {
                        let n = s.parse::<i32>().expect("Invalid DIMACS File");
                        // FIXME: This ignores zeros not just as line enders but in the formulas
                        // themselves. TODO: Split on zeros at the end here.
                        if n == 0 { return None; }
                        if n > nvar { panic!(format!("Variable out of range: {}", n)); }
                        Some(if n < 0 { (-n) << 1 | 1 } else { n << 1 })
                    })
                    .collect();
                cnf.add_clause(tokens);
            }
        }
    }
    Ok(cnf)
}

pub fn parse_dimacs_file(f: File) -> Result<CNF, SatError> {
    // Read the file
    let mut reader = BufReader::new(f);

    // TODO: This is definitely not the correct way to handle errors.
    // Should parse_dimacs have options for returning an error AND panicking?
    let line = parse_dimacs(&mut reader);
    line
}

#[cfg(test)]
mod tests {
	extern crate tempfile;
	use std::fs::File;
	use std::io::{Write, Seek, SeekFrom};

    use super::parse_dimacs_file;

    macro_rules! create_tempfile {
        ($x: expr) => {{
            let mut tmpfile: File = tempfile::tempfile().unwrap();
            let _ = write!(tmpfile, $x);
            tmpfile.seek(SeekFrom::Start(0)).unwrap();

            tmpfile
        }};
    }

    #[test]
    #[should_panic]
    fn variable_out_of_range() {
        let tmpfile = create_tempfile!("
            p cnf 2 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }
}
<commit_msg>Improved error handling and added tests<commit_after>extern crate tempfile;

use std::fmt::{ Display, Formatter, Error };
use std::iter::Iterator;
use std::collections::HashMap;
use std::vec::Vec;
use std::io::prelude::*;
use std::io::BufReader;
use std::fs::File;

use std::clone::Clone;

/**
 * test can be deleted.
 * clauses will house all clauses, key is int so that we can use occurrences
 * ID for simplifications later
 * occurrences tracks which clauses literals are used in
 */
#[derive(Debug)]
pub struct CNF {
    nvar        : i32,
    nclause     : i32,
    clauses     : HashMap<i32, Vec<i32>>,
    occurrences : HashMap<i32, Vec<i32>>
}

impl CNF {
    pub fn new(nvar: i32, nclause: i32) -> CNF {
        CNF {
            nvar        : nvar,
            nclause     : nclause,
            clauses     : HashMap::new(),
            occurrences : HashMap::new()
        }
    }

    // Add a clause, return the ID of the inserted clause
    fn add_clause(&mut self, clause : Vec<i32>) -> i32 {
        let id : i32 = self.clauses.len() as i32;
        for var in &clause {
            let occ = self.occurrences.entry(*var).or_insert(Vec::new());
            occ.push(id);
        }
        self.clauses.insert(id, clause);
        id
    }

    pub fn to_string(self) -> String {
        format!("Nvar: {:?} Nclause: {:?}\nClauses: {:?}\nOccurrrences: {:?}",
                self.nvar, self.nclause,
                self.clauses, self.occurrences)
    }
}

impl Clone for CNF {
    fn clone(&self) -> CNF {
        CNF {
            nvar : self.nvar,
            nclause : self.nclause,
            clauses : self.clauses.clone(),
            occurrences : self.occurrences.clone(),
        }
    }
}

impl Display for CNF {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        let mut comma_separated = String::new();
        comma_separated.push_str("Need to implement formatter");
        write!(f, "{}", comma_separated)
    }
}

// End CNF

// Begin Parsing

fn parse_dimacs(reader: &mut BufReader<File>) -> Result<CNF, &'static str> {
    let mut line_iterator = reader.lines();

    let mut nvar: i32 = -1;
    let mut nclause: i32 = -1;
    // DIMACS file must have a problem statement before other lines.
    // This first loop searches for the problem statement.
    for line in &mut line_iterator {
        let line = line.expect("could not read file");  // Unwrap result
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; } // Ignore empty lines
        match words[0] {
            "c" => { }
            "p" => { // Problem statement
                // Must have format "p cnf nvar nclause"
                if words.len() != 4 || words[1] != "cnf" {
                    return Err("invalid problem statement");
                }
                nvar = words[2].parse()
                    .expect(&format!("invalid number of variables {}", words[2]));
                nclause = words[3].parse()
                    .expect(&format!("invalid number of clauses {}", words[3]));
                break;
            }
            // TODO: Add words[0] to this error message
            _ => { return Err("unknown statement beginning"); }
        }
    }
    // Then nvar, nclause were never initialized
    if nvar == -1 || nclause == -1 {
       return Err("no problem statement found");
    }
    // TODO: Different errors for different descriptions (hence why I've split up this if
    // statement)
    if nvar == 0 || nclause == 0 {
        return Err("invalid number of literals in problem")
    }

    // Initialize CNF and parse the rest of the file
    let mut cnf = CNF::new(nvar, nclause);
    let mut clauses_read: i32 = 0;
    for line in &mut line_iterator {
        let line = line.unwrap();
        let words: Vec<&str> = line.split_whitespace().collect();
        if words.len() == 0 { continue; }
        match words[0] {
            "c" => { }
            "p" => { return Err("duplicate problem statement"); }
            _   => {
                clauses_read = clauses_read + 1;
                if clauses_read > nclause { return Err("too many clauses in file"); }
                let tokens: Vec<i32> = words.iter()
                    .filter_map(|s| {
                        let n = s.parse::<i32>().unwrap();
                        // FIXME: This ignores zeros not just as line enders but in the formulas
                        // themselves. Split on zeros at the end here.
                        if n == 0 { return None; }
                        // FIXME: This should return an error instead of
                        // panicking, but I can't return an error
                        // in a closure
                        if n > nvar { panic!("variable out of range: {}", n); }
                        Some(if n < 0 { (-n) << 1 | 1 } else { n << 1 })
                    })
                    .collect();
                cnf.add_clause(tokens);
            }
        }
    }
    // Double check that the number of clauses read is equal
    if clauses_read != nclause { return Err("too few clauses in file"); }
    Ok(cnf)
}

pub fn parse_dimacs_file(f: File) -> Result<CNF, &'static str> {
    // Read the file
    let mut reader = BufReader::new(f);

    // TODO: This is definitely not the correct way to handle errors.
    // Should parse_dimacs have options for returning an error AND panicking?
    let line = parse_dimacs(&mut reader);
    line
}

#[cfg(test)]
mod tests {
	extern crate tempfile;
	use std::fs::File;
	use std::io::prelude::*;
	use std::io::SeekFrom;

    use super::parse_dimacs_file;

    macro_rules! create_tempfile {
        ($x: expr) => {{
            let mut tmpfile: File = tempfile::tempfile().unwrap();
            let _ = write!(tmpfile, $x);
            tmpfile.seek(SeekFrom::Start(0)).unwrap();

            tmpfile
        }};
    }

    #[test]
    #[should_panic(expected = "out of range")]
    fn variable_out_of_range() {
        let tmpfile = create_tempfile!("
            p cnf 2 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nvar() {
        let tmpfile = create_tempfile!("
            p cnf gd 3
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "invalid number")]
    fn invalid_nclause() {
        let tmpfile = create_tempfile!("
            p cnf 2 gdd
            1 2 0
            4 1 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too many")]
    fn too_many_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
            4 5 0
            1 3 0
            2 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "too few")]
    fn too_little_clauses() {
        let tmpfile = create_tempfile!("
            p cnf 5 5
            1 2 0
            2 3 0
            3 4 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_work() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    fn should_ignore_comments() {
        let tmpfile = create_tempfile!("
            c comment
            p cnf 3 3
            c comment
            1 2 0
            2 3 0
            c comment
            1 -3 0
            c comment
            c comment
            c comment
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            1 2 0
            p cnf 3 3
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }

    #[test]
    #[should_panic(expected = "duplicate problem")]
    fn duplicate_problem_statement_2() {
        let tmpfile = create_tempfile!("
            p cnf 3 3
            p cnf 3 3
            1 2 0
            2 3 0
            1 -3 0
        ");
        let _ = parse_dimacs_file(tmpfile).unwrap();
    }
}
<|endoftext|>


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

use crate::{
    sparse_merkle::{
        node::{InternalNode, Node, NodeHandle},
        utils::{partition, swap_if, Either},
        UpdateError,
    },
    ProofRead,
};
use diem_crypto::{
    hash::{CryptoHash, SPARSE_MERKLE_PLACEHOLDER_HASH},
    HashValue,
};
use diem_types::proof::{SparseMerkleLeafNode, SparseMerkleProof};
use std::{borrow::Borrow, cmp::Ordering};

type Result<T> = std::result::Result<T, UpdateError>;

type InMemSubTree<V> = super::node::SubTree<V>;
type InMemInternal<V> = super::node::InternalNode<V>;

#[derive(Clone)]
enum InMemSubTreeInfo<V> {
    Internal {
        subtree: InMemSubTree<V>,
        // TODO(aldenhu): make it lazy (going up)
        node: InMemInternal<V>,
    },
    Leaf {
        subtree: InMemSubTree<V>,
        key: HashValue,
    },
    Unknown {
        subtree: InMemSubTree<V>,
    },
    Empty,
}

impl<V: Clone + CryptoHash> InMemSubTreeInfo<V> {
    fn create_leaf_with_update(update: (HashValue, &V)) -> Self {
        let subtree = InMemSubTree::new_leaf_with_value(update.0, (*update.1).clone());
        Self::Leaf {
            key: update.0,
            subtree,
        }
    }

    fn create_leaf_with_proof(leaf: &SparseMerkleLeafNode) -> Self {
        let subtree = InMemSubTree::new_leaf_with_value_hash(leaf.key(), leaf.value_hash());
        Self::Leaf {
            key: leaf.key(),
            subtree,
        }
    }

    fn create_internal(left: Self, right: Self) -> Self {
        let node = InternalNode {
            left: left.into_subtree(),
            right: right.into_subtree(),
        };
        let subtree = InMemSubTree::NonEmpty {
            hash: node.calc_hash(),
            root: NodeHandle::new_shared(Node::Internal(node.clone())),
        };

        Self::Internal { subtree, node }
    }

    fn create_unknown(hash: HashValue) -> Self {
        Self::Unknown {
            subtree: InMemSubTree::new_unknown(hash),
        }
    }

    fn into_subtree(self) -> InMemSubTree<V> {
        match self {
            Self::Leaf { subtree, .. } => subtree,
            Self::Internal { subtree, .. } => subtree,
            Self::Unknown { subtree } => subtree,
            Self::Empty => InMemSubTree::Empty,
        }
    }

    fn combine(left: Self, right: Self) -> Self {
        // If there's a only leaf in the subtree,
        // rollup the leaf, otherwise create an internal node.
        match (&left, &right) {
            (Self::Empty, Self::Leaf { .. }) => right,
            (Self::Leaf { .. }, Self::Empty) => left,
            (Self::Empty, Self::Empty) => unreachable!(),
            _ => InMemSubTreeInfo::create_internal(left, right),
        }
    }
}

#[derive(Clone)]
enum PersistedSubTreeInfo<'a, V> {
    ProofPathInternal { proof: &'a SparseMerkleProof<V> },
    ProofSibling { hash: HashValue },
    Leaf { leaf: SparseMerkleLeafNode },
}

#[derive(Clone)]
enum SubTreeInfo<'a, V> {
    InMem(InMemSubTreeInfo<V>),
    Persisted(PersistedSubTreeInfo<'a, V>),
}

impl<'a, V: Clone + CryptoHash> SubTreeInfo<'a, V> {
    fn new_empty() -> Self {
        Self::InMem(InMemSubTreeInfo::Empty)
    }

    fn new_proof_leaf(leaf: SparseMerkleLeafNode) -> Self {
        Self::Persisted(PersistedSubTreeInfo::Leaf { leaf })
    }

    fn new_proof_sibling(hash: HashValue) -> Self {
        if hash == *SPARSE_MERKLE_PLACEHOLDER_HASH {
            Self::InMem(InMemSubTreeInfo::Empty)
        } else {
            Self::Persisted(PersistedSubTreeInfo::ProofSibling { hash })
        }
    }

    fn new_on_proof_path(proof: &'a SparseMerkleProof<V>, depth: usize) -> Self {
        match proof.siblings().len().cmp(&depth) {
            Ordering::Greater => Self::Persisted(PersistedSubTreeInfo::ProofPathInternal { proof }),
            Ordering::Equal => match proof.leaf() {
                Some(leaf) => Self::new_proof_leaf(leaf),
                None => Self::new_empty(),
            },
            _ => unreachable!(),
        }
    }

    fn from_persisted(
        a_descendant_key: HashValue,
        depth: usize,
        proof_reader: &'a impl ProofRead<V>,
    ) -> Result<Self> {
        let proof = proof_reader
            .get_proof(a_descendant_key)
            .ok_or(UpdateError::MissingProof)?;
        if depth > proof.siblings().len() {
            return Err(UpdateError::ShortProof {
                key: a_descendant_key,
                num_siblings: proof.siblings().len(),
                depth,
            });
        }
        Ok(Self::new_on_proof_path(proof, depth))
    }

    fn from_in_mem(subtree: &InMemSubTree<V>) -> Self {
        match &subtree {
            InMemSubTree::Empty => SubTreeInfo::new_empty(),
            InMemSubTree::NonEmpty { root, .. } => match root.get_node_if_in_mem() {
                Some(arc_node) => match arc_node.borrow() {
                    Node::Internal(node) => SubTreeInfo::InMem(InMemSubTreeInfo::Internal {
                        node: (*node).clone(),
                        subtree: subtree.weak(),
                    }),
                    Node::Leaf(node) => SubTreeInfo::InMem(InMemSubTreeInfo::Leaf {
                        key: node.key,
                        subtree: subtree.weak(),
                    }),
                },
                None => SubTreeInfo::InMem(InMemSubTreeInfo::Unknown {
                    subtree: subtree.weak(),
                }),
            },
        }
    }

    fn is_unknown(&self) -> bool {
        matches!(self, Self::InMem(InMemSubTreeInfo::Unknown { .. }))
            || matches!(
                self,
                Self::Persisted(PersistedSubTreeInfo::ProofSibling { .. })
            )
    }

    fn into_children(
        self,
        a_descendent_key: HashValue,
        depth: usize,
        proof_reader: &'a impl ProofRead<V>,
    ) -> Result<(Self, Self)> {
        let myself = if self.is_unknown() {
            SubTreeInfo::from_persisted(a_descendent_key, depth, proof_reader)?
        } else {
            self
        };

        Ok(match &myself {
            SubTreeInfo::InMem(info) => match info {
                InMemSubTreeInfo::Empty => (Self::new_empty(), Self::new_empty()),
                InMemSubTreeInfo::Leaf { key, .. } => {
                    let key = *key;
                    swap_if(myself, SubTreeInfo::new_empty(), key.bit(depth))
                }
                InMemSubTreeInfo::Internal { node, .. } => (
                    SubTreeInfo::from_in_mem(&node.left),
                    SubTreeInfo::from_in_mem(&node.right),
                ),
                InMemSubTreeInfo::Unknown { .. } => unreachable!(),
            },
            SubTreeInfo::Persisted(info) => match info {
                PersistedSubTreeInfo::Leaf { leaf } => {
                    let key = leaf.key();
                    swap_if(myself, SubTreeInfo::new_empty(), key.bit(depth))
                }
                PersistedSubTreeInfo::ProofPathInternal { proof } => {
                    let siblings = proof.siblings();
                    assert!(siblings.len() > depth);
                    let sibling_child =
                        SubTreeInfo::new_proof_sibling(siblings[siblings.len() - depth - 1]);
                    let on_path_child = SubTreeInfo::new_on_proof_path(proof, depth + 1);
                    swap_if(on_path_child, sibling_child, a_descendent_key.bit(depth))
                }
                PersistedSubTreeInfo::ProofSibling { .. } => unreachable!(),
            },
        })
    }

    fn materialize(self) -> InMemSubTreeInfo<V> {
        match self {
            Self::InMem(info) => info,
            Self::Persisted(info) => match info {
                PersistedSubTreeInfo::Leaf { leaf } => {
                    InMemSubTreeInfo::create_leaf_with_proof(&leaf)
                }
                PersistedSubTreeInfo::ProofSibling { hash } => {
                    InMemSubTreeInfo::create_unknown(hash)
                }
                PersistedSubTreeInfo::ProofPathInternal { .. } => {
                    unreachable!()
                }
            },
        }
    }
}

pub struct SubTreeUpdater<'a, V> {
    depth: usize,
    info: SubTreeInfo<'a, V>,
    updates: &'a [(HashValue, &'a V)],
}

impl<'a, V: Send + Sync + Clone + CryptoHash> SubTreeUpdater<'a, V> {
    pub(crate) fn update(
        root: InMemSubTree<V>,
        updates: &'a [(HashValue, &'a V)],
        proof_reader: &'a impl ProofRead<V>,
    ) -> Result<InMemSubTree<V>> {
        let updater = Self {
            depth: 0,
            info: SubTreeInfo::from_in_mem(&root),
            updates,
        };
        Ok(updater.run(proof_reader)?.into_subtree())
    }

    fn run(self, proof_reader: &impl ProofRead<V>) -> Result<InMemSubTreeInfo<V>> {
        match self.maybe_end_recursion() {
            Either::A(ended) => Ok(ended),
            Either::B(myself) => {
                let (left, right) = myself.into_children(proof_reader)?;
                let (left_ret, right_ret) =
                    rayon::join(|| left.run(proof_reader), || right.run(proof_reader));

                Ok(InMemSubTreeInfo::combine(left_ret?, right_ret?))
            }
        }
    }

    fn maybe_end_recursion(self) -> Either<InMemSubTreeInfo<V>, Self> {
        match self.updates.len() {
            0 => Either::A(self.info.materialize()),
            1 => match &self.info {
                SubTreeInfo::InMem(in_mem_info) => match in_mem_info {
                    InMemSubTreeInfo::Empty => {
                        Either::A(InMemSubTreeInfo::create_leaf_with_update(self.updates[0]))
                    }
                    InMemSubTreeInfo::Leaf { key, .. } => Either::or(
                        *key == self.updates[0].0,
                        InMemSubTreeInfo::create_leaf_with_update(self.updates[0]),
                        self,
                    ),
                    _ => Either::B(self),
                },
                SubTreeInfo::Persisted(PersistedSubTreeInfo::Leaf { leaf }) => Either::or(
                    leaf.key() == self.updates[0].0,
                    InMemSubTreeInfo::create_leaf_with_update(self.updates[0]),
                    self,
                ),
                _ => Either::B(self),
            },
            _ => Either::B(self),
        }
    }

    fn into_children(self, proof_reader: &'a impl ProofRead<V>) -> Result<(Self, Self)> {
        let pivot = partition(self.updates, self.depth);
        let (left_updates, right_updates) = self.updates.split_at(pivot);
        let (left_info, right_info) =
            self.info
                .into_children(self.updates[0].0, self.depth, proof_reader)?;

        Ok((
            Self {
                depth: self.depth + 1,
                info: left_info,
                updates: left_updates,
            },
            Self {
                depth: self.depth + 1,
                info: right_info,
                updates: right_updates,
            },
        ))
    }
}
<commit_msg>[scratchpad] limit concurrency for the updater<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    sparse_merkle::{
        node::{InternalNode, Node, NodeHandle},
        utils::{partition, swap_if, Either},
        UpdateError,
    },
    ProofRead,
};
use diem_crypto::{
    hash::{CryptoHash, SPARSE_MERKLE_PLACEHOLDER_HASH},
    HashValue,
};
use diem_types::proof::{SparseMerkleLeafNode, SparseMerkleProof};
use std::{borrow::Borrow, cmp::Ordering};

type Result<T> = std::result::Result<T, UpdateError>;

type InMemSubTree<V> = super::node::SubTree<V>;
type InMemInternal<V> = super::node::InternalNode<V>;

#[derive(Clone)]
enum InMemSubTreeInfo<V> {
    Internal {
        subtree: InMemSubTree<V>,
        // TODO(aldenhu): make it lazy (going up)
        node: InMemInternal<V>,
    },
    Leaf {
        subtree: InMemSubTree<V>,
        key: HashValue,
    },
    Unknown {
        subtree: InMemSubTree<V>,
    },
    Empty,
}

impl<V: Clone + CryptoHash> InMemSubTreeInfo<V> {
    fn create_leaf_with_update(update: (HashValue, &V)) -> Self {
        let subtree = InMemSubTree::new_leaf_with_value(update.0, (*update.1).clone());
        Self::Leaf {
            key: update.0,
            subtree,
        }
    }

    fn create_leaf_with_proof(leaf: &SparseMerkleLeafNode) -> Self {
        let subtree = InMemSubTree::new_leaf_with_value_hash(leaf.key(), leaf.value_hash());
        Self::Leaf {
            key: leaf.key(),
            subtree,
        }
    }

    fn create_internal(left: Self, right: Self) -> Self {
        let node = InternalNode {
            left: left.into_subtree(),
            right: right.into_subtree(),
        };
        let subtree = InMemSubTree::NonEmpty {
            hash: node.calc_hash(),
            root: NodeHandle::new_shared(Node::Internal(node.clone())),
        };

        Self::Internal { subtree, node }
    }

    fn create_unknown(hash: HashValue) -> Self {
        Self::Unknown {
            subtree: InMemSubTree::new_unknown(hash),
        }
    }

    fn into_subtree(self) -> InMemSubTree<V> {
        match self {
            Self::Leaf { subtree, .. } => subtree,
            Self::Internal { subtree, .. } => subtree,
            Self::Unknown { subtree } => subtree,
            Self::Empty => InMemSubTree::Empty,
        }
    }

    fn combine(left: Self, right: Self) -> Self {
        // If there's a only leaf in the subtree,
        // rollup the leaf, otherwise create an internal node.
        match (&left, &right) {
            (Self::Empty, Self::Leaf { .. }) => right,
            (Self::Leaf { .. }, Self::Empty) => left,
            (Self::Empty, Self::Empty) => unreachable!(),
            _ => InMemSubTreeInfo::create_internal(left, right),
        }
    }
}

#[derive(Clone)]
enum PersistedSubTreeInfo<'a, V> {
    ProofPathInternal { proof: &'a SparseMerkleProof<V> },
    ProofSibling { hash: HashValue },
    Leaf { leaf: SparseMerkleLeafNode },
}

#[derive(Clone)]
enum SubTreeInfo<'a, V> {
    InMem(InMemSubTreeInfo<V>),
    Persisted(PersistedSubTreeInfo<'a, V>),
}

impl<'a, V: Clone + CryptoHash> SubTreeInfo<'a, V> {
    fn new_empty() -> Self {
        Self::InMem(InMemSubTreeInfo::Empty)
    }

    fn new_proof_leaf(leaf: SparseMerkleLeafNode) -> Self {
        Self::Persisted(PersistedSubTreeInfo::Leaf { leaf })
    }

    fn new_proof_sibling(hash: HashValue) -> Self {
        if hash == *SPARSE_MERKLE_PLACEHOLDER_HASH {
            Self::InMem(InMemSubTreeInfo::Empty)
        } else {
            Self::Persisted(PersistedSubTreeInfo::ProofSibling { hash })
        }
    }

    fn new_on_proof_path(proof: &'a SparseMerkleProof<V>, depth: usize) -> Self {
        match proof.siblings().len().cmp(&depth) {
            Ordering::Greater => Self::Persisted(PersistedSubTreeInfo::ProofPathInternal { proof }),
            Ordering::Equal => match proof.leaf() {
                Some(leaf) => Self::new_proof_leaf(leaf),
                None => Self::new_empty(),
            },
            _ => unreachable!(),
        }
    }

    fn from_persisted(
        a_descendant_key: HashValue,
        depth: usize,
        proof_reader: &'a impl ProofRead<V>,
    ) -> Result<Self> {
        let proof = proof_reader
            .get_proof(a_descendant_key)
            .ok_or(UpdateError::MissingProof)?;
        if depth > proof.siblings().len() {
            return Err(UpdateError::ShortProof {
                key: a_descendant_key,
                num_siblings: proof.siblings().len(),
                depth,
            });
        }
        Ok(Self::new_on_proof_path(proof, depth))
    }

    fn from_in_mem(subtree: &InMemSubTree<V>) -> Self {
        match &subtree {
            InMemSubTree::Empty => SubTreeInfo::new_empty(),
            InMemSubTree::NonEmpty { root, .. } => match root.get_node_if_in_mem() {
                Some(arc_node) => match arc_node.borrow() {
                    Node::Internal(node) => SubTreeInfo::InMem(InMemSubTreeInfo::Internal {
                        node: (*node).clone(),
                        subtree: subtree.weak(),
                    }),
                    Node::Leaf(node) => SubTreeInfo::InMem(InMemSubTreeInfo::Leaf {
                        key: node.key,
                        subtree: subtree.weak(),
                    }),
                },
                None => SubTreeInfo::InMem(InMemSubTreeInfo::Unknown {
                    subtree: subtree.weak(),
                }),
            },
        }
    }

    fn is_unknown(&self) -> bool {
        matches!(self, Self::InMem(InMemSubTreeInfo::Unknown { .. }))
            || matches!(
                self,
                Self::Persisted(PersistedSubTreeInfo::ProofSibling { .. })
            )
    }

    fn into_children(
        self,
        a_descendent_key: HashValue,
        depth: usize,
        proof_reader: &'a impl ProofRead<V>,
    ) -> Result<(Self, Self)> {
        let myself = if self.is_unknown() {
            SubTreeInfo::from_persisted(a_descendent_key, depth, proof_reader)?
        } else {
            self
        };

        Ok(match &myself {
            SubTreeInfo::InMem(info) => match info {
                InMemSubTreeInfo::Empty => (Self::new_empty(), Self::new_empty()),
                InMemSubTreeInfo::Leaf { key, .. } => {
                    let key = *key;
                    swap_if(myself, SubTreeInfo::new_empty(), key.bit(depth))
                }
                InMemSubTreeInfo::Internal { node, .. } => (
                    SubTreeInfo::from_in_mem(&node.left),
                    SubTreeInfo::from_in_mem(&node.right),
                ),
                InMemSubTreeInfo::Unknown { .. } => unreachable!(),
            },
            SubTreeInfo::Persisted(info) => match info {
                PersistedSubTreeInfo::Leaf { leaf } => {
                    let key = leaf.key();
                    swap_if(myself, SubTreeInfo::new_empty(), key.bit(depth))
                }
                PersistedSubTreeInfo::ProofPathInternal { proof } => {
                    let siblings = proof.siblings();
                    assert!(siblings.len() > depth);
                    let sibling_child =
                        SubTreeInfo::new_proof_sibling(siblings[siblings.len() - depth - 1]);
                    let on_path_child = SubTreeInfo::new_on_proof_path(proof, depth + 1);
                    swap_if(on_path_child, sibling_child, a_descendent_key.bit(depth))
                }
                PersistedSubTreeInfo::ProofSibling { .. } => unreachable!(),
            },
        })
    }

    fn materialize(self) -> InMemSubTreeInfo<V> {
        match self {
            Self::InMem(info) => info,
            Self::Persisted(info) => match info {
                PersistedSubTreeInfo::Leaf { leaf } => {
                    InMemSubTreeInfo::create_leaf_with_proof(&leaf)
                }
                PersistedSubTreeInfo::ProofSibling { hash } => {
                    InMemSubTreeInfo::create_unknown(hash)
                }
                PersistedSubTreeInfo::ProofPathInternal { .. } => {
                    unreachable!()
                }
            },
        }
    }
}

pub struct SubTreeUpdater<'a, V> {
    depth: usize,
    info: SubTreeInfo<'a, V>,
    updates: &'a [(HashValue, &'a V)],
}

impl<'a, V: Send + Sync + Clone + CryptoHash> SubTreeUpdater<'a, V> {
    pub(crate) fn update(
        root: InMemSubTree<V>,
        updates: &'a [(HashValue, &'a V)],
        proof_reader: &'a impl ProofRead<V>,
    ) -> Result<InMemSubTree<V>> {
        let updater = Self {
            depth: 0,
            info: SubTreeInfo::from_in_mem(&root),
            updates,
        };
        Ok(updater.run(proof_reader)?.into_subtree())
    }

    fn run(self, proof_reader: &impl ProofRead<V>) -> Result<InMemSubTreeInfo<V>> {
        // Limit total tasks that are potentially sent to other threads.
        const MAX_PARALLELIZABLE_DEPTH: usize = 8;
        // No point to introduce Rayon overhead if work is small.
        const MIN_PARALLELIZABLE_SIZE: usize = 2;

        let depth = self.depth;
        match self.maybe_end_recursion() {
            Either::A(ended) => Ok(ended),
            Either::B(myself) => {
                let (left, right) = myself.into_children(proof_reader)?;
                let (left_ret, right_ret) = if depth <= MAX_PARALLELIZABLE_DEPTH
                    && left.updates.len() >= MIN_PARALLELIZABLE_SIZE
                    && right.updates.len() >= MIN_PARALLELIZABLE_SIZE
                {
                    rayon::join(|| left.run(proof_reader), || right.run(proof_reader))
                } else {
                    (left.run(proof_reader), right.run(proof_reader))
                };

                Ok(InMemSubTreeInfo::combine(left_ret?, right_ret?))
            }
        }
    }

    fn maybe_end_recursion(self) -> Either<InMemSubTreeInfo<V>, Self> {
        match self.updates.len() {
            0 => Either::A(self.info.materialize()),
            1 => match &self.info {
                SubTreeInfo::InMem(in_mem_info) => match in_mem_info {
                    InMemSubTreeInfo::Empty => {
                        Either::A(InMemSubTreeInfo::create_leaf_with_update(self.updates[0]))
                    }
                    InMemSubTreeInfo::Leaf { key, .. } => Either::or(
                        *key == self.updates[0].0,
                        InMemSubTreeInfo::create_leaf_with_update(self.updates[0]),
                        self,
                    ),
                    _ => Either::B(self),
                },
                SubTreeInfo::Persisted(PersistedSubTreeInfo::Leaf { leaf }) => Either::or(
                    leaf.key() == self.updates[0].0,
                    InMemSubTreeInfo::create_leaf_with_update(self.updates[0]),
                    self,
                ),
                _ => Either::B(self),
            },
            _ => Either::B(self),
        }
    }

    fn into_children(self, proof_reader: &'a impl ProofRead<V>) -> Result<(Self, Self)> {
        let pivot = partition(self.updates, self.depth);
        let (left_updates, right_updates) = self.updates.split_at(pivot);
        let (left_info, right_info) =
            self.info
                .into_children(self.updates[0].0, self.depth, proof_reader)?;

        Ok((
            Self {
                depth: self.depth + 1,
                info: left_info,
                updates: left_updates,
            },
            Self {
                depth: self.depth + 1,
                info: right_info,
                updates: right_updates,
            },
        ))
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
// Copyright 2013 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The dirichlet distribution.

use rand::Rng;
use crate::Distribution;
use crate::gamma::Gamma;

/// The dirichelet distribution `Dirichlet(alpha)`.
///
/// The Dirichlet distribution is a family of continuous multivariate
/// probability distributions parameterized by a vector alpha of positive reals.
/// It is a multivariate generalization of the beta distribution.
///
/// # Example
///
/// ```
/// use rand::prelude::*;
/// use rand_distr::Dirichlet;
///
/// let dirichlet = Dirichlet::new(vec![1.0, 2.0, 3.0]).unwrap();
/// let samples = dirichlet.sample(&mut rand::thread_rng());
/// println!("{:?} is from a Dirichlet([1.0, 2.0, 3.0]) distribution", samples);
/// ```
#[derive(Clone, Debug)]
pub struct Dirichlet {
    /// Concentration parameters (alpha)
    alpha: Vec<f64>,
}

/// Error type returned from `Dirchlet::new`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
    /// `alpha.len() < 2`.
    AlphaTooShort,
    /// `alpha <= 0.0` or `nan`.
    AlphaTooSmall,
    /// `size < 2`.
    SizeTooSmall,
}

impl Dirichlet {
    /// Construct a new `Dirichlet` with the given alpha parameter `alpha`.
    ///
    /// Requires `alpha.len() >= 2`.
    #[inline]
    pub fn new<V: Into<Vec<f64>>>(alpha: V) -> Result<Dirichlet, Error> {
        let a = alpha.into();
        if a.len() < 2 {
            return Err(Error::AlphaTooShort);
        }
        for i in 0..a.len() {
            if !(a[i] > 0.0) {
                return Err(Error::AlphaTooSmall);
            }
        }

        Ok(Dirichlet { alpha: a })
    }

    /// Construct a new `Dirichlet` with the given shape parameter `alpha` and `size`.
    ///
    /// Requires `size >= 2`.
    #[inline]
    pub fn new_with_param(alpha: f64, size: usize) -> Result<Dirichlet, Error> {
        if !(alpha > 0.0) {
            return Err(Error::AlphaTooSmall);
        }
        if size < 2 {
            return Err(Error::SizeTooSmall);
        }
        Ok(Dirichlet {
            alpha: vec![alpha; size],
        })
    }
}

impl Distribution<Vec<f64>> for Dirichlet {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec<f64> {
        let n = self.alpha.len();
        let mut samples = vec![0.0f64; n];
        let mut sum = 0.0f64;

        for i in 0..n {
            let g = Gamma::new(self.alpha[i], 1.0).unwrap();
            samples[i] = g.sample(rng);
            sum += samples[i];
        }
        let invacc = 1.0 / sum;
        for i in 0..n {
            samples[i] *= invacc;
        }
        samples
    }
}

#[cfg(test)]
mod test {
    use super::Dirichlet;
    use crate::Distribution;

    #[test]
    fn test_dirichlet() {
        let d = Dirichlet::new(vec![1.0, 2.0, 3.0]).unwrap();
        let mut rng = crate::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    fn test_dirichlet_with_param() {
        let alpha = 0.5f64;
        let size = 2;
        let d = Dirichlet::new_with_param(alpha, size).unwrap();
        let mut rng = crate::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_length() {
        Dirichlet::new_with_param(0.5f64, 1).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_alpha() {
        Dirichlet::new_with_param(0.0f64, 2).unwrap();
    }
}
<commit_msg>rand_distr::Dirichlet: rename constructor<commit_after>// Copyright 2018 Developers of the Rand project.
// Copyright 2013 The Rust Project Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The dirichlet distribution.

use rand::Rng;
use crate::Distribution;
use crate::gamma::Gamma;

/// The dirichelet distribution `Dirichlet(alpha)`.
///
/// The Dirichlet distribution is a family of continuous multivariate
/// probability distributions parameterized by a vector alpha of positive reals.
/// It is a multivariate generalization of the beta distribution.
///
/// # Example
///
/// ```
/// use rand::prelude::*;
/// use rand_distr::Dirichlet;
///
/// let dirichlet = Dirichlet::new(vec![1.0, 2.0, 3.0]).unwrap();
/// let samples = dirichlet.sample(&mut rand::thread_rng());
/// println!("{:?} is from a Dirichlet([1.0, 2.0, 3.0]) distribution", samples);
/// ```
#[derive(Clone, Debug)]
pub struct Dirichlet {
    /// Concentration parameters (alpha)
    alpha: Vec<f64>,
}

/// Error type returned from `Dirchlet::new`.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Error {
    /// `alpha.len() < 2`.
    AlphaTooShort,
    /// `alpha <= 0.0` or `nan`.
    AlphaTooSmall,
    /// `size < 2`.
    SizeTooSmall,
}

impl Dirichlet {
    /// Construct a new `Dirichlet` with the given alpha parameter `alpha`.
    ///
    /// Requires `alpha.len() >= 2`.
    #[inline]
    pub fn new<V: Into<Vec<f64>>>(alpha: V) -> Result<Dirichlet, Error> {
        let a = alpha.into();
        if a.len() < 2 {
            return Err(Error::AlphaTooShort);
        }
        for i in 0..a.len() {
            if !(a[i] > 0.0) {
                return Err(Error::AlphaTooSmall);
            }
        }

        Ok(Dirichlet { alpha: a })
    }

    /// Construct a new `Dirichlet` with the given shape parameter `alpha` and `size`.
    ///
    /// Requires `size >= 2`.
    #[inline]
    pub fn new_with_size(alpha: f64, size: usize) -> Result<Dirichlet, Error> {
        if !(alpha > 0.0) {
            return Err(Error::AlphaTooSmall);
        }
        if size < 2 {
            return Err(Error::SizeTooSmall);
        }
        Ok(Dirichlet {
            alpha: vec![alpha; size],
        })
    }
}

impl Distribution<Vec<f64>> for Dirichlet {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Vec<f64> {
        let n = self.alpha.len();
        let mut samples = vec![0.0f64; n];
        let mut sum = 0.0f64;

        for i in 0..n {
            let g = Gamma::new(self.alpha[i], 1.0).unwrap();
            samples[i] = g.sample(rng);
            sum += samples[i];
        }
        let invacc = 1.0 / sum;
        for i in 0..n {
            samples[i] *= invacc;
        }
        samples
    }
}

#[cfg(test)]
mod test {
    use super::Dirichlet;
    use crate::Distribution;

    #[test]
    fn test_dirichlet() {
        let d = Dirichlet::new(vec![1.0, 2.0, 3.0]).unwrap();
        let mut rng = crate::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    fn test_dirichlet_with_param() {
        let alpha = 0.5f64;
        let size = 2;
        let d = Dirichlet::new_with_size(alpha, size).unwrap();
        let mut rng = crate::test::rng(221);
        let samples = d.sample(&mut rng);
        let _: Vec<f64> = samples
            .into_iter()
            .map(|x| {
                assert!(x > 0.0);
                x
            })
            .collect();
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_length() {
        Dirichlet::new_with_size(0.5f64, 1).unwrap();
    }

    #[test]
    #[should_panic]
    fn test_dirichlet_invalid_alpha() {
        Dirichlet::new_with_size(0.0f64, 2).unwrap();
    }
}
<|endoftext|>


<commit_before>extern mod http;
use http::client::RequestWriter;
use http::method::Get;
use http::headers::HeaderEnum;
use std::str;
use std::rt::io::Reader;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};

fn main() {
    let mut request = ~RequestWriter::new(Get, FromStr::from_str("http://localhost/example")
                                                .expect("Uh oh, that's *really* badly broken!"));
    // Temporary measure, as hostname lookup is not yet supported in std::rt::io.
    request.remote_addr = Some(SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 });
    let mut response = match request.read_response() {
        Ok(response) => response,
        Err(_request) => fail!("This example can progress no further with no response :-("),
    };
    println("Yay! Started to get the response.");
    println!("Status: {}", response.status);
    println("Headers:");
    for header in response.headers.iter() {
        println!(" - {}: {}", header.header_name(), header.header_value());
    }
    print("\n");
    println("First 1024 bytes of response:");
    let mut buf = [0, ..1024];
    match response.read(buf) {
        Some(len) => println!("{}", str::from_utf8(buf.slice_to(len))),
        None => println("uh oh, got None :-("),
    }
    // TODO: read it *all*, correctly
}
<commit_msg>Read entire response in client example.<commit_after>extern mod http;
use http::client::RequestWriter;
use http::method::Get;
use http::headers::HeaderEnum;
use std::str;
use std::rt::io::extensions::ReaderUtil;
use std::rt::io::net::ip::{SocketAddr, Ipv4Addr};

fn main() {
    let mut request = ~RequestWriter::new(Get, FromStr::from_str("http://localhost/example")
                                                .expect("Uh oh, that's *really* badly broken!"));
    // Temporary measure, as hostname lookup is not yet supported in std::rt::io.
    request.remote_addr = Some(SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 8001 });
    let mut response = match request.read_response() {
        Ok(response) => response,
        Err(_request) => fail!("This example can progress no further with no response :-("),
    };
    println("Yay! Started to get the response.");
    println!("Status: {}", response.status);
    println("Headers:");
    for header in response.headers.iter() {
        println!(" - {}: {}", header.header_name(), header.header_value());
    }
    print("\n");
    println("Response:");
    println(str::from_utf8(response.read_to_end()));
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashMap};
use std::path::{Path, PathBuf};
use std::sync::Arc;

use async_oncecell::OnceCell;
use fs::{DirectoryDigest, Permissions, RelativePath};
use futures::TryFutureExt;
use hashing::Digest;
use parking_lot::Mutex;
use store::Store;
use tempfile::TempDir;

use crate::WorkdirSymlink;

async fn rename_readonly_directory(
  src: impl AsRef<Path>,
  dest: impl AsRef<Path>,
  map_rename_err: impl Fn(std::io::Error) -> String,
) -> Result<(), String> {
  // If you try to rename a read-only directory (mode 0o555) under masOS you get permission
  // denied; so we temporarily make the directory writeable by the current process in order to be
  // able to rename it without error.
  #[cfg(target_os = "macos")]
  {
    use std::os::unix::fs::PermissionsExt;
    tokio::fs::set_permissions(&src, std::fs::Permissions::from_mode(0o755))
      .map_err(|e| {
        format!(
          "Failed to prepare {src:?} perms for a rename to {dest:?}: {err}",
          src = src.as_ref(),
          dest = dest.as_ref(),
          err = e
        )
      })
      .await?;
  }
  tokio::fs::rename(&src, &dest)
    .map_err(map_rename_err)
    .await?;
  #[cfg(target_os = "macos")]
  {
    use std::os::unix::fs::PermissionsExt;
    tokio::fs::set_permissions(&dest, std::fs::Permissions::from_mode(0o555))
      .map_err(|e| {
        format!(
          "Failed to seal {dest:?} as read-only: {err}",
          dest = dest.as_ref(),
          err = e
        )
      })
      .await?;
  }
  Ok(())
}

/// Holds Digests materialized into a temporary directory, for symlinking into local sandboxes.
pub struct ImmutableInputs {
  store: Store,
  // The TempDir that digests are materialized in.
  workdir: TempDir,
  // A map from Digest to the location it has been materialized at. The DoubleCheckedCell allows
  // for cooperation between threads attempting to create Digests.
  contents: Mutex<HashMap<Digest, Arc<OnceCell<PathBuf>>>>,
}

impl ImmutableInputs {
  pub fn new(store: Store, base: &Path) -> Result<Self, String> {
    let workdir = tempfile::Builder::new()
      .prefix("immutable_inputs")
      .tempdir_in(base)
      .map_err(|e| {
        format!(
          "Failed to create temporary directory for immutable inputs: {}",
          e
        )
      })?;
    Ok(Self {
      store,
      workdir,
      contents: Mutex::default(),
    })
  }

  /// Returns an absolute Path to immutably consume the given Digest from.
  async fn path(&self, directory_digest: DirectoryDigest) -> Result<PathBuf, String> {
    let digest = directory_digest.as_digest();
    let cell = self.contents.lock().entry(digest).or_default().clone();
    let value = cell
      .get_or_try_init(async {
        let chroot = TempDir::new_in(self.workdir.path()).map_err(|e| {
          format!(
            "Failed to create a temporary directory for materialization of immutable input \
            digest {:?}: {}",
            digest, e
          )
        })?;
        self
          .store
          .materialize_directory(
            chroot.path().to_path_buf(),
            directory_digest,
            Permissions::ReadOnly,
          )
          .await?;
        let src = chroot.into_path();
        let dest = self.workdir.path().join(digest.hash.to_hex());
        rename_readonly_directory(&src, &dest, |e| {
          // TODO(John Sirois): This diagnostic is over the top and should be trimmed down once
          //  we have confidence in the fix. We've had issues with permission denied errors in
          //  the past though; so all this information is in here to root-cause the issue should
          //  it persist.
          let maybe_collision_metadata = std::fs::metadata(&dest);
          let maybe_unwriteable_parent_metadata = dest
            .parent()
            .ok_or(format!(
              "The destination directory for digest {:?} of {:?} has no parent dir.",
              &digest, &dest
            ))
            .map(|p| std::fs::metadata(&p));
          format!(
            "Failed to move materialized immutable input for {digest:?} from {src:?} to \
              {dest:?}: {err}\n\
              Parent directory (un-writeable parent dir?) metadata: {parent_metadata:?}\n\
              Destination directory (collision?) metadata: {existing_metadata:?}\n\
              Current immutable check outs (~dup fingerprints / differing sizes?): {contents:?}
              ",
            digest = digest,
            src = src,
            dest = &dest,
            // If the parent dir is un-writeable, which is unexpected, we will get permission
            // denied on the rename.
            parent_metadata = maybe_unwriteable_parent_metadata,
            // If the destination directory already exists then we have a leaky locking regime or
            // broken materialization failure cleanup.
            existing_metadata = maybe_collision_metadata,
            // Two digests that have different size_bytes but the same fingerprint is a bug in its
            // own right, but would lead to making the same `digest_str` accessible via two
            // different Digest keys here; so display all the keys and values to be able to spot
            // this should it occur.
            contents = self.contents.lock(),
            err = e
          )
        })
        .await?;
        Ok::<_, String>(dest)
      })
      .await?;
    Ok(value.clone())
  }

  ///
  /// Returns symlinks to create for the given set of immutable cache paths.
  ///
  pub(crate) async fn local_paths(
    &self,
    immutable_inputs: &BTreeMap<RelativePath, DirectoryDigest>,
  ) -> Result<Vec<WorkdirSymlink>, String> {
    let dsts = futures::future::try_join_all(
      immutable_inputs
        .values()
        .map(|d| self.path(d.clone()))
        .collect::<Vec<_>>(),
    )
    .await?;

    Ok(
      immutable_inputs
        .keys()
        .zip(dsts.into_iter())
        .map(|(src, dst)| WorkdirSymlink {
          src: src.clone(),
          dst,
        })
        .collect(),
    )
  }
}
<commit_msg>Prevent collisions between attempts to materialize an immutable input digest. (#15652)<commit_after>use std::collections::{BTreeMap, HashMap};
use std::path::{Path, PathBuf};
use std::sync::Arc;

use async_oncecell::OnceCell;
use fs::{DirectoryDigest, Permissions, RelativePath};
use hashing::Digest;
use parking_lot::Mutex;
use store::Store;
use tempfile::TempDir;

use crate::WorkdirSymlink;

/// Holds Digests materialized into a temporary directory, for symlinking into local sandboxes.
pub struct ImmutableInputs {
  store: Store,
  // The TempDir that digests are materialized in.
  workdir: TempDir,
  // A map from Digest to the location it has been materialized at. The OnceCell allows
  // for cooperation between threads attempting to create Digests.
  contents: Mutex<HashMap<Digest, Arc<OnceCell<PathBuf>>>>,
}

impl ImmutableInputs {
  pub fn new(store: Store, base: &Path) -> Result<Self, String> {
    let workdir = tempfile::Builder::new()
      .prefix("immutable_inputs")
      .tempdir_in(base)
      .map_err(|e| {
        format!(
          "Failed to create temporary directory for immutable inputs: {}",
          e
        )
      })?;
    Ok(Self {
      store,
      workdir,
      contents: Mutex::default(),
    })
  }

  /// Returns an absolute Path to immutably consume the given Digest from.
  async fn path(&self, directory_digest: DirectoryDigest) -> Result<PathBuf, String> {
    let digest = directory_digest.as_digest();
    let cell = self.contents.lock().entry(digest).or_default().clone();

    // We (might) need to initialize the value.
    //
    // Because this code executes a side-effect which could be observed elsewhere within this
    // process (other threads can observe the contents of the temporary directory), we need to
    // ensure that if this method is cancelled (via async Drop), whether the cell has been
    // initialized or not stays in sync with whether the side-effect is visible.
    //
    // Making the initialization "cancellation safe", involves either:
    //
    //   1. Adding a Drop guard to "undo" the side-effect if we're dropped before we fully
    //      initialize the cell.
    //       * This is challenging to do correctly in this case, because the `Drop` guard cannot
    //         be created until after initialization begins, but cannot be cleared until after the
    //         cell has been initialized (i.e., after `get_or_try_init` returns).
    //   2. Shielding ourselves from cancellation by `spawn`ing a new Task to guarantee that the
    //      cell initialization always runs to completion.
    //       * This would work, but would mean that we would finish initializing cells even when
    //         work was cancelled. Cancellation usually means that the work is no longer necessary,
    //         and so that could result in a lot of spurious IO (in e.g. warm cache cases which
    //         never end up actually needing any inputs).
    //       * An advanced variant of this approach would be to _pause_ work on materializing a
    //         Digest when demand for it disappeared, and resume the work if another caller
    //         requested that Digest.
    //   3. Using anonymous destination paths, such that multiple attempts to initialize cannot
    //      collide.
    //       * This means that although the side-effect is visible, it can never collide.
    //
    // We take the final approach here currently (for simplicity's sake), but the advanced variant
    // of approach 2 might eventually be worthwhile.
    cell
      .get_or_try_init(async {
        let chroot = TempDir::new_in(self.workdir.path()).map_err(|e| {
          format!(
            "Failed to create a temporary directory for materialization of immutable input \
            digest {:?}: {}",
            digest, e
          )
        })?;

        let dest = chroot.path().join(digest.hash.to_hex());
        self
          .store
          .materialize_directory(dest.clone(), directory_digest, Permissions::ReadOnly)
          .await?;

        // Now that we've successfully initialized the destination, forget the TempDir so that it
        // is not cleaned up.
        let _ = chroot.into_path();

        Ok(dest)
      })
      .await
      .cloned()
  }

  ///
  /// Returns symlinks to create for the given set of immutable cache paths.
  ///
  pub(crate) async fn local_paths(
    &self,
    immutable_inputs: &BTreeMap<RelativePath, DirectoryDigest>,
  ) -> Result<Vec<WorkdirSymlink>, String> {
    let dsts = futures::future::try_join_all(
      immutable_inputs
        .values()
        .map(|d| self.path(d.clone()))
        .collect::<Vec<_>>(),
    )
    .await?;

    Ok(
      immutable_inputs
        .keys()
        .zip(dsts.into_iter())
        .map(|(src, dst)| WorkdirSymlink {
          src: src.clone(),
          dst,
        })
        .collect(),
    )
  }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::iter::FromIterator;

use helpers::HelperDef;
use registry::Registry;
use context::Context;
use render::{Renderable, RenderContext, RenderError, Helper};

#[derive(Clone, Copy)]
pub struct IncludeHelper;

#[derive(Clone, Copy)]
pub struct BlockHelper;

#[derive(Clone, Copy)]
pub struct PartialHelper;

impl HelperDef for IncludeHelper {
    fn call(&self,
            c: &Context,
            h: &Helper,
            r: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let template = match h.params().get(0) {
            Some(ref t) => {
                if let Some(include_path) = t.path() {
                    if rc.current_template == Some(include_path.to_owned()) {
                        return Err(RenderError::new("Cannot include self in >"));
                    } else {
                        r.get_template(&include_path)
                    }
                } else {
                    return Err(RenderError::new("Do not use literal here, use template name \
                                                 directly."));
                }
            }
            None => return Err(RenderError::new("Param not found for helper")),
        };

        let context_param = h.params().get(1).and_then(|p| p.path());
        let old_path = match context_param {
            Some(p) => {
                let old_path = rc.get_path().clone();
                rc.promote_local_vars();
                let new_path = format!("{}/{}", old_path, p);
                rc.set_path(new_path);
                Some(old_path)
            }
            None => None,
        };

        let result = match template {
            Some(t) => {
                if h.hash().is_empty() {
                    t.render(c, r, rc)
                } else {
                    let hash_ctx = BTreeMap::from_iter(h.hash()
                                                        .iter()
                                                        .map(|(k, v)| {
                                                            (k.clone(), v.value().clone())
                                                        }));
                    let new_ctx = c.extend(&hash_ctx);
                    t.render(&new_ctx, r, rc)
                }
            }
            None => Err(RenderError::new("Template not found.")),
        };

        if let Some(path) = old_path {
            rc.set_path(path);
            rc.demote_local_vars();
        }

        result
    }
}

impl HelperDef for BlockHelper {
    fn call(&self,
            c: &Context,
            h: &Helper,
            r: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let param = try!(h.param(0).ok_or_else(|| RenderError::new("Param not found for helper")));

        if let Some(partial_path) = param.path() {
            let partial_template = rc.get_partial(partial_path);

            match partial_template {
                Some(partial_template) => partial_template.render(c, r, rc),
                None => h.template().unwrap().render(c, r, rc),
            }
        } else {
            Err(RenderError::new("Do not use literal here, use template name directly."))
        }
    }
}

impl HelperDef for PartialHelper {
    fn call(&self,
            _: &Context,
            h: &Helper,
            _: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let param = try!(h.param(0).ok_or_else(|| RenderError::new("Param not found for helper")));

        if let Some(partial_path) = param.path() {
            rc.set_partial(partial_path.to_owned(), h.template().unwrap().clone());
        }

        Ok(())
    }
}

pub static INCLUDE_HELPER: IncludeHelper = IncludeHelper;
pub static BLOCK_HELPER: BlockHelper = BlockHelper;
pub static PARTIAL_HELPER: PartialHelper = PartialHelper;

#[cfg(test)]
mod test {
    use template::Template;
    use registry::Registry;
    use std::collections::BTreeMap;

    #[test]
    fn test() {
        let t0 = Template::compile("
{{#block title}}default{{/block}}
".to_string())
                     .ok()
                     .unwrap();
        let t1 = Template::compile("{{#partial title}}{{this}}{{/partial}}{{> t0}}".to_string())
                     .ok()
                     .unwrap();
        let t2 = Template::compile("{{> t0}}
{{this}}
".to_string()).ok().unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);
        handlebars.register_template("t2", t2);

        let r0 = handlebars.render("t1", &true);
        assert_eq!(r0.ok().unwrap(), "
true
".to_string());

        let r1 = handlebars.render("t2", &true);
        assert_eq!(r1.ok().unwrap(), "
default

true
".to_string());
    }

    #[test]
    fn test_context() {
        let t0 = Template::compile("
{{> (body) data}}
".to_string()).ok().unwrap();
        let t1 = Template::compile("
{{this}}
".to_string()).ok().unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);

        let mut map: BTreeMap<String, String> = BTreeMap::new();
        map.insert("body".into(), "t1".into());
        map.insert("data".into(), "hello".into());

        let r0 = handlebars.render("t0", &map);
        assert_eq!(r0.ok().unwrap(), "

hello

".to_string());
    }

    #[test]
    fn test_partial_hash_context() {
        let t0 = Template::compile("
{{> t1 hello=\"world\"}}
".to_string()).ok().unwrap();
        let t1 = Template::compile("
{{data}}

{{hello}}
".to_string()).ok().unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);

        let mut map: BTreeMap<String, String> = BTreeMap::new();
        map.insert("data".into(), "hello".into());

        let r0 = handlebars.render("t0", &map);
        assert_eq!(r0.ok().unwrap(),
                   "

hello

world

".to_string());
    }

    #[test]
    fn test_inline_partial() {
        let t0 = Template::compile("{{#partial title}}hello {{name}}{{/partial}}
include \
                                    partial: {{#block title}}{{/block}}
"
                                       .to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);

        let mut map: BTreeMap<String, String> = BTreeMap::new();
        map.insert("name".into(), "world".into());

        let r0 = handlebars.render("t0", &map);
        assert_eq!(r0.ok().unwrap(),
                   "
include partial: hello world
".to_string());
    }

    #[test]
    fn test_include_self() {
        let t0 = Template::compile("
{{> t0}}
".to_string()).ok().unwrap();
        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);

        let map: BTreeMap<String, String> = BTreeMap::new();

        let r0 = handlebars.render("t0", &map);
        assert!(r0.is_err());
    }
}
<commit_msg>(fix) update error message [#98]<commit_after>use std::collections::BTreeMap;
use std::iter::FromIterator;

use helpers::HelperDef;
use registry::Registry;
use context::Context;
use render::{Renderable, RenderContext, RenderError, Helper};

#[derive(Clone, Copy)]
pub struct IncludeHelper;

#[derive(Clone, Copy)]
pub struct BlockHelper;

#[derive(Clone, Copy)]
pub struct PartialHelper;

impl HelperDef for IncludeHelper {
    fn call(&self,
            c: &Context,
            h: &Helper,
            r: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let template = match h.params().get(0) {
            Some(ref t) => {
                if let Some(include_path) = t.path() {
                    if rc.current_template == Some(include_path.to_owned()) {
                        return Err(RenderError::new("Cannot include self in >"));
                    } else {
                        r.get_template(&include_path)
                    }
                } else {
                    return Err(RenderError::new("Do not use literal here, use partial name directly."));
                }
            }
            None => return Err(RenderError::new("Param not found for helper")),
        };

        let context_param = h.params().get(1).and_then(|p| p.path());
        let old_path = match context_param {
            Some(p) => {
                let old_path = rc.get_path().clone();
                rc.promote_local_vars();
                let new_path = format!("{}/{}", old_path, p);
                rc.set_path(new_path);
                Some(old_path)
            }
            None => None,
        };

        let result = match template {
            Some(t) => {
                if h.hash().is_empty() {
                    t.render(c, r, rc)
                } else {
                    let hash_ctx = BTreeMap::from_iter(h.hash()
                                                        .iter()
                                                        .map(|(k, v)| {
                                                            (k.clone(), v.value().clone())
                                                        }));
                    let new_ctx = c.extend(&hash_ctx);
                    t.render(&new_ctx, r, rc)
                }
            }
            None => Err(RenderError::new("Template not found.")),
        };

        if let Some(path) = old_path {
            rc.set_path(path);
            rc.demote_local_vars();
        }

        result
    }
}

impl HelperDef for BlockHelper {
    fn call(&self,
            c: &Context,
            h: &Helper,
            r: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let param = try!(h.param(0).ok_or_else(|| RenderError::new("Param not found for helper")));

        if let Some(partial_path) = param.path() {
            let partial_template = rc.get_partial(partial_path);

            match partial_template {
                Some(partial_template) => partial_template.render(c, r, rc),
                None => h.template().unwrap().render(c, r, rc),
            }
        } else {
            Err(RenderError::new("Do not use literal here, use template name directly."))
        }
    }
}

impl HelperDef for PartialHelper {
    fn call(&self,
            _: &Context,
            h: &Helper,
            _: &Registry,
            rc: &mut RenderContext)
            -> Result<(), RenderError> {
        let param = try!(h.param(0).ok_or_else(|| RenderError::new("Param not found for helper")));

        if let Some(partial_path) = param.path() {
            rc.set_partial(partial_path.to_owned(), h.template().unwrap().clone());
        }

        Ok(())
    }
}

pub static INCLUDE_HELPER: IncludeHelper = IncludeHelper;
pub static BLOCK_HELPER: BlockHelper = BlockHelper;
pub static PARTIAL_HELPER: PartialHelper = PartialHelper;

#[cfg(test)]
mod test {
    use template::Template;
    use registry::Registry;
    use std::collections::BTreeMap;

    #[test]
    fn test() {
        let t0 = Template::compile("
{{#block title}}default{{/block}}
".to_string())
                     .ok()
                     .unwrap();
        let t1 = Template::compile("{{#partial title}}{{this}}{{/partial}}{{> t0}}".to_string())
                     .ok()
                     .unwrap();
        let t2 = Template::compile("{{> t0}}
{{this}}
".to_string()).ok().unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);
        handlebars.register_template("t2", t2);

        let r0 = handlebars.render("t1", &true);
        assert_eq!(r0.ok().unwrap(), "
true
".to_string());

        let r1 = handlebars.render("t2", &true);
        assert_eq!(r1.ok().unwrap(), "
default

true
".to_string());
    }

    #[test]
    fn test_context() {
        let t0 = Template::compile("
{{> (body) data}}
".to_string()).ok().unwrap();
        let t1 = Template::compile("
{{this}}
".to_string()).ok().unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);

        let mut map: BTreeMap<String, String> = BTreeMap::new();
        map.insert("body".into(), "t1".into());
        map.insert("data".into(), "hello".into());

        let r0 = handlebars.render("t0", &map);
        assert_eq!(r0.ok().unwrap(), "

hello

".to_string());
    }

    #[test]
    fn test_partial_hash_context() {
        let t0 = Template::compile("
{{> t1 hello=\"world\"}}
".to_string()).ok().unwrap();
        let t1 = Template::compile("
{{data}}

{{hello}}
".to_string()).ok().unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);
        handlebars.register_template("t1", t1);

        let mut map: BTreeMap<String, String> = BTreeMap::new();
        map.insert("data".into(), "hello".into());

        let r0 = handlebars.render("t0", &map);
        assert_eq!(r0.ok().unwrap(),
                   "

hello

world

".to_string());
    }

    #[test]
    fn test_inline_partial() {
        let t0 = Template::compile("{{#partial title}}hello {{name}}{{/partial}}
include \
                                    partial: {{#block title}}{{/block}}
"
                                       .to_string())
                     .ok()
                     .unwrap();

        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);

        let mut map: BTreeMap<String, String> = BTreeMap::new();
        map.insert("name".into(), "world".into());

        let r0 = handlebars.render("t0", &map);
        assert_eq!(r0.ok().unwrap(),
                   "
include partial: hello world
".to_string());
    }

    #[test]
    fn test_include_self() {
        let t0 = Template::compile("
{{> t0}}
".to_string()).ok().unwrap();
        let mut handlebars = Registry::new();
        handlebars.register_template("t0", t0);

        let map: BTreeMap<String, String> = BTreeMap::new();

        let r0 = handlebars.render("t0", &map);
        assert!(r0.is_err());
    }
}
<|endoftext|>


<commit_before>use sync::Arc;
use libc::c_void;

use glfw::{WindowEvent, Key, MouseButton, Glfw, Context};
use glfw::{Press, Release, KeyEvent, MouseButtonEvent, CursorPosEvent};
use glfw::{CloseEvent, FocusEvent, FullScreen};
use glfw::{Windowed, RenderContext};
use glfw;
use gl;

use semver;
use collections::{HashSet, TrieMap};

use cgmath::quaternion::Quaternion;

use ovr;

pub type WindowId = uint;

#[deriving(Clone)]
struct InputHistory {
    older: Option<Arc<InputHistory>>,
    time: Option<f64>,
    event: WindowEvent
}

#[deriving(Clone)]
pub struct InputState {
    history: Option<Arc<InputHistory>>,
    keyboard: HashSet<Key>,
    mouse: HashSet<MouseButton>,
    should_close: bool,
    focus: bool,
    framebuffer_size: (i32, i32),
    screen_size: (i32, i32),
    predicted: Quaternion<f32>,
}

struct InputHistoryIterator {
    current: Option<Arc<InputHistory>>
}

impl Iterator<(Option<f64>, WindowEvent)> for InputHistoryIterator {
    fn next(&mut self) -> Option<(Option<f64>, WindowEvent)> {
        let (next, res) = match self.current {
            Some(ref next) => {
                let next = next.deref();
                (next.older.clone(), Some((next.time.clone(), next.event.clone())))
            },
            None => (None, None)
        };

        self.current = next;
        res
    }
}

pub struct DeltaIterator {
    current: Option<Arc<InputHistory>>,
    origin: Option<Arc<InputHistory>>
}

impl Iterator<(Option<f64>, WindowEvent)> for DeltaIterator {
    fn next(&mut self) -> Option<(Option<f64>, WindowEvent)> {
        match (&self.current, &self.origin) {
            (&None, &None) => return None,
            (&Some(ref a), &Some(ref b)) => {
                if a.deref() as *InputHistory == b.deref() as *InputHistory {
                    return None
                }
            }
            _ => ()
        }

        let (next, res) = match self.current {
            Some(ref next) => {
                let next = next.deref();
                (next.older.clone(), Some((next.time.clone(), next.event.clone())))
            },
            None => (None, None)
        };

        self.current = next;
        res
    }
}

impl InputState {
    fn new(win: &glfw::Window) -> InputState {
        InputState {
            history: None,
            keyboard: HashSet::new(),
            mouse: HashSet::new(),
            should_close: false,
            focus: win.is_focused(),
            framebuffer_size: win.get_framebuffer_size(),
            screen_size: win.get_size(),
            predicted: Quaternion::identity()
        }
    }

    fn event(&mut self, time: Option<f64>, event: WindowEvent) {
        self.history = Some(Arc::new( InputHistory{
            older: self.history.clone(),
            time: time,
            event: event.clone()
        }));

        match event {
            KeyEvent(key, _, Press, _) => { self.keyboard.insert(key); },
            KeyEvent(key, _, Release, _) => { self.keyboard.remove(&key); },
            MouseButtonEvent(key, Press, _) => { self.mouse.insert(key); },
            MouseButtonEvent(key, Release, _) => { self.mouse.remove(&key); },
            CloseEvent => { self.should_close = true; },
            FocusEvent(s) => { self.focus = s; },
            _ => ()
        }
    }

    fn iter(&self) -> InputHistoryIterator {
        InputHistoryIterator {
            current: self.history.clone()
        }
    }

    pub fn key_down(&self, key: Key) -> bool
    {
        self.keyboard.contains(&key)
    }

    pub fn mouse_up(&self, button: MouseButton) -> bool
    {
        self.mouse.contains(&button)
    }

    pub fn time(&self) -> f64 {
        for (t, _) in self.iter() {
            match t {
                Some(t) => return t,
                None => ()
            }
        }
        0.
    }

    pub fn cursor_delta(&self, epoc: f64) -> Option<(f64, f64)> {
        let mut latest = None;
        let mut old = (0f64, 0f64);
        let mut iter = self.iter();

        // find the latest cursor position
        for (time, event) in iter {
            // no change found
            if time.is_none() || time.unwrap() <= epoc {
                return None;
            }
            match event {
                CursorPosEvent(x, y) => {
                    latest = Some((x, y));
                    break;
                },
                _ => ()
            }
        }

        // no change found
        if latest.is_none() {
            return None;
        }

        let (nx, ny) = latest.unwrap();

        // find the first cursor positon before
        for (time, event) in iter {
            if time.is_none() || time.unwrap() <= epoc {
                match event {
                    CursorPosEvent(x, y) => {
                        old = (x, y);
                        break;
                    },
                    _ => ()
                }
            }
        }

        let (x, y) = old;
        Some((nx-x, ny-y))
    }

    pub fn should_close(&self) -> bool {
        self.should_close
    }

    pub fn is_focused(&self) -> bool {
        self.focus
    }

    pub fn screen_size(&self) -> (i32, i32) {
        self.screen_size.clone()
    }

    pub fn framebuffer_size(&self) -> (i32, i32) {
        self.framebuffer_size.clone()
    }

    pub fn iter_delta(&self, old: &InputState) -> DeltaIterator {
        DeltaIterator {
            current: self.history.clone(),
            origin: old.history.clone()
        }
    }
}

struct WindowHandle {
    window: glfw::Window,
    receiver: Receiver<(f64, WindowEvent)>,
    state: InputState
}

pub struct IOManager {
    glfw: Glfw,
    ovr: Option<ovr::Ovr>,
    windows: TrieMap<WindowHandle>,
    window_id: uint
}

impl IOManager {
    pub fn new(glfw: glfw::Glfw) -> IOManager {
        IOManager {
            glfw: glfw,
            ovr: None,
            windows: TrieMap::new(),
            window_id: 0
        }
    }

    fn add_window(&mut self, window: glfw::Window, recv: Receiver<(f64, WindowEvent)>) -> InputHandle {
        let id = self.window_id;
        self.window_id += 1;

        let state = InputState::new(&window);

        self.windows.insert(id, {
            WindowHandle {
                window: window,
                receiver: recv,
                state: state
            }
        });

        InputHandle{ handle: id }
    }

    pub fn window(&mut self, size: (u32, u32)) -> Option<Window> {
        let (width, height) = size;
        let win_opt = self.glfw.create_window(width, height, "Snowmew", Windowed);
        let (mut window, events) = match win_opt {
            Some((window, events)) => (window, events),
            None => return None
        };

        window.make_current();
        gl::load_with(|name| self.glfw.get_proc_address(name));
        self.glfw.set_swap_interval(1);
        glfw::make_context_current(None);

        window.set_all_polling(true);
        window.show();
        let version = window.get_context_version();
        let rc = window.render_context();
        let handle = self.add_window(window, events);

        Some(Window {
            handle: handle,
            render: rc,
            version: version,
            hmd: None,
            display: self.glfw.get_x11_display()
        })
    }

    #[cfg(target_os="linux")]
    fn create_hmd_window(&self, hmd: &ovr::HmdDescription) -> Option<(glfw::Window, Receiver<(f64,WindowEvent)>)> {
        self.glfw.with_connected_monitors(|monitors| {
            for m in monitors.iter() {
                let (x, y) = m.get_pos();
                if x == hmd.window_position.x &&
                   y == hmd.window_position.y {
                    let (width, height) = (hmd.resolution.x, hmd.resolution.y);
                    let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew Fullscreen", FullScreen(m));
                    let (window, events) = match win_opt {
                        Some((window, events)) => (window, events),
                        None => return None
                    };

                    return Some((window, events));
                }
            }

            // fallback if we could not guess at the screen
            let (width, height) = (hmd.resolution.x, hmd.resolution.y);
            let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew", Windowed);
            let (window, events) = match win_opt {
                Some((window, events)) => (window, events),
                None => return None
            };

            // move viewport
            let (dx, dy) = (hmd.window_position.x, hmd.window_position.y);
            window.set_pos(dx as i32, dy as i32);

            Some((window, events))

        })
    }

    #[cfg(target_os="macos")]
    fn create_hmd_window(&self, hmd: &ovr::HmdDescription) -> Option<(glfw::Window, Receiver<(f64,WindowEvent)>)> {
        self.glfw.with_connected_monitors(|monitors| {
            for m in monitors.iter() {
                if !m.get_name().as_slice().contains("Rift") {
                    continue;
                }

                let (width, height) = hmd.resolution();
                let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew Fullscreen", FullScreen(m));
                let (window, events) = match win_opt {
                    Some((window, events)) => (window, events),
                    None => return None
                };

                return Some((window, events));
            }
            None
        })
    }

    pub fn hmd(&mut self) -> Option<Window> {
        if !self.setup_ovr() {
            return None;
        }

        let (window, events, rc, hmd) = {
            let hmd = match self.ovr.as_ref().unwrap().first_hmd() {
                Some(hmd) => hmd,
                None => return None
            };
            let hmdinfo = hmd.get_description();

            let (mut window, events) = match self.create_hmd_window(&hmdinfo) {
                Some((window, events)) => (window, events),
                None => return None
            };

            window.make_current();
            gl::load_with(|name| self.glfw.get_proc_address(name));
            self.glfw.set_swap_interval(1);
            glfw::make_context_current(None);

            window.set_all_polling(true);
            window.show();

            let rc = window.render_context();
            (window, events, rc, hmd)
        };

        let version = window.get_context_version();
        let handle = self.add_window(window, events);

        Some(Window {
            handle: handle,
            render: rc,
            version: version,
            hmd: Some(Arc::new(hmd)),
            display: self.glfw.get_x11_display()
        })
    }

    pub fn get(&self, handle: &InputHandle) -> InputState {
        self.windows.find(&handle.handle).unwrap().state.clone()
    }

    fn update(&mut self) {
        for (_, win) in self.windows.mut_iter() {
            for (time, event) in glfw::flush_messages(&win.receiver) {
                win.state.event(Some(time), event);
            }
        }
    }

    pub fn wait(&mut self) {
        self.glfw.wait_events();
        self.update();
    }

    pub fn poll(&mut self) {
        self.glfw.poll_events();
        self.update();
    }

    pub fn setup_ovr(&mut self) -> bool {
        if self.ovr.is_some() &&
           self.ovr.as_ref().unwrap().detect() > 0 {
            return true;
        }

        if self.ovr.is_none() {
            self.ovr = ovr::Ovr::init();
        }

        self.ovr.is_some() && self.ovr.as_ref().unwrap().detect() > 0
    }
}

#[deriving(Clone)]
pub struct InputHandle {
    handle: uint,
}

pub struct Window {
    handle: InputHandle,
    render: RenderContext,
    version: semver::Version,
    hmd: Option<Arc<ovr::Hmd>>,
    display: *c_void
}

impl Window {
    pub fn swap_buffers(&self) {
        self.render.swap_buffers()
    }

    pub fn make_context_current(&self) {
        self.render.make_current()
    }

    pub fn get_context_version(&self) -> (uint, uint) {
        let version = self.version.clone();
        (version.major, version.minor)
    }

    pub fn handle(&self) -> InputHandle {
        self.handle.clone()
    }

    pub fn is_hmd(&self) -> bool {
        self.hmd.is_some()
    }

    pub fn get_hmd<'a>(&'a self) -> Arc<ovr::Hmd> {
        self.hmd.as_ref().expect("no hmd device found!").clone()
    }

    /// Wrapper for `glfwGetGLXContext`
    #[cfg(target_os="linux")]
    pub fn get_x11_display(&self) -> *c_void {
        self.display
    }

}<commit_msg>Fixed os for mac os<commit_after>use sync::Arc;
#[cfg(target_os="linux")]
use libc::c_void;

use glfw::{WindowEvent, Key, MouseButton, Glfw, Context};
use glfw::{Press, Release, KeyEvent, MouseButtonEvent, CursorPosEvent};
use glfw::{CloseEvent, FocusEvent, FullScreen};
use glfw::{Windowed, RenderContext};
use glfw;
use gl;

use semver;
use collections::{HashSet, TrieMap};

use cgmath::quaternion::Quaternion;

use ovr;

pub type WindowId = uint;

#[deriving(Clone)]
struct InputHistory {
    older: Option<Arc<InputHistory>>,
    time: Option<f64>,
    event: WindowEvent
}

#[deriving(Clone)]
pub struct InputState {
    history: Option<Arc<InputHistory>>,
    keyboard: HashSet<Key>,
    mouse: HashSet<MouseButton>,
    should_close: bool,
    focus: bool,
    framebuffer_size: (i32, i32),
    screen_size: (i32, i32),
    predicted: Quaternion<f32>,
}

struct InputHistoryIterator {
    current: Option<Arc<InputHistory>>
}

impl Iterator<(Option<f64>, WindowEvent)> for InputHistoryIterator {
    fn next(&mut self) -> Option<(Option<f64>, WindowEvent)> {
        let (next, res) = match self.current {
            Some(ref next) => {
                let next = next.deref();
                (next.older.clone(), Some((next.time.clone(), next.event.clone())))
            },
            None => (None, None)
        };

        self.current = next;
        res
    }
}

pub struct DeltaIterator {
    current: Option<Arc<InputHistory>>,
    origin: Option<Arc<InputHistory>>
}

impl Iterator<(Option<f64>, WindowEvent)> for DeltaIterator {
    fn next(&mut self) -> Option<(Option<f64>, WindowEvent)> {
        match (&self.current, &self.origin) {
            (&None, &None) => return None,
            (&Some(ref a), &Some(ref b)) => {
                if a.deref() as *InputHistory == b.deref() as *InputHistory {
                    return None
                }
            }
            _ => ()
        }

        let (next, res) = match self.current {
            Some(ref next) => {
                let next = next.deref();
                (next.older.clone(), Some((next.time.clone(), next.event.clone())))
            },
            None => (None, None)
        };

        self.current = next;
        res
    }
}

impl InputState {
    fn new(win: &glfw::Window) -> InputState {
        InputState {
            history: None,
            keyboard: HashSet::new(),
            mouse: HashSet::new(),
            should_close: false,
            focus: win.is_focused(),
            framebuffer_size: win.get_framebuffer_size(),
            screen_size: win.get_size(),
            predicted: Quaternion::identity()
        }
    }

    fn event(&mut self, time: Option<f64>, event: WindowEvent) {
        self.history = Some(Arc::new( InputHistory{
            older: self.history.clone(),
            time: time,
            event: event.clone()
        }));

        match event {
            KeyEvent(key, _, Press, _) => { self.keyboard.insert(key); },
            KeyEvent(key, _, Release, _) => { self.keyboard.remove(&key); },
            MouseButtonEvent(key, Press, _) => { self.mouse.insert(key); },
            MouseButtonEvent(key, Release, _) => { self.mouse.remove(&key); },
            CloseEvent => { self.should_close = true; },
            FocusEvent(s) => { self.focus = s; },
            _ => ()
        }
    }

    fn iter(&self) -> InputHistoryIterator {
        InputHistoryIterator {
            current: self.history.clone()
        }
    }

    pub fn key_down(&self, key: Key) -> bool
    {
        self.keyboard.contains(&key)
    }

    pub fn mouse_up(&self, button: MouseButton) -> bool
    {
        self.mouse.contains(&button)
    }

    pub fn time(&self) -> f64 {
        for (t, _) in self.iter() {
            match t {
                Some(t) => return t,
                None => ()
            }
        }
        0.
    }

    pub fn cursor_delta(&self, epoc: f64) -> Option<(f64, f64)> {
        let mut latest = None;
        let mut old = (0f64, 0f64);
        let mut iter = self.iter();

        // find the latest cursor position
        for (time, event) in iter {
            // no change found
            if time.is_none() || time.unwrap() <= epoc {
                return None;
            }
            match event {
                CursorPosEvent(x, y) => {
                    latest = Some((x, y));
                    break;
                },
                _ => ()
            }
        }

        // no change found
        if latest.is_none() {
            return None;
        }

        let (nx, ny) = latest.unwrap();

        // find the first cursor positon before
        for (time, event) in iter {
            if time.is_none() || time.unwrap() <= epoc {
                match event {
                    CursorPosEvent(x, y) => {
                        old = (x, y);
                        break;
                    },
                    _ => ()
                }
            }
        }

        let (x, y) = old;
        Some((nx-x, ny-y))
    }

    pub fn should_close(&self) -> bool {
        self.should_close
    }

    pub fn is_focused(&self) -> bool {
        self.focus
    }

    pub fn screen_size(&self) -> (i32, i32) {
        self.screen_size.clone()
    }

    pub fn framebuffer_size(&self) -> (i32, i32) {
        self.framebuffer_size.clone()
    }

    pub fn iter_delta(&self, old: &InputState) -> DeltaIterator {
        DeltaIterator {
            current: self.history.clone(),
            origin: old.history.clone()
        }
    }
}

struct WindowHandle {
    window: glfw::Window,
    receiver: Receiver<(f64, WindowEvent)>,
    state: InputState
}

pub struct IOManager {
    glfw: Glfw,
    ovr: Option<ovr::Ovr>,
    windows: TrieMap<WindowHandle>,
    window_id: uint
}

impl IOManager {
    pub fn new(glfw: glfw::Glfw) -> IOManager {
        IOManager {
            glfw: glfw,
            ovr: None,
            windows: TrieMap::new(),
            window_id: 0
        }
    }

    fn add_window(&mut self, window: glfw::Window, recv: Receiver<(f64, WindowEvent)>) -> InputHandle {
        let id = self.window_id;
        self.window_id += 1;

        let state = InputState::new(&window);

        self.windows.insert(id, {
            WindowHandle {
                window: window,
                receiver: recv,
                state: state
            }
        });

        InputHandle{ handle: id }
    }

    pub fn window(&mut self, size: (u32, u32)) -> Option<Window> {
        let (width, height) = size;
        let win_opt = self.glfw.create_window(width, height, "Snowmew", Windowed);
        let (mut window, events) = match win_opt {
            Some((window, events)) => (window, events),
            None => return None
        };

        window.make_current();
        gl::load_with(|name| self.glfw.get_proc_address(name));
        self.glfw.set_swap_interval(1);
        glfw::make_context_current(None);

        window.set_all_polling(true);
        window.show();
        let version = window.get_context_version();
        let rc = window.render_context();
        let handle = self.add_window(window, events);

        Some(Window {
            handle: handle,
            render: rc,
            version: version,
            hmd: None,
            os_spec: WindowOSSpec::new(&self.glfw)
        })
    }

    #[cfg(target_os="linux")]
    fn create_hmd_window(&self, hmd: &ovr::HmdDescription) -> Option<(glfw::Window, Receiver<(f64,WindowEvent)>)> {
        self.glfw.with_connected_monitors(|monitors| {
            for m in monitors.iter() {
                let (x, y) = m.get_pos();
                if x == hmd.window_position.x &&
                   y == hmd.window_position.y {
                    let (width, height) = (hmd.resolution.x, hmd.resolution.y);
                    let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew Fullscreen", FullScreen(m));
                    let (window, events) = match win_opt {
                        Some((window, events)) => (window, events),
                        None => return None
                    };

                    return Some((window, events));
                }
            }

            // fallback if we could not guess at the screen
            let (width, height) = (hmd.resolution.x, hmd.resolution.y);
            let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew", Windowed);
            let (window, events) = match win_opt {
                Some((window, events)) => (window, events),
                None => return None
            };

            // move viewport
            let (dx, dy) = (hmd.window_position.x, hmd.window_position.y);
            window.set_pos(dx as i32, dy as i32);

            Some((window, events))

        })
    }

    #[cfg(target_os="macos")]
    fn create_hmd_window(&self, hmd: &ovr::HmdDescription) -> Option<(glfw::Window, Receiver<(f64,WindowEvent)>)> {
        self.glfw.with_connected_monitors(|monitors| {
            for m in monitors.iter() {
                if !m.get_name().as_slice().contains("Rift") {
                    continue;
                }

                let (width, height) = (hmd.resolution.x, hmd.resolution.y);
                let win_opt = self.glfw.create_window(width as u32, height as u32, "Snowmew Fullscreen", FullScreen(m));
                let (window, events) = match win_opt {
                    Some((window, events)) => (window, events),
                    None => return None
                };

                return Some((window, events));
            }
            None
        })
    }

    pub fn hmd(&mut self) -> Option<Window> {
        if !self.setup_ovr() {
            return None;
        }

        let (window, events, rc, hmd) = {
            let hmd = match self.ovr.as_ref().unwrap().first_hmd() {
                Some(hmd) => hmd,
                None => return None
            };
            let hmdinfo = hmd.get_description();

            let (mut window, events) = match self.create_hmd_window(&hmdinfo) {
                Some((window, events)) => (window, events),
                None => return None
            };

            window.make_current();
            gl::load_with(|name| self.glfw.get_proc_address(name));
            self.glfw.set_swap_interval(1);
            glfw::make_context_current(None);

            window.set_all_polling(true);
            window.show();

            let rc = window.render_context();
            (window, events, rc, hmd)
        };

        let version = window.get_context_version();
        let handle = self.add_window(window, events);

        Some(Window {
            handle: handle,
            render: rc,
            version: version,
            hmd: Some(Arc::new(hmd)),
            os_spec: WindowOSSpec::new(&self.glfw)
        })
    }

    pub fn get(&self, handle: &InputHandle) -> InputState {
        self.windows.find(&handle.handle).unwrap().state.clone()
    }

    fn update(&mut self) {
        for (_, win) in self.windows.mut_iter() {
            for (time, event) in glfw::flush_messages(&win.receiver) {
                win.state.event(Some(time), event);
            }
        }
    }

    pub fn wait(&mut self) {
        self.glfw.wait_events();
        self.update();
    }

    pub fn poll(&mut self) {
        self.glfw.poll_events();
        self.update();
    }

    pub fn setup_ovr(&mut self) -> bool {
        if self.ovr.is_some() &&
           self.ovr.as_ref().unwrap().detect() > 0 {
            return true;
        }

        if self.ovr.is_none() {
            self.ovr = ovr::Ovr::init();
        }

        self.ovr.is_some() && self.ovr.as_ref().unwrap().detect() > 0
    }
}

#[deriving(Clone)]
pub struct InputHandle {
    handle: uint,
}

#[cfg(target_os="macos")]
struct WindowOSSpec;

#[cfg(target_os="macos")]
impl WindowOSSpec {
    fn new(_: &Glfw) -> WindowOSSpec {WindowOSSpec}
}

#[cfg(target_os="linux")]
struct WindowOSSpec {
    display: *c_void
}

#[cfg(target_os="linux")]
impl WindowOSSpec {
    fn new(glfw: &Glfw) -> WindowOSSpec {
        WindowOSSpec {
            display: glfw.get_x11_display()
        }
    }
}

pub struct Window {
    handle: InputHandle,
    render: RenderContext,
    version: semver::Version,
    hmd: Option<Arc<ovr::Hmd>>,
    os_spec: WindowOSSpec
}

impl Window {
    pub fn swap_buffers(&self) {
        self.render.swap_buffers()
    }

    pub fn make_context_current(&self) {
        self.render.make_current()
    }

    pub fn get_context_version(&self) -> (uint, uint) {
        let version = self.version.clone();
        (version.major, version.minor)
    }

    pub fn handle(&self) -> InputHandle {
        self.handle.clone()
    }

    pub fn is_hmd(&self) -> bool {
        self.hmd.is_some()
    }

    pub fn get_hmd<'a>(&'a self) -> Arc<ovr::Hmd> {
        self.hmd.as_ref().expect("no hmd device found!").clone()
    }

    /// Wrapper for `glfwGetGLXContext`
    #[cfg(target_os="linux")]
    pub fn get_x11_display(&self) -> *c_void {
        self.os_spec.display
    }

}<|endoftext|>