<commit_before>use std::default::Default;
use std::str;

use nom::IResult;
use nom::{be_u8, digit, is_alphabetic, is_alphanumeric};

use asnom::common::TagClass;
use asnom::structures::{Boolean, ExplicitTag, OctetString, Sequence, Tag};

pub fn parse(input: &str) -> Result<Tag, ()> {
    match filtexpr(input.as_bytes()) {
        IResult::Done(r, t) => {
            if r.is_empty() {
                Ok(t)
            } else {
                Err(())
            }
        },
        IResult::Error(_) | IResult::Incomplete(_) => Err(()),
    }
}

named!(filtexpr<Tag>, alt!(filter | item));

named!(filter<Tag>, delimited!(char!('('), filtercomp, char!(')')));
named!(filtercomp<Tag>, alt!(and | or | not | item));
named!(filterlist<Vec<Tag>>, many1!(filter));

named!(and<Tag>, map!(preceded!(char!('&'), filterlist),
    |tagv: Vec<Tag>| -> Tag {
        Tag::Sequence(Sequence {
            class: TagClass::Context,
            id: 0,
            inner: tagv,
        })
    }
));

named!(or<Tag>, map!(preceded!(char!('|'), filterlist),
    |tagv: Vec<Tag>| -> Tag {
        Tag::Sequence(Sequence {
            class: TagClass::Context,
            id: 1,
            inner: tagv,
        })
    }
));

named!(not<Tag>, map!(preceded!(char!('!'), filter),
    |tag: Tag| -> Tag {
        Tag::ExplicitTag(ExplicitTag {
            class: TagClass::Context,
            id: 2,
            inner: Box::new(tag),
        })
    }
));

named!(item<Tag>, alt!(non_extensible | extensible));

const EQ_MATCH: u64 = 3;

named!(non_extensible<Tag>, do_parse!(
    attr: attributedescription >>
    filtertype: filtertype >>
    value: verify!(take_while!(is_value_char), |v: &[u8]| !str::from_utf8(v).expect("assertion value").contains("**")) >> ({
        if filtertype != EQ_MATCH || !value.contains(&b'*') {
            simple_tag(attr, filtertype, value)
        } else {
            if value.len() == 1 && value[0] == b'*' {
                present_tag(attr)
            } else {
                substr_tag(attr, value)
            }
        }
    })
));

fn is_value_char(c: u8) -> bool {
    c != 0 && c != b'(' && c != b')' && c != b'\\'
}

named!(filtertype<u64>, alt!(
    char!('=') => { |_| 3 } |
    tag!(">=") => { |_| 5 } |
    tag!("<=") => { |_| 6 } |
    tag!("~=") => { |_| 8 }
));

fn simple_tag(attr: &[u8], filtertype: u64, value: &[u8]) -> Tag {
    Tag::Sequence(Sequence {
        class: TagClass::Context,
        id: filtertype,
        inner: vec![
               Tag::OctetString(OctetString {
                   inner: attr.to_vec(),
                   .. Default::default()
               }),
               Tag::OctetString(OctetString {
                   inner: value.to_vec(),
                   .. Default::default()
               })
        ]
    })
}

fn present_tag(attr: &[u8]) -> Tag {
    (Tag::OctetString(OctetString {
        class: TagClass::Context,
        id: 7,
        inner: attr.to_vec(),
    }))
}

const SUB_MATCH: u64 = 4;

const SUB_INITIAL: u64 = 0;
const SUB_ANY: u64 = 1;
const SUB_FINAL: u64 = 2;

fn substr_tag(attr: &[u8], value: &[u8]) -> Tag {
    let mut inner = vec![];
    let mut first = true;
    let mut replace_last = true;
    for sub_elem in value.split(|&b| b == b'*') {
        if first {
            first = false;
            if !sub_elem.is_empty() {
                inner.push(Tag::OctetString(OctetString {
                    class: TagClass::Context,
                    id: SUB_INITIAL,
                    inner: sub_elem.to_vec(),
                }));
            }
        } else {
            if sub_elem.is_empty() {
                replace_last = false;
            } else {
                inner.push(Tag::OctetString(OctetString {
                    class: TagClass::Context,
                    id: SUB_ANY,
                    inner: sub_elem.to_vec(),
                }));
            }
        }
    }
    if replace_last {
        let mut last_elem = inner.pop().expect("last element");
        match last_elem {
            Tag::OctetString(ref mut o) => { o.id = SUB_FINAL; },
            _ => unimplemented!(),
        }
        inner.push(last_elem);
    }
    Tag::Sequence(Sequence {
        class: TagClass::Context,
        id: SUB_MATCH,
        inner: vec![
               Tag::OctetString(OctetString {
                   inner: attr.to_vec(),
                   .. Default::default()
               }),
               Tag::Sequence(Sequence {
                   inner: inner,
                   .. Default::default()
               })
        ]
    })
}

named!(extensible<Tag>, alt!(attr_dn_mrule | dn_mrule));

named!(attr_dn_mrule<Tag>, do_parse!(
    attr: attributedescription >>
    dn: opt!(tag!(":dn")) >>
    mrule: opt!(preceded!(char!(':'), attributetype)) >>
    tag!(":=") >>
    value: take_while!(is_ext_value_char) >>
    (extensible_tag(mrule, Some(attr), value, dn.is_some()))
));

named!(dn_mrule<Tag>, do_parse!(
    dn: opt!(tag!(":dn")) >>
    mrule: preceded!(char!(':'), attributetype) >>
    tag!(":=") >>
    value: take_while!(is_ext_value_char) >>
    (extensible_tag(Some(mrule), None, value, dn.is_some()))
));

fn is_ext_value_char(c: u8) -> bool {
    is_value_char(c) && c != b'*'
}

fn extensible_tag(mrule: Option<&[u8]>, attr: Option<&[u8]>, value: &[u8], dn: bool) -> Tag {
    let mut inner = vec![];
    if let Some(mrule) = mrule {
        inner.push(Tag::OctetString(OctetString {
            class: TagClass::Context,
            id: 1,
            inner: mrule.to_vec()
        }));
    }
    if let Some(attr) = attr {
        inner.push(Tag::OctetString(OctetString {
            class: TagClass::Context,
            id: 2,
            inner: attr.to_vec()
        }));
    }
    inner.push(Tag::OctetString(OctetString {
        class: TagClass::Context,
        id: 3,
        inner: value.to_vec()
    }));
    if dn {
        inner.push(Tag::Boolean(Boolean {
            class: TagClass::Context,
            id: 4,
            inner: dn
        }));
    }
    Tag::Sequence(Sequence {
        class: TagClass::Context,
        id: 9,
        inner: inner
    })
}

named!(attributedescription<&[u8]>, recognize!(do_parse!(
    _type: attributetype >>
    _opts: many0!(preceded!(char!(';'), take_while1!(is_alnum_hyphen))) >> ()
)));

named!(attributetype<&[u8]>, alt!(numericoid | descr));

named!(numericoid<&[u8]>, recognize!(
    do_parse!(
        _leading: number >>
        _rest: many0!(preceded!(char!('.'), number)) >> ()
    )
));

named!(number<&[u8]>, verify!(digit, |d: &[u8]| d.len() == 1 || d[0] != b'0'));

named!(descr<&[u8]>, recognize!(
    do_parse!(
        _leading: verify!(be_u8, |a: u8| is_alphabetic(a)) >>
        _rest: take_while!(is_alnum_hyphen) >> ()
    )
));

fn is_alnum_hyphen(c: u8) -> bool {
    is_alphanumeric(c) || c == b'-'
}
<commit_msg>Further filter parser improvements<commit_after>use std::default::Default;
use std::str;

use nom::IResult;
use nom::{be_u8, digit, is_alphabetic, is_alphanumeric, is_hex_digit};

use asnom::common::TagClass;
use asnom::structures::{Boolean, ExplicitTag, OctetString, Sequence, Tag};

pub fn parse(input: &str) -> Result<Tag, ()> {
    match filtexpr(input.as_bytes()) {
        IResult::Done(r, t) => {
            if r.is_empty() {
                Ok(t)
            } else {
                Err(())
            }
        },
        IResult::Error(_) | IResult::Incomplete(_) => Err(()),
    }
}

const AND_FILT: u64 = 0;
const OR_FILT: u64 = 1;
const NOT_FILT: u64 = 2;

const EQ_MATCH: u64 = 3;
const SUBSTR_MATCH: u64 = 4;
const GTE_MATCH: u64 = 5;
const LTE_MATCH: u64 = 6;
const PRES_MATCH: u64 = 7;
const APPROX_MATCH: u64 = 8;
const EXT_MATCH: u64 = 9;

const SUB_INITIAL: u64 = 0;
const SUB_ANY: u64 = 1;
const SUB_FINAL: u64 = 2;

named!(filtexpr<Tag>, alt!(filter | item));

named!(filter<Tag>, delimited!(char!('('), filtercomp, char!(')')));
named!(filtercomp<Tag>, alt!(and | or | not | item));
named!(filterlist<Vec<Tag>>, many0!(filter));

named!(and<Tag>, map!(preceded!(char!('&'), filterlist),
    |tagv: Vec<Tag>| -> Tag {
        Tag::Sequence(Sequence {
            class: TagClass::Context,
            id: AND_FILT,
            inner: tagv,
        })
    }
));

named!(or<Tag>, map!(preceded!(char!('|'), filterlist),
    |tagv: Vec<Tag>| -> Tag {
        Tag::Sequence(Sequence {
            class: TagClass::Context,
            id: OR_FILT,
            inner: tagv,
        })
    }
));

named!(not<Tag>, map!(preceded!(char!('!'), filter),
    |tag: Tag| -> Tag {
        Tag::ExplicitTag(ExplicitTag {
            class: TagClass::Context,
            id: NOT_FILT,
            inner: Box::new(tag),
        })
    }
));

named!(item<Tag>, alt!(eq | non_eq | extensible));

enum Unescaper {
    WantFirst,
    WantSecond(u8),
    Value(u8),
    Error,
}

impl Unescaper {
    fn feed(&self, c: u8) -> Unescaper {
        match *self {
            Unescaper::Error => Unescaper::Error,
            Unescaper::WantFirst => {
                if is_hex_digit(c) {
                    Unescaper::WantSecond(c - if c <= b'9' { b'0' } else { (c & 0x20) + b'A' - 10 })
                } else {
                    Unescaper::Error
                }
            },
            Unescaper::WantSecond(partial) => {
                if is_hex_digit(c) {
                    Unescaper::Value((partial << 4) + (c - if c <= b'9' { b'0' } else { (c & 0x20) + b'A' - 10 }))
                } else {
                    Unescaper::Error
                }
            },
            Unescaper::Value(_v) => if c != b'\\' { Unescaper::Value(c) } else { Unescaper::WantFirst },
        }
    }
}

// Any byte in the assertion value may be represented by \NN, where N is a hex digit.
// Some characters must be represented in this way: parentheses, asterisk and backslash
// itself.
named!(unescaped<Vec<u8>>, map_res!(fold_many0!(
    verify!(be_u8, is_value_char),
    (Unescaper::Value(0), Vec::new()),
    |(mut u, mut vec): (Unescaper, Vec<_>), c: u8| {
        u = u.feed(c);
        if let Unescaper::Value(c) = u {
            vec.push(c);
        }
        (u, vec)
    }), |(u, vec): (Unescaper, Vec<_>)| -> Result<Vec<u8>, ()> {
        if let Unescaper::Value(_) = u {
            Ok(vec)
        } else {
            Err(())
        }
    }
));

named!(non_eq<Tag>, do_parse!(
    attr: attributedescription >>
    filterop: alt!(tag!(">=") | tag!("<=") | tag!("~=")) >>
    value: unescaped >> ({
        Tag::Sequence(Sequence {
            class: TagClass::Context,
            id: filtertag(filterop),
            inner: vec![
                   Tag::OctetString(OctetString {
                       inner: attr.to_vec(),
                       .. Default::default()
                   }),
                   Tag::OctetString(OctetString {
                       inner: value,
                       .. Default::default()
                   })
            ]
        })
    })
));

fn filtertag(filterop: &[u8]) -> u64 {
    match filterop {
        b">=" => GTE_MATCH,
        b"<=" => LTE_MATCH,
        b"~=" => APPROX_MATCH,
        _ => unimplemented!(),
    }
}

named!(eq<Tag>, do_parse!(
    attr: attributedescription >>
    tag!("=") >>
    initial: unescaped >>
    mid_final: map_res!(many0!(preceded!(tag!("*"), unescaped)), |v: Vec<Vec<u8>>| -> Result<Vec<Vec<u8>>, ()> {
        // an empty element may exist only at the very end; otherwise, we have two adjacent asterisks
        if v.iter().enumerate().fold(false, |acc, (n, ref ve)| acc || ve.is_empty() && n + 1 != v.len()) {
            Err(())
        } else {
            Ok(v)
        }
    }) >> ({
        if mid_final.is_empty() {
            // simple equality, no asterisks in assertion value
            Tag::Sequence(Sequence {
                class: TagClass::Context,
                id: EQ_MATCH,
                inner: vec![
                       Tag::OctetString(OctetString {
                           inner: attr.to_vec(),
                           .. Default::default()
                       }),
                       Tag::OctetString(OctetString {
                           inner: initial,
                           .. Default::default()
                       })
                ]
            })
        } else if initial.is_empty() && mid_final.len() == 1 && mid_final[0].is_empty() {
            // presence, single asterisk in assertion value
            Tag::OctetString(OctetString {
                class: TagClass::Context,
                id: PRES_MATCH,
                inner: attr.to_vec(),
            })
        } else {
            // substring match
            let mut inner = vec![];
            if !initial.is_empty() {
                inner.push(Tag::OctetString(OctetString {
                    class: TagClass::Context,
                    id: SUB_INITIAL,
                    inner: initial,
                }));
            }
            let n = mid_final.len();
            for (i, sub_elem) in mid_final.into_iter().enumerate() {
                if sub_elem.is_empty() {
                    break;
                }
                inner.push(Tag::OctetString(OctetString {
                    class: TagClass::Context,
                    id: if i + 1 != n { SUB_ANY } else { SUB_FINAL },
                    inner: sub_elem,
                }));
            }
            Tag::Sequence(Sequence {
                class: TagClass::Context,
                id: SUBSTR_MATCH,
                inner: vec![
                       Tag::OctetString(OctetString {
                           inner: attr.to_vec(),
                           .. Default::default()
                       }),
                       Tag::Sequence(Sequence {
                           inner: inner,
                           .. Default::default()
                       })
                ]
            })
        }
    })
));

fn is_value_char(c: u8) -> bool {
    c != 0 && c != b'(' && c != b')' && c != b'*'
}

named!(extensible<Tag>, alt!(attr_dn_mrule | dn_mrule));

named!(attr_dn_mrule<Tag>, do_parse!(
    attr: attributedescription >>
    dn: opt!(tag!(":dn")) >>
    mrule: opt!(preceded!(char!(':'), attributetype)) >>
    tag!(":=") >>
    value: unescaped >>
    (extensible_tag(mrule, Some(attr), value, dn.is_some()))
));

named!(dn_mrule<Tag>, do_parse!(
    dn: opt!(tag!(":dn")) >>
    mrule: preceded!(char!(':'), attributetype) >>
    tag!(":=") >>
    value: unescaped >>
    (extensible_tag(Some(mrule), None, value, dn.is_some()))
));

fn extensible_tag(mrule: Option<&[u8]>, attr: Option<&[u8]>, value: Vec<u8>, dn: bool) -> Tag {
    let mut inner = vec![];
    if let Some(mrule) = mrule {
        inner.push(Tag::OctetString(OctetString {
            class: TagClass::Context,
            id: 1,
            inner: mrule.to_vec()
        }));
    }
    if let Some(attr) = attr {
        inner.push(Tag::OctetString(OctetString {
            class: TagClass::Context,
            id: 2,
            inner: attr.to_vec()
        }));
    }
    inner.push(Tag::OctetString(OctetString {
        class: TagClass::Context,
        id: 3,
        inner: value
    }));
    if dn {
        inner.push(Tag::Boolean(Boolean {
            class: TagClass::Context,
            id: 4,
            inner: dn
        }));
    }
    Tag::Sequence(Sequence {
        class: TagClass::Context,
        id: EXT_MATCH,
        inner: inner
    })
}

named!(attributedescription<&[u8]>, recognize!(do_parse!(
    _type: attributetype >>
    _opts: many0!(preceded!(char!(';'), take_while1!(is_alnum_hyphen))) >> ()
)));

named!(attributetype<&[u8]>, alt!(numericoid | descr));

named!(numericoid<&[u8]>, recognize!(
    do_parse!(
        _leading: number >>
        _rest: many0!(preceded!(char!('.'), number)) >> ()
    )
));

// A number may be zero, but must not have superfluous leading zeroes
named!(number<&[u8]>, verify!(digit, |d: &[u8]| d.len() == 1 || d[0] != b'0'));

named!(descr<&[u8]>, recognize!(
    do_parse!(
        _leading: verify!(be_u8, |a: u8| is_alphabetic(a)) >>
        _rest: take_while!(is_alnum_hyphen) >> ()
    )
));

fn is_alnum_hyphen(c: u8) -> bool {
    is_alphanumeric(c) || c == b'-'
}
<|endoftext|>


<commit_before>use crate::hasher::{Digest, Size, StatefulHasher};
use generic_array::GenericArray;

macro_rules! derive_digest {
    ($name:ident) => {
        /// Multihash digest.
        #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
        pub struct $name<S: Size>(GenericArray<u8, S>);

        impl<S: Size> Copy for $name<S> where S::ArrayType: Copy {}

        impl<S: Size> AsRef<[u8]> for $name<S> {
            fn as_ref(&self) -> &[u8] {
                &self.0
            }
        }

        impl<S: Size> AsMut<[u8]> for $name<S> {
            fn as_mut(&mut self) -> &mut [u8] {
                &mut self.0
            }
        }

        impl<S: Size> From<GenericArray<u8, S>> for $name<S> {
            fn from(array: GenericArray<u8, S>) -> Self {
                Self(array)
            }
        }

        impl<S: Size> From<$name<S>> for GenericArray<u8, S> {
            fn from(digest: $name<S>) -> Self {
                digest.0
            }
        }

        #[cfg(feature = "scale-codec")]
        impl parity_scale_codec::Encode for $name<$crate::U32> {
            fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
                let mut digest = [0; 32];
                digest.copy_from_slice(self.as_ref());
                digest.using_encoded(f)
            }
        }

        #[cfg(feature = "scale-codec")]
        impl parity_scale_codec::Decode for $name<$crate::U32> {
            fn decode<I: parity_scale_codec::Input>(
                input: &mut I,
            ) -> Result<Self, parity_scale_codec::Error> {
                let digest = <[u8; 32]>::decode(input)?;
                let mut array = GenericArray::default();
                array.copy_from_slice(&digest[..]);
                Ok(Self(array))
            }
        }

        #[cfg(feature = "scale-codec")]
        impl parity_scale_codec::Encode for $name<$crate::U64> {
            fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
                let mut digest = [0; 64];
                digest.copy_from_slice(self.as_ref());
                digest.using_encoded(f)
            }
        }

        #[cfg(feature = "scale-codec")]
        impl parity_scale_codec::Decode for $name<$crate::U64> {
            fn decode<I: parity_scale_codec::Input>(
                input: &mut I,
            ) -> Result<Self, parity_scale_codec::Error> {
                let digest = <[u8; 64]>::decode(input)?;
                let mut array = GenericArray::default();
                array.copy_from_slice(&digest[..]);
                Ok(Self(array))
            }
        }

        #[cfg(feature = "serde-codec")]
        impl<SZ: Size> serde::Serialize for $name<SZ> {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                use serde::ser::SerializeTuple;

                let mut seq = serializer.serialize_tuple(self.0.len())?;
                for elem in &self.0[..] {
                    seq.serialize_element(elem)?;
                }
                seq.end()
            }
        }

        #[cfg(feature = "serde-codec")]
        impl<'de, S: Size> serde::Deserialize<'de> for $name<S> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                use core::marker::PhantomData;

                pub struct DigestVisitor<S: Size>(PhantomData<S>);

                impl<'de, S: Size> serde::de::Visitor<'de> for DigestVisitor<S> {
                    type Value = $name<S>;

                    fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
                        write!(f, "an array of length {}", S::to_u8())
                    }

                    fn visit_seq<A: serde::de::SeqAccess<'de>>(
                        self,
                        mut seq: A,
                    ) -> Result<Self::Value, A::Error> {
                        let mut arr = GenericArray::default();
                        for (i, b) in arr.iter_mut().enumerate() {
                            *b = seq
                                .next_element()?
                                .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;
                        }
                        Ok($name(arr))
                    }
                }
                deserializer.deserialize_tuple(S::to_usize(), DigestVisitor(PhantomData))
            }
        }

        impl<S: Size> Digest<S> for $name<S> {}
    };
}

#[cfg(any(feature = "blake2b", feature = "blake2s"))]
macro_rules! derive_hasher_blake {
    ($module:ident, $name:ident, $digest:ident) => {
        derive_digest!($digest);

        /// Multihash hasher.
        #[derive(Debug)]
        pub struct $name<S: Size> {
            _marker: PhantomData<S>,
            state: $module::State,
        }

        impl<S: Size> Default for $name<S> {
            fn default() -> Self {
                let mut params = $module::Params::new();
                params.hash_length(S::to_usize());
                Self {
                    _marker: PhantomData,
                    state: params.to_state(),
                }
            }
        }

        impl<S: Size> StatefulHasher for $name<S> {
            type Size = S;
            type Digest = $digest<Self::Size>;

            fn update(&mut self, input: &[u8]) {
                self.state.update(input);
            }

            fn finalize(&self) -> Self::Digest {
                let digest = GenericArray::clone_from_slice(self.state.finalize().as_bytes());
                Self::Digest::from(digest)
            }

            fn reset(&mut self) {
                let Self { state, .. } = Self::default();
                self.state = state;
            }
        }
    };
}

#[cfg(feature = "blake2b")]
pub mod blake2b {
    use super::*;
    use core::marker::PhantomData;
    use generic_array::typenum::{U32, U64};

    derive_hasher_blake!(blake2b_simd, Blake2bHasher, Blake2bDigest);

    /// 256 bit blake2b hasher.
    pub type Blake2b256 = Blake2bHasher<U32>;

    /// 512 bit blake2b hasher.
    pub type Blake2b512 = Blake2bHasher<U64>;
}

#[cfg(feature = "blake2s")]
pub mod blake2s {
    use super::*;
    use core::marker::PhantomData;
    use generic_array::typenum::{U16, U32};

    derive_hasher_blake!(blake2s_simd, Blake2sHasher, Blake2sDigest);

    /// 256 bit blake2b hasher.
    pub type Blake2s128 = Blake2sHasher<U16>;

    /// 512 bit blake2b hasher.
    pub type Blake2s256 = Blake2sHasher<U32>;
}

#[cfg(feature = "digest")]
macro_rules! derive_hasher_sha {
    ($module:ty, $name:ident, $size:ty, $digest:ident) => {
        /// Multihash hasher.
        #[derive(Debug, Default)]
        pub struct $name {
            state: $module,
        }

        impl $crate::hasher::StatefulHasher for $name {
            type Size = $size;
            type Digest = $digest<Self::Size>;

            fn update(&mut self, input: &[u8]) {
                use digest::Digest;
                self.state.update(input)
            }

            fn finalize(&self) -> Self::Digest {
                use digest::Digest;
                Self::Digest::from(self.state.clone().finalize())
            }

            fn reset(&mut self) {
                use digest::Digest;
                self.state.reset();
            }
        }
    };
}

#[cfg(feature = "sha1")]
pub mod sha1 {
    use super::*;
    use generic_array::typenum::U20;

    derive_digest!(Sha1Digest);
    derive_hasher_sha!(::sha1::Sha1, Sha1, U20, Sha1Digest);
}

#[cfg(feature = "sha2")]
pub mod sha2 {
    use super::*;
    use generic_array::typenum::{U32, U64};

    derive_digest!(Sha2Digest);
    derive_hasher_sha!(sha_2::Sha256, Sha2_256, U32, Sha2Digest);
    derive_hasher_sha!(sha_2::Sha512, Sha2_512, U64, Sha2Digest);
}

#[cfg(feature = "sha3")]
pub mod sha3 {
    use super::*;
    use generic_array::typenum::{U28, U32, U48, U64};

    derive_digest!(Sha3Digest);
    derive_hasher_sha!(sha_3::Sha3_224, Sha3_224, U28, Sha3Digest);
    derive_hasher_sha!(sha_3::Sha3_256, Sha3_256, U32, Sha3Digest);
    derive_hasher_sha!(sha_3::Sha3_384, Sha3_384, U48, Sha3Digest);
    derive_hasher_sha!(sha_3::Sha3_512, Sha3_512, U64, Sha3Digest);

    derive_digest!(KeccakDigest);
    derive_hasher_sha!(sha_3::Keccak224, Keccak224, U28, KeccakDigest);
    derive_hasher_sha!(sha_3::Keccak256, Keccak256, U32, KeccakDigest);
    derive_hasher_sha!(sha_3::Keccak384, Keccak384, U48, KeccakDigest);
    derive_hasher_sha!(sha_3::Keccak512, Keccak512, U64, KeccakDigest);
}

pub mod identity {
    use super::*;
    use crate::error::Error;
    use generic_array::typenum::U32;

    /// Multihash digest.
    #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
    pub struct IdentityDigest<S: Size>(u8, GenericArray<u8, S>);

    impl<S: Size> AsRef<[u8]> for IdentityDigest<S> {
        fn as_ref(&self) -> &[u8] {
            &self.1[..self.0 as usize]
        }
    }

    impl<S: Size> AsMut<[u8]> for IdentityDigest<S> {
        fn as_mut(&mut self) -> &mut [u8] {
            &mut self.1[..self.0 as usize]
        }
    }

    impl<S: Size> From<GenericArray<u8, S>> for IdentityDigest<S> {
        fn from(array: GenericArray<u8, S>) -> Self {
            Self(array.len() as u8, array)
        }
    }

    impl<S: Size> From<IdentityDigest<S>> for GenericArray<u8, S> {
        fn from(digest: IdentityDigest<S>) -> Self {
            digest.1
        }
    }

    impl<S: Size> Digest<S> for IdentityDigest<S> {
        fn size(&self) -> u8 {
            self.0
        }

        // A custom implementation is needed as an identity hash value might be shorter than the
        // allocated Digest.
        fn wrap(digest: &[u8]) -> Result<Self, Error> {
            Self::extend(digest)
        }

        // a custom implementation is needed as an identity hash also stores the actual size of
        // the given digest.
        fn fit(digest: &[u8]) -> Self {
            let mut array = GenericArray::default();
            let len = digest.len().min(array.len());
            array[..len].copy_from_slice(&digest[..len]);
            Self(len as u8, array)
        }

        // A custom implementation is needed as an identity hash also stores the actual size of
        // the given digest.
        #[cfg(feature = "std")]
        fn from_reader<R>(mut r: R) -> Result<Self, Error>
        where
            R: std::io::Read,
        {
            use unsigned_varint::io::read_u64;

            let size = read_u64(&mut r)?;
            if size > S::to_u64() || size > u8::MAX as u64 {
                return Err(Error::InvalidSize(size));
            }
            let mut digest = GenericArray::default();
            r.read_exact(&mut digest[..size as usize])?;
            Ok(Self(size as u8, digest))
        }
    }

    /// Identity hasher with a maximum size.
    ///
    /// # Panics
    ///
    /// Panics if the input is bigger than the maximum size.
    #[derive(Debug, Default)]
    pub struct IdentityHasher<S: Size> {
        bytes: GenericArray<u8, S>,
        i: usize,
    }

    impl<S: Size> StatefulHasher for IdentityHasher<S> {
        type Size = S;
        type Digest = IdentityDigest<Self::Size>;

        fn update(&mut self, input: &[u8]) {
            let start = self.i.min(self.bytes.len());
            let end = (self.i + input.len()).min(self.bytes.len());
            self.bytes[start..end].copy_from_slice(&input);
            self.i = end;
        }

        fn finalize(&self) -> Self::Digest {
            IdentityDigest(self.i as u8, self.bytes.clone())
        }

        fn reset(&mut self) {
            self.bytes = Default::default();
            self.i = 0;
        }
    }

    /// 32 byte Identity hasher (constrained to 32 bytes).
    ///
    /// # Panics
    ///
    /// Panics if the input is bigger than 32 bytes.
    pub type Identity256 = IdentityHasher<U32>;
}

pub mod unknown {
    use super::*;
    derive_digest!(UnknownDigest);
}

#[cfg(feature = "strobe")]
pub mod strobe {
    use super::*;
    use core::marker::PhantomData;
    use generic_array::typenum::{U32, U64};
    use strobe_rs::{SecParam, Strobe};

    derive_digest!(StrobeDigest);

    /// Strobe hasher.
    pub struct StrobeHasher<S: Size> {
        _marker: PhantomData<S>,
        strobe: Strobe,
        initialized: bool,
    }

    impl<S: Size> Default for StrobeHasher<S> {
        fn default() -> Self {
            Self {
                _marker: PhantomData,
                strobe: Strobe::new(b"StrobeHash", SecParam::B128),
                initialized: false,
            }
        }
    }

    impl<S: Size> StatefulHasher for StrobeHasher<S> {
        type Size = S;
        type Digest = StrobeDigest<Self::Size>;

        fn update(&mut self, input: &[u8]) {
            self.strobe.ad(input, self.initialized);
            self.initialized = true;
        }

        fn finalize(&self) -> Self::Digest {
            let mut hash = GenericArray::default();
            self.strobe.clone().prf(&mut hash, false);
            Self::Digest::from(hash)
        }

        fn reset(&mut self) {
            let Self { strobe, .. } = Self::default();
            self.strobe = strobe;
            self.initialized = false;
        }
    }

    /// 256 bit strobe hasher.
    pub type Strobe256 = StrobeHasher<U32>;

    /// 512 bit strobe hasher.
    pub type Strobe512 = StrobeHasher<U64>;
}
<commit_msg>feat: add slice to Digest conversion<commit_after>use crate::error::Error;
use crate::hasher::{Digest, Size, StatefulHasher};
use core::convert::TryFrom;
use generic_array::GenericArray;

macro_rules! derive_digest {
    ($name:ident) => {
        /// Multihash digest.
        #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
        pub struct $name<S: Size>(GenericArray<u8, S>);

        impl<S: Size> Copy for $name<S> where S::ArrayType: Copy {}

        impl<S: Size> AsRef<[u8]> for $name<S> {
            fn as_ref(&self) -> &[u8] {
                &self.0
            }
        }

        impl<S: Size> AsMut<[u8]> for $name<S> {
            fn as_mut(&mut self) -> &mut [u8] {
                &mut self.0
            }
        }

        impl<S: Size> From<GenericArray<u8, S>> for $name<S> {
            fn from(array: GenericArray<u8, S>) -> Self {
                Self(array)
            }
        }

        impl<S: Size> From<$name<S>> for GenericArray<u8, S> {
            fn from(digest: $name<S>) -> Self {
                digest.0
            }
        }

        /// Convert slice to `Digest`.
        ///
        /// It errors when the length of the slice does not match the size of the `Digest`.
        impl<S: Size> TryFrom<&[u8]> for $name<S> {
            type Error = Error;

            fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
                Self::wrap(slice)
            }
        }

        #[cfg(feature = "scale-codec")]
        impl parity_scale_codec::Encode for $name<$crate::U32> {
            fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
                let mut digest = [0; 32];
                digest.copy_from_slice(self.as_ref());
                digest.using_encoded(f)
            }
        }

        #[cfg(feature = "scale-codec")]
        impl parity_scale_codec::Decode for $name<$crate::U32> {
            fn decode<I: parity_scale_codec::Input>(
                input: &mut I,
            ) -> Result<Self, parity_scale_codec::Error> {
                let digest = <[u8; 32]>::decode(input)?;
                let mut array = GenericArray::default();
                array.copy_from_slice(&digest[..]);
                Ok(Self(array))
            }
        }

        #[cfg(feature = "scale-codec")]
        impl parity_scale_codec::Encode for $name<$crate::U64> {
            fn using_encoded<R, F: FnOnce(&[u8]) -> R>(&self, f: F) -> R {
                let mut digest = [0; 64];
                digest.copy_from_slice(self.as_ref());
                digest.using_encoded(f)
            }
        }

        #[cfg(feature = "scale-codec")]
        impl parity_scale_codec::Decode for $name<$crate::U64> {
            fn decode<I: parity_scale_codec::Input>(
                input: &mut I,
            ) -> Result<Self, parity_scale_codec::Error> {
                let digest = <[u8; 64]>::decode(input)?;
                let mut array = GenericArray::default();
                array.copy_from_slice(&digest[..]);
                Ok(Self(array))
            }
        }

        #[cfg(feature = "serde-codec")]
        impl<SZ: Size> serde::Serialize for $name<SZ> {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                use serde::ser::SerializeTuple;

                let mut seq = serializer.serialize_tuple(self.0.len())?;
                for elem in &self.0[..] {
                    seq.serialize_element(elem)?;
                }
                seq.end()
            }
        }

        #[cfg(feature = "serde-codec")]
        impl<'de, S: Size> serde::Deserialize<'de> for $name<S> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: serde::Deserializer<'de>,
            {
                use core::marker::PhantomData;

                pub struct DigestVisitor<S: Size>(PhantomData<S>);

                impl<'de, S: Size> serde::de::Visitor<'de> for DigestVisitor<S> {
                    type Value = $name<S>;

                    fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
                        write!(f, "an array of length {}", S::to_u8())
                    }

                    fn visit_seq<A: serde::de::SeqAccess<'de>>(
                        self,
                        mut seq: A,
                    ) -> Result<Self::Value, A::Error> {
                        let mut arr = GenericArray::default();
                        for (i, b) in arr.iter_mut().enumerate() {
                            *b = seq
                                .next_element()?
                                .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;
                        }
                        Ok($name(arr))
                    }
                }
                deserializer.deserialize_tuple(S::to_usize(), DigestVisitor(PhantomData))
            }
        }

        impl<S: Size> Digest<S> for $name<S> {}
    };
}

#[cfg(any(feature = "blake2b", feature = "blake2s"))]
macro_rules! derive_hasher_blake {
    ($module:ident, $name:ident, $digest:ident) => {
        derive_digest!($digest);

        /// Multihash hasher.
        #[derive(Debug)]
        pub struct $name<S: Size> {
            _marker: PhantomData<S>,
            state: $module::State,
        }

        impl<S: Size> Default for $name<S> {
            fn default() -> Self {
                let mut params = $module::Params::new();
                params.hash_length(S::to_usize());
                Self {
                    _marker: PhantomData,
                    state: params.to_state(),
                }
            }
        }

        impl<S: Size> StatefulHasher for $name<S> {
            type Size = S;
            type Digest = $digest<Self::Size>;

            fn update(&mut self, input: &[u8]) {
                self.state.update(input);
            }

            fn finalize(&self) -> Self::Digest {
                let digest = self.state.finalize();
                Self::Digest::try_from(digest.as_bytes()).expect("digest sizes always match")
            }

            fn reset(&mut self) {
                let Self { state, .. } = Self::default();
                self.state = state;
            }
        }
    };
}

#[cfg(feature = "blake2b")]
pub mod blake2b {
    use super::*;
    use core::marker::PhantomData;
    use generic_array::typenum::{U32, U64};

    derive_hasher_blake!(blake2b_simd, Blake2bHasher, Blake2bDigest);

    /// 256 bit blake2b hasher.
    pub type Blake2b256 = Blake2bHasher<U32>;

    /// 512 bit blake2b hasher.
    pub type Blake2b512 = Blake2bHasher<U64>;
}

#[cfg(feature = "blake2s")]
pub mod blake2s {
    use super::*;
    use core::marker::PhantomData;
    use generic_array::typenum::{U16, U32};

    derive_hasher_blake!(blake2s_simd, Blake2sHasher, Blake2sDigest);

    /// 256 bit blake2b hasher.
    pub type Blake2s128 = Blake2sHasher<U16>;

    /// 512 bit blake2b hasher.
    pub type Blake2s256 = Blake2sHasher<U32>;
}

#[cfg(feature = "digest")]
macro_rules! derive_hasher_sha {
    ($module:ty, $name:ident, $size:ty, $digest:ident) => {
        /// Multihash hasher.
        #[derive(Debug, Default)]
        pub struct $name {
            state: $module,
        }

        impl $crate::hasher::StatefulHasher for $name {
            type Size = $size;
            type Digest = $digest<Self::Size>;

            fn update(&mut self, input: &[u8]) {
                use digest::Digest;
                self.state.update(input)
            }

            fn finalize(&self) -> Self::Digest {
                use digest::Digest;
                Self::Digest::from(self.state.clone().finalize())
            }

            fn reset(&mut self) {
                use digest::Digest;
                self.state.reset();
            }
        }
    };
}

#[cfg(feature = "sha1")]
pub mod sha1 {
    use super::*;
    use generic_array::typenum::U20;

    derive_digest!(Sha1Digest);
    derive_hasher_sha!(::sha1::Sha1, Sha1, U20, Sha1Digest);
}

#[cfg(feature = "sha2")]
pub mod sha2 {
    use super::*;
    use generic_array::typenum::{U32, U64};

    derive_digest!(Sha2Digest);
    derive_hasher_sha!(sha_2::Sha256, Sha2_256, U32, Sha2Digest);
    derive_hasher_sha!(sha_2::Sha512, Sha2_512, U64, Sha2Digest);
}

#[cfg(feature = "sha3")]
pub mod sha3 {
    use super::*;
    use generic_array::typenum::{U28, U32, U48, U64};

    derive_digest!(Sha3Digest);
    derive_hasher_sha!(sha_3::Sha3_224, Sha3_224, U28, Sha3Digest);
    derive_hasher_sha!(sha_3::Sha3_256, Sha3_256, U32, Sha3Digest);
    derive_hasher_sha!(sha_3::Sha3_384, Sha3_384, U48, Sha3Digest);
    derive_hasher_sha!(sha_3::Sha3_512, Sha3_512, U64, Sha3Digest);

    derive_digest!(KeccakDigest);
    derive_hasher_sha!(sha_3::Keccak224, Keccak224, U28, KeccakDigest);
    derive_hasher_sha!(sha_3::Keccak256, Keccak256, U32, KeccakDigest);
    derive_hasher_sha!(sha_3::Keccak384, Keccak384, U48, KeccakDigest);
    derive_hasher_sha!(sha_3::Keccak512, Keccak512, U64, KeccakDigest);
}

pub mod identity {
    use super::*;
    use crate::error::Error;
    use generic_array::typenum::U32;

    /// Multihash digest.
    #[derive(Clone, Debug, Default, Eq, Hash, PartialEq)]
    pub struct IdentityDigest<S: Size>(u8, GenericArray<u8, S>);

    impl<S: Size> AsRef<[u8]> for IdentityDigest<S> {
        fn as_ref(&self) -> &[u8] {
            &self.1[..self.0 as usize]
        }
    }

    impl<S: Size> AsMut<[u8]> for IdentityDigest<S> {
        fn as_mut(&mut self) -> &mut [u8] {
            &mut self.1[..self.0 as usize]
        }
    }

    impl<S: Size> From<GenericArray<u8, S>> for IdentityDigest<S> {
        fn from(array: GenericArray<u8, S>) -> Self {
            Self(array.len() as u8, array)
        }
    }

    impl<S: Size> From<IdentityDigest<S>> for GenericArray<u8, S> {
        fn from(digest: IdentityDigest<S>) -> Self {
            digest.1
        }
    }

    impl<S: Size> Digest<S> for IdentityDigest<S> {
        fn size(&self) -> u8 {
            self.0
        }

        // A custom implementation is needed as an identity hash value might be shorter than the
        // allocated Digest.
        fn wrap(digest: &[u8]) -> Result<Self, Error> {
            Self::extend(digest)
        }

        // a custom implementation is needed as an identity hash also stores the actual size of
        // the given digest.
        fn fit(digest: &[u8]) -> Self {
            let mut array = GenericArray::default();
            let len = digest.len().min(array.len());
            array[..len].copy_from_slice(&digest[..len]);
            Self(len as u8, array)
        }

        // A custom implementation is needed as an identity hash also stores the actual size of
        // the given digest.
        #[cfg(feature = "std")]
        fn from_reader<R>(mut r: R) -> Result<Self, Error>
        where
            R: std::io::Read,
        {
            use unsigned_varint::io::read_u64;

            let size = read_u64(&mut r)?;
            if size > S::to_u64() || size > u8::MAX as u64 {
                return Err(Error::InvalidSize(size));
            }
            let mut digest = GenericArray::default();
            r.read_exact(&mut digest[..size as usize])?;
            Ok(Self(size as u8, digest))
        }
    }

    /// Identity hasher with a maximum size.
    ///
    /// # Panics
    ///
    /// Panics if the input is bigger than the maximum size.
    #[derive(Debug, Default)]
    pub struct IdentityHasher<S: Size> {
        bytes: GenericArray<u8, S>,
        i: usize,
    }

    impl<S: Size> StatefulHasher for IdentityHasher<S> {
        type Size = S;
        type Digest = IdentityDigest<Self::Size>;

        fn update(&mut self, input: &[u8]) {
            let start = self.i.min(self.bytes.len());
            let end = (self.i + input.len()).min(self.bytes.len());
            self.bytes[start..end].copy_from_slice(&input);
            self.i = end;
        }

        fn finalize(&self) -> Self::Digest {
            IdentityDigest(self.i as u8, self.bytes.clone())
        }

        fn reset(&mut self) {
            self.bytes = Default::default();
            self.i = 0;
        }
    }

    /// 32 byte Identity hasher (constrained to 32 bytes).
    ///
    /// # Panics
    ///
    /// Panics if the input is bigger than 32 bytes.
    pub type Identity256 = IdentityHasher<U32>;
}

pub mod unknown {
    use super::*;
    derive_digest!(UnknownDigest);
}

#[cfg(feature = "strobe")]
pub mod strobe {
    use super::*;
    use core::marker::PhantomData;
    use generic_array::typenum::{U32, U64};
    use strobe_rs::{SecParam, Strobe};

    derive_digest!(StrobeDigest);

    /// Strobe hasher.
    pub struct StrobeHasher<S: Size> {
        _marker: PhantomData<S>,
        strobe: Strobe,
        initialized: bool,
    }

    impl<S: Size> Default for StrobeHasher<S> {
        fn default() -> Self {
            Self {
                _marker: PhantomData,
                strobe: Strobe::new(b"StrobeHash", SecParam::B128),
                initialized: false,
            }
        }
    }

    impl<S: Size> StatefulHasher for StrobeHasher<S> {
        type Size = S;
        type Digest = StrobeDigest<Self::Size>;

        fn update(&mut self, input: &[u8]) {
            self.strobe.ad(input, self.initialized);
            self.initialized = true;
        }

        fn finalize(&self) -> Self::Digest {
            let mut hash = GenericArray::default();
            self.strobe.clone().prf(&mut hash, false);
            Self::Digest::from(hash)
        }

        fn reset(&mut self) {
            let Self { strobe, .. } = Self::default();
            self.strobe = strobe;
            self.initialized = false;
        }
    }

    /// 256 bit strobe hasher.
    pub type Strobe256 = StrobeHasher<U32>;

    /// 512 bit strobe hasher.
    pub type Strobe512 = StrobeHasher<U64>;
}
<|endoftext|>


<commit_before>use std::fmt;

use eval::BinOp;

pub struct Module {
	pub imports: ~[UseDef],
	pub lets: ~[LetDef],
	pub defs: ~[Def],
}

pub struct Block {
	pub lets: ~[LetDef],
	pub actions: ~[Action],
}

pub struct Def {
	pub name: ~str,
	pub params: ~[ParamDef],
	pub block: Block,
}

pub enum ActionTarget {
	ActionDef(Expr),
	ActionEntity(Expr, ~str)
}

pub struct Action {
	pub action: ActionTarget,
	pub positional: ~[Expr],
	pub body: Option<ActionBody>,
}

pub struct ActionBody {
	pub param_names: ~[~str],
	pub block: Block,
}

pub struct UseDef(~str);
pub struct ParamDef {
	pub name: ~str,
	pub tp: TypeExpr,
	pub default: Option<Expr>
}

pub struct LetDef(~str, Expr);

#[deriving(Eq, Clone)]
pub enum TypeExpr {
	SymbolType, // TODO: include variants?
	IntegerType, // TODO: range
	BitsType(uint),
	VectorType(uint), //TODO: element type
	NumberType,
	EntityType,
	InvalidType,
	TopType
}

#[deriving(Clone, Eq)]
pub enum Value {
	NumberValue(f64),
	IntegerValue(i64),
	SymbolValue(~str),
	VectorValue(~[Value]),
}

impl Value {
	pub fn get_type(&self) -> TypeExpr {
		match *self {
			NumberValue(..) => NumberType,
			IntegerValue(..) => IntegerType,
			SymbolValue(..) => SymbolType,
			VectorValue(ref n) => VectorType(n.len()),
		}
	}

	pub fn matches(&self, other: &Value) -> bool {
		*self == *other
	}
}

impl fmt::Show for Value {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			NumberValue(n) => write!(f.buf, "{}", n),
			IntegerValue(n) => write!(f.buf, "{}", n),
			SymbolValue(ref s) => write!(f.buf, "${}", *s),
			VectorValue(ref n) => write!(f.buf, "[{}]", n.to_str()),
		}
	}
}

pub enum Expr {
	ValueExpr(Value),
	IgnoreExpr,

	FlipExpr(~Expr, ~Expr),
	RangeExpr(~Expr, ~Expr),
	ChooseExpr(~Expr, ~[(Expr, Expr)]),
	ConcatExpr(~[Expr]),

	BinExpr(~Expr, BinOp, ~Expr),

	VarExpr(~str),
	DotExpr(~Expr, ~str),
}
<commit_msg>rust: tuple structs also private by default<commit_after>use std::fmt;

use eval::BinOp;

pub struct Module {
	pub imports: ~[UseDef],
	pub lets: ~[LetDef],
	pub defs: ~[Def],
}

pub struct Block {
	pub lets: ~[LetDef],
	pub actions: ~[Action],
}

pub struct Def {
	pub name: ~str,
	pub params: ~[ParamDef],
	pub block: Block,
}

pub enum ActionTarget {
	ActionDef(Expr),
	ActionEntity(Expr, ~str)
}

pub struct Action {
	pub action: ActionTarget,
	pub positional: ~[Expr],
	pub body: Option<ActionBody>,
}

pub struct ActionBody {
	pub param_names: ~[~str],
	pub block: Block,
}

pub struct UseDef(pub ~str);
pub struct ParamDef {
	pub name: ~str,
	pub tp: TypeExpr,
	pub default: Option<Expr>
}

pub struct LetDef(pub ~str, pub Expr);

#[deriving(Eq, Clone)]
pub enum TypeExpr {
	SymbolType, // TODO: include variants?
	IntegerType, // TODO: range
	BitsType(uint),
	VectorType(uint), //TODO: element type
	NumberType,
	EntityType,
	InvalidType,
	TopType
}

#[deriving(Clone, Eq)]
pub enum Value {
	NumberValue(f64),
	IntegerValue(i64),
	SymbolValue(~str),
	VectorValue(~[Value]),
}

impl Value {
	pub fn get_type(&self) -> TypeExpr {
		match *self {
			NumberValue(..) => NumberType,
			IntegerValue(..) => IntegerType,
			SymbolValue(..) => SymbolType,
			VectorValue(ref n) => VectorType(n.len()),
		}
	}

	pub fn matches(&self, other: &Value) -> bool {
		*self == *other
	}
}

impl fmt::Show for Value {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match *self {
			NumberValue(n) => write!(f.buf, "{}", n),
			IntegerValue(n) => write!(f.buf, "{}", n),
			SymbolValue(ref s) => write!(f.buf, "${}", *s),
			VectorValue(ref n) => write!(f.buf, "[{}]", n.to_str()),
		}
	}
}

pub enum Expr {
	ValueExpr(Value),
	IgnoreExpr,

	FlipExpr(~Expr, ~Expr),
	RangeExpr(~Expr, ~Expr),
	ChooseExpr(~Expr, ~[(Expr, Expr)]),
	ConcatExpr(~[Expr]),

	BinExpr(~Expr, BinOp, ~Expr),

	VarExpr(~str),
	DotExpr(~Expr, ~str),
}
<|endoftext|>


<commit_before>use acyclic_network::{Network, NodeType, NodeIndex};
use weight::{Weight, WeightRange, WeightPerturbanceMethod};
use prob::Prob;
use rand::Rng;

/// Genome representing a feed-forward (acyclic) network with node type `NT`.
#[derive(Clone, Debug)]
pub struct Genome<NT: NodeType> {
    /// Represents the acyclic feed forward network, with `NT` as node type and `Weight` for the edge weights.
    /// Other than that, nodes and edges do not have any further associated information (`()`).
    network: Network<NT, Weight, ()>,
}

impl<NT: NodeType> Genome<NT> {
    pub fn new() -> Self {
        Genome { network: Network::new() }
    }

    /// Returns a reference to the feed forward network.

    pub fn network(&self) -> &Network<NT, Weight, ()> {
        &self.network
    }

    /// Connects two previously unconnected nodes by adding a link between `source_node` and `target_node` using `weight`.
    ///
    /// Does not check for cycles. Test for cycles before using this method!
    ///
    /// # Panics
    ///
    /// If one of `source_node` or `target_node` does not exist.
    ///
    /// If a connection between these nodes already exists!
    ///
    /// # Complexity
    ///
    /// O(1) because we use `add_link_unorderd`.

    pub fn add_link(&mut self, source_node: NodeIndex, target_node: NodeIndex, weight: Weight) {
        debug_assert!(!self.network.link_would_cycle(source_node, target_node));
        debug_assert!(self.network.valid_link(source_node, target_node).is_ok());

        let _link_index = self.network.add_link_unordered(source_node, target_node, weight, ());
    }

    pub fn add_node(&mut self, node_type: NT) -> NodeIndex {
        self.network.add_node(node_type, ())
    }

    pub fn node_count(&self) -> usize {
        self.network.node_count()
    }

    fn random_node<R>(&self,
                      protected_nodes: usize,
                      tournament_k: usize,
                      rng: &mut R)
                      -> Option<NodeIndex>
        where R: Rng
    {
        assert!(tournament_k > 0);

        let n = self.network.node_count();
        if protected_nodes >= n {
            return None;
        }

        let mut min_node = NodeIndex::new(rng.gen_range(protected_nodes, n));
        let mut min_degree = self.network.node(min_node).degree();
        for _ in 1..tournament_k {
            let node_idx = NodeIndex::new(rng.gen_range(protected_nodes, n));
            let degree = self.network.node(node_idx).degree();
            if degree < min_degree {
                min_node = node_idx;
                min_degree = degree;
            }
        }

        Some(min_node)
    }

    /// Structural Mutation `AddNode`.
    ///
    /// Choose a random link and split it into two by inserting a new node in the middle.
    ///
    /// Note that the new `node_type` should allow incoming and outgoing links! Otherwise
    /// this panics!

    pub fn mutate_add_node<R>(&mut self,
                              node_type: NT,
                              second_link_weight: Option<Weight>,
                              rng: &mut R)
                              -> bool
        where R: Rng
    {
        let link_index = match self.network.random_link_index(rng) {
            Some(idx) => idx,
            None => return false,
        };

        let (orig_source_node, orig_target_node, orig_weight) = {
            let link = self.network.link(link_index);
            (link.source_node_index(),
             link.target_node_index(),
             link.weight())
        };

        // remove original link
        self.network.remove_link_at(link_index);

        // Add new "middle" node
        let middle_node = self.network.add_node(node_type, ());

        // Add two new links connecting the three nodes. This cannot add a cycle!
        //
        // The first link reuses the same weight as the original link.
        // The second link uses `second_link_weight` as weight (or if `None`, `orig_weight`).
        // Ideally this is of full strength as we want to make the modification
        // to the network (CPPN) as little as possible.

        self.add_link(orig_source_node, middle_node, orig_weight);
        self.add_link(middle_node,
                      orig_target_node,
                      second_link_weight.unwrap_or(orig_weight));

        return true;
    }

    /// Structural Mutation `DropNode`.
    ///
    /// Choose a random node and remove it. All in and outgoing links to and from that node
    /// are removed as well. Note that the first `protected_nodes` are not removed!
    ///
    /// We choose `tournament_k` random nodes and remove the one with the smallest degree.

    pub fn mutate_drop_node<R>(&mut self,
                               protected_nodes: usize,
                               tournament_k: usize,
                               rng: &mut R)
                               -> bool
        where R: Rng
    {
        match self.random_node(protected_nodes, tournament_k, rng) {
            None => false,
            Some(node_idx) => {
                self.network.remove_node(node_idx);
                true
            }
        }
    }

    /// Structural Mutation `ModifyNode`.
    ///
    /// Choose a random node and change it's type to `new_node_type`.
    ///
    /// We choose from `tournament_k` nodes the one with the smallest degree.

    pub fn mutate_modify_node<R>(&mut self,
                                 new_node_type: NT,
                                 protected_nodes: usize,
                                 tournament_k: usize,
                                 rng: &mut R)
                                 -> bool
        where R: Rng
    {
        match self.random_node(protected_nodes, tournament_k, rng) {
            None => false,
            Some(node_idx) => {
                self.network.node_mut(node_idx).set_node_type(new_node_type);
                true
            }
        }
    }

    /// Structural Mutation `Connect`.
    ///
    /// Mutate the genome by adding a random valid link which does not introduce a cycle.
    ///
    /// Return `true` if the genome was modified. Otherwise `false`.

    pub fn mutate_connect<R>(&mut self, link_weight: Weight, rng: &mut R) -> bool
        where R: Rng
    {
        match self.network.find_random_unconnected_link_no_cycle(rng) {
            Some((source_node, target_node)) => {
                // Add new link to the genome
                self.add_link(source_node, target_node, link_weight);
                return true;
            }
            None => {
                return false;
            }
        }
    }

    /// Structural Mutation `Disconnect`.
    ///
    /// Mutate the genome by removing a random link.
    ///
    /// Return `true` if the genome was modified. Otherwise `false`.

    pub fn mutate_disconnect<R>(&mut self, rng: &mut R) -> bool
        where R: Rng
    {
        match self.network.random_link_index(rng) {
            Some(idx) => {
                self.network.remove_link_at(idx);
                true
            }
            None => false,
        }
    }

    /// Uniformly modify the weight of links, each with a probability of `mutate_element_prob`. It
    /// the genome contains at least one link, it is guaranteed that this method makes a modification.
    ///
    /// Returns the number of modifications (if negative, indicates that we used a random link).

    pub fn mutate_weights<R>(&mut self,
                             mutate_element_prob: Prob,
                             weight_perturbance: &WeightPerturbanceMethod,
                             link_weight_range: &WeightRange,
                             rng: &mut R)
                             -> isize
        where R: Rng
    {
        let mut modifications = 0;

        self.network.each_link_mut(|link| {
            if mutate_element_prob.flip(rng) {
                let new_weight = weight_perturbance.perturb(link.weight(), link_weight_range, rng);
                link.set_weight(new_weight);
                modifications += 1;
            }
        });

        if modifications == 0 {
            // Make at least one change to a randomly selected link.
            if let Some(link_idx) = self.network.random_link_index(rng) {
                let link = self.network.link_mut(link_idx);
                let new_weight = weight_perturbance.perturb(link.weight(), link_weight_range, rng);
                link.set_weight(new_weight);
                modifications -= 1;
            }
        }

        return modifications;
    }
}
<commit_msg>Store protected_nodes inside the Genome<commit_after>use acyclic_network::{Network, NodeType, NodeIndex};
use weight::{Weight, WeightRange, WeightPerturbanceMethod};
use prob::Prob;
use rand::Rng;

/// Genome representing a feed-forward (acyclic) network with node type `NT`.
#[derive(Clone, Debug)]
pub struct Genome<NT: NodeType> {
    /// Represents the acyclic feed forward network, with `NT` as node type and `Weight` for the edge weights.
    /// Other than that, nodes and edges do not have any further associated information (`()`).
    network: Network<NT, Weight, ()>,

    /// The genome can contain some nodes which cannot be modified or removed. These are the first
    /// `protected_nodes` in `network`.
    protected_nodes: usize,
}

impl<NT: NodeType> Genome<NT> {
    pub fn new() -> Self {
        Genome { network: Network::new(), protected_nodes: 0 }
    }

    pub fn protect_node(&mut self) {
        self.protected_nodes = self.network.node_count();
    }

    /// Returns a reference to the feed forward network.

    pub fn network(&self) -> &Network<NT, Weight, ()> {
        &self.network
    }

    /// Connects two previously unconnected nodes by adding a link between `source_node` and `target_node` using `weight`.
    ///
    /// Does not check for cycles. Test for cycles before using this method!
    ///
    /// # Panics
    ///
    /// If one of `source_node` or `target_node` does not exist.
    ///
    /// If a connection between these nodes already exists!
    ///
    /// # Complexity
    ///
    /// O(1) because we use `add_link_unorderd`.

    pub fn add_link(&mut self, source_node: NodeIndex, target_node: NodeIndex, weight: Weight) {
        debug_assert!(!self.network.link_would_cycle(source_node, target_node));
        debug_assert!(self.network.valid_link(source_node, target_node).is_ok());

        let _link_index = self.network.add_link_unordered(source_node, target_node, weight, ());
    }

    pub fn add_node(&mut self, node_type: NT) -> NodeIndex {
        self.network.add_node(node_type, ())
    }

    pub fn node_count(&self) -> usize {
        self.network.node_count()
    }

    fn random_node<R>(&self,
                      tournament_k: usize,
                      rng: &mut R)
                      -> Option<NodeIndex>
        where R: Rng
    {
        assert!(tournament_k > 0);

        let n = self.network.node_count();
        if self.protected_nodes >= n {
            return None;
        }

        let mut min_node = NodeIndex::new(rng.gen_range(self.protected_nodes, n));
        let mut min_degree = self.network.node(min_node).degree();
        for _ in 1..tournament_k {
            let node_idx = NodeIndex::new(rng.gen_range(self.protected_nodes, n));
            let degree = self.network.node(node_idx).degree();
            if degree < min_degree {
                min_node = node_idx;
                min_degree = degree;
            }
        }

        Some(min_node)
    }

    /// Structural Mutation `AddNode`.
    ///
    /// Choose a random link and split it into two by inserting a new node in the middle.
    ///
    /// Note that the new `node_type` should allow incoming and outgoing links! Otherwise
    /// this panics!

    pub fn mutate_add_node<R>(&mut self,
                              node_type: NT,
                              second_link_weight: Option<Weight>,
                              rng: &mut R)
                              -> bool
        where R: Rng
    {
        let link_index = match self.network.random_link_index(rng) {
            Some(idx) => idx,
            None => return false,
        };

        let (orig_source_node, orig_target_node, orig_weight) = {
            let link = self.network.link(link_index);
            (link.source_node_index(),
             link.target_node_index(),
             link.weight())
        };

        // remove original link
        self.network.remove_link_at(link_index);

        // Add new "middle" node
        let middle_node = self.network.add_node(node_type, ());

        // Add two new links connecting the three nodes. This cannot add a cycle!
        //
        // The first link reuses the same weight as the original link.
        // The second link uses `second_link_weight` as weight (or if `None`, `orig_weight`).
        // Ideally this is of full strength as we want to make the modification
        // to the network (CPPN) as little as possible.

        self.add_link(orig_source_node, middle_node, orig_weight);
        self.add_link(middle_node,
                      orig_target_node,
                      second_link_weight.unwrap_or(orig_weight));

        return true;
    }

    /// Structural Mutation `DropNode`.
    ///
    /// Choose a random node and remove it. All in and outgoing links to and from that node
    /// are removed as well. Note that the first `protected_nodes` cannot be removed!
    ///
    /// We choose `tournament_k` random nodes and remove the one with the smallest degree.

    pub fn mutate_drop_node<R>(&mut self,
                               tournament_k: usize,
                               rng: &mut R)
                               -> bool
        where R: Rng
    {
        match self.random_node(tournament_k, rng) {
            None => false,
            Some(node_idx) => {
                self.network.remove_node(node_idx);
                true
            }
        }
    }

    /// Structural Mutation `ModifyNode`.
    ///
    /// Choose a random node and change it's type to `new_node_type`.
    /// Note that protected nodes are not modified.
    ///
    /// We choose from `tournament_k` nodes the one with the smallest degree.

    pub fn mutate_modify_node<R>(&mut self,
                                 new_node_type: NT,
                                 tournament_k: usize,
                                 rng: &mut R)
                                 -> bool
        where R: Rng
    {
        match self.random_node(tournament_k, rng) {
            None => false,
            Some(node_idx) => {
                self.network.node_mut(node_idx).set_node_type(new_node_type);
                true
            }
        }
    }

    /// Structural Mutation `Connect`.
    ///
    /// Mutate the genome by adding a random valid link which does not introduce a cycle.
    ///
    /// Return `true` if the genome was modified. Otherwise `false`.

    pub fn mutate_connect<R>(&mut self, link_weight: Weight, rng: &mut R) -> bool
        where R: Rng
    {
        match self.network.find_random_unconnected_link_no_cycle(rng) {
            Some((source_node, target_node)) => {
                // Add new link to the genome
                self.add_link(source_node, target_node, link_weight);
                return true;
            }
            None => {
                return false;
            }
        }
    }

    /// Structural Mutation `Disconnect`.
    ///
    /// Mutate the genome by removing a random link.
    ///
    /// Return `true` if the genome was modified. Otherwise `false`.

    pub fn mutate_disconnect<R>(&mut self, rng: &mut R) -> bool
        where R: Rng
    {
        match self.network.random_link_index(rng) {
            Some(idx) => {
                self.network.remove_link_at(idx);
                true
            }
            None => false,
        }
    }

    /// Uniformly modify the weight of links, each with a probability of `mutate_element_prob`. It
    /// the genome contains at least one link, it is guaranteed that this method makes a modification.
    ///
    /// Returns the number of modifications (if negative, indicates that we used a random link).

    pub fn mutate_weights<R>(&mut self,
                             mutate_element_prob: Prob,
                             weight_perturbance: &WeightPerturbanceMethod,
                             link_weight_range: &WeightRange,
                             rng: &mut R)
                             -> isize
        where R: Rng
    {
        let mut modifications = 0;

        self.network.each_link_mut(|link| {
            if mutate_element_prob.flip(rng) {
                let new_weight = weight_perturbance.perturb(link.weight(), link_weight_range, rng);
                link.set_weight(new_weight);
                modifications += 1;
            }
        });

        if modifications == 0 {
            // Make at least one change to a randomly selected link.
            if let Some(link_idx) = self.network.random_link_index(rng) {
                let link = self.network.link_mut(link_idx);
                let new_weight = weight_perturbance.perturb(link.weight(), link_weight_range, rng);
                link.set_weight(new_weight);
                modifications -= 1;
            }
        }

        return modifications;
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::ty::subst::Substs;
use rustc::ty::{self, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};

/// Replaces all free regions appearing in the MIR with fresh
/// inference variables, returning the number of variables created.
pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, '_, 'tcx>, mir: &mut Mir<'tcx>) {
    debug!("renumber_mir()");
    debug!("renumber_mir: mir.arg_count={:?}", mir.arg_count);

    let mut visitor = NLLVisitor { infcx };
    visitor.visit_mir(mir);
}

/// Replaces all regions appearing in `value` with fresh inference
/// variables.
pub fn renumber_regions<'tcx, T>(
    infcx: &InferCtxt<'_, '_, 'tcx>,
    ty_context: TyContext,
    value: &T,
) -> T
where
    T: TypeFoldable<'tcx>,
{
    debug!("renumber_regions(value={:?})", value);

    infcx
        .tcx
        .fold_regions(value, &mut false, |_region, _depth| {
            let origin = NLLRegionVariableOrigin::Inferred(ty_context);
            infcx.next_nll_region_var(origin)
        })
}

struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
}

impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
    fn renumber_regions<T>(&mut self, ty_context: TyContext, value: &T) -> T
    where
        T: TypeFoldable<'tcx>,
    {
        renumber_regions(self.infcx, ty_context, value)
    }
}

impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
        debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context);

        *ty = self.renumber_regions(ty_context, ty);

        debug!("visit_ty: ty={:?}", ty);
    }

    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
        debug!("visit_substs(substs={:?}, location={:?})", substs, location);

        let ty_context = TyContext::Location(location);
        *substs = self.renumber_regions(ty_context, &{ *substs });

        debug!("visit_substs: substs={:?}", substs);
    }

    fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) {
        debug!("visit_region(region={:?}, location={:?})", region, location);

        let old_region = *region;
        let ty_context = TyContext::Location(location);
        *region = self.renumber_regions(ty_context, &old_region);

        debug!("visit_region: region={:?}", region);
    }

    fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, location: Location) {
        let ty_context = TyContext::Location(location);
        *constant = self.renumber_regions(ty_context, &*constant);
    }

    fn visit_generator_interior(&mut self,
                                interior: &mut GeneratorInterior<'tcx>,
                                location: Location) {
        debug!(
            "visit_generator_interior(interior={:?}, location={:?})",
            interior,
            location,
        );

        let ty_context = TyContext::Location(location);
        *interior = self.renumber_regions(ty_context, interior);

        debug!("visit_generator_interior: interior={:?}", interior);
    }

    fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
        debug!(
            "visit_closure_substs(substs={:?}, location={:?})",
            substs,
            location
        );

        let ty_context = TyContext::Location(location);
        *substs = self.renumber_regions(ty_context, substs);

        debug!("visit_closure_substs: substs={:?}", substs);
    }

    fn visit_user_assert_ty(&mut self, _ty: &mut Ty<'tcx>, _local: &mut Local,
                            _location: Location) {
        debug!("visit_user_assert_ty: skipping renumber");
    }

    fn visit_statement(
        &mut self,
        block: BasicBlock,
        statement: &mut Statement<'tcx>,
        location: Location,
    ) {
        if let StatementKind::EndRegion(_) = statement.kind {
            statement.kind = StatementKind::Nop;
        }
        self.super_statement(block, statement, location);
    }
}
<commit_msg>Added comment in renumberer about UserAssertTy.<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use rustc::ty::subst::Substs;
use rustc::ty::{self, ClosureSubsts, GeneratorInterior, Ty, TypeFoldable};
use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, StatementKind};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};

/// Replaces all free regions appearing in the MIR with fresh
/// inference variables, returning the number of variables created.
pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, '_, 'tcx>, mir: &mut Mir<'tcx>) {
    debug!("renumber_mir()");
    debug!("renumber_mir: mir.arg_count={:?}", mir.arg_count);

    let mut visitor = NLLVisitor { infcx };
    visitor.visit_mir(mir);
}

/// Replaces all regions appearing in `value` with fresh inference
/// variables.
pub fn renumber_regions<'tcx, T>(
    infcx: &InferCtxt<'_, '_, 'tcx>,
    ty_context: TyContext,
    value: &T,
) -> T
where
    T: TypeFoldable<'tcx>,
{
    debug!("renumber_regions(value={:?})", value);

    infcx
        .tcx
        .fold_regions(value, &mut false, |_region, _depth| {
            let origin = NLLRegionVariableOrigin::Inferred(ty_context);
            infcx.next_nll_region_var(origin)
        })
}

struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
}

impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
    fn renumber_regions<T>(&mut self, ty_context: TyContext, value: &T) -> T
    where
        T: TypeFoldable<'tcx>,
    {
        renumber_regions(self.infcx, ty_context, value)
    }
}

impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
    fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
        debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context);

        *ty = self.renumber_regions(ty_context, ty);

        debug!("visit_ty: ty={:?}", ty);
    }

    fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
        debug!("visit_substs(substs={:?}, location={:?})", substs, location);

        let ty_context = TyContext::Location(location);
        *substs = self.renumber_regions(ty_context, &{ *substs });

        debug!("visit_substs: substs={:?}", substs);
    }

    fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) {
        debug!("visit_region(region={:?}, location={:?})", region, location);

        let old_region = *region;
        let ty_context = TyContext::Location(location);
        *region = self.renumber_regions(ty_context, &old_region);

        debug!("visit_region: region={:?}", region);
    }

    fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, location: Location) {
        let ty_context = TyContext::Location(location);
        *constant = self.renumber_regions(ty_context, &*constant);
    }

    fn visit_generator_interior(&mut self,
                                interior: &mut GeneratorInterior<'tcx>,
                                location: Location) {
        debug!(
            "visit_generator_interior(interior={:?}, location={:?})",
            interior,
            location,
        );

        let ty_context = TyContext::Location(location);
        *interior = self.renumber_regions(ty_context, interior);

        debug!("visit_generator_interior: interior={:?}", interior);
    }

    fn visit_closure_substs(&mut self, substs: &mut ClosureSubsts<'tcx>, location: Location) {
        debug!(
            "visit_closure_substs(substs={:?}, location={:?})",
            substs,
            location
        );

        let ty_context = TyContext::Location(location);
        *substs = self.renumber_regions(ty_context, substs);

        debug!("visit_closure_substs: substs={:?}", substs);
    }

    fn visit_user_assert_ty(&mut self, _ty: &mut Ty<'tcx>, _local: &mut Local,
                            _location: Location) {
        // User-assert-ty statements represent types that the user added explicitly.
        // We don't want to erase the regions from these types: rather, we want to
        // add them as constraints at type-check time.
        debug!("visit_user_assert_ty: skipping renumber");
    }

    fn visit_statement(
        &mut self,
        block: BasicBlock,
        statement: &mut Statement<'tcx>,
        location: Location,
    ) {
        if let StatementKind::EndRegion(_) = statement.kind {
            statement.kind = StatementKind::Nop;
        }
        self.super_statement(block, statement, location);
    }
}
<|endoftext|>


<commit_before>use serde::de::Error;
use serde::{self, Deserialize, Serialize};
use std::fmt::Debug;
use std::mem;
use std::ops::Deref;

/// An object that can be incrementally updated with events.
pub trait Incremental: Sized {
    /// Incoming event type.
    type Event;

    /// Try to update the object with an event.
    fn update(self, e: &Self::Event) -> Self;
}

/// An incremental object that can fail when updated.
///
/// Use the `Incremental` implementation on a `Result` type with `FailingIncremental` value to use
/// this.
pub trait FailingIncremental: Sized {
    /// Incoming event type.
    type Event;
    /// Error in case an event couldn't be handled.
    type Error: Debug;

    /// Try to update the object with an event.
    fn update(self, e: &Self::Event) -> Result<Self, Self::Error>;
}

impl<T: FailingIncremental> Incremental for Result<T, T::Error> {
    type Event = T::Event;

    fn update(self, e: &Self::Event) -> Self {
        match self {
            Ok(state) => state.update(e),
            err => err,
        }
    }
}

/// Handle that stores an `Incremental` object and the event sequence used to build it.
///
/// Serializes itself by only storing the log.
pub struct IncrementalState<T: Incremental + Default> {
    log: Vec<T::Event>,
    state: T,
}

// Implemented manually instead of derived so that T::Event doesn't need to implement Default.
impl<T: Incremental + Default> Default for IncrementalState<T> {
    fn default() -> Self {
        IncrementalState {
            log: Vec::new(),
            state: Default::default(),
        }
    }
}

impl<T: Incremental + Default> IncrementalState<T> {
    pub fn push(&mut self, e: T::Event) {
        // XXX: Need to get state away from borrow checker for updating, is there a better way than
        // ugly unsafe tricks?
        let state = mem::replace(&mut self.state, unsafe { mem::uninitialized() }).update(&e);
        self.state = state;
        self.log.push(e);
    }

    pub fn pop(&mut self) -> Option<T::Event> {
        // TODO: Way to pop several items without O(n) delay for each.
        let ret = self.log.pop();
        self.replay();
        ret
    }

    fn replay(&mut self) {
        let mut state: T = Default::default();

        for e in &self.log {
            state = state.update(e);
        }

        self.state = state;
    }
}

impl<T: Incremental + Default> Deref for IncrementalState<T> {
    type Target = T;

    fn deref(&self) -> &T { &self.state }
}

impl<T: Incremental<Event = impl Serialize> + Default> Serialize for IncrementalState<T> {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.log.serialize(s)
    }
}

impl<'a, T: Incremental<Event = impl Deserialize<'a>> + Default> Deserialize<'a>
    for IncrementalState<T>
{
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        let mut ret: Self = IncrementalState {
            log: Vec::deserialize(d)?,
            state: Default::default(),
        };
        ret.replay();
        Ok(ret)
    }
}
<commit_msg>Incremental event as parameter<commit_after>use serde::{self, Deserialize, Serialize};
use std::fmt::Debug;
use std::mem;
use std::ops::Deref;

/// An object that can be incrementally updated with events.
pub trait Incremental<E>: Sized {
    /// Try to update the object with an event.
    fn update(self, e: &E) -> Self;
}

/// An incremental object that can fail when updated.
///
/// Use the `Incremental` implementation on a `Result` type with `FailingIncremental` value to use
/// this.
pub trait FailingIncremental<E>: Sized {
    /// Error in case an event couldn't be handled.
    type Error: Debug;

    /// Try to update the object with an event.
    fn update(self, e: &E) -> Result<Self, Self::Error>;
}

impl<T: FailingIncremental<E>, E> Incremental<E> for Result<T, T::Error> {
    fn update(self, e: &E) -> Self {
        match self {
            Ok(state) => state.update(e),
            err => err,
        }
    }
}

/// Handle that stores an `Incremental` object and the event sequence used to build it.
///
/// Serializes itself by only storing the log.
pub struct IncrementalState<T: Incremental<E> + Default, E> {
    log: Vec<E>,
    state: T,
}

// Implemented manually instead of derived so that T::Event doesn't need to implement Default.
impl<T: Incremental<E> + Default, E> Default for IncrementalState<T, E> {
    fn default() -> Self {
        IncrementalState {
            log: Vec::new(),
            state: Default::default(),
        }
    }
}

impl<T: Incremental<E> + Default, E> IncrementalState<T, E> {
    pub fn push(&mut self, e: E) {
        // XXX: Need to get state away from borrow checker for updating, is there a better way than
        // ugly unsafe tricks?
        let state = mem::replace(&mut self.state, unsafe { mem::uninitialized() }).update(&e);
        self.state = state;
        self.log.push(e);
    }

    pub fn pop(&mut self) -> Option<E> {
        // TODO: Way to pop several items without O(n) delay for each.
        let ret = self.log.pop();
        self.replay();
        ret
    }

    fn replay(&mut self) {
        let mut state: T = Default::default();

        for e in &self.log {
            state = state.update(e);
        }

        self.state = state;
    }
}

impl<T: Incremental<E> + Default, E> Deref for IncrementalState<T, E> {
    type Target = T;

    fn deref(&self) -> &T { &self.state }
}

impl<T: Incremental<E> + Default, E: Serialize> Serialize for IncrementalState<T, E> {
    fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
        self.log.serialize(s)
    }
}

impl<'a, T: Incremental<E> + Default, E: Deserialize<'a>> Deserialize<'a>
    for IncrementalState<T, E>
{
    fn deserialize<D: serde::Deserializer<'a>>(d: D) -> Result<Self, D::Error> {
        let mut ret: Self = IncrementalState {
            log: Vec::deserialize(d)?,
            state: Default::default(),
        };
        ret.replay();
        Ok(ret)
    }
}
<|endoftext|>


<commit_before>use getopts::{getopts};
use help;

fn verify_command(command: &str) -> bool {
    match command {
        "new"  => true,
        "open" => true,
        _      => false
    }
}

fn run_command(command: &str) {
    println!("{}", command);
}

pub fn init(args: Vec<String>) {
    let program = args[0].clone();
    let opts = help::opts();

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_string()) }
    };

    if matches.opt_present("h") {
        help::print_usage(program.as_slice(), opts);
        return;
    }

    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        help::print_usage(program.as_slice(), opts);
        return;
    };

    if !verify_command(input.as_slice()) {
      return;
    }

    run_command(input.as_slice());
}
<commit_msg>Add testing for verify_command.<commit_after>use getopts::{getopts};
use help;

fn verify_command(command: &str) -> bool {
    match command {
        "new"  => true,
        "open" => true,
        _      => false
    }
}

fn run_command(command: &str) {
    println!("{}", command);
}

pub fn init(args: Vec<String>) {
    let program = args[0].clone();
    let opts = help::opts();

    let matches = match getopts(args.tail(), opts) {
        Ok(m) => { m }
        Err(f) => { fail!(f.to_string()) }
    };

    if matches.opt_present("h") {
        help::print_usage(program.as_slice(), opts);
        return;
    }

    let input = if !matches.free.is_empty() {
        matches.free[0].clone()
    } else {
        help::print_usage(program.as_slice(), opts);
        return;
    };

    if !verify_command(input.as_slice()) {
      return;
    }

    run_command(input.as_slice());
}

#[test]
fn verify_command_new_returns_true() {
  assert_eq!(verify_command("new"), true);
}

#[test]
fn verify_command_open_returns_true() {
  assert_eq!(verify_command("open"), true);
}

#[test]
fn verify_command_value_returns_false() {
  assert_eq!(verify_command("value"), false);
}

<|endoftext|>


<commit_before>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers

// Copyright (c) 2012-2014 The Rust Project Developers
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// - Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in
//   the documentation and/or other materials provided with the
//   distribution.
//
// - Neither the name of "The Computer Language Benchmarks Game" nor
//   the name of "The Computer Language Shootout Benchmarks" nor the
//   names of its contributors may be used to endorse or promote
//   products derived from this software without specific prior
//   written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#![feature(macro_rules)]
#![feature(simd)]
#![allow(experimental)]

// ignore-pretty very bad with line comments

use std::io;
use std::os;
use std::simd::f64x2;
use std::sync::{Arc, Future};

static ITER: int = 50;
static LIMIT: f64 = 2.0;
static WORKERS: uint = 16;

#[inline(always)]
fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
    assert!(WORKERS % 2 == 0);

    // Ensure w and h are multiples of 8.
    let w = (w + 7) / 8 * 8;
    let h = w;

    let chunk_size = h / WORKERS;

    // Account for remainders in workload division, e.g. 1000 / 16 = 62.5
    let first_chunk_size = if h % WORKERS != 0 {
        chunk_size + h % WORKERS
    } else {
        chunk_size
    };

    // precalc values
    let inverse_w_doubled = 2.0 / w as f64;
    let inverse_h_doubled = 2.0 / h as f64;
    let v_inverses = f64x2(inverse_w_doubled, inverse_h_doubled);
    let v_consts = f64x2(1.5, 1.0);

    // A lot of this code assumes this (so do other lang benchmarks)
    assert!(w == h);
    let mut precalc_r = Vec::with_capacity(w);
    let mut precalc_i = Vec::with_capacity(h);

    let precalc_futures = Vec::from_fn(WORKERS, |i| {
        Future::spawn(proc () {
            let mut rs = Vec::with_capacity(w / WORKERS);
            let mut is = Vec::with_capacity(w / WORKERS);

            let start = i * chunk_size;
            let end = if i == 0 {
                first_chunk_size
            } else {
                (i + 1) * chunk_size
            };

            // This assumes w == h
            for x in range(start, end) {
                let xf = x as f64;
                let xy = f64x2(xf, xf);

                let f64x2(r, i) = xy * v_inverses - v_consts;
                rs.push(r);
                is.push(i);
            }

            (rs, is)
        })
    });

    for res in precalc_futures.move_iter() {
        let (rs, is) = res.unwrap();
        precalc_r.push_all_move(rs);
        precalc_i.push_all_move(is);
    }

    assert_eq!(precalc_r.len(), w);
    assert_eq!(precalc_i.len(), h);

    let arc_init_r = Arc::new(precalc_r);
    let arc_init_i = Arc::new(precalc_i);

    let data = Vec::from_fn(WORKERS, |i| {
        let vec_init_r = arc_init_r.clone();
        let vec_init_i = arc_init_i.clone();

        Future::spawn(proc () {
            let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
            let init_r_slice = vec_init_r.as_slice();
            for &init_i in vec_init_i.slice(i * chunk_size, (i + 1) * chunk_size).iter() {
                write_line(init_i, init_r_slice, &mut res);
            }

            res
        })
    });

    try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
    for res in data.move_iter() {
        try!(out.write(res.unwrap().as_slice()));
    }
    out.flush()
}

fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
    let v_init_i : f64x2 = f64x2(init_i, init_i);
    let v_2 : f64x2 = f64x2(2.0, 2.0);
    static LIMIT_SQUARED: f64 = LIMIT * LIMIT;

    for chunk_init_r in vec_init_r.chunks(8) {
        let mut cur_byte = 0xff;
        let mut i = 0;

        while i < 8 {
            let v_init_r = f64x2(chunk_init_r[i], chunk_init_r[i + 1]);
            let mut cur_r = v_init_r;
            let mut cur_i = v_init_i;
            let mut r_sq = v_init_r * v_init_r;
            let mut i_sq = v_init_i * v_init_i;

            let mut b = 0;
            for _ in range(0, ITER) {
                let r = cur_r;
                let i = cur_i;

                cur_i = v_2 * r * i + v_init_i;
                cur_r = r_sq - i_sq + v_init_r;

                let f64x2(bit1, bit2) = r_sq + i_sq;

                if bit1 > LIMIT_SQUARED {
                    b |= 2;
                    if b == 3 { break; }
                }

                if bit2 > LIMIT_SQUARED {
                    b |= 1;
                    if b == 3 { break; }
                }

                r_sq = cur_r * cur_r;
                i_sq = cur_i * cur_i;
            }

            cur_byte = (cur_byte << 2) + b;
            i += 2;
        }

        res.push(cur_byte^-1);
    }
}

fn main() {
    let args = os::args();
    let args = args.as_slice();
    let res = if args.len() < 2 {
        println!("Test mode: do not dump the image because it's not utf8, \
                  which interferes with the test runner.");
        mandelbrot(1000, io::util::NullWriter)
    } else {
        mandelbrot(from_str(args[1].as_slice()).unwrap(), io::stdout())
    };
    res.unwrap();
}
<commit_msg>auto merge of #15743 : Ryman/rust/mandelbrot_fix, r=alexcrichton<commit_after>// The Computer Language Benchmarks Game
// http://benchmarksgame.alioth.debian.org/
//
// contributed by the Rust Project Developers

// Copyright (c) 2012-2014 The Rust Project Developers
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// - Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// - Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in
//   the documentation and/or other materials provided with the
//   distribution.
//
// - Neither the name of "The Computer Language Benchmarks Game" nor
//   the name of "The Computer Language Shootout Benchmarks" nor the
//   names of its contributors may be used to endorse or promote
//   products derived from this software without specific prior
//   written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.

#![feature(macro_rules)]
#![feature(simd)]
#![allow(experimental)]

// ignore-pretty very bad with line comments

use std::io;
use std::os;
use std::simd::f64x2;
use std::sync::{Arc, Future};

static ITER: int = 50;
static LIMIT: f64 = 2.0;
static WORKERS: uint = 16;

#[inline(always)]
fn mandelbrot<W: io::Writer>(w: uint, mut out: W) -> io::IoResult<()> {
    assert!(WORKERS % 2 == 0);

    // Ensure w and h are multiples of 8.
    let w = (w + 7) / 8 * 8;
    let h = w;

    let chunk_size = h / WORKERS;

    // Account for remainders in workload division, e.g. 1000 / 16 = 62.5
    let last_chunk_size = if h % WORKERS != 0 {
        chunk_size + h % WORKERS
    } else {
        chunk_size
    };

    // precalc values
    let inverse_w_doubled = 2.0 / w as f64;
    let inverse_h_doubled = 2.0 / h as f64;
    let v_inverses = f64x2(inverse_w_doubled, inverse_h_doubled);
    let v_consts = f64x2(1.5, 1.0);

    // A lot of this code assumes this (so do other lang benchmarks)
    assert!(w == h);
    let mut precalc_r = Vec::with_capacity(w);
    let mut precalc_i = Vec::with_capacity(h);

    let precalc_futures = Vec::from_fn(WORKERS, |i| {
        Future::spawn(proc () {
            let mut rs = Vec::with_capacity(w / WORKERS);
            let mut is = Vec::with_capacity(w / WORKERS);

            let start = i * chunk_size;
            let end = if i == (WORKERS - 1) {
                start + last_chunk_size
            } else {
                (i + 1) * chunk_size
            };

            // This assumes w == h
            for x in range(start, end) {
                let xf = x as f64;
                let xy = f64x2(xf, xf);

                let f64x2(r, i) = xy * v_inverses - v_consts;
                rs.push(r);
                is.push(i);
            }

            (rs, is)
        })
    });

    for res in precalc_futures.move_iter() {
        let (rs, is) = res.unwrap();
        precalc_r.push_all_move(rs);
        precalc_i.push_all_move(is);
    }

    assert_eq!(precalc_r.len(), w);
    assert_eq!(precalc_i.len(), h);

    let arc_init_r = Arc::new(precalc_r);
    let arc_init_i = Arc::new(precalc_i);

    let data = Vec::from_fn(WORKERS, |i| {
        let vec_init_r = arc_init_r.clone();
        let vec_init_i = arc_init_i.clone();

        Future::spawn(proc () {
            let mut res: Vec<u8> = Vec::with_capacity((chunk_size * w) / 8);
            let init_r_slice = vec_init_r.as_slice();
            for &init_i in vec_init_i.slice(i * chunk_size, (i + 1) * chunk_size).iter() {
                write_line(init_i, init_r_slice, &mut res);
            }

            res
        })
    });

    try!(writeln!(&mut out as &mut Writer, "P4\n{} {}", w, h));
    for res in data.move_iter() {
        try!(out.write(res.unwrap().as_slice()));
    }
    out.flush()
}

fn write_line(init_i: f64, vec_init_r: &[f64], res: &mut Vec<u8>) {
    let v_init_i : f64x2 = f64x2(init_i, init_i);
    let v_2 : f64x2 = f64x2(2.0, 2.0);
    static LIMIT_SQUARED: f64 = LIMIT * LIMIT;

    for chunk_init_r in vec_init_r.chunks(8) {
        let mut cur_byte = 0xff;
        let mut i = 0;

        while i < 8 {
            let v_init_r = f64x2(chunk_init_r[i], chunk_init_r[i + 1]);
            let mut cur_r = v_init_r;
            let mut cur_i = v_init_i;
            let mut r_sq = v_init_r * v_init_r;
            let mut i_sq = v_init_i * v_init_i;

            let mut b = 0;
            for _ in range(0, ITER) {
                let r = cur_r;
                let i = cur_i;

                cur_i = v_2 * r * i + v_init_i;
                cur_r = r_sq - i_sq + v_init_r;

                let f64x2(bit1, bit2) = r_sq + i_sq;

                if bit1 > LIMIT_SQUARED {
                    b |= 2;
                    if b == 3 { break; }
                }

                if bit2 > LIMIT_SQUARED {
                    b |= 1;
                    if b == 3 { break; }
                }

                r_sq = cur_r * cur_r;
                i_sq = cur_i * cur_i;
            }

            cur_byte = (cur_byte << 2) + b;
            i += 2;
        }

        res.push(cur_byte^-1);
    }
}

fn main() {
    let args = os::args();
    let args = args.as_slice();
    let res = if args.len() < 2 {
        println!("Test mode: do not dump the image because it's not utf8, \
                  which interferes with the test runner.");
        mandelbrot(1000, io::util::NullWriter)
    } else {
        mandelbrot(from_str(args[1].as_slice()).unwrap(), io::stdout())
    };
    res.unwrap();
}
<|endoftext|>