<commit_before>use bvh::*;
use bounding_hierarchy::BHShape;
use std::collections::HashSet;

// TODO Consider: Instead of getting the scene's shapes passed, let leaf nodes store an AABB
// that is updated from the outside, perhaps by passing not only the indices of the changed
// shapes, but also their new AABBs into optimize().

impl BVH {
    /// Optimizes the `BVH` by batch-reorganizing updated nodes.
    /// Based on https://github.com/jeske/SimpleScene/blob/master/SimpleScene/Util/ssBVH/ssBVH.cs
    ///
    /// Needs all the scene's shapes, plus the indices of the shapes that were updated.
    ///
    pub fn optimize<Shape: BHShape>(&mut self,
                                    refit_shape_indices: &HashSet<usize>,
                                    shapes: &[Shape]) {
        let mut refit_node_indices: HashSet<usize> = refit_shape_indices.iter()
            .map(|x| shapes[*x].bh_node_index())
            .collect();

        // As long as we have refit nodes left, take the list of refit nodes
        // with the highest depth (sweep nodes) and try to rotate them all
        while refit_node_indices.len() > 0 {
            let mut max_depth = 0;
            let mut sweep_node_indices: Vec<usize> = Vec::new();

            // Find max_depth and sweep_node_indices in one iteration
            for refit_node_index in refit_node_indices.iter() {
                let depth = match self.nodes[*refit_node_index] {
                    BVHNode::Node { depth, .. } => depth,
                    BVHNode::Leaf { depth, .. } => depth,
                    BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
                };

                if depth > max_depth {
                    max_depth = depth;
                    sweep_node_indices.clear();
                    sweep_node_indices.push(*refit_node_index);
                } else if depth == max_depth {
                    sweep_node_indices.push(*refit_node_index);
                }
            }

            // Try to find a useful tree rotation with all nodes previously found
            for sweep_node_index in sweep_node_indices.iter() {
                // This node does not need to be checked again
                refit_node_indices.remove(&sweep_node_index);

                let new_refit_node_index = self.try_rotate(*sweep_node_index, shapes);

                // Instead of finding a useful tree rotation, we found another node
                // that we should check, so we add its index to the refit_node_indices.
                if let Some(index) = new_refit_node_index {
                    refit_node_indices.insert(index);
                }
            }
        }
    }

    /// Checks if there is a way to rotate a child and a grandchild node of
    /// the given node (specified by `node_index`) that would improve the `BVH`.
    /// If there is, the best rotation found is performed.
    /// Relies on the children nodes of the given node having correct AABBs.
    ///
    /// Returns Some(index_of_node) if a new node was found that should be used for optimization.
    ///
    fn try_rotate<Shape: BHShape>(&mut self, node_index: usize, shapes: &[Shape]) -> Option<usize> {
        let mut nodes = &mut self.nodes;

        let mut node_clone = nodes[node_index].clone();

        // Contains the surface area that would result from applying the currently favored rotation.
        // The rotation with the smallest SA will be applied in the end.
        // The value is calculated by child_l_aabb.surface_area() + child_r_aabb.surface_area()
        let mut best_SA = 0f32;

        // TODO Re-implement without mutability
        let mut parent_index: usize = 0;

        // If this node is not a grandparent, update the AABB,
        // queue the parent for refitting, and bail out.
        // If it is a grandparent, calculate the current best_SA.
        match node_clone {
            BVHNode::Node { parent, child_l, child_r, child_l_aabb, child_r_aabb, .. } => {
                if let BVHNode::Leaf { shape, .. } = nodes[child_l] {
                    let shape_l_index = shape;
                    if let BVHNode::Leaf { shape, .. } = nodes[child_r] {
                        let shape_r_index = shape;

                        // Update the AABBs saved for the children
                        // since at least one of them changed
                        let mut node = &mut nodes[node_index];
                        match node {
                            &mut BVHNode::Node { ref mut child_l_aabb,
                                                 ref mut child_r_aabb,
                                                 .. } => {
                                *child_l_aabb = shapes[shape_l_index].aabb();
                                *child_r_aabb = shapes[shape_r_index].aabb();
                            }
                            _ => unreachable!(),
                        }

                        return Some(parent);
                    }
                }

                parent_index = parent;
                best_SA = child_l_aabb.surface_area() + child_r_aabb.surface_area();
            }
            BVHNode::Leaf { parent, .. } => {
                return Some(parent);
            }
            BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
        }

        // Stores the Rotation that would result in the surface area best_SA,
        // thus being the favored rotation that will be executed after considering all rotations.
        let mut best_rotation: Option<(usize, usize)> = None;

        macro_rules! consider_rotation {
            ($a:expr, $b:expr) => {
                // TODO Calculate surface area that would result from rotating the given nodes.
                // TODO If the result SA is smaller than the current best, save as best_SA and
                // the nodes as best_rotation.
                unimplemented!();
            };
        }

        // Child to grandchild rotations
        consider_rotation!(child_l, child_rl);
        consider_rotation!(child_l, child_rr);
        consider_rotation!(child_r, child_ll);
        consider_rotation!(child_r, child_lr);
        // Grandchild to grandchild rotations
        consider_rotation!(child_ll, child_rl);
        consider_rotation!(child_ll, child_rr);

        let new_refit_node_index = if parent_index > 0 {
            Some(parent_index)
        } else {
            None
        };

        if best_rotation == None {
            // TODO Recalculate this node's AABBs (child_l_aabb, child_r_aabb)
            // according to the children nodes' AABBs.

            // Even with no rotation being useful for this node, a parent node's rotation
            // could be beneficial, so queue the parent sometimes.
            // TODO Return None most of the time, randomly
            // (see https://github.com/jeske/SimpleScene/blob/master/SimpleScene/Util/ssBVH/ssBVH_Node.cs#L307)
            new_refit_node_index
        } else {
            // TODO Perform rotation using rotate()

            // TODO Update all changed node AABBs

            // Return parent node's index for upcoming refitting,
            // since this node just changed its AABB
            new_refit_node_index
        }
    }

    /// Switch two nodes by rewiring the involved indices (not by moving them in the nodes slice)
    fn rotate(&mut self, node_a_index: usize, node_b_index: usize) {
        let mut nodes = &mut self.nodes;

        macro_rules! should_not_happen {
            () => ( panic!("While rotating BVH nodes, something unexpected happened."); );
            ($s:expr) => ( panic!("While rotating BVH nodes, something unexpected happened: {}", $s); );
        }

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn get_parent_index(nodes: &Vec<BVHNode>, node_index: usize) -> usize {
            let node = &nodes[node_index];

            match *node {
                BVHNode::Node { parent, .. } |
                BVHNode::Leaf { parent, .. } => parent,
                _ => should_not_happen!(),
            }
        }

        let node_a_parent_index = get_parent_index(nodes, node_a_index);
        let node_b_parent_index = get_parent_index(nodes, node_b_index);

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn get_is_left_child(nodes: &Vec<BVHNode>,
                             node_index: usize,
                             node_parent_index: usize)
                             -> bool {
            let node_parent = &nodes[node_parent_index];

            match *node_parent {
                BVHNode::Node { child_l, .. } => child_l == node_index,
                _ => should_not_happen!(),
            }
        }

        let node_a_is_left_child = get_is_left_child(nodes, node_a_index, node_a_parent_index);
        let node_b_is_left_child = get_is_left_child(nodes, node_b_index, node_b_parent_index);

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn connect_nodes(nodes: &mut Vec<BVHNode>,
                         child_index: usize,
                         parent_index: usize,
                         left_child: bool) {
            // Set parent's child and get its depth
            let parent_depth = {
                let mut parent = &mut nodes[parent_index];
                match parent {
                    &mut BVHNode::Node { ref mut child_l, ref mut child_r, depth, .. } => {
                        if left_child {
                            *child_l = child_index;
                        } else {
                            *child_r = child_index;
                        }
                        depth
                    }
                    _ => should_not_happen!(),
                }
            };

            // Set child's parent and depth
            {
                let mut child = &mut nodes[child_index];
                match child {
                    &mut BVHNode::Node { ref mut parent, ref mut depth, .. } |
                    &mut BVHNode::Leaf { ref mut parent, ref mut depth, .. } => {
                        *parent = parent_index;
                        *depth = parent_depth + 1;
                    }
                    _ => should_not_happen!(),
                };
            }
        }

        connect_nodes(nodes,
                      node_a_index,
                      node_b_parent_index,
                      node_b_is_left_child);
        connect_nodes(nodes,
                      node_b_index,
                      node_a_parent_index,
                      node_a_is_left_child);
    }
}

#[cfg(test)]
pub mod tests {
    use bvh::BVH;

    #[test]
    /// Tests if the optimize function tries to change a fresh BVH even though it shouldn't
    fn test_optimizing_new_bvh() {
        let (mut shapes, mut bvh) = build_some_bh::<BVH>();

        let refit_shape_indices: HashSet<usize> = (0..shapes.len()).collect();
        bvh.optimize(&refit_shape_indices, &mut shapes);
    }

    // TODO Add tests for:
    // * correct parent
    // * correct depth
    // * correct BVH after optimizing
    // * correct parent and depth after optimizing
}
<commit_msg>Improve comments<commit_after>use bvh::*;
use bounding_hierarchy::BHShape;
use std::collections::HashSet;

// TODO Consider: Instead of getting the scene's shapes passed, let leaf nodes store an AABB
// that is updated from the outside, perhaps by passing not only the indices of the changed
// shapes, but also their new AABBs into optimize().

impl BVH {
    /// Optimizes the `BVH` by batch-reorganizing updated nodes.
    /// Based on https://github.com/jeske/SimpleScene/blob/master/SimpleScene/Util/ssBVH/ssBVH.cs
    ///
    /// Needs all the scene's shapes, plus the indices of the shapes that were updated.
    ///
    pub fn optimize<Shape: BHShape>(&mut self,
                                    refit_shape_indices: &HashSet<usize>,
                                    shapes: &[Shape]) {
        let mut refit_node_indices: HashSet<usize> = refit_shape_indices.iter()
            .map(|x| shapes[*x].bh_node_index())
            .collect();

        // As long as we have refit nodes left, take the list of refit nodes
        // with the highest depth (sweep nodes) and try to rotate them all
        while refit_node_indices.len() > 0 {
            let mut max_depth = 0;
            let mut sweep_node_indices: Vec<usize> = Vec::new();

            // Find max_depth and sweep_node_indices in one iteration
            for refit_node_index in refit_node_indices.iter() {
                let depth = match self.nodes[*refit_node_index] {
                    BVHNode::Node { depth, .. } => depth,
                    BVHNode::Leaf { depth, .. } => depth,
                    BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
                };

                if depth > max_depth {
                    max_depth = depth;
                    sweep_node_indices.clear();
                    sweep_node_indices.push(*refit_node_index);
                } else if depth == max_depth {
                    sweep_node_indices.push(*refit_node_index);
                }
            }

            // Try to find a useful tree rotation with all nodes previously found
            for sweep_node_index in sweep_node_indices.iter() {
                // This node does not need to be checked again
                refit_node_indices.remove(&sweep_node_index);

                let new_refit_node_index = self.try_rotate(*sweep_node_index, shapes);

                // Instead of finding a useful tree rotation, we found another node
                // that we should check, so we add its index to the refit_node_indices.
                if let Some(index) = new_refit_node_index {
                    refit_node_indices.insert(index);
                }
            }
        }
    }

    /// Checks if there is a way to rotate a child and a grandchild (or two grandchildren) of
    /// the given node (specified by `node_index`) that would improve the `BVH`.
    /// If there is, the best rotation found is performed.
    /// Relies on the children and transitive children of the given node having correct AABBs.
    ///
    /// Returns Some(index_of_node) if a new node was found that should be used for optimization.
    ///
    fn try_rotate<Shape: BHShape>(&mut self, node_index: usize, shapes: &[Shape]) -> Option<usize> {
        let mut nodes = &mut self.nodes;

        let mut node_clone = nodes[node_index].clone();

        // Contains the surface area that would result from applying the currently favored rotation.
        // The rotation with the smallest SA will be applied in the end.
        // The value is calculated by child_l_aabb.surface_area() + child_r_aabb.surface_area()
        let mut best_SA = 0f32;

        // TODO Re-implement without mutability
        let mut parent_index: usize = 0;

        // If this node is not a grandparent, update the AABB,
        // queue the parent for refitting, and bail out.
        // If it is a grandparent, calculate the current best_SA.
        match node_clone {
            BVHNode::Node { parent, child_l, child_r, child_l_aabb, child_r_aabb, .. } => {
                if let BVHNode::Leaf { shape, .. } = nodes[child_l] {
                    let shape_l_index = shape;
                    if let BVHNode::Leaf { shape, .. } = nodes[child_r] {
                        let shape_r_index = shape;

                        // Update the AABBs saved for the children
                        // since at least one of them changed
                        let mut node = &mut nodes[node_index];
                        match node {
                            &mut BVHNode::Node { ref mut child_l_aabb,
                                                 ref mut child_r_aabb,
                                                 .. } => {
                                *child_l_aabb = shapes[shape_l_index].aabb();
                                *child_r_aabb = shapes[shape_r_index].aabb();
                            }
                            _ => unreachable!(),
                        }

                        return Some(parent);
                    }
                }

                parent_index = parent;
                best_SA = child_l_aabb.surface_area() + child_r_aabb.surface_area();
            }
            BVHNode::Leaf { parent, .. } => {
                return Some(parent);
            }
            BVHNode::Dummy => panic!("Dummy node found during BVH optimization!"),
        }

        // Stores the Rotation that would result in the surface area best_SA,
        // thus being the favored rotation that will be executed after considering all rotations.
        let mut best_rotation: Option<(usize, usize)> = None;

        macro_rules! consider_rotation {
            ($a:expr, $b:expr) => {
                // TODO Calculate surface area that would result from rotating the given nodes.
                // TODO If the result SA is smaller than the current best, save as best_SA and
                // the nodes as best_rotation.
                unimplemented!();
            };
        }

        // Child to grandchild rotations
        consider_rotation!(child_l, child_rl);
        consider_rotation!(child_l, child_rr);
        consider_rotation!(child_r, child_ll);
        consider_rotation!(child_r, child_lr);
        // Grandchild to grandchild rotations
        consider_rotation!(child_ll, child_rl);
        consider_rotation!(child_ll, child_rr);

        let new_refit_node_index = if parent_index > 0 {
            Some(parent_index)
        } else {
            None
        };

        if best_rotation == None {
            // TODO Recalculate this node's AABBs (child_l_aabb, child_r_aabb)
            // according to the children nodes' AABBs.

            // Even with no rotation being useful for this node, a parent node's rotation
            // could be beneficial, so queue the parent sometimes.
            // TODO Return None most of the time, randomly
            // (see https://github.com/jeske/SimpleScene/blob/master/SimpleScene/Util/ssBVH/ssBVH_Node.cs#L307)
            new_refit_node_index
        } else {
            // TODO Perform rotation using rotate()

            // TODO Update all changed node AABBs

            // Return parent node's index for upcoming refitting,
            // since this node just changed its AABB
            new_refit_node_index
        }
    }

    /// Switch two nodes by rewiring the involved indices (not by moving them in the nodes slice).
    fn rotate(&mut self, node_a_index: usize, node_b_index: usize) {
        let mut nodes = &mut self.nodes;

        macro_rules! should_not_happen {
            () => ( panic!("While rotating BVH nodes, something unexpected happened."); );
            ($s:expr) => ( panic!("While rotating BVH nodes, something unexpected happened: {}", $s); );
        }

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn get_parent_index(nodes: &Vec<BVHNode>, node_index: usize) -> usize {
            let node = &nodes[node_index];

            match *node {
                BVHNode::Node { parent, .. } |
                BVHNode::Leaf { parent, .. } => parent,
                _ => should_not_happen!(),
            }
        }

        // Get parent indices
        let node_a_parent_index = get_parent_index(nodes, node_a_index);
        let node_b_parent_index = get_parent_index(nodes, node_b_index);

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn get_is_left_child(nodes: &Vec<BVHNode>,
                             node_index: usize,
                             node_parent_index: usize)
                             -> bool {
            let node_parent = &nodes[node_parent_index];

            match *node_parent {
                BVHNode::Node { child_l, .. } => child_l == node_index,
                _ => should_not_happen!(),
            }
        }

        // Get info about the nodes being a left or right child
        let node_a_is_left_child = get_is_left_child(nodes, node_a_index, node_a_parent_index);
        let node_b_is_left_child = get_is_left_child(nodes, node_b_index, node_b_parent_index);

        #[allow(dead_code)] // The compiler falsely detects dead code here
        fn connect_nodes(nodes: &mut Vec<BVHNode>,
                         child_index: usize,
                         parent_index: usize,
                         left_child: bool) {
            // Set parent's child and get its depth
            let parent_depth = {
                let mut parent = &mut nodes[parent_index];
                match parent {
                    &mut BVHNode::Node { ref mut child_l, ref mut child_r, depth, .. } => {
                        if left_child {
                            *child_l = child_index;
                        } else {
                            *child_r = child_index;
                        }
                        depth
                    }
                    _ => should_not_happen!(),
                }
            };

            // Set child's parent and depth
            {
                let mut child = &mut nodes[child_index];
                match child {
                    &mut BVHNode::Node { ref mut parent, ref mut depth, .. } |
                    &mut BVHNode::Leaf { ref mut parent, ref mut depth, .. } => {
                        *parent = parent_index;
                        *depth = parent_depth + 1;
                    }
                    _ => should_not_happen!(),
                };
            }
        }

        // Perform the switch
        connect_nodes(nodes,
                      node_a_index,
                      node_b_parent_index,
                      node_b_is_left_child);
        connect_nodes(nodes,
                      node_b_index,
                      node_a_parent_index,
                      node_a_is_left_child);
    }
}

#[cfg(test)]
pub mod tests {
    use bvh::BVH;

    #[test]
    /// Tests if the optimize function tries to change a fresh BVH even though it shouldn't
    fn test_optimizing_new_bvh() {
        let (mut shapes, mut bvh) = build_some_bh::<BVH>();

        let refit_shape_indices: HashSet<usize> = (0..shapes.len()).collect();
        bvh.optimize(&refit_shape_indices, &mut shapes);
    }

    // TODO Add tests for:
    // * correct parent
    // * correct depth
    // * correct BVH after optimizing
    // * correct parent and depth after optimizing
}
<|endoftext|>


<commit_before>use core::fmt::{Debug, Formatter, Result as FmtResult};

use futures_core::{Async, Poll};
use futures_core::task;
use futures_sink::{ Sink};

/// Sink that clones incoming items and forwards them to two sinks at the same time.
///
/// Backpressure from any downstream sink propagates up, which means that this sink
/// can only process items as fast as its _slowest_ downstream sink.
pub struct Fanout<A: Sink, B: Sink> {
    left: Downstream<A>,
    right: Downstream<B>
}

impl<A: Sink, B: Sink> Fanout<A, B> {
    /// Consumes this combinator, returning the underlying sinks.
    ///
    /// Note that this may discard intermediate state of this combinator,
    /// so care should be taken to avoid losing resources when this is called.
    pub fn into_inner(self) -> (A, B) {
        (self.left.sink, self.right.sink)
    }
}

impl<A: Sink + Debug, B: Sink + Debug> Debug for Fanout<A, B>
    where A::SinkItem: Debug,
          B::SinkItem: Debug
{
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        f.debug_struct("Fanout")
            .field("left", &self.left)
            .field("right", &self.right)
            .finish()
    }
}

pub fn new<A: Sink, B: Sink>(left: A, right: B) -> Fanout<A, B> {
    Fanout {
        left: Downstream::new(left),
        right: Downstream::new(right)
    }
}

impl<A, B> Sink for Fanout<A, B>
    where A: Sink,
          A::SinkItem: Clone,
          B: Sink<SinkItem=A::SinkItem, SinkError=A::SinkError>
{
    type SinkItem = A::SinkItem;
    type SinkError = A::SinkError;

    fn poll_ready(&mut self, cx: &mut task::Context) -> Poll<(), Self::SinkError> {
        self.left.keep_flushing(cx)?;
        self.right.keep_flushing(cx)?;
        if self.left.is_ready() && self.right.is_ready() {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::Pending)
        }
    }

    fn start_send(&mut self, item: Self::SinkItem) -> Result<(), Self::SinkError> {
        self.left.sink.start_send(item.clone())?;
        self.right.sink.start_send(item)?;
        Ok(())
    }

    fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<(), Self::SinkError> {
        let left_async = self.left.poll_flush(cx)?;
        let right_async = self.right.poll_flush(cx)?;

        if left_async.is_ready() && right_async.is_ready() {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::Pending)
        }
    }

    fn poll_close(&mut self, cx: &mut task::Context) -> Poll<(), Self::SinkError> {
        let left_async = self.left.poll_close(cx)?;
        let right_async = self.right.poll_close(cx)?;

        if left_async.is_ready() && right_async.is_ready() {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::Pending)
        }
    }
}

#[derive(Debug)]
struct Downstream<S: Sink> {
    sink: S,
    state: Option<S::SinkItem>,
}

impl<S: Sink> Downstream<S> {
    fn new(sink: S) -> Self {
        Downstream { sink: sink, state: None }
    }

    fn is_ready(&self) -> bool {
        self.state.is_none()
    }

    fn keep_flushing(&mut self, cx: &mut task::Context) -> Result<(), S::SinkError> {
        if let Async::Ready(()) = self.sink.poll_ready(cx)? {
            if let Some(item) = self.state.take() {
                self.sink.start_send(item)?;
            }
        }
        Ok(())
    }

    fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<(), S::SinkError> {
        self.keep_flushing(cx)?;
        let async = self.sink.poll_flush(cx)?;

        // Only if all values have been sent _and_ the underlying
        // sink is completely flushed, signal readiness.
        if self.state.is_none() && async.is_ready() {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::Pending)
        }
    }

    fn poll_close(&mut self, cx: &mut task::Context) -> Poll<(), S::SinkError> {
        self.keep_flushing(cx)?;
        let async = self.sink.poll_flush(cx)?;

        if self.is_ready() {
            try_ready!(self.sink.poll_close(cx));
        }

        // Only if all values have been sent _and_ the underlying
        // sink is completely flushed, signal readiness.
        if self.state.is_none() && async.is_ready() {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::Pending)
        }
    }
}
<commit_msg>Fixed Fanout sink which was always ready<commit_after>use core::fmt::{Debug, Formatter, Result as FmtResult};

use futures_core::{Async, Poll};
use futures_core::task;
use futures_sink::{ Sink};

/// Sink that clones incoming items and forwards them to two sinks at the same time.
///
/// Backpressure from any downstream sink propagates up, which means that this sink
/// can only process items as fast as its _slowest_ downstream sink.
pub struct Fanout<A: Sink, B: Sink> {
    left: A,
    right: B
}

impl<A: Sink, B: Sink> Fanout<A, B> {
    /// Consumes this combinator, returning the underlying sinks.
    ///
    /// Note that this may discard intermediate state of this combinator,
    /// so care should be taken to avoid losing resources when this is called.
    pub fn into_inner(self) -> (A, B) {
        (self.left, self.right)
    }
}

impl<A: Sink + Debug, B: Sink + Debug> Debug for Fanout<A, B>
    where A::SinkItem: Debug,
          B::SinkItem: Debug
{
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        f.debug_struct("Fanout")
            .field("left", &self.left)
            .field("right", &self.right)
            .finish()
    }
}

pub fn new<A: Sink, B: Sink>(left: A, right: B) -> Fanout<A, B> {
    Fanout {left, right}
}

impl<A, B> Sink for Fanout<A, B>
    where A: Sink,
          A::SinkItem: Clone,
          B: Sink<SinkItem=A::SinkItem, SinkError=A::SinkError>
{
    type SinkItem = A::SinkItem;
    type SinkError = A::SinkError;

    fn poll_ready(&mut self, cx: &mut task::Context) -> Poll<(), Self::SinkError> {
        let left_ready = self.left.poll_ready(cx)?.is_ready();
        let right_ready = self.right.poll_ready(cx)?.is_ready();
        let ready = left_ready && right_ready;
        Ok(if ready {Async::Ready(())} else {Async::Pending})
    }

    fn start_send(&mut self, item: Self::SinkItem) -> Result<(), Self::SinkError> {
        self.left.start_send(item.clone())?;
        self.right.start_send(item)?;
        Ok(())
    }

    fn poll_flush(&mut self, cx: &mut task::Context) -> Poll<(), Self::SinkError> {
        let left_ready = self.left.poll_flush(cx)?.is_ready();
        let right_ready = self.right.poll_flush(cx)?.is_ready();
        let ready = left_ready && right_ready;
        Ok(if ready {Async::Ready(())} else {Async::Pending})
    }

    fn poll_close(&mut self, cx: &mut task::Context) -> Poll<(), Self::SinkError> {
        let left_ready = self.left.poll_close(cx)?.is_ready();
        let right_ready = self.right.poll_close(cx)?.is_ready();
        let ready = left_ready && right_ready;
        Ok(if ready {Async::Ready(())} else {Async::Pending})
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::{self, File, OpenOptions};
use std::io;
use std::io::prelude::*;
use std::iter;
use std::path::{Component, Path, PathBuf};

use filetime::FileTime;

use crate::util::errors::{CargoResult, CargoResultExt, Internal};

pub fn join_paths<T: AsRef<OsStr>>(paths: &[T], env: &str) -> CargoResult<OsString> {
    let err = match env::join_paths(paths.iter()) {
        Ok(paths) => return Ok(paths),
        Err(e) => e,
    };
    let paths = paths.iter().map(Path::new).collect::<Vec<_>>();
    let err = failure::Error::from(err);
    let explain = Internal::new(failure::format_err!(
        "failed to join path array: {:?}",
        paths
    ));
    let err = failure::Error::from(err.context(explain));
    let more_explain = format!(
        "failed to join search paths together\n\
         Does ${} have an unterminated quote character?",
        env
    );
    Err(err.context(more_explain).into())
}

pub fn dylib_path_envvar() -> &'static str {
    if cfg!(windows) {
        "PATH"
    } else if cfg!(target_os = "macos") {
        "DYLD_LIBRARY_PATH"
    } else {
        "LD_LIBRARY_PATH"
    }
}

pub fn dylib_path() -> Vec<PathBuf> {
    match env::var_os(dylib_path_envvar()) {
        Some(var) => env::split_paths(&var).collect(),
        None => Vec::new(),
    }
}

pub fn normalize_path(path: &Path) -> PathBuf {
    let mut components = path.components().peekable();
    let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
        components.next();
        PathBuf::from(c.as_os_str())
    } else {
        PathBuf::new()
    };

    for component in components {
        match component {
            Component::Prefix(..) => unreachable!(),
            Component::RootDir => {
                ret.push(component.as_os_str());
            }
            Component::CurDir => {}
            Component::ParentDir => {
                ret.pop();
            }
            Component::Normal(c) => {
                ret.push(c);
            }
        }
    }
    ret
}

pub fn without_prefix<'a>(long_path: &'a Path, prefix: &'a Path) -> Option<&'a Path> {
    let mut a = long_path.components();
    let mut b = prefix.components();
    loop {
        match b.next() {
            Some(y) => match a.next() {
                Some(x) if x == y => continue,
                _ => return None,
            },
            None => return Some(a.as_path()),
        }
    }
}

pub fn resolve_executable(exec: &Path) -> CargoResult<PathBuf> {
    if exec.components().count() == 1 {
        let paths = env::var_os("PATH").ok_or_else(|| failure::format_err!("no PATH"))?;
        let candidates = env::split_paths(&paths).flat_map(|path| {
            let candidate = path.join(&exec);
            let with_exe = if env::consts::EXE_EXTENSION == "" {
                None
            } else {
                Some(candidate.with_extension(env::consts::EXE_EXTENSION))
            };
            iter::once(candidate).chain(with_exe)
        });
        for candidate in candidates {
            if candidate.is_file() {
                // PATH may have a component like "." in it, so we still need to
                // canonicalize.
                return Ok(candidate.canonicalize()?);
            }
        }

        failure::bail!("no executable for `{}` found in PATH", exec.display())
    } else {
        Ok(exec.canonicalize()?)
    }
}

pub fn read(path: &Path) -> CargoResult<String> {
    match String::from_utf8(read_bytes(path)?) {
        Ok(s) => Ok(s),
        Err(_) => failure::bail!("path at `{}` was not valid utf-8", path.display()),
    }
}

pub fn read_bytes(path: &Path) -> CargoResult<Vec<u8>> {
    let res = (|| -> CargoResult<_> {
        let mut ret = Vec::new();
        let mut f = File::open(path)?;
        if let Ok(m) = f.metadata() {
            ret.reserve(m.len() as usize + 1);
        }
        f.read_to_end(&mut ret)?;
        Ok(ret)
    })()
    .chain_err(|| format!("failed to read `{}`", path.display()))?;
    Ok(res)
}

pub fn write(path: &Path, contents: &[u8]) -> CargoResult<()> {
    (|| -> CargoResult<()> {
        let mut f = File::create(path)?;
        f.write_all(contents)?;
        Ok(())
    })()
    .chain_err(|| format!("failed to write `{}`", path.display()))?;
    Ok(())
}

pub fn write_if_changed<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> CargoResult<()> {
    (|| -> CargoResult<()> {
        let contents = contents.as_ref();
        let mut f = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)?;
        let mut orig = Vec::new();
        f.read_to_end(&mut orig)?;
        if orig != contents {
            f.set_len(0)?;
            f.seek(io::SeekFrom::Start(0))?;
            f.write_all(contents)?;
        }
        Ok(())
    })()
    .chain_err(|| format!("failed to write `{}`", path.as_ref().display()))?;
    Ok(())
}

pub fn append(path: &Path, contents: &[u8]) -> CargoResult<()> {
    (|| -> CargoResult<()> {
        let mut f = OpenOptions::new()
            .write(true)
            .append(true)
            .create(true)
            .open(path)?;

        f.write_all(contents)?;
        Ok(())
    })()
    .chain_err(|| format!("failed to write `{}`", path.display()))?;
    Ok(())
}

pub fn mtime(path: &Path) -> CargoResult<FileTime> {
    let meta = fs::metadata(path).chain_err(|| format!("failed to stat `{}`", path.display()))?;
    Ok(FileTime::from_last_modification_time(&meta))
}

#[cfg(unix)]
pub fn path2bytes(path: &Path) -> CargoResult<&[u8]> {
    use std::os::unix::prelude::*;
    Ok(path.as_os_str().as_bytes())
}
#[cfg(windows)]
pub fn path2bytes(path: &Path) -> CargoResult<&[u8]> {
    match path.as_os_str().to_str() {
        Some(s) => Ok(s.as_bytes()),
        None => Err(failure::format_err!(
            "invalid non-unicode path: {}",
            path.display()
        )),
    }
}

#[cfg(unix)]
pub fn bytes2path(bytes: &[u8]) -> CargoResult<PathBuf> {
    use std::ffi::OsStr;
    use std::os::unix::prelude::*;
    Ok(PathBuf::from(OsStr::from_bytes(bytes)))
}
#[cfg(windows)]
pub fn bytes2path(bytes: &[u8]) -> CargoResult<PathBuf> {
    use std::str;
    match str::from_utf8(bytes) {
        Ok(s) => Ok(PathBuf::from(s)),
        Err(..) => Err(failure::format_err!("invalid non-unicode path")),
    }
}

pub fn ancestors(path: &Path) -> PathAncestors<'_> {
    PathAncestors::new(path)
}

pub struct PathAncestors<'a> {
    current: Option<&'a Path>,
    stop_at: Option<PathBuf>,
}

impl<'a> PathAncestors<'a> {
    fn new(path: &Path) -> PathAncestors<'_> {
        PathAncestors {
            current: Some(path),
            //HACK: avoid reading `~/.cargo/config` when testing Cargo itself.
            stop_at: env::var("__CARGO_TEST_ROOT").ok().map(PathBuf::from),
        }
    }
}

impl<'a> Iterator for PathAncestors<'a> {
    type Item = &'a Path;

    fn next(&mut self) -> Option<&'a Path> {
        if let Some(path) = self.current {
            self.current = path.parent();

            if let Some(ref stop_at) = self.stop_at {
                if path == stop_at {
                    self.current = None;
                }
            }

            Some(path)
        } else {
            None
        }
    }
}

pub fn remove_dir_all<P: AsRef<Path>>(p: P) -> CargoResult<()> {
    _remove_dir_all(p.as_ref())
}

fn _remove_dir_all(p: &Path) -> CargoResult<()> {
    if p.symlink_metadata()?.file_type().is_symlink() {
        return remove_file(p);
    }
    let entries = p
        .read_dir()
        .chain_err(|| format!("failed to read directory `{}`", p.display()))?;
    for entry in entries {
        let entry = entry?;
        let path = entry.path();
        if entry.file_type()?.is_dir() {
            remove_dir_all(&path)?;
        } else {
            remove_file(&path)?;
        }
    }
    remove_dir(&p)
}

pub fn remove_dir<P: AsRef<Path>>(p: P) -> CargoResult<()> {
    _remove_dir(p.as_ref())
}

fn _remove_dir(p: &Path) -> CargoResult<()> {
    fs::remove_dir(p).chain_err(|| format!("failed to remove directory `{}`", p.display()))?;
    Ok(())
}

pub fn remove_file<P: AsRef<Path>>(p: P) -> CargoResult<()> {
    _remove_file(p.as_ref())
}

fn _remove_file(p: &Path) -> CargoResult<()> {
    let mut err = match fs::remove_file(p) {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if err.kind() == io::ErrorKind::PermissionDenied && set_not_readonly(p).unwrap_or(false) {
        match fs::remove_file(p) {
            Ok(()) => return Ok(()),
            Err(e) => err = e,
        }
    }

    Err(err).chain_err(|| format!("failed to remove file `{}`", p.display()))?;
    Ok(())
}

fn set_not_readonly(p: &Path) -> io::Result<bool> {
    let mut perms = p.metadata()?.permissions();
    if !perms.readonly() {
        return Ok(false);
    }
    perms.set_readonly(false);
    fs::set_permissions(p, perms)?;
    Ok(true)
}
<commit_msg>Auto merge of #6355 - MarcusCalhoun-Lopez:dyld_fix, r=alexcrichton<commit_after>use std::env;
use std::ffi::{OsStr, OsString};
use std::fs::{self, File, OpenOptions};
use std::io;
use std::io::prelude::*;
use std::iter;
use std::path::{Component, Path, PathBuf};

use filetime::FileTime;

use crate::util::errors::{CargoResult, CargoResultExt, Internal};

pub fn join_paths<T: AsRef<OsStr>>(paths: &[T], env: &str) -> CargoResult<OsString> {
    let err = match env::join_paths(paths.iter()) {
        Ok(paths) => return Ok(paths),
        Err(e) => e,
    };
    let paths = paths.iter().map(Path::new).collect::<Vec<_>>();
    let err = failure::Error::from(err);
    let explain = Internal::new(failure::format_err!(
        "failed to join path array: {:?}",
        paths
    ));
    let err = failure::Error::from(err.context(explain));
    let more_explain = format!(
        "failed to join search paths together\n\
         Does ${} have an unterminated quote character?",
        env
    );
    Err(err.context(more_explain).into())
}

pub fn dylib_path_envvar() -> &'static str {
    if cfg!(windows) {
        "PATH"
    } else if cfg!(target_os = "macos") {
        // When loading and linking a dynamic library or bundle, dlopen
        // searches in LD_LIBRARY_PATH, DYLD_LIBRARY_PATH, PWD, and
        // DYLD_FALLBACK_LIBRARY_PATH.
        // In the Mach-O format, a dynamic library has an "install path."
        // Clients linking against the library record this path, and the
        // dynamic linker, dyld, uses it to locate the library.
        // dyld searches DYLD_LIBRARY_PATH *before* the install path.
        // dyld searches DYLD_FALLBACK_LIBRARY_PATH only if it cannot
        // find the library in the install path.
        // Setting DYLD_LIBRARY_PATH can easily have unintended
        // consequences.
        "DYLD_FALLBACK_LIBRARY_PATH"
    } else {
        "LD_LIBRARY_PATH"
    }
}

pub fn dylib_path() -> Vec<PathBuf> {
    match env::var_os(dylib_path_envvar()) {
        Some(var) => env::split_paths(&var).collect(),
        None => Vec::new(),
    }
}

pub fn normalize_path(path: &Path) -> PathBuf {
    let mut components = path.components().peekable();
    let mut ret = if let Some(c @ Component::Prefix(..)) = components.peek().cloned() {
        components.next();
        PathBuf::from(c.as_os_str())
    } else {
        PathBuf::new()
    };

    for component in components {
        match component {
            Component::Prefix(..) => unreachable!(),
            Component::RootDir => {
                ret.push(component.as_os_str());
            }
            Component::CurDir => {}
            Component::ParentDir => {
                ret.pop();
            }
            Component::Normal(c) => {
                ret.push(c);
            }
        }
    }
    ret
}

pub fn without_prefix<'a>(long_path: &'a Path, prefix: &'a Path) -> Option<&'a Path> {
    let mut a = long_path.components();
    let mut b = prefix.components();
    loop {
        match b.next() {
            Some(y) => match a.next() {
                Some(x) if x == y => continue,
                _ => return None,
            },
            None => return Some(a.as_path()),
        }
    }
}

pub fn resolve_executable(exec: &Path) -> CargoResult<PathBuf> {
    if exec.components().count() == 1 {
        let paths = env::var_os("PATH").ok_or_else(|| failure::format_err!("no PATH"))?;
        let candidates = env::split_paths(&paths).flat_map(|path| {
            let candidate = path.join(&exec);
            let with_exe = if env::consts::EXE_EXTENSION == "" {
                None
            } else {
                Some(candidate.with_extension(env::consts::EXE_EXTENSION))
            };
            iter::once(candidate).chain(with_exe)
        });
        for candidate in candidates {
            if candidate.is_file() {
                // PATH may have a component like "." in it, so we still need to
                // canonicalize.
                return Ok(candidate.canonicalize()?);
            }
        }

        failure::bail!("no executable for `{}` found in PATH", exec.display())
    } else {
        Ok(exec.canonicalize()?)
    }
}

pub fn read(path: &Path) -> CargoResult<String> {
    match String::from_utf8(read_bytes(path)?) {
        Ok(s) => Ok(s),
        Err(_) => failure::bail!("path at `{}` was not valid utf-8", path.display()),
    }
}

pub fn read_bytes(path: &Path) -> CargoResult<Vec<u8>> {
    let res = (|| -> CargoResult<_> {
        let mut ret = Vec::new();
        let mut f = File::open(path)?;
        if let Ok(m) = f.metadata() {
            ret.reserve(m.len() as usize + 1);
        }
        f.read_to_end(&mut ret)?;
        Ok(ret)
    })()
    .chain_err(|| format!("failed to read `{}`", path.display()))?;
    Ok(res)
}

pub fn write(path: &Path, contents: &[u8]) -> CargoResult<()> {
    (|| -> CargoResult<()> {
        let mut f = File::create(path)?;
        f.write_all(contents)?;
        Ok(())
    })()
    .chain_err(|| format!("failed to write `{}`", path.display()))?;
    Ok(())
}

pub fn write_if_changed<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> CargoResult<()> {
    (|| -> CargoResult<()> {
        let contents = contents.as_ref();
        let mut f = OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(&path)?;
        let mut orig = Vec::new();
        f.read_to_end(&mut orig)?;
        if orig != contents {
            f.set_len(0)?;
            f.seek(io::SeekFrom::Start(0))?;
            f.write_all(contents)?;
        }
        Ok(())
    })()
    .chain_err(|| format!("failed to write `{}`", path.as_ref().display()))?;
    Ok(())
}

pub fn append(path: &Path, contents: &[u8]) -> CargoResult<()> {
    (|| -> CargoResult<()> {
        let mut f = OpenOptions::new()
            .write(true)
            .append(true)
            .create(true)
            .open(path)?;

        f.write_all(contents)?;
        Ok(())
    })()
    .chain_err(|| format!("failed to write `{}`", path.display()))?;
    Ok(())
}

pub fn mtime(path: &Path) -> CargoResult<FileTime> {
    let meta = fs::metadata(path).chain_err(|| format!("failed to stat `{}`", path.display()))?;
    Ok(FileTime::from_last_modification_time(&meta))
}

#[cfg(unix)]
pub fn path2bytes(path: &Path) -> CargoResult<&[u8]> {
    use std::os::unix::prelude::*;
    Ok(path.as_os_str().as_bytes())
}
#[cfg(windows)]
pub fn path2bytes(path: &Path) -> CargoResult<&[u8]> {
    match path.as_os_str().to_str() {
        Some(s) => Ok(s.as_bytes()),
        None => Err(failure::format_err!(
            "invalid non-unicode path: {}",
            path.display()
        )),
    }
}

#[cfg(unix)]
pub fn bytes2path(bytes: &[u8]) -> CargoResult<PathBuf> {
    use std::ffi::OsStr;
    use std::os::unix::prelude::*;
    Ok(PathBuf::from(OsStr::from_bytes(bytes)))
}
#[cfg(windows)]
pub fn bytes2path(bytes: &[u8]) -> CargoResult<PathBuf> {
    use std::str;
    match str::from_utf8(bytes) {
        Ok(s) => Ok(PathBuf::from(s)),
        Err(..) => Err(failure::format_err!("invalid non-unicode path")),
    }
}

pub fn ancestors(path: &Path) -> PathAncestors<'_> {
    PathAncestors::new(path)
}

pub struct PathAncestors<'a> {
    current: Option<&'a Path>,
    stop_at: Option<PathBuf>,
}

impl<'a> PathAncestors<'a> {
    fn new(path: &Path) -> PathAncestors<'_> {
        PathAncestors {
            current: Some(path),
            //HACK: avoid reading `~/.cargo/config` when testing Cargo itself.
            stop_at: env::var("__CARGO_TEST_ROOT").ok().map(PathBuf::from),
        }
    }
}

impl<'a> Iterator for PathAncestors<'a> {
    type Item = &'a Path;

    fn next(&mut self) -> Option<&'a Path> {
        if let Some(path) = self.current {
            self.current = path.parent();

            if let Some(ref stop_at) = self.stop_at {
                if path == stop_at {
                    self.current = None;
                }
            }

            Some(path)
        } else {
            None
        }
    }
}

pub fn remove_dir_all<P: AsRef<Path>>(p: P) -> CargoResult<()> {
    _remove_dir_all(p.as_ref())
}

fn _remove_dir_all(p: &Path) -> CargoResult<()> {
    if p.symlink_metadata()?.file_type().is_symlink() {
        return remove_file(p);
    }
    let entries = p
        .read_dir()
        .chain_err(|| format!("failed to read directory `{}`", p.display()))?;
    for entry in entries {
        let entry = entry?;
        let path = entry.path();
        if entry.file_type()?.is_dir() {
            remove_dir_all(&path)?;
        } else {
            remove_file(&path)?;
        }
    }
    remove_dir(&p)
}

pub fn remove_dir<P: AsRef<Path>>(p: P) -> CargoResult<()> {
    _remove_dir(p.as_ref())
}

fn _remove_dir(p: &Path) -> CargoResult<()> {
    fs::remove_dir(p).chain_err(|| format!("failed to remove directory `{}`", p.display()))?;
    Ok(())
}

pub fn remove_file<P: AsRef<Path>>(p: P) -> CargoResult<()> {
    _remove_file(p.as_ref())
}

fn _remove_file(p: &Path) -> CargoResult<()> {
    let mut err = match fs::remove_file(p) {
        Ok(()) => return Ok(()),
        Err(e) => e,
    };

    if err.kind() == io::ErrorKind::PermissionDenied && set_not_readonly(p).unwrap_or(false) {
        match fs::remove_file(p) {
            Ok(()) => return Ok(()),
            Err(e) => err = e,
        }
    }

    Err(err).chain_err(|| format!("failed to remove file `{}`", p.display()))?;
    Ok(())
}

fn set_not_readonly(p: &Path) -> io::Result<bool> {
    let mut perms = p.metadata()?.permissions();
    if !perms.readonly() {
        return Ok(false);
    }
    perms.set_readonly(false);
    fs::set_permissions(p, perms)?;
    Ok(true)
}
<|endoftext|>


<commit_before>//! This pass replaces a drop of a type that does not need dropping, with a goto

use crate::transform::MirPass;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::{ParamEnv, TyCtxt};

use super::simplify::simplify_cfg;

pub struct RemoveUnneededDrops;

impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        trace!("Running RemoveUnneededDrops on {:?}", body.source);
        let mut opt_finder = RemoveUnneededDropsOptimizationFinder {
            tcx,
            body,
            param_env: tcx.param_env(body.source.def_id()),
            optimizations: vec![],
        };
        opt_finder.visit_body(body);
        let should_simplify = !opt_finder.optimizations.is_empty();
        for (loc, target) in opt_finder.optimizations {
            if !tcx
                .consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", body.source.def_id()))
            {
                break;
            }

            let terminator = body.basic_blocks_mut()[loc.block].terminator_mut();
            debug!("SUCCESS: replacing `drop` with goto({:?})", target);
            terminator.kind = TerminatorKind::Goto { target };
        }

        // if we applied optimizations, we potentially have some cfg to cleanup to
        // make it easier for further passes
        if should_simplify {
            simplify_cfg(body);
        }
    }
}

impl<'a, 'tcx> Visitor<'tcx> for RemoveUnneededDropsOptimizationFinder<'a, 'tcx> {
    fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
        match terminator.kind {
            TerminatorKind::Drop { place, target, .. } => {
                let ty = place.ty(self.body, self.tcx);
                let needs_drop = ty.ty.needs_drop(self.tcx, self.param_env);
                if !needs_drop {
                    self.optimizations.push((location, target));
                }
            }
            _ => {}
        }
        self.super_terminator(terminator, location);
    }
}
pub struct RemoveUnneededDropsOptimizationFinder<'a, 'tcx> {
    tcx: TyCtxt<'tcx>,
    body: &'a Body<'tcx>,
    optimizations: Vec<(Location, BasicBlock)>,
    param_env: ParamEnv<'tcx>,
}
<commit_msg>Auto merge of #81122 - tmiasko:no-drop, r=davidtwco<commit_after>//! This pass replaces a drop of a type that does not need dropping, with a goto

use crate::transform::MirPass;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;

use super::simplify::simplify_cfg;

pub struct RemoveUnneededDrops;

impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
        trace!("Running RemoveUnneededDrops on {:?}", body.source);

        let did = body.source.def_id();
        let param_env = tcx.param_env(did);
        let mut should_simplify = false;

        let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
        for block in basic_blocks {
            let terminator = block.terminator_mut();
            if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
                let ty = place.ty(local_decls, tcx);
                if ty.ty.needs_drop(tcx, param_env) {
                    continue;
                }
                if !tcx.consider_optimizing(|| format!("RemoveUnneededDrops {:?} ", did)) {
                    continue;
                }
                debug!("SUCCESS: replacing `drop` with goto({:?})", target);
                terminator.kind = TerminatorKind::Goto { target };
                should_simplify = true;
            }
        }

        // if we applied optimizations, we potentially have some cfg to cleanup to
        // make it easier for further passes
        if should_simplify {
            simplify_cfg(body);
        }
    }
}
<|endoftext|>


<commit_before>use std::result;

/// Error type
///
/// `cfitsio` passes errors through integer status codes. This struct wraps this and its associated
/// error message.
#[derive(Debug, PartialEq, Eq)]
pub struct FitsError {
    pub status: i32,
    pub message: String,
}

/// Macro for returning a FITS error type
macro_rules! fits_try {
    ($status: ident, $e: expr) => {
        match $status {
            0 => Ok($e),
            _ => {
                Err(FitsError {
                    status: $status,
                    message: stringutils::status_to_string($status).unwrap(),
                })
            }
        }
    }
}

/// FITS specific result type
///
/// This is a shortcut for a result with `FitsError` as the error type
pub type Result<T> = result::Result<T, FitsError>;
<commit_msg>Add function to convert status to Err(FitsError)<commit_after>use std::result;
use super::stringutils::status_to_string;

/// Error type
///
/// `cfitsio` passes errors through integer status codes. This struct wraps this and its associated
/// error message.
#[derive(Debug, PartialEq, Eq)]
pub struct FitsError {
    pub status: i32,
    pub message: String,
}

/// Macro for returning a FITS error type
macro_rules! fits_try {
    ($status: ident, $e: expr) => {
        match $status {
            0 => Ok($e),
            _ => {
                Err(FitsError {
                    status: $status,
                    message: stringutils::status_to_string($status).unwrap(),
                })
            }
        }
    }
}

/// FITS specific result type
///
/// This is a shortcut for a result with `FitsError` as the error type
pub type Result<T> = result::Result<T, FitsError>;

pub fn status_to_error(status: i32) -> Result<()> {
    Err(FitsError {
        status: status,
        message: status_to_string(status).unwrap(),
    })
}
<|endoftext|>


<commit_before>use crypto::digest::Digest;
use crypto::sha1::Sha1;
use num;
use std::fmt;

pub const LENGTH: usize = 160;

#[derive(Clone,Copy,Eq,Hash,PartialEq)]
pub struct Address {
    data: [u8; 20]
}

impl Address {
    pub fn for_content(content: &str) -> Address {
        let mut hasher = Sha1::new();
        hasher.input_str(content);
        let mut data = [0; 20];
        hasher.result(&mut data);
        Address {
            data: data
        }
    }

    pub fn from_str(string: &str) -> Address {
        use rustc_serialize::hex::FromHex;
        let bytes = string.from_hex().unwrap();
        let mut data = [0u8; 20];
        for (place, byte) in data.iter_mut().zip(bytes.iter()) {
            *place = *byte;
        }
        Address {
            data: data
        }
    }

    pub fn null() -> Address {
        let data = [0u8; 20];
        Address { data: data }
    }

    pub fn as_numeric(&self) -> num::BigUint {
        num::BigUint::from_bytes_be(&self.data)
    }

    pub fn distance_from(&self, other: &Self) -> num::BigUint {
        use std::ops::BitXor;
        self.as_numeric().bitxor(other.as_numeric())
    }

    pub fn to_str(&self) -> String {
        use rustc_serialize::hex::ToHex;
        self.data.to_hex()
    }
}

pub trait Addressable {
    fn get_address(&self) -> Address;
}

impl fmt::Debug for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Address {{ {} }}", self.to_str())
    }
}

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

    #[test]
    fn test_for_content() {
        let address = Address::for_content("some string");
        assert_eq!(address.to_str(), "8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
    }

    #[test]
    fn test_from_str() {
        let address = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        assert_eq!(address.to_str(), "8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
    }

    #[test]
    fn test_as_numeric() {
        use num::bigint::ToBigUint;

        let address = Address::from_str("000000000000000000000000000000000000000f");
        assert_eq!(address.as_numeric(), 15u8.to_biguint().unwrap());
        let address = Address::from_str("00000000000000000000000000000000000000f0");
        assert_eq!(address.as_numeric(), 240u8.to_biguint().unwrap());
    }

    #[test]
    fn test_equal() {
        let a = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        let b = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        assert_eq!(a, b);
    }

    #[test]
    fn test_not_equal() {
        let a = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        let b = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3f");
        assert!(a != b);
    }
}
<commit_msg>Remove unnecessary number suffix<commit_after>use crypto::digest::Digest;
use crypto::sha1::Sha1;
use num;
use std::fmt;

pub const LENGTH: usize = 160;

#[derive(Clone,Copy,Eq,Hash,PartialEq)]
pub struct Address {
    data: [u8; 20]
}

impl Address {
    pub fn for_content(content: &str) -> Address {
        let mut hasher = Sha1::new();
        hasher.input_str(content);
        let mut data = [0; 20];
        hasher.result(&mut data);
        Address {
            data: data
        }
    }

    pub fn from_str(string: &str) -> Address {
        use rustc_serialize::hex::FromHex;
        let bytes = string.from_hex().unwrap();
        let mut data = [0u8; 20];
        for (place, byte) in data.iter_mut().zip(bytes.iter()) {
            *place = *byte;
        }
        Address {
            data: data
        }
    }

    pub fn null() -> Address {
        let data = [0; 20];
        Address { data: data }
    }

    pub fn as_numeric(&self) -> num::BigUint {
        num::BigUint::from_bytes_be(&self.data)
    }

    pub fn distance_from(&self, other: &Self) -> num::BigUint {
        use std::ops::BitXor;
        self.as_numeric().bitxor(other.as_numeric())
    }

    pub fn to_str(&self) -> String {
        use rustc_serialize::hex::ToHex;
        self.data.to_hex()
    }
}

pub trait Addressable {
    fn get_address(&self) -> Address;
}

impl fmt::Debug for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Address {{ {} }}", self.to_str())
    }
}

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

    #[test]
    fn test_for_content() {
        let address = Address::for_content("some string");
        assert_eq!(address.to_str(), "8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
    }

    #[test]
    fn test_from_str() {
        let address = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        assert_eq!(address.to_str(), "8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
    }

    #[test]
    fn test_as_numeric() {
        use num::bigint::ToBigUint;

        let address = Address::from_str("000000000000000000000000000000000000000f");
        assert_eq!(address.as_numeric(), 15u8.to_biguint().unwrap());
        let address = Address::from_str("00000000000000000000000000000000000000f0");
        assert_eq!(address.as_numeric(), 240u8.to_biguint().unwrap());
    }

    #[test]
    fn test_equal() {
        let a = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        let b = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        assert_eq!(a, b);
    }

    #[test]
    fn test_not_equal() {
        let a = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3e");
        let b = Address::from_str("8b45e4bd1c6acb88bebf6407d16205f567e62a3f");
        assert!(a != b);
    }
}
<|endoftext|>


<commit_before>use request::{Request, ToRequest};
use service::Service;
use application::Application;
use user::User;

#[derive(Debug)]
pub enum Type {
    Authorize,
    AuthRep,
    Report
}

impl Type {
    pub fn method(&self) -> String {
        use self::Type::*;
        match *self {
            Report => "POST".to_owned(),
            AuthRep | Authorize => "GET".to_owned(),
        }
    }
}

#[derive(Debug)]
pub struct Info<'service, 'app, 'user> {
    kind: Type,
    service: &'service Service,
    application: &'app Application,
    user: Option<&'user User>,
}

// TODO: define endpoints for oauth
const AUTH_ENDPOINT: &str = "/transactions/authorize.xml";
const AUTHREP_ENDPOINT: &str = "/transactions/authrep.xml";
const REPORT_ENDPOINT: &str = "/transactions.xml";

impl<'service, 'app, 'user> Info<'service, 'app, 'user> {
    pub fn new(kind: Type, service: &'service Service, application: &'app Application, user: Option<&'user User>) -> Self {
        Self { kind, service, application, user }
    }

    fn endpoint(&self) -> &str {
        use self::Type::*;

        match self.kind {
            Authorize => AUTH_ENDPOINT,
            AuthRep => AUTHREP_ENDPOINT,
            Report => REPORT_ENDPOINT,
        }
    }

    fn path(&self) -> String {
        use request::ToParams;

        let mut params: Vec<(&str, &str)> = Vec::new();
        params.extend(self.service.to_params().iter());
        params.extend(self.application.to_params().iter());

        if let Some(user_params) = self.user.as_ref() {
            params.extend(user_params.to_params().iter());
        }

        let params = params.iter()
            .map(|&(param, value)| param.to_owned() + "=" + value)
            .collect::<Vec<String>>()
            .join("&");

        self.endpoint().to_owned() + "?" + params.as_str()
    }
}

impl<'service, 'app, 'user> ToRequest for Info<'service, 'app, 'user> {
    fn to_request(&self) -> Request {
        Request::new(self.kind.method(), self.path(), None)
    }
}
<commit_msg>apicall: iter cleanups<commit_after>use request::{Request, ToRequest};
use service::Service;
use application::Application;
use user::User;

#[derive(Debug)]
pub enum Type {
    Authorize,
    AuthRep,
    Report
}

impl Type {
    pub fn method(&self) -> String {
        use self::Type::*;
        match *self {
            Report => "POST".to_owned(),
            AuthRep | Authorize => "GET".to_owned(),
        }
    }
}

#[derive(Debug)]
pub struct Info<'service, 'app, 'user> {
    kind: Type,
    service: &'service Service,
    application: &'app Application,
    user: Option<&'user User>,
}

// TODO: define endpoints for oauth
const AUTH_ENDPOINT: &str = "/transactions/authorize.xml";
const AUTHREP_ENDPOINT: &str = "/transactions/authrep.xml";
const REPORT_ENDPOINT: &str = "/transactions.xml";

impl<'service, 'app, 'user> Info<'service, 'app, 'user> {
    pub fn new(kind: Type, service: &'service Service, application: &'app Application, user: Option<&'user User>) -> Self {
        Self { kind, service, application, user }
    }

    fn endpoint(&self) -> &str {
        use self::Type::*;

        match self.kind {
            Authorize => AUTH_ENDPOINT,
            AuthRep => AUTHREP_ENDPOINT,
            Report => REPORT_ENDPOINT,
        }
    }

    fn path(&self) -> String {
        use request::ToParams;

        let mut params: Vec<(&str, &str)> = Vec::new();
        params.extend(self.service.to_params());
        params.extend(self.application.to_params());

        if let Some(user_params) = self.user.as_ref() {
            params.extend(user_params.to_params());
        }

        let params = params.into_iter()
            .map(|(param, value)| param.to_owned() + "=" + value)
            .collect::<Vec<String>>()
            .join("&");

        self.endpoint().to_owned() + "?" + params.as_str()
    }
}

impl<'service, 'app, 'user> ToRequest for Info<'service, 'app, 'user> {
    fn to_request(&self) -> Request {
        Request::new(self.kind.method(), self.path(), None)
    }
}
<|endoftext|>


<commit_before>use request::{Request, ToRequest};
use service::Service;
use application::Application;
use user::User;

#[derive(Debug)]
pub enum Type {
    Authorize,
    AuthRep,
    Report
}

impl Type {
    pub fn method(&self) -> String {
        use self::Type::*;
        match *self {
            Report => "POST".to_owned(),
            AuthRep | Authorize => "GET".to_owned(),
        }
    }
}

#[derive(Debug)]
pub struct Info<'service, 'app, 'user> {
    kind: Type,
    service: &'service Service,
    application: &'app Application,
    user: Option<&'user User>,
}

impl<'service, 'app, 'user> Info<'service, 'app, 'user> {
    pub fn new(kind: Type, service: &'service Service, application: &'app Application, user: Option<&'user User>) -> Self {
        Self { kind, service, application, user }
    }
}

impl<'service, 'app, 'user> ToRequest for Info<'service, 'app, 'user> {
    fn to_request(&self) -> Request {
        use request::ToParams;

        let mut path: String = self.service.to_params();

        path.push_str(self.application.to_params().as_str());

        if let Some(user_params) = self.user.as_ref() {
            path.push_str(user_params.to_params().as_str());
        }

        Request::new(self.kind.method(), path, None)
    }
}<commit_msg>apicall: complete to_request()<commit_after>use request::{Request, ToRequest};
use service::Service;
use application::Application;
use user::User;

#[derive(Debug)]
pub enum Type {
    Authorize,
    AuthRep,
    Report
}

impl Type {
    pub fn method(&self) -> String {
        use self::Type::*;
        match *self {
            Report => "POST".to_owned(),
            AuthRep | Authorize => "GET".to_owned(),
        }
    }
}

#[derive(Debug)]
pub struct Info<'service, 'app, 'user> {
    kind: Type,
    service: &'service Service,
    application: &'app Application,
    user: Option<&'user User>,
}

// TODO: define endpoints for oauth
const AUTH_ENDPOINT: &str = "/transactions/authorize.xml";
const AUTHREP_ENDPOINT: &str = "/transactions/authrep.xml";
const REPORT_ENDPOINT: &str = "/transactions.xml";

impl<'service, 'app, 'user> Info<'service, 'app, 'user> {
    pub fn new(kind: Type, service: &'service Service, application: &'app Application, user: Option<&'user User>) -> Self {
        Self { kind, service, application, user }
    }

    fn endpoint(&self) -> &str {
        use self::Type::*;

        match self.kind {
            Authorize => AUTH_ENDPOINT,
            AuthRep => AUTHREP_ENDPOINT,
            Report => REPORT_ENDPOINT,
        }
    }

    fn path(&self) -> String {
        use request::ToParams;

        let mut params: Vec<(&str, &str)> = Vec::new();
        params.extend(self.service.to_params().iter());
        params.extend(self.application.to_params().iter());

        if let Some(user_params) = self.user.as_ref() {
            params.extend(user_params.to_params().iter());
        }

        let params = params.iter()
            .map(|&(param, value)| param.to_owned() + "=" + value)
            .collect::<Vec<String>>()
            .join("&");

        self.endpoint().to_owned() + "?" + params.as_str()
    }
}

impl<'service, 'app, 'user> ToRequest for Info<'service, 'app, 'user> {
    fn to_request(&self) -> Request {
        Request::new(self.kind.method(), self.path(), None)
    }
}<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::hash_map::{self, HashMap};
use std::fmt;

use rustc_serialize::base64::{self, ToBase64};

use crypto::PublicKey;
use block::HashedBlockExt;
use error::{SimplesError, SimplesResult};
use simples_pb::{Balance, BalancePatch, BlockPatch, HashedBlock,
                 Transaction, Transfer};

pub fn make_genesis_patch(genesis: &HashedBlock) -> SimplesResult<BlockPatch> {
    try!(genesis.verify());
    let txes = genesis.get_block().get_transactions();
    match txes.len() {
        0 => Ok(BlockPatch::new()),
        1 => {
            let mut cache = HashMap::<PublicKey, u64>::new();
            let commit = txes[0].get_commit();
            for transfer in commit.get_transfers() {
                let destination =
                    try!(PublicKey::from_bytes(transfer.get_destination_pk()));
                match cache.entry(destination) {
                    hash_map::Entry::Occupied(mut tokens) => {
                        let new_balance = tokens.get() + transfer.get_tokens();
                        tokens.insert(new_balance);
                    },
                    hash_map::Entry::Vacant(tokens) => {
                        tokens.insert(transfer.get_tokens());
                    }
                };
            }
            let mut block_patch = BlockPatch::new();
            for (address, tokens) in cache.into_iter() {
                let mut before = Balance::new();
                before.set_tokens(0u64);
                before.set_op_index(0u32);

                let mut after = Balance::new();
                after.set_tokens(tokens);
                after.set_op_index(0u32);

                let mut patch = BalancePatch::new();
                patch.set_public_key(address.0.to_vec());
                patch.set_before(before);
                patch.set_after(after);
                block_patch.mut_patches().push(patch);
            }
            Ok(block_patch)
        },
        _ => Err(SimplesError::new(
            "Genesis block must contain at most 1 transaction."))
    }
}

pub trait BalancePatchExt {
    fn decode_public_key(&self) -> SimplesResult<PublicKey>;
    fn reverse(&self) -> Self;
}

impl BalancePatchExt for BalancePatch {
    fn decode_public_key(&self) -> SimplesResult<PublicKey> {
        PublicKey::from_bytes(&self.get_public_key())
    }

    fn reverse(&self) -> Self {
        let mut reversed = BalancePatch::new();
        reversed.set_public_key(self.get_public_key().to_vec());
        reversed.set_before(self.get_after().clone());
        reversed.set_after(self.get_before().clone());
        reversed
    }
}

pub trait LedgerReader {
    fn get_balance(&self, address: &PublicKey) -> SimplesResult<Balance>;
}

pub trait LedgerWriter {
    fn set_balance(&mut self, address: &PublicKey, balance: Balance)
                   -> SimplesResult<()>;
}

pub trait Patchable {
    fn apply_patch(&mut self, patch: BalancePatch) -> SimplesResult<()>;
}

impl<LedgerMutator: LedgerReader + LedgerWriter>
    Patchable for LedgerMutator {
    fn apply_patch(&mut self, patch: BalancePatch) -> SimplesResult<()> {
        let public_key = try!(PublicKey::from_bytes(patch.get_public_key()));
        let before_balance = try!(self.get_balance(&public_key));
        if before_balance != *patch.get_before() {
            return Err(SimplesError::new(&format!(
                "Actual initial balance ({}, {}) != ({}, {}) from the patch.",
                before_balance.get_tokens(), before_balance.get_op_index(),
                patch.get_before().get_tokens(),
                patch.get_before().get_op_index())[]));
        }
        try!(self.set_balance(&public_key, patch.get_after().clone()));
        Ok(())
    }
}

pub struct LedgerSnapshot<'a, LedgerReadOnly: 'a + LedgerReader> {
    cache: RefCell<HashMap<PublicKey, BalancePatch>>,
    store: &'a LedgerReadOnly
}

impl<'a, L: 'a + LedgerReader> LedgerSnapshot<'a, L> {
    pub fn new(store: &'a L) -> LedgerSnapshot<'a, L> {
        LedgerSnapshot {
            cache: RefCell::new(HashMap::<PublicKey, BalancePatch>::new()),
            store: store
        }
    }

    pub fn clear(&mut self) { self.cache.borrow_mut().clear(); }

    pub fn add_transfer(&mut self, transfer: &Transfer) ->
        SimplesResult<()>
    {
        let source_pk = try!(PublicKey::from_bytes(transfer.get_source_pk()));
        let destination_pk =
            try!(PublicKey::from_bytes(transfer.get_destination_pk()));
        let mut source = try!(self.get_balance(&source_pk));
        let mut destination = try!(self.get_balance(&destination_pk));

        if source.get_tokens() >= transfer.get_tokens() {
            // println!("source: {}",
            //          transfer.get_source_pk().to_base64(base64::STANDARD));
            // println!("destination: {}",
            //          transfer.get_destination_pk().to_base64(base64::STANDARD));
            if transfer.get_op_index() == source.get_op_index() {
                // println!("num: {} / tokens: {} / balance: {} -> {}\n",
                //          source.get_op_index(), transfer.get_tokens(),
                //          source.get_tokens(),
                //          source.get_tokens() - transfer.get_tokens());

                let source_tokens = source.get_tokens() - transfer.get_tokens();
                let source_op_index = source.get_op_index() + 1;
                let dest_tokens = destination.get_tokens() + transfer.get_tokens();
                source.set_tokens(source_tokens);
                source.set_op_index(source_op_index);
                destination.set_tokens(dest_tokens);

                try!(self.set_balance(&source_pk, source));
                try!(self.set_balance(&destination_pk, destination));
                Ok(())
            } else {
                Err(SimplesError::new(&format!(
                    "Wrong op number for source address {}: op_index was
{} != {} (required)", source_pk, transfer.get_op_index(), source.get_op_index())[]))
            }
        } else {
            Err(SimplesError::new(&format!(
                "ERROR: Not enough funds. Source address balance is {} but
{} tokens were transferred: {} -> {}", source.get_tokens(), transfer.get_tokens(),
                source_pk, destination_pk)[]))
        }
    }

    pub fn apply_transaction(
        &mut self, transaction: &Transaction) -> SimplesResult<()> {
        for transfer in transaction.get_commit().get_transfers().iter() {
            try!(self.add_transfer(transfer));
        }
        Ok(())
    }

    pub fn apply_block(&mut self, block: &HashedBlock) -> SimplesResult<()> {
        for transaction in block.get_block().get_transactions().iter() {
            try!(self.apply_transaction(transaction));
        }
        Ok(())
    }

    pub fn make_patches(&self) -> Vec<BalancePatch> {
        let mut block_patch = Vec::<BalancePatch>::new();
        for patch in self.cache.borrow().values() {
            block_patch.push(patch.clone());
        }
        block_patch
    }
}

impl<'a, L: 'a + LedgerReader> fmt::Debug for LedgerSnapshot<'a, L> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", self.cache.borrow())
    }
}

impl<'a, L: 'a + LedgerReader> LedgerReader for LedgerSnapshot<'a, L> {
    fn get_balance(&self, address: &PublicKey) -> SimplesResult<Balance> {
        match self.cache.borrow_mut().entry(address.clone()) {
            hash_map::Entry::Occupied(occupied_patch) =>
                Ok(occupied_patch.get().get_after().clone()),
            hash_map::Entry::Vacant(vacant_patch) => {
                let db_balance = try!(self.store.get_balance(address));
                let mut patch = BalancePatch::new();
                patch.set_public_key(address.0.to_vec());
                patch.set_before(db_balance.clone());
                patch.set_after(db_balance.clone());
                vacant_patch.insert(patch);
                Ok(db_balance)
            }
        }
    }
}

impl<'a, LedgerReadOnly: 'a + LedgerReader> LedgerWriter
    for LedgerSnapshot<'a, LedgerReadOnly> {
    fn set_balance(&mut self, address: &PublicKey, balance: Balance)
                   -> SimplesResult<()> {
        match self.cache.borrow_mut().entry(address.clone()) {
            hash_map::Entry::Occupied(mut occupied_patch) => {
                occupied_patch.get_mut().set_after(balance);
            },
            hash_map::Entry::Vacant(vacant_patch) => {
                let db_balance = try!(self.store.get_balance(address));
                let mut patch = BalancePatch::new();
                patch.set_public_key(address.0.to_vec());
                patch.set_before(db_balance);
                patch.set_after(balance);
                vacant_patch.insert(patch);
            }
        };
        Ok(())
    }
}

/*****  Tests  *****/

#[test]
fn test_make_genesis_patch_empty() {
    use block::GenesisBuilder;

    let builder = GenesisBuilder::new();
    let genesis = builder.build();
    let maybe_patch = make_genesis_patch(&genesis);
    assert!(maybe_patch.is_ok());
    assert!(0 == maybe_patch.unwrap().get_patches().len());
}

#[test]
fn test_make_genesis_patch_non_unqiue_dest() {
    use std::iter::FromIterator;
    use block::GenesisBuilder;
    use crypto::gen_keypair;

    let (pk1, _) = gen_keypair();
    let (pk2, _) = gen_keypair();
    let mut builder = GenesisBuilder::new();
    builder.add_transfer(pk1.clone(), 101);
    builder.add_transfer(pk2.clone(), 271);
    builder.add_transfer(pk1.clone(), 5000);
    let genesis = builder.build();
    let maybe_patch = make_genesis_patch(&genesis);
    assert!(maybe_patch.is_ok());
    assert!(2 == maybe_patch.as_ref().unwrap().get_patches().len());
    let patch_map: HashMap<PublicKey, BalancePatch> =
        FromIterator::from_iter(maybe_patch.unwrap().get_patches().iter().map(
            |patch| {(PublicKey::from_bytes(patch.get_public_key()).unwrap(),
                      patch.clone())}));

    let maybe_patch_pk1 = patch_map.get(&pk1);
    assert!(maybe_patch_pk1.is_some());
    let patch_pk1 = maybe_patch_pk1.unwrap();
    assert!(pk1 == PublicKey::from_bytes(patch_pk1.get_public_key()).unwrap());
    assert!(0 == patch_pk1.get_before().get_tokens());
    assert!(0 == patch_pk1.get_before().get_op_index());
    assert!(5101 == patch_pk1.get_after().get_tokens());
    assert!(0 == patch_pk1.get_after().get_op_index());

    let maybe_patch_pk2 = patch_map.get(&pk2);
    assert!(maybe_patch_pk2.is_some());
    let patch_pk2 = maybe_patch_pk2.unwrap();
    assert!(pk2 == PublicKey::from_bytes(patch_pk2.get_public_key()).unwrap());
    assert!(0 == patch_pk2.get_before().get_tokens());
    assert!(0 == patch_pk2.get_before().get_op_index());
    assert!(271 == patch_pk2.get_after().get_tokens());
    assert!(0 == patch_pk2.get_after().get_op_index());
}

struct TestLedgerOneAddress {
    address: PublicKey,
    balance: Balance
}

impl LedgerReader for TestLedgerOneAddress {
    fn get_balance(&self, address: &PublicKey) -> SimplesResult<Balance> {
        if self.address == *address {
            Ok(self.balance.clone())
        } else {
            Err(SimplesError::new(""))
        }
    }
}

impl LedgerWriter for TestLedgerOneAddress {
    fn set_balance(&mut self, address: &PublicKey, balance: Balance)
                   -> SimplesResult<()> {
        if self.address == *address {
            self.balance = balance;
            Ok(())
        } else {
            Err(SimplesError::new(""))
        }
    }
}

struct TestLedgerHashMap {
    ledger: RefCell<HashMap<PublicKey, Balance>>
}

impl LedgerReader for TestLedgerHashMap {
    fn get_balance(&self, address: &PublicKey) -> SimplesResult<Balance> {
        match self.ledger.borrow_mut().entry(address.clone()) {
            hash_map::Entry::Occupied(occupied) => Ok(occupied.get().clone()),
            hash_map::Entry::Vacant(vacant) => {
                let mut balance = Balance::new();
                balance.set_tokens(0);
                balance.set_op_index(0);
                vacant.insert(balance.clone());
                Ok(balance)
            }
        }
    }
}

#[test]
fn test_patchable_apply_patch() {
    use crypto::gen_keypair;

    let (pk1, sk1) = gen_keypair();
    let (pk2, sk2) = gen_keypair();
    let mut initial_balance = Balance::new();
    initial_balance.set_tokens(1000);
    initial_balance.set_op_index(7);
    let mut mutator = TestLedgerOneAddress {
        address: pk2.clone(),
        balance: initial_balance.clone()
    };

    let mut patch = BalancePatch::new();
    assert!(mutator.apply_patch(patch.clone()).is_err());
    assert!(initial_balance == mutator.balance);

    patch.set_public_key(pk1.0.to_vec());
    patch.mut_before().set_tokens(999);
    patch.mut_before().set_tokens(7);
    assert!(mutator.apply_patch(patch.clone()).is_err());
    assert!(initial_balance == mutator.balance);

    patch.mut_before().set_tokens(1000);
    patch.mut_before().set_op_index(7);
    patch.mut_after().set_tokens(499);
    patch.mut_after().set_op_index(17);
    assert!(mutator.apply_patch(patch.clone()).is_err());

    patch.set_public_key(pk2.0.to_vec());
    assert!(mutator.apply_patch(patch.clone()).is_ok());
    assert!(499 == mutator.balance.get_tokens());
    assert!(17 == mutator.balance.get_op_index());

    patch = patch.reverse();
    assert!(mutator.apply_patch(patch.clone()).is_ok());
    assert!(1000 == mutator.balance.get_tokens());
    assert!(7 == mutator.balance.get_op_index());
}

#[test]
fn test_ledger_snapshot_make_patches() {
    use crypto::gen_keypair;

    let (pk1, sk1) = gen_keypair();
    let (pk2, sk2) = gen_keypair();
    let (pk3, sk3) = gen_keypair();

    let mut balance_pk1 = Balance::new();
    balance_pk1.set_tokens(1000);
    balance_pk1.set_op_index(7);
    let mut ledger_cell = RefCell::new(HashMap::new());
    ledger_cell.borrow_mut().insert(pk1.clone(), balance_pk1.clone());
    let mut ledger = TestLedgerHashMap { ledger: ledger_cell };

    let mut snapshot = LedgerSnapshot::new(&ledger);
    assert!(0 == snapshot.make_patches().len());
    balance_pk1.set_tokens(400);
    balance_pk1.set_op_index(91);
    snapshot.set_balance(&pk1, balance_pk1.clone());
    println!("{:?}", snapshot.make_patches());
}
<commit_msg>Moved make_genesis_patch out of balance.<commit_after>use std::cell::RefCell;
use std::collections::hash_map::{self, HashMap};
use std::fmt;

use crypto::PublicKey;
use block::HashedBlockExt;
use error::{SimplesError, SimplesResult};
use simples_pb::{Balance, BalancePatch, HashedBlock, Transaction, Transfer};

pub trait BalancePatchExt {
    fn decode_public_key(&self) -> SimplesResult<PublicKey>;
    fn reverse(&self) -> Self;
}

impl BalancePatchExt for BalancePatch {
    fn decode_public_key(&self) -> SimplesResult<PublicKey> {
        PublicKey::from_bytes(&self.get_public_key())
    }

    fn reverse(&self) -> Self {
        let mut reversed = BalancePatch::new();
        reversed.set_public_key(self.get_public_key().to_vec());
        reversed.set_before(self.get_after().clone());
        reversed.set_after(self.get_before().clone());
        reversed
    }
}

pub trait LedgerReader {
    fn get_balance(&self, address: &PublicKey) -> SimplesResult<Balance>;
}

pub trait LedgerWriter {
    fn set_balance(&mut self, address: &PublicKey, balance: Balance)
                   -> SimplesResult<()>;
}

pub trait Patchable {
    fn apply_patch(&mut self, patch: BalancePatch) -> SimplesResult<()>;
}

impl<LedgerMutator: LedgerReader + LedgerWriter>
    Patchable for LedgerMutator {
    fn apply_patch(&mut self, patch: BalancePatch) -> SimplesResult<()> {
        let public_key = try!(PublicKey::from_bytes(patch.get_public_key()));
        let before_balance = try!(self.get_balance(&public_key));
        if before_balance != *patch.get_before() {
            return Err(SimplesError::new(&format!(
                "Actual initial balance ({}, {}) != ({}, {}) from the patch.",
                before_balance.get_tokens(), before_balance.get_op_index(),
                patch.get_before().get_tokens(),
                patch.get_before().get_op_index())[]));
        }
        try!(self.set_balance(&public_key, patch.get_after().clone()));
        Ok(())
    }
}

pub struct LedgerSnapshot<'a, LedgerReadOnly: 'a + LedgerReader> {
    cache: RefCell<HashMap<PublicKey, BalancePatch>>,
    store: &'a LedgerReadOnly
}

impl<'a, L: 'a + LedgerReader> LedgerSnapshot<'a, L> {
    pub fn new(store: &'a L) -> LedgerSnapshot<'a, L> {
        LedgerSnapshot {
            cache: RefCell::new(HashMap::<PublicKey, BalancePatch>::new()),
            store: store
        }
    }

    pub fn clear(&mut self) { self.cache.borrow_mut().clear(); }

    pub fn add_transfer(&mut self, transfer: &Transfer) ->
        SimplesResult<()>
    {
        let source_pk = try!(PublicKey::from_bytes(transfer.get_source_pk()));
        let destination_pk =
            try!(PublicKey::from_bytes(transfer.get_destination_pk()));
        let mut source = try!(self.get_balance(&source_pk));
        let mut destination = try!(self.get_balance(&destination_pk));

        if source.get_tokens() >= transfer.get_tokens() {
            // println!("source: {}",
            //          transfer.get_source_pk().to_base64(base64::STANDARD));
            // println!("destination: {}",
            //          transfer.get_destination_pk().to_base64(base64::STANDARD));
            if transfer.get_op_index() == source.get_op_index() {
                // println!("num: {} / tokens: {} / balance: {} -> {}\n",
                //          source.get_op_index(), transfer.get_tokens(),
                //          source.get_tokens(),
                //          source.get_tokens() - transfer.get_tokens());

                let source_tokens = source.get_tokens() - transfer.get_tokens();
                let source_op_index = source.get_op_index() + 1;
                let dest_tokens = destination.get_tokens() + transfer.get_tokens();
                source.set_tokens(source_tokens);
                source.set_op_index(source_op_index);
                destination.set_tokens(dest_tokens);

                try!(self.set_balance(&source_pk, source));
                try!(self.set_balance(&destination_pk, destination));
                Ok(())
            } else {
                Err(SimplesError::new(&format!(
                    "Wrong op number for source address {}: op_index was
{} != {} (required)", source_pk, transfer.get_op_index(), source.get_op_index())[]))
            }
        } else {
            Err(SimplesError::new(&format!(
                "ERROR: Not enough funds. Source address balance is {} but
{} tokens were transferred: {} -> {}", source.get_tokens(), transfer.get_tokens(),
                source_pk, destination_pk)[]))
        }
    }

    pub fn apply_transaction(
        &mut self, transaction: &Transaction) -> SimplesResult<()> {
        for transfer in transaction.get_commit().get_transfers().iter() {
            try!(self.add_transfer(transfer));
        }
        Ok(())
    }

    pub fn apply_block(&mut self, block: &HashedBlock) -> SimplesResult<()> {
        for transaction in block.get_block().get_transactions().iter() {
            try!(self.apply_transaction(transaction));
        }
        Ok(())
    }

    pub fn make_patches(&self) -> Vec<BalancePatch> {
        let mut block_patch = Vec::<BalancePatch>::new();
        for patch in self.cache.borrow().values() {
            block_patch.push(patch.clone());
        }
        block_patch
    }
}

impl<'a, L: 'a + LedgerReader> fmt::Debug for LedgerSnapshot<'a, L> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", self.cache.borrow())
    }
}

impl<'a, L: 'a + LedgerReader> LedgerReader for LedgerSnapshot<'a, L> {
    fn get_balance(&self, address: &PublicKey) -> SimplesResult<Balance> {
        match self.cache.borrow_mut().entry(address.clone()) {
            hash_map::Entry::Occupied(occupied_patch) =>
                Ok(occupied_patch.get().get_after().clone()),
            hash_map::Entry::Vacant(vacant_patch) => {
                let db_balance = try!(self.store.get_balance(address));
                let mut patch = BalancePatch::new();
                patch.set_public_key(address.0.to_vec());
                patch.set_before(db_balance.clone());
                patch.set_after(db_balance.clone());
                vacant_patch.insert(patch);
                Ok(db_balance)
            }
        }
    }
}

impl<'a, LedgerReadOnly: 'a + LedgerReader> LedgerWriter
    for LedgerSnapshot<'a, LedgerReadOnly> {
    fn set_balance(&mut self, address: &PublicKey, balance: Balance)
                   -> SimplesResult<()> {
        match self.cache.borrow_mut().entry(address.clone()) {
            hash_map::Entry::Occupied(mut occupied_patch) => {
                occupied_patch.get_mut().set_after(balance);
            },
            hash_map::Entry::Vacant(vacant_patch) => {
                let db_balance = try!(self.store.get_balance(address));
                let mut patch = BalancePatch::new();
                patch.set_public_key(address.0.to_vec());
                patch.set_before(db_balance);
                patch.set_after(balance);
                vacant_patch.insert(patch);
            }
        };
        Ok(())
    }
}

/*****  Tests  *****/

struct TestLedgerOneAddress {
    address: PublicKey,
    balance: Balance
}

impl LedgerReader for TestLedgerOneAddress {
    fn get_balance(&self, address: &PublicKey) -> SimplesResult<Balance> {
        if self.address == *address {
            Ok(self.balance.clone())
        } else {
            Err(SimplesError::new(""))
        }
    }
}

impl LedgerWriter for TestLedgerOneAddress {
    fn set_balance(&mut self, address: &PublicKey, balance: Balance)
                   -> SimplesResult<()> {
        if self.address == *address {
            self.balance = balance;
            Ok(())
        } else {
            Err(SimplesError::new(""))
        }
    }
}

struct TestLedgerHashMap {
    ledger: RefCell<HashMap<PublicKey, Balance>>
}

impl LedgerReader for TestLedgerHashMap {
    fn get_balance(&self, address: &PublicKey) -> SimplesResult<Balance> {
        match self.ledger.borrow_mut().entry(address.clone()) {
            hash_map::Entry::Occupied(occupied) => Ok(occupied.get().clone()),
            hash_map::Entry::Vacant(vacant) => {
                let mut balance = Balance::new();
                balance.set_tokens(0);
                balance.set_op_index(0);
                vacant.insert(balance.clone());
                Ok(balance)
            }
        }
    }
}

#[test]
fn test_patchable_apply_patch() {
    use crypto::gen_keypair;

    let (pk1, sk1) = gen_keypair();
    let (pk2, sk2) = gen_keypair();
    let mut initial_balance = Balance::new();
    initial_balance.set_tokens(1000);
    initial_balance.set_op_index(7);
    let mut mutator = TestLedgerOneAddress {
        address: pk2.clone(),
        balance: initial_balance.clone()
    };

    let mut patch = BalancePatch::new();
    assert!(mutator.apply_patch(patch.clone()).is_err());
    assert!(initial_balance == mutator.balance);

    patch.set_public_key(pk1.0.to_vec());
    patch.mut_before().set_tokens(999);
    patch.mut_before().set_tokens(7);
    assert!(mutator.apply_patch(patch.clone()).is_err());
    assert!(initial_balance == mutator.balance);

    patch.mut_before().set_tokens(1000);
    patch.mut_before().set_op_index(7);
    patch.mut_after().set_tokens(499);
    patch.mut_after().set_op_index(17);
    assert!(mutator.apply_patch(patch.clone()).is_err());

    patch.set_public_key(pk2.0.to_vec());
    assert!(mutator.apply_patch(patch.clone()).is_ok());
    assert!(499 == mutator.balance.get_tokens());
    assert!(17 == mutator.balance.get_op_index());

    patch = patch.reverse();
    assert!(mutator.apply_patch(patch.clone()).is_ok());
    assert!(1000 == mutator.balance.get_tokens());
    assert!(7 == mutator.balance.get_op_index());
}

#[test]
fn test_ledger_snapshot_make_patches() {
    use crypto::gen_keypair;

    let (pk1, sk1) = gen_keypair();
    let (pk2, sk2) = gen_keypair();
    let (pk3, sk3) = gen_keypair();

    let mut balance_pk1 = Balance::new();
    balance_pk1.set_tokens(1000);
    balance_pk1.set_op_index(7);
    let ledger_cell = RefCell::new(HashMap::new());
    ledger_cell.borrow_mut().insert(pk1.clone(), balance_pk1.clone());
    let mut ledger = TestLedgerHashMap { ledger: ledger_cell };

    let mut snapshot = LedgerSnapshot::new(&ledger);
    assert!(0 == snapshot.make_patches().len());
    balance_pk1.set_tokens(400);
    balance_pk1.set_op_index(91);
    snapshot.set_balance(&pk1, balance_pk1.clone());
    println!("{:?}", snapshot.make_patches());
}
<|endoftext|>


<commit_before>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_use]
extern crate serde_derive;

mod remote {
    pub struct S {
        pub a: u8,
    }
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::S")]
struct S {
    b: u8, //~^^^ ERROR: no field `b` on type `&remote::S`
}

fn main() {}
<commit_msg>Additional errors for some reason<commit_after>// Copyright 2017 Serde Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[macro_use]
extern crate serde_derive;

mod remote {
    pub struct S {
        pub a: u8,
    }
}

#[derive(Serialize, Deserialize)]
#[serde(remote = "remote::S")]
struct S {
    //~^^^ ERROR: struct `remote::S` has no field named `b`
    //~^^^^ ERROR: struct `remote::S` has no field named `b`
    b: u8, //~^^^^^ ERROR: no field `b` on type `&remote::S`
}

fn main() {}
<|endoftext|>