<commit_before>//! Contains structures used for announcing and decoding the Encoding
//! Scheme, as defined in https://github.com/cjdelisle/cjdns/blob/cjdns-v18/doc/Whitepaper.md#encoding-schemes
//!
//! EncodingScheme can be constructed either from bytes (ie. from the network)
//! or from an interator on `EncodingSchemeForm`.
//! Its content can be accessed either by writing it to bytes (ie. to the
//! network) or by turning it `into_iter`ator of `EncodingSchemeForm`.

use std::iter::FromIterator;

/// An item of the Encoding Scheme.
/// See https://github.com/cjdelisle/cjdns/blob/cjdns-v18/doc/Whitepaper.md#definitions
/// for its definition.
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct EncodingSchemeForm {
    pub prefix: u64,
    pub bit_count: u8,
    pub prefix_length: u8,
}

/// A list of `EncodingSchemeForm`. Can be serialized to/deserialized from
/// bytes, and constructed from/read to an iterator of `EncodingSchemeForm`.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct EncodingScheme {
    bytes: Vec<u8>,
}

impl EncodingScheme {
    pub fn new(bytes: Vec<u8>) -> EncodingScheme {
        EncodingScheme { bytes: bytes }
    }

    pub fn bytes(&self) -> &Vec<u8> {
        &self.bytes
    }

    pub fn into_bytes(self) -> Vec<u8> {
        self.bytes
    }
}

impl IntoIterator for EncodingScheme {
    type Item = EncodingSchemeForm;
    type IntoIter = EncodingSchemeIterator;

    fn into_iter(self) -> EncodingSchemeIterator {
        EncodingSchemeIterator { bytes: self.bytes, window: 0, bits_in_window: 0, bytes_offset: 0 }
    }
}

/// Iterator of `EncodingSchemeForm`, constructed from an instance of
/// `EncodingScheme`
#[derive(Debug)]
pub struct EncodingSchemeIterator {
    bytes: Vec<u8>,
    window: u64, // integer view of a slice of the buffer (in little endian)
    bits_in_window: u8,
    bytes_offset: usize,
}

impl Iterator for EncodingSchemeIterator {
    type Item = EncodingSchemeForm;

    fn next(&mut self) -> Option<EncodingSchemeForm> {
        // Load new bytes in the window, so it is larger than any possible form
        while self.bits_in_window < 5+5+0b11111 {
            let byte = *self.bytes.get(self.bytes_offset).unwrap_or(&0);
            self.window = self.window + ((byte as u64) << self.bits_in_window);
            self.bytes_offset += 1;
            self.bits_in_window += 8;
        }

        if self.window == 0 {
            None
        }
        else {
            assert!(self.bytes_offset <= self.bytes.len()+(5+5+0b11111)/8);
            let prefix_length = self.window as u8 & 0b11111;
            self.window >>= 5;
            self.bits_in_window -= 5;

            let bit_count = self.window as u8 & 0b11111;
            self.window >>= 5;
            self.bits_in_window -= 5;

            let prefix_mask = (0b1 << prefix_length) -1; // mask for the prefix_length last digits
            let prefix = self.window & prefix_mask;
            self.window >>= prefix_length;
            self.bits_in_window -= prefix_length;

            Some(EncodingSchemeForm { prefix: prefix, bit_count: bit_count, prefix_length: prefix_length })
        }
    }
}

impl<'a> FromIterator<&'a EncodingSchemeForm> for EncodingScheme {
    fn from_iter<T: IntoIterator<Item=&'a EncodingSchemeForm>>(forms: T) -> Self {
        let mut bytes = Vec::<u8>::new();
        let mut window = 0u64;
        let mut bits_in_window = 0u8;
        println!("---");
        for form in forms {
            assert!(form.prefix_length <= 0b11111);
            assert!(form.bit_count <= 0b11111);
            assert!(form.prefix < (1 << form.prefix_length));

            window += (form.prefix as u64) << (5+5+bits_in_window);
            window += (form.bit_count as u64) << (5+bits_in_window);
            window += (form.prefix_length as u64) << (bits_in_window);

            bits_in_window += 5+5+form.prefix_length;

            while bits_in_window >= 8 {
                bytes.push((window & 0b11111111) as u8);
                window >>= 8;
                bits_in_window -= 8;
            }
        }

        if bits_in_window > 0 {
            assert!(bits_in_window < 8);
            assert!(window <= 0b11111111);
            bytes.push(window as u8);
        }

        EncodingScheme::new(bytes)
    }
}

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

    #[test]
    fn test_trivial() {
        let encoding = vec![0b011_00000, 0b00];
        let forms = vec![EncodingSchemeForm { prefix: 0, bit_count: 3, prefix_length: 0 }];

        assert_eq!(EncodingScheme::new(encoding.clone()).into_bytes(), encoding);
        assert_eq!(EncodingScheme::from_iter(forms.iter()).into_bytes(), encoding);
        assert_eq!(EncodingScheme::new(encoding.clone()).into_iter().collect::<Vec<_>>(), forms);
        assert_eq!(EncodingScheme::from_iter(forms.iter()).into_iter().collect::<Vec<_>>(), forms);
    }

    /// From https://github.com/cjdelisle/cjdns/blob/cjdns-v18/switch/test/EncodingScheme_test.c#L121-L158
    #[test]
    fn test_three() {
        let encoding = b"\x4f\xf4\xff\x29\xd9\xff\x7f\x89\xee\xff\x07".to_vec();
        let forms = vec![
            EncodingSchemeForm {
                prefix_length: 15,
                bit_count: 2,
                prefix: ((1<<15)-1) ^ (1<<1),
            },
            EncodingSchemeForm {
                prefix_length: 20,
                bit_count: 4,
                prefix: ((1<<20)-1) ^ (1<<2),
            },
            EncodingSchemeForm {
                prefix_length: 18,
                bit_count: 8,
                prefix: ((1<<18)-1) ^ (1<<3),
            }
        ];

        assert_eq!(EncodingScheme::new(encoding.clone()).into_bytes(), encoding);
        assert_eq!(EncodingScheme::from_iter(forms.iter()).into_bytes(), encoding);
        assert_eq!(EncodingScheme::new(encoding.clone()).into_iter().collect::<Vec<_>>(), forms);
        assert_eq!(EncodingScheme::from_iter(forms.iter()).into_iter().collect::<Vec<_>>(), forms);
    }
}
<commit_msg>Remove debug print.<commit_after>//! Contains structures used for announcing and decoding the Encoding
//! Scheme, as defined in https://github.com/cjdelisle/cjdns/blob/cjdns-v18/doc/Whitepaper.md#encoding-schemes
//!
//! EncodingScheme can be constructed either from bytes (ie. from the network)
//! or from an interator on `EncodingSchemeForm`.
//! Its content can be accessed either by writing it to bytes (ie. to the
//! network) or by turning it `into_iter`ator of `EncodingSchemeForm`.

use std::iter::FromIterator;

/// An item of the Encoding Scheme.
/// See https://github.com/cjdelisle/cjdns/blob/cjdns-v18/doc/Whitepaper.md#definitions
/// for its definition.
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct EncodingSchemeForm {
    pub prefix: u64,
    pub bit_count: u8,
    pub prefix_length: u8,
}

/// A list of `EncodingSchemeForm`. Can be serialized to/deserialized from
/// bytes, and constructed from/read to an iterator of `EncodingSchemeForm`.
#[derive(Clone, Eq, PartialEq, Debug)]
pub struct EncodingScheme {
    bytes: Vec<u8>,
}

impl EncodingScheme {
    pub fn new(bytes: Vec<u8>) -> EncodingScheme {
        EncodingScheme { bytes: bytes }
    }

    pub fn bytes(&self) -> &Vec<u8> {
        &self.bytes
    }

    pub fn into_bytes(self) -> Vec<u8> {
        self.bytes
    }
}

impl IntoIterator for EncodingScheme {
    type Item = EncodingSchemeForm;
    type IntoIter = EncodingSchemeIterator;

    fn into_iter(self) -> EncodingSchemeIterator {
        EncodingSchemeIterator { bytes: self.bytes, window: 0, bits_in_window: 0, bytes_offset: 0 }
    }
}

/// Iterator of `EncodingSchemeForm`, constructed from an instance of
/// `EncodingScheme`
#[derive(Debug)]
pub struct EncodingSchemeIterator {
    bytes: Vec<u8>,
    window: u64, // integer view of a slice of the buffer (in little endian)
    bits_in_window: u8,
    bytes_offset: usize,
}

impl Iterator for EncodingSchemeIterator {
    type Item = EncodingSchemeForm;

    fn next(&mut self) -> Option<EncodingSchemeForm> {
        // Load new bytes in the window, so it is larger than any possible form
        while self.bits_in_window < 5+5+0b11111 {
            let byte = *self.bytes.get(self.bytes_offset).unwrap_or(&0);
            self.window = self.window + ((byte as u64) << self.bits_in_window);
            self.bytes_offset += 1;
            self.bits_in_window += 8;
        }

        if self.window == 0 {
            None
        }
        else {
            assert!(self.bytes_offset <= self.bytes.len()+(5+5+0b11111)/8);
            let prefix_length = self.window as u8 & 0b11111;
            self.window >>= 5;
            self.bits_in_window -= 5;

            let bit_count = self.window as u8 & 0b11111;
            self.window >>= 5;
            self.bits_in_window -= 5;

            let prefix_mask = (0b1 << prefix_length) -1; // mask for the prefix_length last digits
            let prefix = self.window & prefix_mask;
            self.window >>= prefix_length;
            self.bits_in_window -= prefix_length;

            Some(EncodingSchemeForm { prefix: prefix, bit_count: bit_count, prefix_length: prefix_length })
        }
    }
}

impl<'a> FromIterator<&'a EncodingSchemeForm> for EncodingScheme {
    fn from_iter<T: IntoIterator<Item=&'a EncodingSchemeForm>>(forms: T) -> Self {
        let mut bytes = Vec::<u8>::new();
        let mut window = 0u64;
        let mut bits_in_window = 0u8;
        for form in forms {
            assert!(form.prefix_length <= 0b11111);
            assert!(form.bit_count <= 0b11111);
            assert!(form.prefix < (1 << form.prefix_length));

            window += (form.prefix as u64) << (5+5+bits_in_window);
            window += (form.bit_count as u64) << (5+bits_in_window);
            window += (form.prefix_length as u64) << (bits_in_window);

            bits_in_window += 5+5+form.prefix_length;

            while bits_in_window >= 8 {
                bytes.push((window & 0b11111111) as u8);
                window >>= 8;
                bits_in_window -= 8;
            }
        }

        if bits_in_window > 0 {
            assert!(bits_in_window < 8);
            assert!(window <= 0b11111111);
            bytes.push(window as u8);
        }

        EncodingScheme::new(bytes)
    }
}

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

    #[test]
    fn test_trivial() {
        let encoding = vec![0b011_00000, 0b00];
        let forms = vec![EncodingSchemeForm { prefix: 0, bit_count: 3, prefix_length: 0 }];

        assert_eq!(EncodingScheme::new(encoding.clone()).into_bytes(), encoding);
        assert_eq!(EncodingScheme::from_iter(forms.iter()).into_bytes(), encoding);
        assert_eq!(EncodingScheme::new(encoding.clone()).into_iter().collect::<Vec<_>>(), forms);
        assert_eq!(EncodingScheme::from_iter(forms.iter()).into_iter().collect::<Vec<_>>(), forms);
    }

    /// From https://github.com/cjdelisle/cjdns/blob/cjdns-v18/switch/test/EncodingScheme_test.c#L121-L158
    #[test]
    fn test_three() {
        let encoding = b"\x4f\xf4\xff\x29\xd9\xff\x7f\x89\xee\xff\x07".to_vec();
        let forms = vec![
            EncodingSchemeForm {
                prefix_length: 15,
                bit_count: 2,
                prefix: ((1<<15)-1) ^ (1<<1),
            },
            EncodingSchemeForm {
                prefix_length: 20,
                bit_count: 4,
                prefix: ((1<<20)-1) ^ (1<<2),
            },
            EncodingSchemeForm {
                prefix_length: 18,
                bit_count: 8,
                prefix: ((1<<18)-1) ^ (1<<3),
            }
        ];

        assert_eq!(EncodingScheme::new(encoding.clone()).into_bytes(), encoding);
        assert_eq!(EncodingScheme::from_iter(forms.iter()).into_bytes(), encoding);
        assert_eq!(EncodingScheme::new(encoding.clone()).into_iter().collect::<Vec<_>>(), forms);
        assert_eq!(EncodingScheme::from_iter(forms.iter()).into_iter().collect::<Vec<_>>(), forms);
    }
}
<|endoftext|>


<commit_before>extern crate document;

use document::Nodeset;

use super::XPathEvaluationContext;
use super::XPathNodeTest;
use super::XPathValue;
use super::{Boolean,Number,Nodes};

use super::axis::XPathAxis;

pub trait XPathExpression {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue;
}

pub type SubExpression = Box<XPathExpression + 'static>;

pub struct ExpressionAnd {
    pub left:  SubExpression,
    pub right: SubExpression,
}

impl XPathExpression for ExpressionAnd {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        Boolean(self.left.evaluate(context).boolean() &&
                self.right.evaluate(context).boolean())
    }
}

pub struct ExpressionContextNode;

impl XPathExpression for ExpressionContextNode {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let mut result = Nodeset::new();
        result.add(context.node().clone());
        Nodes(result.clone())
    }
}

pub struct ExpressionEqual {
    pub left:  SubExpression,
    pub right: SubExpression,
}

impl ExpressionEqual {
    fn boolean_evaluate(& self, context: &XPathEvaluationContext) -> bool {
        let left_val = self.left.evaluate(context);
        let right_val = self.right.evaluate(context);

        match (&left_val, &right_val) {
            (&Boolean(_), _) |
            (_, &Boolean(_)) => left_val.boolean() == right_val.boolean(),
            (&Number(_), _) |
            (_, &Number(_)) => left_val.number() == right_val.number(),
            _ => left_val.string() == right_val.string()
        }
    }
}

impl XPathExpression for ExpressionEqual {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        Boolean(self.boolean_evaluate(context))
    }
}

pub struct ExpressionNotEqual {
    equal: ExpressionEqual,
}

impl ExpressionNotEqual {
    pub fn new(left: SubExpression, right: SubExpression) -> ExpressionNotEqual {
        ExpressionNotEqual {
            equal: ExpressionEqual{left: left, right: right}
        }
    }
}

impl XPathExpression for ExpressionNotEqual {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        Boolean(!self.equal.boolean_evaluate(context))
    }
}

pub struct ExpressionFunction {
    pub name: String,
    pub arguments: Vec<SubExpression>,
}

impl XPathExpression for ExpressionFunction {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        match context.function_for_name(self.name.as_slice()) {
            Some(fun) => {
                // TODO: Error when argument count mismatch
                let args = self.arguments.iter().map(|ref arg| arg.evaluate(context)).collect();

                fun.evaluate(context, args)
            },
            None => fail!("throw UnknownXPathFunctionException(_name)"),
        }
    }
}

pub struct ExpressionLiteral {
    pub value: XPathValue,
}

impl XPathExpression for ExpressionLiteral {
    fn evaluate(& self, _: &XPathEvaluationContext) -> XPathValue {
        self.value.clone()
    }
}

pub struct ExpressionMath {
    left:  SubExpression,
    right: SubExpression,
    operation: fn(f64, f64) -> f64,
}

fn      add(a: f64, b: f64) -> f64 {a + b}
fn subtract(a: f64, b: f64) -> f64 {a - b}
fn multiply(a: f64, b: f64) -> f64 {a * b}
fn   divide(a: f64, b: f64) -> f64 {a / b}
fn  modulus(a: f64, b: f64) -> f64 {a % b}

impl ExpressionMath {
    pub fn addition(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: add}
    }

    pub fn subtraction(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: subtract}
    }

    pub fn multiplication(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: multiply}
    }

    pub fn division(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: divide}
    }

    pub fn remainder(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: modulus}
    }
}

impl XPathExpression for ExpressionMath {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        let left = self.left.evaluate(context);
        let right = self.right.evaluate(context);
        let op = self.operation;
        return Number(op(left.number(), right.number()));
    }
}

pub struct ExpressionNegation {
    expression: SubExpression,
}

impl XPathExpression for ExpressionNegation {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        let result = self.expression.evaluate(context);
        return Number(-result.number());
    }
}

pub struct ExpressionOr {
    left:  SubExpression,
    right: SubExpression,
}

impl XPathExpression for ExpressionOr {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        return Boolean(self.left.evaluate(context).boolean() ||
                       self.right.evaluate(context).boolean())
    }
}

pub struct ExpressionPath {
    start_point: SubExpression,
    steps: Vec<SubExpression>,
}

impl XPathExpression for ExpressionPath {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        let mut result = self.start_point.evaluate(context).nodeset();

        for step in self.steps.iter() {
            let mut step_result = Nodeset::new();

            let mut sub_context = context.new_context_for(result.size());

            for current_node in result.iter() {
                sub_context.next(current_node.clone());
                let selected = step.evaluate(&sub_context);
                // TODO: What if it is not a nodeset?
                step_result.add_nodeset(&selected.nodeset());
            }

            result = step_result;
        }

        Nodes(result)
    }
}

pub struct ExpressionPredicate {
    pub node_selector: SubExpression,
    pub predicate: SubExpression,
}

impl ExpressionPredicate {
    fn include(value: &XPathValue, context: &XPathEvaluationContext) -> bool {
        match value {
            &Number(v) => context.position() == v as uint,
            _ => value.boolean()
        }
    }
}

impl XPathExpression for ExpressionPredicate {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let mut selected = Nodeset::new();

        let nodes = self.node_selector.evaluate(context).nodeset();

        let mut sub_context = context.new_context_for(nodes.size());

        for current_node in nodes.iter() {
            sub_context.next(current_node.clone());

            let value = self.predicate.evaluate(&sub_context);

            if ExpressionPredicate::include(&value, &sub_context) {
                selected.add(current_node.clone());
            }
        }

        Nodes(selected)
    }
}

pub struct ExpressionRelational {
    pub  left: SubExpression,
    pub right: SubExpression,
    pub operation: fn(f64, f64) -> bool,
}

fn             less_than(left: f64, right: f64) -> bool { left <  right }
fn    less_than_or_equal(left: f64, right: f64) -> bool { left <= right }
fn          greater_than(left: f64, right: f64) -> bool { left >  right }
fn greater_than_or_equal(left: f64, right: f64) -> bool { left >= right }

impl ExpressionRelational {
    pub fn less_than(left: SubExpression, right: SubExpression) -> ExpressionRelational
    {
        ExpressionRelational{left: left, right: right, operation: less_than}
    }

    pub fn less_than_or_equal(left: SubExpression, right: SubExpression) -> ExpressionRelational
    {
        ExpressionRelational{left: left, right: right, operation: less_than_or_equal}
    }

    pub fn greater_than(left: SubExpression, right: SubExpression) -> ExpressionRelational
    {
        ExpressionRelational{left: left, right: right, operation: greater_than}
    }

    pub fn greater_than_or_equal(left: SubExpression, right: SubExpression) -> ExpressionRelational
    {
        ExpressionRelational{left: left, right: right, operation: greater_than_or_equal}
    }
}

impl XPathExpression for ExpressionRelational {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let left_val = self.left.evaluate(context);
        let right_val = self.right.evaluate(context);
        let op = self.operation;
        Boolean(op(left_val.number(), right_val.number()))
    }
}

pub struct ExpressionRootNode;

impl XPathExpression for ExpressionRootNode {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let n = &context.node;

        let mut result = Nodeset::new();
        result.add(n.document().root());
        Nodes(result)
    }
}

pub type StepAxis = Box<XPathAxis + 'static>;
pub type StepTest = Box<XPathNodeTest + 'static>;

pub struct ExpressionStep {
    axis: StepAxis,
    node_test: StepTest,
}

impl ExpressionStep {
    pub fn new(axis: StepAxis, node_test: StepTest) -> ExpressionStep {
        ExpressionStep {axis: axis, node_test: node_test}
    }
}

impl XPathExpression for ExpressionStep {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let mut result = Nodeset::new();
        self.axis.select_nodes(context, self.node_test, & mut result);
        Nodes(result)
    }
}

pub struct ExpressionUnion {
    pub left:  SubExpression,
    pub right: SubExpression,
}

impl XPathExpression for ExpressionUnion {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let mut left_val = self.left.evaluate(context).nodeset();
        let right_val = self.right.evaluate(context).nodeset();
        left_val.add_nodeset(&right_val);
        Nodes(left_val)
    }
}

pub struct ExpressionVariable {
    pub name: String,
}

impl XPathExpression for ExpressionVariable {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        match context.value_of(self.name.as_slice()) {
            Some(v) => v.clone(),
            None => fail!("throw UnknownVariableException(_name)"),
        }
    }
}
<commit_msg>Add a constructor for ExpressionEqual<commit_after>extern crate document;

use document::Nodeset;

use super::XPathEvaluationContext;
use super::XPathNodeTest;
use super::XPathValue;
use super::{Boolean,Number,Nodes};

use super::axis::XPathAxis;

pub trait XPathExpression {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue;
}

pub type SubExpression = Box<XPathExpression + 'static>;

pub struct ExpressionAnd {
    pub left:  SubExpression,
    pub right: SubExpression,
}

impl XPathExpression for ExpressionAnd {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        Boolean(self.left.evaluate(context).boolean() &&
                self.right.evaluate(context).boolean())
    }
}

pub struct ExpressionContextNode;

impl XPathExpression for ExpressionContextNode {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let mut result = Nodeset::new();
        result.add(context.node().clone());
        Nodes(result.clone())
    }
}

pub struct ExpressionEqual {
    pub left:  SubExpression,
    pub right: SubExpression,
}

impl ExpressionEqual {
    pub fn new(left: SubExpression, right: SubExpression) -> SubExpression {
        box ExpressionEqual{left: left, right: right} as SubExpression
    }

    fn boolean_evaluate(& self, context: &XPathEvaluationContext) -> bool {
        let left_val = self.left.evaluate(context);
        let right_val = self.right.evaluate(context);

        match (&left_val, &right_val) {
            (&Boolean(_), _) |
            (_, &Boolean(_)) => left_val.boolean() == right_val.boolean(),
            (&Number(_), _) |
            (_, &Number(_)) => left_val.number() == right_val.number(),
            _ => left_val.string() == right_val.string()
        }
    }
}

impl XPathExpression for ExpressionEqual {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        Boolean(self.boolean_evaluate(context))
    }
}

pub struct ExpressionNotEqual {
    equal: ExpressionEqual,
}

impl ExpressionNotEqual {
    pub fn new(left: SubExpression, right: SubExpression) -> ExpressionNotEqual {
        ExpressionNotEqual {
            equal: ExpressionEqual{left: left, right: right}
        }
    }
}

impl XPathExpression for ExpressionNotEqual {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        Boolean(!self.equal.boolean_evaluate(context))
    }
}

pub struct ExpressionFunction {
    pub name: String,
    pub arguments: Vec<SubExpression>,
}

impl XPathExpression for ExpressionFunction {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        match context.function_for_name(self.name.as_slice()) {
            Some(fun) => {
                // TODO: Error when argument count mismatch
                let args = self.arguments.iter().map(|ref arg| arg.evaluate(context)).collect();

                fun.evaluate(context, args)
            },
            None => fail!("throw UnknownXPathFunctionException(_name)"),
        }
    }
}

pub struct ExpressionLiteral {
    pub value: XPathValue,
}

impl XPathExpression for ExpressionLiteral {
    fn evaluate(& self, _: &XPathEvaluationContext) -> XPathValue {
        self.value.clone()
    }
}

pub struct ExpressionMath {
    left:  SubExpression,
    right: SubExpression,
    operation: fn(f64, f64) -> f64,
}

fn      add(a: f64, b: f64) -> f64 {a + b}
fn subtract(a: f64, b: f64) -> f64 {a - b}
fn multiply(a: f64, b: f64) -> f64 {a * b}
fn   divide(a: f64, b: f64) -> f64 {a / b}
fn  modulus(a: f64, b: f64) -> f64 {a % b}

impl ExpressionMath {
    pub fn addition(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: add}
    }

    pub fn subtraction(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: subtract}
    }

    pub fn multiplication(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: multiply}
    }

    pub fn division(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: divide}
    }

    pub fn remainder(left: SubExpression, right: SubExpression) -> ExpressionMath {
        ExpressionMath{left: left, right: right, operation: modulus}
    }
}

impl XPathExpression for ExpressionMath {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        let left = self.left.evaluate(context);
        let right = self.right.evaluate(context);
        let op = self.operation;
        return Number(op(left.number(), right.number()));
    }
}

pub struct ExpressionNegation {
    expression: SubExpression,
}

impl XPathExpression for ExpressionNegation {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        let result = self.expression.evaluate(context);
        return Number(-result.number());
    }
}

pub struct ExpressionOr {
    left:  SubExpression,
    right: SubExpression,
}

impl XPathExpression for ExpressionOr {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        return Boolean(self.left.evaluate(context).boolean() ||
                       self.right.evaluate(context).boolean())
    }
}

pub struct ExpressionPath {
    start_point: SubExpression,
    steps: Vec<SubExpression>,
}

impl XPathExpression for ExpressionPath {
    fn evaluate(& self, context: &XPathEvaluationContext) -> XPathValue {
        let mut result = self.start_point.evaluate(context).nodeset();

        for step in self.steps.iter() {
            let mut step_result = Nodeset::new();

            let mut sub_context = context.new_context_for(result.size());

            for current_node in result.iter() {
                sub_context.next(current_node.clone());
                let selected = step.evaluate(&sub_context);
                // TODO: What if it is not a nodeset?
                step_result.add_nodeset(&selected.nodeset());
            }

            result = step_result;
        }

        Nodes(result)
    }
}

pub struct ExpressionPredicate {
    pub node_selector: SubExpression,
    pub predicate: SubExpression,
}

impl ExpressionPredicate {
    fn include(value: &XPathValue, context: &XPathEvaluationContext) -> bool {
        match value {
            &Number(v) => context.position() == v as uint,
            _ => value.boolean()
        }
    }
}

impl XPathExpression for ExpressionPredicate {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let mut selected = Nodeset::new();

        let nodes = self.node_selector.evaluate(context).nodeset();

        let mut sub_context = context.new_context_for(nodes.size());

        for current_node in nodes.iter() {
            sub_context.next(current_node.clone());

            let value = self.predicate.evaluate(&sub_context);

            if ExpressionPredicate::include(&value, &sub_context) {
                selected.add(current_node.clone());
            }
        }

        Nodes(selected)
    }
}

pub struct ExpressionRelational {
    pub  left: SubExpression,
    pub right: SubExpression,
    pub operation: fn(f64, f64) -> bool,
}

fn             less_than(left: f64, right: f64) -> bool { left <  right }
fn    less_than_or_equal(left: f64, right: f64) -> bool { left <= right }
fn          greater_than(left: f64, right: f64) -> bool { left >  right }
fn greater_than_or_equal(left: f64, right: f64) -> bool { left >= right }

impl ExpressionRelational {
    pub fn less_than(left: SubExpression, right: SubExpression) -> ExpressionRelational
    {
        ExpressionRelational{left: left, right: right, operation: less_than}
    }

    pub fn less_than_or_equal(left: SubExpression, right: SubExpression) -> ExpressionRelational
    {
        ExpressionRelational{left: left, right: right, operation: less_than_or_equal}
    }

    pub fn greater_than(left: SubExpression, right: SubExpression) -> ExpressionRelational
    {
        ExpressionRelational{left: left, right: right, operation: greater_than}
    }

    pub fn greater_than_or_equal(left: SubExpression, right: SubExpression) -> ExpressionRelational
    {
        ExpressionRelational{left: left, right: right, operation: greater_than_or_equal}
    }
}

impl XPathExpression for ExpressionRelational {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let left_val = self.left.evaluate(context);
        let right_val = self.right.evaluate(context);
        let op = self.operation;
        Boolean(op(left_val.number(), right_val.number()))
    }
}

pub struct ExpressionRootNode;

impl XPathExpression for ExpressionRootNode {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let n = &context.node;

        let mut result = Nodeset::new();
        result.add(n.document().root());
        Nodes(result)
    }
}

pub type StepAxis = Box<XPathAxis + 'static>;
pub type StepTest = Box<XPathNodeTest + 'static>;

pub struct ExpressionStep {
    axis: StepAxis,
    node_test: StepTest,
}

impl ExpressionStep {
    pub fn new(axis: StepAxis, node_test: StepTest) -> ExpressionStep {
        ExpressionStep {axis: axis, node_test: node_test}
    }
}

impl XPathExpression for ExpressionStep {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let mut result = Nodeset::new();
        self.axis.select_nodes(context, self.node_test, & mut result);
        Nodes(result)
    }
}

pub struct ExpressionUnion {
    pub left:  SubExpression,
    pub right: SubExpression,
}

impl XPathExpression for ExpressionUnion {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        let mut left_val = self.left.evaluate(context).nodeset();
        let right_val = self.right.evaluate(context).nodeset();
        left_val.add_nodeset(&right_val);
        Nodes(left_val)
    }
}

pub struct ExpressionVariable {
    pub name: String,
}

impl XPathExpression for ExpressionVariable {
    fn evaluate(&self, context: &XPathEvaluationContext) -> XPathValue {
        match context.value_of(self.name.as_slice()) {
            Some(v) => v.clone(),
            None => fail!("throw UnknownVariableException(_name)"),
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, BTreeSet};
use std::env;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::path::{Path, PathBuf};

use semver::VersionReq;
use serde::{Deserialize, Serialize};

use crate::core::package::PackageSet;
use crate::core::source::SourceMap;
use crate::core::PackageId;
use crate::core::{Dependency, Package, Source, SourceId};
use crate::sources::PathSource;
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::{internal, Config, ToSemver};
use crate::util::{FileLock, Filesystem};

#[derive(Deserialize, Serialize)]
#[serde(untagged)]
pub enum CrateListing {
    V1(CrateListingV1),
    Empty(Empty),
}

#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Empty {}

#[derive(Deserialize, Serialize)]
pub struct CrateListingV1 {
    v1: BTreeMap<PackageId, BTreeSet<String>>,
}

pub fn resolve_root(flag: Option<&str>, config: &Config) -> CargoResult<Filesystem> {
    let config_root = config.get_path("install.root")?;
    Ok(flag
        .map(PathBuf::from)
        .or_else(|| env::var_os("CARGO_INSTALL_ROOT").map(PathBuf::from))
        .or_else(move || config_root.map(|v| v.val))
        .map(Filesystem::new)
        .unwrap_or_else(|| config.home().clone()))
}

pub fn path_source<'a>(source_id: SourceId, config: &'a Config) -> CargoResult<PathSource<'a>> {
    let path = source_id
        .url()
        .to_file_path()
        .map_err(|()| failure::format_err!("path sources must have a valid path"))?;
    Ok(PathSource::new(&path, source_id, config))
}

pub fn select_pkg<'a, T>(
    mut source: T,
    name: Option<&str>,
    vers: Option<&str>,
    config: &Config,
    needs_update: bool,
    list_all: &mut dyn FnMut(&mut T) -> CargoResult<Vec<Package>>,
) -> CargoResult<(Package, Box<dyn Source + 'a>)>
where
    T: Source + 'a,
{
    if needs_update {
        source.update()?;
    }

    match name {
        Some(name) => {
            let vers = match vers {
                Some(v) => {
                    // If the version begins with character <, >, =, ^, ~ parse it as a
                    // version range, otherwise parse it as a specific version
                    let first = v.chars().nth(0).ok_or_else(|| {
                        failure::format_err!("no version provided for the `--vers` flag")
                    })?;

                    match first {
                        '<' | '>' | '=' | '^' | '~' => match v.parse::<VersionReq>() {
                            Ok(v) => Some(v.to_string()),
                            Err(_) => failure::bail!(
                                "the `--vers` provided, `{}`, is \
                                       not a valid semver version requirement\n\n
                                       Please have a look at \
                                       http://doc.crates.io/specifying-dependencies.html \
                                       for the correct format",
                                v
                            ),
                        },
                        _ => match v.to_semver() {
                            Ok(v) => Some(format!("={}", v)),
                            Err(_) => {
                                let mut msg = format!(
                                    "\
                                     the `--vers` provided, `{}`, is \
                                     not a valid semver version\n\n\
                                     historically Cargo treated this \
                                     as a semver version requirement \
                                     accidentally\nand will continue \
                                     to do so, but this behavior \
                                     will be removed eventually",
                                    v
                                );

                                // If it is not a valid version but it is a valid version
                                // requirement, add a note to the warning
                                if v.parse::<VersionReq>().is_ok() {
                                    msg.push_str(&format!(
                                        "\nif you want to specify semver range, \
                                         add an explicit qualifier, like ^{}",
                                        v
                                    ));
                                }
                                config.shell().warn(&msg)?;
                                Some(v.to_string())
                            }
                        },
                    }
                }
                None => None,
            };
            let vers = vers.as_ref().map(|s| &**s);
            let vers_spec = if vers.is_none() && source.source_id().is_registry() {
                // Avoid pre-release versions from crate.io
                // unless explicitly asked for
                Some("*")
            } else {
                vers
            };
            let dep = Dependency::parse_no_deprecated(name, vers_spec, source.source_id())?;
            let deps = source.query_vec(&dep)?;
            let pkgid = match deps.iter().map(|p| p.package_id()).max() {
                Some(pkgid) => pkgid,
                None => {
                    let vers_info = vers
                        .map(|v| format!(" with version `{}`", v))
                        .unwrap_or_default();
                    failure::bail!(
                        "could not find `{}` in {}{}",
                        name,
                        source.source_id(),
                        vers_info
                    )
                }
            };

            let pkg = {
                let mut map = SourceMap::new();
                map.insert(Box::new(&mut source));
                PackageSet::new(&[pkgid], map, config)?
                    .get_one(pkgid)?
                    .clone()
            };
            Ok((pkg, Box::new(source)))
        }
        None => {
            let candidates = list_all(&mut source)?;
            let binaries = candidates
                .iter()
                .filter(|cand| cand.targets().iter().filter(|t| t.is_bin()).count() > 0);
            let examples = candidates
                .iter()
                .filter(|cand| cand.targets().iter().filter(|t| t.is_example()).count() > 0);
            let pkg = match one(binaries, |v| multi_err("binaries", v))? {
                Some(p) => p,
                None => match one(examples, |v| multi_err("examples", v))? {
                    Some(p) => p,
                    None => failure::bail!(
                        "no packages found with binaries or \
                         examples"
                    ),
                },
            };
            return Ok((pkg.clone(), Box::new(source)));

            fn multi_err(kind: &str, mut pkgs: Vec<&Package>) -> String {
                pkgs.sort_unstable_by_key(|a| a.name());
                format!(
                    "multiple packages with {} found: {}",
                    kind,
                    pkgs.iter()
                        .map(|p| p.name().as_str())
                        .collect::<Vec<_>>()
                        .join(", ")
                )
            }
        }
    }
}

pub fn one<I, F>(mut i: I, f: F) -> CargoResult<Option<I::Item>>
where
    I: Iterator,
    F: FnOnce(Vec<I::Item>) -> String,
{
    match (i.next(), i.next()) {
        (Some(i1), Some(i2)) => {
            let mut v = vec![i1, i2];
            v.extend(i);
            Err(failure::format_err!("{}", f(v)))
        }
        (Some(i), None) => Ok(Some(i)),
        (None, _) => Ok(None),
    }
}

pub fn read_crate_list(file: &FileLock) -> CargoResult<CrateListingV1> {
    let listing = (|| -> CargoResult<_> {
        let mut contents = String::new();
        file.file().read_to_string(&mut contents)?;
        let listing =
            toml::from_str(&contents).chain_err(|| internal("invalid TOML found for metadata"))?;
        match listing {
            CrateListing::V1(v1) => Ok(v1),
            CrateListing::Empty(_) => Ok(CrateListingV1 {
                v1: BTreeMap::new(),
            }),
        }
    })()
    .chain_err(|| {
        failure::format_err!(
            "failed to parse crate metadata at `{}`",
            file.path().to_string_lossy()
        )
    })?;
    Ok(listing)
}

pub fn write_crate_list(file: &FileLock, listing: CrateListingV1) -> CargoResult<()> {
    (|| -> CargoResult<_> {
        let mut file = file.file();
        file.seek(SeekFrom::Start(0))?;
        file.set_len(0)?;
        let data = toml::to_string(&CrateListing::V1(listing))?;
        file.write_all(data.as_bytes())?;
        Ok(())
    })()
    .chain_err(|| {
        failure::format_err!(
            "failed to write crate metadata at `{}`",
            file.path().to_string_lossy()
        )
    })?;
    Ok(())
}

pub fn metadata(config: &Config, root: &Filesystem) -> CargoResult<FileLock> {
    root.open_rw(Path::new(".crates.toml"), config, "crate metadata")
}
<commit_msg>feat: Add v1 field getter<commit_after>use std::collections::{BTreeMap, BTreeSet};
use std::env;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::path::{Path, PathBuf};

use semver::VersionReq;
use serde::{Deserialize, Serialize};

use crate::core::package::PackageSet;
use crate::core::source::SourceMap;
use crate::core::PackageId;
use crate::core::{Dependency, Package, Source, SourceId};
use crate::sources::PathSource;
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::{internal, Config, ToSemver};
use crate::util::{FileLock, Filesystem};

#[derive(Deserialize, Serialize)]
#[serde(untagged)]
pub enum CrateListing {
    V1(CrateListingV1),
    Empty(Empty),
}

#[derive(Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct Empty {}

#[derive(Deserialize, Serialize)]
pub struct CrateListingV1 {
    v1: BTreeMap<PackageId, BTreeSet<String>>,
}

impl CrateListingV1 {
    pub fn v1(&self) -> &BTreeMap<PackageId, BTreeSet<String>> {
        &self.v1
    }
}

pub fn resolve_root(flag: Option<&str>, config: &Config) -> CargoResult<Filesystem> {
    let config_root = config.get_path("install.root")?;
    Ok(flag
        .map(PathBuf::from)
        .or_else(|| env::var_os("CARGO_INSTALL_ROOT").map(PathBuf::from))
        .or_else(move || config_root.map(|v| v.val))
        .map(Filesystem::new)
        .unwrap_or_else(|| config.home().clone()))
}

pub fn path_source<'a>(source_id: SourceId, config: &'a Config) -> CargoResult<PathSource<'a>> {
    let path = source_id
        .url()
        .to_file_path()
        .map_err(|()| failure::format_err!("path sources must have a valid path"))?;
    Ok(PathSource::new(&path, source_id, config))
}

pub fn select_pkg<'a, T>(
    mut source: T,
    name: Option<&str>,
    vers: Option<&str>,
    config: &Config,
    needs_update: bool,
    list_all: &mut dyn FnMut(&mut T) -> CargoResult<Vec<Package>>,
) -> CargoResult<(Package, Box<dyn Source + 'a>)>
where
    T: Source + 'a,
{
    if needs_update {
        source.update()?;
    }

    match name {
        Some(name) => {
            let vers = match vers {
                Some(v) => {
                    // If the version begins with character <, >, =, ^, ~ parse it as a
                    // version range, otherwise parse it as a specific version
                    let first = v.chars().nth(0).ok_or_else(|| {
                        failure::format_err!("no version provided for the `--vers` flag")
                    })?;

                    match first {
                        '<' | '>' | '=' | '^' | '~' => match v.parse::<VersionReq>() {
                            Ok(v) => Some(v.to_string()),
                            Err(_) => failure::bail!(
                                "the `--vers` provided, `{}`, is \
                                       not a valid semver version requirement\n\n
                                       Please have a look at \
                                       http://doc.crates.io/specifying-dependencies.html \
                                       for the correct format",
                                v
                            ),
                        },
                        _ => match v.to_semver() {
                            Ok(v) => Some(format!("={}", v)),
                            Err(_) => {
                                let mut msg = format!(
                                    "\
                                     the `--vers` provided, `{}`, is \
                                     not a valid semver version\n\n\
                                     historically Cargo treated this \
                                     as a semver version requirement \
                                     accidentally\nand will continue \
                                     to do so, but this behavior \
                                     will be removed eventually",
                                    v
                                );

                                // If it is not a valid version but it is a valid version
                                // requirement, add a note to the warning
                                if v.parse::<VersionReq>().is_ok() {
                                    msg.push_str(&format!(
                                        "\nif you want to specify semver range, \
                                         add an explicit qualifier, like ^{}",
                                        v
                                    ));
                                }
                                config.shell().warn(&msg)?;
                                Some(v.to_string())
                            }
                        },
                    }
                }
                None => None,
            };
            let vers = vers.as_ref().map(|s| &**s);
            let vers_spec = if vers.is_none() && source.source_id().is_registry() {
                // Avoid pre-release versions from crate.io
                // unless explicitly asked for
                Some("*")
            } else {
                vers
            };
            let dep = Dependency::parse_no_deprecated(name, vers_spec, source.source_id())?;
            let deps = source.query_vec(&dep)?;
            let pkgid = match deps.iter().map(|p| p.package_id()).max() {
                Some(pkgid) => pkgid,
                None => {
                    let vers_info = vers
                        .map(|v| format!(" with version `{}`", v))
                        .unwrap_or_default();
                    failure::bail!(
                        "could not find `{}` in {}{}",
                        name,
                        source.source_id(),
                        vers_info
                    )
                }
            };

            let pkg = {
                let mut map = SourceMap::new();
                map.insert(Box::new(&mut source));
                PackageSet::new(&[pkgid], map, config)?
                    .get_one(pkgid)?
                    .clone()
            };
            Ok((pkg, Box::new(source)))
        }
        None => {
            let candidates = list_all(&mut source)?;
            let binaries = candidates
                .iter()
                .filter(|cand| cand.targets().iter().filter(|t| t.is_bin()).count() > 0);
            let examples = candidates
                .iter()
                .filter(|cand| cand.targets().iter().filter(|t| t.is_example()).count() > 0);
            let pkg = match one(binaries, |v| multi_err("binaries", v))? {
                Some(p) => p,
                None => match one(examples, |v| multi_err("examples", v))? {
                    Some(p) => p,
                    None => failure::bail!(
                        "no packages found with binaries or \
                         examples"
                    ),
                },
            };
            return Ok((pkg.clone(), Box::new(source)));

            fn multi_err(kind: &str, mut pkgs: Vec<&Package>) -> String {
                pkgs.sort_unstable_by_key(|a| a.name());
                format!(
                    "multiple packages with {} found: {}",
                    kind,
                    pkgs.iter()
                        .map(|p| p.name().as_str())
                        .collect::<Vec<_>>()
                        .join(", ")
                )
            }
        }
    }
}

pub fn one<I, F>(mut i: I, f: F) -> CargoResult<Option<I::Item>>
where
    I: Iterator,
    F: FnOnce(Vec<I::Item>) -> String,
{
    match (i.next(), i.next()) {
        (Some(i1), Some(i2)) => {
            let mut v = vec![i1, i2];
            v.extend(i);
            Err(failure::format_err!("{}", f(v)))
        }
        (Some(i), None) => Ok(Some(i)),
        (None, _) => Ok(None),
    }
}

pub fn read_crate_list(file: &FileLock) -> CargoResult<CrateListingV1> {
    let listing = (|| -> CargoResult<_> {
        let mut contents = String::new();
        file.file().read_to_string(&mut contents)?;
        let listing =
            toml::from_str(&contents).chain_err(|| internal("invalid TOML found for metadata"))?;
        match listing {
            CrateListing::V1(v1) => Ok(v1),
            CrateListing::Empty(_) => Ok(CrateListingV1 {
                v1: BTreeMap::new(),
            }),
        }
    })()
    .chain_err(|| {
        failure::format_err!(
            "failed to parse crate metadata at `{}`",
            file.path().to_string_lossy()
        )
    })?;
    Ok(listing)
}

pub fn write_crate_list(file: &FileLock, listing: CrateListingV1) -> CargoResult<()> {
    (|| -> CargoResult<_> {
        let mut file = file.file();
        file.seek(SeekFrom::Start(0))?;
        file.set_len(0)?;
        let data = toml::to_string(&CrateListing::V1(listing))?;
        file.write_all(data.as_bytes())?;
        Ok(())
    })()
    .chain_err(|| {
        failure::format_err!(
            "failed to write crate metadata at `{}`",
            file.path().to_string_lossy()
        )
    })?;
    Ok(())
}

pub fn metadata(config: &Config, root: &Filesystem) -> CargoResult<FileLock> {
    root.open_rw(Path::new(".crates.toml"), config, "crate metadata")
}
<|endoftext|>


<commit_before>#![no_main]

use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
    if data == b"banana!" {
        panic!("success!");
    }
});
<commit_msg>Change example to use `str::as_bytes` instead of array comparison<commit_after>#![no_main]

use libfuzzer_sys::fuzz_target;

fuzz_target!(|data: &[u8]| {
    if data == "banana!".as_bytes() {
        panic!("success!");
    }
});
<|endoftext|>


<commit_before>#![allow(unused_variables)]

extern crate glutin_window;
extern crate graphics;
extern crate rebind;
extern crate piston;
extern crate opengl_graphics;
extern crate viewport;

use glutin_window::GlutinWindow;
use graphics::*;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventMap, Events};
use piston::input::{
    Event,
    Input,
    Motion,
    RenderArgs,
    RenderEvent,
    UpdateArgs,
    UpdateEvent
};
use piston::input::keyboard::Key;
use piston::input::Button::Keyboard;
use piston::window::WindowSettings;
use rebind::{Action, InputTranslator, RebindBuilder, Translated};
use std::cell::RefCell;
use std::rc::Rc;

struct App {
    window: Rc<RefCell<GlutinWindow>>,
    graphics: Rc<RefCell<GlGraphics>>,
    translator: InputTranslator<CharacterAction>,
    character: Character,
    virtual_cursor_pos: [f64; 2],
    bg_color: [f32; 4]
}

impl App {
    fn input(&mut self, input: &Input) {
        if let Some(t) = self.translator.translate(input) {
            match t {
                Translated::Press(action) => {
                    const CHARACTER_WALK_SPEED_INCREMENT: f64 = 400.0f64;
                    match action {
                        CharacterAction::Jump => {
                            println!("You jumped! Yay!");
                        },
                        CharacterAction::MoveLeft => {
                            if self.character.current_velocity[0] > (self.character.max_velocity[0] * -1.0) {
                                self.character.current_velocity[0] -= CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        },
                        CharacterAction::MoveRight => {
                            if self.character.current_velocity[0] < self.character.max_velocity[0] {
                                self.character.current_velocity[0] += CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        }
                    }
                },
                Translated::Release(_) => {
                    self.character.current_velocity = [0.0, 0.0];
                },
                Translated::Move(Motion::MouseCursor(x, y)) => {
                    self.virtual_cursor_pos = [x, y];
                },
                _ => { }
            }
        }
    }

    fn update(&mut self, args: &UpdateArgs) {
        let ctl = self.character.topleft;
        let v = self.character.current_velocity;

        self.character.topleft = [ctl[0] + (v[0] * args.dt), ctl[1] + (v[1] * args.dt)];
    }

    fn render(&mut self, args: &RenderArgs) {
        let mut gl_graphics = self.graphics.borrow_mut();

        // draw the background color
        {
            gl_graphics.draw(args.viewport(), |_, gl| clear(self.bg_color, gl));
        }

        // draw the character
        {
            let square = rectangle::square(self.character.topleft[0],
                                           self.character.topleft[1],
                                           self.character.size);

            gl_graphics.draw(args.viewport(), |c, gl| rectangle(self.character.color, square, c.transform, gl));
        }

        // draw the cursor dot
        {
            let dot = ellipse::circle(self.virtual_cursor_pos[0], self.virtual_cursor_pos[1], 5.0);
            gl_graphics.draw(args.viewport(), |c, gl| ellipse([0.0, 1.0, 0.0, 1.0], dot, c.transform, gl));
        }
    }
}

struct Character {
    color: [f32; 4],
    topleft: [f64; 2],
    current_velocity: [f64; 2],
    max_velocity: [f64; 2],
    size: f64
}

impl Character {
    fn new(col: [f32; 4], tl: [f64; 2], sz: f64) -> Self {
        Character {
            color: col,
            topleft: tl,
            current_velocity: [0.0f64, 0.0],
            max_velocity: [800.0, 0.0],
            size: sz
        }
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
enum CharacterAction {
    Jump,
    MoveLeft,
    MoveRight
}

impl Action for CharacterAction { }

fn main() {
    const WINDOW_SIZE: (u32, u32)  = (800, 600);
    const OPENGL: OpenGL = OpenGL::V3_2;

    let window = WindowSettings::new("calaxite", WINDOW_SIZE)
        .exit_on_esc(true)
        .fullscreen(false)
        .opengl(OPENGL)
        .vsync(true)
        .build()
        .unwrap_or_else(|e| panic!("Could not create window: {}", e));

    let gl_graphics = GlGraphics::new(OPENGL);

    let translator = RebindBuilder::new(WINDOW_SIZE.into())
        .with_action_mapping(Keyboard(Key::Space), CharacterAction::Jump)
        .with_action_mapping(Keyboard(Key::Left),  CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::A),     CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::Right), CharacterAction::MoveRight)
        .with_action_mapping(Keyboard(Key::D),     CharacterAction::MoveRight)
        .build_translator();

    let character = Character::new([1.0, 0.0, 0.0, 1.0],
                                   [30.0, (WINDOW_SIZE.1 as f64) * 0.85],
                                   50.0);

    let mut app = App {
        window: Rc::new(RefCell::new(window)),
        graphics: Rc::new(RefCell::new(gl_graphics)),
        translator: translator,
        character: character,
        virtual_cursor_pos: [0.0, 0.0],
        bg_color: [0.0, 0.0, 0.0, 1.0] // black background
    };

    for e in app.window.clone().events() {
        match e {
            Event::Render(r) => { app.render(&r); },
            Event::Update(u) => { app.update(&u); },
            Event::Input(i)  => { app.input(&i); },
            _ => { }
        }
    }
}
<commit_msg>Small style tweak on declaration of constants in main()<commit_after>#![allow(unused_variables)]

extern crate glutin_window;
extern crate graphics;
extern crate rebind;
extern crate piston;
extern crate opengl_graphics;
extern crate viewport;

use glutin_window::GlutinWindow;
use graphics::*;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::{EventMap, Events};
use piston::input::{
    Event,
    Input,
    Motion,
    RenderArgs,
    RenderEvent,
    UpdateArgs,
    UpdateEvent
};
use piston::input::keyboard::Key;
use piston::input::Button::Keyboard;
use piston::window::WindowSettings;
use rebind::{Action, InputTranslator, RebindBuilder, Translated};
use std::cell::RefCell;
use std::rc::Rc;

struct App {
    window: Rc<RefCell<GlutinWindow>>,
    graphics: Rc<RefCell<GlGraphics>>,
    translator: InputTranslator<CharacterAction>,
    character: Character,
    virtual_cursor_pos: [f64; 2],
    bg_color: [f32; 4]
}

impl App {
    fn input(&mut self, input: &Input) {
        if let Some(t) = self.translator.translate(input) {
            match t {
                Translated::Press(action) => {
                    const CHARACTER_WALK_SPEED_INCREMENT: f64 = 400.0f64;
                    match action {
                        CharacterAction::Jump => {
                            println!("You jumped! Yay!");
                        },
                        CharacterAction::MoveLeft => {
                            if self.character.current_velocity[0] > (self.character.max_velocity[0] * -1.0) {
                                self.character.current_velocity[0] -= CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        },
                        CharacterAction::MoveRight => {
                            if self.character.current_velocity[0] < self.character.max_velocity[0] {
                                self.character.current_velocity[0] += CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        }
                    }
                },
                Translated::Release(_) => {
                    self.character.current_velocity = [0.0, 0.0];
                },
                Translated::Move(Motion::MouseCursor(x, y)) => {
                    self.virtual_cursor_pos = [x, y];
                },
                _ => { }
            }
        }
    }

    fn update(&mut self, args: &UpdateArgs) {
        let ctl = self.character.topleft;
        let v = self.character.current_velocity;

        self.character.topleft = [ctl[0] + (v[0] * args.dt), ctl[1] + (v[1] * args.dt)];
    }

    fn render(&mut self, args: &RenderArgs) {
        let mut gl_graphics = self.graphics.borrow_mut();

        // draw the background color
        {
            gl_graphics.draw(args.viewport(), |_, gl| clear(self.bg_color, gl));
        }

        // draw the character
        {
            let square = rectangle::square(self.character.topleft[0],
                                           self.character.topleft[1],
                                           self.character.size);

            gl_graphics.draw(args.viewport(), |c, gl| rectangle(self.character.color, square, c.transform, gl));
        }

        // draw the cursor dot
        {
            let dot = ellipse::circle(self.virtual_cursor_pos[0], self.virtual_cursor_pos[1], 5.0);
            gl_graphics.draw(args.viewport(), |c, gl| ellipse([0.0, 1.0, 0.0, 1.0], dot, c.transform, gl));
        }
    }
}

struct Character {
    color: [f32; 4],
    topleft: [f64; 2],
    current_velocity: [f64; 2],
    max_velocity: [f64; 2],
    size: f64
}

impl Character {
    fn new(col: [f32; 4], tl: [f64; 2], sz: f64) -> Self {
        Character {
            color: col,
            topleft: tl,
            current_velocity: [0.0f64, 0.0],
            max_velocity: [800.0, 0.0],
            size: sz
        }
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
enum CharacterAction {
    Jump,
    MoveLeft,
    MoveRight
}

impl Action for CharacterAction { }

fn main() {
    const OPENGL: OpenGL = OpenGL::V3_2;
    const WINDOW_SIZE: (u32, u32) = (800, 600);

    let window = WindowSettings::new("calaxite", WINDOW_SIZE)
        .exit_on_esc(true)
        .fullscreen(false)
        .opengl(OPENGL)
        .vsync(true)
        .build()
        .unwrap_or_else(|e| panic!("Could not create window: {}", e));

    let gl_graphics = GlGraphics::new(OPENGL);

    let translator = RebindBuilder::new(WINDOW_SIZE.into())
        .with_action_mapping(Keyboard(Key::Space), CharacterAction::Jump)
        .with_action_mapping(Keyboard(Key::Left),  CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::A),     CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::Right), CharacterAction::MoveRight)
        .with_action_mapping(Keyboard(Key::D),     CharacterAction::MoveRight)
        .build_translator();

    let character = Character::new([1.0, 0.0, 0.0, 1.0],
                                   [30.0, (WINDOW_SIZE.1 as f64) * 0.85],
                                   50.0);

    let mut app = App {
        window: Rc::new(RefCell::new(window)),
        graphics: Rc::new(RefCell::new(gl_graphics)),
        translator: translator,
        character: character,
        virtual_cursor_pos: [0.0, 0.0],
        bg_color: [0.0, 0.0, 0.0, 1.0] // black background
    };

    for e in app.window.clone().events() {
        match e {
            Event::Render(r) => { app.render(&r); },
            Event::Update(u) => { app.update(&u); },
            Event::Input(i)  => { app.input(&i); },
            _ => { }
        }
    }
}
<|endoftext|>


<commit_before>//! Information and types for Falcon's supported architectures.

use analysis::calling_convention::{CallingConvention, CallingConventionType};
use il;
use std::fmt::Debug;
use translator;

/// An architecture's endanness.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum Endian {
    Big,
    Little
}

/// Necessary functions for analysis over architectures.
pub trait Architecture: Debug + Send + Sync {
    /// Get the endianness of this architecture.
    fn endian(&self) -> Endian;
    /// Get this architecture's translator.
    fn translator(&self) -> Box<translator::Translator>;
    /// Get the _default_ calling convention for this architecture.
    fn calling_convention(&self) -> CallingConvention;
    /// Get the scalar used to represent the stack pointer by this
    /// architecture's translator.
    fn stack_pointer(&self) -> il::Scalar;
    /// Get the size of a natural word for this architecture in bits.
    fn word_size(&self) -> usize;
}

/// The 64-bit X86 Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Amd64 {}

impl Amd64 {
    pub fn new() -> Amd64 { Amd64 {} }
}

impl Architecture for Amd64 {
    fn endian(&self) -> Endian { Endian::Little }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::x86::Amd64::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::Amd64SystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("rsp", 64) }
    fn word_size(&self) -> usize { 64 }
}

/// The 32-bit Mips Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Mips {}

impl Mips {
    pub fn new() -> Mips { Mips {} }
}

impl Architecture for Mips {
    fn endian(&self) -> Endian { Endian::Big }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::mips::Mips::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::MipsSystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("$sp", 32) }
    fn word_size(&self) -> usize { 32 }
}

/// The 32-bit Mipsel Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Mipsel {}

impl Mipsel {
    pub fn new() -> Mipsel { Mipsel {} }
}

impl Architecture for Mipsel {
    fn endian(&self) -> Endian { Endian::Big }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::mips::Mipsel::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::MipsSystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("$sp", 32) }
    fn word_size(&self) -> usize { 32 }
}

/// The 32-bit X86 Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct X86 {}

impl X86 {
    pub fn new() -> X86 { X86 {} }
}

impl Architecture for X86 {
    fn endian(&self) -> Endian { Endian::Little }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::x86::X86::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::Cdecl)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("esp", 32) }
    fn word_size(&self) -> usize { 32 }
}<commit_msg>Add box_clone method to Architecture<commit_after>//! Information and types for Falcon's supported architectures.

use analysis::calling_convention::{CallingConvention, CallingConventionType};
use il;
use std::fmt::Debug;
use translator;

/// An architecture's endanness.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub enum Endian {
    Big,
    Little
}

/// Necessary functions for analysis over architectures.
pub trait Architecture: Debug + Send + Sync {
    /// Get the endianness of this architecture.
    fn endian(&self) -> Endian;
    /// Get this architecture's translator.
    fn translator(&self) -> Box<translator::Translator>;
    /// Get the _default_ calling convention for this architecture.
    fn calling_convention(&self) -> CallingConvention;
    /// Get the scalar used to represent the stack pointer by this
    /// architecture's translator.
    fn stack_pointer(&self) -> il::Scalar;
    /// Get the size of a natural word for this architecture in bits.
    fn word_size(&self) -> usize;
    /// Clone into a boxed `Architecture`
    fn box_clone(&self) -> Box<Architecture>;
}

/// The 64-bit X86 Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Amd64 {}

impl Amd64 {
    pub fn new() -> Amd64 { Amd64 {} }
}

impl Architecture for Amd64 {
    fn endian(&self) -> Endian { Endian::Little }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::x86::Amd64::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::Amd64SystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("rsp", 64) }
    fn word_size(&self) -> usize { 64 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}

/// The 32-bit Mips Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Mips {}

impl Mips {
    pub fn new() -> Mips { Mips {} }
}

impl Architecture for Mips {
    fn endian(&self) -> Endian { Endian::Big }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::mips::Mips::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::MipsSystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("$sp", 32) }
    fn word_size(&self) -> usize { 32 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}

/// The 32-bit Mipsel Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Mipsel {}

impl Mipsel {
    pub fn new() -> Mipsel { Mipsel {} }
}

impl Architecture for Mipsel {
    fn endian(&self) -> Endian { Endian::Big }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::mips::Mipsel::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::MipsSystemV)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("$sp", 32) }
    fn word_size(&self) -> usize { 32 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}

/// The 32-bit X86 Architecture.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct X86 {}

impl X86 {
    pub fn new() -> X86 { X86 {} }
}

impl Architecture for X86 {
    fn endian(&self) -> Endian { Endian::Little }
    fn translator(&self) -> Box<translator::Translator> {
        Box::new(translator::x86::X86::new())
    }
    fn calling_convention(&self) -> CallingConvention {
        CallingConvention::new(CallingConventionType::Cdecl)
    }
    fn stack_pointer(&self) -> il::Scalar { il::scalar("esp", 32) }
    fn word_size(&self) -> usize { 32 }
    fn box_clone(&self) -> Box<Architecture> { Box::new(self.clone()) }
}<|endoftext|>


<commit_before>fn function() {
    println!("called `function()`");
}

// A module named `my`
mod my {
    // A module can contain items like functions
    #[allow(dead_code)]
    fn function() {
        println!("called `my::function()`");
    }

    // Modules can be nested
    mod nested {
        #[allow(dead_code)]
        fn function() {
            println!("called `my::nested::function()`");
        }
    }
}

fn main() {
    function();

    // Items inside a module can be called using their full  path
    // The `println` function lives in the `stdio` module
    // The `stdio` module lives in the `io` module
    // And the `io` module lives in the `std` crate
    std::io::stdio::println("Hello World!");

    // Error! `my::function` is private
    my::function();
    // TODO ^ Comment out this line
}
<commit_msg>Remove extra space<commit_after>fn function() {
    println!("called `function()`");
}

// A module named `my`
mod my {
    // A module can contain items like functions
    #[allow(dead_code)]
    fn function() {
        println!("called `my::function()`");
    }

    // Modules can be nested
    mod nested {
        #[allow(dead_code)]
        fn function() {
            println!("called `my::nested::function()`");
        }
    }
}

fn main() {
    function();

    // Items inside a module can be called using their full path
    // The `println` function lives in the `stdio` module
    // The `stdio` module lives in the `io` module
    // And the `io` module lives in the `std` crate
    std::io::stdio::println("Hello World!");

    // Error! `my::function` is private
    my::function();
    // TODO ^ Comment out this line
}
<|endoftext|>


<commit_before>use std::iter::RandomAccessIterator;

/**
(
a0,
a1,
...
)
 →
(
a0`.clone()`,
a1`.clone()`,
...
)

*/
pub trait CloneEachIterator<'a, E>: Iterator<Item=&'a E> + Sized where E: Clone {
    /**
Creates an iterator which will clone each element of the input iterator.
    */
    fn clone_each(self) -> CloneEach<Self> {
        CloneEach {
            iter: self,
        }
    }
}

impl<'a, It, E> CloneEachIterator<'a, E> for It where It: Iterator<Item=&'a E>, E: Clone {}

#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct CloneEach<It> {
    iter: It,
}

impl<It> CloneEach<It> {
    /**
Unwraps the iterator, returning the underlying iterator.
    */
    pub fn unwrap(self) -> It {
        self.iter
    }
}

impl<'a, It, E> Iterator for CloneEach<It> where It: Iterator<Item=&'a E>, E: 'a + Clone {
    type Item = E;

    fn next(&mut self) -> Option<E> {
        match self.iter.next() {
            None => None,
            Some(e) => Some(e.clone())
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a, E, It> DoubleEndedIterator for CloneEach<It> where It: DoubleEndedIterator<Item=&'a E>, E: 'a + Clone {
    fn next_back(&mut self) -> Option<E> {
        self.iter.next_back().map(|e| e.clone())
    }
}

impl<'a, E, It> RandomAccessIterator for CloneEach<It> where It: RandomAccessIterator<Item=&'a E>, E: 'a + Clone {
    fn indexable(&self) -> usize {
        self.iter.indexable()
    }

    fn idx(&mut self, index: usize) -> Option<E> {
        self.iter.idx(index).map(|e| e.clone())
    }
}

#[test]
fn test_clone_each() {
    let it: Vec<i32> = vec![1, 2, 3];
    let mut it = it.iter().clone_each();
    assert_eq!(it.next(), Some(1));
    assert_eq!(it.next(), Some(2));
    assert_eq!(it.next(), Some(3));
    assert_eq!(it.next(), None);
}
<commit_msg>Deprecated CloneEach since there's `cloned()` in the std lib now.<commit_after>use std::iter::RandomAccessIterator;

/**
(
a0,
a1,
...
)
 →
(
a0`.clone()`,
a1`.clone()`,
...
)

*/
pub trait CloneEachIterator<'a, E>: Iterator<Item=&'a E> + Sized where E: Clone {
    /**
Creates an iterator which will clone each element of the input iterator.
    */
    #[deprecated = "use `it.cloned()` provided by the standard library"]
    fn clone_each(self) -> CloneEach<Self> {
        CloneEach {
            iter: self,
        }
    }
}

impl<'a, It, E> CloneEachIterator<'a, E> for It where It: Iterator<Item=&'a E>, E: Clone {}

#[derive(Clone, Debug)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
pub struct CloneEach<It> {
    iter: It,
}

impl<It> CloneEach<It> {
    /**
Unwraps the iterator, returning the underlying iterator.
    */
    pub fn unwrap(self) -> It {
        self.iter
    }
}

impl<'a, It, E> Iterator for CloneEach<It> where It: Iterator<Item=&'a E>, E: 'a + Clone {
    type Item = E;

    fn next(&mut self) -> Option<E> {
        match self.iter.next() {
            None => None,
            Some(e) => Some(e.clone())
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a, E, It> DoubleEndedIterator for CloneEach<It> where It: DoubleEndedIterator<Item=&'a E>, E: 'a + Clone {
    fn next_back(&mut self) -> Option<E> {
        self.iter.next_back().map(|e| e.clone())
    }
}

impl<'a, E, It> RandomAccessIterator for CloneEach<It> where It: RandomAccessIterator<Item=&'a E>, E: 'a + Clone {
    fn indexable(&self) -> usize {
        self.iter.indexable()
    }

    fn idx(&mut self, index: usize) -> Option<E> {
        self.iter.idx(index).map(|e| e.clone())
    }
}

#[test]
fn test_clone_each() {
    let it: Vec<i32> = vec![1, 2, 3];
    let mut it = it.iter().clone_each();
    assert_eq!(it.next(), Some(1));
    assert_eq!(it.next(), Some(2));
    assert_eq!(it.next(), Some(3));
    assert_eq!(it.next(), None);
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::vec::Vec;

use analysis::imports::Imports;
use analysis::needed_upcast::needed_upcast;
use analysis::out_parameters;
use analysis::return_value;
use analysis::rust_type::*;
use analysis::upcasts::Upcasts;
use env::Env;
use library::{self, Nullable};
use nameutil;
use regexlist::RegexList;
use traits::*;
use version::Version;

//TODO: change use Parameter to reference?
pub struct Info {
    pub name: String,
    pub glib_name: String,
    pub kind: library::FunctionKind,
    pub comented: bool,
    pub type_name: Result,
    pub parameters: Vec<library::Parameter>,
    pub ret: return_value::Info,
    pub upcasts: Upcasts,
    pub outs: out_parameters::Info,
    pub version: Option<Version>,
}

pub fn analyze(env: &Env, functions: &[library::Function], type_tid: library::TypeId,
    non_nullable_overrides: &[String], ignored_functions: &RegexList,
    imports: &mut Imports) -> Vec<Info> {
    let mut funcs = Vec::new();

    for func in functions {
        if ignored_functions.is_match(&func.name) {
            continue;
        }
        let info = analyze_function(env, func, type_tid, non_nullable_overrides, imports);
        funcs.push(info);
    }

    funcs
}

fn analyze_function(env: &Env, func: &library::Function, type_tid: library::TypeId,
    non_nullable_overrides: &[String], imports: &mut Imports) -> Info {
    let mut commented = false;
    let mut upcasts: Upcasts = Default::default();
    let mut used_types: Vec<String> = Vec::with_capacity(4);

    let ret = return_value::analyze(env, func, type_tid, non_nullable_overrides, &mut used_types);
    commented |= ret.commented;

    let mut parameters = func.parameters.clone();

    for (pos, par) in parameters.iter_mut().enumerate() {
        assert!(!par.instance_parameter || pos == 0,
            "Wrong instance parameter in {}", func.c_identifier.as_ref().unwrap());
        if let Ok(s) = used_rust_type(env, par.typ) {
            used_types.push(s);
        }
        if !par.instance_parameter {
            if let Cow::Owned(mangled) = nameutil::mangle_keywords(&*par.name) {
                par.name = mangled;
            }
        }
        let type_error = parameter_rust_type(env, par.typ, par.direction, Nullable(false)).is_err();
        if !par.instance_parameter && needed_upcast(&env.library, par.typ) {
            let type_name = rust_type(env, par.typ);
            let ignored = if type_error { "/*Ignored*/" } else { "" };
            if !upcasts.add_parameter(&par.name, &format!("{}{}", ignored, type_name.as_str())) {
                panic!("Too many parameters upcasts for {}", func.c_identifier.as_ref().unwrap())
            }
        }
        if type_error {
            commented = true;
        }
    }

    let (outs, unsupported_outs) = out_parameters::analyze(env, func);
    if unsupported_outs {
        warn!("Function {} has unsupported outs", func.c_identifier.as_ref().unwrap_or(&func.name));
        commented = true;
    } else if !outs.is_empty() {
        imports.add("std::mem".into(), func.version);
    }

    if !commented {
        for s in used_types {
            if let Some(i) = s.find("::") {
                imports.add(s[..i].into(), func.version);
            }
            else {
                imports.add(s, func.version);
            }
        }
        if ret.base_tid.is_some() {
            imports.add("glib::object::Downcast".into(), None);
        }
        if !upcasts.is_empty() {
            imports.add("glib::object::Upcast".into(), None);
        }
    }

    Info {
        name: nameutil::mangle_keywords(&*func.name).into_owned(),
        glib_name: func.c_identifier.as_ref().unwrap().clone(),
        kind: func.kind,
        comented: commented,
        type_name: rust_type(env, type_tid),
        parameters: parameters,
        ret: ret,
        upcasts: upcasts,
        outs: outs,
        version: func.version,
    }
}
<commit_msg>Use std::mem only for uncommented functions with outs<commit_after>use std::borrow::Cow;
use std::vec::Vec;

use analysis::imports::Imports;
use analysis::needed_upcast::needed_upcast;
use analysis::out_parameters;
use analysis::return_value;
use analysis::rust_type::*;
use analysis::upcasts::Upcasts;
use env::Env;
use library::{self, Nullable};
use nameutil;
use regexlist::RegexList;
use traits::*;
use version::Version;

//TODO: change use Parameter to reference?
pub struct Info {
    pub name: String,
    pub glib_name: String,
    pub kind: library::FunctionKind,
    pub comented: bool,
    pub type_name: Result,
    pub parameters: Vec<library::Parameter>,
    pub ret: return_value::Info,
    pub upcasts: Upcasts,
    pub outs: out_parameters::Info,
    pub version: Option<Version>,
}

pub fn analyze(env: &Env, functions: &[library::Function], type_tid: library::TypeId,
    non_nullable_overrides: &[String], ignored_functions: &RegexList,
    imports: &mut Imports) -> Vec<Info> {
    let mut funcs = Vec::new();

    for func in functions {
        if ignored_functions.is_match(&func.name) {
            continue;
        }
        let info = analyze_function(env, func, type_tid, non_nullable_overrides, imports);
        funcs.push(info);
    }

    funcs
}

fn analyze_function(env: &Env, func: &library::Function, type_tid: library::TypeId,
    non_nullable_overrides: &[String], imports: &mut Imports) -> Info {
    let mut commented = false;
    let mut upcasts: Upcasts = Default::default();
    let mut used_types: Vec<String> = Vec::with_capacity(4);

    let ret = return_value::analyze(env, func, type_tid, non_nullable_overrides, &mut used_types);
    commented |= ret.commented;

    let mut parameters = func.parameters.clone();

    for (pos, par) in parameters.iter_mut().enumerate() {
        assert!(!par.instance_parameter || pos == 0,
            "Wrong instance parameter in {}", func.c_identifier.as_ref().unwrap());
        if let Ok(s) = used_rust_type(env, par.typ) {
            used_types.push(s);
        }
        if !par.instance_parameter {
            if let Cow::Owned(mangled) = nameutil::mangle_keywords(&*par.name) {
                par.name = mangled;
            }
        }
        let type_error = parameter_rust_type(env, par.typ, par.direction, Nullable(false)).is_err();
        if !par.instance_parameter && needed_upcast(&env.library, par.typ) {
            let type_name = rust_type(env, par.typ);
            let ignored = if type_error { "/*Ignored*/" } else { "" };
            if !upcasts.add_parameter(&par.name, &format!("{}{}", ignored, type_name.as_str())) {
                panic!("Too many parameters upcasts for {}", func.c_identifier.as_ref().unwrap())
            }
        }
        if type_error {
            commented = true;
        }
    }

    let (outs, unsupported_outs) = out_parameters::analyze(env, func);
    if unsupported_outs {
        warn!("Function {} has unsupported outs", func.c_identifier.as_ref().unwrap_or(&func.name));
        commented = true;
    } else if !outs.is_empty() && !commented {
        //TODO: move to out_parameters::analyze
        imports.add("std::mem".into(), func.version);
    }

    if !commented {
        for s in used_types {
            if let Some(i) = s.find("::") {
                imports.add(s[..i].into(), func.version);
            }
            else {
                imports.add(s, func.version);
            }
        }
        if ret.base_tid.is_some() {
            imports.add("glib::object::Downcast".into(), None);
        }
        if !upcasts.is_empty() {
            imports.add("glib::object::Upcast".into(), None);
        }
    }

    Info {
        name: nameutil::mangle_keywords(&*func.name).into_owned(),
        glib_name: func.c_identifier.as_ref().unwrap().clone(),
        kind: func.kind,
        comented: commented,
        type_name: rust_type(env, type_tid),
        parameters: parameters,
        ret: ret,
        upcasts: upcasts,
        outs: outs,
        version: func.version,
    }
}
<|endoftext|>


<commit_before>extern mod std;

enum HashEngine { SHA1, SHA128, SHA224, SHA256, SHA384, SHA512, MD5 }

extern mod crypto {
  fn SHA1(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn MD5(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
}

extern mod cryptobindings {
  fn wrap_HMAC(method: HashEngine,
    key: *u8,
    key_size: libc::size_t,
    data: *u8,
    size: libc::size_t,
    target: *u8) -> libc::c_uint;
}

struct Digest { digest: ~[u8] }

impl Digest {
    fn new(digest: ~[u8]) -> ~Digest { return ~Digest{ digest: digest } }

    fn hexdigest(&self) -> ~str {
        let mut acc = ~"";
        for self.digest.each |&byte| { acc += fmt!("%02x", byte as uint); }
        acc
    }
}

fn hash(data: ~[u8], hash_func: &fn(*u8, libc::c_uint, *u8) -> *u8, len: uint) -> ~Digest {
  unsafe {
    Digest::new(
      vec::from_buf(
        hash_func(
          vec::raw::to_ptr(data),
          data.len() as libc::c_uint, ptr::null()
        ),
        len
      )
    )
  }
}

fn sha1(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::SHA1, 20)
  }
}

fn md5(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::MD5, 16)
  }
}

fn xor_with(subject: &str, val: u8) -> ~[u8] {
  do subject.to_bytes().map |&c| { val ^ c }
}

fn hmac(key: ~str, message: ~str) -> ~str {
  let block_size = 64;

  let computed_key: &str = if key.len() > block_size {
    sha1(key.to_bytes()).hexdigest() // TODO this should be .digest more likely
  } else if key.len() < block_size {
    key + str::from_bytes(vec::from_elem(block_size - key.len(), 0))
  } else {
    key
  };

  let o_key_pad = xor_with(computed_key, 0x5c);
  let i_key_pad = xor_with(computed_key, 0x36);
  let bin_message = message.to_bytes();

  sha1(o_key_pad + sha1(i_key_pad + bin_message).digest).hexdigest()
}

fn main() {
  if core::os::args().len() < 2 { fail!(~"Nothing to hash: supply an argument") }
  io::println(sha1(core::os::args()[1].clone().to_bytes()).hexdigest());
}

#[test]
fn test_sha1() {
  assert_eq!(sha1("testing SHA1".to_bytes()).hexdigest(), ~"a07bb2f7f56b7b47e54fd9e29b4629c8967dde4c");
}

#[test]
fn test_md5() {
  assert_eq!(md5("testing MD5".to_bytes()).hexdigest(), ~"da35df95d34f166890fa759f5e00e94c");
}

#[test]
fn test_hmac() {
  assert_eq!(
    hmac(~"my key", ~"some data to hmac"),
    ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2"
  )
}

/*
#[test]
fn test_hmac_sha1() {
  assert_eq!(hmac(SHA1, ~"my key", ~"some data to hmac"), ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2");
}

#[test]
fn test_hmac_sha256() {
  assert_eq!(
    hmac(SHA256, ~"my key", ~"some data to hmac"),
    ~"17764a8a2e8c23ae3b9e1781c5ebeb5754c7920806021032e9133051e10118be"
  );
}

#[test]
fn test_hmac_sha512() {
  assert_eq!(
    hmac(SHA512, ~"my key", ~"some data to hmac"),
    ~"b54973feba2e436c4f0911855c80e7320d72edd37b359d6474d714718c52775f163832b79214e9fa9d400208d21372a465b2cda2a1d5ab488bbc02b0daea9626"
  );
}

#[test]
fn test_hmac_md5() {
  assert_eq!(hmac(MD5, ~"my key", ~"some data to hmac"), ~"befd13e00ee07549520ade402c664a3a");
}
*/
<commit_msg>Implement hmac as a generic, pluggable method. HMAC-MD5 and HMAC-SHA1.<commit_after>extern mod std;

enum HashEngine { SHA1, SHA128, SHA224, SHA256, SHA384, SHA512, MD5 }

extern mod crypto {
  fn SHA1(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
  fn MD5(src: *u8, sz: libc::c_uint, out: *u8) -> *u8;
}

extern mod cryptobindings {
  fn wrap_HMAC(method: HashEngine,
    key: *u8,
    key_size: libc::size_t,
    data: *u8,
    size: libc::size_t,
    target: *u8) -> libc::c_uint;
}

struct Digest { digest: ~[u8] }

impl Digest {
    fn new(digest: ~[u8]) -> ~Digest { return ~Digest{ digest: digest } }

    fn hexdigest(&self) -> ~str {
        let mut acc = ~"";
        for self.digest.each |&byte| { acc += fmt!("%02x", byte as uint); }
        acc
    }
}

fn hash(data: ~[u8], hash_func: &fn(*u8, libc::c_uint, *u8) -> *u8, len: uint) -> ~Digest {
  unsafe {
    Digest::new(
      vec::from_buf(
        hash_func(
          vec::raw::to_ptr(data),
          data.len() as libc::c_uint, ptr::null()
        ),
        len
      )
    )
  }
}

fn sha1(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::SHA1, 20)
  }
}

fn md5(data: ~[u8]) -> ~Digest {
  unsafe {
    hash(data, crypto::MD5, 16)
  }
}

fn xor_with(subject: &str, val: u8) -> ~[u8] {
  do subject.to_bytes().map |&c| { val ^ c }
}

fn hmac_sha1(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, sha1)
}

fn hmac_md5(key: ~str, message: ~str) -> ~Digest {
  hmac(key, message, 64, md5)
}

fn hmac(key: ~str, message: ~str, block_size: uint, hash_func: &fn(~[u8]) -> ~Digest) -> ~Digest {
  let computed_key: &str = if key.len() > block_size {
    hash_func(key.to_bytes()).hexdigest() // TODO this should be .digest more likely
  } else if key.len() < block_size {
    key + str::from_bytes(vec::from_elem(block_size - key.len(), 0))
  } else {
    key
  };

  let o_key_pad = xor_with(computed_key, 0x5c);
  let i_key_pad = xor_with(computed_key, 0x36);
  let bin_message = message.to_bytes();

  hash_func(o_key_pad + hash_func(i_key_pad + bin_message).digest)
}

fn main() {
  if core::os::args().len() < 2 { fail!(~"Nothing to hash: supply an argument") }
  io::println(sha1(core::os::args()[1].clone().to_bytes()).hexdigest());
}

#[test]
fn test_sha1() {
  assert_eq!(sha1("testing SHA1".to_bytes()).hexdigest(), ~"a07bb2f7f56b7b47e54fd9e29b4629c8967dde4c");
}

#[test]
fn test_md5() {
  assert_eq!(md5("testing MD5".to_bytes()).hexdigest(), ~"da35df95d34f166890fa759f5e00e94c");
}

#[test]
fn test_hmac_sha1() {
  assert_eq!(
    hmac_sha1(~"my key", ~"some data to hmac").hexdigest(),
    ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2"
  )
}

/*
#[test]
fn test_hmac_sha1() {
  assert_eq!(hmac(SHA1, ~"my key", ~"some data to hmac"), ~"331c9bf4d7dc8ad7e9bab2f566c8612042a9f4e2");
}

#[test]
fn test_hmac_sha256() {
  assert_eq!(
    hmac(SHA256, ~"my key", ~"some data to hmac"),
    ~"17764a8a2e8c23ae3b9e1781c5ebeb5754c7920806021032e9133051e10118be"
  );
}

#[test]
fn test_hmac_sha512() {
  assert_eq!(
    hmac(SHA512, ~"my key", ~"some data to hmac"),
    ~"b54973feba2e436c4f0911855c80e7320d72edd37b359d6474d714718c52775f163832b79214e9fa9d400208d21372a465b2cda2a1d5ab488bbc02b0daea9626"
  );
}

*/
#[test]
fn test_hmac_md5() {
  assert_eq!(hmac_md5(~"my key", ~"some data to hmac").hexdigest(), ~"befd13e00ee07549520ade402c664a3a");
}
<|endoftext|>