<commit_before>// Implements the `zakopane checksum` subcommand.

use crate::structs::ZakopaneError;

const MAX_TASKS: usize = 8;
type ChecksumResult = Result<String, ZakopaneError>;

#[derive(Default)]
struct ChecksumTaskManager {
    // Non-associative container enumerating paths and checksums.
    sums: std::vec::Vec<(String, String)>,

    // Map of outstanding checksum tasks.
    // *    Keys: absolute paths being checksummed
    // *    Values: tokio JoinHandles for checksum tasks
    tasks: std::collections::HashMap<String, tokio::task::JoinHandle<ChecksumResult>>,
}

async fn do_checksum(path: std::path::PathBuf) -> ChecksumResult {
    todo!()
}

impl ChecksumTaskManager {
    pub fn new() -> Self {
        Default::default()
    }

    pub async fn spawn_task(&mut self, path: std::path::PathBuf) {
        assert!(
            self.tasks.len() < MAX_TASKS,
            "attempted to spawn too many tasks"
        );
        self.tasks.insert(String::from(path.to_str().unwrap()), tokio::spawn(do_checksum(path)));
    }
}

async fn checksum_impl() -> ChecksumResult {
    // *    Walk the target path.
    // *    If we can, then spawn a task, providing the current path
    //      in the walk and a cloned transmitter.
    // *    Call `poll_recv()` on the receiver repeatedly, updating
    //      our checksum map and `join()`ing the completed tasks.
    todo!()
}

#[allow(dead_code)]
fn checksum() -> ChecksumResult {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl())
}
<commit_msg>checksum: Erase spurious `async` label<commit_after>// Implements the `zakopane checksum` subcommand.

use crate::structs::ZakopaneError;

const MAX_TASKS: usize = 8;
type ChecksumResult = Result<String, ZakopaneError>;

#[derive(Default)]
struct ChecksumTaskManager {
    // Non-associative container enumerating paths and checksums.
    sums: std::vec::Vec<(String, String)>,

    // Map of outstanding checksum tasks.
    // *    Keys: absolute paths being checksummed
    // *    Values: tokio JoinHandles for checksum tasks
    tasks: std::collections::HashMap<String, tokio::task::JoinHandle<ChecksumResult>>,
}

async fn do_checksum(path: std::path::PathBuf) -> ChecksumResult {
    todo!()
}

impl ChecksumTaskManager {
    pub fn new() -> Self {
        Default::default()
    }

    pub fn spawn_task(&mut self, path: std::path::PathBuf) {
        assert!(
            self.tasks.len() < MAX_TASKS,
            "attempted to spawn too many tasks"
        );
        self.tasks.insert(String::from(path.to_str().unwrap()), tokio::spawn(do_checksum(path)));
    }
}

async fn checksum_impl() -> ChecksumResult {
    // *    Walk the target path.
    // *    If we can, then spawn a task, providing the current path
    //      in the walk and a cloned transmitter.
    // *    Call `poll_recv()` on the receiver repeatedly, updating
    //      our checksum map and `join()`ing the completed tasks.
    todo!()
}

#[allow(dead_code)]
fn checksum() -> ChecksumResult {
    let runtime = tokio::runtime::Runtime::new().unwrap();
    runtime.block_on(checksum_impl())
}
<|endoftext|>


<commit_before>extern crate bit_vec;
extern crate ssz;

use bit_vec::BitVec;

use serde::ser::{Serialize, Serializer};
use std::cmp;
use std::default;

/// A BooleanBitfield represents a set of booleans compactly stored as a vector of bits.
/// The BooleanBitfield is given a fixed size during construction. Reads outside of the current size return an out-of-bounds error. Writes outside of the current size expand the size of the set.
#[derive(Debug, Clone)]
pub struct BooleanBitfield(BitVec);

/// Error represents some reason a request against a bitfield was not satisfied
#[derive(Debug, PartialEq)]
pub enum Error {
    /// OutOfBounds refers to indexing into a bitfield where no bits exist; returns the illegal index and the current size of the bitfield, respectively
    OutOfBounds(usize, usize),
}

impl BooleanBitfield {
    /// Create a new bitfield.
    pub fn new() -> Self {
        Default::default()
    }

    pub fn with_capacity(initial_len: usize) -> Self {
        Self::from_elem(initial_len, false)
    }

    /// Create a new bitfield with the given length `initial_len` and all values set to `bit`.
    pub fn from_elem(inital_len: usize, bit: bool) -> Self {
        Self {
            0: BitVec::from_elem(inital_len, bit),
        }
    }

    /// Create a new bitfield using the supplied `bytes` as input
    pub fn from_bytes(bytes: &[u8]) -> Self {
        Self {
            0: BitVec::from_bytes(bytes),
        }
    }

    /// Read the value of a bit.
    ///
    /// If the index is in bounds, then result is Ok(value) where value is `true` if the bit is 1 and `false` if the bit is 0.
    /// If the index is out of bounds, we return an error to that extent.
    pub fn get(&self, i: usize) -> Result<bool, Error> {
        match self.0.get(i) {
            Some(value) => Ok(value),
            None => Err(Error::OutOfBounds(i, self.0.len())),
        }
    }

    /// Set the value of a bit.
    ///
    /// If the index is out of bounds, we expand the size of the underlying set to include the new index.
    /// Returns the previous value if there was one.
    pub fn set(&mut self, i: usize, value: bool) -> Option<bool> {
        let previous = match self.get(i) {
            Ok(previous) => Some(previous),
            Err(Error::OutOfBounds(_, len)) => {
                let new_len = i - len + 1;
                self.0.grow(new_len, false);
                None
            }
        };
        self.0.set(i, value);
        previous
    }

    /// Returns the index of the highest set bit. Some(n) if some bit is set, None otherwise.
    pub fn highest_set_bit(&self) -> Option<usize> {
        self.0.iter().rposition(|bit| bit)
    }

    /// Returns the number of bits in this bitfield.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns the number of bytes required to represent this bitfield.
    pub fn num_bytes(&self) -> usize {
        self.to_bytes().len()
    }

    /// Returns the number of `1` bits in the bitfield
    pub fn num_set_bits(&self) -> usize {
        self.0.iter().filter(|&bit| bit).count()
    }

    /// Returns a vector of bytes representing the bitfield
    /// Note that this returns the bit layout of the underlying implementation in the `bit-vec` crate.
    pub fn to_bytes(&self) -> Vec<u8> {
        self.0.to_bytes()
    }
}

impl default::Default for BooleanBitfield {
    /// default provides the "empty" bitfield
    /// Note: the empty bitfield is set to the `0` byte.
    fn default() -> Self {
        Self::from_elem(8, false)
    }
}

impl cmp::PartialEq for BooleanBitfield {
    /// Determines equality by comparing the `ssz` encoding of the two candidates.
    /// This method ensures that the presence of high-order (empty) bits in the highest byte do not exclude equality when they are in fact representing the same information.
    fn eq(&self, other: &Self) -> bool {
        ssz::ssz_encode(self) == ssz::ssz_encode(other)
    }
}

impl ssz::Encodable for BooleanBitfield {
    // ssz_append encodes Self according to the `ssz` spec.
    fn ssz_append(&self, s: &mut ssz::SszStream) {
        s.append_vec(&self.to_bytes())
    }
}

impl ssz::Decodable for BooleanBitfield {
    fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), ssz::DecodeError> {
        let len = ssz::decode::decode_length(bytes, index, ssz::LENGTH_BYTES)?;
        if (ssz::LENGTH_BYTES + len) > bytes.len() {
            return Err(ssz::DecodeError::TooShort);
        }

        if len == 0 {
            Ok((BooleanBitfield::new(), index + ssz::LENGTH_BYTES))
        } else {
            let bytes = &bytes[(index + 4)..(index + len + 4)];

            let count = len * 8;
            let mut field = BooleanBitfield::with_capacity(count);
            for (byte_index, byte) in bytes.iter().enumerate() {
                for i in 0..8 {
                    let bit = byte & (128 >> i);
                    if bit != 0 {
                        field.set(8 * byte_index + i, true);
                    }
                }
            }

            let index = index + ssz::LENGTH_BYTES + len;
            Ok((field, index))
        }
    }
}

impl Serialize for BooleanBitfield {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&ssz::ssz_encode(self))
    }
}

impl ssz::TreeHash for BooleanBitfield {
    fn hash_tree_root(&self) -> Vec<u8> {
        self.to_bytes().hash_tree_root()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ssz::{ssz_encode, Decodable, SszStream};

    #[test]
    fn test_new_bitfield() {
        let mut field = BooleanBitfield::new();
        let original_len = field.len();

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }
    }

    #[test]
    fn test_empty_bitfield() {
        let mut field = BooleanBitfield::from_elem(0, false);
        let original_len = field.len();

        assert_eq!(original_len, 0);

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }

        assert_eq!(field.len(), 100);
        assert_eq!(field.num_set_bits(), 100);
    }

    const INPUT: &[u8] = &[0b0000_0010, 0b0000_0010];

    #[test]
    fn test_get_from_bitfield() {
        let field = BooleanBitfield::from_bytes(INPUT);
        let unset = field.get(0).unwrap();
        assert!(!unset);
        let set = field.get(6).unwrap();
        assert!(set);
        let set = field.get(14).unwrap();
        assert!(set);
    }

    #[test]
    fn test_set_for_bitfield() {
        let mut field = BooleanBitfield::from_bytes(INPUT);
        let previous = field.set(10, true).unwrap();
        assert!(!previous);
        let previous = field.get(10).unwrap();
        assert!(previous);
        let previous = field.set(6, false).unwrap();
        assert!(previous);
        let previous = field.get(6).unwrap();
        assert!(!previous);
    }

    #[test]
    fn test_highest_set_bit() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.highest_set_bit().unwrap(), 14);

        let field = BooleanBitfield::from_bytes(&[0b0000_0011]);
        assert_eq!(field.highest_set_bit().unwrap(), 7);

        let field = BooleanBitfield::new();
        assert_eq!(field.highest_set_bit(), None);
    }

    #[test]
    fn test_len() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.len(), 16);

        let field = BooleanBitfield::new();
        assert_eq!(field.len(), 8);
    }

    #[test]
    fn test_num_set_bits() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_set_bits(), 2);

        let field = BooleanBitfield::new();
        assert_eq!(field.num_set_bits(), 0);
    }

    #[test]
    fn test_to_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.to_bytes(), INPUT);

        let field = BooleanBitfield::new();
        assert_eq!(field.to_bytes(), vec![0]);
    }

    #[test]
    fn test_out_of_bounds() {
        let mut field = BooleanBitfield::from_bytes(INPUT);

        let out_of_bounds_index = field.len();
        assert!(field.set(out_of_bounds_index, true).is_none());
        assert!(field.len() == out_of_bounds_index + 1);
        assert!(field.get(out_of_bounds_index).unwrap());

        for i in 0..100 {
            if i <= out_of_bounds_index {
                assert!(field.set(i, true).is_some());
            } else {
                assert!(field.set(i, true).is_none());
            }
        }
    }

    #[test]
    fn test_grows_with_false() {
        let input_all_set: &[u8] = &[0b1111_1111, 0b1111_1111];
        let mut field = BooleanBitfield::from_bytes(input_all_set);

        // Define `a` and `b`, where both are out of bounds and `b` is greater than `a`.
        let a = field.len();
        let b = a + 1;

        // Ensure `a` is out-of-bounds for test integrity.
        assert!(field.get(a).is_err());

        // Set `b` to `true`. Also, for test integrity, ensure it was previously out-of-bounds.
        assert!(field.set(b, true).is_none());

        // Ensure that `a` wasn't also set to `true` during the grow.
        assert_eq!(field.get(a), Ok(false));
        assert_eq!(field.get(b), Ok(true));
    }

    #[test]
    fn test_num_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_bytes(), 2);

        let field = BooleanBitfield::from_elem(2, true);
        assert_eq!(field.num_bytes(), 1);

        let field = BooleanBitfield::from_elem(13, true);
        assert_eq!(field.num_bytes(), 2);
    }

    #[test]
    fn test_ssz_encode() {
        let field = create_test_bitfield();

        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 2, 225, 192]);

        let field = BooleanBitfield::from_elem(18, true);
        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 3, 255, 255, 192]);
    }

    fn create_test_bitfield() -> BooleanBitfield {
        let count = 2 * 8;
        let mut field = BooleanBitfield::with_capacity(count);

        let indices = &[0, 1, 2, 7, 8, 9];
        for &i in indices {
            field.set(i, true);
        }
        field
    }

    #[test]
    fn test_ssz_decode() {
        let encoded = vec![0, 0, 0, 2, 225, 192];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = create_test_bitfield();
        assert_eq!(field, expected);

        let encoded = vec![0, 0, 0, 3, 255, 255, 3];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_bytes(&[255, 255, 3]);
        assert_eq!(field, expected);
    }

    #[test]
    fn test_ssz_round_trip() {
        let original = BooleanBitfield::from_bytes(&vec![18; 12][..]);
        let ssz = ssz_encode(&original);
        let (decoded, _) = BooleanBitfield::ssz_decode(&ssz, 0).unwrap();
        assert_eq!(original, decoded);
    }
}
<commit_msg>Add `BitAnd` impl for BooleanBitfield<commit_after>extern crate bit_vec;
extern crate ssz;

use bit_vec::BitVec;

use serde::ser::{Serialize, Serializer};
use std::cmp;
use std::default;

/// A BooleanBitfield represents a set of booleans compactly stored as a vector of bits.
/// The BooleanBitfield is given a fixed size during construction. Reads outside of the current size return an out-of-bounds error. Writes outside of the current size expand the size of the set.
#[derive(Debug, Clone)]
pub struct BooleanBitfield(BitVec);

/// Error represents some reason a request against a bitfield was not satisfied
#[derive(Debug, PartialEq)]
pub enum Error {
    /// OutOfBounds refers to indexing into a bitfield where no bits exist; returns the illegal index and the current size of the bitfield, respectively
    OutOfBounds(usize, usize),
}

impl BooleanBitfield {
    /// Create a new bitfield.
    pub fn new() -> Self {
        Default::default()
    }

    pub fn with_capacity(initial_len: usize) -> Self {
        Self::from_elem(initial_len, false)
    }

    /// Create a new bitfield with the given length `initial_len` and all values set to `bit`.
    pub fn from_elem(inital_len: usize, bit: bool) -> Self {
        Self {
            0: BitVec::from_elem(inital_len, bit),
        }
    }

    /// Create a new bitfield using the supplied `bytes` as input
    pub fn from_bytes(bytes: &[u8]) -> Self {
        Self {
            0: BitVec::from_bytes(bytes),
        }
    }

    /// Read the value of a bit.
    ///
    /// If the index is in bounds, then result is Ok(value) where value is `true` if the bit is 1 and `false` if the bit is 0.
    /// If the index is out of bounds, we return an error to that extent.
    pub fn get(&self, i: usize) -> Result<bool, Error> {
        match self.0.get(i) {
            Some(value) => Ok(value),
            None => Err(Error::OutOfBounds(i, self.0.len())),
        }
    }

    /// Set the value of a bit.
    ///
    /// If the index is out of bounds, we expand the size of the underlying set to include the new index.
    /// Returns the previous value if there was one.
    pub fn set(&mut self, i: usize, value: bool) -> Option<bool> {
        let previous = match self.get(i) {
            Ok(previous) => Some(previous),
            Err(Error::OutOfBounds(_, len)) => {
                let new_len = i - len + 1;
                self.0.grow(new_len, false);
                None
            }
        };
        self.0.set(i, value);
        previous
    }

    /// Returns the index of the highest set bit. Some(n) if some bit is set, None otherwise.
    pub fn highest_set_bit(&self) -> Option<usize> {
        self.0.iter().rposition(|bit| bit)
    }

    /// Returns the number of bits in this bitfield.
    pub fn len(&self) -> usize {
        self.0.len()
    }

    /// Returns the number of bytes required to represent this bitfield.
    pub fn num_bytes(&self) -> usize {
        self.to_bytes().len()
    }

    /// Returns the number of `1` bits in the bitfield
    pub fn num_set_bits(&self) -> usize {
        self.0.iter().filter(|&bit| bit).count()
    }

    /// Returns a vector of bytes representing the bitfield
    /// Note that this returns the bit layout of the underlying implementation in the `bit-vec` crate.
    pub fn to_bytes(&self) -> Vec<u8> {
        self.0.to_bytes()
    }
}

impl default::Default for BooleanBitfield {
    /// default provides the "empty" bitfield
    /// Note: the empty bitfield is set to the `0` byte.
    fn default() -> Self {
        Self::from_elem(8, false)
    }
}

impl cmp::PartialEq for BooleanBitfield {
    /// Determines equality by comparing the `ssz` encoding of the two candidates.
    /// This method ensures that the presence of high-order (empty) bits in the highest byte do not exclude equality when they are in fact representing the same information.
    fn eq(&self, other: &Self) -> bool {
        ssz::ssz_encode(self) == ssz::ssz_encode(other)
    }
}

/// Create a new bitfield that is a union of two other bitfields.
///
/// For example `union(0101, 1000) == 1101`
impl std::ops::BitAnd for BooleanBitfield {
    type Output = Self;

    fn bitand(self, other: Self) -> Self {
        let (biggest, smallest) = if self.len() > other.len() {
            (&self, &other)
        } else {
            (&other, &self)
        };
        let mut new = biggest.clone();
        for i in 0..smallest.len() {
            if let Ok(true) = smallest.get(i) {
                new.set(i, true);
            }
        }
        new
    }
}

impl ssz::Encodable for BooleanBitfield {
    // ssz_append encodes Self according to the `ssz` spec.
    fn ssz_append(&self, s: &mut ssz::SszStream) {
        s.append_vec(&self.to_bytes())
    }
}

impl ssz::Decodable for BooleanBitfield {
    fn ssz_decode(bytes: &[u8], index: usize) -> Result<(Self, usize), ssz::DecodeError> {
        let len = ssz::decode::decode_length(bytes, index, ssz::LENGTH_BYTES)?;
        if (ssz::LENGTH_BYTES + len) > bytes.len() {
            return Err(ssz::DecodeError::TooShort);
        }

        if len == 0 {
            Ok((BooleanBitfield::new(), index + ssz::LENGTH_BYTES))
        } else {
            let bytes = &bytes[(index + 4)..(index + len + 4)];

            let count = len * 8;
            let mut field = BooleanBitfield::with_capacity(count);
            for (byte_index, byte) in bytes.iter().enumerate() {
                for i in 0..8 {
                    let bit = byte & (128 >> i);
                    if bit != 0 {
                        field.set(8 * byte_index + i, true);
                    }
                }
            }

            let index = index + ssz::LENGTH_BYTES + len;
            Ok((field, index))
        }
    }
}

impl Serialize for BooleanBitfield {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_bytes(&ssz::ssz_encode(self))
    }
}

impl ssz::TreeHash for BooleanBitfield {
    fn hash_tree_root(&self) -> Vec<u8> {
        self.to_bytes().hash_tree_root()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use ssz::{ssz_encode, Decodable, SszStream};

    #[test]
    fn test_new_bitfield() {
        let mut field = BooleanBitfield::new();
        let original_len = field.len();

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }
    }

    #[test]
    fn test_empty_bitfield() {
        let mut field = BooleanBitfield::from_elem(0, false);
        let original_len = field.len();

        assert_eq!(original_len, 0);

        for i in 0..100 {
            if i < original_len {
                assert!(!field.get(i).unwrap());
            } else {
                assert!(field.get(i).is_err());
            }
            let previous = field.set(i, true);
            if i < original_len {
                assert!(!previous.unwrap());
            } else {
                assert!(previous.is_none());
            }
        }

        assert_eq!(field.len(), 100);
        assert_eq!(field.num_set_bits(), 100);
    }

    const INPUT: &[u8] = &[0b0000_0010, 0b0000_0010];

    #[test]
    fn test_get_from_bitfield() {
        let field = BooleanBitfield::from_bytes(INPUT);
        let unset = field.get(0).unwrap();
        assert!(!unset);
        let set = field.get(6).unwrap();
        assert!(set);
        let set = field.get(14).unwrap();
        assert!(set);
    }

    #[test]
    fn test_set_for_bitfield() {
        let mut field = BooleanBitfield::from_bytes(INPUT);
        let previous = field.set(10, true).unwrap();
        assert!(!previous);
        let previous = field.get(10).unwrap();
        assert!(previous);
        let previous = field.set(6, false).unwrap();
        assert!(previous);
        let previous = field.get(6).unwrap();
        assert!(!previous);
    }

    #[test]
    fn test_highest_set_bit() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.highest_set_bit().unwrap(), 14);

        let field = BooleanBitfield::from_bytes(&[0b0000_0011]);
        assert_eq!(field.highest_set_bit().unwrap(), 7);

        let field = BooleanBitfield::new();
        assert_eq!(field.highest_set_bit(), None);
    }

    #[test]
    fn test_len() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.len(), 16);

        let field = BooleanBitfield::new();
        assert_eq!(field.len(), 8);
    }

    #[test]
    fn test_num_set_bits() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_set_bits(), 2);

        let field = BooleanBitfield::new();
        assert_eq!(field.num_set_bits(), 0);
    }

    #[test]
    fn test_to_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.to_bytes(), INPUT);

        let field = BooleanBitfield::new();
        assert_eq!(field.to_bytes(), vec![0]);
    }

    #[test]
    fn test_out_of_bounds() {
        let mut field = BooleanBitfield::from_bytes(INPUT);

        let out_of_bounds_index = field.len();
        assert!(field.set(out_of_bounds_index, true).is_none());
        assert!(field.len() == out_of_bounds_index + 1);
        assert!(field.get(out_of_bounds_index).unwrap());

        for i in 0..100 {
            if i <= out_of_bounds_index {
                assert!(field.set(i, true).is_some());
            } else {
                assert!(field.set(i, true).is_none());
            }
        }
    }

    #[test]
    fn test_grows_with_false() {
        let input_all_set: &[u8] = &[0b1111_1111, 0b1111_1111];
        let mut field = BooleanBitfield::from_bytes(input_all_set);

        // Define `a` and `b`, where both are out of bounds and `b` is greater than `a`.
        let a = field.len();
        let b = a + 1;

        // Ensure `a` is out-of-bounds for test integrity.
        assert!(field.get(a).is_err());

        // Set `b` to `true`. Also, for test integrity, ensure it was previously out-of-bounds.
        assert!(field.set(b, true).is_none());

        // Ensure that `a` wasn't also set to `true` during the grow.
        assert_eq!(field.get(a), Ok(false));
        assert_eq!(field.get(b), Ok(true));
    }

    #[test]
    fn test_num_bytes() {
        let field = BooleanBitfield::from_bytes(INPUT);
        assert_eq!(field.num_bytes(), 2);

        let field = BooleanBitfield::from_elem(2, true);
        assert_eq!(field.num_bytes(), 1);

        let field = BooleanBitfield::from_elem(13, true);
        assert_eq!(field.num_bytes(), 2);
    }

    #[test]
    fn test_ssz_encode() {
        let field = create_test_bitfield();

        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 2, 225, 192]);

        let field = BooleanBitfield::from_elem(18, true);
        let mut stream = SszStream::new();
        stream.append(&field);
        assert_eq!(stream.drain(), vec![0, 0, 0, 3, 255, 255, 192]);
    }

    fn create_test_bitfield() -> BooleanBitfield {
        let count = 2 * 8;
        let mut field = BooleanBitfield::with_capacity(count);

        let indices = &[0, 1, 2, 7, 8, 9];
        for &i in indices {
            field.set(i, true);
        }
        field
    }

    #[test]
    fn test_ssz_decode() {
        let encoded = vec![0, 0, 0, 2, 225, 192];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = create_test_bitfield();
        assert_eq!(field, expected);

        let encoded = vec![0, 0, 0, 3, 255, 255, 3];
        let (field, _): (BooleanBitfield, usize) = ssz::decode_ssz(&encoded, 0).unwrap();
        let expected = BooleanBitfield::from_bytes(&[255, 255, 3]);
        assert_eq!(field, expected);
    }

    #[test]
    fn test_ssz_round_trip() {
        let original = BooleanBitfield::from_bytes(&vec![18; 12][..]);
        let ssz = ssz_encode(&original);
        let (decoded, _) = BooleanBitfield::ssz_decode(&ssz, 0).unwrap();
        assert_eq!(original, decoded);
    }

    #[test]
    fn test_bitand() {
        let a = BooleanBitfield::from_bytes(&vec![2, 8, 1][..]);
        let b = BooleanBitfield::from_bytes(&vec![4, 8, 16][..]);
        let c = BooleanBitfield::from_bytes(&vec![6, 8, 17][..]);
        assert_eq!(c, a & b);
    }
}
<|endoftext|>


<commit_before><commit_msg>Info on traits<commit_after><|endoftext|>


<commit_before>#[macro_export]
macro_rules! __inst_gen_bf {
    (
        $itop:expr, [ {$fpart:expr}.$fwidth:expr $(; $part:tt.$width:expr)* ],
                    { $($spart:ident: $splow:expr => $sphi:expr),* }, $ty:ty
    ) => (
        // Move counter but otherwise pass it right through
        __inst_gen_bf!($itop - $fwidth, [ $($part.$width);* ],
                                        { $($spart: $splow => $sphi),* }, $ty);
    );

    (
        $itop:expr, [ {}.$fwidth:expr $(; $part:tt.$width:expr)* ],
                    { $($spart:ident: $splow:expr => $sphi:expr),* }, $ty:ty
    ) => (
        // Move counter but otherwise pass it right through
        __inst_gen_bf!($itop - $fwidth, [ $($part.$width);* ],
                                        { $($spart: $splow => $sphi),* }, $ty);
    );

    (
        $itop:expr, [ $fpart:tt.$fwidth:expr $(; $part:tt.$width:expr)* ],
                    { $($spart:ident: $splow:expr => $sphi:expr),* }, $ty:ty
    ) => (
        __inst_gen_bf!($itop - $fwidth, [ $($part.$width);* ], {
                                            $($spart: $splow => $sphi,)*
                                            $fpart: ($itop - $fwidth) => ($itop - 1)
                                        }, $ty);
    );

    (
        $itop:expr, [ ], { $($spart:ident: $splow:expr => $sphi:expr),* }, $ty:ty
    ) => (
        bitfield!(InstrDesc: $ty, {
            $($spart: $splow => $sphi),*
        });
    )
}

#[macro_export]
macro_rules! __inst_gen_decode {
    (
        $itop:expr, [ {$fpart:expr}.$fwidth:expr $(; $part:tt.$width:expr)* ], $mask:expr, $test:expr, $ty:ty
    ) => (
        __inst_gen_decode!($itop - $fwidth, [ $($part.$width);* ],
                           $mask | (bits!(!0 as $ty,     0 => ($fwidth - 1)) << ($itop - $fwidth)),
                           $test | (bits!($fpart as $ty, 0 => ($fwidth - 1)) << ($itop - $fwidth)), $ty);
    );

    (
        $itop:expr, [ $fpart:tt.$fwidth:expr $(; $part:tt.$width:expr)* ], $mask:expr, $test:expr, $ty:ty
    ) => (
        // Move counter but otherwise pass it right through
        __inst_gen_decode!($itop - $fwidth, [ $($part.$width);* ], $mask, $test, $ty);
    );

    (
        $itop:expr, [ {}.$fwidth:expr $(; $part:tt.$width:expr)* ], $mask:expr, $test:expr, $ty:ty
    ) => (
        // Move counter but otherwise pass it right through
        __inst_gen_decode!($itop - $fwidth, [ $($part.$width);* ], $mask, $test, $ty);
    );

    (
        $itop:expr, [ ], $mask:expr, $test:expr, $ty:ty
    ) => (
        #[inline(always)]
        pub fn decodable(encoding: $ty) -> bool {
            assert!($itop == 0, format!("{} encoded bits do not add up!", module_path!()));
            encoding & $mask == $test
        }
    )
}

#[macro_export]
macro_rules! define_inst {
    ($name:ident: $ty:ty, $($part:tt.$width:expr);* ) => (
        pub mod $name {
            __inst_gen_bf!(::std::mem::size_of::<$ty>()*8, [ $($part.$width);* ], { }, $ty);
            __inst_gen_decode!(::std::mem::size_of::<$ty>()*8, [ $($part.$width);* ], 0, 0, $ty);
        }
    )
}

#[macro_export]
macro_rules! define_insts {
    ($enumname:ident: $ty:ty, {
        $(
            with $([ $($wpart:tt.$wwidth:expr);* ])or*
            {
                $( $name:ident: [ $($part:tt.$width:expr);* ] ),*
            }
        )*
    }) => (
        $($( define_inst!($name: $ty, $($part.$width);*); )*)*

        #[derive(Debug)]
        #[allow(non_camel_case_types)]
        pub enum $enumname {
            $($( $name($name::InstrDesc), )*)*
            Unknown
        }

        impl $enumname {
            pub fn decode(encoding: $ty) -> $enumname {
                $(
                    if $({ __inst_gen_decode!(::std::mem::size_of::<$ty>()*8, [ $($wpart.$wwidth);* ], 0, 0, $ty);
                         decodable(encoding) })||* {
                    $(
                        if $name::decodable(encoding) {
                            return $enumname::$name($name::InstrDesc::new(encoding))
                        }
                    )*
                    }
                )*

                $enumname::Unknown
            }
        }
    )
}

#[cfg(test)]
mod test {
    define_inst!(add_1: u16, {0b0001110}.7;immed_3.3;rn.3;rd.3);
    define_inst!(ldrh: u32, cond.4; {0b000}.3; p_bit.1; u_bit.1; i_bit.1; w_bit.1;
                            {0b1}.1; rn.4; rd.4; addr_mode.4; {0b1011}.4; addr_mode_.4);

    #[test]
    fn decode_add1() {
        assert!(add_1::try_decode(0b0001110000000000).is_some());
        assert!(add_1::try_decode(0b0011110000000000).is_none());
    }

    #[test]
    fn decode_ldrh() {
        let desc = ldrh::try_decode(0b11100000110101001001000010110100).unwrap();
        assert_eq!(bf!(desc.cond), 0b1110);
        assert_eq!(bf!(desc.rn), 4);
        assert_eq!(bf!(desc.rd), 9);
        assert!(ldrh::try_decode(0b11100000110101001001000011110100).is_none());
    }
}<commit_msg>define_inst: Add some documentation<commit_after>#[macro_export]
macro_rules! __inst_gen_bf {
    // We don't care about the value (`{val}.n`) parts. Reduces item list. Reduces $itop to next item.
    (
        $itop:expr, [ {$fpart:expr}.$fwidth:expr $(; $part:tt.$width:expr)* ],
                    { $($spart:ident: $splow:expr => $sphi:expr),* }, $ty:ty
    ) => (
        // Move counter but otherwise pass it right through
        __inst_gen_bf!($itop - $fwidth, [ $($part.$width);* ],
                                        { $($spart: $splow => $sphi),* }, $ty);
    );

    // Skip filler (`{}.n`) parts. Reduces item list. Reduces $itop to next item.
    (
        $itop:expr, [ {}.$fwidth:expr $(; $part:tt.$width:expr)* ],
                    { $($spart:ident: $splow:expr => $sphi:expr),* }, $ty:ty
    ) => (
        // Move counter but otherwise pass it right through
        __inst_gen_bf!($itop - $fwidth, [ $($part.$width);* ],
                                        { $($spart: $splow => $sphi),* }, $ty);
    );

    // From named (`foo.n`) parts, accumulate top and bottom bits into position list.
    // Reduces item list. Reduces $itop to next item.
    (
        $itop:expr, [ $fpart:tt.$fwidth:expr $(; $part:tt.$width:expr)* ],
                    { $($spart:ident: $splow:expr => $sphi:expr),* }, $ty:ty
    ) => (
        __inst_gen_bf!($itop - $fwidth, [ $($part.$width);* ], {
                                            $($spart: $splow => $sphi,)*
                                            $fpart: ($itop - $fwidth) => ($itop - 1)
                                        }, $ty);
    );

    // Once item list is empty, finally produce our end result: the `InstrDesc` bitfield.
    (
        $itop:expr, [ ], { $($spart:ident: $splow:expr => $sphi:expr),* }, $ty:ty
    ) => (
        bitfield!(InstrDesc: $ty, {
            $($spart: $splow => $sphi),*
        });
    )
}

#[macro_export]
macro_rules! __inst_gen_decode {
    // ORs value (`{val}.n`) at position into $test, mask of value into $mask. Reduces item list.
    // Reduces $itop to next item.
    (
        $itop:expr, [ {$fpart:expr}.$fwidth:expr $(; $part:tt.$width:expr)* ], $mask:expr, $test:expr, $ty:ty
    ) => (
        __inst_gen_decode!($itop - $fwidth, [ $($part.$width);* ],
                           $mask | (bits!(!0 as $ty,     0 => ($fwidth - 1)) << ($itop - $fwidth)),
                           $test | (bits!($fpart as $ty, 0 => ($fwidth - 1)) << ($itop - $fwidth)), $ty);
    );

    // We don't care about the named (`foo.n`) parts. Reduces item list. Reduces $itop to next item.
    (
        $itop:expr, [ $fpart:tt.$fwidth:expr $(; $part:tt.$width:expr)* ], $mask:expr, $test:expr, $ty:ty
    ) => (
        // Move counter but otherwise pass it right through
        __inst_gen_decode!($itop - $fwidth, [ $($part.$width);* ], $mask, $test, $ty);
    );

    // Skip filler (`{}.n`) parts. Reduces item list. Reduces $itop to next item.
    (
        $itop:expr, [ {}.$fwidth:expr $(; $part:tt.$width:expr)* ], $mask:expr, $test:expr, $ty:ty
    ) => (
        // Move counter but otherwise pass it right through
        __inst_gen_decode!($itop - $fwidth, [ $($part.$width);* ], $mask, $test, $ty);
    );

    // Once item list is empty, finally produce our end result: the `decodable` function.
    (
        $itop:expr, [ ], $mask:expr, $test:expr, $ty:ty
    ) => (
        #[inline(always)]
        pub fn decodable(encoding: $ty) -> bool {
            assert!($itop == 0, format!("{} encoded bits do not add up!", module_path!()));
            encoding & $mask == $test
        }
    )
}

#[macro_export]
macro_rules! define_inst {
    ($name:ident: $ty:ty, $($part:tt.$width:expr);* ) => (
        pub mod $name {
            __inst_gen_bf!(::std::mem::size_of::<$ty>()*8, [ $($part.$width);* ], { }, $ty);
            __inst_gen_decode!(::std::mem::size_of::<$ty>()*8, [ $($part.$width);* ], 0, 0, $ty);
        }
    )
}

// Usage:
// define_insts!(Foo: ty {
//     with [ constraints ]
//       or [ constraints ]...
//     {
//         bar: [ constraints ],...
//     }
//     ...
// });
#[macro_export]
macro_rules! define_insts {
    ($enumname:ident: $ty:ty, {
        $(
            with $([ $($wpart:tt.$wwidth:expr);* ])or*
            {
                $( $name:ident: [ $($part:tt.$width:expr);* ] ),*
            }
        )*
    }) => (
        $($( define_inst!($name: $ty, $($part.$width);*); )*)*

        #[derive(Debug)]
        #[allow(non_camel_case_types)]
        pub enum $enumname {
            $($( $name($name::InstrDesc), )*)*
            Unknown
        }

        impl $enumname {
            pub fn decode(encoding: $ty) -> $enumname {
                $(
                    if $({ __inst_gen_decode!(::std::mem::size_of::<$ty>()*8, [ $($wpart.$wwidth);* ], 0, 0, $ty);
                         decodable(encoding) })||* {
                    $(
                        if $name::decodable(encoding) {
                            return $enumname::$name($name::InstrDesc::new(encoding))
                        }
                    )*
                    }
                )*

                $enumname::Unknown
            }
        }
    )
}

#[cfg(test)]
mod test {
    define_inst!(add_1: u16, {0b0001110}.7;immed_3.3;rn.3;rd.3);
    define_inst!(ldrh: u32, cond.4; {0b000}.3; p_bit.1; u_bit.1; i_bit.1; w_bit.1;
                            {0b1}.1; rn.4; rd.4; addr_mode.4; {0b1011}.4; addr_mode_.4);

    #[test]
    fn decode_add1() {
        assert!(add_1::try_decode(0b0001110000000000).is_some());
        assert!(add_1::try_decode(0b0011110000000000).is_none());
    }

    #[test]
    fn decode_ldrh() {
        let desc = ldrh::try_decode(0b11100000110101001001000010110100).unwrap();
        assert_eq!(bf!(desc.cond), 0b1110);
        assert_eq!(bf!(desc.rn), 4);
        assert_eq!(bf!(desc.rd), 9);
        assert!(ldrh::try_decode(0b11100000110101001001000011110100).is_none());
    }
}<|endoftext|>


<commit_before>use byteorder::{BigEndian, ReaderBytesExt, WriterBytesExt};

use rustc_serialize::Encodable;
use rustc_serialize::Encoder;
use rustc_serialize::json;

use openssl;
use openssl::ssl;
use openssl::ssl::SslStream;
use openssl::ssl::error::SslError;

use std::cell::RefCell;
use std::num::Int;
use std::ops::{Range, Index};
use std::old_io::net;
use std::old_io::net::ip::SocketAddr;
use std::old_io::{TcpStream, MemReader};
use std::old_path::posix::Path;
use std::collections::HashMap;

use rand::{self, Rng};
use time;

#[derive(Debug)]
pub struct Payload<'a> {
	pub aps: PayloadAPS<'a>,
	pub info: Option<HashMap<&'a str, &'a str>>
}

#[derive(Debug)]
pub struct PayloadAPS<'a> {
	pub alert: PayloadAPSAlert<'a>,
	pub badge: Option<i32>,
	pub sound: Option<&'a str>,
	pub content_available: Option<i32>
}

#[derive(Debug)]
pub enum PayloadAPSAlert<'a> {
	Plain(&'a str),
	Localized(&'a str, Vec<&'a str>)
}

impl<'a> Encodable for Payload<'a> {
	fn encode<S: Encoder>(&self, encoder: &mut S) -> Result<(), S::Error> {
	    match *self {
			Payload{ref aps, ref info} => {
				if let Some(ref map) = *info {
	    	        encoder.emit_struct("Payload", 1 + map.len(), |encoder| {
						try!(encoder.emit_struct_field( "aps", 0usize, |encoder| aps.encode(encoder)));
						let mut index = 1usize;
						for (key, val) in map.iter() {
							try!(encoder.emit_struct_field(key, index, |encoder| val.encode(encoder)));
							index = index + 1;
						}
						Ok(())
	    	        })
				}
				else {
	    	        encoder.emit_struct("Payload", 1, |encoder| {
						try!(encoder.emit_struct_field( "aps", 0usize, |encoder| aps.encode(encoder)));
						Ok(())
	    	        })
				}
			}
		}
	}
}

impl<'a> Encodable for PayloadAPS<'a> {
	fn encode<S: Encoder>(&self, encoder: &mut S) -> Result<(), S::Error> {
	    match *self {
			PayloadAPS{ref alert, ref badge, ref sound, ref content_available} => {
				let mut count = 1;
				if badge.is_some() { count = count + 1; }
				if sound.is_some() { count = count + 1; }
				if content_available.is_some() { count = count + 1; }

				let mut index = 0usize;
    	        encoder.emit_struct("PayloadAPS", count, |encoder| {
					try!(encoder.emit_struct_field( "alert", index, |encoder| alert.encode(encoder)));
					index = index + 1;
					if badge.is_some() {
						try!(encoder.emit_struct_field( "badge", index, |encoder| badge.unwrap().encode(encoder)));
						index = index + 1;
					}
					if sound.is_some() {
						try!(encoder.emit_struct_field( "sound", index, |encoder| sound.unwrap().encode(encoder)));
						index = index + 1;
					}
					if content_available.is_some() {
						try!(encoder.emit_struct_field( "content-available", index, |encoder| content_available.unwrap().encode(encoder)));
						index = index + 1;
					}
					Ok(())
    	        })
			}
		}
	}
}

impl<'a> Encodable for PayloadAPSAlert<'a> {
	fn encode<S: Encoder>(&self, encoder: &mut S) -> Result<(), S::Error> {
	    match *self {
			PayloadAPSAlert::Plain(ref str) => {
    	        encoder.emit_str(str)
			},
			PayloadAPSAlert::Localized(ref key, ref args) => {
    	        encoder.emit_struct("PayloadAPSAlert", 2, |encoder| {
					try!(encoder.emit_struct_field( "loc-key", 0usize, |encoder| key.encode(encoder)));
					try!(encoder.emit_struct_field( "loc-args", 1usize, |encoder| args.encode(encoder)));
					Ok(())
				})
			}
		}
	}
}

#[allow(dead_code)]
fn hex_to_int(hex: &str) -> u32 {
	let mut total = 0u32;
	let mut n = hex.to_string().len() - 1;

	for c in hex.chars() {
		match c {
			'0'...'9' => {
				total += 16.pow(n) * ((c as u32) - ('0' as u32));
			},
			'a'...'f' => {
				total += 16.pow(n) * ((c as u32) - ('a' as u32) + 10);
			},
			_ => {
			}
		}
		n = n - 1;
	}

	return total;
}

#[allow(dead_code)]
fn convert_to_binary(device_token: &str) -> Vec<u8> {
	let mut device_token_bytes: Vec<u8> = vec![];
	for i in 0..8 {
		let string = device_token.to_string();
		let range = Range{start:i*8, end:i*8+8};
		let sub_str = string.index(&range);

		let sub_str_num = hex_to_int(sub_str);
		let mut sub_str_bytes = vec![];
		let _ = sub_str_bytes.write_u32::<BigEndian>(sub_str_num);

		device_token_bytes.push_all(sub_str_bytes.as_slice());
	}

	return device_token_bytes;
}

#[allow(dead_code)]
pub fn convert_to_token(binary: &[u8]) -> String {
	let mut token = "".to_string();
	for i in 0..8 {
		let range = Range{start:i*4, end:i*4+4};
		let sub_slice = binary.index(&range);

		let mut rdr = MemReader::new(sub_slice.to_vec());
		let num = rdr.read_u32::<BigEndian>().unwrap();

		token = format!("{}{:x}", token, num);
	}
	return token;
}

#[allow(dead_code)]
pub fn convert_to_timestamp(binary: &[u8]) -> u32 {
	let mut rdr = MemReader::new(binary.to_vec());
	let num = rdr.read_u32::<BigEndian>().unwrap();

	return num;
}

pub struct APNS {
	pub sandbox: bool,
	pub certificate: Path,
	pub private_key: Path,
	pub ca_certificate: Path,
	pub ssl_stream: RefCell<Option<SslStream<TcpStream>>>
}

impl APNS {
	pub fn new(sandbox: bool, cert_file: Path, private_key_file: Path, ca_file: Path) -> APNS {
		APNS{sandbox: sandbox, certificate: cert_file, private_key: private_key_file, ca_certificate: ca_file, ssl_stream: RefCell::new(None)}
	}

	#[allow(dead_code)]
    pub fn get_feedback(&self) -> Result<Vec<(u32, String)>, SslError> {
		let apns_feedback_production = "feedback.push.apple.com";
		let apns_feedback_development = "feedback.sandbox.push.apple.com";
		let feedback_port = 2196;

		let apns_feedback_url = if self.sandbox { apns_feedback_development } else { apns_feedback_production };
		let mut stream = try!(get_ssl_stream(apns_feedback_url, feedback_port, &self.certificate, &self.private_key, &self.ca_certificate));

		let mut tokens: Vec<(u32, String)> = Vec::new();
        loop {
			let mut read_buffer = [0u8; 38];
			if let Err(..) = stream.read(&mut read_buffer) {
				break;
/*				return Result::Err(SslError::StreamError(error));*/
            }

			let time_range = Range{start:0, end:4};
			let time_slice = read_buffer.index(&time_range);
			let time = convert_to_timestamp(time_slice);

			let token_range = Range{start:6, end:38};
			let token_slice = read_buffer.index(&token_range);
            let token = convert_to_token(token_slice);

			tokens.push((time, token));
        }

        return Result::Ok(tokens);
    }

	#[allow(dead_code)]
	pub fn send_payload(&self, payload: Payload, device_token: &str) {
		let payload_str = match json::encode(&payload) {
			Ok(json_str) => { json_str.to_string() }
			_ => { return; }
		};

		let payload_bytes = payload_str.into_bytes();
		let device_token_bytes: Vec<u8> = convert_to_binary(device_token);

		let mut notification_buffer: Vec<u8> = vec![];
		let mut message_buffer: Vec<u8> = vec![];

		// Device token
		let mut device_token_length = vec![];
		let _ = device_token_length.write_u16::<BigEndian>(device_token_bytes.len() as u16);

		message_buffer.push(1u8);
		message_buffer.push_all(device_token_length.as_slice());
		message_buffer.push_all(device_token_bytes.as_slice());

		// Payload
		let mut payload_length = vec![];
		let _ = payload_length.write_u16::<BigEndian>(payload_bytes.len() as u16);

		message_buffer.push(2u8);
		message_buffer.push_all(payload_length.as_slice());
		message_buffer.push_all(payload_bytes.as_slice());

		// Notification identifier
		let payload_id = rand::thread_rng().gen();
		let mut payload_id_be = vec![];
		let _ = payload_id_be.write_u32::<BigEndian>(payload_id);

		let mut payload_id_length = vec![];
		let _ = payload_id_length.write_u16::<BigEndian>(payload_id_be.len() as u16);

		message_buffer.push(3u8);
		message_buffer.push_all(payload_id_length.as_slice());
		message_buffer.push_all(payload_id_be.as_slice());

		//	Expiration date
		let time = time::now().to_timespec().sec + 86400;	// expired after one day
		let mut exp_date_be = vec![];
		let _ = exp_date_be.write_u32::<BigEndian>(time as u32);

		let mut exp_date_length = vec![];
		let _ = exp_date_length.write_u16::<BigEndian>(exp_date_be.len() as u16);

		message_buffer.push(4u8);
		message_buffer.push_all(exp_date_length.as_slice());
		message_buffer.push_all(exp_date_be.as_slice());

		// Priority
		let mut priority_length = vec![];
		let _ = priority_length.write_u16::<BigEndian>(1u16);

		message_buffer.push(5u8);
		message_buffer.push_all(priority_length.as_slice());
		message_buffer.push(10u8);

		let mut message_buffer_length = vec![];
		let _ = message_buffer_length.write_u32::<BigEndian>(message_buffer.len() as u32);

		let command = 2u8;
		notification_buffer.push(command);
		notification_buffer.push_all(message_buffer_length.as_slice());
		notification_buffer.push_all(message_buffer.as_slice());

		let should_init_ssl_stream = self.ssl_stream.borrow().is_none();

		if should_init_ssl_stream {
			self.init_push_ssl_stream();
		}
		else {
			if let Some(ssl_stream) = self.ssl_stream.borrow_mut().as_mut() {
				while let Err(error) = ssl_stream.write_all(&notification_buffer) {
					println!("ssl_stream write error {:?}", error);
/*		            self.init_push_ssl_stream();*/
				}

				// Response error code
				/*let mut read_buffer = [0u8; 6];
				println!("SslStream read {:?}", ssl_stream.read(&mut read_buffer));

				for c in read_buffer.iter() {
					print!("{}", c);
				}
				println!("");*/
			}
		}
	}

	fn init_push_ssl_stream(&self) {
		let mut borrow_ssl_stream = self.ssl_stream.borrow_mut();

		let apns_url_production = "gateway.push.apple.com";
		let apns_url_development = "gateway.sandbox.push.apple.com";
		let apns_port = 2195;

		let apns_url = if self.sandbox { apns_url_development } else { apns_url_production };

		*borrow_ssl_stream = Some(get_ssl_stream(apns_url, apns_port, &self.certificate, &self.private_key, &self.ca_certificate).unwrap());
	}
}

fn get_ssl_stream(url: &str, port: u16, cert_file: &Path, private_key_file: &Path, ca_file: &Path) -> Result<SslStream<TcpStream>, SslError> {
	let mut context = try!(ssl::SslContext::new(ssl::SslMethod::Sslv23));

	if let Some(error) = context.set_CA_file(&ca_file) {
		println!("set_CA_file error {:?}", error);
	}
	if let Some(error) = context.set_certificate_file(&cert_file, openssl::x509::X509FileType::PEM) {
		println!("set_certificate_file error {:?}", error);
	}
	if let Some(error) = context.set_private_key_file(&private_key_file, openssl::x509::X509FileType::PEM) {
		println!("set_private_key_file error {:?}", error);
	}

	let apns_ip = match net::addrinfo::get_host_addresses(url) {
		Ok(results) => { results[0] },
		Err(error) => {
			return Result::Err(SslError::StreamError(error));
		}
	};

	let sock_addr = SocketAddr{ip: apns_ip, port: port};
    let tcp_conn = match TcpStream::connect(sock_addr) {
		Ok(conn) => { conn },
		Err(error) => {
			return Result::Err(SslError::StreamError(error));
		}
	};

	let ssl = try!(ssl::Ssl::new(&context));

	return SslStream::new_from(ssl, tcp_conn);
}

<commit_msg>bugs fixed<commit_after>use byteorder::{BigEndian, ReaderBytesExt, WriterBytesExt};

use rustc_serialize::Encodable;
use rustc_serialize::Encoder;
use rustc_serialize::json;

use openssl;
use openssl::ssl;
use openssl::ssl::SslStream;
use openssl::ssl::error::SslError;

use std::cell::RefCell;
use std::num::Int;
use std::ops::{Range, Index};
use std::old_io::net;
use std::old_io::net::ip::SocketAddr;
use std::old_io::{TcpStream, MemReader};
use std::old_path::posix::Path;
use std::collections::HashMap;

use rand::{self, Rng};
use time;

#[derive(Debug)]
pub struct Payload<'a> {
	pub aps: PayloadAPS<'a>,
	pub info: Option<HashMap<&'a str, &'a str>>
}

#[derive(Debug)]
pub struct PayloadAPS<'a> {
	pub alert: PayloadAPSAlert<'a>,
	pub badge: Option<i32>,
	pub sound: Option<&'a str>,
	pub content_available: Option<i32>
}

#[derive(Debug)]
pub enum PayloadAPSAlert<'a> {
	Plain(&'a str),
	Localized(&'a str, Vec<&'a str>)
}

impl<'a> Encodable for Payload<'a> {
	fn encode<S: Encoder>(&self, encoder: &mut S) -> Result<(), S::Error> {
	    match *self {
			Payload{ref aps, ref info} => {
				if let Some(ref map) = *info {
	    	        encoder.emit_struct("Payload", 1 + map.len(), |encoder| {
						try!(encoder.emit_struct_field( "aps", 0usize, |encoder| aps.encode(encoder)));
						let mut index = 1usize;
						for (key, val) in map.iter() {
							try!(encoder.emit_struct_field(key, index, |encoder| val.encode(encoder)));
							index = index + 1;
						}
						Ok(())
	    	        })
				}
				else {
	    	        encoder.emit_struct("Payload", 1, |encoder| {
						try!(encoder.emit_struct_field( "aps", 0usize, |encoder| aps.encode(encoder)));
						Ok(())
	    	        })
				}
			}
		}
	}
}

impl<'a> Encodable for PayloadAPS<'a> {
	fn encode<S: Encoder>(&self, encoder: &mut S) -> Result<(), S::Error> {
	    match *self {
			PayloadAPS{ref alert, ref badge, ref sound, ref content_available} => {
				let mut count = 1;
				if badge.is_some() { count = count + 1; }
				if sound.is_some() { count = count + 1; }
				if content_available.is_some() { count = count + 1; }

				let mut index = 0usize;
    	        encoder.emit_struct("PayloadAPS", count, |encoder| {
					try!(encoder.emit_struct_field( "alert", index, |encoder| alert.encode(encoder)));
					index = index + 1;
					if badge.is_some() {
						try!(encoder.emit_struct_field( "badge", index, |encoder| badge.unwrap().encode(encoder)));
						index = index + 1;
					}
					if sound.is_some() {
						try!(encoder.emit_struct_field( "sound", index, |encoder| sound.unwrap().encode(encoder)));
						index = index + 1;
					}
					if content_available.is_some() {
						try!(encoder.emit_struct_field( "content-available", index, |encoder| content_available.unwrap().encode(encoder)));
						index = index + 1;
					}
					Ok(())
    	        })
			}
		}
	}
}

impl<'a> Encodable for PayloadAPSAlert<'a> {
	fn encode<S: Encoder>(&self, encoder: &mut S) -> Result<(), S::Error> {
	    match *self {
			PayloadAPSAlert::Plain(ref str) => {
    	        encoder.emit_str(str)
			},
			PayloadAPSAlert::Localized(ref key, ref args) => {
    	        encoder.emit_struct("PayloadAPSAlert", 2, |encoder| {
					try!(encoder.emit_struct_field( "loc-key", 0usize, |encoder| key.encode(encoder)));
					try!(encoder.emit_struct_field( "loc-args", 1usize, |encoder| args.encode(encoder)));
					Ok(())
				})
			}
		}
	}
}

#[allow(dead_code)]
fn hex_to_int(hex: &str) -> u32 {
	let mut total = 0u32;
	let mut n = hex.to_string().len() - 1;

	for c in hex.chars() {
		match c {
			'0'...'9' => {
				total += 16.pow(n) * ((c as u32) - ('0' as u32));
			},
			'a'...'f' => {
				total += 16.pow(n) * ((c as u32) - ('a' as u32) + 10);
			},
			_ => {
			}
		}
		n = n - 1;
	}

	return total;
}

#[allow(dead_code)]
fn convert_to_binary(device_token: &str) -> Vec<u8> {
	let mut device_token_bytes: Vec<u8> = vec![];
	for i in 0..8 {
		let string = device_token.to_string();
		let range = Range{start:i*8, end:i*8+8};
		let sub_str = string.index(&range);

		let sub_str_num = hex_to_int(sub_str);
		let mut sub_str_bytes = vec![];
		let _ = sub_str_bytes.write_u32::<BigEndian>(sub_str_num);

		device_token_bytes.push_all(sub_str_bytes.as_slice());
	}

	return device_token_bytes;
}

#[allow(dead_code)]
pub fn convert_to_token(binary: &[u8]) -> String {
	let mut token = "".to_string();
	for i in 0..8 {
		let range = Range{start:i*4, end:i*4+4};
		let sub_slice = binary.index(&range);

		let mut rdr = MemReader::new(sub_slice.to_vec());
		let num = rdr.read_u32::<BigEndian>().unwrap();

		token = format!("{}{:x}", token, num);
	}
	return token;
}

#[allow(dead_code)]
pub fn convert_to_timestamp(binary: &[u8]) -> u32 {
	let mut rdr = MemReader::new(binary.to_vec());
	let num = rdr.read_u32::<BigEndian>().unwrap();

	return num;
}

pub struct APNS {
	pub sandbox: bool,
	pub certificate: Path,
	pub private_key: Path,
	pub ca_certificate: Path,
	pub ssl_stream: RefCell<SslStream<TcpStream>>
}

impl APNS {
	pub fn new(sandbox: bool, cert_file: Path, private_key_file: Path, ca_file: Path) -> APNS {
		let apns_url_production = "gateway.push.apple.com";
		let apns_url_development = "gateway.sandbox.push.apple.com";
		let apns_port = 2195;

		let apns_url = if sandbox { apns_url_development } else { apns_url_production };

		let ssl_stream = RefCell::new(get_ssl_stream(apns_url, apns_port, &cert_file, &private_key_file, &ca_file).unwrap());
		APNS{sandbox: sandbox, certificate: cert_file, private_key: private_key_file, ca_certificate: ca_file, ssl_stream: ssl_stream}
	}

	#[allow(dead_code)]
    pub fn get_feedback(&self) -> Result<Vec<(u32, String)>, SslError> {
		let apns_feedback_production = "feedback.push.apple.com";
		let apns_feedback_development = "feedback.sandbox.push.apple.com";
		let feedback_port = 2196;

		let apns_feedback_url = if self.sandbox { apns_feedback_development } else { apns_feedback_production };
		let mut stream = try!(get_ssl_stream(apns_feedback_url, feedback_port, &self.certificate, &self.private_key, &self.ca_certificate));

		let mut tokens: Vec<(u32, String)> = Vec::new();
        loop {
			let mut read_buffer = [0u8; 38];
			if let Err(..) = stream.read(&mut read_buffer) {
				break;
/*				return Result::Err(SslError::StreamError(error));*/
            }

			let time_range = Range{start:0, end:4};
			let time_slice = read_buffer.index(&time_range);
			let time = convert_to_timestamp(time_slice);

			let token_range = Range{start:6, end:38};
			let token_slice = read_buffer.index(&token_range);
            let token = convert_to_token(token_slice);

			tokens.push((time, token));
        }

        return Result::Ok(tokens);
    }

	#[allow(dead_code)]
	pub fn send_payload(&self, payload: Payload, device_token: &str) {
		let payload_str = match json::encode(&payload) {
			Ok(json_str) => { json_str.to_string() }
			_ => { return; }
		};

		let payload_bytes = payload_str.into_bytes();
		let device_token_bytes: Vec<u8> = convert_to_binary(device_token);

		let mut notification_buffer: Vec<u8> = vec![];
		let mut message_buffer: Vec<u8> = vec![];

		// Device token
		let mut device_token_length = vec![];
		let _ = device_token_length.write_u16::<BigEndian>(device_token_bytes.len() as u16);

		message_buffer.push(1u8);
		message_buffer.push_all(device_token_length.as_slice());
		message_buffer.push_all(device_token_bytes.as_slice());

		// Payload
		let mut payload_length = vec![];
		let _ = payload_length.write_u16::<BigEndian>(payload_bytes.len() as u16);

		message_buffer.push(2u8);
		message_buffer.push_all(payload_length.as_slice());
		message_buffer.push_all(payload_bytes.as_slice());

		// Notification identifier
		let payload_id = rand::thread_rng().gen();
		let mut payload_id_be = vec![];
		let _ = payload_id_be.write_u32::<BigEndian>(payload_id);

		let mut payload_id_length = vec![];
		let _ = payload_id_length.write_u16::<BigEndian>(payload_id_be.len() as u16);

		message_buffer.push(3u8);
		message_buffer.push_all(payload_id_length.as_slice());
		message_buffer.push_all(payload_id_be.as_slice());

		//	Expiration date
		let time = time::now().to_timespec().sec + 86400;	// expired after one day
		let mut exp_date_be = vec![];
		let _ = exp_date_be.write_u32::<BigEndian>(time as u32);

		let mut exp_date_length = vec![];
		let _ = exp_date_length.write_u16::<BigEndian>(exp_date_be.len() as u16);

		message_buffer.push(4u8);
		message_buffer.push_all(exp_date_length.as_slice());
		message_buffer.push_all(exp_date_be.as_slice());

		// Priority
		let mut priority_length = vec![];
		let _ = priority_length.write_u16::<BigEndian>(1u16);

		message_buffer.push(5u8);
		message_buffer.push_all(priority_length.as_slice());
		message_buffer.push(10u8);

		let mut message_buffer_length = vec![];
		let _ = message_buffer_length.write_u32::<BigEndian>(message_buffer.len() as u32);

		let command = 2u8;
		notification_buffer.push(command);
		notification_buffer.push_all(message_buffer_length.as_slice());
		notification_buffer.push_all(message_buffer.as_slice());

		let mut retry_count = 3;
		let mut borrow_ssl_stream = self.ssl_stream.borrow_mut();

		while let Err(error) = borrow_ssl_stream.write_all(&notification_buffer) {
			println!("ssl_stream write error {:?}", error);

            retry_count = retry_count - 1;
            if retry_count <= 0 {
                break;
            }

            // try to recreate ssl stream
			let apns_url_production = "gateway.push.apple.com";
			let apns_url_development = "gateway.sandbox.push.apple.com";
			let apns_port = 2195;

			let apns_url = if self.sandbox { apns_url_development } else { apns_url_production };

			let ssl_result = get_ssl_stream(apns_url, apns_port, &self.certificate, &self.private_key, &self.ca_certificate);
			*borrow_ssl_stream = match ssl_result {
				Ok(ssl_stream) => {
					ssl_stream
				},
				Err(error) => {
                    println!("failed to get_ssl_stream error {:?}", error);
                    continue;
				}
			}
		}
	}
		// Response error code
/*
		let mut read_buffer = [0u8; 6];
		println!("SslStream read {:?}", self.ssl_stream.read(&mut read_buffer));

		for c in read_buffer.iter() {
			print!("{}", c);
		}
		println!("");
*/
}

fn get_ssl_stream(url: &str, port: u16, cert_file: &Path, private_key_file: &Path, ca_file: &Path) -> Result<SslStream<TcpStream>, SslError> {
	let mut context = try!(ssl::SslContext::new(ssl::SslMethod::Sslv23));

	if let Some(error) = context.set_CA_file(&ca_file) {
		println!("set_CA_file error {:?}", error);
	}
	if let Some(error) = context.set_certificate_file(&cert_file, openssl::x509::X509FileType::PEM) {
		println!("set_certificate_file error {:?}", error);
	}
	if let Some(error) = context.set_private_key_file(&private_key_file, openssl::x509::X509FileType::PEM) {
		println!("set_private_key_file error {:?}", error);
	}

	let apns_ip = match net::addrinfo::get_host_addresses(url) {
		Ok(results) => { results[0] },
		Err(error) => {
			return Result::Err(SslError::StreamError(error));
		}
	};

	let sock_addr = SocketAddr{ip: apns_ip, port: port};
    let tcp_conn = match TcpStream::connect(sock_addr) {
		Ok(conn) => { conn },
		Err(error) => {
			return Result::Err(SslError::StreamError(error));
		}
	};

	let ssl = try!(ssl::Ssl::new(&context));

	return SslStream::new_from(ssl, tcp_conn);
}

<|endoftext|>


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

//! This module provides a generic set of traits for dealing with cryptographic primitives.
//!
//! For examples on how to use these traits, see the implementations of the [`ed25519`] or
//! [`bls12381`] modules.

use crate::HashValue;
use core::convert::{From, TryFrom};
use failure::prelude::*;
use std::{fmt::Debug, hash::Hash};

/// An error type for key and signature validation issues, see [`ValidKey`][ValidKey].
///
/// This enum reflects there are two interesting causes of validation
/// failure for the ingestion of key or signature material: deserialization errors
/// (often, due to mangled material or curve equation failure for ECC) and
/// validation errors (material recognizable but unacceptable for use,
/// e.g. unsafe).
#[derive(Clone, Debug, PartialEq, Eq, failure::prelude::Fail)]
pub enum CryptoMaterialError {
    /// Key or signature material does not deserialize correctly.
    #[fail(display = "DeserializationError")]
    DeserializationError,
    /// Key or signature material deserializes, but is otherwise not valid.
    #[fail(display = "ValidationError")]
    ValidationError,
    /// Key or signature material does not have the expected size.
    #[fail(display = "WrongLengthError")]
    WrongLengthError,
    /// Part of the signature or key is not canonical resulting to malleability issues.
    #[fail(display = "CanonicalRepresentationError")]
    CanonicalRepresentationError,
    /// A curve point (i.e., a public key) lies on a small group.
    #[fail(display = "SmallSubgroupError")]
    SmallSubgroupError,
    /// A curve point (i.e., a public key) does not satisfy the curve equation.
    #[fail(display = "PointNotOnCurveError")]
    PointNotOnCurveError,
}

/// Key material with a notion of byte validation.
///
/// A type family for material that knows how to serialize and
/// deserialize, as well as validate byte-encoded material. The
/// validation must be implemented as a [`TryFrom`][TryFrom] which
/// classifies its failures against the above
/// [`CryptoMaterialError`][CryptoMaterialError].
///
/// This provides an implementation for a validation that relies on a
/// round-trip to bytes and corresponding [`TryFrom`][TryFrom].
pub trait ValidKey:
    // The for<'a> exactly matches the assumption "deserializable from any lifetime".
    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError> + Debug
{
    /// TryFrom is the source of truth on whether we can build a valid key.
    /// => we can use it once we've built, to validate!
    fn validate(&self) -> std::result::Result<(), CryptoMaterialError> {
        Self::try_from(self.to_bytes().as_slice())?;
        Ok(())
    }

    /// Convert the valid key to bytes.
    fn to_bytes(&self) -> Vec<u8>;
}

/// An extension to to/from Strings for [`ValidKey`][ValidKey].
///
/// Relies on [`hex`][::hex] for string encoding / decoding.
/// No required fields, provides a default implementation.
pub trait ValidKeyStringExt: ValidKey {
    /// When trying to convert from bytes, we simply decode the string into
    /// bytes before checking if we can convert.
    fn from_encoded_string(encoded_str: &str) -> std::result::Result<Self, CryptoMaterialError> {
        let bytes_out = ::hex::decode(encoded_str);
        // We defer to `try_from` to make sure we only produce valid keys.
        bytes_out
            // We reinterpret a failure to serialize: key is mangled someway.
            .or(Err(CryptoMaterialError::DeserializationError))
            .and_then(|ref bytes| Self::try_from(bytes))
    }
    /// A function to encode into hex-string after serializing.
    fn to_encoded_string(&self) -> Result<String> {
        Ok(::hex::encode(&self.to_bytes()))
    }
}

// There's nothing required in this extension, so let's just derive it
// for anybody that has a ValidKey.
impl<T: ValidKey> ValidKeyStringExt for T {}

/// A type family for key material that should remain secret and has an
/// associated type of the [`PublicKey`][PublicKey] family.
pub trait PrivateKey: Sized {
    /// We require public / private types to be coupled, i.e. their
    /// associated type is each other.
    type PublicKeyMaterial: PublicKey<PrivateKeyMaterial = Self>;

    /// Returns the associated public key
    fn public_key(&self) -> Self::PublicKeyMaterial {
        self.into()
    }
}

/// A type family of valid keys that know how to sign.
///
/// A trait for a [`ValidKey`][ValidKey] which knows how to sign a
/// message, and return an associated `Signature` type.
pub trait SigningKey:
    PrivateKey<PublicKeyMaterial = <Self as SigningKey>::VerifyingKeyMaterial> + ValidKey
{
    /// The associated verifying key type for this signing key.
    type VerifyingKeyMaterial: VerifyingKey<SigningKeyMaterial = Self>;
    /// The associated signature type for this signing key.
    type SignatureMaterial: Signature<SigningKeyMaterial = Self>;

    /// Signs an input message.
    fn sign_message(&self, message: &HashValue) -> Self::SignatureMaterial;

    /// Returns the associated verifying key
    fn verifying_key(&self) -> Self::VerifyingKeyMaterial {
        self.public_key()
    }
}

/// A type for key material that can be publicly shared, and in asymmetric
/// fashion, can be obtained from a [`PrivateKey`][PrivateKey]
/// reference.
/// This convertibility requirement ensures the existence of a
/// deterministic, canonical public key construction from a private key.
pub trait PublicKey: Sized + Clone + Eq + Hash +
    // This unsightly turbofish type parameter is the precise constraint
    // needed to require that there exists an
    //
    // ```
    // impl From<&MyPrivateKeyMaterial> for MyPublicKeyMaterial
    // ```
    //
    // declaration, for any `MyPrivateKeyMaterial`, `MyPublicKeyMaterial`
    // on which we register (respectively) `PublicKey` and `PrivateKey`
    // implementations.
    for<'a> From<&'a <Self as PublicKey>::PrivateKeyMaterial> {
    /// We require public / private types to be coupled, i.e. their
    /// associated type is each other.
    type PrivateKeyMaterial: PrivateKey<PublicKeyMaterial = Self>;
}

/// A type family of public keys that are used for signing.
///
/// It is linked to a type of the Signature family, which carries the
/// verification implementation.
pub trait VerifyingKey:
    PublicKey<PrivateKeyMaterial = <Self as VerifyingKey>::SigningKeyMaterial> + ValidKey
{
    /// The associated signing key type for this verifying key.
    type SigningKeyMaterial: SigningKey<VerifyingKeyMaterial = Self>;
    /// The associated signature type for this verifying key.
    type SignatureMaterial: Signature<VerifyingKeyMaterial = Self>;

    /// We provide the logical implementation which dispatches to the signature.
    fn verify_signature(
        &self,
        message: &HashValue,
        signature: &Self::SignatureMaterial,
    ) -> Result<()> {
        signature.verify(message, self)
    }

    /// We provide the implementation which dispatches to the signature.
    fn batch_verify_signatures(
        message: &HashValue,
        keys_and_signatures: Vec<(Self, Self::SignatureMaterial)>,
    ) -> Result<()> {
        Self::SignatureMaterial::batch_verify_signatures(message, keys_and_signatures)
    }
}

/// A type family for signature material that knows which public key type
/// is needed to verify it, and given such a public key, knows how to
/// verify.
///
/// This trait simply requires an association to some type of the
/// [`PublicKey`][PublicKey] family of which we are the `SignatureMaterial`.
///
/// It should be possible to write a generic signature function that
/// checks signature material passed as `&[u8]` and only returns Ok when
/// that material de-serializes to a signature of the expected concrete
/// scheme. This would be done as an extension trait of
/// [`Signature`][Signature].
pub trait Signature:
    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError> + Sized + Debug + Clone + Eq + Hash
{
    /// The associated verifying key type for this signature.
    type VerifyingKeyMaterial: VerifyingKey<SignatureMaterial = Self>;
    /// The associated signing key type for this signature
    type SigningKeyMaterial: SigningKey<SignatureMaterial = Self>;

    /// The verification function.
    fn verify(&self, message: &HashValue, public_key: &Self::VerifyingKeyMaterial) -> Result<()>;

    /// Native verification function.
    fn verify_arbitrary_msg(
        &self,
        message: &[u8],
        public_key: &Self::VerifyingKeyMaterial,
    ) -> Result<()>;

    /// Convert the signature into a byte representation.
    fn to_bytes(&self) -> Vec<u8>;

    /// The implementer can override a batch verification implementation
    /// that by default iterates over each signature. More efficient
    /// implementations exist and should be implemented for many schemes.
    fn batch_verify_signatures(
        message: &HashValue,
        keys_and_signatures: Vec<(Self::VerifyingKeyMaterial, Self)>,
    ) -> Result<()> {
        for (key, signature) in keys_and_signatures {
            signature.verify(message, &key)?
        }
        Ok(())
    }
}

/// A type family for schemes which know how to generate key material from
/// a cryptographically-secure [`CryptoRng`][::rand::CryptoRng].
pub trait Uniform {
    /// Generate key material from an RNG for testing purposes.
    fn generate_for_testing<R>(rng: &mut R) -> Self
    where
        R: ::rand::SeedableRng + ::rand::RngCore + ::rand::CryptoRng;
}

/// A type family with a by-convention notion of genesis private key.
pub trait Genesis: PrivateKey {
    /// Produces the genesis private key.
    fn genesis() -> Self;
}

/// A type family for Diffie-Hellman private key material
pub trait ExchangeKey:
    PrivateKey<PublicKeyMaterial = <Self as ExchangeKey>::DHPublicKeyMaterial> + Uniform
{
    /// The associated PublicKey type
    type DHPublicKeyMaterial: PublicKey<PrivateKeyMaterial = Self>;

    /// The associated SharedKey type obtained as a result of the DH exchange
    ///
    /// Warning: This type may soon receive bounds for encryption & signing
    type DHSharedKeyMaterial;

    /// Generates a SharedKey using a peer PublicKey
    fn dh(self, public_key: &Self::DHPublicKeyMaterial) -> Self::DHSharedKeyMaterial;
}
<commit_msg>Removing validate from crypto/crypto/src/traits.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! This module provides a generic set of traits for dealing with cryptographic primitives.
//!
//! For examples on how to use these traits, see the implementations of the [`ed25519`] or
//! [`bls12381`] modules.

use crate::HashValue;
use core::convert::{From, TryFrom};
use failure::prelude::*;
use std::{fmt::Debug, hash::Hash};

/// An error type for key and signature validation issues, see [`ValidKey`][ValidKey].
///
/// This enum reflects there are two interesting causes of validation
/// failure for the ingestion of key or signature material: deserialization errors
/// (often, due to mangled material or curve equation failure for ECC) and
/// validation errors (material recognizable but unacceptable for use,
/// e.g. unsafe).
#[derive(Clone, Debug, PartialEq, Eq, failure::prelude::Fail)]
pub enum CryptoMaterialError {
    /// Key or signature material does not deserialize correctly.
    #[fail(display = "DeserializationError")]
    DeserializationError,
    /// Key or signature material deserializes, but is otherwise not valid.
    #[fail(display = "ValidationError")]
    ValidationError,
    /// Key or signature material does not have the expected size.
    #[fail(display = "WrongLengthError")]
    WrongLengthError,
    /// Part of the signature or key is not canonical resulting to malleability issues.
    #[fail(display = "CanonicalRepresentationError")]
    CanonicalRepresentationError,
    /// A curve point (i.e., a public key) lies on a small group.
    #[fail(display = "SmallSubgroupError")]
    SmallSubgroupError,
    /// A curve point (i.e., a public key) does not satisfy the curve equation.
    #[fail(display = "PointNotOnCurveError")]
    PointNotOnCurveError,
}

/// Key material with a notion of byte validation.
///
/// A type family for material that knows how to serialize and
/// deserialize, as well as validate byte-encoded material. The
/// validation must be implemented as a [`TryFrom`][TryFrom] which
/// classifies its failures against the above
/// [`CryptoMaterialError`][CryptoMaterialError].
///
/// This provides an implementation for a validation that relies on a
/// round-trip to bytes and corresponding [`TryFrom`][TryFrom].
pub trait ValidKey:
    // The for<'a> exactly matches the assumption "deserializable from any lifetime".
    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError> + Debug
{

    /// Convert the valid key to bytes.
    fn to_bytes(&self) -> Vec<u8>;
}

/// An extension to to/from Strings for [`ValidKey`][ValidKey].
///
/// Relies on [`hex`][::hex] for string encoding / decoding.
/// No required fields, provides a default implementation.
pub trait ValidKeyStringExt: ValidKey {
    /// When trying to convert from bytes, we simply decode the string into
    /// bytes before checking if we can convert.
    fn from_encoded_string(encoded_str: &str) -> std::result::Result<Self, CryptoMaterialError> {
        let bytes_out = ::hex::decode(encoded_str);
        // We defer to `try_from` to make sure we only produce valid keys.
        bytes_out
            // We reinterpret a failure to serialize: key is mangled someway.
            .or(Err(CryptoMaterialError::DeserializationError))
            .and_then(|ref bytes| Self::try_from(bytes))
    }
    /// A function to encode into hex-string after serializing.
    fn to_encoded_string(&self) -> Result<String> {
        Ok(::hex::encode(&self.to_bytes()))
    }
}

// There's nothing required in this extension, so let's just derive it
// for anybody that has a ValidKey.
impl<T: ValidKey> ValidKeyStringExt for T {}

/// A type family for key material that should remain secret and has an
/// associated type of the [`PublicKey`][PublicKey] family.
pub trait PrivateKey: Sized {
    /// We require public / private types to be coupled, i.e. their
    /// associated type is each other.
    type PublicKeyMaterial: PublicKey<PrivateKeyMaterial = Self>;

    /// Returns the associated public key
    fn public_key(&self) -> Self::PublicKeyMaterial {
        self.into()
    }
}

/// A type family of valid keys that know how to sign.
///
/// A trait for a [`ValidKey`][ValidKey] which knows how to sign a
/// message, and return an associated `Signature` type.
pub trait SigningKey:
    PrivateKey<PublicKeyMaterial = <Self as SigningKey>::VerifyingKeyMaterial> + ValidKey
{
    /// The associated verifying key type for this signing key.
    type VerifyingKeyMaterial: VerifyingKey<SigningKeyMaterial = Self>;
    /// The associated signature type for this signing key.
    type SignatureMaterial: Signature<SigningKeyMaterial = Self>;

    /// Signs an input message.
    fn sign_message(&self, message: &HashValue) -> Self::SignatureMaterial;

    /// Returns the associated verifying key
    fn verifying_key(&self) -> Self::VerifyingKeyMaterial {
        self.public_key()
    }
}

/// A type for key material that can be publicly shared, and in asymmetric
/// fashion, can be obtained from a [`PrivateKey`][PrivateKey]
/// reference.
/// This convertibility requirement ensures the existence of a
/// deterministic, canonical public key construction from a private key.
pub trait PublicKey: Sized + Clone + Eq + Hash +
    // This unsightly turbofish type parameter is the precise constraint
    // needed to require that there exists an
    //
    // ```
    // impl From<&MyPrivateKeyMaterial> for MyPublicKeyMaterial
    // ```
    //
    // declaration, for any `MyPrivateKeyMaterial`, `MyPublicKeyMaterial`
    // on which we register (respectively) `PublicKey` and `PrivateKey`
    // implementations.
    for<'a> From<&'a <Self as PublicKey>::PrivateKeyMaterial> {
    /// We require public / private types to be coupled, i.e. their
    /// associated type is each other.
    type PrivateKeyMaterial: PrivateKey<PublicKeyMaterial = Self>;
}

/// A type family of public keys that are used for signing.
///
/// It is linked to a type of the Signature family, which carries the
/// verification implementation.
pub trait VerifyingKey:
    PublicKey<PrivateKeyMaterial = <Self as VerifyingKey>::SigningKeyMaterial> + ValidKey
{
    /// The associated signing key type for this verifying key.
    type SigningKeyMaterial: SigningKey<VerifyingKeyMaterial = Self>;
    /// The associated signature type for this verifying key.
    type SignatureMaterial: Signature<VerifyingKeyMaterial = Self>;

    /// We provide the logical implementation which dispatches to the signature.
    fn verify_signature(
        &self,
        message: &HashValue,
        signature: &Self::SignatureMaterial,
    ) -> Result<()> {
        signature.verify(message, self)
    }

    /// We provide the implementation which dispatches to the signature.
    fn batch_verify_signatures(
        message: &HashValue,
        keys_and_signatures: Vec<(Self, Self::SignatureMaterial)>,
    ) -> Result<()> {
        Self::SignatureMaterial::batch_verify_signatures(message, keys_and_signatures)
    }
}

/// A type family for signature material that knows which public key type
/// is needed to verify it, and given such a public key, knows how to
/// verify.
///
/// This trait simply requires an association to some type of the
/// [`PublicKey`][PublicKey] family of which we are the `SignatureMaterial`.
///
/// It should be possible to write a generic signature function that
/// checks signature material passed as `&[u8]` and only returns Ok when
/// that material de-serializes to a signature of the expected concrete
/// scheme. This would be done as an extension trait of
/// [`Signature`][Signature].
pub trait Signature:
    for<'a> TryFrom<&'a [u8], Error = CryptoMaterialError> + Sized + Debug + Clone + Eq + Hash
{
    /// The associated verifying key type for this signature.
    type VerifyingKeyMaterial: VerifyingKey<SignatureMaterial = Self>;
    /// The associated signing key type for this signature
    type SigningKeyMaterial: SigningKey<SignatureMaterial = Self>;

    /// The verification function.
    fn verify(&self, message: &HashValue, public_key: &Self::VerifyingKeyMaterial) -> Result<()>;

    /// Native verification function.
    fn verify_arbitrary_msg(
        &self,
        message: &[u8],
        public_key: &Self::VerifyingKeyMaterial,
    ) -> Result<()>;

    /// Convert the signature into a byte representation.
    fn to_bytes(&self) -> Vec<u8>;

    /// The implementer can override a batch verification implementation
    /// that by default iterates over each signature. More efficient
    /// implementations exist and should be implemented for many schemes.
    fn batch_verify_signatures(
        message: &HashValue,
        keys_and_signatures: Vec<(Self::VerifyingKeyMaterial, Self)>,
    ) -> Result<()> {
        for (key, signature) in keys_and_signatures {
            signature.verify(message, &key)?
        }
        Ok(())
    }
}

/// A type family for schemes which know how to generate key material from
/// a cryptographically-secure [`CryptoRng`][::rand::CryptoRng].
pub trait Uniform {
    /// Generate key material from an RNG for testing purposes.
    fn generate_for_testing<R>(rng: &mut R) -> Self
    where
        R: ::rand::SeedableRng + ::rand::RngCore + ::rand::CryptoRng;
}

/// A type family with a by-convention notion of genesis private key.
pub trait Genesis: PrivateKey {
    /// Produces the genesis private key.
    fn genesis() -> Self;
}

/// A type family for Diffie-Hellman private key material
pub trait ExchangeKey:
    PrivateKey<PublicKeyMaterial = <Self as ExchangeKey>::DHPublicKeyMaterial> + Uniform
{
    /// The associated PublicKey type
    type DHPublicKeyMaterial: PublicKey<PrivateKeyMaterial = Self>;

    /// The associated SharedKey type obtained as a result of the DH exchange
    ///
    /// Warning: This type may soon receive bounds for encryption & signing
    type DHSharedKeyMaterial;

    /// Generates a SharedKey using a peer PublicKey
    fn dh(self, public_key: &Self::DHPublicKeyMaterial) -> Self::DHSharedKeyMaterial;
}
<|endoftext|>