<commit_before>extern crate ndarray;

use ndarray_ext::NdArray;
use op;
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::mem;
use std::rc::Rc;
use tensor::Tensor;

// Context in evaluation of `node`
pub struct OpComputeContext<'a, 'b: 'a>
{
    pub node:       &'b Tensor, // Expose to its op for convenience
    resource_store: &'a ResourceStore<'b>,
    feed_store:     &'a FeedStore<'b>,
}

impl<'a, 'b> OpComputeContext<'a, 'b>
{
    #[inline]
    fn new(
        node: &'b Tensor,
        resource_store: &'a ResourceStore<'b>,
        feed_store: &'a FeedStore<'b>,
    ) -> Self
    {
        OpComputeContext {
            node,
            resource_store,
            feed_store,
        }
    }

    #[inline]
    pub fn grab_inputs(&self) -> Vec<&NdArray>
    {
        self.grab_inputs_internal(false)
    }

    #[inline]
    pub unsafe fn grab_assignable_inputs(&self) -> Vec<&mut NdArray>
    {
        mem::transmute(self.grab_inputs_internal(true))
    }

    #[inline]
    fn grab_inputs_internal(&self, is_mutable: bool) -> Vec<&NdArray>
    {
        fn find_value_of<'a, 'b: 'a>(
            x: &'b Tensor,
            store: &'a ResourceStore,
            feed_store: &FeedStore<'a>,
            mutable: bool,
            value_index: usize,
        ) -> &'a NdArray
        {
            if let Some(ref per) = x.persistent_array {
                per.get_array()
            } else if x.is_placeholder {
                feed_store[x.resource_lookup_key.get()]
            } else {
                match store[x.resource_lookup_key.get()].value[value_index] {
                    Ok(ref res) => res,
                    // hoping for x.inputs[i] to have the value
                    Err(::errors::OpComputeErrorStatus::Delegate { to: i }) => {
                        find_value_of(&x.inputs[i], store, feed_store, mutable, x.input_indices[i])
                    }
                    Err(::errors::OpComputeErrorStatus::NoOutput) => {
                        panic!("autograd failed: {}'s output not usable", x)
                    }
                    Err(::OpComputeErrorStatus::BadInput(ref msg)) => {
                        panic!("autograd failed: {}, msg: {}", x, msg)
                    }
                }
            }
        }

        let input_nodes = &self.node.inputs;
        let mut input_arrays = Vec::with_capacity(input_nodes.len());
        for (x, &i) in input_nodes.into_iter().zip(self.node.input_indices.iter()) {
            input_arrays.push(find_value_of(
                x,
                self.resource_store,
                self.feed_store,
                is_mutable,
                i,
            ));
        }
        input_arrays
    }
}

struct NodeWithValue<'a>
{
    node:  &'a Tensor,
    value: op::ComputeResult,
    // How many resources of this node does user requires.
    // When this is reduced to one, `value` is ready to be moved out (without copy).
    pending_count: usize,
}

impl<'a> Tensor
{
    #[inline]
    fn with_value(&'a self, val: op::ComputeResult) -> NodeWithValue<'a>
    {
        NodeWithValue {
            node:          self,
            value:         val,
            pending_count: 0,
        }
    }
}

/// Evaluates given symbolic tensors.
///
/// ```
/// extern crate ndarray;
/// extern crate autograd as ag;
///
/// let ref a = ag::zeros(&[2]);
/// let ref b = ag::ones(&[2]);
///
/// // eval two tensors at once.
/// let evaluated = ag::eval(&[a, b], &[]);
/// assert_eq!(evaluated[0], ndarray::arr1(&[0., 0.]).into_dyn());
/// assert_eq!(evaluated[1], ndarray::arr1(&[1., 1.]).into_dyn());
/// ```
pub fn eval<'a, 'b: 'a, 'c: 'a, T, U>(
    tensors: &[T],
    feeds: U,
) -> Vec<ndarray::Array<f32, ndarray::IxDyn>>
where
    T: AsRef<Tensor>,
    U: IntoIterator<Item = &'a (&'b Tensor, &'c ndarray::Array<f32, ndarray::IxDyn>)>,
{
    // Run graph
    let feeds = feeds.into_iter().collect::<Vec<_>>();
    let mut output_storage = eval_internal(&tensors.iter().map(|t| t.as_ref()).collect(), &feeds);

    // Treat in-place or delegation ops
    let creators = tensors
        .iter()
        .map(|x| {
            let x = x.as_ref();
            let creator = if x.is_placeholder || x.persistent_array.is_some() {
                x
            } else {
                let creator = find_resource_creator(&output_storage, x);
                output_storage[creator.resource_lookup_key.get()].pending_count += 1;
                creator
            };
            creator
        })
        .collect::<Vec<&Tensor>>();

    // Shrink to fit (output_storage is moved)
    let mut key2res: BTreeMap<usize, NodeWithValue> = finalize_resource_store(output_storage);

    // Aggregate return values
    creators
        .iter()
        .map(|ref creator| {
            if let Some(ref per) = creator.persistent_array {
                // Rarely happens (case that a persistent array given by user is required)
                per.get_array().clone()
            } else if creator.is_placeholder {
                // Rarely happens (case that a feed by user is required)
                get_fed_resource(creator, &feeds).clone()
            } else {
                let res = match key2res.entry(creator.resource_lookup_key.get()) {
                    Entry::Occupied(mut ent) => {
                        // pending_count = 1, so move out
                        if ent.get().pending_count == 1 {
                            let mut got = ent.remove();
                            got.value.remove(0).expect(got.node.op.name())
                        } else {
                            // pending_count > 1, so copy the resource
                            let mut got = ent.get_mut();
                            got.pending_count -= 1;
                            got.value[0].as_ref().expect(got.node.op.name()).clone()
                        }
                    }
                    _ => unreachable!(),
                };
                res
            }
        })
        .collect()
}

/// Runs given symbolic tensors.
///
/// Runs, but returns nothing.
/// ```
/// extern crate ndarray;
/// extern crate autograd as ag;
///
/// let a = ag::variable(ndarray::arr1(&[1., 1.]));
/// let b = ag::ones(&[2]);
/// let c = ag::sub_inplace(a, &b);
///
/// // runs inplace op.
/// ag::run(&[&c], &[]);
/// // pull out shared variable
/// let should_be_zeros = &c.persistent_array;
/// assert_eq!(should_be_zeros, ndarray::arr1(&[0., 0.]).into_dyn());
///
/// ```
pub fn run<'a, 'b: 'a, 'c: 'a, T, U>(tensors: &[T], feeds: U)
where
    T: AsRef<Tensor>,
    U: IntoIterator<Item = &'a (&'b Tensor, &'c NdArray)>,
{
    // Just run the graph
    eval_internal(
        &tensors.iter().map(|t| t.as_ref()).collect(),
        &feeds.into_iter().collect(),
    );
}

#[inline]
// Recursive function which seeks a node holding the x's resource.
// Actual recursion "rarely" happens.
fn find_resource_creator<'a, 'b>(storage: &ResourceStore, x: &'b Tensor) -> &'b Tensor
{
    match storage[x.resource_lookup_key.get()].value[0] {
        Ok(_) => x,

        // recurse
        Err(::OpComputeErrorStatus::Delegate { to: i }) => {
            find_resource_creator(storage, &x.inputs[i])
        }

        Err(::OpComputeErrorStatus::BadInput(ref msg)) => {
            panic!("autograd failed: {}, msg: {}", x, msg)
        }

        // TODO: Implementing (Returning None is good probably)
        Err(::OpComputeErrorStatus::NoOutput) => unimplemented!("\"eval\" for {}", x),
    }
}

type ResourceStore<'a> = Vec<NodeWithValue<'a>>;
type FeedStore<'a> = Vec<&'a NdArray>;

// TODO: Use raw pointer comparison after removing "Rc"
fn get_fed_resource<'a>(node: &Tensor, feeds: &Vec<&(&Tensor, &'a NdArray)>) -> &'a NdArray
{
    // Linear search is suitable because number of feeds are so small in most cases
    for feed in feeds {
        if Rc::ptr_eq(feed.0, node) {
            return feed.1;
        }
    }
    panic!("Placeholder unfilled");
}

// Actually evaluates nodes "targets".
fn eval_internal<'a>(
    targets: &Vec<&'a Tensor>,
    feeds: &Vec<&(&'a Tensor, &NdArray)>,
) -> ResourceStore<'a>
{
    let mut resource_store = Vec::new();
    let mut feed_store = Vec::new();

    // Obtain array resources while visiting nodes in topological order.
    // Stack-based DFS is used, to avoid stack overflow in explicit recursion.
    let mut dfs_stack: Vec<(&Tensor, bool)> = targets.iter().map(|&x| (x, false)).collect();
    while let Some((node, is_parent)) = dfs_stack.pop() {
        if is_parent {
            // Visit this node
            if node.is_placeholder {
                node.resource_lookup_key.set(feed_store.len());
                feed_store.push(get_fed_resource(node, &feeds));
            } else {
                node.resource_lookup_key.set(resource_store.len());
                if node.persistent_array.is_none() {
                    let y =
                        node.op
                            .compute(OpComputeContext::new(node, &resource_store, &feed_store));
                    resource_store.push(node.with_value(y));
                }
            }
        } else {
            // Update dfs stack
            dfs_stack.push((node, true));
            // Push children if needed
            for child in &node.inputs {
                // TODO: Use raw pointer comparison after removing "Rc"
                let visited = {
                    let k = child.resource_lookup_key.get();
                    k < resource_store.len() && Rc::ptr_eq(child, resource_store[k].node)
                };
                if !visited {
                    dfs_stack.push((child, false));
                }
            }
        }
    }
    resource_store
}

// Shrink it by dropping useless resources
// and convert it into mappings of {lookup key => resource}
fn finalize_resource_store(mut vec: ResourceStore) -> BTreeMap<usize, NodeWithValue>
{
    let mut retained_keys = Vec::new();
    let len = vec.len();
    {
        let mut_ref = &mut vec;
        let mut del = 0;
        // Align the resources. Unused resources are placed in the latter part.
        {
            let v = &mut **mut_ref;

            for i in 0..len {
                if v[i].pending_count == 0 {
                    del += 1;
                    continue;
                }
                retained_keys.push(i);
                if del > 0 {
                    // slides i th node forward
                    v.swap(i - del, i);
                }
            }
        }
        if del > 0 {
            // Drop unused resources here
            mut_ref.truncate(len - del);
        }
    }
    debug_assert_eq!(vec.len(), retained_keys.len());
    // `retained_keys` are sorted.
    // `vec` is moved into Map.
    retained_keys.into_iter().zip(vec).collect()
}

#[test]
fn test_eval()
{
    let ref v = ::ops::placeholder(&[3, 2, 1]);
    let ref z = ::ops::squeeze(v, &[2]);
    let ref g = ::ops::grad_with_default(&[z], &[v], &[&::ones(&z.shape())]);
    let eval_result = eval(g, &[(v, &::ndarray_ext::ones(&[3, 2, 1]))]);
    assert_eq!(eval_result[0].shape(), &[3, 2, 1]);
}

#[test]
fn test_constant_eval()
{
    let arr = ndarray::arr1(&[0., 0., 0.]);
    assert_eq!(arr.clone().into_dyn(), ::variable(arr).eval(&[]));
}

#[test]
fn test_placeholder_eval()
{
    let arr = ::ndarray_ext::ones(&[3, 2, 1]);
    let ref v = ::ops::placeholder(&[3, 2, 1]);
    let eval_result = eval(&[v], &[(v, &arr)]);
    assert_eq!(eval_result[0], arr);
}

#[test]
fn test_eval_internal()
{
    let ref v = ::ops::placeholder(&[3, 2, 1]);
    let ref z = ::ops::squeeze(v, &[2]);
    let ref g = ::ops::grad_with_default(&[z], &[v], &[&::ones(&z.shape())]);
    let storage = eval_internal(&vec![&g[0]], &vec![&(v, &::ndarray_ext::ones(&[3, 2, 1]))]);

    assert_eq!(
        storage.iter().map(|x| x.node.op.name()).collect::<Vec<_>>(),
        vec![
            "ConvertToTensor",
            "Squeeze", // forward end
            "Shape",
            "Ones",
            "ExpandDims",
        ]
    );
}
<commit_msg>Fix docstring of runtime::run<commit_after>extern crate ndarray;

use ndarray_ext::NdArray;
use op;
use std::collections::BTreeMap;
use std::collections::btree_map::Entry;
use std::mem;
use std::rc::Rc;
use tensor::Tensor;

// Context in evaluation of `node`
pub struct OpComputeContext<'a, 'b: 'a>
{
    pub node:       &'b Tensor, // Expose to its op for convenience
    resource_store: &'a ResourceStore<'b>,
    feed_store:     &'a FeedStore<'b>,
}

impl<'a, 'b> OpComputeContext<'a, 'b>
{
    #[inline]
    fn new(
        node: &'b Tensor,
        resource_store: &'a ResourceStore<'b>,
        feed_store: &'a FeedStore<'b>,
    ) -> Self
    {
        OpComputeContext {
            node,
            resource_store,
            feed_store,
        }
    }

    #[inline]
    pub fn grab_inputs(&self) -> Vec<&NdArray>
    {
        self.grab_inputs_internal(false)
    }

    #[inline]
    pub unsafe fn grab_assignable_inputs(&self) -> Vec<&mut NdArray>
    {
        mem::transmute(self.grab_inputs_internal(true))
    }

    #[inline]
    fn grab_inputs_internal(&self, is_mutable: bool) -> Vec<&NdArray>
    {
        fn find_value_of<'a, 'b: 'a>(
            x: &'b Tensor,
            store: &'a ResourceStore,
            feed_store: &FeedStore<'a>,
            mutable: bool,
            value_index: usize,
        ) -> &'a NdArray
        {
            if let Some(ref per) = x.persistent_array {
                per.get_array()
            } else if x.is_placeholder {
                feed_store[x.resource_lookup_key.get()]
            } else {
                match store[x.resource_lookup_key.get()].value[value_index] {
                    Ok(ref res) => res,
                    // hoping for x.inputs[i] to have the value
                    Err(::errors::OpComputeErrorStatus::Delegate { to: i }) => {
                        find_value_of(&x.inputs[i], store, feed_store, mutable, x.input_indices[i])
                    }
                    Err(::errors::OpComputeErrorStatus::NoOutput) => {
                        panic!("autograd failed: {}'s output not usable", x)
                    }
                    Err(::OpComputeErrorStatus::BadInput(ref msg)) => {
                        panic!("autograd failed: {}, msg: {}", x, msg)
                    }
                }
            }
        }

        let input_nodes = &self.node.inputs;
        let mut input_arrays = Vec::with_capacity(input_nodes.len());
        for (x, &i) in input_nodes.into_iter().zip(self.node.input_indices.iter()) {
            input_arrays.push(find_value_of(
                x,
                self.resource_store,
                self.feed_store,
                is_mutable,
                i,
            ));
        }
        input_arrays
    }
}

struct NodeWithValue<'a>
{
    node:  &'a Tensor,
    value: op::ComputeResult,
    // How many resources of this node does user requires.
    // When this is reduced to one, `value` is ready to be moved out (without copy).
    pending_count: usize,
}

impl<'a> Tensor
{
    #[inline]
    fn with_value(&'a self, val: op::ComputeResult) -> NodeWithValue<'a>
    {
        NodeWithValue {
            node:          self,
            value:         val,
            pending_count: 0,
        }
    }
}

/// Evaluates given symbolic tensors.
///
/// ```
/// extern crate ndarray;
/// extern crate autograd as ag;
///
/// let ref a = ag::zeros(&[2]);
/// let ref b = ag::ones(&[2]);
///
/// // eval two tensors at once.
/// let evaluated = ag::eval(&[a, b], &[]);
/// assert_eq!(evaluated[0], ndarray::arr1(&[0., 0.]).into_dyn());
/// assert_eq!(evaluated[1], ndarray::arr1(&[1., 1.]).into_dyn());
/// ```
pub fn eval<'a, 'b: 'a, 'c: 'a, T, U>(
    tensors: &[T],
    feeds: U,
) -> Vec<ndarray::Array<f32, ndarray::IxDyn>>
where
    T: AsRef<Tensor>,
    U: IntoIterator<Item = &'a (&'b Tensor, &'c ndarray::Array<f32, ndarray::IxDyn>)>,
{
    // Run graph
    let feeds = feeds.into_iter().collect::<Vec<_>>();
    let mut output_storage = eval_internal(&tensors.iter().map(|t| t.as_ref()).collect(), &feeds);

    // Treat in-place or delegation ops
    let creators = tensors
        .iter()
        .map(|x| {
            let x = x.as_ref();
            let creator = if x.is_placeholder || x.persistent_array.is_some() {
                x
            } else {
                let creator = find_resource_creator(&output_storage, x);
                output_storage[creator.resource_lookup_key.get()].pending_count += 1;
                creator
            };
            creator
        })
        .collect::<Vec<&Tensor>>();

    // Shrink to fit (output_storage is moved)
    let mut key2res: BTreeMap<usize, NodeWithValue> = finalize_resource_store(output_storage);

    // Aggregate return values
    creators
        .iter()
        .map(|ref creator| {
            if let Some(ref per) = creator.persistent_array {
                // Rarely happens (case that a persistent array given by user is required)
                per.get_array().clone()
            } else if creator.is_placeholder {
                // Rarely happens (case that a feed by user is required)
                get_fed_resource(creator, &feeds).clone()
            } else {
                let res = match key2res.entry(creator.resource_lookup_key.get()) {
                    Entry::Occupied(mut ent) => {
                        // pending_count = 1, so move out
                        if ent.get().pending_count == 1 {
                            let mut got = ent.remove();
                            got.value.remove(0).expect(got.node.op.name())
                        } else {
                            // pending_count > 1, so copy the resource
                            let mut got = ent.get_mut();
                            got.pending_count -= 1;
                            got.value[0].as_ref().expect(got.node.op.name()).clone()
                        }
                    }
                    _ => unreachable!(),
                };
                res
            }
        })
        .collect()
}

/// Runs given symbolic tensors.
///
/// Runs, but returns nothing.
///
/// ```
/// extern crate ndarray;
/// extern crate autograd as ag;
///
/// let a = ag::variable(ndarray::arr1(&[1., 1.]));
/// let b = ag::ones(&[2]);
/// let c = ag::sub_inplace(a, &b);
///
/// // runs inplace op.
/// ag::run(&[&c], &[]);
/// ```
pub fn run<'a, 'b: 'a, 'c: 'a, T, U>(tensors: &[T], feeds: U)
where
    T: AsRef<Tensor>,
    U: IntoIterator<Item = &'a (&'b Tensor, &'c NdArray)>,
{
    // Just run the graph
    eval_internal(
        &tensors.iter().map(|t| t.as_ref()).collect(),
        &feeds.into_iter().collect(),
    );
}

#[inline]
// Recursive function which seeks a node holding the x's resource.
// Actual recursion "rarely" happens.
fn find_resource_creator<'a, 'b>(storage: &ResourceStore, x: &'b Tensor) -> &'b Tensor
{
    match storage[x.resource_lookup_key.get()].value[0] {
        Ok(_) => x,

        // recurse
        Err(::OpComputeErrorStatus::Delegate { to: i }) => {
            find_resource_creator(storage, &x.inputs[i])
        }

        Err(::OpComputeErrorStatus::BadInput(ref msg)) => {
            panic!("autograd failed: {}, msg: {}", x, msg)
        }

        // TODO: Implementing (Returning None is good probably)
        Err(::OpComputeErrorStatus::NoOutput) => unimplemented!("\"eval\" for {}", x),
    }
}

type ResourceStore<'a> = Vec<NodeWithValue<'a>>;
type FeedStore<'a> = Vec<&'a NdArray>;

// TODO: Use raw pointer comparison after removing "Rc"
fn get_fed_resource<'a>(node: &Tensor, feeds: &Vec<&(&Tensor, &'a NdArray)>) -> &'a NdArray
{
    // Linear search is suitable because number of feeds are so small in most cases
    for feed in feeds {
        if Rc::ptr_eq(feed.0, node) {
            return feed.1;
        }
    }
    panic!("Placeholder unfilled");
}

// Actually evaluates nodes "targets".
fn eval_internal<'a>(
    targets: &Vec<&'a Tensor>,
    feeds: &Vec<&(&'a Tensor, &NdArray)>,
) -> ResourceStore<'a>
{
    let mut resource_store = Vec::new();
    let mut feed_store = Vec::new();

    // Obtain array resources while visiting nodes in topological order.
    // Stack-based DFS is used, to avoid stack overflow in explicit recursion.
    let mut dfs_stack: Vec<(&Tensor, bool)> = targets.iter().map(|&x| (x, false)).collect();
    while let Some((node, is_parent)) = dfs_stack.pop() {
        if is_parent {
            // Visit this node
            if node.is_placeholder {
                node.resource_lookup_key.set(feed_store.len());
                feed_store.push(get_fed_resource(node, &feeds));
            } else {
                node.resource_lookup_key.set(resource_store.len());
                if node.persistent_array.is_none() {
                    let y =
                        node.op
                            .compute(OpComputeContext::new(node, &resource_store, &feed_store));
                    resource_store.push(node.with_value(y));
                }
            }
        } else {
            // Update dfs stack
            dfs_stack.push((node, true));
            // Push children if needed
            for child in &node.inputs {
                // TODO: Use raw pointer comparison after removing "Rc"
                let visited = {
                    let k = child.resource_lookup_key.get();
                    k < resource_store.len() && Rc::ptr_eq(child, resource_store[k].node)
                };
                if !visited {
                    dfs_stack.push((child, false));
                }
            }
        }
    }
    resource_store
}

// Shrink it by dropping useless resources
// and convert it into mappings of {lookup key => resource}
fn finalize_resource_store(mut vec: ResourceStore) -> BTreeMap<usize, NodeWithValue>
{
    let mut retained_keys = Vec::new();
    let len = vec.len();
    {
        let mut_ref = &mut vec;
        let mut del = 0;
        // Align the resources. Unused resources are placed in the latter part.
        {
            let v = &mut **mut_ref;

            for i in 0..len {
                if v[i].pending_count == 0 {
                    del += 1;
                    continue;
                }
                retained_keys.push(i);
                if del > 0 {
                    // slides i th node forward
                    v.swap(i - del, i);
                }
            }
        }
        if del > 0 {
            // Drop unused resources here
            mut_ref.truncate(len - del);
        }
    }
    debug_assert_eq!(vec.len(), retained_keys.len());
    // `retained_keys` are sorted.
    // `vec` is moved into Map.
    retained_keys.into_iter().zip(vec).collect()
}

#[test]
fn test_eval()
{
    let ref v = ::ops::placeholder(&[3, 2, 1]);
    let ref z = ::ops::squeeze(v, &[2]);
    let ref g = ::ops::grad_with_default(&[z], &[v], &[&::ones(&z.shape())]);
    let eval_result = eval(g, &[(v, &::ndarray_ext::ones(&[3, 2, 1]))]);
    assert_eq!(eval_result[0].shape(), &[3, 2, 1]);
}

#[test]
fn test_constant_eval()
{
    let arr = ndarray::arr1(&[0., 0., 0.]);
    assert_eq!(arr.clone().into_dyn(), ::variable(arr).eval(&[]));
}

#[test]
fn test_placeholder_eval()
{
    let arr = ::ndarray_ext::ones(&[3, 2, 1]);
    let ref v = ::ops::placeholder(&[3, 2, 1]);
    let eval_result = eval(&[v], &[(v, &arr)]);
    assert_eq!(eval_result[0], arr);
}

#[test]
fn test_eval_internal()
{
    let ref v = ::ops::placeholder(&[3, 2, 1]);
    let ref z = ::ops::squeeze(v, &[2]);
    let ref g = ::ops::grad_with_default(&[z], &[v], &[&::ones(&z.shape())]);
    let storage = eval_internal(&vec![&g[0]], &vec![&(v, &::ndarray_ext::ones(&[3, 2, 1]))]);

    assert_eq!(
        storage.iter().map(|x| x.node.op.name()).collect::<Vec<_>>(),
        vec![
            "ConvertToTensor",
            "Squeeze", // forward end
            "Shape",
            "Ones",
            "ExpandDims",
        ]
    );
}
<|endoftext|>


<commit_before>use rand::{thread_rng, Rng};
use std::f64;
use std::cmp::Ordering;
use std::mem;
use super::MinPQ;
use super::binary_heaps::BinaryHeapMinPQ;

#[derive(PartialEq, Debug)]
pub struct Particle {
    pub rx: f64,
    pub ry: f64,
    pub vx: f64,
    pub vy: f64,
    pub mass: f64,
    pub radius: f64,
    count: usize
}

impl Particle {
    pub fn new() -> Particle {
        let mut rng = thread_rng();

        Particle {
            rx: rng.next_f64(),
            ry: rng.next_f64(),
            vx: (rng.next_f64() - 0.5) / 10.0,
            vy: (rng.next_f64() - 0.5) / 10.0,
            mass: rng.next_f64() / 100.0,
            radius: (rng.next_f64() + 0.3) / 100.0,
            count: 0
        }
    }

    pub fn do_move(&mut self, dt: f64) {
        // collision with walls
        let (rx, ry, vx, vy) = (self.rx, self.ry, self.vx, self.vy);
        let radius = self.radius;
        if rx + vx*dt < radius || rx + vx*dt > 1.0 - radius {
            self.vx = -vx;
        }
        if ry + vy*dt < radius || ry + vy*dt > 1.0 - radius {
            self.vy = -vy;
        }
        self.rx = rx + vx*dt;
        self.ry = ry + vy*dt;
    }

    pub fn time_to_hit(&self, that: &Particle) -> f64 {
        if self == that {
            return f64::INFINITY
        }
        let dx = that.rx - self.rx;
        let dy = that.ry - self.ry;

        let dvx = that.vx - self.vx;
        let dvy = that.vy - self.vy;

        let dvdr = dx*dvx + dy*dvy;

        if dvdr > 0.0 {
            return f64::INFINITY;
        }

        let dvdv = dvx*dvx + dvy*dvy;
        let drdr = dx*dx + dy*dy;
        let sigma = self.radius + that.radius;
        let d = dvdr*dvdr - dvdv * (drdr - sigma*sigma);
        if d < 0.0 {
            return f64::INFINITY;
        }

        return - (dvdr + d.sqrt()) / dvdv
    }

    pub fn time_to_hit_vertical_wall(&self) -> f64 {
        if self.vx > 0.0 {
            (1.0 - self.rx) / self.vx
        } else {
            - self.rx / self.vx
        }
    }

    pub fn time_to_hit_horizontal_wall(&self) -> f64 {
        if self.vy > 0.0 {
            (1.0 - self.ry) / self.vy
        } else {
            - self.ry / self.vy
        }
    }

    pub fn bounce_off(&mut self, that: &mut Particle) {
        let dx = that.rx - self.rx;
        let dy = that.ry - self.ry;
        let dvx = that.vx - self.vx;
        let dvy = that.vy - self.vy;
        let dvdr = dx*dvx + dy*dvy;
        let dist = self.radius + that.radius;
        let j = 2.0 * self.mass * that.mass * dvdr / ((self.mass + that.mass) * dist);

        let jx = j*dx / dist;
        let jy = j*dy / dist;

        self.vx += jx / self.mass;
        self.vy += jy / self.mass;
        that.vx -= jx / that.mass;
        that.vy -= jy / that.mass;

        self.count += 1;
        that.count += 1;
    }

    pub fn bounce_off_vertical_wall(&mut self) {
        self.vx = -self.vx;
    }

    pub fn bounce_off_horizontal_wall(&mut self) {
        self.vy = -self.vy;
    }
}

#[derive(PartialEq)]
pub enum Event {
    Hit { timestamp: f64, a: usize, b: usize },
    HitVerticalWall { timestamp: f64, a: usize },
    HitHorizontalWall { timestamp: f64, a: usize },
    Refresh { timestamp: f64 }
}

impl Event {
    pub fn timestamp(&self) -> f64 {
        match self {
            &Event::Hit { timestamp: t, .. } => t,
            &Event::HitVerticalWall { timestamp: t, .. } => t,
            &Event::HitHorizontalWall { timestamp: t, .. } => t,
            &Event::Refresh { timestamp: t } => t
        }
    }
}

impl PartialOrd for Event {
    fn partial_cmp(&self, other: &Event) -> Option<Ordering> {
        self.timestamp().partial_cmp(&other.timestamp())
    }
}

pub struct CollisionSystem {
    pq: BinaryHeapMinPQ<Event>,
    t: f64,
    particles: Vec<Particle>
}

impl CollisionSystem {
    pub fn new(particles: Vec<Particle>) -> CollisionSystem {
        CollisionSystem {
            pq: BinaryHeapMinPQ::new(),
            t: 0.0,
            particles: particles
        }
    }

    fn predict(&mut self, a: usize) {
        // TODO move events in PQ out
        for i in 0 .. self.particles.len() {
            if i == a {
                continue;
            }
            let dt = self.particles[a].time_to_hit(&self.particles[i]);
            self.pq.insert(Event::Hit { timestamp: self.t + dt,
                                        a: a, b: i });
        }
        self.pq.insert(Event::HitVerticalWall { timestamp: self.t + self.particles[a].time_to_hit_vertical_wall(),
                                                a: a });
        self.pq.insert(Event::HitHorizontalWall { timestamp: self.t + self.particles[a].time_to_hit_horizontal_wall(),
                                                  a: a });
    }

    // FIXME: un-done
    // TODO: add message remove or valid check
    pub fn simulate(&mut self) {
        self.pq = BinaryHeapMinPQ::new();

        let n = self.particles.len();
        for i in 0 .. n {
            self.predict(i);
        }
        self.pq.insert(Event::Refresh { timestamp: 0.0 });

        loop {
            if self.pq.is_empty() {
                break;
            }
            let event = self.pq.del_min().unwrap();

            // if !event.is_valid() {
            //     continue;
            // }

            for i in 0 .. n {
                self.particles[i].do_move(event.timestamp() - self.t);
            }
            self.t = event.timestamp();

            match event {
                Event::Hit { a, b, .. } => {
                    let ptr = unsafe { mem::transmute::<_, usize>(&mut self.particles[b]) };
                    self.particles[a].bounce_off(unsafe { mem::transmute::<_, &mut Particle>(ptr) });
                    self.predict(a);
                    self.predict(b);
                },
                Event::HitVerticalWall { a, .. } => {
                    self.particles[a].bounce_off_vertical_wall();
                    self.predict(a);
                },
                Event::HitHorizontalWall { a, .. } => {
                    self.particles[a].bounce_off_horizontal_wall();
                    self.predict(a);
                },
                Event::Refresh { .. } => {
                    println!("refresh");
                }
            }

        }
    }

}
<commit_msg>priority_queues/event_driven_simulation: finish Collision System<commit_after>use rand::{thread_rng, Rng, Rand};
use std::f64;
use std::cmp::Ordering;
use std::mem;
use super::MinPQ;
use super::binary_heaps::BinaryHeapMinPQ;

#[derive(PartialEq, Debug)]
pub struct Particle {
    pub rx: f64,
    pub ry: f64,
    pub vx: f64,
    pub vy: f64,
    pub mass: f64,
    pub radius: f64,
    count: usize
}

impl Particle {
    pub fn new() -> Particle {
        let mut rng = thread_rng();

        Particle {
            rx: rng.next_f64(),
            ry: rng.next_f64(),
            vx: (rng.next_f64() - 0.5) / 10.0,
            vy: (rng.next_f64() - 0.5) / 10.0,
            mass: rng.next_f64() / 100.0,
            radius: (rng.next_f64() + 0.4) / 100.0,
            count: 0
        }
    }

    pub fn do_move(&mut self, dt: f64) {
        // collision with walls
        let (rx, ry, vx, vy) = (self.rx, self.ry, self.vx, self.vy);
        let radius = self.radius;
        if rx + vx*dt < radius || rx + vx*dt > 1.0 - radius {
            self.vx = -vx;
        }
        if ry + vy*dt < radius || ry + vy*dt > 1.0 - radius {
            self.vy = -vy;
        }
        self.rx = rx + vx*dt;
        self.ry = ry + vy*dt;
    }

    pub fn time_to_hit(&self, that: &Particle) -> f64 {
        if self == that {
            return f64::INFINITY
        }
        let dx = that.rx - self.rx;
        let dy = that.ry - self.ry;

        let dvx = that.vx - self.vx;
        let dvy = that.vy - self.vy;

        let dvdr = dx*dvx + dy*dvy;

        if dvdr > 0.0 {
            return f64::INFINITY;
        }

        let dvdv = dvx*dvx + dvy*dvy;
        let drdr = dx*dx + dy*dy;
        let sigma = self.radius + that.radius;
        let d = dvdr*dvdr - dvdv * (drdr - sigma*sigma);
        if d < 0.0 {
            return f64::INFINITY;
        }

        return - (dvdr + d.sqrt()) / dvdv
    }

    pub fn time_to_hit_vertical_wall(&self) -> f64 {
        if self.vx > 0.0 {
            (1.0 - self.rx - self.radius) / self.vx
        } else {
            - (self.rx - self.radius) / self.vx
        }
    }

    pub fn time_to_hit_horizontal_wall(&self) -> f64 {
        if self.vy > 0.0 {
            (1.0 - self.ry - self.radius) / self.vy
        } else {
            - (self.ry - self.radius) / self.vy
        }
    }

    pub fn bounce_off(&mut self, that: &mut Particle) {
        let dx = that.rx - self.rx;
        let dy = that.ry - self.ry;
        let dvx = that.vx - self.vx;
        let dvy = that.vy - self.vy;
        let dvdr = dx*dvx + dy*dvy;
        let dist = self.radius + that.radius;
        let j = 2.0 * self.mass * that.mass * dvdr / ((self.mass + that.mass) * dist);

        let jx = j*dx / dist;
        let jy = j*dy / dist;

        self.vx += jx / self.mass;
        self.vy += jy / self.mass;
        that.vx -= jx / that.mass;
        that.vy -= jy / that.mass;

        self.count += 1;
        that.count += 1;
    }

    pub fn bounce_off_vertical_wall(&mut self) {
        self.vx = -self.vx;
        self.count += 1;
    }

    pub fn bounce_off_horizontal_wall(&mut self) {
        self.vy = -self.vy;
        self.count += 1;
    }
}

impl Rand for Particle {
    fn rand<R: Rng>(rng: &mut R) -> Self {
        Particle {
            rx: rng.next_f64(),
            ry: rng.next_f64(),
            vx: (rng.next_f64() - 0.5) / 10.0,
            vy: (rng.next_f64() - 0.5) / 10.0,
            mass: rng.next_f64() / 100.0,
            radius: (rng.next_f64() + 0.4) / 100.0,
            count: 0
        }
    }
}

#[derive(PartialEq, Debug)]
pub enum Event {
    Hit { timestamp: f64, a: usize, b: usize, count_a: usize, count_b: usize },
    HitVerticalWall { timestamp: f64, a: usize, count_a: usize },
    HitHorizontalWall { timestamp: f64, a: usize, count_a: usize },
    Refresh { timestamp: f64 }
}

impl Event {
    pub fn timestamp(&self) -> f64 {
        match self {
            &Event::Hit { timestamp: t, .. } => t,
            &Event::HitVerticalWall { timestamp: t, .. } => t,
            &Event::HitHorizontalWall { timestamp: t, .. } => t,
            &Event::Refresh { timestamp: t } => t
        }
    }

    pub fn is_valid_for(&self, particles: &[Particle]) -> bool {
        match *self {
            Event::Hit { a, count_a, b, count_b, .. } => {
                println!("a={:?} cnt={}\nb={:?} cnt={}",
                         particles[a], count_a,
                         particles[b], count_b);
                particles[a].count == count_a && particles[b].count == count_b
            },
            Event::HitVerticalWall { a, count_a, .. } => {
                println!("a={:?} cnt={}", particles[a], count_a);
                particles[a].count == count_a
            },
            Event::HitHorizontalWall { a, count_a, .. } => {
                println!("a={:?} cnt={}", particles[a], count_a);
                particles[a].count == count_a
            },
            Event::Refresh { .. } => true
        }
    }
}

impl PartialOrd for Event {
    fn partial_cmp(&self, other: &Event) -> Option<Ordering> {
        self.timestamp().partial_cmp(&other.timestamp())
    }
}

pub struct CollisionSystem {
    pq: BinaryHeapMinPQ<Event>,
    t: f64,
    particles: Vec<Particle>
}

impl CollisionSystem {
    pub fn new(particles: Vec<Particle>) -> CollisionSystem {
        CollisionSystem {
            pq: BinaryHeapMinPQ::new(),
            t: 0.0,
            particles: particles
        }
    }

    fn predict(&mut self, a: usize) {
        // TODO move events in PQ out
        for i in 0 .. self.particles.len() {
            if i == a {
                continue;
            }
            let dt = self.particles[a].time_to_hit(&self.particles[i]);
            self.pq.insert(Event::Hit {
                timestamp: self.t + dt,
                a: a, b: i,
                count_a: self.particles[a].count,
                count_b: self.particles[i].count });
        }
        self.pq.insert(Event::HitVerticalWall {
            timestamp: self.t + self.particles[a].time_to_hit_vertical_wall(),
            a: a,
            count_a: self.particles[a].count });
        self.pq.insert(Event::HitHorizontalWall {
            timestamp: self.t + self.particles[a].time_to_hit_horizontal_wall(),
            a: a,
            count_a: self.particles[a].count });
    }

    // FIXME: un-done
    // TODO: add message remove or valid check
    pub fn simulate(&mut self) {
        self.pq = BinaryHeapMinPQ::new();

        let n = self.particles.len();
        for i in 0 .. n {
            self.predict(i);
        }
        self.pq.insert(Event::Refresh { timestamp: 0.0 });

        // loop {
        for _ in 0 .. 10 {
            if self.pq.is_empty() {
                break;
            }
            let event = self.pq.del_min().unwrap();

            // FIXME: <= self.t
            if !event.is_valid_for(&self.particles) || event.timestamp() <= self.t {
                continue
            }

            for i in 0 .. n {
                self.particles[i].do_move(event.timestamp() - self.t);
            }
            self.t = event.timestamp();

            match event {
                Event::Hit { a, b, .. } => {
                    println!("{}: {} hit {}", self.t, a, b);
                    let ptr = unsafe { mem::transmute::<_, usize>(&mut self.particles[b]) };
                    self.particles[a].bounce_off(unsafe { mem::transmute::<_, &mut Particle>(ptr) });
                    self.predict(a);
                    self.predict(b);
                },
                Event::HitVerticalWall { a, .. } => {
                    println!("{}: {} hit vertical wall", self.t, a);
                    self.particles[a].bounce_off_vertical_wall();
                    self.predict(a);
                },
                Event::HitHorizontalWall { a, .. } => {
                    println!("{}: {} hit horizontal wall", self.t, a);
                    self.particles[a].bounce_off_horizontal_wall();
                    self.predict(a);
                },
                Event::Refresh { .. } => {
                    println!("refresh");
                }
            }
        }
    }
}

#[test]
fn test_collision_system() {
    let mut rng = thread_rng();
    let mut ps: Vec<Particle> = Vec::new();
    for _ in 0 .. 20 {
        ps.push(rng.gen());
    }

    let mut sys = CollisionSystem::new(ps);
    sys.simulate();
}
<|endoftext|>


<commit_before>extern crate minifb;

use minifb::{Key, MENU_KEY_CTRL, MENU_KEY_COMMAND};
use minifb::Menu as MinifbMenu;

const MENU_FILE_OPEN_AND_RUN_EXE: usize = 1;
const MENU_FILE_OPEN_SOURCE: usize = 1;
const MENU_DEBUG_ATTACH_TO_REMOTE: usize = 50;
const MENU_DEBUG_START: usize = 51;
const MENU_DEBUG_STEP_IN: usize = 52;
const MENU_DEBUG_STEP_OVER: usize = 53;
const MENU_DEBUG_TOGGLE_BREAKPOINT: usize = 54;

pub struct Menu<'a> {
    pub file_menu: Vec<MinifbMenu<'a>>,
    pub debug_menu: Vec<MinifbMenu<'a>>,
}

impl<'a> Menu<'a> {
    pub fn new() -> Menu<'a> {
        Menu {
            file_menu: Self::create_file_menu(),
            debug_menu: Self::create_debug_menu(),
        }
    }

    pub fn create_file_menu() -> Vec<MinifbMenu<'a>> {
        vec![
            MinifbMenu {
                name: "Open and run executable...",
                key: Key::D,
                id: MENU_FILE_OPEN_AND_RUN_EXE,
                modifier: MENU_KEY_CTRL,
                mac_mod: MENU_KEY_COMMAND,
                ..MinifbMenu::default()
            },
            MinifbMenu {
                name: "Open Source...",
                key: Key::O,
                id: MENU_FILE_OPEN_SOURCE,
                modifier: MENU_KEY_CTRL,
                mac_mod: MENU_KEY_COMMAND,
                ..MinifbMenu::default()
            }
        ]
    }

    pub fn create_debug_menu() -> Vec<MinifbMenu<'a>> {
        vec![
            MinifbMenu {
                name: "Attach to Remote...",
                key: Key::F6,
                id: MENU_DEBUG_ATTACH_TO_REMOTE ,
                ..MinifbMenu::default()
            },
            MinifbMenu  {
                name: "Start",
                key: Key::F5,
                id: MENU_DEBUG_START,
                ..MinifbMenu::default()
            },
            MinifbMenu {
                name: "Step In",
                key: Key::F11,
                id: MENU_DEBUG_STEP_IN,
                ..MinifbMenu::default()
            },
            MinifbMenu {
                name: "Step Over",
                key: Key::F10,
                id: MENU_DEBUG_STEP_OVER,
                ..MinifbMenu::default()
            },
            MinifbMenu {
                name: "Toggle Breakpoint",
                key: Key::F9,
                id: MENU_DEBUG_TOGGLE_BREAKPOINT,
                ..MinifbMenu::default()
            }
        ]
    }
}

<commit_msg>Export menu ids<commit_after>extern crate minifb;

use minifb::{Key, MENU_KEY_CTRL, MENU_KEY_COMMAND};
use minifb::Menu as MinifbMenu;

pub const MENU_FILE_OPEN_AND_RUN_EXE: usize = 1;
pub const MENU_FILE_OPEN_SOURCE: usize = 1;
pub const MENU_DEBUG_ATTACH_TO_REMOTE: usize = 50;
pub const MENU_DEBUG_START: usize = 51;
pub const MENU_DEBUG_STEP_IN: usize = 52;
pub const MENU_DEBUG_STEP_OVER: usize = 53;
pub const MENU_DEBUG_TOGGLE_BREAKPOINT: usize = 54;

pub struct Menu<'a> {
    pub file_menu: Vec<MinifbMenu<'a>>,
    pub debug_menu: Vec<MinifbMenu<'a>>,
}

impl<'a> Menu<'a> {
    pub fn new() -> Menu<'a> {
        Menu {
            file_menu: Self::create_file_menu(),
            debug_menu: Self::create_debug_menu(),
        }
    }

    pub fn create_file_menu() -> Vec<MinifbMenu<'a>> {
        vec![
            MinifbMenu {
                name: "Open and run executable...",
                key: Key::D,
                id: MENU_FILE_OPEN_AND_RUN_EXE,
                modifier: MENU_KEY_CTRL,
                mac_mod: MENU_KEY_COMMAND,
                ..MinifbMenu::default()
            },
            MinifbMenu {
                name: "Open Source...",
                key: Key::O,
                id: MENU_FILE_OPEN_SOURCE,
                modifier: MENU_KEY_CTRL,
                mac_mod: MENU_KEY_COMMAND,
                ..MinifbMenu::default()
            }
        ]
    }

    pub fn create_debug_menu() -> Vec<MinifbMenu<'a>> {
        vec![
            MinifbMenu {
                name: "Attach to Remote...",
                key: Key::F6,
                id: MENU_DEBUG_ATTACH_TO_REMOTE ,
                ..MinifbMenu::default()
            },
            MinifbMenu  {
                name: "Start",
                key: Key::F5,
                id: MENU_DEBUG_START,
                ..MinifbMenu::default()
            },
            MinifbMenu {
                name: "Step In",
                key: Key::F11,
                id: MENU_DEBUG_STEP_IN,
                ..MinifbMenu::default()
            },
            MinifbMenu {
                name: "Step Over",
                key: Key::F10,
                id: MENU_DEBUG_STEP_OVER,
                ..MinifbMenu::default()
            },
            MinifbMenu {
                name: "Toggle Breakpoint",
                key: Key::F9,
                id: MENU_DEBUG_TOGGLE_BREAKPOINT,
                ..MinifbMenu::default()
            }
        ]
    }
}

<|endoftext|>


<commit_before>// As the name implies, unsigned integers (u8, u16, u32, u64) cannot be negative
#[test]
fn unsigned_ints() {
    assert!(u8::min_value() == __);
}

// Unsigned integers can be reduced only as far as their minimum value of 0
#[test]
fn sub_unsigned_int() {
    let mut num: u8 = 10;
    num -= 10;
    assert!(num __ u8::min_value());
}

// Signed integers(i8, i16, i32, i64), on the other hand, can be negative
#[test]
fn signed_ints() {
    assert!(i8::min_value() __ 0);
}

// Signed integers can be reduced below zero, as far as their minimum value.
// hint: The maximum magnitude for a negative integer is greater than
// that of a positive integer
#[test]
fn sub_signed_int() {
    let mut num: i8 = 0;
    let negative: i8 = __;
    num += negative;
    assert!(num == i8::min_value());
}

// Addition of positive integers works much the same for signed and unsigned numbers
#[test]
fn add_numbers() {
    let mut sig: i8 = 0;
    let mut unsig: u8 = 0;
    sig += __;
    unsig += __;
    assert!(sig == i8::max_value() && unsig == u8::max_value());
}

// Like any variable in Rust, integers are immutable unless declared otherwise
#[test]
fn mutating_ints() {
    let num: i8 = 1;
    num += 2;
    assert!(num == 3);
}

// While regular immutable variables cannot be changed, mutable versions of them can be
#[test]
fn referencing_values() {
    let num: i8 = 1;
    __ = num;
    mut_num += 1;
    assert!(num != mut_num);
}
<commit_msg>Updated koan with missing __ in integer.rs<commit_after>// As the name implies, unsigned integers (u8, u16, u32, u64) cannot be negative
#[test]
fn unsigned_ints() {
    assert!(u8::min_value() == __);
}

// Unsigned integers can be reduced only as far as their minimum value of 0
#[test]
fn sub_unsigned_int() {
    let mut num: u8 = 10;
    num -= 10;
    assert!(num __ u8::min_value());
}

// Signed integers(i8, i16, i32, i64), on the other hand, can be negative
#[test]
fn signed_ints() {
    assert!(i8::min_value() __ 0);
}

// Signed integers can be reduced below zero, as far as their minimum value.
// hint: The maximum magnitude for a negative integer is greater than
// that of a positive integer
#[test]
fn sub_signed_int() {
    let mut num: i8 = 0;
    let negative: i8 = __;
    num += negative;
    assert!(num == i8::min_value());
}

// Addition of positive integers works much the same for signed and unsigned numbers
#[test]
fn add_numbers() {
    let mut sig: i8 = 0;
    let mut unsig: u8 = 0;
    sig += __;
    unsig += __;
    assert!(sig == i8::max_value() && unsig == u8::max_value());
}

// Like any variable in Rust, integers are immutable unless declared otherwise
#[test]
fn mutating_ints() {
    let __ num: i8 = 1;
    num += 2;
    assert!(num == 3);
}

// While regular immutable variables cannot be changed, mutable versions of them can be
#[test]
fn referencing_values() {
    let num: i8 = 1;
    __ = num;
    mut_num += 1;
    assert!(num != mut_num);
}
<|endoftext|>


<commit_before>/* AES-128 CBC mode
 *
 * Dmitry Vasiliev <dima@hlabs.org>
 */

extern crate libc;
extern crate serialize;

#[cfg(not(test))]
use std::path::Path;
#[cfg(not(test))]
use std::io::fs::File;
#[cfg(not(test))]
use std::str;

use libc::{c_int, c_uint};

#[cfg(not(test))]
use serialize::base64::FromBase64;

static AES_BLOCK_SIZE: uint = 16u;
static RD_KEY_SIZE: uint = 4 * (14 + 1); // 4 * (AEX_MAXNR + 1)

#[repr(C)]
struct AesKey {
    rd_key: [c_uint, ..RD_KEY_SIZE],
    rounds: c_int,
}

#[link(name="crypto")]
extern {
    fn AES_set_decrypt_key(userKey: *const u8, bits: c_int,
                           key: *mut AesKey) -> c_int;
    fn AES_decrypt(input: *const u8, out: *mut u8, key: *const AesKey);

}

/*
 * Initialize AES key structure
 */
fn init_aes_key(key: &[u8]) -> AesKey {
    if key.len() != AES_BLOCK_SIZE {
        fail!("Invalid key size");
    }
    let mut aes_key = AesKey{rd_key: [0, ..RD_KEY_SIZE], rounds: 0};
    let bits = 8 * AES_BLOCK_SIZE as c_int;
    let res = unsafe {AES_set_decrypt_key(key.as_ptr(), bits, &mut aes_key)};
    if res != 0 {
        fail!("Unable to init AES key. AES_set_decrypt_key() -> {}", res);
    }
    aes_key
}

/*
 * Remove PKCS-7 padding
 */
fn remove_pkcs7_padding(mut data: Vec<u8>) -> Vec<u8> {
    let len = data.len();
    match data.last() {
        Some(&c) if (c as uint) < AES_BLOCK_SIZE =>
            data.truncate(len - c as uint),
        _ => ()
    }
    data
}

/*
 * AES CBC decryption
 */
fn decrypt_aes_cbc(encrypted: &[u8], key: &[u8], iv: &[u8]) -> Vec<u8> {
    if iv.len() != AES_BLOCK_SIZE {
        fail!("Invlaid IV size");
    }
    let enc_len = encrypted.len();
    if enc_len % AES_BLOCK_SIZE != 0 {
        fail!("Invalid size of encrypted data");
    }
    let mut result: Vec<u8> = Vec::with_capacity(enc_len);
    if enc_len > 0 {
        let aes_key = init_aes_key(key);
        let mut dec = [0u8, ..AES_BLOCK_SIZE];
        encrypted.chunks(AES_BLOCK_SIZE).fold(iv, |prev, block| {
            unsafe {AES_decrypt(block.as_ptr(), dec.as_mut_ptr(), &aes_key)};
            // XOR ECB decripted block with the previous encrypted block
            let dblk = prev.iter().zip(dec.iter()).map(|(&c1, &c2)| c1 ^ c2);
            result.extend(dblk);
            block
        });
    }
    remove_pkcs7_padding(result)
}

#[cfg(not(test))]
fn read_hex_file(path: &Path) -> Vec<u8> {
    match File::open(path) {
        Ok(mut file) => {
            let data = file.read_to_end().unwrap();
            let text = str::from_utf8(data.as_slice()).unwrap();
            text.from_base64().unwrap()
        },
        Err(error) => fail!("Unable to open {}: {}", path.as_str(), error)
    }
}

/*
 * Main entry point
 */
#[cfg(not(test))]
fn main() {
    let path = Path::new("10.txt");
    let data = read_hex_file(&path);
    let key = "YELLOW SUBMARINE".into_string().into_bytes();
    let iv = Vec::from_elem(16u, 0u8);
    let decrypted = decrypt_aes_cbc(data.as_slice(), key.as_slice(),
                                    iv.as_slice());
    println!("Decrypted => \"{}\"",
             String::from_utf8_lossy(decrypted.as_slice()));
}
<commit_msg>Implement AES CBC encryption<commit_after>/* AES-128 CBC mode
 *
 * Dmitry Vasiliev <dima@hlabs.org>
 */

extern crate libc;
extern crate serialize;

#[cfg(not(test))]
use std::path::Path;
#[cfg(not(test))]
use std::io::fs::File;
#[cfg(not(test))]
use std::str;

use libc::{c_int, c_uint};

#[cfg(not(test))]
use serialize::base64::FromBase64;

static AES_BLOCK_SIZE: uint = 16u;
static RD_KEY_SIZE: uint = 4 * (14 + 1); // 4 * (AEX_MAXNR + 1)

#[repr(C)]
struct AesKey {
    rd_key: [c_uint, ..RD_KEY_SIZE],
    rounds: c_int,
}

#[link(name="crypto")]
extern {
    fn AES_set_decrypt_key(userKey: *const u8, bits: c_int,
                           key: *mut AesKey) -> c_int;
    fn AES_set_encrypt_key(userKey: *const u8, bits: c_int,
                           key: *mut AesKey) -> c_int;
    fn AES_decrypt(input: *const u8, out: *mut u8, key: *const AesKey);
    fn AES_encrypt(input: *const u8, out: *mut u8, key: *const AesKey);

}

/*
 * Initialize AES key structure
 */
#[inline]
fn init_aes_key(key: &[u8], set_key: |*const u8, c_int, *mut AesKey| -> c_int)
        -> AesKey {
    if key.len() != AES_BLOCK_SIZE {
        fail!("Invalid key size");
    }
    let mut aes_key = AesKey{rd_key: [0, ..RD_KEY_SIZE], rounds: 0};
    let bits = 8 * AES_BLOCK_SIZE as c_int;
    let res = set_key(key.as_ptr(), bits, &mut aes_key);
    if res != 0 {
        fail!("Unable to init AES key -> {}", res);
    }
    aes_key
}

/*
 * Initialize AES decryption key
 */
fn init_aes_decrypt_key(key: &[u8]) -> AesKey {
    init_aes_key(key, |user_key, bits, aes_key| unsafe {
        AES_set_decrypt_key(user_key, bits, aes_key)
        })
}

/*
 * Initialize AES encryption key
 */
fn init_aes_encrypt_key(key: &[u8]) -> AesKey {
    init_aes_key(key, |user_key, bits, aes_key| unsafe {
        AES_set_encrypt_key(user_key, bits, aes_key)
        })
}

/*
 * Remove PKCS-7 padding
 */
fn remove_pkcs7_padding(mut data: Vec<u8>) -> Vec<u8> {
    let len = data.len();
    match data.last() {
        Some(&c) if (c as uint) < AES_BLOCK_SIZE =>
            data.truncate(len - c as uint),
        _ => ()
    }
    data
}

/*
 * AES CBC decryption
 */
fn decrypt_aes_cbc(encrypted: &[u8], key: &[u8], iv: &[u8]) -> Vec<u8> {
    if iv.len() != AES_BLOCK_SIZE {
        fail!("Invlaid IV size");
    }
    let len = encrypted.len();
    if len % AES_BLOCK_SIZE != 0 {
        fail!("Invalid size of encrypted data");
    }
    let mut result: Vec<u8> = Vec::with_capacity(len);
    if len > 0 {
        let aes_key = init_aes_decrypt_key(key);
        let mut dec = [0u8, ..AES_BLOCK_SIZE];
        encrypted.chunks(AES_BLOCK_SIZE).fold(iv, |prev, block| {
            unsafe {AES_decrypt(block.as_ptr(), dec.as_mut_ptr(), &aes_key)};
            // XOR ECB decripted block with the previous encrypted block
            let dblk = prev.iter().zip(dec.iter()).map(|(&c1, &c2)| c1 ^ c2);
            result.extend(dblk);
            block
        });
    }
    remove_pkcs7_padding(result)
}

/*
 * PKCS-7 padding
 */
fn pkcs7_padding(data: &[u8]) -> Vec<u8> {
    match data.len() % AES_BLOCK_SIZE {
        0 => data.into_vec(),
        size => {
            let pad = AES_BLOCK_SIZE - size;
            data.into_vec() + Vec::from_elem(pad, pad as u8)
        }
    }
}

/*
 * AES CBC encryption
 */
fn encrypt_aes_cbc(orig_data: &[u8], key: &[u8], iv: &[u8]) -> Vec<u8> {
    if iv.len() != AES_BLOCK_SIZE {
        fail!("Invlaid IV size");
    }
    let data = pkcs7_padding(orig_data);
    let len = data.len();
    let mut result: Vec<u8> = Vec::with_capacity(len);
    if len > 0 {
        let aes_key = init_aes_encrypt_key(key);
        let mut enc = [0u8, ..AES_BLOCK_SIZE];
        data.as_slice().chunks(AES_BLOCK_SIZE).fold(iv, |prev, block| {
            // XOR block with the previous encrypted block
            let eblk: Vec<u8> = prev.iter().zip(block.iter()).map(
                                            |(&c1, &c2)| c1 ^ c2).collect();
            unsafe {AES_encrypt(eblk.as_ptr(), enc.as_mut_ptr(), &aes_key)};
            result.extend(enc.iter().map(|c| *c));
            enc
        });
    }
    result
}

#[cfg(not(test))]
fn read_hex_file(path: &Path) -> Vec<u8> {
    match File::open(path) {
        Ok(mut file) => {
            let data = file.read_to_end().unwrap();
            let text = str::from_utf8(data.as_slice()).unwrap();
            text.from_base64().unwrap()
        },
        Err(error) => fail!("Unable to open {}: {}", path.as_str(), error)
    }
}

/*
 * Main entry point
 */
#[cfg(not(test))]
fn main() {
    let path = Path::new("10.txt");
    let data = read_hex_file(&path);
    let key = "YELLOW SUBMARINE".into_string().into_bytes();
    let iv = Vec::from_elem(16u, 0u8);
    let decrypted = decrypt_aes_cbc(data.as_slice(), key.as_slice(),
                                    iv.as_slice());
    println!("Decrypted => \"{}\"",
             String::from_utf8_lossy(decrypted.as_slice()));
    assert_eq!(data, encrypt_aes_cbc(decrypted.as_slice(), key.as_slice(),
                                     iv.as_slice()));
    println!("Encryption OK!");
}
<|endoftext|>


<commit_before>//! Parse byte iterators to float.

use super::algorithm::*;
use super::digit::*;
use super::exponent::*;
use super::num::*;

// PARSERS
// -------

/// Parse the significant digits of the float.
///
/// * `integer`     - Slice containing the integer digits.
/// * `fraction`    - Slice containing the fraction digits.
fn parse_mantissa(integer: &[u8], fraction: &[u8]) -> (u64, usize) {
    let mut value: u64 = 0;
    // On overflow, validate that all the remaining characters are valid
    // digits, if not, return the first invalid digit. Otherwise,
    // calculate the number of truncated digits.
    let mut integer = integer.iter();
    while let Some(c) = integer.next() {
        value = match add_digit(value, to_digit(*c).unwrap()) {
            Some(v) => v,
            None => return (value, 1 + integer.count() + fraction.len()),
        };
    }
    let mut fraction = fraction.iter();
    while let Some(c) = fraction.next() {
        value = match add_digit(value, to_digit(*c).unwrap()) {
            Some(v) => v,
            None => return (value, 1 + fraction.count()),
        };
    }
    (value, 0)
}

/// Parse float from extracted float components.
///
/// * `integer`     - Slice containing the integer digits.
/// * `fraction`    - Slice containing the fraction digits.
/// * `exponent`    - Parsed, 32-bit exponent.
///
/// Precondition: The integer must not have leading zeros.
pub fn parse_float<F>(integer: &[u8], mut fraction: &[u8], exponent: i32) -> F
where
    F: Float,
{
    // Trim trailing zeroes from the fraction part.
    while fraction.last() == Some(&b'0') {
        fraction = &fraction[..fraction.len() - 1];
    }

    // Parse the mantissa and attempt the fast and moderate-path algorithms.
    let (mantissa, truncated) = parse_mantissa(integer, fraction);
    let is_truncated = truncated != 0;

    // Process the state to a float.
    if mantissa == 0 {
        // Literal 0, return early.
        // Value cannot be truncated, since truncation only occurs on
        // overflow or underflow.
        F::ZERO
    } else if !is_truncated {
        // Try the fast path, no mantissa truncation.
        let mant_exp = mantissa_exponent(exponent, fraction.len(), 0);
        if let Some(float) = fast_path(mantissa, mant_exp) {
            float
        } else {
            fallback_path(
                integer,
                fraction,
                mantissa,
                exponent,
                mant_exp,
                is_truncated,
            )
        }
    } else {
        let mant_exp = mantissa_exponent(exponent, fraction.len(), truncated);
        fallback_path(
            integer,
            fraction,
            mantissa,
            exponent,
            mant_exp,
            is_truncated,
        )
    }
}
<commit_msg>Remove inapplicable comment about validation in parse_mantissa<commit_after>//! Parse byte iterators to float.

use super::algorithm::*;
use super::digit::*;
use super::exponent::*;
use super::num::*;

// PARSERS
// -------

/// Parse the significant digits of the float.
///
/// * `integer`     - Slice containing the integer digits.
/// * `fraction`    - Slice containing the fraction digits.
fn parse_mantissa(integer: &[u8], fraction: &[u8]) -> (u64, usize) {
    let mut value: u64 = 0;
    // On overflow, calculate the number of truncated digits.
    let mut integer = integer.iter();
    while let Some(c) = integer.next() {
        value = match add_digit(value, to_digit(*c).unwrap()) {
            Some(v) => v,
            None => return (value, 1 + integer.count() + fraction.len()),
        };
    }
    let mut fraction = fraction.iter();
    while let Some(c) = fraction.next() {
        value = match add_digit(value, to_digit(*c).unwrap()) {
            Some(v) => v,
            None => return (value, 1 + fraction.count()),
        };
    }
    (value, 0)
}

/// Parse float from extracted float components.
///
/// * `integer`     - Slice containing the integer digits.
/// * `fraction`    - Slice containing the fraction digits.
/// * `exponent`    - Parsed, 32-bit exponent.
///
/// Precondition: The integer must not have leading zeros.
pub fn parse_float<F>(integer: &[u8], mut fraction: &[u8], exponent: i32) -> F
where
    F: Float,
{
    // Trim trailing zeroes from the fraction part.
    while fraction.last() == Some(&b'0') {
        fraction = &fraction[..fraction.len() - 1];
    }

    // Parse the mantissa and attempt the fast and moderate-path algorithms.
    let (mantissa, truncated) = parse_mantissa(integer, fraction);
    let is_truncated = truncated != 0;

    // Process the state to a float.
    if mantissa == 0 {
        // Literal 0, return early.
        // Value cannot be truncated, since truncation only occurs on
        // overflow or underflow.
        F::ZERO
    } else if !is_truncated {
        // Try the fast path, no mantissa truncation.
        let mant_exp = mantissa_exponent(exponent, fraction.len(), 0);
        if let Some(float) = fast_path(mantissa, mant_exp) {
            float
        } else {
            fallback_path(
                integer,
                fraction,
                mantissa,
                exponent,
                mant_exp,
                is_truncated,
            )
        }
    } else {
        let mant_exp = mantissa_exponent(exponent, fraction.len(), truncated);
        fallback_path(
            integer,
            fraction,
            mantissa,
            exponent,
            mant_exp,
            is_truncated,
        )
    }
}
<|endoftext|>


<commit_before>use mio;
use std::io;
use std::thread;
use std::sync::mpsc;

pub struct Session {
	cmd_sender: mio::Sender<SessionCmd>,
	evt_receiver: mpsc::Receiver<SessionEvt>

	// Could use https://github.com/polyfractal/bounded-spsc-queue ?
	// Only if there is one receiver per NanoSocket and they are only 'Send'
}

impl Session {
	pub fn new() -> io::Result<Session> {
		let mut event_loop = try!(mio::EventLoop::new());
		let (tx, rx) = mpsc::channel();
		let mut handler = SessionEventLoopHandler { event_sender: tx };
		let session = Session {
			cmd_sender: event_loop.channel(),
			evt_receiver: rx };

		thread::spawn(move || event_loop.run(&mut handler));

		Ok(session)
	}

	fn ping_event_loop(&self) {
		self.cmd_sender.send(SessionCmd::Ping);
		self.evt_receiver.recv();
	}
}

enum SessionCmd {
	Ping
}

enum SessionEvt {
	Pong
}

struct SessionEventLoopHandler {
	event_sender: mpsc::Sender<SessionEvt>
}

impl SessionEventLoopHandler {

	fn pong(&self) {
		self.event_sender.send(SessionEvt::Pong);
	}

}

impl mio::Handler for SessionEventLoopHandler {
    type Timeout = ();
    type Message = SessionCmd;

    fn notify(&mut self, event_loop: &mut mio::EventLoop<Self>, msg: Self::Message) {
    	match msg {
    		SessionCmd::Ping => self.pong()
    	}

    }
}

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

    #[test]
    fn session_can_be_created() {
    	let session = Session::new().unwrap();

    	session.ping_event_loop();
    }
}<commit_msg>Adds socket and protocol socket structs<commit_after>use mio;
use mio::util::Slab;
use std::io;
use std::thread;
use std::sync::mpsc;

pub struct Session {
	cmd_sender: mio::Sender<SessionCmd>,
	evt_receiver: mpsc::Receiver<SessionEvt>
	// Could use https://github.com/polyfractal/bounded-spsc-queue ?
	// Only if there is one receiver per NanoSocket and they are only 'Send'
}

impl Session {
	pub fn new() -> io::Result<Session> {
		let mut event_loop = try!(mio::EventLoop::new());
		let (tx, rx) = mpsc::channel();
		let mut handler = SessionEventLoopHandler {
			event_sender: tx,
			sockets: Slab::new(1024) };
		let session = Session {
			cmd_sender: event_loop.channel(),
			evt_receiver: rx };

		thread::spawn(move || event_loop.run(&mut handler));

		Ok(session)
	}

	fn ping_event_loop(&self) {
		self.cmd_sender.send(SessionCmd::Ping);
		self.evt_receiver.recv().unwrap();
	}

	pub fn create_socket(&self) -> Option<Socket> {
		self.cmd_sender.send(SessionCmd::CreateSocket);
		match self.evt_receiver.recv().unwrap() {

			SessionEvt::SocketCreated(rx) => {

				let socket = Socket {
					cmd_sender: self.cmd_sender.clone(),
					evt_receiver: rx
				};

				Some(socket)
			}
			_ => None
		}
	}
}

impl Drop for Session {
	fn drop(&mut self) {
		self.cmd_sender.send(SessionCmd::Shutdown);
	}
}

pub struct Socket {
	cmd_sender: mio::Sender<SessionCmd>,
	evt_receiver: mpsc::Receiver<SocketEvt>
}

impl Socket {
	pub fn ping(&self) {
		self.cmd_sender.send(SessionCmd::PingSocket);
		self.evt_receiver.recv().unwrap();
	}
}

struct ProtocolSocket {
	evt_sender: mpsc::Sender<SocketEvt>
}

impl ProtocolSocket {

	fn pong(&self) {
		self.evt_sender.send(SocketEvt::Pong);
	}

}

enum SocketEvt {
    Pong
}

enum SessionCmd {
	Ping,
	CreateSocket,
	PingSocket,
	Shutdown
}

enum SessionEvt {
	Pong,
	SocketCreated(mpsc::Receiver<SocketEvt>)
}

struct SessionEventLoopHandler {
	event_sender: mpsc::Sender<SessionEvt>,
	sockets: Slab<ProtocolSocket>
}

impl SessionEventLoopHandler {

	fn pong(&self) {
		self.event_sender.send(SessionEvt::Pong);
	}

	fn create_socket(&mut self) {
		let (tx, rx) = mpsc::channel();
		let socket = ProtocolSocket { evt_sender: tx };

		self.sockets.insert(socket);
		self.event_sender.send(SessionEvt::SocketCreated(rx));
	}

	fn ping_socket(&self) {
		for socket in self.sockets.iter() {
			socket.pong();
		}
	}
}

impl mio::Handler for SessionEventLoopHandler {
    type Timeout = ();
    type Message = SessionCmd;

    fn notify(&mut self, event_loop: &mut mio::EventLoop<Self>, msg: Self::Message) {
    	match msg {
    		SessionCmd::Ping => self.pong(),
    		SessionCmd::CreateSocket => self.create_socket(),
    		SessionCmd::PingSocket => self.ping_socket(),
    		SessionCmd::Shutdown => event_loop.shutdown()
    	}

    }
}

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

    #[test]
    fn session_can_be_created() {
    	let session = Session::new().unwrap();

    	session.ping_event_loop();
    }

    #[test]
    fn session_can_create_a_socket() {
    	let session = Session::new().unwrap();
    	let socket = session.create_socket();

    }

    #[test]
    fn can_ping_socket() {
    	let session = Session::new().unwrap();
    	let socket = session.create_socket().unwrap();

    	socket.ping();
    }
}<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

/*!
Primitive traits representing basic 'kinds' of types

Rust types can be classified in various useful ways according to
intrinsic properties of the type. These classifications, often called
'kinds', are represented as traits.

They cannot be implemented by user code, but are instead implemented
by the compiler automatically for the types to which they apply.

*/

/// Types able to be transferred across task boundaries.
#[lang="send"]
pub trait Send {
    // empty.
}

/// Types with a constant size known at compile-time.
#[lang="sized"]
pub trait Sized {
    // Empty.
}

/// Types that can be copied by simply copying bits (i.e. `memcpy`).
#[lang="copy"]
pub trait Copy {
    // Empty.
}

/// Types that can be safely shared between tasks when aliased.
///
/// The precise definition is: a type `T` is `Share` if `&T` is
/// thread-safe. In other words, there is no possibility of data races
/// when passing `&T` references between tasks.
///
/// As one would expect, primitive types like `u8` and `f64` are all
/// `Share`, and so are simple aggregate types containing them (like
/// tuples, structs and enums). More instances of basic `Share` types
/// include "immutable" types like `&T` and those with simple
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
/// collection types. (Generic parameters need to be `Share` for their
/// container to be `Share`.)
///
/// A somewhat surprising consequence of the definition is `&mut T` is
/// `Share` (if `T` is `Share`) even though it seems that it might
/// provide unsynchronised mutation. The trick is a mutable reference
/// stored in an aliasable reference (that is, `& &mut T`) becomes
/// read-only, as if it were a `& &T`, hence there is no risk of a data
/// race.
///
/// Types that are not `Share` are those that have "interior
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
/// in `std::cell`. These types allow for mutation of their contents
/// even when in an immutable, aliasable slot, e.g. the contents of
/// `&Cell<T>` can be `.set`, and do not ensure data races are
/// impossible, hence they cannot be `Share`. A higher level example
/// of a non-`Share` type is the reference counted pointer
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
/// reference, which modifies the reference counts in a non-atomic
/// way.
///
/// For cases when one does need thread-safe interior mutability,
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
/// the `sync` crate do ensure that any mutation cannot cause data
/// races.  Hence these types are `Share`.
///
/// Users writing their own types with interior mutability (or anything
/// else that is not thread-safe) should use the `NoShare` marker type
/// (from `std::kinds::marker`) to ensure that the compiler doesn't
/// consider the user-defined type to be `Share`.  Any types with
/// interior mutability must also use the `std::cell::UnsafeCell` wrapper
/// around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[lang="share"]
pub trait Share {
    // Empty
}

/// Marker types are special types that are used with unsafe code to
/// inform the compiler of special constraints. Marker types should
/// only be needed when you are creating an abstraction that is
/// implemented using unsafe code. In that case, you may want to embed
/// some of the marker types below into your type.
pub mod marker {

    /// A marker type whose type parameter `T` is considered to be
    /// covariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` is being stored
    /// into memory and read from, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a covariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```ignore
    /// use std::mem;
    ///
    /// struct S<T> { x: *() }
    /// fn get<T>(s: &S<T>) -> T {
    ///    unsafe {
    ///        let x: *T = mem::transmute(s.x);
    ///        *x
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<~[int]>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `*T` and reads from it. Therefore, we should include the
    /// a marker field `CovariantType<T>` to inform the type checker that
    /// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
    /// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
    /// for some lifetime `'a`, but not the other way around).
    #[lang="covariant_type"]
    #[deriving(PartialEq,Clone)]
    pub struct CovariantType<T>;

    /// A marker type whose type parameter `T` is considered to be
    /// contravariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` will be consumed
    /// (but not read from), even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a contravariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```
    /// use std::mem;
    ///
    /// struct S<T> { x: *const () }
    /// fn get<T>(s: &S<T>, v: T) {
    ///    unsafe {
    ///        let x: fn(T) = mem::transmute(s.x);
    ///        x(v)
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<~[int]>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `fn(T)` and then passes a value of type `T` to it.
    ///
    /// Supplying a `ContravariantType` marker would correct the
    /// problem, because it would mark `S` so that `S<T>` is only a
    /// subtype of `S<U>` if `U` is a subtype of `T`; given that the
    /// function requires arguments of type `T`, it must also accept
    /// arguments of type `U`, hence such a conversion is safe.
    #[lang="contravariant_type"]
    #[deriving(PartialEq,Clone)]
    pub struct ContravariantType<T>;

    /// A marker type whose type parameter `T` is considered to be
    /// invariant with respect to the type itself. This is (typically)
    /// used to indicate that instances of the type `T` may be read or
    /// written, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// # Example
    ///
    /// The Cell type is an example which uses unsafe code to achieve
    /// "interior" mutability:
    ///
    /// ```
    /// pub struct Cell<T> { value: T }
    /// # fn main() {}
    /// ```
    ///
    /// The type system would infer that `value` is only read here and
    /// never written, but in fact `Cell` uses unsafe code to achieve
    /// interior mutability.
    #[lang="invariant_type"]
    #[deriving(PartialEq,Clone)]
    pub struct InvariantType<T>;

    /// As `CovariantType`, but for lifetime parameters. Using
    /// `CovariantLifetime<'a>` indicates that it is ok to substitute
    /// a *longer* lifetime for `'a` than the one you originally
    /// started with (e.g., you could convert any lifetime `'foo` to
    /// `'static`). You almost certainly want `ContravariantLifetime`
    /// instead, or possibly `InvariantLifetime`. The only case where
    /// it would be appropriate is that you have a (type-casted, and
    /// hence hidden from the type system) function pointer with a
    /// signature like `fn(&'a T)` (and no other uses of `'a`). In
    /// this case, it is ok to substitute a larger lifetime for `'a`
    /// (e.g., `fn(&'static T)`), because the function is only
    /// becoming more selective in terms of what it accepts as
    /// argument.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="covariant_lifetime"]
    #[deriving(PartialEq,Clone)]
    pub struct CovariantLifetime<'a>;

    /// As `ContravariantType`, but for lifetime parameters. Using
    /// `ContravariantLifetime<'a>` indicates that it is ok to
    /// substitute a *shorter* lifetime for `'a` than the one you
    /// originally started with (e.g., you could convert `'static` to
    /// any lifetime `'foo`). This is appropriate for cases where you
    /// have an unsafe pointer that is actually a pointer into some
    /// memory with lifetime `'a`, and thus you want to limit the
    /// lifetime of your data structure to `'a`. An example of where
    /// this is used is the iterator for vectors.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="contravariant_lifetime"]
    #[deriving(PartialEq,Clone)]
    pub struct ContravariantLifetime<'a>;

    /// As `InvariantType`, but for lifetime parameters. Using
    /// `InvariantLifetime<'a>` indicates that it is not ok to
    /// substitute any other lifetime for `'a` besides its original
    /// value. This is appropriate for cases where you have an unsafe
    /// pointer that is actually a pointer into memory with lifetime `'a`,
    /// and this pointer is itself stored in an inherently mutable
    /// location (such as a `Cell`).
    #[lang="invariant_lifetime"]
    #[deriving(PartialEq,Clone)]
    pub struct InvariantLifetime<'a>;

    /// A type which is considered "not sendable", meaning that it cannot
    /// be safely sent between tasks, even if it is owned. This is
    /// typically embedded in other types, such as `Gc`, to ensure that
    /// their instances remain thread-local.
    #[lang="no_send_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct NoSend;

    /// A type which is considered "not POD", meaning that it is not
    /// implicitly copyable. This is typically embedded in other types to
    /// ensure that they are never copied, even if they lack a destructor.
    #[lang="no_copy_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct NoCopy;

    /// A type which is considered "not shareable", meaning that
    /// its contents are not threadsafe, hence they cannot be
    /// shared between tasks.
    #[lang="no_share_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct NoShare;

    /// A type which is considered managed by the GC. This is typically
    /// embedded in other types.
    #[lang="managed_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct Managed;
}
<commit_msg>Remove references to `~[]` in core::kinds::marker docs.<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

/*!
Primitive traits representing basic 'kinds' of types

Rust types can be classified in various useful ways according to
intrinsic properties of the type. These classifications, often called
'kinds', are represented as traits.

They cannot be implemented by user code, but are instead implemented
by the compiler automatically for the types to which they apply.

*/

/// Types able to be transferred across task boundaries.
#[lang="send"]
pub trait Send {
    // empty.
}

/// Types with a constant size known at compile-time.
#[lang="sized"]
pub trait Sized {
    // Empty.
}

/// Types that can be copied by simply copying bits (i.e. `memcpy`).
#[lang="copy"]
pub trait Copy {
    // Empty.
}

/// Types that can be safely shared between tasks when aliased.
///
/// The precise definition is: a type `T` is `Share` if `&T` is
/// thread-safe. In other words, there is no possibility of data races
/// when passing `&T` references between tasks.
///
/// As one would expect, primitive types like `u8` and `f64` are all
/// `Share`, and so are simple aggregate types containing them (like
/// tuples, structs and enums). More instances of basic `Share` types
/// include "immutable" types like `&T` and those with simple
/// inherited mutability, such as `Box<T>`, `Vec<T>` and most other
/// collection types. (Generic parameters need to be `Share` for their
/// container to be `Share`.)
///
/// A somewhat surprising consequence of the definition is `&mut T` is
/// `Share` (if `T` is `Share`) even though it seems that it might
/// provide unsynchronised mutation. The trick is a mutable reference
/// stored in an aliasable reference (that is, `& &mut T`) becomes
/// read-only, as if it were a `& &T`, hence there is no risk of a data
/// race.
///
/// Types that are not `Share` are those that have "interior
/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell`
/// in `std::cell`. These types allow for mutation of their contents
/// even when in an immutable, aliasable slot, e.g. the contents of
/// `&Cell<T>` can be `.set`, and do not ensure data races are
/// impossible, hence they cannot be `Share`. A higher level example
/// of a non-`Share` type is the reference counted pointer
/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new
/// reference, which modifies the reference counts in a non-atomic
/// way.
///
/// For cases when one does need thread-safe interior mutability,
/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in
/// the `sync` crate do ensure that any mutation cannot cause data
/// races.  Hence these types are `Share`.
///
/// Users writing their own types with interior mutability (or anything
/// else that is not thread-safe) should use the `NoShare` marker type
/// (from `std::kinds::marker`) to ensure that the compiler doesn't
/// consider the user-defined type to be `Share`.  Any types with
/// interior mutability must also use the `std::cell::UnsafeCell` wrapper
/// around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[lang="share"]
pub trait Share {
    // Empty
}

/// Marker types are special types that are used with unsafe code to
/// inform the compiler of special constraints. Marker types should
/// only be needed when you are creating an abstraction that is
/// implemented using unsafe code. In that case, you may want to embed
/// some of the marker types below into your type.
pub mod marker {

    /// A marker type whose type parameter `T` is considered to be
    /// covariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` is being stored
    /// into memory and read from, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a covariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```ignore
    /// use std::mem;
    ///
    /// struct S<T> { x: *() }
    /// fn get<T>(s: &S<T>) -> T {
    ///    unsafe {
    ///        let x: *T = mem::transmute(s.x);
    ///        *x
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `*T` and reads from it. Therefore, we should include the
    /// a marker field `CovariantType<T>` to inform the type checker that
    /// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
    /// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
    /// for some lifetime `'a`, but not the other way around).
    #[lang="covariant_type"]
    #[deriving(PartialEq,Clone)]
    pub struct CovariantType<T>;

    /// A marker type whose type parameter `T` is considered to be
    /// contravariant with respect to the type itself. This is (typically)
    /// used to indicate that an instance of the type `T` will be consumed
    /// (but not read from), even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// *Note:* It is very unusual to have to add a contravariant constraint.
    /// If you are not sure, you probably want to use `InvariantType`.
    ///
    /// # Example
    ///
    /// Given a struct `S` that includes a type parameter `T`
    /// but does not actually *reference* that type parameter:
    ///
    /// ```
    /// use std::mem;
    ///
    /// struct S<T> { x: *const () }
    /// fn get<T>(s: &S<T>, v: T) {
    ///    unsafe {
    ///        let x: fn(T) = mem::transmute(s.x);
    ///        x(v)
    ///    }
    /// }
    /// ```
    ///
    /// The type system would currently infer that the value of
    /// the type parameter `T` is irrelevant, and hence a `S<int>` is
    /// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
    /// any `U`). But this is incorrect because `get()` converts the
    /// `*()` into a `fn(T)` and then passes a value of type `T` to it.
    ///
    /// Supplying a `ContravariantType` marker would correct the
    /// problem, because it would mark `S` so that `S<T>` is only a
    /// subtype of `S<U>` if `U` is a subtype of `T`; given that the
    /// function requires arguments of type `T`, it must also accept
    /// arguments of type `U`, hence such a conversion is safe.
    #[lang="contravariant_type"]
    #[deriving(PartialEq,Clone)]
    pub struct ContravariantType<T>;

    /// A marker type whose type parameter `T` is considered to be
    /// invariant with respect to the type itself. This is (typically)
    /// used to indicate that instances of the type `T` may be read or
    /// written, even though that may not be apparent.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    ///
    /// # Example
    ///
    /// The Cell type is an example which uses unsafe code to achieve
    /// "interior" mutability:
    ///
    /// ```
    /// pub struct Cell<T> { value: T }
    /// # fn main() {}
    /// ```
    ///
    /// The type system would infer that `value` is only read here and
    /// never written, but in fact `Cell` uses unsafe code to achieve
    /// interior mutability.
    #[lang="invariant_type"]
    #[deriving(PartialEq,Clone)]
    pub struct InvariantType<T>;

    /// As `CovariantType`, but for lifetime parameters. Using
    /// `CovariantLifetime<'a>` indicates that it is ok to substitute
    /// a *longer* lifetime for `'a` than the one you originally
    /// started with (e.g., you could convert any lifetime `'foo` to
    /// `'static`). You almost certainly want `ContravariantLifetime`
    /// instead, or possibly `InvariantLifetime`. The only case where
    /// it would be appropriate is that you have a (type-casted, and
    /// hence hidden from the type system) function pointer with a
    /// signature like `fn(&'a T)` (and no other uses of `'a`). In
    /// this case, it is ok to substitute a larger lifetime for `'a`
    /// (e.g., `fn(&'static T)`), because the function is only
    /// becoming more selective in terms of what it accepts as
    /// argument.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="covariant_lifetime"]
    #[deriving(PartialEq,Clone)]
    pub struct CovariantLifetime<'a>;

    /// As `ContravariantType`, but for lifetime parameters. Using
    /// `ContravariantLifetime<'a>` indicates that it is ok to
    /// substitute a *shorter* lifetime for `'a` than the one you
    /// originally started with (e.g., you could convert `'static` to
    /// any lifetime `'foo`). This is appropriate for cases where you
    /// have an unsafe pointer that is actually a pointer into some
    /// memory with lifetime `'a`, and thus you want to limit the
    /// lifetime of your data structure to `'a`. An example of where
    /// this is used is the iterator for vectors.
    ///
    /// For more information about variance, refer to this Wikipedia
    /// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
    #[lang="contravariant_lifetime"]
    #[deriving(PartialEq,Clone)]
    pub struct ContravariantLifetime<'a>;

    /// As `InvariantType`, but for lifetime parameters. Using
    /// `InvariantLifetime<'a>` indicates that it is not ok to
    /// substitute any other lifetime for `'a` besides its original
    /// value. This is appropriate for cases where you have an unsafe
    /// pointer that is actually a pointer into memory with lifetime `'a`,
    /// and this pointer is itself stored in an inherently mutable
    /// location (such as a `Cell`).
    #[lang="invariant_lifetime"]
    #[deriving(PartialEq,Clone)]
    pub struct InvariantLifetime<'a>;

    /// A type which is considered "not sendable", meaning that it cannot
    /// be safely sent between tasks, even if it is owned. This is
    /// typically embedded in other types, such as `Gc`, to ensure that
    /// their instances remain thread-local.
    #[lang="no_send_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct NoSend;

    /// A type which is considered "not POD", meaning that it is not
    /// implicitly copyable. This is typically embedded in other types to
    /// ensure that they are never copied, even if they lack a destructor.
    #[lang="no_copy_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct NoCopy;

    /// A type which is considered "not shareable", meaning that
    /// its contents are not threadsafe, hence they cannot be
    /// shared between tasks.
    #[lang="no_share_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct NoShare;

    /// A type which is considered managed by the GC. This is typically
    /// embedded in other types.
    #[lang="managed_bound"]
    #[deriving(PartialEq,Clone)]
    pub struct Managed;
}
<|endoftext|>