<commit_before>// https://leetcode.com/problems/minimum-number-of-operations-to-sort-a-binary-tree-by-level/
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Rc<RefCell<TreeNode>>>,
    pub right: Option<Rc<RefCell<TreeNode>>>,
}

impl TreeNode {
    #[inline]
    pub fn new(val: i32) -> Self {
        TreeNode {
            val,
            left: None,
            right: None,
        }
    }
}

pub fn minimum_operations(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
    todo!()
}

fn main() {
    fn create_node(value: i32) -> Option<Rc<RefCell<TreeNode>>> {
        Some(Rc::new(RefCell::new(TreeNode::new(value))))
    }

    fn add_left(
        parent: &Option<Rc<RefCell<TreeNode>>>,
        value: i32,
    ) -> Option<Rc<RefCell<TreeNode>>> {
        parent.as_ref().unwrap().as_ref().borrow_mut().left = create_node(value);
        parent.as_ref().unwrap().as_ref().borrow().left.clone()
    }

    fn add_right(
        parent: &Option<Rc<RefCell<TreeNode>>>,
        value: i32,
    ) -> Option<Rc<RefCell<TreeNode>>> {
        parent.as_ref().unwrap().as_ref().borrow_mut().right = create_node(value);
        parent.as_ref().unwrap().as_ref().borrow().right.clone()
    }

    fn to_tree(nodes: Vec<Option<i32>>) -> Option<Rc<RefCell<TreeNode>>> {
        let mut deque: VecDeque<Option<Rc<RefCell<TreeNode>>>> = VecDeque::new();
        let root = create_node(nodes[0].unwrap());
        deque.push_back(root.clone());
        let mut i = 1;
        while i < nodes.len() {
            let parent = deque.pop_front().unwrap();
            let mut has_left = false;
            if let Some(left) = nodes[i] {
                deque.push_back(add_left(&parent, left));
                has_left = true;
            }
            let mut has_right = false;
            if i + 1 < nodes.len() {
                if let Some(right) = nodes[i + 1] {
                    deque.push_back(add_right(&parent, right));
                    has_right = true;
                }
            }
            if !has_left && !has_right {
                deque.push_back(parent);
            }
            i += 2;
        }
        root
    }

    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(4),
            Some(3),
            Some(7),
            Some(6),
            Some(8),
            Some(5),
            None,
            None,
            None,
            None,
            Some(9),
            None,
            Some(10)
        ]))
    ); // 3
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(3),
            Some(2),
            Some(7),
            Some(6),
            Some(5),
            Some(4)
        ]))
    ); // 3
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(2),
            Some(3),
            Some(4),
            Some(5),
            Some(6)
        ]))
    ); // 0
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(9),
            Some(4),
            Some(5),
            Some(3),
            Some(7),
            Some(8)
        ]))
    ); // 0
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(2),
            Some(3),
            Some(7),
            Some(6),
            Some(4),
            Some(5)
        ]))
    ); // 3
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(2),
            Some(3),
            Some(7),
            Some(6),
            Some(5),
            Some(4)
        ]))
    ); // 2
}
<commit_msg>Solve problem 2471<commit_after>// https://leetcode.com/problems/minimum-number-of-operations-to-sort-a-binary-tree-by-level/
use std::cell::RefCell;
use std::collections::{HashMap, VecDeque};
use std::rc::Rc;

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Rc<RefCell<TreeNode>>>,
    pub right: Option<Rc<RefCell<TreeNode>>>,
}

impl TreeNode {
    #[inline]
    pub fn new(val: i32) -> Self {
        TreeNode {
            val,
            left: None,
            right: None,
        }
    }
}

pub fn minimum_operations(root: Option<Rc<RefCell<TreeNode>>>) -> i32 {
    fn swap(v: &mut Vec<i32>, i: usize, j: usize) {
        let tmp = v[i];
        v[i] = v[j];
        v[j] = tmp;
    }

    let mut answer = 0;
    let mut deque: VecDeque<Option<Rc<RefCell<TreeNode>>>> = VecDeque::new();
    deque.push_back(root.clone());
    while !deque.is_empty() {
        let size = deque.len();
        let mut vec: Vec<i32> = vec![];
        let mut map: HashMap<i32, usize> = HashMap::new();
        for i in 0..size {
            let node = deque.pop_front().unwrap().clone();
            vec.push(node.as_ref().unwrap().as_ref().borrow().val);
            map.insert(node.as_ref().unwrap().as_ref().borrow().val, i);
            if let Some(n) = node {
                let left = n.as_ref().borrow().left.clone();
                if left.is_some() {
                    deque.push_back(left);
                }
                let right = n.as_ref().borrow().right.clone();
                if right.is_some() {
                    deque.push_back(right);
                }
            }
        }
        let mut sorted_vec = vec.clone();
        sorted_vec.sort();
        for i in 0..vec.len() {
            if vec[i] == sorted_vec[i] {
                continue;
            }
            let n = sorted_vec[i];
            let j = *map.get(&n).as_ref().unwrap().clone();
            map.insert(vec[i], j);
            swap(&mut vec, i, j);
            answer += 1;
        }
    }
    answer
}

fn main() {
    fn create_node(value: i32) -> Option<Rc<RefCell<TreeNode>>> {
        Some(Rc::new(RefCell::new(TreeNode::new(value))))
    }

    fn add_left(
        parent: &Option<Rc<RefCell<TreeNode>>>,
        value: i32,
    ) -> Option<Rc<RefCell<TreeNode>>> {
        parent.as_ref().unwrap().as_ref().borrow_mut().left = create_node(value);
        parent.as_ref().unwrap().as_ref().borrow().left.clone()
    }

    fn add_right(
        parent: &Option<Rc<RefCell<TreeNode>>>,
        value: i32,
    ) -> Option<Rc<RefCell<TreeNode>>> {
        parent.as_ref().unwrap().as_ref().borrow_mut().right = create_node(value);
        parent.as_ref().unwrap().as_ref().borrow().right.clone()
    }

    fn to_tree(nodes: Vec<Option<i32>>) -> Option<Rc<RefCell<TreeNode>>> {
        let mut deque: VecDeque<Option<Rc<RefCell<TreeNode>>>> = VecDeque::new();
        let root = create_node(nodes[0].unwrap());
        deque.push_back(root.clone());
        let mut i = 1;
        while i < nodes.len() {
            let parent = deque.pop_front().unwrap();
            let mut has_left = false;
            if let Some(left) = nodes[i] {
                deque.push_back(add_left(&parent, left));
                has_left = true;
            }
            let mut has_right = false;
            if i + 1 < nodes.len() {
                if let Some(right) = nodes[i + 1] {
                    deque.push_back(add_right(&parent, right));
                    has_right = true;
                }
            }
            if !has_left && !has_right {
                deque.push_back(parent);
            }
            i += 2;
        }
        root
    }

    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(4),
            Some(3),
            Some(7),
            Some(6),
            Some(8),
            Some(5),
            None,
            None,
            None,
            None,
            Some(9),
            None,
            Some(10)
        ]))
    ); // 3
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(3),
            Some(2),
            Some(7),
            Some(6),
            Some(5),
            Some(4)
        ]))
    ); // 3
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(2),
            Some(3),
            Some(4),
            Some(5),
            Some(6)
        ]))
    ); // 0
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(9),
            Some(4),
            Some(5),
            Some(3),
            Some(7),
            Some(8)
        ]))
    ); // 0
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(2),
            Some(3),
            Some(7),
            Some(6),
            Some(4),
            Some(5)
        ]))
    ); // 3
    println!(
        "{}",
        minimum_operations(to_tree(vec![
            Some(1),
            Some(2),
            Some(3),
            Some(7),
            Some(6),
            Some(5),
            Some(4)
        ]))
    ); // 2
}
<|endoftext|>


<commit_before>use std::{iter, mem};
use byteorder::{LE, ByteOrder};
use std::marker::PhantomData;

use crate::{accessor, buffer};

fn buffer_view_slice<'a, 's>(
    view: buffer::View<'a>,
    get_buffer_data: &dyn Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
) -> Option<&'s [u8]> {
    let start = view.offset();
    let end = start + view.length();
    get_buffer_data(view.buffer())
        .map(|slice| &slice[start..end])
}

/// General iterator for an accessor.
#[derive(Clone, Debug)]
pub enum Iter<'a, T: Item> {
    /// Standard accessor iterator.
    Standard(ItemIter<'a, T>),

    /// Iterator for accessor with sparse values.
    Sparse(SparseIter<'a, T>),
}

impl<'a, T: Item> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            &mut Iter::Standard(ref mut iter) => iter.next(),
            &mut Iter::Sparse(ref mut iter) => iter.next(),
        }
    }
}

/// Iterator over indices of sparse accessor.
#[derive(Clone, Debug)]
pub enum SparseIndicesIter<'a> {
    /// 8-bit indices.
    U8(ItemIter<'a, u8>),
    /// 16-bit indices.
    U16(ItemIter<'a, u16>),
    /// 32-bit indices.
    U32(ItemIter<'a, u32>),
}

impl<'a> Iterator for SparseIndicesIter<'a> {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        match *self {
            SparseIndicesIter::U8(ref mut iter) => iter.next().map(|x| x as u32),
            SparseIndicesIter::U16(ref mut iter) => iter.next().map(|x| x as u32),
            SparseIndicesIter::U32(ref mut iter) => iter.next(),
        }
    }
}

/// Iterates over a sparse accessor.
#[derive(Clone, Debug)]
pub struct SparseIter<'a, T: Item> {
    /// Base value iterator.
    ///
    /// This can be `None` if the base buffer view is not set. In this case the base values are all zero.
    base: Option<ItemIter<'a, T>>,

    /// Sparse indices iterator.
    indices: iter::Peekable<SparseIndicesIter<'a>>,

    /// Sparse values iterator.
    values: ItemIter<'a, T>,

    /// Iterator counter.
    counter: u32,
}

impl<'a, T: Item> SparseIter<'a, T> {
    /// Constructor.
    ///
    /// Here `base` is allowed to be `None` when the base buffer view is not explicitly specified.
    pub fn new(
        base: Option<ItemIter<'a, T>>,
        indices: SparseIndicesIter<'a>,
        values: ItemIter<'a, T>,
    ) -> Self {
        SparseIter {
            base,
            indices: indices.peekable(),
            values: values,
            counter: 0,
        }
    }
}

impl<'a, T: Item> Iterator for SparseIter<'a, T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let next_base_value = self.base.as_mut().map(|iter| iter.next()).unwrap_or(Some(T::zero()));
        if next_base_value.is_none() {
            return None;
        }

        let mut next_value = next_base_value.unwrap();
        let next_sparse_index = self.indices.peek().clone();
        if let Some(index) = next_sparse_index {
            if *index == self.counter {
                self.indices.next(); // advance
                next_value = self.values.next().unwrap();
            }
        }

        self.counter += 1;

        Some(next_value)
    }
}

/// Represents items that can be read by an [`Accessor`].
///
/// [`Accessor`]: struct.Accessor.html
pub trait Item {
    /// Create an object of this type from a byte slice.
    fn from_slice(slice: &[u8]) -> Self;
    /// Create an object of this type that represents a zero value.
    fn zero() -> Self;
}

/// Visits the items in an [`Accessor`].
///
/// [`Accessor`]: struct.Accessor.html
#[derive(Copy, Clone, Debug)]
pub struct ItemIter<'a, T: Item> {
    stride: usize,
    data: &'a [u8],
    _phantom: PhantomData<T>,
}

impl Item for i8 {
    fn from_slice(slice: &[u8]) -> Self {
        slice[0] as i8
    }
    fn zero() -> Self {
        0
    }
}

impl Item for i16 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_i16(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u8 {
    fn from_slice(slice: &[u8]) -> Self {
        slice[0]
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u16 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_u16(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u32 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_u32(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for f32 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_f32(slice)
    }
    fn zero() -> Self {
        0.0
    }
}

impl<T: Item + Copy> Item for [T; 2] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 2 * mem::size_of::<T>());
        [T::from_slice(slice),
         T::from_slice(&slice[mem::size_of::<T>() ..])]
    }
    fn zero() -> Self {
        [T::zero(); 2]
    }
}

impl<T: Item + Copy> Item for [T; 3] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 3 * mem::size_of::<T>());
        [T::from_slice(slice),
         T::from_slice(&slice[1 * mem::size_of::<T>() ..]),
         T::from_slice(&slice[2 * mem::size_of::<T>() ..])]
    }
    fn zero() -> Self {
        [T::zero(); 3]
    }
}

impl<T: Item + Copy> Item for [T; 4] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 4 * mem::size_of::<T>());
        [T::from_slice(slice),
         T::from_slice(&slice[1 * mem::size_of::<T>() ..]),
         T::from_slice(&slice[2 * mem::size_of::<T>() ..]),
         T::from_slice(&slice[3 * mem::size_of::<T>() ..])]
    }
    fn zero() -> Self {
        [T::zero(); 4]
    }
}

impl<'a, T: Item> ItemIter<'a, T> {
    /// Constructor.
    pub fn new(slice: &'a [u8], stride: usize) -> Self {
        ItemIter {
            data: slice,
            stride: stride,
            _phantom: PhantomData,
        }
    }
}

impl<'a, 's, T: Item> Iter<'s, T> {
    /// Constructor.
    pub fn new<F>(
        accessor: super::Accessor<'a>,
        get_buffer_data: F,
    ) -> Option<Iter<'s, T>>
        where F: Clone + Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
    {
        let is_sparse = accessor.sparse().is_some();
        if is_sparse {
            let sparse = accessor.sparse();
            let indices = sparse.as_ref().unwrap().indices();
            let values = sparse.as_ref().unwrap().values();
            let base_iter = {
                // Using `if let` here instead of map to preserve the early return behavior.
                if let Some(view) = accessor.view() {
                    let stride = view.stride().unwrap_or(mem::size_of::<T>());
                    let start = accessor.offset();
                    let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
                    let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
                        &slice[start..end]
                    } else {
                        return None
                    };
                    Some(ItemIter::new(subslice, stride))
                } else {
                    None
                }
            };
            let sparse_count = sparse.as_ref().unwrap().count() as usize;
            let index_iter = {
                let view = indices.view();
                let index_size = indices.index_type().size();
                let stride = view.stride().unwrap_or(index_size);
                let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
                    let start = indices.offset() as usize;
                    let end = start + stride * (sparse_count - 1) + index_size;
                    &slice[start..end]
                } else {
                    return None
                };
                match indices.index_type() {
                    accessor::sparse::IndexType::U8 => SparseIndicesIter::U8(ItemIter::new(subslice, stride)),
                    accessor::sparse::IndexType::U16 => SparseIndicesIter::U16(ItemIter::new(subslice, stride)),
                    accessor::sparse::IndexType::U32 => SparseIndicesIter::U32(ItemIter::new(subslice, stride)),
                }
            };
            let value_iter = {
                let view = values.view();
                let stride = view.stride().unwrap_or(mem::size_of::<T>());
                let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
                    let start = values.offset() as usize;
                    let end = start + stride * (sparse_count - 1) + mem::size_of::<T>();
                    &slice[start..end]
                } else {
                    return None
                };
                ItemIter::new(subslice, stride)
            };
            Some(Iter::Sparse(SparseIter::new(base_iter, index_iter, value_iter)))
        } else {
            debug_assert_eq!(mem::size_of::<T>(), accessor.size());
            debug_assert!(mem::size_of::<T>() > 0);
            if let Some(view) = accessor.view() {
                let stride = view.stride().unwrap_or(mem::size_of::<T>());
                debug_assert!(stride >= mem::size_of::<T>(), "Mismatch in stride, expected at least {} stride but found {}", mem::size_of::<T>(), stride);
                let start = accessor.offset();
                let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
                let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
                    &slice[start..end]
                } else {
                    return None
                };
                Some(Iter::Standard(ItemIter { stride, data: subslice, _phantom: PhantomData }))
            } else {
                None
            }
        }
    }
}

impl<'a, T: Item> ExactSizeIterator for ItemIter<'a, T> {}
impl<'a, T: Item> Iterator for ItemIter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        let stride = if self.data.len() >= self.stride {
            Some(self.stride)
        } else if self.data.len() >= mem::size_of::<T>() {
            Some(mem::size_of::<T>())
        } else {
            None
        };
        if let Some(stride) = stride {
            let (val, data) = self.data.split_at(stride);
            let val = T::from_slice(val);
            self.data = data;
            Some(val)
        } else {
            None
        }
    }

    fn nth(&mut self, nth: usize) -> Option<Self::Item> {
        if let Some(val_data) = self.data.get(nth * self.stride ..) {
            if val_data.len() >= mem::size_of::<T>() {
                let val = T::from_slice(val_data);
                self.data = &val_data[self.stride.min(val_data.len()) ..];
                Some(val)
            } else {
                None
            }
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> {
        if self.data.len() >= mem::size_of::<T>() {
            self.data
                .get((self.data.len() - 1) / self.stride * self.stride ..)
                .map(T::from_slice)
        } else {
            None
        }
    }

    fn count(self) -> usize {
        self.size_hint().0
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let hint = self.data.len() / self.stride
            + (self.data.len() % self.stride >= mem::size_of::<T>()) as usize;
        (hint, Some(hint))
    }
}
<commit_msg>Implement ExactSizeIterator for accessor::util::Iter<commit_after>use std::{iter, mem};
use byteorder::{LE, ByteOrder};
use std::marker::PhantomData;

use crate::{accessor, buffer};

fn buffer_view_slice<'a, 's>(
    view: buffer::View<'a>,
    get_buffer_data: &dyn Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
) -> Option<&'s [u8]> {
    let start = view.offset();
    let end = start + view.length();
    get_buffer_data(view.buffer())
        .map(|slice| &slice[start..end])
}

/// General iterator for an accessor.
#[derive(Clone, Debug)]
pub enum Iter<'a, T: Item> {
    /// Standard accessor iterator.
    Standard(ItemIter<'a, T>),

    /// Iterator for accessor with sparse values.
    Sparse(SparseIter<'a, T>),
}

impl<'a, T: Item> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            &mut Iter::Standard(ref mut iter) => iter.next(),
            &mut Iter::Sparse(ref mut iter) => iter.next(),
        }
    }
}

impl<'a, T: Item> ExactSizeIterator for Iter<'a, T> {
    fn len(&self) -> usize {
        match self {
            &Iter::Standard(ref iter) => iter.len(),
            &Iter::Sparse(ref iter) => iter.values.len(),
        }
    }
}

/// Iterator over indices of sparse accessor.
#[derive(Clone, Debug)]
pub enum SparseIndicesIter<'a> {
    /// 8-bit indices.
    U8(ItemIter<'a, u8>),
    /// 16-bit indices.
    U16(ItemIter<'a, u16>),
    /// 32-bit indices.
    U32(ItemIter<'a, u32>),
}

impl<'a> Iterator for SparseIndicesIter<'a> {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        match *self {
            SparseIndicesIter::U8(ref mut iter) => iter.next().map(|x| x as u32),
            SparseIndicesIter::U16(ref mut iter) => iter.next().map(|x| x as u32),
            SparseIndicesIter::U32(ref mut iter) => iter.next(),
        }
    }
}

/// Iterates over a sparse accessor.
#[derive(Clone, Debug)]
pub struct SparseIter<'a, T: Item> {
    /// Base value iterator.
    ///
    /// This can be `None` if the base buffer view is not set. In this case the base values are all zero.
    base: Option<ItemIter<'a, T>>,

    /// Sparse indices iterator.
    indices: iter::Peekable<SparseIndicesIter<'a>>,

    /// Sparse values iterator.
    values: ItemIter<'a, T>,

    /// Iterator counter.
    counter: u32,
}

impl<'a, T: Item> SparseIter<'a, T> {
    /// Constructor.
    ///
    /// Here `base` is allowed to be `None` when the base buffer view is not explicitly specified.
    pub fn new(
        base: Option<ItemIter<'a, T>>,
        indices: SparseIndicesIter<'a>,
        values: ItemIter<'a, T>,
    ) -> Self {
        SparseIter {
            base,
            indices: indices.peekable(),
            values: values,
            counter: 0,
        }
    }
}

impl<'a, T: Item> Iterator for SparseIter<'a, T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let next_base_value = self.base.as_mut().map(|iter| iter.next()).unwrap_or(Some(T::zero()));
        if next_base_value.is_none() {
            return None;
        }

        let mut next_value = next_base_value.unwrap();
        let next_sparse_index = self.indices.peek().clone();
        if let Some(index) = next_sparse_index {
            if *index == self.counter {
                self.indices.next(); // advance
                next_value = self.values.next().unwrap();
            }
        }

        self.counter += 1;

        Some(next_value)
    }
}

/// Represents items that can be read by an [`Accessor`].
///
/// [`Accessor`]: struct.Accessor.html
pub trait Item {
    /// Create an object of this type from a byte slice.
    fn from_slice(slice: &[u8]) -> Self;
    /// Create an object of this type that represents a zero value.
    fn zero() -> Self;
}

/// Visits the items in an [`Accessor`].
///
/// [`Accessor`]: struct.Accessor.html
#[derive(Copy, Clone, Debug)]
pub struct ItemIter<'a, T: Item> {
    stride: usize,
    data: &'a [u8],
    _phantom: PhantomData<T>,
}

impl Item for i8 {
    fn from_slice(slice: &[u8]) -> Self {
        slice[0] as i8
    }
    fn zero() -> Self {
        0
    }
}

impl Item for i16 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_i16(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u8 {
    fn from_slice(slice: &[u8]) -> Self {
        slice[0]
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u16 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_u16(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u32 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_u32(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for f32 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_f32(slice)
    }
    fn zero() -> Self {
        0.0
    }
}

impl<T: Item + Copy> Item for [T; 2] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 2 * mem::size_of::<T>());
        [T::from_slice(slice),
         T::from_slice(&slice[mem::size_of::<T>() ..])]
    }
    fn zero() -> Self {
        [T::zero(); 2]
    }
}

impl<T: Item + Copy> Item for [T; 3] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 3 * mem::size_of::<T>());
        [T::from_slice(slice),
         T::from_slice(&slice[1 * mem::size_of::<T>() ..]),
         T::from_slice(&slice[2 * mem::size_of::<T>() ..])]
    }
    fn zero() -> Self {
        [T::zero(); 3]
    }
}

impl<T: Item + Copy> Item for [T; 4] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 4 * mem::size_of::<T>());
        [T::from_slice(slice),
         T::from_slice(&slice[1 * mem::size_of::<T>() ..]),
         T::from_slice(&slice[2 * mem::size_of::<T>() ..]),
         T::from_slice(&slice[3 * mem::size_of::<T>() ..])]
    }
    fn zero() -> Self {
        [T::zero(); 4]
    }
}

impl<'a, T: Item> ItemIter<'a, T> {
    /// Constructor.
    pub fn new(slice: &'a [u8], stride: usize) -> Self {
        ItemIter {
            data: slice,
            stride: stride,
            _phantom: PhantomData,
        }
    }
}

impl<'a, 's, T: Item> Iter<'s, T> {
    /// Constructor.
    pub fn new<F>(
        accessor: super::Accessor<'a>,
        get_buffer_data: F,
    ) -> Option<Iter<'s, T>>
        where F: Clone + Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
    {
        let is_sparse = accessor.sparse().is_some();
        if is_sparse {
            let sparse = accessor.sparse();
            let indices = sparse.as_ref().unwrap().indices();
            let values = sparse.as_ref().unwrap().values();
            let base_iter = {
                // Using `if let` here instead of map to preserve the early return behavior.
                if let Some(view) = accessor.view() {
                    let stride = view.stride().unwrap_or(mem::size_of::<T>());
                    let start = accessor.offset();
                    let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
                    let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
                        &slice[start..end]
                    } else {
                        return None
                    };
                    Some(ItemIter::new(subslice, stride))
                } else {
                    None
                }
            };
            let sparse_count = sparse.as_ref().unwrap().count() as usize;
            let index_iter = {
                let view = indices.view();
                let index_size = indices.index_type().size();
                let stride = view.stride().unwrap_or(index_size);
                let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
                    let start = indices.offset() as usize;
                    let end = start + stride * (sparse_count - 1) + index_size;
                    &slice[start..end]
                } else {
                    return None
                };
                match indices.index_type() {
                    accessor::sparse::IndexType::U8 => SparseIndicesIter::U8(ItemIter::new(subslice, stride)),
                    accessor::sparse::IndexType::U16 => SparseIndicesIter::U16(ItemIter::new(subslice, stride)),
                    accessor::sparse::IndexType::U32 => SparseIndicesIter::U32(ItemIter::new(subslice, stride)),
                }
            };
            let value_iter = {
                let view = values.view();
                let stride = view.stride().unwrap_or(mem::size_of::<T>());
                let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
                    let start = values.offset() as usize;
                    let end = start + stride * (sparse_count - 1) + mem::size_of::<T>();
                    &slice[start..end]
                } else {
                    return None
                };
                ItemIter::new(subslice, stride)
            };
            Some(Iter::Sparse(SparseIter::new(base_iter, index_iter, value_iter)))
        } else {
            debug_assert_eq!(mem::size_of::<T>(), accessor.size());
            debug_assert!(mem::size_of::<T>() > 0);
            if let Some(view) = accessor.view() {
                let stride = view.stride().unwrap_or(mem::size_of::<T>());
                debug_assert!(stride >= mem::size_of::<T>(), "Mismatch in stride, expected at least {} stride but found {}", mem::size_of::<T>(), stride);
                let start = accessor.offset();
                let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
                let subslice = if let Some(slice) = buffer_view_slice(view, &get_buffer_data) {
                    &slice[start..end]
                } else {
                    return None
                };
                Some(Iter::Standard(ItemIter { stride, data: subslice, _phantom: PhantomData }))
            } else {
                None
            }
        }
    }
}

impl<'a, T: Item> ExactSizeIterator for ItemIter<'a, T> {}
impl<'a, T: Item> Iterator for ItemIter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        let stride = if self.data.len() >= self.stride {
            Some(self.stride)
        } else if self.data.len() >= mem::size_of::<T>() {
            Some(mem::size_of::<T>())
        } else {
            None
        };
        if let Some(stride) = stride {
            let (val, data) = self.data.split_at(stride);
            let val = T::from_slice(val);
            self.data = data;
            Some(val)
        } else {
            None
        }
    }

    fn nth(&mut self, nth: usize) -> Option<Self::Item> {
        if let Some(val_data) = self.data.get(nth * self.stride ..) {
            if val_data.len() >= mem::size_of::<T>() {
                let val = T::from_slice(val_data);
                self.data = &val_data[self.stride.min(val_data.len()) ..];
                Some(val)
            } else {
                None
            }
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> {
        if self.data.len() >= mem::size_of::<T>() {
            self.data
                .get((self.data.len() - 1) / self.stride * self.stride ..)
                .map(T::from_slice)
        } else {
            None
        }
    }

    fn count(self) -> usize {
        self.size_hint().0
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let hint = self.data.len() / self.stride
            + (self.data.len() % self.stride >= mem::size_of::<T>()) as usize;
        (hint, Some(hint))
    }
}
<|endoftext|>


<commit_before>extern crate slack;

use std::env;
use std::sync::atomic::{AtomicIsize, Ordering};
use std::sync::mpsc::Sender;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::channel;
use std::thread;

use rustc_serialize::json::Json;
use rustc_serialize::json;
use rustc_serialize::json::DecoderError::MissingFieldError;
use rustc_serialize::Decodable;
use rustc_serialize::Decoder;

use slack::Message;

use message::AdapterMsg;
use message::IncomingMessage;
use adapter::ChatAdapter;

/// SlackAdapter sends and receives messages from the Slack chat service. Until actualy
/// configuration is added, the slack token should be placed in the environment variable
/// `SLACK_BOT_TOKEN`
pub struct SlackAdapter;

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

struct MyHandler {
  count: i64,
  tx_bot: Sender<IncomingMessage>,
  tx_adapter: Sender<AdapterMsg>
}

/// Data for a SlackMsg::Message
#[allow(dead_code)]
struct MessageData {
    text: String,
    channel: String,
    user: String,
    ts: String,
    team: String
}

macro_rules! str_accessor {
    ($s:ident) => {
        pub fn $s(&self) -> &str {
            self.$s.as_ref()
        }
    }
}

#[allow(dead_code)]
impl MessageData {
    str_accessor!(text);
    str_accessor!(channel);
    str_accessor!(user);
    str_accessor!(ts);
    str_accessor!(team);
}

/// Incoming slack messages on the websocket api
enum SlackMsg {
    /// A message was sent to a channel
    Message(MessageData),

    /// Some other type of message arrived.
    /// [The list](https://api.slack.com/rtm) is quite extensive, and only the
    /// messages the adapter is concerned with are enumerated here.
    Other
}

impl Decodable for SlackMsg {
    fn decode<D: Decoder>(d: &mut D) -> Result<SlackMsg, D::Error> {
        d.read_struct("root", 0, |root| {
            let msg_type = try!(root.read_struct_field("type", 0, |f| f.read_str() ));

            match msg_type.as_ref() {
                "message" => {
                    Ok(SlackMsg::Message(MessageData {
                        text: try!(root.read_struct_field("text", 0, |f| f.read_str())),
                        channel: try!(root.read_struct_field("channel", 0, |f| f.read_str())),
                        user: try!(root.read_struct_field("user", 0, |f| f.read_str())),
                        ts: try!(root.read_struct_field("ts", 0, |f| f.read_str())),
                        team: try!(root.read_struct_field("team", 0, |f| f.read_str())),
                    }))
                },
                _ => {
                    Ok(SlackMsg::Other)
                }
            }
        })
    }
}

fn string_to_slack_msg(raw: &str) -> Result<SlackMsg, json::DecoderError> {
    // Some messages arriving from the slack client don't have a type. So far I've only
    // witnessed confirmation messages arriving in this fashion. Since they go through the same
    // pipeline as content messages, the decoder should be able to handle them.
    match json::decode::<SlackMsg>(raw) {
        Ok(value) => Ok(value),
        Err(e) => {
            match e {
                MissingFieldError(field) => {
                    match field.as_ref() {
                        "type" => Ok(SlackMsg::Other),
                        _ => Err(MissingFieldError(field))
                    }
                },
                _ => Err(e)
            }
        }
    }
}

#[allow(unused_variables)]
impl slack::MessageHandler for MyHandler {
    fn on_receive(&mut self, cli: &mut slack::RtmClient, raw: &str) {
        println!("Received[{}]: {}", self.count, raw.to_string());
        self.count = self.count + 1;

        match string_to_slack_msg(raw) {
            Ok(slack_msg) => {
                match slack_msg {
                    SlackMsg::Message(msg) => {
                        let incoming = IncomingMessage::new("SlackAdapter".to_owned(), None,
                            Some(msg.channel().to_owned()), Some(msg.user().to_owned()),
                            msg.text().to_owned(), self.tx_adapter.clone());

                        self.tx_bot.send(incoming).ok().expect("Bot unable to process messages");
                    },
                    _ => ()
                }
            },
            Err(e) => {
                println!("error decoding slack message: {:?}", e);
                println!("please consider reporting this to jwilm/chatbot as it is probably a bug");
            }
        }
    }

    fn on_ping(&mut self, cli: &mut slack::RtmClient) {
        println!("<on_ping>");
    }

    fn on_close(&mut self, cli: &mut slack::RtmClient) {
        println!("<on_close>");
    }

    fn on_connect(&mut self, cli: &mut slack::RtmClient) {
        println!("<on_connect>");
        // let _ = cli.send_message("#general", "bla");
    }
}

impl ChatAdapter for SlackAdapter {
    /// SlackAdapter name
    fn get_name(&self) -> &str {
        "SlackAdapter"
    }

    fn process_events(&self) -> Receiver<IncomingMessage> {
        println!("SlackAdapter: process_events");
        let (tx_bot, rx_bot) = channel();
        let (tx_adapter, rx_adapter) = channel();

        let token = match env::var("SLACK_BOT_TOKEN") {
            Ok(t) => t,
            Err(_) => panic!("Failed to get SLACK_BOT_TOKEN from env")
        };

        let uid = AtomicIsize::new(0);

        let mut cli = slack::RtmClient::new();
        let (client, slack_rx) = cli.login(token.as_ref()).unwrap();
        let slack_tx = cli.get_outs().unwrap();

        thread::Builder::new().name("Chatbot Slack Receiver".to_owned()).spawn(move || {
            let mut handler = MyHandler{count: 0, tx_bot: tx_bot, tx_adapter: tx_adapter};
            cli.run::<MyHandler>(&mut handler, client, slack_rx).unwrap();
        }).ok().expect("failed to create thread for slack receiver");

        thread::Builder::new().name("Chatbot Slack Sender".to_owned()).spawn(move || {
            loop {
                match rx_adapter.recv() {
                    Ok(msg) => {
                        match msg {
                            AdapterMsg::Outgoing(msg) => {
                                let n = uid.fetch_add(1, Ordering::SeqCst);
                                let chan = msg.get_incoming().channel().unwrap();
                                let payload = msg.as_ref();
                                let mut obj = json::Object::new();
                                obj.insert("id".to_string(), Json::I64(n as i64));
                                obj.insert("channel".to_string(), Json::String(chan.to_owned()));
                                obj.insert("type".to_string(), Json::String("message".to_owned()));
                                obj.insert("text".to_string(), Json::String(payload.to_owned()));
                                let json = Json::Object(obj);
                                let slack_msg = Message::Text(json.to_string());
                                slack_tx.send(slack_msg).unwrap();
                            }
                            _ => println!("TODO")
                        }
                    },
                    Err(e) => {
                        println!("error receiving outgoing messages to the slack adapter: {}", e);
                        break
                    }
                }
            }
        }).ok().expect("failed to create thread for slack sender");

        rx_bot
    }
}

#[cfg(test)]
mod tests {
    use adapter::slack::SlackMsg;
    use adapter::slack::string_to_slack_msg;

    #[test]
    fn decode_message() {
        let raw = "{\"type\":\"message\", \
                    \"channel\":\"D04UYUAMW\", \
                    \"user\":\"U02ALMR84\", \
                    \"text\":\"ping\", \
                    \"ts\":\"1432563914.000007\", \
                    \"team\":\"T02ALMR82\"}";

        let slack_msg = string_to_slack_msg(raw).unwrap();

        match slack_msg {
            SlackMsg::Message(data) => {
                assert_eq!(data.text(), "ping");
                assert_eq!(data.channel(), "D04UYUAMW");
                assert_eq!(data.user(), "U02ALMR84");
                assert_eq!(data.ts(), "1432563914.000007");
                assert_eq!(data.team(), "T02ALMR82");
            },
            _ => panic!("Expected SlackMsg::Message")
        }
    }
    #[test]
    fn decode_confirmation_message() {
        let raw = r#"{"ok":true,"reply_to":0,"ts":"1432566639.000014","text":"pong"}"#;

        match string_to_slack_msg(raw).unwrap() {
            SlackMsg::Other => (),
            _ => panic!("expected SlackMsg::Other")
        }
    }

    #[test]
    fn decode_unexpected_type() {
        let raw = r#"{"type":"not_a_slack_msg_type"}"#;

        match string_to_slack_msg(raw).unwrap() {
            SlackMsg::Other => (),
            _ => panic!("expected SlackMsg::Other")
        }
    }
}
<commit_msg>Move SlackAdapter token parsing into ::new<commit_after>extern crate slack;

use std::env;
use std::sync::atomic::{AtomicIsize, Ordering};
use std::sync::mpsc::Sender;
use std::sync::mpsc::Receiver;
use std::sync::mpsc::channel;
use std::thread;

use rustc_serialize::json::Json;
use rustc_serialize::json;
use rustc_serialize::json::DecoderError::MissingFieldError;
use rustc_serialize::Decodable;
use rustc_serialize::Decoder;

use slack::Message;

use message::AdapterMsg;
use message::IncomingMessage;
use adapter::ChatAdapter;

/// SlackAdapter sends and receives messages from the Slack chat service. Until actualy
/// configuration is added, the slack token should be placed in the environment variable
/// `SLACK_BOT_TOKEN`
pub struct SlackAdapter {
    token: String
}

impl SlackAdapter {
    pub fn new() -> SlackAdapter {
        SlackAdapter {
            token: match env::var("SLACK_BOT_TOKEN") {
                Ok(t) => t,
                Err(_) => panic!("Failed to get SLACK_BOT_TOKEN from env")
            }
        }
    }
}

struct MyHandler {
  count: i64,
  tx_bot: Sender<IncomingMessage>,
  tx_adapter: Sender<AdapterMsg>
}

/// Data for a SlackMsg::Message
#[allow(dead_code)]
struct MessageData {
    text: String,
    channel: String,
    user: String,
    ts: String,
    team: String
}

macro_rules! str_accessor {
    ($s:ident) => {
        pub fn $s(&self) -> &str {
            self.$s.as_ref()
        }
    }
}

#[allow(dead_code)]
impl MessageData {
    str_accessor!(text);
    str_accessor!(channel);
    str_accessor!(user);
    str_accessor!(ts);
    str_accessor!(team);
}

/// Incoming slack messages on the websocket api
enum SlackMsg {
    /// A message was sent to a channel
    Message(MessageData),

    /// Some other type of message arrived.
    /// [The list](https://api.slack.com/rtm) is quite extensive, and only the
    /// messages the adapter is concerned with are enumerated here.
    Other
}

impl Decodable for SlackMsg {
    fn decode<D: Decoder>(d: &mut D) -> Result<SlackMsg, D::Error> {
        d.read_struct("root", 0, |root| {
            let msg_type = try!(root.read_struct_field("type", 0, |f| f.read_str() ));

            match msg_type.as_ref() {
                "message" => {
                    Ok(SlackMsg::Message(MessageData {
                        text: try!(root.read_struct_field("text", 0, |f| f.read_str())),
                        channel: try!(root.read_struct_field("channel", 0, |f| f.read_str())),
                        user: try!(root.read_struct_field("user", 0, |f| f.read_str())),
                        ts: try!(root.read_struct_field("ts", 0, |f| f.read_str())),
                        team: try!(root.read_struct_field("team", 0, |f| f.read_str())),
                    }))
                },
                _ => {
                    Ok(SlackMsg::Other)
                }
            }
        })
    }
}

fn string_to_slack_msg(raw: &str) -> Result<SlackMsg, json::DecoderError> {
    // Some messages arriving from the slack client don't have a type. So far I've only
    // witnessed confirmation messages arriving in this fashion. Since they go through the same
    // pipeline as content messages, the decoder should be able to handle them.
    match json::decode::<SlackMsg>(raw) {
        Ok(value) => Ok(value),
        Err(e) => {
            match e {
                MissingFieldError(field) => {
                    match field.as_ref() {
                        "type" => Ok(SlackMsg::Other),
                        _ => Err(MissingFieldError(field))
                    }
                },
                _ => Err(e)
            }
        }
    }
}

#[allow(unused_variables)]
impl slack::MessageHandler for MyHandler {
    fn on_receive(&mut self, cli: &mut slack::RtmClient, raw: &str) {
        println!("Received[{}]: {}", self.count, raw.to_string());
        self.count = self.count + 1;

        match string_to_slack_msg(raw) {
            Ok(slack_msg) => {
                match slack_msg {
                    SlackMsg::Message(msg) => {
                        let incoming = IncomingMessage::new("SlackAdapter".to_owned(), None,
                            Some(msg.channel().to_owned()), Some(msg.user().to_owned()),
                            msg.text().to_owned(), self.tx_adapter.clone());

                        self.tx_bot.send(incoming).ok().expect("Bot unable to process messages");
                    },
                    _ => ()
                }
            },
            Err(e) => {
                println!("error decoding slack message: {:?}", e);
                println!("please consider reporting this to jwilm/chatbot as it is probably a bug");
            }
        }
    }

    fn on_ping(&mut self, cli: &mut slack::RtmClient) {
        println!("<on_ping>");
    }

    fn on_close(&mut self, cli: &mut slack::RtmClient) {
        println!("<on_close>");
    }

    fn on_connect(&mut self, cli: &mut slack::RtmClient) {
        println!("<on_connect>");
        // let _ = cli.send_message("#general", "bla");
    }
}

impl ChatAdapter for SlackAdapter {
    /// SlackAdapter name
    fn get_name(&self) -> &str {
        "SlackAdapter"
    }

    fn process_events(&self) -> Receiver<IncomingMessage> {
        println!("SlackAdapter: process_events");
        let (tx_bot, rx_bot) = channel();
        let (tx_adapter, rx_adapter) = channel();

        let uid = AtomicIsize::new(0);

        let mut cli = slack::RtmClient::new();
        let (client, slack_rx) = cli.login(self.token.as_ref()).unwrap();
        let slack_tx = cli.get_outs().unwrap();

        thread::Builder::new().name("Chatbot Slack Receiver".to_owned()).spawn(move || {
            let mut handler = MyHandler{count: 0, tx_bot: tx_bot, tx_adapter: tx_adapter};
            cli.run::<MyHandler>(&mut handler, client, slack_rx).unwrap();
        }).ok().expect("failed to create thread for slack receiver");

        thread::Builder::new().name("Chatbot Slack Sender".to_owned()).spawn(move || {
            loop {
                match rx_adapter.recv() {
                    Ok(msg) => {
                        match msg {
                            AdapterMsg::Outgoing(msg) => {
                                let n = uid.fetch_add(1, Ordering::SeqCst);
                                let chan = msg.get_incoming().channel().unwrap();
                                let payload = msg.as_ref();
                                let mut obj = json::Object::new();
                                obj.insert("id".to_string(), Json::I64(n as i64));
                                obj.insert("channel".to_string(), Json::String(chan.to_owned()));
                                obj.insert("type".to_string(), Json::String("message".to_owned()));
                                obj.insert("text".to_string(), Json::String(payload.to_owned()));
                                let json = Json::Object(obj);
                                let slack_msg = Message::Text(json.to_string());
                                slack_tx.send(slack_msg).unwrap();
                            }
                            _ => println!("TODO")
                        }
                    },
                    Err(e) => {
                        println!("error receiving outgoing messages to the slack adapter: {}", e);
                        break
                    }
                }
            }
        }).ok().expect("failed to create thread for slack sender");

        rx_bot
    }
}

#[cfg(test)]
mod tests {
    use adapter::slack::SlackMsg;
    use adapter::slack::string_to_slack_msg;

    #[test]
    fn decode_message() {
        let raw = "{\"type\":\"message\", \
                    \"channel\":\"D04UYUAMW\", \
                    \"user\":\"U02ALMR84\", \
                    \"text\":\"ping\", \
                    \"ts\":\"1432563914.000007\", \
                    \"team\":\"T02ALMR82\"}";

        let slack_msg = string_to_slack_msg(raw).unwrap();

        match slack_msg {
            SlackMsg::Message(data) => {
                assert_eq!(data.text(), "ping");
                assert_eq!(data.channel(), "D04UYUAMW");
                assert_eq!(data.user(), "U02ALMR84");
                assert_eq!(data.ts(), "1432563914.000007");
                assert_eq!(data.team(), "T02ALMR82");
            },
            _ => panic!("Expected SlackMsg::Message")
        }
    }
    #[test]
    fn decode_confirmation_message() {
        let raw = r#"{"ok":true,"reply_to":0,"ts":"1432566639.000014","text":"pong"}"#;

        match string_to_slack_msg(raw).unwrap() {
            SlackMsg::Other => (),
            _ => panic!("expected SlackMsg::Other")
        }
    }

    #[test]
    fn decode_unexpected_type() {
        let raw = r#"{"type":"not_a_slack_msg_type"}"#;

        match string_to_slack_msg(raw).unwrap() {
            SlackMsg::Other => (),
            _ => panic!("expected SlackMsg::Other")
        }
    }
}
<|endoftext|>


<commit_before>//! Algorithms capable of signing and verifying tokens. By default only the
//! `hmac` crate's `Hmac` type is supported. For more algorithms, enable the
//! feature `openssl` and see the [openssl](openssl/index.html)
//! module. The `none` algorithm is explicitly not supported.
//! ## Examples
//! ```
//! extern crate hmac;
//! extern crate sha2;
//!
//! use hmac::{Hmac, Mac};
//! use sha2::Sha256;
//!
//! let hs256_key: Hmac<Sha256> = Hmac::new_varkey(b"some-secret").unwrap();
//! ```

use crate::error::Error;

#[cfg(feature = "openssl")]
pub mod openssl;
pub mod rust_crypto;

/// The type of an algorithm, corresponding to the
/// [JWA](https://tools.ietf.org/html/rfc7518) specification.
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum AlgorithmType {
    Hs256,
    Hs384,
    Hs512,
    Rs256,
    Rs384,
    Rs512,
    Es256,
    Es384,
    Es512,
    Ps256,
    Ps384,
    Ps512,
    #[serde(rename = "none")]
    None,
}

impl Default for AlgorithmType {
    fn default() -> Self {
        AlgorithmType::Hs256
    }
}

/// An algorithm capable of signing base64 encoded header and claims strings.
/// strings.
pub trait SigningAlgorithm {
    fn algorithm_type(&self) -> AlgorithmType;

    fn sign(&self, header: &str, claims: &str) -> Result<String, Error>;
}

/// An algorithm capable of verifying base64 encoded header and claims strings.
pub trait VerifyingAlgorithm {
    fn algorithm_type(&self) -> AlgorithmType;

    fn verify_bytes(&self, header: &str, claims: &str, signature: &[u8]) -> Result<bool, Error>;

    fn verify(&self, header: &str, claims: &str, signature: &str) -> Result<bool, Error> {
        let signature_bytes = base64::decode_config(signature, base64::URL_SAFE_NO_PAD)?;
        self.verify_bytes(header, claims, &*signature_bytes)
    }
}
<commit_msg>Add AsRef blanket implementations<commit_after>//! Algorithms capable of signing and verifying tokens. By default only the
//! `hmac` crate's `Hmac` type is supported. For more algorithms, enable the
//! feature `openssl` and see the [openssl](openssl/index.html)
//! module. The `none` algorithm is explicitly not supported.
//! ## Examples
//! ```
//! extern crate hmac;
//! extern crate sha2;
//!
//! use hmac::{Hmac, Mac};
//! use sha2::Sha256;
//!
//! let hs256_key: Hmac<Sha256> = Hmac::new_varkey(b"some-secret").unwrap();
//! ```

use crate::error::Error;

#[cfg(feature = "openssl")]
pub mod openssl;
pub mod rust_crypto;

/// The type of an algorithm, corresponding to the
/// [JWA](https://tools.ietf.org/html/rfc7518) specification.
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum AlgorithmType {
    Hs256,
    Hs384,
    Hs512,
    Rs256,
    Rs384,
    Rs512,
    Es256,
    Es384,
    Es512,
    Ps256,
    Ps384,
    Ps512,
    #[serde(rename = "none")]
    None,
}

impl Default for AlgorithmType {
    fn default() -> Self {
        AlgorithmType::Hs256
    }
}

/// An algorithm capable of signing base64 encoded header and claims strings.
/// strings.
pub trait SigningAlgorithm {
    fn algorithm_type(&self) -> AlgorithmType;

    fn sign(&self, header: &str, claims: &str) -> Result<String, Error>;
}

/// An algorithm capable of verifying base64 encoded header and claims strings.
pub trait VerifyingAlgorithm {
    fn algorithm_type(&self) -> AlgorithmType;

    fn verify_bytes(&self, header: &str, claims: &str, signature: &[u8]) -> Result<bool, Error>;

    fn verify(&self, header: &str, claims: &str, signature: &str) -> Result<bool, Error> {
        let signature_bytes = base64::decode_config(signature, base64::URL_SAFE_NO_PAD)?;
        self.verify_bytes(header, claims, &*signature_bytes)
    }
}

// TODO: investigate if these AsRef impls are necessary
impl<T: AsRef<dyn VerifyingAlgorithm>> VerifyingAlgorithm for T {
    fn algorithm_type(&self) -> AlgorithmType {
        self.as_ref().algorithm_type()
    }

    fn verify_bytes(&self, header: &str, claims: &str, signature: &[u8]) -> Result<bool, Error> {
        self.as_ref().verify_bytes(header, claims, signature)
    }
}

impl<T: AsRef<dyn SigningAlgorithm>> SigningAlgorithm for T {
    fn algorithm_type(&self) -> AlgorithmType {
        self.as_ref().algorithm_type()
    }

    fn sign(&self, header: &str, claims: &str) -> Result<String, Error> {
        self.as_ref().sign(header, claims)
    }
}
<|endoftext|>


<commit_before>// Copyright © 2018 Cormac O'Brien
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
// and associated documentation files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

extern crate byteorder;
extern crate num;
extern crate pnet;
extern crate richter;

use byteorder::{LittleEndian, ReadBytesExt};
use num::FromPrimitive;
use std::io::Cursor;
use std::str::{self, FromStr};
use pnet::packet::Packet;
use pnet::packet::udp::UdpPacket;
use pnet::packet::ip::IpNextHeaderProtocols::Udp;
use pnet::transport::{self, TransportChannelType};
use richter::qw::{self, ClCmd, MoveDeltaFlags, SvCmd};
use richter::util;

static USAGE: &'static str = "Usage: cl-sniff <client IP> <client port> <server IP> <server port>";

fn transcribe_clcmd<'a>(src: &'a [u8]) -> String {
    let mut result = String::new();
    let mut curs = Cursor::new(src);

    let qport = curs.read_u16::<LittleEndian>().unwrap();
    result += &format!("qport={} ", qport);

    let opcode = match curs.read_u8() {
        Ok(o) => o,
        Err(why) => {
            result += &format!("ERROR: {}", why);
            return result;
        }
    };

    let clcmd = match ClCmd::from_u8(opcode) {
        Some(c) => c,
        None => {
            result += &format!("ERROR: Unrecognized opcode {}", opcode);
            return result;
        }
    };

    match clcmd {

        // TODO: use MoveDelta::from_bytes
        ClCmd::Move => {
            result += &format!("Move ");
            result += &format!("crc={} ", curs.read_u8().unwrap());
            result += &format!("loss={} ", curs.read_u8().unwrap());
            result += "\n";

            for i in 0..3 {
                result += &format!("| [D{}] ", i);

                let flags = MoveDeltaFlags::from_bits(curs.read_u8().unwrap()).unwrap();

                result += &format!("flags={:08b} ", flags.bits());

                if flags.contains(MoveDeltaFlags::MOVE_ANGLE1) {
                    result += &format!("angle1={} ", curs.read_u16::<LittleEndian>().unwrap());
                }

                if flags.contains(MoveDeltaFlags::MOVE_ANGLE2) {
                    result += &format!("angle2={} ", curs.read_u16::<LittleEndian>().unwrap());
                }

                if flags.contains(MoveDeltaFlags::MOVE_ANGLE3) {
                    result += &format!("angle3={} ", curs.read_u16::<LittleEndian>().unwrap());
                }

                if flags.contains(MoveDeltaFlags::MOVE_FORWARD) {
                    result += &format!("forward={} ", curs.read_u16::<LittleEndian>().unwrap());
                }

                if flags.contains(MoveDeltaFlags::MOVE_SIDE) {
                    result += &format!("side={} ", curs.read_u16::<LittleEndian>().unwrap());
                }

                if flags.contains(MoveDeltaFlags::MOVE_UP) {
                    result += &format!("up={} ", curs.read_u16::<LittleEndian>().unwrap());
                }

                if flags.contains(MoveDeltaFlags::MOVE_BUTTONS) {
                    result += &format!("buttons={} ", curs.read_u8().unwrap());
                }

                if flags.contains(MoveDeltaFlags::MOVE_IMPULSE) {
                    result += &format!("impulse={} ", curs.read_u8().unwrap());
                }

                result += &format!("msec={} ", curs.read_u8().unwrap());
                result += "\n";
            }
        }

        ClCmd::StringCmd => {
            let cmd = util::read_cstring(&mut curs).unwrap();
            result += &format!("cmd=\"{}\"", cmd);
        }

        c => {
            result += &format!("{:?} ", c);
        }
    }

    return result;
}

fn transcribe_svcmd<'a>(src: &'a [u8]) -> String {
    let mut result = String::new();
    let mut curs = Cursor::new(src);

    let cmdbyte = curs.read_u8().unwrap();

    match SvCmd::from_u8(cmdbyte).unwrap() {
        SvCmd::Disconnect => {
            result += "disconnect";
        }

        SvCmd::ModelList => {
            result += "modellist ";

            let modellist = qw::ModelListPacket::from_bytes(&mut curs).unwrap();

            result += &format!("count={} ", modellist.get_count());

            let list = modellist.get_list();
            result += "\nMODEL LIST\n==========\n";
            for model in list.into_iter() {
                result += &format!("\"{}\"\n", model);
            }
            result += "==========\n";
            result += &format!("progress={}\n", modellist.get_progress());
        }

        SvCmd::PlayerInfo => {
            result += "playerinfo ";

            let playerinfo = qw::PlayerInfoPacket::from_bytes(&mut curs).unwrap();
            result += &format!("{:#?} ", playerinfo);
        }

        SvCmd::Print => {
            result += "print ";

            let print_type = qw::PrintType::from_u8(curs.read_u8().unwrap()).unwrap();
            result += &format!("type={:?} ", print_type);

            let msg = util::read_cstring(&mut curs).unwrap();
            result += &format!("msg=\"{}\"", msg);
        }

        SvCmd::ServerData => {
            result += "serverdata ";
            let data = qw::ServerDataPacket::from_bytes(&mut curs).unwrap();

            result += &format!("proto={} ", data.get_protocol_version());
            result += &format!("servercount={} ", data.get_server_count());
            result += &format!("gamedir=\"{}\" ", data.get_game_directory());
            result += &format!("playerno={} ", data.get_player_number());
            result += &format!("levelname=\"{}\" ", data.get_level_name());
            result += &format!("gravity={} ", data.get_gravity());
            result += &format!("stopspeed={} ", data.get_stop_speed());
            result += &format!("maxspeed={} ", data.get_max_speed());
            result += &format!("spectatormaxspeed={} ", data.get_spec_max_speed());
            result += &format!("accelerate={} ", data.get_accelerate());
            result += &format!("airaccelerate={} ", data.get_air_accelerate());
            result += &format!("wateraccelerate={} ", data.get_water_accelerate());
            result += &format!("friction={} ", data.get_friction());
            result += &format!("waterfriction={} ", data.get_water_friction());
            result += &format!("entgravity={} ", data.get_ent_gravity());
        }

        SvCmd::SoundList => {
            result += "soundlist ";

            let soundlist = qw::SoundListPacket::from_bytes(&mut curs).unwrap();

            result += &format!("count={} ", soundlist.get_count());

            let list = soundlist.get_list();
            result += "\nSOUND LIST\n==========\n";
            for sound in list.into_iter() {
                result += &format!("\"{}\"\n", sound);
            }
            result += "==========\n";
            result += &format!("progress={}\n", soundlist.get_progress());
        }

        s => {
            result += &format!("{:?} ", s);
        }
    }

    return result;
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() != 5 {
        println!("{}", USAGE);
        std::process::exit(1);
    }

    let client_ip = std::net::Ipv4Addr::from_str(&args[1]).unwrap();
    let client_port = u16::from_str(&args[2]).unwrap();
    let server_ip = std::net::Ipv4Addr::from_str(&args[3]).unwrap();
    let server_port = u16::from_str(&args[4]).unwrap();

    let (_, mut rx) =
        match pnet::transport::transport_channel(4096, TransportChannelType::Layer3(Udp)) {
            Ok((tx, rx)) => (tx, rx),
            Err(why) => panic!("Error creating channel: {}", why),
        };

    let mut iter = transport::ipv4_packet_iter(&mut rx);
    loop {
        match iter.next() {
            Ok((packet, _)) => {
                let udp_packet = UdpPacket::new(packet.payload()).unwrap();
                let dest_ip = packet.get_destination();
                let dest_port = udp_packet.get_destination();

                if dest_ip == server_ip && dest_port == server_port {
                    print!("CL: ");
                } else if dest_ip == client_ip && dest_port == client_port {
                    print!("SV: ");
                } else {
                    continue;
                }

                let qw_packet = qw::Packet::new(udp_packet.payload()).unwrap();
                match qw_packet {
                    qw::Packet::OutOfBand(oob_packet) => {
                        match oob_packet {
                            qw::OutOfBandPacket::GetChallenge => print!("getchallenge"),
                            qw::OutOfBandPacket::Challenge(challenge) => {
                                print!("challenge={}", challenge)
                            }
                            qw::OutOfBandPacket::Connect(conn_packet) => print!("{}", conn_packet),
                            qw::OutOfBandPacket::Accept => print!("accept"),
                            _ => (),
                        }
                    }

                    qw::Packet::NetChan(nc_packet) => {
                        print!("seq={} [", nc_packet.get_sequence());
                        if nc_packet.get_sequence_reliable() {
                            print!("R");
                        } else {
                            print!(" ");
                        }
                        print!("] ack={} ", nc_packet.get_ack_sequence());

                        if dest_ip == server_ip && dest_port == server_port {
                            print!("{} ", transcribe_clcmd(nc_packet.payload()));
                        } else if dest_ip == client_ip && dest_port == client_port {
                            if nc_packet.payload().len() != 0 {
                                print!("{} ", transcribe_svcmd(nc_packet.payload()));
                            } else {
                                print!("empty");
                            }
                        }
                    }
                }

                println!("");
            }

            Err(why) => panic!("Error reading packet: {}", why),
        }
    }
}
<commit_msg>Remove cl-sniff<commit_after><|endoftext|>


<commit_before>use std;

use cgmath::Point2;
use gfx;
use specs;
use specs::prelude::{Read, ReadStorage, WriteStorage};

use crate::character::{character_stats::CharacterStats, controls::CharacterInputState};
use crate::critter::{CharacterSprite, CritterData};
use crate::data;
use crate::game::constants::{AMMO_POSITIONS, ASPECT_RATIO, CHARACTER_SHEET_TOTAL_WIDTH, RUN_SPRITE_OFFSET, SPRITE_OFFSET, VIEW_DISTANCE};
use crate::gfx_app::{ColorFormat, DepthFormat};
use crate::gfx_app::mouse_controls::MouseInputState;
use crate::graphics::{camera::CameraInputState, dimensions::{Dimensions, get_projection, get_view_matrix}, get_orientation_from_center, orientation::{Orientation, Stance}, overlaps, texture::load_texture};
use crate::graphics::mesh::RectangularMesh;
use crate::graphics::texture::Texture;
use crate::shaders::{CharacterSheet, critter_pipeline, Position, Projection};
use crate::terrain_object::{terrain_objects::TerrainObjects, TerrainObjectDrawable, TerrainTexture};
use crate::zombie::{ZombieDrawable, zombies::Zombies};

pub mod controls;
mod character_stats;

const SHADER_VERT: &[u8] = include_bytes!("../shaders/character.v.glsl");
const SHADER_FRAG: &[u8] = include_bytes!("../shaders/character.f.glsl");

#[derive(Clone)]
pub struct CharacterDrawable {
  pub stats: CharacterStats,
  projection: Projection,
  pub position: Position,
  orientation: Orientation,
  pub stance: Stance,
  direction: Orientation,
}

impl CharacterDrawable {
  pub fn new() -> CharacterDrawable {
    let view = get_view_matrix(VIEW_DISTANCE);
    let projection = get_projection(view, ASPECT_RATIO);
    let stats = CharacterStats::new();
    CharacterDrawable {
      stats,
      projection,
      position: Position::origin(),
      orientation: Orientation::Right,
      stance: Stance::Walking,
      direction: Orientation::Right,
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, mouse_input: &MouseInputState,
                dimensions: &Dimensions, objs: &mut Vec<TerrainObjectDrawable>, zombies: &[ZombieDrawable]) {
    self.projection = *world_to_clip;

    fn zombie_not_dead(z: &ZombieDrawable) -> bool {
      z.stance != Stance::NormalDeath &&
        z.stance != Stance::CriticalDeath
    }

    for idx in 0..AMMO_POSITIONS.len() {
      self.ammo_pick_up(ci.movement, objs, idx);
    }

    if !cfg!(feature = "godmode") &&
      zombies.iter()
        .any(|z|
          zombie_not_dead(z) &&
            overlaps(ci.movement,
                     ci.movement - z.position,
                     15.0,
                     30.0)) {
      self.stance = Stance::NormalDeath;
      println!("Player died");
      std::process::exit(0);
    }

    if self.stance != Stance::NormalDeath {
      if ci.is_shooting && mouse_input.left_click_point.is_some() && !ci.is_colliding {
        self.stance = Stance::Firing;
        self.orientation = get_orientation_from_center(mouse_input, dimensions);
      } else if ci.is_colliding {
        self.stance = Stance::Still;
      } else {
        self.stance = Stance::Walking;
        self.orientation = ci.orientation;
      }
    }
  }

  fn ammo_pick_up(&mut self, movement: Position, objs: &mut Vec<TerrainObjectDrawable>, idx: usize) {
    if objs[idx].object_type == TerrainTexture::Ammo && overlaps(movement, movement - objs[idx].position, 20.0, 20.0) {
      self.stats.magazines = 2;
      objs.remove(idx);
    }
  }
}

impl Default for CharacterDrawable {
  fn default() -> Self {
    CharacterDrawable::new()
  }
}

impl specs::prelude::Component for CharacterDrawable {
  type Storage = specs::storage::VecStorage<CharacterDrawable>;
}

pub struct CharacterDrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, critter_pipeline::Data<R>>,
  data: Vec<CritterData>,
}

impl<R: gfx::Resources> CharacterDrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> CharacterDrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let charter_bytes = &include_bytes!("../../assets/character.png")[..];
    let char_texture = load_texture(factory, charter_bytes);

    let rect_mesh =
      RectangularMesh::new(factory, Texture::new(char_texture, None), Point2::new(20.0, 28.0));

    let pso = factory.create_pipeline_simple(SHADER_VERT, SHADER_FRAG, critter_pipeline::new())
      .expect("Character shader loading error");

    let pipeline_data = critter_pipeline::Data {
      vbuf: rect_mesh.mesh.vertex_buffer,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (rect_mesh.mesh.texture.raw, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    CharacterDrawSystem {
      bundle: gfx::Bundle::new(rect_mesh.mesh.slice, pso, pipeline_data),
      data,
    }
  }

  fn get_next_sprite(&self, character_idx: usize, character_fire_idx: usize, drawable: &mut CharacterDrawable) -> CharacterSheet {
    let sprite_idx =
      if drawable.orientation == Orientation::Still && drawable.stance == Stance::Walking {
        (drawable.direction as usize * 28 + RUN_SPRITE_OFFSET)
      } else if drawable.stance == Stance::Walking {
        drawable.direction = drawable.orientation;
        (drawable.orientation as usize * 28 + character_idx + RUN_SPRITE_OFFSET)
      } else {
        (drawable.orientation as usize * 8 + character_fire_idx)
      } as usize;

    let elements_x = CHARACTER_SHEET_TOTAL_WIDTH / (self.data[sprite_idx].data[2] + SPRITE_OFFSET);
    CharacterSheet {
      x_div: elements_x,
      y_div: 0.0,
      row_idx: 0,
      index: sprite_idx as f32,
    }
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb,
                                   &self.get_next_sprite(character.character_idx,
                                                         character.character_fire_idx,
                                                         &mut drawable));
    self.bundle.encode(encoder);
  }
}

pub struct PreDrawSystem;

impl<'a> specs::prelude::System<'a> for PreDrawSystem {
  type SystemData = (WriteStorage<'a, CharacterDrawable>,
                     ReadStorage<'a, CameraInputState>,
                     ReadStorage<'a, CharacterInputState>,
                     ReadStorage<'a, MouseInputState>,
                     WriteStorage<'a, TerrainObjects>,
                     ReadStorage<'a, Zombies>,
                     Read<'a, Dimensions>);

  fn run(&mut self, (mut character, camera_input, character_input, mouse_input, mut terrain_objects, zombies, dim): Self::SystemData) {
    use specs::join::Join;

    for (c, camera, ci, mi, to, zs) in (&mut character, &camera_input, &character_input, &mouse_input, &mut terrain_objects, &zombies).join() {
      let world_to_clip = dim.world_to_projection(camera);
      c.update(&world_to_clip, ci, mi, &dim, &mut to.objects, &zs.zombies);
    }
  }
}
<commit_msg>Remove useless if-guard<commit_after>use std;

use cgmath::Point2;
use gfx;
use specs;
use specs::prelude::{Read, ReadStorage, WriteStorage};

use crate::character::{character_stats::CharacterStats, controls::CharacterInputState};
use crate::critter::{CharacterSprite, CritterData};
use crate::data;
use crate::game::constants::{AMMO_POSITIONS, ASPECT_RATIO, CHARACTER_SHEET_TOTAL_WIDTH, RUN_SPRITE_OFFSET, SPRITE_OFFSET, VIEW_DISTANCE};
use crate::gfx_app::{ColorFormat, DepthFormat};
use crate::gfx_app::mouse_controls::MouseInputState;
use crate::graphics::{camera::CameraInputState, dimensions::{Dimensions, get_projection, get_view_matrix}, get_orientation_from_center, orientation::{Orientation, Stance}, overlaps, texture::load_texture};
use crate::graphics::mesh::RectangularMesh;
use crate::graphics::texture::Texture;
use crate::shaders::{CharacterSheet, critter_pipeline, Position, Projection};
use crate::terrain_object::{terrain_objects::TerrainObjects, TerrainObjectDrawable, TerrainTexture};
use crate::zombie::{ZombieDrawable, zombies::Zombies};

pub mod controls;
mod character_stats;

const SHADER_VERT: &[u8] = include_bytes!("../shaders/character.v.glsl");
const SHADER_FRAG: &[u8] = include_bytes!("../shaders/character.f.glsl");

#[derive(Clone)]
pub struct CharacterDrawable {
  pub stats: CharacterStats,
  projection: Projection,
  pub position: Position,
  orientation: Orientation,
  pub stance: Stance,
  direction: Orientation,
}

impl CharacterDrawable {
  pub fn new() -> CharacterDrawable {
    let view = get_view_matrix(VIEW_DISTANCE);
    let projection = get_projection(view, ASPECT_RATIO);
    let stats = CharacterStats::new();
    CharacterDrawable {
      stats,
      projection,
      position: Position::origin(),
      orientation: Orientation::Right,
      stance: Stance::Walking,
      direction: Orientation::Right,
    }
  }

  pub fn update(&mut self, world_to_clip: &Projection, ci: &CharacterInputState, mouse_input: &MouseInputState,
                dimensions: &Dimensions, objs: &mut Vec<TerrainObjectDrawable>, zombies: &[ZombieDrawable]) {
    self.projection = *world_to_clip;

    fn zombie_not_dead(z: &ZombieDrawable) -> bool {
      z.stance != Stance::NormalDeath &&
        z.stance != Stance::CriticalDeath
    }

    for idx in 0..AMMO_POSITIONS.len() {
      self.ammo_pick_up(ci.movement, objs, idx);
    }

    if !cfg!(feature = "godmode") &&
      zombies.iter()
        .any(|z|
          zombie_not_dead(z) &&
            overlaps(ci.movement,
                     ci.movement - z.position,
                     15.0,
                     30.0)) {
      self.stance = Stance::NormalDeath;
      println!("Player died");
      std::process::exit(0);
    }

    if ci.is_shooting && mouse_input.left_click_point.is_some() && !ci.is_colliding {
      self.stance = Stance::Firing;
      self.orientation = get_orientation_from_center(mouse_input, dimensions);
    } else if ci.is_colliding {
      self.stance = Stance::Still;
    } else {
      self.stance = Stance::Walking;
      self.orientation = ci.orientation;
    }
  }

  fn ammo_pick_up(&mut self, movement: Position, objs: &mut Vec<TerrainObjectDrawable>, idx: usize) {
    if objs[idx].object_type == TerrainTexture::Ammo && overlaps(movement, movement - objs[idx].position, 20.0, 20.0) {
      self.stats.magazines = 2;
      objs.remove(idx);
    }
  }
}

impl Default for CharacterDrawable {
  fn default() -> Self {
    CharacterDrawable::new()
  }
}

impl specs::prelude::Component for CharacterDrawable {
  type Storage = specs::storage::VecStorage<CharacterDrawable>;
}

pub struct CharacterDrawSystem<R: gfx::Resources> {
  bundle: gfx::pso::bundle::Bundle<R, critter_pipeline::Data<R>>,
  data: Vec<CritterData>,
}

impl<R: gfx::Resources> CharacterDrawSystem<R> {
  pub fn new<F>(factory: &mut F,
                rtv: gfx::handle::RenderTargetView<R, ColorFormat>,
                dsv: gfx::handle::DepthStencilView<R, DepthFormat>) -> CharacterDrawSystem<R>
    where F: gfx::Factory<R> {
    use gfx::traits::FactoryExt;

    let charter_bytes = &include_bytes!("../../assets/character.png")[..];
    let char_texture = load_texture(factory, charter_bytes);

    let rect_mesh =
      RectangularMesh::new(factory, Texture::new(char_texture, None), Point2::new(20.0, 28.0));

    let pso = factory.create_pipeline_simple(SHADER_VERT, SHADER_FRAG, critter_pipeline::new())
      .expect("Character shader loading error");

    let pipeline_data = critter_pipeline::Data {
      vbuf: rect_mesh.mesh.vertex_buffer,
      projection_cb: factory.create_constant_buffer(1),
      position_cb: factory.create_constant_buffer(1),
      character_sprite_cb: factory.create_constant_buffer(1),
      charactersheet: (rect_mesh.mesh.texture.raw, factory.create_sampler_linear()),
      out_color: rtv,
      out_depth: dsv,
    };

    let data = data::load_character();

    CharacterDrawSystem {
      bundle: gfx::Bundle::new(rect_mesh.mesh.slice, pso, pipeline_data),
      data,
    }
  }

  fn get_next_sprite(&self, character_idx: usize, character_fire_idx: usize, drawable: &mut CharacterDrawable) -> CharacterSheet {
    let sprite_idx =
      if drawable.orientation == Orientation::Still && drawable.stance == Stance::Walking {
        (drawable.direction as usize * 28 + RUN_SPRITE_OFFSET)
      } else if drawable.stance == Stance::Walking {
        drawable.direction = drawable.orientation;
        (drawable.orientation as usize * 28 + character_idx + RUN_SPRITE_OFFSET)
      } else {
        (drawable.orientation as usize * 8 + character_fire_idx)
      } as usize;

    let elements_x = CHARACTER_SHEET_TOTAL_WIDTH / (self.data[sprite_idx].data[2] + SPRITE_OFFSET);
    CharacterSheet {
      x_div: elements_x,
      y_div: 0.0,
      row_idx: 0,
      index: sprite_idx as f32,
    }
  }

  pub fn draw<C>(&mut self,
                 mut drawable: &mut CharacterDrawable,
                 character: &CharacterSprite,
                 encoder: &mut gfx::Encoder<R, C>)
    where C: gfx::CommandBuffer<R> {
    encoder.update_constant_buffer(&self.bundle.data.projection_cb, &drawable.projection);
    encoder.update_constant_buffer(&self.bundle.data.position_cb, &drawable.position);
    encoder.update_constant_buffer(&self.bundle.data.character_sprite_cb,
                                   &self.get_next_sprite(character.character_idx,
                                                         character.character_fire_idx,
                                                         &mut drawable));
    self.bundle.encode(encoder);
  }
}

pub struct PreDrawSystem;

impl<'a> specs::prelude::System<'a> for PreDrawSystem {
  type SystemData = (WriteStorage<'a, CharacterDrawable>,
                     ReadStorage<'a, CameraInputState>,
                     ReadStorage<'a, CharacterInputState>,
                     ReadStorage<'a, MouseInputState>,
                     WriteStorage<'a, TerrainObjects>,
                     ReadStorage<'a, Zombies>,
                     Read<'a, Dimensions>);

  fn run(&mut self, (mut character, camera_input, character_input, mouse_input, mut terrain_objects, zombies, dim): Self::SystemData) {
    use specs::join::Join;

    for (c, camera, ci, mi, to, zs) in (&mut character, &camera_input, &character_input, &mouse_input, &mut terrain_objects, &zombies).join() {
      let world_to_clip = dim.world_to_projection(camera);
      c.update(&world_to_clip, ci, mi, &dim, &mut to.objects, &zs.zombies);
    }
  }
}
<|endoftext|>