<commit_before>use std::fmt;
use std::slice;

use crate::reflect::value::value_ref::ReflectValueRef;
use crate::reflect::value::ProtobufValue;

use crate::reflect::dynamic::repeated::DynamicRepeated;
use crate::reflect::reflect_eq::ReflectEq;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::ProtobufValueSized;
use crate::reflect::ReflectValueBox;
use crate::reflect::RuntimeTypeBox;

pub(crate) trait ReflectRepeated: Sync + 'static + fmt::Debug {
    fn reflect_iter(&self) -> ReflectRepeatedIter;
    fn len(&self) -> usize;
    fn get(&self, index: usize) -> ReflectValueRef;
    fn set(&mut self, index: usize, value: ReflectValueBox);
    fn push(&mut self, value: ReflectValueBox);
    fn clear(&mut self);
    fn element_type(&self) -> RuntimeTypeBox;
}

impl<V: ProtobufValueSized> ReflectRepeated for Vec<V> {
    fn reflect_iter<'a>(&'a self) -> ReflectRepeatedIter<'a> {
        ReflectRepeatedIter {
            imp: Box::new(ReflectRepeatedIterImplSlice::<'a, V> { iter: self.iter() }),
        }
    }

    fn len(&self) -> usize {
        Vec::len(self)
    }

    fn get(&self, index: usize) -> ReflectValueRef {
        V::as_ref(&self[index])
    }

    fn set(&mut self, index: usize, value: ReflectValueBox) {
        let value = value.downcast().expect("wrong type");
        self[index] = value;
    }

    fn push(&mut self, value: ReflectValueBox) {
        let value = value.downcast().expect("wrong type");
        self.push(value)
    }

    fn clear(&mut self) {
        self.clear()
    }

    fn element_type(&self) -> RuntimeTypeBox {
        V::runtime_type_box()
    }
}

// useless
impl<V: ProtobufValueSized> ReflectRepeated for [V] {
    fn reflect_iter<'a>(&'a self) -> ReflectRepeatedIter<'a> {
        ReflectRepeatedIter {
            imp: Box::new(ReflectRepeatedIterImplSlice::<'a, V> { iter: self.iter() }),
        }
    }

    fn len(&self) -> usize {
        <[_]>::len(self)
    }

    fn get(&self, index: usize) -> ReflectValueRef {
        V::as_ref(&self[index])
    }

    fn set(&mut self, index: usize, value: ReflectValueBox) {
        let value = value.downcast().expect("wrong type");
        self[index] = value;
    }

    fn push(&mut self, _value: ReflectValueBox) {
        panic!("push is not possible for [V]");
    }

    fn clear(&mut self) {
        panic!("clear is not possible for [V]");
    }

    fn element_type(&self) -> RuntimeTypeBox {
        V::runtime_type_box()
    }
}

trait ReflectRepeatedIterTrait<'a> {
    fn next(&mut self) -> Option<&'a dyn ProtobufValue>;
}

struct ReflectRepeatedIterImplSlice<'a, V: ProtobufValue + 'static> {
    iter: slice::Iter<'a, V>,
}

impl<'a, V: ProtobufValue + 'static> ReflectRepeatedIterTrait<'a>
    for ReflectRepeatedIterImplSlice<'a, V>
{
    fn next(&mut self) -> Option<&'a dyn ProtobufValue> {
        self.iter.next().map(|v| v as &dyn ProtobufValue)
    }
}

pub struct ReflectRepeatedIter<'a> {
    imp: Box<dyn ReflectRepeatedIterTrait<'a> + 'a>,
}

impl<'a> Iterator for ReflectRepeatedIter<'a> {
    type Item = &'a dyn ProtobufValue;

    fn next(&mut self) -> Option<Self::Item> {
        self.imp.next()
    }
}

impl<'a> IntoIterator for &'a dyn ReflectRepeated {
    type Item = &'a dyn ProtobufValue;
    type IntoIter = ReflectRepeatedIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.reflect_iter()
    }
}

#[derive(Clone)]
enum ReflectRepeatedRefImpl<'a> {
    Generated(&'a dyn ReflectRepeated),
    DynamicEmpty(DynamicRepeated),
}

impl<'a> fmt::Debug for ReflectRepeatedRefImpl<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ReflectRepeatedRefImpl::Generated(r) => fmt::Debug::fmt(r, f),
            ReflectRepeatedRefImpl::DynamicEmpty(r) => fmt::Debug::fmt(r, f),
        }
    }
}

/// Dynamic reference to repeated field
#[derive(Clone)]
pub struct ReflectRepeatedRef<'a> {
    imp: ReflectRepeatedRefImpl<'a>,
}

/// Dynamic mutable reference to repeated field
pub struct ReflectRepeatedMut<'a> {
    repeated: &'a mut dyn ReflectRepeated,
}

impl<'a> ReflectRepeatedRef<'a> {
    pub(crate) fn new(repeated: &'a dyn ReflectRepeated) -> ReflectRepeatedRef<'a> {
        ReflectRepeatedRef {
            imp: ReflectRepeatedRefImpl::Generated(repeated),
        }
    }

    pub(crate) fn new_empty(elem: RuntimeTypeBox) -> ReflectRepeatedRef<'static> {
        ReflectRepeatedRef {
            imp: ReflectRepeatedRefImpl::DynamicEmpty(DynamicRepeated::new(elem)),
        }
    }

    /// Number of elements in repeated field
    pub fn len(&self) -> usize {
        match &self.imp {
            ReflectRepeatedRefImpl::Generated(g) => g.len(),
            ReflectRepeatedRefImpl::DynamicEmpty(d) => d.len(),
        }
    }

    /// Repeated field is empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Get item by index
    // TODO: replace with index
    pub fn get(&self, index: usize) -> ReflectValueRef<'a> {
        match &self.imp {
            ReflectRepeatedRefImpl::Generated(r) => r.get(index),
            ReflectRepeatedRefImpl::DynamicEmpty(..) => panic!("empty"),
        }
    }

    /// Runtime type of element
    pub fn element_type(&self) -> RuntimeTypeBox {
        match &self.imp {
            ReflectRepeatedRefImpl::Generated(r) => r.element_type(),
            ReflectRepeatedRefImpl::DynamicEmpty(r) => r.element_type(),
        }
    }
}

impl<'a> ReflectEq for ReflectRepeatedRef<'a> {
    fn reflect_eq(&self, that: &Self, mode: &ReflectEqMode) -> bool {
        let len = self.len();

        if len != that.len() {
            return false;
        }

        for i in 0..len {
            let a = self.get(i);
            let b = that.get(i);
            if !a.reflect_eq(&b, mode) {
                return false;
            }
        }

        true
    }
}

impl<'a> PartialEq for ReflectRepeatedRef<'a> {
    fn eq(&self, other: &Self) -> bool {
        if self.len() != other.len() {
            return false;
        }

        for i in 0..self.len() {
            if self.get(i) != other.get(i) {
                return false;
            }
        }

        return true;
    }
}

impl<'a> PartialEq<[ReflectValueBox]> for ReflectRepeatedRef<'a> {
    fn eq(&self, other: &[ReflectValueBox]) -> bool {
        if self.len() != other.len() {
            return false;
        }

        for i in 0..self.len() {
            if self.get(i) != other[i] {
                return false;
            }
        }

        return true;
    }
}

impl<'a> PartialEq<ReflectRepeatedRef<'a>> for [ReflectValueBox] {
    fn eq(&self, other: &ReflectRepeatedRef) -> bool {
        other == self
    }
}

impl<'a> PartialEq<Vec<ReflectValueBox>> for ReflectRepeatedRef<'a> {
    fn eq(&self, other: &Vec<ReflectValueBox>) -> bool {
        self == other.as_slice()
    }
}

impl<'a> PartialEq<ReflectRepeatedRef<'a>> for Vec<ReflectValueBox> {
    fn eq(&self, other: &ReflectRepeatedRef) -> bool {
        self.as_slice() == other
    }
}

impl<'a> ReflectRepeatedMut<'a> {
    pub(crate) fn new(repeated: &'a mut dyn ReflectRepeated) -> ReflectRepeatedMut<'a> {
        ReflectRepeatedMut { repeated }
    }

    fn as_ref(&'a self) -> ReflectRepeatedRef<'a> {
        ReflectRepeatedRef::new(self.repeated)
    }

    /// Number of elements in repeated field
    pub fn len(&self) -> usize {
        self.repeated.len()
    }

    /// Self-explanatory
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Get an item by index
    ///
    /// Note: return immutable reference.
    pub fn get(&'a self, index: usize) -> ReflectValueRef<'a> {
        self.repeated.get(index)
    }

    /// Runtime type of element
    pub fn element_type(&self) -> RuntimeTypeBox {
        self.repeated.element_type()
    }

    /// Set a value at given index.
    ///
    /// # Panics
    ///
    /// If index if out of range or value type does not match container element type
    pub fn set(&mut self, index: usize, value: ReflectValueBox) {
        self.repeated.set(index, value);
    }

    /// Push an item to repeated field.
    ///
    /// # Panics
    ///
    /// If index if out of range or value type does not match container element type
    pub fn push(&mut self, value: ReflectValueBox) {
        self.repeated.push(value);
    }

    /// Self-explanatory
    pub fn clear(&mut self) {
        self.repeated.clear();
    }
}

/// Iterator over repeated field.
pub struct ReflectRepeatedRefIter<'a> {
    repeated: ReflectRepeatedRef<'a>,
    index: usize,
}

impl<'a> Iterator for ReflectRepeatedRefIter<'a> {
    type Item = ReflectValueRef<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        let index = self.index;
        if index != self.repeated.len() {
            let r = self.repeated.get(index);
            self.index += 1;
            Some(r)
        } else {
            None
        }
    }
}

impl<'a> IntoIterator for &'a ReflectRepeatedRef<'a> {
    type Item = ReflectValueRef<'a>;
    type IntoIter = ReflectRepeatedRefIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        ReflectRepeatedRefIter {
            repeated: self.clone(),
            index: 0,
        }
    }
}

impl<'a> IntoIterator for ReflectRepeatedRef<'a> {
    type Item = ReflectValueRef<'a>;
    type IntoIter = ReflectRepeatedRefIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        ReflectRepeatedRefIter {
            repeated: self,
            index: 0,
        }
    }
}

impl<'a> IntoIterator for &'a ReflectRepeatedMut<'a> {
    type Item = ReflectValueRef<'a>;
    type IntoIter = ReflectRepeatedRefIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.as_ref().into_iter()
    }
}

impl<'a> fmt::Debug for ReflectRepeatedRef<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.imp, f)
    }
}

impl<'a> fmt::Debug for ReflectRepeatedMut<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.repeated, f)
    }
}

impl<'a> PartialEq for ReflectRepeatedMut<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl<'a> PartialEq<ReflectRepeatedRef<'a>> for ReflectRepeatedMut<'a> {
    fn eq(&self, other: &ReflectRepeatedRef) -> bool {
        PartialEq::eq(&self.as_ref(), other)
    }
}

impl<'a> PartialEq<[ReflectValueBox]> for ReflectRepeatedMut<'a> {
    fn eq(&self, other: &[ReflectValueBox]) -> bool {
        PartialEq::eq(&self.as_ref(), other)
    }
}

impl<'a> PartialEq<ReflectRepeatedMut<'a>> for [ReflectValueBox] {
    fn eq(&self, other: &ReflectRepeatedMut) -> bool {
        PartialEq::eq(self, &other.as_ref())
    }
}

impl<'a> PartialEq<Vec<ReflectValueBox>> for ReflectRepeatedMut<'a> {
    fn eq(&self, other: &Vec<ReflectValueBox>) -> bool {
        self == other.as_slice()
    }
}

impl<'a> PartialEq<ReflectRepeatedMut<'a>> for Vec<ReflectValueBox> {
    fn eq(&self, other: &ReflectRepeatedMut) -> bool {
        self.as_slice() == other
    }
}
<commit_msg>Switch more API to ReflectValueRef<commit_after>use std::fmt;
use std::slice;

use crate::reflect::value::value_ref::ReflectValueRef;
use crate::reflect::value::ProtobufValue;

use crate::reflect::dynamic::repeated::DynamicRepeated;
use crate::reflect::reflect_eq::ReflectEq;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::ProtobufValueSized;
use crate::reflect::ReflectValueBox;
use crate::reflect::RuntimeTypeBox;

pub(crate) trait ReflectRepeated: Sync + 'static + fmt::Debug {
    fn reflect_iter(&self) -> ReflectRepeatedIter;
    fn len(&self) -> usize;
    fn get(&self, index: usize) -> ReflectValueRef;
    fn set(&mut self, index: usize, value: ReflectValueBox);
    fn push(&mut self, value: ReflectValueBox);
    fn clear(&mut self);
    fn element_type(&self) -> RuntimeTypeBox;
}

impl<V: ProtobufValueSized> ReflectRepeated for Vec<V> {
    fn reflect_iter<'a>(&'a self) -> ReflectRepeatedIter<'a> {
        ReflectRepeatedIter {
            imp: Box::new(ReflectRepeatedIterImplSlice::<'a, V> { iter: self.iter() }),
        }
    }

    fn len(&self) -> usize {
        Vec::len(self)
    }

    fn get(&self, index: usize) -> ReflectValueRef {
        V::as_ref(&self[index])
    }

    fn set(&mut self, index: usize, value: ReflectValueBox) {
        let value = value.downcast().expect("wrong type");
        self[index] = value;
    }

    fn push(&mut self, value: ReflectValueBox) {
        let value = value.downcast().expect("wrong type");
        self.push(value)
    }

    fn clear(&mut self) {
        self.clear()
    }

    fn element_type(&self) -> RuntimeTypeBox {
        V::runtime_type_box()
    }
}

// useless
impl<V: ProtobufValueSized> ReflectRepeated for [V] {
    fn reflect_iter<'a>(&'a self) -> ReflectRepeatedIter<'a> {
        ReflectRepeatedIter {
            imp: Box::new(ReflectRepeatedIterImplSlice::<'a, V> { iter: self.iter() }),
        }
    }

    fn len(&self) -> usize {
        <[_]>::len(self)
    }

    fn get(&self, index: usize) -> ReflectValueRef {
        V::as_ref(&self[index])
    }

    fn set(&mut self, index: usize, value: ReflectValueBox) {
        let value = value.downcast().expect("wrong type");
        self[index] = value;
    }

    fn push(&mut self, _value: ReflectValueBox) {
        panic!("push is not possible for [V]");
    }

    fn clear(&mut self) {
        panic!("clear is not possible for [V]");
    }

    fn element_type(&self) -> RuntimeTypeBox {
        V::runtime_type_box()
    }
}

trait ReflectRepeatedIterTrait<'a> {
    fn next(&mut self) -> Option<ReflectValueRef<'a>>;
}

struct ReflectRepeatedIterImplSlice<'a, V: ProtobufValue + 'static> {
    iter: slice::Iter<'a, V>,
}

impl<'a, V: ProtobufValueSized + 'static> ReflectRepeatedIterTrait<'a>
    for ReflectRepeatedIterImplSlice<'a, V>
{
    fn next(&mut self) -> Option<ReflectValueRef<'a>> {
        self.iter.next().map(ProtobufValueSized::as_ref)
    }
}

pub struct ReflectRepeatedIter<'a> {
    imp: Box<dyn ReflectRepeatedIterTrait<'a> + 'a>,
}

impl<'a> Iterator for ReflectRepeatedIter<'a> {
    type Item = ReflectValueRef<'a>;

    fn next(&mut self) -> Option<ReflectValueRef<'a>> {
        self.imp.next()
    }
}

impl<'a> IntoIterator for &'a dyn ReflectRepeated {
    type Item = ReflectValueRef<'a>;
    type IntoIter = ReflectRepeatedIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.reflect_iter()
    }
}

#[derive(Clone)]
enum ReflectRepeatedRefImpl<'a> {
    Generated(&'a dyn ReflectRepeated),
    DynamicEmpty(DynamicRepeated),
}

impl<'a> fmt::Debug for ReflectRepeatedRefImpl<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ReflectRepeatedRefImpl::Generated(r) => fmt::Debug::fmt(r, f),
            ReflectRepeatedRefImpl::DynamicEmpty(r) => fmt::Debug::fmt(r, f),
        }
    }
}

/// Dynamic reference to repeated field
#[derive(Clone)]
pub struct ReflectRepeatedRef<'a> {
    imp: ReflectRepeatedRefImpl<'a>,
}

/// Dynamic mutable reference to repeated field
pub struct ReflectRepeatedMut<'a> {
    repeated: &'a mut dyn ReflectRepeated,
}

impl<'a> ReflectRepeatedRef<'a> {
    pub(crate) fn new(repeated: &'a dyn ReflectRepeated) -> ReflectRepeatedRef<'a> {
        ReflectRepeatedRef {
            imp: ReflectRepeatedRefImpl::Generated(repeated),
        }
    }

    pub(crate) fn new_empty(elem: RuntimeTypeBox) -> ReflectRepeatedRef<'static> {
        ReflectRepeatedRef {
            imp: ReflectRepeatedRefImpl::DynamicEmpty(DynamicRepeated::new(elem)),
        }
    }

    /// Number of elements in repeated field
    pub fn len(&self) -> usize {
        match &self.imp {
            ReflectRepeatedRefImpl::Generated(g) => g.len(),
            ReflectRepeatedRefImpl::DynamicEmpty(d) => d.len(),
        }
    }

    /// Repeated field is empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Get item by index
    // TODO: replace with index
    pub fn get(&self, index: usize) -> ReflectValueRef<'a> {
        match &self.imp {
            ReflectRepeatedRefImpl::Generated(r) => r.get(index),
            ReflectRepeatedRefImpl::DynamicEmpty(..) => panic!("empty"),
        }
    }

    /// Runtime type of element
    pub fn element_type(&self) -> RuntimeTypeBox {
        match &self.imp {
            ReflectRepeatedRefImpl::Generated(r) => r.element_type(),
            ReflectRepeatedRefImpl::DynamicEmpty(r) => r.element_type(),
        }
    }
}

impl<'a> ReflectEq for ReflectRepeatedRef<'a> {
    fn reflect_eq(&self, that: &Self, mode: &ReflectEqMode) -> bool {
        let len = self.len();

        if len != that.len() {
            return false;
        }

        for i in 0..len {
            let a = self.get(i);
            let b = that.get(i);
            if !a.reflect_eq(&b, mode) {
                return false;
            }
        }

        true
    }
}

impl<'a> PartialEq for ReflectRepeatedRef<'a> {
    fn eq(&self, other: &Self) -> bool {
        if self.len() != other.len() {
            return false;
        }

        for i in 0..self.len() {
            if self.get(i) != other.get(i) {
                return false;
            }
        }

        return true;
    }
}

impl<'a> PartialEq<[ReflectValueBox]> for ReflectRepeatedRef<'a> {
    fn eq(&self, other: &[ReflectValueBox]) -> bool {
        if self.len() != other.len() {
            return false;
        }

        for i in 0..self.len() {
            if self.get(i) != other[i] {
                return false;
            }
        }

        return true;
    }
}

impl<'a> PartialEq<ReflectRepeatedRef<'a>> for [ReflectValueBox] {
    fn eq(&self, other: &ReflectRepeatedRef) -> bool {
        other == self
    }
}

impl<'a> PartialEq<Vec<ReflectValueBox>> for ReflectRepeatedRef<'a> {
    fn eq(&self, other: &Vec<ReflectValueBox>) -> bool {
        self == other.as_slice()
    }
}

impl<'a> PartialEq<ReflectRepeatedRef<'a>> for Vec<ReflectValueBox> {
    fn eq(&self, other: &ReflectRepeatedRef) -> bool {
        self.as_slice() == other
    }
}

impl<'a> ReflectRepeatedMut<'a> {
    pub(crate) fn new(repeated: &'a mut dyn ReflectRepeated) -> ReflectRepeatedMut<'a> {
        ReflectRepeatedMut { repeated }
    }

    fn as_ref(&'a self) -> ReflectRepeatedRef<'a> {
        ReflectRepeatedRef::new(self.repeated)
    }

    /// Number of elements in repeated field
    pub fn len(&self) -> usize {
        self.repeated.len()
    }

    /// Self-explanatory
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Get an item by index
    ///
    /// Note: return immutable reference.
    pub fn get(&'a self, index: usize) -> ReflectValueRef<'a> {
        self.repeated.get(index)
    }

    /// Runtime type of element
    pub fn element_type(&self) -> RuntimeTypeBox {
        self.repeated.element_type()
    }

    /// Set a value at given index.
    ///
    /// # Panics
    ///
    /// If index if out of range or value type does not match container element type
    pub fn set(&mut self, index: usize, value: ReflectValueBox) {
        self.repeated.set(index, value);
    }

    /// Push an item to repeated field.
    ///
    /// # Panics
    ///
    /// If index if out of range or value type does not match container element type
    pub fn push(&mut self, value: ReflectValueBox) {
        self.repeated.push(value);
    }

    /// Self-explanatory
    pub fn clear(&mut self) {
        self.repeated.clear();
    }
}

/// Iterator over repeated field.
pub struct ReflectRepeatedRefIter<'a> {
    repeated: ReflectRepeatedRef<'a>,
    index: usize,
}

impl<'a> Iterator for ReflectRepeatedRefIter<'a> {
    type Item = ReflectValueRef<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        let index = self.index;
        if index != self.repeated.len() {
            let r = self.repeated.get(index);
            self.index += 1;
            Some(r)
        } else {
            None
        }
    }
}

impl<'a> IntoIterator for &'a ReflectRepeatedRef<'a> {
    type Item = ReflectValueRef<'a>;
    type IntoIter = ReflectRepeatedRefIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        ReflectRepeatedRefIter {
            repeated: self.clone(),
            index: 0,
        }
    }
}

impl<'a> IntoIterator for ReflectRepeatedRef<'a> {
    type Item = ReflectValueRef<'a>;
    type IntoIter = ReflectRepeatedRefIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        ReflectRepeatedRefIter {
            repeated: self,
            index: 0,
        }
    }
}

impl<'a> IntoIterator for &'a ReflectRepeatedMut<'a> {
    type Item = ReflectValueRef<'a>;
    type IntoIter = ReflectRepeatedRefIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.as_ref().into_iter()
    }
}

impl<'a> fmt::Debug for ReflectRepeatedRef<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.imp, f)
    }
}

impl<'a> fmt::Debug for ReflectRepeatedMut<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.repeated, f)
    }
}

impl<'a> PartialEq for ReflectRepeatedMut<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl<'a> PartialEq<ReflectRepeatedRef<'a>> for ReflectRepeatedMut<'a> {
    fn eq(&self, other: &ReflectRepeatedRef) -> bool {
        PartialEq::eq(&self.as_ref(), other)
    }
}

impl<'a> PartialEq<[ReflectValueBox]> for ReflectRepeatedMut<'a> {
    fn eq(&self, other: &[ReflectValueBox]) -> bool {
        PartialEq::eq(&self.as_ref(), other)
    }
}

impl<'a> PartialEq<ReflectRepeatedMut<'a>> for [ReflectValueBox] {
    fn eq(&self, other: &ReflectRepeatedMut) -> bool {
        PartialEq::eq(self, &other.as_ref())
    }
}

impl<'a> PartialEq<Vec<ReflectValueBox>> for ReflectRepeatedMut<'a> {
    fn eq(&self, other: &Vec<ReflectValueBox>) -> bool {
        self == other.as_slice()
    }
}

impl<'a> PartialEq<ReflectRepeatedMut<'a>> for Vec<ReflectValueBox> {
    fn eq(&self, other: &ReflectRepeatedMut) -> bool {
        self.as_slice() == other
    }
}
<|endoftext|>


<commit_before>use std::string::ToString;
use std::collections::{HashMap, HashSet};

pub static EMPTY_MENU: [Link; 0] = [];

/// Stores information for a link.
///
/// [`NavigationItem`]: enum.NavigationItem.html
/// [`SidebarItem::Links`]: enum.SidebarItem.html#Links.v
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Link {
    text: String,
    url: String,
    #[serde(default)]
    attributes: HashMap<String, String>,
    #[serde(default)]
    classes: HashSet<String>,
}

impl Link {
    /// Creates a new `Link` with the given `text` and `url`.
    pub fn new<T: ToString, U: ToString>(text: T, url: U) -> Link {
        Link {
            text: text.to_string(),
            url: url.to_string(),
            attributes: HashMap::new(),
            classes: HashSet::new(),
        }
    }

    /// Adds a class to this link.
    /// Duplicate classes are ignored.
    pub fn add_class<T: ToString>(&mut self, class: T) {
        self.classes.insert(class.to_string());
    }

    /// Adds classes to this link.
    /// Duplicate classes are ignored.
    pub fn add_classes<I, T>(&mut self, classes: I)
    where I: IntoIterator<Item=T>, T: ToString {
        for class in classes.into_iter() {
            self.add_class(class);
        }
    }

    /// Returns a reference to the url.
    pub fn url(&self) -> &str {
        self.url.as_str()
    }

    pub fn extend_attributes(&mut self, new_attributes: HashMap<String, String>) {
        for (attr, val) in new_attributes {
            let current = self.attributes.entry(attr).or_insert("".to_string());
            if !current.is_empty() {
                current.push_str(" ");
            }
            current.push_str(val.as_str());
        }
    }
}

/// Builder for `Vec<Link>`.
/// [`Link`](struct.Link.html)
pub struct MenuBuilder {
    menu: Vec<Link>,
    active: Option<String>,
    attributes: HashMap<String, String>,
    classes: HashSet<String>,
}

impl MenuBuilder {
    pub fn new(menu: &[Link]) -> MenuBuilder {
        MenuBuilder {
            menu: menu.to_owned(),
            active: None,
            attributes: HashMap::new(),
            classes: HashSet::new(),
        }
    }

    /// Adds a class to all menu items.
    pub fn add_class<T: ToString>(&mut self, class: T) {
        self.classes.insert(class.to_string());
    }

    /// Sets the currently active url.
    pub fn set_active<T: ToString>(&mut self, url: T) {
        self.active = Some(url.to_string());
    }

    /// Finalizes the menu and returns a `Vec<Link>`.
    pub fn finalize(self) -> Vec<Link> {
        self.menu
            .iter()
            .map(|link| {
                let mut link = link.clone();
                link.extend_attributes(self.attributes.clone());
                link.add_classes(self.classes.clone());
                add_class_if_active(&mut link, &self.active);
                link
            })
            .collect()
    }
}

fn add_class_if_active(link: &mut Link, active: &Option<String>) {
    if let Some(ref active_url) = *active {
        if link.url() == active_url {
            link.add_class("active");
        }
    }
}

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

    fn link() -> Link {
        Link::new("Click here", "https://somewhere.net")
    }

    #[test]
    fn create_link() {
        let link = link();
        assert_eq!(
            link,
            Link {
                text: String::from("Click here"),
                url: String::from("https://somewhere.net"),
                attributes: HashMap::new(),
                classes: HashSet::new(),
            }
        );
    }

    #[test]
    fn extend_link_attributes() {
        let mut link = link();
        let mut attributes = HashMap::new();
        attributes.insert(String::from("class"), String::from("active"));
        attributes.insert(String::from("id"), String::from("some-id"));
        link.extend_attributes(attributes);

        assert_eq!(link.attributes, {
            let mut m = HashMap::new();
            m.insert(String::from("class"), String::from("active"));
            m.insert(String::from("id"), String::from("some-id"));
            m
        });
    }

    #[test]
    fn add_class_to_link() {
        let mut link = link();
        link.add_class("active");

        assert_eq!(link.attributes, {
            let mut m = HashMap::new();
            m.insert(String::from("class"), String::from("active"));
            m
        });
    }

    #[test]
    fn build_menu() {
        let links = vec![
            Link::new("Home", "/"),
            Link::new("About", "/about"),
            Link::new("Blog", "/blog"),
            Link::new("Somewhere else", "/se"),
        ];
        let mut builder = MenuBuilder::new(links.as_ref());
        builder.add_class("main-nav");
        builder.set_active("/blog");
        let menu = builder.finalize();

        assert_eq!(menu[0], {
            let mut attrs = HashMap::new();
            attrs.insert(String::from("class"), String::from("main-nav"));
            Link::with_attributes("Home", "/", attrs)
        });
        assert_eq!(menu[1], {
            let mut attrs = HashMap::new();
            attrs.insert(String::from("class"), String::from("main-nav"));
            Link::with_attributes("About", "/about", attrs)
        });
        assert_eq!(menu[2], {
            let mut attrs = HashMap::new();
            attrs.insert(String::from("class"), String::from("main-nav active"));
            Link::with_attributes("Blog", "/blog", attrs)
        });
        assert_eq!(menu[3], {
            let mut attrs = HashMap::new();
            attrs.insert(String::from("class"), String::from("main-nav"));
            Link::with_attributes("Somewhere else", "/se", attrs)
        });
    }
}
<commit_msg>Fixed tests for Link and MenuBuilder<commit_after>use std::string::ToString;
use std::collections::{HashMap, HashSet};

pub static EMPTY_MENU: [Link; 0] = [];

/// Stores information for a link.
///
/// [`NavigationItem`]: enum.NavigationItem.html
/// [`SidebarItem::Links`]: enum.SidebarItem.html#Links.v
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
pub struct Link {
    text: String,
    url: String,
    #[serde(default)]
    attributes: HashMap<String, String>,
    #[serde(default)]
    classes: HashSet<String>,
}

impl Link {
    /// Creates a new `Link` with the given `text` and `url`.
    pub fn new<T: ToString, U: ToString>(text: T, url: U) -> Link {
        Link {
            text: text.to_string(),
            url: url.to_string(),
            attributes: HashMap::new(),
            classes: HashSet::new(),
        }
    }

    /// Adds a class to this link.
    /// Duplicate classes are ignored.
    pub fn add_class<T: ToString>(&mut self, class: T) {
        self.classes.insert(class.to_string());
    }

    /// Adds classes to this link.
    /// Duplicate classes are ignored.
    pub fn add_classes<I, T>(&mut self, classes: I)
    where I: IntoIterator<Item=T>, T: ToString {
        for class in classes.into_iter() {
            self.add_class(class);
        }
    }

    /// Returns a reference to the url.
    pub fn url(&self) -> &str {
        self.url.as_str()
    }

    pub fn extend_attributes(&mut self, new_attributes: HashMap<String, String>) {
        for (attr, val) in new_attributes {
            let current = self.attributes.entry(attr).or_insert("".to_string());
            if !current.is_empty() {
                current.push_str(" ");
            }
            current.push_str(val.as_str());
        }
    }
}

/// Builder for `Vec<Link>`.
/// [`Link`](struct.Link.html)
pub struct MenuBuilder {
    menu: Vec<Link>,
    active: Option<String>,
    attributes: HashMap<String, String>,
    classes: HashSet<String>,
}

impl MenuBuilder {
    pub fn new(menu: &[Link]) -> MenuBuilder {
        MenuBuilder {
            menu: menu.to_owned(),
            active: None,
            attributes: HashMap::new(),
            classes: HashSet::new(),
        }
    }

    /// Adds a class to all menu items.
    pub fn add_class<T: ToString>(&mut self, class: T) {
        self.classes.insert(class.to_string());
    }

    /// Sets the currently active url.
    pub fn set_active<T: ToString>(&mut self, url: T) {
        self.active = Some(url.to_string());
    }

    /// Finalizes the menu and returns a `Vec<Link>`.
    pub fn finalize(self) -> Vec<Link> {
        self.menu
            .iter()
            .map(|link| {
                let mut link = link.clone();
                link.extend_attributes(self.attributes.clone());
                link.add_classes(self.classes.clone());
                add_class_if_active(&mut link, &self.active);
                link
            })
            .collect()
    }
}

fn add_class_if_active(link: &mut Link, active: &Option<String>) {
    if let Some(ref active_url) = *active {
        if link.url() == active_url {
            link.add_class("active");
        }
    }
}

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

    fn link() -> Link {
        Link::new("Click here", "https://somewhere.net")
    }

    #[test]
    fn create_link() {
        let link = link();
        assert_eq!(
            link,
            Link {
                text: String::from("Click here"),
                url: String::from("https://somewhere.net"),
                attributes: HashMap::new(),
                classes: HashSet::new(),
            }
        );
    }

    #[test]
    fn extend_link_attributes() {
        let mut link = link();
        let mut attributes = HashMap::new();
        attributes.insert(String::from("class"), String::from("active"));
        attributes.insert(String::from("id"), String::from("some-id"));
        link.extend_attributes(attributes);

        assert_eq!(link.attributes, {
            let mut m = HashMap::new();
            m.insert(String::from("class"), String::from("active"));
            m.insert(String::from("id"), String::from("some-id"));
            m
        });
    }

    #[test]
    fn add_class_to_link() {
        let mut link = link();
        link.add_class("active");

        assert_eq!(link.classes, {
            let mut s = HashSet::new();
            s.insert(String::from("active"));
            s
        });
    }

    #[test]
    fn build_menu() {
        let links = vec![
            Link::new("Home", "/"),
            Link::new("About", "/about"),
            Link::new("Blog", "/blog"),
            Link::new("Somewhere else", "/se"),
        ];
        let mut builder = MenuBuilder::new(links.as_ref());
        builder.add_class("main-nav");
        builder.set_active("/blog");
        let menu = builder.finalize();

        assert_eq!(menu[0], {
            Link {
                text: "Home".to_string(),
                url: "/".to_string(),
                attributes: HashMap::new(),
                classes: {
                    let mut s = HashSet::new();
                    s.insert("main-nav".to_string());
                    s
                },
            }
        });
        assert_eq!(menu[1], {
            Link {
                text: "About".to_string(),
                url: "/about".to_string(),
                attributes: HashMap::new(),
                classes: {
                    let mut s = HashSet::new();
                    s.insert("main-nav".to_string());
                    s
                },
            }
        });
        assert_eq!(menu[2], {
            Link {
                text: "Blog".to_string(),
                url: "/blog".to_string(),
                attributes: HashMap::new(),
                classes: {
                    let mut s = HashSet::new();
                    s.insert("main-nav".to_string());
                    s.insert("active".to_string());
                    s
                },
            }
        });
        assert_eq!(menu[3], {
            Link {
                text: "Somewhere else".to_string(),
                url: "/se".to_string(),
                attributes: HashMap::new(),
                classes: {
                    let mut s = HashSet::new();
                    s.insert("main-nav".to_string());
                    s
                },
            }
        });
    }
}
<|endoftext|>


<commit_before>//! This crate helps to create a Fractalide component
//!
//! It provides the macro `component` which takes the high level view of the component, and creates the code for the scheduler.
//!
//! It also declare the Trait Agent and the shared methods needed by every component and the scheduler.

extern crate capnp;

// TODO : Add method to remove components
use ports::{IPSender, IPReceiver};
use scheduler::Signal;
use result::Result;

/// Provide the generic functions of agents
///
/// These three functions are used by the scheduler
pub trait Agent {
    /// Return true if there is at least one input port
    fn is_input_ports(&self) -> bool;
    /// Connect output port
    fn connect(&mut self, port: &str, sender: IPSender) -> Result<()>;
    /// Connect array output port
    fn connect_array(&mut self, port: &str, element: String, sender: IPSender) -> Result<()>;
    /// Add input element
    fn add_inarr_element(&mut self, port: &str, element: String, recv: IPReceiver) -> Result<()>;
    /// Run the method of the component, his personal logic
    fn run(&mut self) -> Result<Signal>;
}

/// The agent macro.
///
/// It helps to define a agent, by defining the input and output ports, if there is an option or an acc port, ...
///
/// Example :
///
/// ```rust,ignore
/// agent! {
///    inputs(input: any),
///    outputs(output: any),
///    option(generic_text),
///    fn run(&mut self) -> Result<Signal> {
///        // Receive an IP
///        let ip = try!(self.input.input.recv());
///
///        // Received an IP from the option port (a generic_text)
///        let opt = self.recv_opt();
///
///        // Get the capn'p reader
///        let reader: generic_text::Reader = try!(opt.read_schema());
///        // Print the option
///        println!("{}", try!(reader.get_text()));
///
///        // Send the received IP outside, but don't care about the success (drop on fail)
///        let _ = self.output.output.send(ip);
///
///        Ok(End)
///    }
/// }
/// ```
#[macro_export]
macro_rules! agent {
    (
        $( input($( $input_name:ident: $input_contract:ident ),*), )*
        $( inarr($( $input_a_name:ident: $input_a_contract:ident ),*), )*
        $( output($( $output_name:ident: $output_contract:ident ),*), )*
        $( outarr($( $output_a_name:ident: $output_a_contract:ident ),*), )*
        $( portal( $portal_type:ty => $portal_value:expr ), )*
        $( option($option:ident), )*
        $( accumulator($acc:ident ), )*
        fn run(&mut $arg:ident) -> Result<Signal> $fun:block
    )
        =>
    {
        use rustfbp::agent::Agent;

        use rustfbp::result;
        use rustfbp::result::Result;
        use rustfbp::scheduler::{CompMsg, Signal};
        use std::error::Error;

        use std::sync::mpsc::{Sender};
        use std::sync::mpsc::channel;

        use rustfbp::ports::{IP, IPSender, IPReceiver, OutputSend};

        #[allow(unused_imports)]
        use std::collections::HashMap;

        use capnp::serialize;
        use capnp::message;

        use std::io::{Read, Write};

        use rustfbp::scheduler::Signal::*;

        mod edge_capnp {
                include!("edge_capnp.rs");
        }

        use edge_capnp::*;

        impl $name {
            pub fn recv_option(&mut self) -> IP {
                self.try_recv_option();
                if self.option_ip.is_none() {
                    self.option_ip = self.ports.recv("option").ok();
                }
                match self.option_ip {
                    Some(ref ip) => ip.clone(),
                    None => unreachable!(),
                }
            }

            pub fn try_recv_option(&mut self) -> Option<IP> {
                loop {
                    match self.ports.try_recv("option") {
                        Err(_) => { break; },
                        Ok(ip) => { self.option_ip = Some(ip); }
                    };
                }
                self.option_ip.as_ref().map(|ip|{ ip.clone() })
            }
        }

        // simple and array
        impl Agent for $name {

            fn get_ports(&mut self) -> &mut Ports {
                &mut self.ports
            }

            fn is_input_ports(&self) -> bool {
                $(
                    if true || stringify!($input_field_name) == "" { return true; }
                )*
                $(
                    if true || stringify!($input_array_name) == "" { return true; }
                )*
                false
            }

            fn run(&mut $arg) -> Result<()> $fun

        }

        /* Global agent */

        #[allow(dead_code)]
        #[allow(non_camel_case_types)]
        pub struct $name {
            name: String,
            pub ports: Ports,
            pub option_ip: Option<IP>,
            $(
            pub portal: $portal_type ,
            )*
        }

        #[allow(dead_code)]
        pub fn new(name: String, sched: Sender<CompMsg>) -> Result<(Box<Agent + Send>, HashMap<String, IPSender>)> {
            let (ports, senders) = try!(Ports::new(name.clone(), sched,
                                   vec!["option".into(), "acc".into(), $( stringify!($input_field_name).to_string() ),*],
                                   vec![$( stringify!($input_array_name).to_string() ),*],
                                   vec!["acc".into(), $( stringify!($output_field_name).to_string() ),*],
                                   vec![$( stringify!($output_array_name).to_string() ),*],));

            // Put it together
            let comp = $name{
                name: name,
                ports: ports,
                option_ip: None,
                $(
                    portal: $portal_value,
                )*
            };
            Ok((Box::new(comp) as Box<Agent + Send>, senders))
        }

        #[no_mangle]
        pub extern fn create_agent(name: String, sched: Sender<CompMsg>) -> Result<(Box<Agent + Send>, HashMap<String, IPSender>)> {
            new(name, sched)
        }

        #[no_mangle]
        pub extern fn get_schema_input(port: &str) -> Result<String> {
            match port {
                $(
                    stringify!($input_field_name)=> Ok(stringify!($input_edge_name).into()),
                )*
                _ => { Err(result::Error::PortNotFound("unknown".into(), port.into())) }
            }
        }

        #[no_mangle]
        pub extern fn get_schema_input_array(port: &str) -> Result<String> {
            match port {
                $(
                    stringify!($input_array_name) => Ok(stringify!($input_edge_array).into()),
                )*
                _ => { Err(result::Error::PortNotFound("unknown".into(), port.into())) }
            }
        }

        #[no_mangle]
        pub extern fn get_schema_output(port: &str) -> Result<String> {
            match port {
                $(
                    stringify!($output_field_name)=> Ok(stringify!($output_edge_name).into()),
                )*
                _ => { Err(result::Error::PortNotFound("unknown".into(), port.into())) }
            }
        }

        #[no_mangle]
        pub extern fn get_schema_output_array(port: &str) -> Result<String> {
            match port {
                $(
                    stringify!($output_array_name) => Ok(stringify!($output_edge_array).into()),
                )*
                _ => { Err(result::Error::PortNotFound("unknown".into(), port.into())) }
            }
        }
    }
}
<commit_msg>Agent: ThisAgent<commit_after>//! This crate helps to create a Fractalide component
//!
//! It provides the macro `component` which takes the high level view of the component, and creates the code for the scheduler.
//!
//! It also declare the Trait Agent and the shared methods needed by every component and the scheduler.

extern crate capnp;

// TODO : Add method to remove components
use ports::{IPSender, IPReceiver};
use scheduler::Signal;
use result::Result;

/// Provide the generic functions of agents
///
/// These three functions are used by the scheduler
pub trait Agent {
    /// Return true if there is at least one input port
    fn is_input_ports(&self) -> bool;
    /// Connect output port
    fn connect(&mut self, port: &str, sender: IPSender) -> Result<()>;
    /// Connect array output port
    fn connect_array(&mut self, port: &str, element: String, sender: IPSender) -> Result<()>;
    /// Add input element
    fn add_inarr_element(&mut self, port: &str, element: String, recv: IPReceiver) -> Result<()>;
    /// Run the method of the component, his personal logic
    fn run(&mut self) -> Result<Signal>;
}

/// The agent macro.
///
/// It helps to define a agent, by defining the input and output ports, if there is an option or an acc port, ...
///
/// Example :
///
/// ```rust,ignore
/// agent! {
///    inputs(input: any),
///    outputs(output: any),
///    option(generic_text),
///    fn run(&mut self) -> Result<Signal> {
///        // Receive an IP
///        let ip = try!(self.input.input.recv());
///
///        // Received an IP from the option port (a generic_text)
///        let opt = self.recv_opt();
///
///        // Get the capn'p reader
///        let reader: generic_text::Reader = try!(opt.read_schema());
///        // Print the option
///        println!("{}", try!(reader.get_text()));
///
///        // Send the received IP outside, but don't care about the success (drop on fail)
///        let _ = self.output.output.send(ip);
///
///        Ok(End)
///    }
/// }
/// ```
#[macro_export]
macro_rules! agent {
    (
        $( input($( $input_name:ident: $input_contract:ident ),*), )*
        $( inarr($( $input_a_name:ident: $input_a_contract:ident ),*), )*
        $( output($( $output_name:ident: $output_contract:ident ),*), )*
        $( outarr($( $output_a_name:ident: $output_a_contract:ident ),*), )*
        $( portal( $portal_type:ty => $portal_value:expr ), )*
        $( option($option:ident), )*
        $( accumulator($acc:ident ), )*
        fn run(&mut $arg:ident) -> Result<Signal> $fun:block
    )
        =>
    {
        use rustfbp::agent::Agent;

        use rustfbp::result;
        use rustfbp::result::Result;
        use rustfbp::scheduler::{CompMsg, Signal};
        use std::error::Error;

        use std::sync::mpsc::{Sender};
        use std::sync::mpsc::channel;

        use rustfbp::ports::{IP, IPSender, IPReceiver, OutputSend};

        #[allow(unused_imports)]
        use std::collections::HashMap;

        use capnp::serialize;
        use capnp::message;

        use std::io::{Read, Write};

        use rustfbp::scheduler::Signal::*;

        mod edge_capnp {
                include!("edge_capnp.rs");
        }

        use edge_capnp::*;

        impl ThisAgent {
            pub fn recv_option(&mut self) -> IP {
                self.try_recv_option();
                if self.option_ip.is_none() {
                    self.option_ip = self.ports.recv("option").ok();
                }
                match self.option_ip {
                    Some(ref ip) => ip.clone(),
                    None => unreachable!(),
                }
            }

            pub fn try_recv_option(&mut self) -> Option<IP> {
                loop {
                    match self.ports.try_recv("option") {
                        Err(_) => { break; },
                        Ok(ip) => { self.option_ip = Some(ip); }
                    };
                }
                self.option_ip.as_ref().map(|ip|{ ip.clone() })
            }
        }

        // simple and array

            fn get_ports(&mut self) -> &mut Ports {
                &mut self.ports
            }
        impl Agent for ThisAgent {

            fn is_input_ports(&self) -> bool {
                $(
                    if true || stringify!($input_field_name) == "" { return true; }
                )*
                $(
                    if true || stringify!($input_array_name) == "" { return true; }
                )*
                false
            }

            fn run(&mut $arg) -> Result<()> $fun

        }

        /* Global agent */

        #[allow(dead_code)]
        #[allow(non_camel_case_types)]
        pub struct ThisAgent {
            name: String,
            pub ports: Ports,
            pub option_ip: Option<IP>,
            $(
            pub portal: $portal_type ,
            )*
        }

        #[allow(dead_code)]
        pub fn new(name: String, sched: Sender<CompMsg>) -> Result<(Box<Agent + Send>, HashMap<String, IPSender>)> {
            let (ports, senders) = try!(Ports::new(name.clone(), sched,
                                   vec!["option".into(), "acc".into(), $( stringify!($input_field_name).to_string() ),*],
                                   vec![$( stringify!($input_array_name).to_string() ),*],
                                   vec!["acc".into(), $( stringify!($output_field_name).to_string() ),*],
                                   vec![$( stringify!($output_array_name).to_string() ),*],));

            // Put it together
            let comp = $name{
                name: name,
                ports: ports,
                option_ip: None,
                $(
                    portal: $portal_value,
                )*
            };
            Ok((Box::new(comp) as Box<Agent + Send>, senders))
        }

        #[no_mangle]
        pub extern fn create_agent(name: String, sched: Sender<CompMsg>) -> Result<(Box<Agent + Send>, HashMap<String, IPSender>)> {
            new(name, sched)
        }

        #[no_mangle]
        pub extern fn get_schema_input(port: &str) -> Result<String> {
            match port {
                $(
                    stringify!($input_field_name)=> Ok(stringify!($input_edge_name).into()),
                )*
                _ => { Err(result::Error::PortNotFound("unknown".into(), port.into())) }
            }
        }

        #[no_mangle]
        pub extern fn get_schema_input_array(port: &str) -> Result<String> {
            match port {
                $(
                    stringify!($input_array_name) => Ok(stringify!($input_edge_array).into()),
                )*
                _ => { Err(result::Error::PortNotFound("unknown".into(), port.into())) }
            }
        }

        #[no_mangle]
        pub extern fn get_schema_output(port: &str) -> Result<String> {
            match port {
                $(
                    stringify!($output_field_name)=> Ok(stringify!($output_edge_name).into()),
                )*
                _ => { Err(result::Error::PortNotFound("unknown".into(), port.into())) }
            }
        }

        #[no_mangle]
        pub extern fn get_schema_output_array(port: &str) -> Result<String> {
            match port {
                $(
                    stringify!($output_array_name) => Ok(stringify!($output_edge_array).into()),
                )*
                _ => { Err(result::Error::PortNotFound("unknown".into(), port.into())) }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! SHA-1 (Secure Hash Algorithm)
//!
//! # WARNING!!!
//!
//! This hash function has been severely compromised. **Do not use!**
//!
//! Instead you should use SHA-2 or SHA-3 family.
//!
//! # General info
//!
//! | Name  | Digest size | Block size | Rounds | Structure            | Reference               |
//! | ----- | ----------: | ---------: | -----: | -------------------- | ----------------------- |
//! | SHA-1 |    160 bits |   512 bits |     80 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
//!
//! [fips180-4]: http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf "FIPS 180-4 Secure Hash Standard (SHS)"
//! [md]: https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction

use byteorder::{ByteOrder, BigEndian};
use typenum::consts::{U20, U64, U160};
use static_buffer::{FixedBuf, FixedBuffer64, StandardPadding};

use Digest;

#[derive(Copy, Clone, Debug)]
struct State {
    a: u32,
    b: u32,
    c: u32,
    d: u32,
    e: u32,
}

macro_rules! schedule {
    ($schedule:ident[$i:expr] = $data:ident) => {
        unsafe {
            *$schedule.get_unchecked_mut($i) =
                  (*$data.get_unchecked($i * 4 + 0) as u32) << 24
                | (*$data.get_unchecked($i * 4 + 1) as u32) << 16
                | (*$data.get_unchecked($i * 4 + 2) as u32) << 8
                | (*$data.get_unchecked($i * 4 + 3) as u32);
        }
    };

    ($schedule:ident[$i:expr]) => {
        unsafe {
            *$schedule.get_unchecked_mut($i & 0xf) = {
                  *$schedule.get_unchecked(($i - 3) & 0xf)
                ^ *$schedule.get_unchecked(($i - 8) & 0xf)
                ^ *$schedule.get_unchecked(($i - 14) & 0xf)
                ^ *$schedule.get_unchecked(($i - 16) & 0xf)
            }.rotate_left(1);
        }
    }
}

macro_rules! process {
    () => ();
    (proc $state:ident, $f:block, $c:expr, $schedule:ident, $i:expr) => {{
        let tmp = $state.a
                      .rotate_left(5)
                      .wrapping_add($f)
                      .wrapping_add($state.e)
                      .wrapping_add($c)
                      .wrapping_add(unsafe { *$schedule.get_unchecked($i & 0xf) });

        $state.e = $state.d;
        $state.d = $state.c;
        $state.c = $state.b.rotate_left(30);
        $state.b = $state.a;
        $state.a = tmp;
    }};

    (ff($state:ident, $schedule:ident[$i:expr] , $data:ident); $($rest:tt)*) => {
        schedule!($schedule[$i] = $data);
        process!(proc $state, {
            $state.d ^ ($state.b & ($state.c ^ $state.d))
        }, 0x5a827999, $schedule, $i);
        process!($($rest)*);
    };
    (ff($state:ident, $schedule:ident[$i:expr]); $($rest:tt)*) => {
        schedule!($schedule[$i]);
        process!(proc $state, {
            $state.d ^ ($state.b & ($state.c ^ $state.d))
        }, 0x5a827999, $schedule, $i);
        process!($($rest)*);
    };
    (gg($state:ident, $schedule:ident[$i:expr]); $($rest:tt)*) => {
        schedule!($schedule[$i]);
        process!(proc $state, {
            $state.b ^ $state.c ^ $state.d
        }, 0x6ed9eba1, $schedule, $i);
        process!($($rest)*);
    };
    (hh($state:ident, $schedule:ident[$i:expr]); $($rest:tt)*) => {
        schedule!($schedule[$i]);
        process!(proc $state, {
            ($state.b & $state.c) | ($state.d & ($state.b | $state.c))
        }, 0x8f1bbcdc, $schedule, $i);
        process!($($rest)*);
    };
    (ii($state:ident, $schedule:ident[$i:expr]); $($rest:tt)*) => {
        schedule!($schedule[$i]);
        process!(proc $state, {
            $state.b ^ $state.c ^ $state.d
        }, 0xca62c1d6, $schedule, $i);
        process!($($rest)*);
    };
}

impl State {
    fn new() -> Self {
        State {
            a: 0x67452301,
            b: 0xefcdab89,
            c: 0x98badcfe,
            d: 0x10325476,
            e: 0xc3d2e1f0,
        }
    }

    fn process_block(&mut self, data: &[u8]) {
        debug_assert!(data.len() == 64);

        let mut words = [0u32; 16];
        let mut state = self.clone();

        process! {
            ff(state, words[0],  data);
            ff(state, words[1],  data);
            ff(state, words[2],  data);
            ff(state, words[3],  data);
            ff(state, words[4],  data);
            ff(state, words[5],  data);
            ff(state, words[6],  data);
            ff(state, words[7],  data);
            ff(state, words[8],  data);
            ff(state, words[9],  data);
            ff(state, words[10], data);
            ff(state, words[11], data);
            ff(state, words[12], data);
            ff(state, words[13], data);
            ff(state, words[14], data);
            ff(state, words[15], data);
            ff(state, words[16]);
            ff(state, words[17]);
            ff(state, words[18]);
            ff(state, words[19]);
        }
        process! {
            gg(state, words[20]);
            gg(state, words[21]);
            gg(state, words[22]);
            gg(state, words[23]);
            gg(state, words[24]);
            gg(state, words[25]);
            gg(state, words[26]);
            gg(state, words[27]);
            gg(state, words[28]);
            gg(state, words[29]);
            gg(state, words[30]);
            gg(state, words[31]);
            gg(state, words[32]);
            gg(state, words[33]);
            gg(state, words[34]);
            gg(state, words[35]);
            gg(state, words[36]);
            gg(state, words[37]);
            gg(state, words[38]);
            gg(state, words[39]);
        }
        process! {
            hh(state, words[40]);
            hh(state, words[41]);
            hh(state, words[42]);
            hh(state, words[43]);
            hh(state, words[44]);
            hh(state, words[45]);
            hh(state, words[46]);
            hh(state, words[47]);
            hh(state, words[48]);
            hh(state, words[49]);
            hh(state, words[50]);
            hh(state, words[51]);
            hh(state, words[52]);
            hh(state, words[53]);
            hh(state, words[54]);
            hh(state, words[55]);
            hh(state, words[56]);
            hh(state, words[57]);
            hh(state, words[58]);
            hh(state, words[59]);
        }
        process! {
            ii(state, words[60]);
            ii(state, words[61]);
            ii(state, words[62]);
            ii(state, words[63]);
            ii(state, words[64]);
            ii(state, words[65]);
            ii(state, words[66]);
            ii(state, words[67]);
            ii(state, words[68]);
            ii(state, words[69]);
            ii(state, words[70]);
            ii(state, words[71]);
            ii(state, words[72]);
            ii(state, words[73]);
            ii(state, words[74]);
            ii(state, words[75]);
            ii(state, words[76]);
            ii(state, words[77]);
            ii(state, words[78]);
            ii(state, words[79]);
        }

        self.a = self.a.wrapping_add(state.a);
        self.b = self.b.wrapping_add(state.b);
        self.c = self.c.wrapping_add(state.c);
        self.d = self.d.wrapping_add(state.d);
        self.e = self.e.wrapping_add(state.e);
    }
}

/// SHA-1 implementation
///
/// For more details check [module docs](index.html)
#[derive(Clone)]
pub struct Sha1 {
    state: State,
    buffer: FixedBuffer64,
    length: u64,
}

impl Default for Sha1 {
    fn default() -> Self {
        Sha1 {
            state: State::new(),
            buffer: FixedBuffer64::new(),
            length: 0,
        }
    }
}

impl Digest for Sha1 {
    type OutputBits = U160;
    type OutputBytes = U20;

    type BlockSize = U64;

    fn update<T: AsRef<[u8]>>(&mut self, data: T) {
        let data = data.as_ref();
        self.length += data.len() as u64;

        let state = &mut self.state;
        self.buffer.input(data, |d| state.process_block(d));
    }

    fn result<T: AsMut<[u8]>>(mut self, mut out: T) {
        let state = &mut self.state;

        self.buffer.standard_padding(8, |d| state.process_block(d));
        BigEndian::write_u64(self.buffer.next(8), self.length * 8);
        state.process_block(self.buffer.full_buffer());

        let mut out = out.as_mut();
        assert!(out.len() >= Self::output_bytes());
        BigEndian::write_u32(&mut out[0..4], state.a);
        BigEndian::write_u32(&mut out[4..8], state.b);
        BigEndian::write_u32(&mut out[8..12], state.c);
        BigEndian::write_u32(&mut out[12..16], state.d);
        BigEndian::write_u32(&mut out[16..20], state.e);
    }
}
<commit_msg>perf(digest::sha1): do not rotate state variables<commit_after>//! SHA-1 (Secure Hash Algorithm)
//!
//! # WARNING!!!
//!
//! This hash function has been severely compromised. **Do not use!**
//!
//! Instead you should use SHA-2 or SHA-3 family.
//!
//! # General info
//!
//! | Name  | Digest size | Block size | Rounds | Structure            | Reference               |
//! | ----- | ----------: | ---------: | -----: | -------------------- | ----------------------- |
//! | SHA-1 |    160 bits |   512 bits |     80 | [Merkle–Damgård][md] | [FIPS 180-4][fips180-4] |
//!
//! [fips180-4]: http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf "FIPS 180-4 Secure Hash Standard (SHS)"
//! [md]: https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction

use byteorder::{ByteOrder, BigEndian};
use typenum::consts::{U20, U64, U160};
use static_buffer::{FixedBuf, FixedBuffer64, StandardPadding};

use Digest;

#[derive(Copy, Clone, Debug)]
struct State {
    a: u32,
    b: u32,
    c: u32,
    d: u32,
    e: u32,
}

macro_rules! schedule {
    ($schedule:ident[$i:expr] = $data:ident) => {
        unsafe {
            *$schedule.get_unchecked_mut($i) =
                  (*$data.get_unchecked($i * 4 + 0) as u32) << 24
                | (*$data.get_unchecked($i * 4 + 1) as u32) << 16
                | (*$data.get_unchecked($i * 4 + 2) as u32) << 8
                | (*$data.get_unchecked($i * 4 + 3) as u32);
        }
    };

    ($schedule:ident[$i:expr]) => {
        unsafe {
            *$schedule.get_unchecked_mut($i & 0xf) = {
                  *$schedule.get_unchecked(($i -  3) & 0xf)
                ^ *$schedule.get_unchecked(($i -  8) & 0xf)
                ^ *$schedule.get_unchecked(($i - 14) & 0xf)
                ^ *$schedule.get_unchecked(($i - 16) & 0xf)
            }.rotate_left(1);
        }
    }
}

macro_rules! process {
    () => ();
    (($a:expr, $b:expr, $c:expr, $d:expr, $e:expr), $f:block, $constant:expr, $schedule:ident, $i:expr) => {{
        $e = $a
             .rotate_left(5)
             .wrapping_add($f)
             .wrapping_add($e)
             .wrapping_add($constant)
             .wrapping_add(unsafe { *$schedule.get_unchecked($i & 0xf) });
        $b = $b.rotate_left(30);
    }};

    (ff(($a:expr, $b:expr, $c:expr, $d:expr, $e:expr), $schedule:ident[$i:expr] , $data:ident); $($rest:tt)*) => {
        schedule!($schedule[$i] = $data);
        process!(($a, $b, $c, $d, $e), {
            ($b & $c) | (!$b & $d)
        }, 0x5a827999, $schedule, $i);
        process!($($rest)*);
    };
    (ff(($a:expr, $b:expr, $c:expr, $d:expr, $e:expr), $schedule:ident[$i:expr]); $($rest:tt)*) => {
        schedule!($schedule[$i]);
        process!(($a, $b, $c, $d, $e), {
            ($b & $c) | (!$b & $d)
        }, 0x5a827999, $schedule, $i);
        process!($($rest)*);
    };
    (gg(($a:expr, $b:expr, $c:expr, $d:expr, $e:expr), $schedule:ident[$i:expr]); $($rest:tt)*) => {
        schedule!($schedule[$i]);
        process!(($a, $b, $c, $d, $e), {
            $b ^ $c ^ $d
        }, 0x6ed9eba1, $schedule, $i);
        process!($($rest)*);
    };
    (hh(($a:expr, $b:expr, $c:expr, $d:expr, $e:expr), $schedule:ident[$i:expr]); $($rest:tt)*) => {
        schedule!($schedule[$i]);
        process!(($a, $b, $c, $d, $e), {
            ($b & $c) ^ ($b & $d) ^ ($c & $d)
        }, 0x8f1bbcdc, $schedule, $i);
        process!($($rest)*);
    };
    (ii(($a:expr, $b:expr, $c:expr, $d:expr, $e:expr), $schedule:ident[$i:expr]); $($rest:tt)*) => {
        schedule!($schedule[$i]);
        process!(($a, $b, $c, $d, $e), {
            $b ^ $c ^ $d
        }, 0xca62c1d6, $schedule, $i);
        process!($($rest)*);
    };
}

impl State {
    fn new() -> Self {
        State {
            a: 0x67452301,
            b: 0xefcdab89,
            c: 0x98badcfe,
            d: 0x10325476,
            e: 0xc3d2e1f0,
        }
    }

    fn process_block(&mut self, data: &[u8]) {
        debug_assert!(data.len() == 64);

        let mut words = [0u32; 16];
        let mut state = self.clone();

        process! {
            ff((state.a, state.b, state.c, state.d, state.e), words[0],  data);
            ff((state.e, state.a, state.b, state.c, state.d), words[1],  data);
            ff((state.d, state.e, state.a, state.b, state.c), words[2],  data);
            ff((state.c, state.d, state.e, state.a, state.b), words[3],  data);
            ff((state.b, state.c, state.d, state.e, state.a), words[4],  data);
            ff((state.a, state.b, state.c, state.d, state.e), words[5],  data);
            ff((state.e, state.a, state.b, state.c, state.d), words[6],  data);
            ff((state.d, state.e, state.a, state.b, state.c), words[7],  data);
            ff((state.c, state.d, state.e, state.a, state.b), words[8],  data);
            ff((state.b, state.c, state.d, state.e, state.a), words[9],  data);
            ff((state.a, state.b, state.c, state.d, state.e), words[10], data);
            ff((state.e, state.a, state.b, state.c, state.d), words[11], data);
            ff((state.d, state.e, state.a, state.b, state.c), words[12], data);
            ff((state.c, state.d, state.e, state.a, state.b), words[13], data);
            ff((state.b, state.c, state.d, state.e, state.a), words[14], data);
            ff((state.a, state.b, state.c, state.d, state.e), words[15], data);
            ff((state.e, state.a, state.b, state.c, state.d), words[16]);
            ff((state.d, state.e, state.a, state.b, state.c), words[17]);
            ff((state.c, state.d, state.e, state.a, state.b), words[18]);
            ff((state.b, state.c, state.d, state.e, state.a), words[19]);
        }
        process! {
            gg((state.a, state.b, state.c, state.d, state.e), words[20]);
            gg((state.e, state.a, state.b, state.c, state.d), words[21]);
            gg((state.d, state.e, state.a, state.b, state.c), words[22]);
            gg((state.c, state.d, state.e, state.a, state.b), words[23]);
            gg((state.b, state.c, state.d, state.e, state.a), words[24]);
            gg((state.a, state.b, state.c, state.d, state.e), words[25]);
            gg((state.e, state.a, state.b, state.c, state.d), words[26]);
            gg((state.d, state.e, state.a, state.b, state.c), words[27]);
            gg((state.c, state.d, state.e, state.a, state.b), words[28]);
            gg((state.b, state.c, state.d, state.e, state.a), words[29]);
            gg((state.a, state.b, state.c, state.d, state.e), words[30]);
            gg((state.e, state.a, state.b, state.c, state.d), words[31]);
            gg((state.d, state.e, state.a, state.b, state.c), words[32]);
            gg((state.c, state.d, state.e, state.a, state.b), words[33]);
            gg((state.b, state.c, state.d, state.e, state.a), words[34]);
            gg((state.a, state.b, state.c, state.d, state.e), words[35]);
            gg((state.e, state.a, state.b, state.c, state.d), words[36]);
            gg((state.d, state.e, state.a, state.b, state.c), words[37]);
            gg((state.c, state.d, state.e, state.a, state.b), words[38]);
            gg((state.b, state.c, state.d, state.e, state.a), words[39]);
        }
        process! {
            hh((state.a, state.b, state.c, state.d, state.e), words[40]);
            hh((state.e, state.a, state.b, state.c, state.d), words[41]);
            hh((state.d, state.e, state.a, state.b, state.c), words[42]);
            hh((state.c, state.d, state.e, state.a, state.b), words[43]);
            hh((state.b, state.c, state.d, state.e, state.a), words[44]);
            hh((state.a, state.b, state.c, state.d, state.e), words[45]);
            hh((state.e, state.a, state.b, state.c, state.d), words[46]);
            hh((state.d, state.e, state.a, state.b, state.c), words[47]);
            hh((state.c, state.d, state.e, state.a, state.b), words[48]);
            hh((state.b, state.c, state.d, state.e, state.a), words[49]);
            hh((state.a, state.b, state.c, state.d, state.e), words[50]);
            hh((state.e, state.a, state.b, state.c, state.d), words[51]);
            hh((state.d, state.e, state.a, state.b, state.c), words[52]);
            hh((state.c, state.d, state.e, state.a, state.b), words[53]);
            hh((state.b, state.c, state.d, state.e, state.a), words[54]);
            hh((state.a, state.b, state.c, state.d, state.e), words[55]);
            hh((state.e, state.a, state.b, state.c, state.d), words[56]);
            hh((state.d, state.e, state.a, state.b, state.c), words[57]);
            hh((state.c, state.d, state.e, state.a, state.b), words[58]);
            hh((state.b, state.c, state.d, state.e, state.a), words[59]);
        }
        process! {
            ii((state.a, state.b, state.c, state.d, state.e), words[60]);
            ii((state.e, state.a, state.b, state.c, state.d), words[61]);
            ii((state.d, state.e, state.a, state.b, state.c), words[62]);
            ii((state.c, state.d, state.e, state.a, state.b), words[63]);
            ii((state.b, state.c, state.d, state.e, state.a), words[64]);
            ii((state.a, state.b, state.c, state.d, state.e), words[65]);
            ii((state.e, state.a, state.b, state.c, state.d), words[66]);
            ii((state.d, state.e, state.a, state.b, state.c), words[67]);
            ii((state.c, state.d, state.e, state.a, state.b), words[68]);
            ii((state.b, state.c, state.d, state.e, state.a), words[69]);
            ii((state.a, state.b, state.c, state.d, state.e), words[70]);
            ii((state.e, state.a, state.b, state.c, state.d), words[71]);
            ii((state.d, state.e, state.a, state.b, state.c), words[72]);
            ii((state.c, state.d, state.e, state.a, state.b), words[73]);
            ii((state.b, state.c, state.d, state.e, state.a), words[74]);
            ii((state.a, state.b, state.c, state.d, state.e), words[75]);
            ii((state.e, state.a, state.b, state.c, state.d), words[76]);
            ii((state.d, state.e, state.a, state.b, state.c), words[77]);
            ii((state.c, state.d, state.e, state.a, state.b), words[78]);
            ii((state.b, state.c, state.d, state.e, state.a), words[79]);
        }

        self.a = self.a.wrapping_add(state.a);
        self.b = self.b.wrapping_add(state.b);
        self.c = self.c.wrapping_add(state.c);
        self.d = self.d.wrapping_add(state.d);
        self.e = self.e.wrapping_add(state.e);
    }
}

/// SHA-1 implementation
///
/// For more details check [module docs](index.html)
#[derive(Clone)]
pub struct Sha1 {
    state: State,
    buffer: FixedBuffer64,
    length: u64,
}

impl Default for Sha1 {
    fn default() -> Self {
        Sha1 {
            state: State::new(),
            buffer: FixedBuffer64::new(),
            length: 0,
        }
    }
}

impl Digest for Sha1 {
    type OutputBits = U160;
    type OutputBytes = U20;

    type BlockSize = U64;

    fn update<T: AsRef<[u8]>>(&mut self, data: T) {
        let data = data.as_ref();
        self.length += data.len() as u64;

        let state = &mut self.state;
        self.buffer.input(data, |d| state.process_block(d));
    }

    fn result<T: AsMut<[u8]>>(mut self, mut out: T) {
        let state = &mut self.state;

        self.buffer.standard_padding(8, |d| state.process_block(d));
        BigEndian::write_u64(self.buffer.next(8), self.length * 8);
        state.process_block(self.buffer.full_buffer());

        let mut out = out.as_mut();
        assert!(out.len() >= Self::output_bytes());
        BigEndian::write_u32(&mut out[0..4], state.a);
        BigEndian::write_u32(&mut out[4..8], state.b);
        BigEndian::write_u32(&mut out[8..12], state.c);
        BigEndian::write_u32(&mut out[12..16], state.d);
        BigEndian::write_u32(&mut out[16..20], state.e);
    }
}
<|endoftext|>


<commit_before>use std::io::Read;

use common::Solution;
use common::read_single_input;

fn skill_after(n: usize) -> u64 {
    let mut state = vec![3u8, 7];
    let mut elves = [0, 1];

    while state.len() < n + 10 {
        let result = state[elves[0]] + state[elves[1]];
        if result >= 10 {
            state.push(result / 10);
        }
        state.push(result % 10);

        elves[0] = (elves[0] + state[elves[0]] as usize + 1) % state.len();
        elves[1] = (elves[1] + state[elves[1]] as usize + 1) % state.len();
    }

    let mut skill = 0;
    for d in state.into_iter().skip(n).take(10) {
        skill *= 10;
        skill += d as u64;
    }

    skill
}

fn update_current(mut current: usize, by: usize, base: usize) -> usize {
    current *= 10;
    current %= base;
    current += by;
    current
}

fn find_first(n: usize, len: usize) -> usize {
    let mut state = vec![3u8, 7];
    let mut elves = [0, 1];
    let mut current = 37;
    let mod_base = 10usize.pow(len as u32);

    loop {
        let result = state[elves[0]] + state[elves[1]];
        if result >= 10 {
            current = update_current(current, result as usize / 10, mod_base);
            if current == n {
                return state.len() - len + 1;
            }
            state.push(result / 10);
        }
        current = update_current(current, result as usize % 10, mod_base);
        if current == n {
            return state.len() - len + 1;
        }
        state.push(result % 10);

        elves[0] = (elves[0] + state[elves[0]] as usize + 1) % state.len();
        elves[1] = (elves[1] + state[elves[1]] as usize + 1) % state.len();
    }
}

#[derive(Default)]
pub struct Day14 {}

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

impl Solution for Day14 {
    fn part1(&mut self, input: &mut Read) -> String {
        let input = read_single_input(input);
        format!("{:010}", skill_after(input))
    }

    fn part2(&mut self, input: &mut Read) -> String {
        let mut buf = String::new();
        input.read_to_string(&mut buf).unwrap();

        let input = buf.trim().parse().unwrap();
        format!("{}", find_first(input, buf.trim().len()))
    }
}

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

    #[test]
    fn test_skill_after() {
        assert_eq!(5158916779, skill_after(9));
        assert_eq!(124515891, skill_after(5));
        assert_eq!(9251071085, skill_after(18));
        assert_eq!(5941429882, skill_after(2018));
    }

    #[test]
    fn test_find_first() {
        assert_eq!(9, find_first(51589, 5));
        assert_eq!(5, find_first(1245, 5));
        assert_eq!(18, find_first(92510, 5));
        assert_eq!(2018, find_first(59414, 5));
    }
}
<commit_msg>Reimplement day 14 with infinite streams.<commit_after>use std::io::Read;

use common::read_single_input;
use common::Solution;

struct ResultStream {
    elves: [usize; 2],
    state: Vec<u8>,
    next: usize,
}

impl ResultStream {
    pub fn new() -> Self {
        ResultStream {
            elves: [0, 1],
            state: vec![3, 7],
            next: 0,
        }
    }
}

impl Iterator for ResultStream {
    type Item = u8;

    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
        let state = &mut self.state;
        if self.next == state.len() {
            let elves = &mut self.elves;
            let n = state[elves[0]] + state[elves[1]];
            if n >= 10 {
                state.push(1);
            }
            state.push(n % 10);

            elves[0] = (elves[0] + 1 + state[elves[0]] as usize) % state.len();
            elves[1] = (elves[1] + 1 + state[elves[1]] as usize) % state.len();
        };
        let n = Some(state[self.next]);
        self.next += 1;
        n
    }
}

fn skill_after(n: usize) -> u64 {
    let state = ResultStream::new();
    let mut skill = 0;
    for d in state.skip(n).take(10) {
        skill *= 10;
        skill += d as u64;
    }

    skill
}

fn find_first(n: usize, len: usize) -> usize {
    let mod_base = 10usize.pow(len as u32);
    let mut current = 0;

    for (i, b) in ResultStream::new().enumerate() {
        current = (current * 10) % mod_base;
        current += b as usize;
        if current == n {
            return i - len + 1;
        }
    }
    unreachable!();
}

#[derive(Default)]
pub struct Day14 {}

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

impl Solution for Day14 {
    fn part1(&mut self, input: &mut Read) -> String {
        let input = read_single_input(input);
        format!("{:010}", skill_after(input))
    }

    fn part2(&mut self, input: &mut Read) -> String {
        let mut buf = String::new();
        input.read_to_string(&mut buf).unwrap();

        let input = buf.trim().parse().unwrap();
        format!("{}", find_first(input, buf.trim().len()))
    }
}

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

    #[test]
    fn test_skill_after() {
        assert_eq!(5158916779, skill_after(9));
        assert_eq!(124515891, skill_after(5));
        assert_eq!(9251071085, skill_after(18));
        assert_eq!(5941429882, skill_after(2018));
    }

    #[test]
    fn test_find_first() {
        assert_eq!(9, find_first(51589, 5));
        assert_eq!(5, find_first(1245, 5));
        assert_eq!(18, find_first(92510, 5));
        assert_eq!(2018, find_first(59414, 5));
    }
}
<|endoftext|>


<commit_before>use quote::Tokens;
use syn;

pub fn ber_choice_serialize(ast: &syn::MacroInput) -> Tokens {
  let name = &ast.ident;
  let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

  let fields = if let syn::Body::Enum(ref fields) = ast.body {
    fields
  } else {
    panic!("Expected an enum, but type {} was not an enum", name);
  };

  let match_pattern: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    quote!(#name::#ident(ref item))
  }).collect();
  let match_action: Vec<_> = fields.iter().map(|_v| {
    // TODO: Handle asn1 attributes
    quote! {
      if false {
        // let mut bytes = Vec::new();
        // try!(item.serialize_enc(e, &mut bytes));
        // try!(tag.write_tag(writer));
        // let len: ::asn1_cereal::tag::Len = Some(bytes.len() as ::asn1_cereal::tag::LenNum).into();
        // try!(writer.write_all(&mut bytes));
      } else {
        // FIXME: Does implicit tagging + CHOICE mean always explicit tag?
        // Maybe not with context-specific tags?
        // FIXME: We should be conditionally setting the constructed flag.
        // if E::tag_rules() == ::asn1_cereal::ber::enc::TagEnc::Implicit {
        //   try!(item.serialize_value(e, writer));
        // } else {
          try!(item.serialize_enc(e, writer));
        // }
      }
    }
  }).collect();

  quote! {
    impl #impl_generics ::asn1_cereal::BerSerialize for #name #ty_generics #where_clause {
      fn serialize_value<E: ::asn1_cereal::BerEncRules, W: ::std::io::Write>
          (&self, e: E, writer: &mut W) -> Result<(), ::asn1_cereal::err::EncodeError> {
        match *self {
          #(#match_pattern => #match_action),*
        }
        Ok(())
      }
    }
  }
}

pub fn ber_choice_deserialize(ast: &syn::MacroInput) -> Tokens {
  let name = &ast.ident;
  let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

  let fields = if let syn::Body::Enum(ref fields) = ast.body {
    fields
  } else {
    panic!("Expected an enum, but type {} was not an enum", name);
  };

  let match_pattern: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    let inner = if let syn::VariantData::Tuple(ref fields) = v.data {
      fields[0].clone()
    } else {
      panic!("Expected a tuple, but type {} variant {} was not a tuple", name, ident);
    };
    // TODO: Handle asn1 attributes
    quote! {
      tag @ ::asn1_cereal::tag::Tag { .. }
        if tag == <#inner as ::asn1_cereal::Asn1Info>::asn1_tag().unwrap()
    }
  }).collect();

  let match_action: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    // TODO: Handle asn1 attributes
    quote! {
      Ok(#name::#ident(
        // FIXME: Does implicit tagging + CHOICE mean always explicit tag?
        // Maybe not with context-specific tags?
        // FIXME: We should be conditionally setting the constructed flag.
        // if E::tag_rules() == ::asn1_cereal::ber::enc::TagEnc::Implicit {
        //   try!(::asn1_cereal::BerDeserialize::deserialize_value(e, reader, len))
        // } else {
          try!(::asn1_cereal::BerDeserialize::deserialize_with_tag(e, reader, tag, len))
        // }
      ))
    }
  }).collect();

  quote! {
    impl #impl_generics ::asn1_cereal::BerDeserialize for #name #ty_generics #where_clause {
      fn deserialize_value<E: ::asn1_cereal::BerEncRules, I: Iterator<Item=::std::io::Result<u8>>>
          (e: E, reader: &mut I, len: ::asn1_cereal::tag::Len) ->
          Result<Self, ::asn1_cereal::err::DecodeError> {
        let (tag, len) = ::asn1_cereal::tag::read_taglen(reader)?;
        match tag {
          #(#match_pattern => #match_action),*,
          _ => unimplemented!(),
        }
      }
    }
  }
}
<commit_msg>Remove blank space<commit_after>use quote::Tokens;
use syn;

pub fn ber_choice_serialize(ast: &syn::MacroInput) -> Tokens {
  let name = &ast.ident;
  let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

  let fields = if let syn::Body::Enum(ref fields) = ast.body {
    fields
  } else {
    panic!("Expected an enum, but type {} was not an enum", name);
  };

  let match_pattern: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    quote!(#name::#ident(ref item))
  }).collect();
  let match_action: Vec<_> = fields.iter().map(|_v| {
    // TODO: Handle asn1 attributes
    quote! {
      if false {
        // let mut bytes = Vec::new();
        // try!(item.serialize_enc(e, &mut bytes));
        // try!(tag.write_tag(writer));
        // let len: ::asn1_cereal::tag::Len = Some(bytes.len() as ::asn1_cereal::tag::LenNum).into();
        // try!(writer.write_all(&mut bytes));
      } else {
        // FIXME: Does implicit tagging + CHOICE mean always explicit tag?
        // Maybe not with context-specific tags?
        // FIXME: We should be conditionally setting the constructed flag.
        // if E::tag_rules() == ::asn1_cereal::ber::enc::TagEnc::Implicit {
        //   try!(item.serialize_value(e, writer));
        // } else {
          try!(item.serialize_enc(e, writer));
        // }
      }
    }
  }).collect();

  quote! {
    impl #impl_generics ::asn1_cereal::BerSerialize for #name #ty_generics #where_clause {
      fn serialize_value<E: ::asn1_cereal::BerEncRules, W: ::std::io::Write>
          (&self, e: E, writer: &mut W) -> Result<(), ::asn1_cereal::err::EncodeError> {
        match *self {
          #(#match_pattern => #match_action),*
        }
        Ok(())
      }
    }
  }
}

pub fn ber_choice_deserialize(ast: &syn::MacroInput) -> Tokens {
  let name = &ast.ident;
  let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();

  let fields = if let syn::Body::Enum(ref fields) = ast.body {
    fields
  } else {
    panic!("Expected an enum, but type {} was not an enum", name);
  };

  let match_pattern: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    let inner = if let syn::VariantData::Tuple(ref fields) = v.data {
      fields[0].clone()
    } else {
      panic!("Expected a tuple, but type {} variant {} was not a tuple", name, ident);
    };
    // TODO: Handle asn1 attributes
    quote! {
      tag @ ::asn1_cereal::tag::Tag { .. }
        if tag == <#inner as ::asn1_cereal::Asn1Info>::asn1_tag().unwrap()
    }
  }).collect();

  let match_action: Vec<_> = fields.iter().map(|v| {
    let ident = &v.ident;
    // TODO: Handle asn1 attributes
    quote! {
      Ok(#name::#ident(
        // FIXME: Does implicit tagging + CHOICE mean always explicit tag?
        // Maybe not with context-specific tags?
        // FIXME: We should be conditionally setting the constructed flag.
        // if E::tag_rules() == ::asn1_cereal::ber::enc::TagEnc::Implicit {
        //   try!(::asn1_cereal::BerDeserialize::deserialize_value(e, reader, len))
        // } else {
          try!(::asn1_cereal::BerDeserialize::deserialize_with_tag(e, reader, tag, len))
        // }
      ))
    }
  }).collect();

  quote! {
    impl #impl_generics ::asn1_cereal::BerDeserialize for #name #ty_generics #where_clause {
      fn deserialize_value<E: ::asn1_cereal::BerEncRules, I: Iterator<Item=::std::io::Result<u8>>>
          (e: E, reader: &mut I, len: ::asn1_cereal::tag::Len) ->
          Result<Self, ::asn1_cereal::err::DecodeError> {
        let (tag, len) = ::asn1_cereal::tag::read_taglen(reader)?;
        match tag {
          #(#match_pattern => #match_action),*,
          _ => unimplemented!(),
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>extern crate rand;
use ::rand::Rng;

fn one_in(n: u32) -> bool {
    rand::thread_rng().gen_weighted_bool(n)
}

#[derive(Debug)]
struct File {
    name: String,
    data: Vec<u8>,
}

impl File {
    fn new(name: &str) -> File {
        File { name: String::from(name), data: Vec::new() }
    }

    fn new_with_data(name: &str, data: &Vec<u8>) -> File {
        let mut f = File::new(name);
        f.data = data.clone();
        f
    }

    fn read(self: &File, save_to: &mut Vec<u8>) -> Result<usize, String> {
        let mut tmp = self.data.clone();
        let read_length = tmp.len();
        save_to.reserve(read_length);
        save_to.append(&mut tmp);
        Ok(read_length)
    }
}

fn  open(f: File) -> Result<File, String> {
    if one_in(10_000) {
        let err_msg = String::from("Permission denied");
        return Err(err_msg);
    }
    Ok(f)
}

fn close(f: File) -> Result<File, String> {
    if one_in(100_000) {
        let err_msg = String::from("Interrupted by signal!");
        return Err(err_msg);
    }
    Ok(f)
}

fn main() {
    let f4_data: Vec<u8> = vec![114, 117, 115, 116, 33];
    let mut f4 = File::new_with_data("4.txt", &f4_data);

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

    f4 = open(f4).unwrap();
    let f4_length = f4.read(&mut buffer).unwrap();
    f4 = close(f4).unwrap();

    let text = String::from_utf8_lossy(&buffer);

    println!("{:?}", f4);
    println!("{} is {} bytes long", &f4.name, f4_length);
    println!("{}", text);
}
<commit_msg>use enums to track the open/closed state of file<commit_after>extern crate rand;
use ::rand::Rng;

#[derive(Debug, PartialEq)]
enum FileState {
    Open,
    Closed,
}

fn one_in(n: u32) -> bool {
    rand::thread_rng().gen_weighted_bool(n)
}

#[derive(Debug)]
struct File {
    name: String,
    data: Vec<u8>,
    state: FileState,
}

impl File {
    fn new(name: &str) -> File {
        File { name: String::from(name), data: Vec::new(), state: FileState::Closed }
    }

    fn new_with_data(name: &str, data: &Vec<u8>) -> File {
        let mut f = File::new(name);
        f.data = data.clone();
        f
    }

    fn read(self: &File, save_to: &mut Vec<u8>) -> Result<usize, String> {
        if self.state != FileState::Open {
            return Err(String::from("File must be open for reading"));
        }
        let mut tmp = self.data.clone();
        let read_length = tmp.len();
        save_to.reserve(read_length);
        save_to.append(&mut tmp);
        Ok(read_length)
    }
}

fn  open(mut f: File) -> Result<File, String> {
    f.state = FileState::Open;
    if one_in(10_000) {
        let err_msg = String::from("Permission denied");
        return Err(err_msg);
    }
    Ok(f)
}

fn close(mut f: File) -> Result<File, String> {
    f.state = FileState::Closed;
    if one_in(100_000) {
        let err_msg = String::from("Interrupted by signal!");
        return Err(err_msg);
    }
    Ok(f)
}

fn main() {
    let f5_data: Vec<u8> = vec![114, 117, 115, 116, 33];
    let mut f5 = File::new_with_data("4.txt", &f5_data);

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

    if f5.read(&mut buffer).is_err() {
        println!("Error checking is working");
    }

    f5 = open(f5).unwrap();
    let f5_length = f5.read(&mut buffer).unwrap();
    f5 = close(f5).unwrap();

    let text = String::from_utf8_lossy(&buffer);

    println!("{:?}", f5);
    println!("{} is {} bytes long", &f5.name, f5_length);
    println!("{}", text);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate collect_mac;
extern crate env_logger;
#[macro_use]
extern crate quick_error;

extern crate gluon_base as base;
extern crate gluon_check as check;
extern crate gluon_parser as parser;

#[macro_use]
mod support;

use crate::check::typecheck::TypeError;

test_check! {
    basic1,
    r#"
    type Test a =
        | Int : Int -> Test Int

    Int 1
    "#,
    "test.Test Int"
}

test_check_err! {
    basic_error,
    r#"
    type Test a =
        | Int : Int -> Test Int

    Int ""
    "#,
    TypeError::Unification(..)
}

test_check! {
    basic2,
    r#"
    type Test a =
        | Int : Int -> Test Int

    let f x : Test a -> Int =
        match x with
        | Int x -> x

    ()
    "#,
    "()"
}
<commit_msg>test: Add another gadt test<commit_after>#[macro_use]
extern crate collect_mac;
extern crate env_logger;
#[macro_use]
extern crate quick_error;

extern crate gluon_base as base;
extern crate gluon_check as check;
extern crate gluon_parser as parser;

#[macro_use]
mod support;

use crate::check::typecheck::TypeError;

test_check! {
    basic1,
    r#"
    type Test a =
        | Int : Int -> Test Int

    Int 1
    "#,
    "test.Test Int"
}

test_check_err! {
    basic_error,
    r#"
    type Test a =
        | Int : Int -> Test Int

    Int ""
    "#,
    TypeError::Unification(..)
}

test_check! {
    basic2,
    r#"
    type Test a =
        | Int : Int -> Test Int

    let f x : Test a -> Int =
        match x with
        | Int x -> x

    ()
    "#,
    "()"
}

test_check! {
    basic3,
    r#"
    type Test a =
        | Int : Int -> Test Int

    let f x : Test a -> a =
        match x with
        | Int x -> x

    ()
    "#,
    "()"
}
<|endoftext|>


<commit_before>extern crate v8;

#[test]
fn up_and_down() {
    with_isolate_and_context(|_, _| {});
    with_isolate_and_context(|_, _| {});
}

#[test]
fn lock_and_unlock() {
    with_isolate_and_context(|isolate, _| {
        assert!(v8::Locker::IsActive());
        assert!(v8::Locker::IsLocked(isolate));
        v8::with_unlocker(isolate, || {
            assert!(!v8::Locker::IsLocked(isolate));
            v8::with_locker(isolate, || {
                assert!(v8::Locker::IsLocked(isolate));
            });
            assert!(!v8::Locker::IsLocked(isolate));
        });
        assert!(v8::Locker::IsLocked(isolate));
    });
}

#[test]
fn fortytwo() {
    with_isolate_and_context(|isolate, _| {
        let source = v8::String::NewFromUtf8(isolate, "42",
                                             v8::kNormalString).unwrap();
        assert!(source.IsString());
        assert!(!source.IsStringObject());
        let script = v8::Script::Compile(source, None).unwrap();
        let result = script.Run().unwrap();
        assert!(!result.IsNull());
        assert!(result.IsNumber());
        assert!(!result.IsUndefined());
    });
}

#[test]
fn basic_number() {
    with_isolate_and_context(|isolate, _| {
        let val = 13.37;
        let num = v8::Number::New(isolate, val).unwrap();
        assert_eq!(val, num.NumberValue());
    });
}

#[test]
fn basic_object() {
    with_isolate_and_context(|isolate, _| {
        let object = v8::Object::New(isolate).unwrap();
        assert!(object.IsObject());
        let key = v8::String::NewFromUtf8(isolate, "the_key",
                                          v8::kNormalString).unwrap();
        let value = v8::String::NewFromUtf8(isolate, "the_value",
                                            v8::kNormalString).unwrap();
        assert!(object.Set(key, value));
        assert!(object.Get(key).unwrap().IsString());
    });
}

#[test]
fn global_object() {
    with_isolate_and_context(|isolate, context| {
        let key = v8::String::NewFromUtf8(isolate, "Object",
                                          v8::kNormalString).unwrap();
        assert!(context.Global().unwrap().Get(key).unwrap().IsObject());
    });
}

#[test]
fn native_api_call() {
    with_isolate_and_context(|isolate, context| {
        extern fn f(info: v8::FunctionCallbackInfo) {
            let isolate = info.GetIsolate();
            assert!(info.At(0).IsNumber());
            assert!(info.At(1).IsNumber());
            let a = info.At(0).NumberValue();
            let b = info.At(1).NumberValue();
            let x = v8::Number::New(isolate, a * b).unwrap();
            info.GetReturnValue().Set(x);
        }
        let t = v8::FunctionTemplate::New(isolate, Some(f),
                                          None, None, 0).unwrap();
        let key = v8::String::NewFromUtf8(isolate, "f",
                                          v8::kNormalString).unwrap();
        let global = context.Global().unwrap();
        global.Set(key, t.GetFunction().unwrap());
        assert!(global.Get(key).unwrap().IsFunction());
        let source = v8::String::NewFromUtf8(isolate, "f(1337, 42)",
                                             v8::kNormalString).unwrap();
        let script = v8::Script::Compile(source, None).unwrap();
        let result = script.Run().unwrap();
        assert!(result.IsNumber());
        assert_eq!(result.NumberValue(), 1337. * 42.);
    });
}

fn with_isolate_and_context(closure: |v8::Isolate, v8::Context|) {
    assert!(v8::V8::Initialize());
    {
        let mut isolate = v8::Isolate::New(None).unwrap();
        v8::with_locker(isolate, || {
            v8::with_handle_scope(isolate, || {
                v8::with_isolate_scope(isolate, || {
                    let context = v8::Context::New(isolate).unwrap();
                    v8::with_context_scope(context, || {
                        closure(isolate, context)
                    });
                });
            });
        });
        isolate.Dispose();
    }
    // Don't call v8::V8::Dispose(), it permanently tears down V8.
}
<commit_msg>Temporarily disable native_api_call test.<commit_after>extern crate v8;

#[test]
fn up_and_down() {
    with_isolate_and_context(|_, _| {});
    with_isolate_and_context(|_, _| {});
}

#[test]
fn lock_and_unlock() {
    with_isolate_and_context(|isolate, _| {
        assert!(v8::Locker::IsActive());
        assert!(v8::Locker::IsLocked(isolate));
        v8::with_unlocker(isolate, || {
            assert!(!v8::Locker::IsLocked(isolate));
            v8::with_locker(isolate, || {
                assert!(v8::Locker::IsLocked(isolate));
            });
            assert!(!v8::Locker::IsLocked(isolate));
        });
        assert!(v8::Locker::IsLocked(isolate));
    });
}

#[test]
fn fortytwo() {
    with_isolate_and_context(|isolate, _| {
        let source = v8::String::NewFromUtf8(isolate, "42",
                                             v8::kNormalString).unwrap();
        assert!(source.IsString());
        assert!(!source.IsStringObject());
        let script = v8::Script::Compile(source, None).unwrap();
        let result = script.Run().unwrap();
        assert!(!result.IsNull());
        assert!(result.IsNumber());
        assert!(!result.IsUndefined());
    });
}

#[test]
fn basic_number() {
    with_isolate_and_context(|isolate, _| {
        let val = 13.37;
        let num = v8::Number::New(isolate, val).unwrap();
        assert_eq!(val, num.NumberValue());
    });
}

#[test]
fn basic_object() {
    with_isolate_and_context(|isolate, _| {
        let object = v8::Object::New(isolate).unwrap();
        assert!(object.IsObject());
        let key = v8::String::NewFromUtf8(isolate, "the_key",
                                          v8::kNormalString).unwrap();
        let value = v8::String::NewFromUtf8(isolate, "the_value",
                                            v8::kNormalString).unwrap();
        assert!(object.Set(key, value));
        assert!(object.Get(key).unwrap().IsString());
    });
}

#[test]
fn global_object() {
    with_isolate_and_context(|isolate, context| {
        let key = v8::String::NewFromUtf8(isolate, "Object",
                                          v8::kNormalString).unwrap();
        assert!(context.Global().unwrap().Get(key).unwrap().IsObject());
    });
}

#[ignore]
#[test]
fn native_api_call() {
    with_isolate_and_context(|isolate, context| {
        extern fn f(info: v8::FunctionCallbackInfo) {
            let isolate = info.GetIsolate();
            assert!(info.At(0).IsNumber());
            assert!(info.At(1).IsNumber());
            let a = info.At(0).NumberValue();
            let b = info.At(1).NumberValue();
            let x = v8::Number::New(isolate, a * b).unwrap();
            info.GetReturnValue().Set(x);
        }
        let t = v8::FunctionTemplate::New(isolate, Some(f),
                                          None, None, 0).unwrap();
        let key = v8::String::NewFromUtf8(isolate, "f",
                                          v8::kNormalString).unwrap();
        let global = context.Global().unwrap();
        global.Set(key, t.GetFunction().unwrap());
        assert!(global.Get(key).unwrap().IsFunction());
        let source = v8::String::NewFromUtf8(isolate, "f(1337, 42)",
                                             v8::kNormalString).unwrap();
        let script = v8::Script::Compile(source, None).unwrap();
        let result = script.Run().unwrap();
        assert!(result.IsNumber());
        assert_eq!(result.NumberValue(), 1337. * 42.);
    });
}

fn with_isolate_and_context(closure: |v8::Isolate, v8::Context|) {
    assert!(v8::V8::Initialize());
    {
        let mut isolate = v8::Isolate::New(None).unwrap();
        v8::with_locker(isolate, || {
            v8::with_handle_scope(isolate, || {
                v8::with_isolate_scope(isolate, || {
                    let context = v8::Context::New(isolate).unwrap();
                    v8::with_context_scope(context, || {
                        closure(isolate, context)
                    });
                });
            });
        });
        isolate.Dispose();
    }
    // Don't call v8::V8::Dispose(), it permanently tears down V8.
}
<|endoftext|>