<commit_before>//! A YAML mapping and its iterator types.

use crate::Value;
use indexmap::IndexMap;
use serde::{Deserialize, Deserializer, Serialize};
use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
use std::ops::{Index, IndexMut};

/// A YAML mapping in which the keys and values are both `serde_yaml::Value`.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Mapping {
    map: IndexMap<Value, Value>,
}

impl Mapping {
    /// Creates an empty YAML map.
    #[inline]
    pub fn new() -> Self {
        Self::default()
    }

    /// Creates an empty YAML map with the given initial capacity.
    #[inline]
    pub fn with_capacity(capacity: usize) -> Self {
        Mapping {
            map: IndexMap::with_capacity(capacity),
        }
    }

    /// Reserves capacity for at least `additional` more elements to be inserted
    /// into the map. The map may reserve more space to avoid frequent
    /// allocations.
    ///
    /// # Panics
    ///
    /// Panics if the new allocation size overflows `usize`.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.map.reserve(additional);
    }

    /// Shrinks the capacity of the map as much as possible. It will drop down
    /// as much as possible while maintaining the internal rules and possibly
    /// leaving some space in accordance with the resize policy.
    #[inline]
    pub fn shrink_to_fit(&mut self) {
        self.map.shrink_to_fit();
    }

    /// Inserts a key-value pair into the map. If the key already existed, the
    /// old value is returned.
    #[inline]
    pub fn insert(&mut self, k: Value, v: Value) -> Option<Value> {
        self.map.insert(k, v)
    }

    /// Checks if the map contains the given key.
    #[inline]
    pub fn contains_key(&self, k: &Value) -> bool {
        self.map.contains_key(k)
    }

    /// Returns the value corresponding to the key in the map.
    #[inline]
    pub fn get(&self, k: &Value) -> Option<&Value> {
        self.map.get(k)
    }

    /// Returns the mutable reference corresponding to the key in the map.
    #[inline]
    pub fn get_mut(&mut self, k: &Value) -> Option<&mut Value> {
        self.map.get_mut(k)
    }

    /// Removes and returns the value corresponding to the key from the map.
    #[inline]
    pub fn remove(&mut self, k: &Value) -> Option<Value> {
        self.map.remove(k)
    }

    /// Returns the maximum number of key-value pairs the map can hold without
    /// reallocating.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.map.capacity()
    }

    /// Returns the number of key-value pairs in the map.
    #[inline]
    pub fn len(&self) -> usize {
        self.map.len()
    }

    /// Returns whether the map is currently empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.map.is_empty()
    }

    /// Clears the map of all key-value pairs.
    #[inline]
    pub fn clear(&mut self) {
        self.map.clear();
    }

    /// Returns a double-ended iterator visiting all key-value pairs in order of
    /// insertion. Iterator element type is `(&'a Value, &'a Value)`.
    #[inline]
    pub fn iter(&self) -> Iter {
        Iter {
            iter: self.map.iter(),
        }
    }

    /// Returns a double-ended iterator visiting all key-value pairs in order of
    /// insertion. Iterator element type is `(&'a Value, &'a mut ValuE)`.
    #[inline]
    pub fn iter_mut(&mut self) -> IterMut {
        IterMut {
            iter: self.map.iter_mut(),
        }
    }
}

impl Hash for Mapping {
    fn hash<H: Hasher>(&self, state: &mut H) {
        // Hash the kv pairs in a way that is not sensitive to their order.
        let mut xor = 0;
        for (k, v) in self {
            let mut hasher = DefaultHasher::new();
            k.hash(&mut hasher);
            v.hash(&mut hasher);
            xor ^= hasher.finish();
        }
        xor.hash(state);
    }
}

impl PartialOrd for Mapping {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        let mut self_entries = Vec::from_iter(self);
        let mut other_entries = Vec::from_iter(other);

        // Sort in an arbitrary order that is consistent with Value's PartialOrd
        // impl.
        fn total_cmp(a: &Value, b: &Value) -> Ordering {
            match (a, b) {
                (Value::Null, Value::Null) => Ordering::Equal,
                (Value::Null, _) => Ordering::Less,
                (_, Value::Null) => Ordering::Greater,

                (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
                (Value::Bool(_), _) => Ordering::Less,
                (_, Value::Bool(_)) => Ordering::Greater,

                (Value::Number(a), Value::Number(b)) => a.total_cmp(b),
                (Value::Number(_), _) => Ordering::Less,
                (_, Value::Number(_)) => Ordering::Greater,

                (Value::String(a), Value::String(b)) => a.cmp(b),
                (Value::String(_), _) => Ordering::Less,
                (_, Value::String(_)) => Ordering::Greater,

                (Value::Sequence(a), Value::Sequence(b)) => iter_cmp_by(a, b, total_cmp),
                (Value::Sequence(_), _) => Ordering::Less,
                (_, Value::Sequence(_)) => Ordering::Greater,

                (Value::Mapping(a), Value::Mapping(b)) => {
                    iter_cmp_by(a, b, |(ak, av), (bk, bv)| {
                        total_cmp(ak, bk).then_with(|| total_cmp(av, bv))
                    })
                }
            }
        }

        fn iter_cmp_by<I, F>(this: I, other: I, mut cmp: F) -> Ordering
        where
            I: IntoIterator,
            F: FnMut(I::Item, I::Item) -> Ordering,
        {
            let mut this = this.into_iter();
            let mut other = other.into_iter();

            loop {
                let x = match this.next() {
                    None => {
                        if other.next().is_none() {
                            return Ordering::Equal;
                        } else {
                            return Ordering::Less;
                        }
                    }
                    Some(val) => val,
                };

                let y = match other.next() {
                    None => return Ordering::Greater,
                    Some(val) => val,
                };

                match cmp(x, y) {
                    Ordering::Equal => {}
                    non_eq => return non_eq,
                }
            }
        }

        // While sorting by map key, we get to assume that no two keys are
        // equal, otherwise they wouldn't both be in the map. This is not a safe
        // assumption outside of this situation.
        let total_cmp = |&(a, _): &_, &(b, _): &_| total_cmp(a, b);
        self_entries.sort_by(total_cmp);
        other_entries.sort_by(total_cmp);
        self_entries.partial_cmp(&other_entries)
    }
}

impl<'a> Index<&'a Value> for Mapping {
    type Output = Value;
    #[inline]
    fn index(&self, index: &'a Value) -> &Value {
        self.map.index(index)
    }
}

impl<'a> IndexMut<&'a Value> for Mapping {
    #[inline]
    fn index_mut(&mut self, index: &'a Value) -> &mut Value {
        self.map.index_mut(index)
    }
}

impl Extend<(Value, Value)> for Mapping {
    #[inline]
    fn extend<I: IntoIterator<Item = (Value, Value)>>(&mut self, iter: I) {
        self.map.extend(iter);
    }
}

impl FromIterator<(Value, Value)> for Mapping {
    #[inline]
    fn from_iter<I: IntoIterator<Item = (Value, Value)>>(iter: I) -> Self {
        Mapping {
            map: IndexMap::from_iter(iter),
        }
    }
}

macro_rules! delegate_iterator {
    (($name:ident $($generics:tt)*) => $item:ty) => {
        impl $($generics)* Iterator for $name $($generics)* {
            type Item = $item;
            #[inline]
            fn next(&mut self) -> Option<Self::Item> {
                self.iter.next()
            }
            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                self.iter.size_hint()
            }
        }

        impl $($generics)* ExactSizeIterator for $name $($generics)* {
            #[inline]
            fn len(&self) -> usize {
                self.iter.len()
            }
        }
    }
}

/// Iterator over `&serde_yaml::Mapping`.
pub struct Iter<'a> {
    iter: indexmap::map::Iter<'a, Value, Value>,
}

delegate_iterator!((Iter<'a>) => (&'a Value, &'a Value));

impl<'a> IntoIterator for &'a Mapping {
    type Item = (&'a Value, &'a Value);
    type IntoIter = Iter<'a>;
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        Iter {
            iter: self.map.iter(),
        }
    }
}

/// Iterator over `&mut serde_yaml::Mapping`.
pub struct IterMut<'a> {
    iter: indexmap::map::IterMut<'a, Value, Value>,
}

delegate_iterator!((IterMut<'a>) => (&'a Value, &'a mut Value));

impl<'a> IntoIterator for &'a mut Mapping {
    type Item = (&'a Value, &'a mut Value);
    type IntoIter = IterMut<'a>;
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        IterMut {
            iter: self.map.iter_mut(),
        }
    }
}

/// Iterator over `serde_yaml::Mapping` by value.
pub struct IntoIter {
    iter: indexmap::map::IntoIter<Value, Value>,
}

delegate_iterator!((IntoIter) => (Value, Value));

impl IntoIterator for Mapping {
    type Item = (Value, Value);
    type IntoIter = IntoIter;
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        IntoIter {
            iter: self.map.into_iter(),
        }
    }
}

impl Serialize for Mapping {
    #[inline]
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        use serde::ser::SerializeMap;
        let mut map_serializer = serializer.serialize_map(Some(self.len()))?;
        for (k, v) in self {
            map_serializer.serialize_entry(k, v)?;
        }
        map_serializer.end()
    }
}

impl<'de> Deserialize<'de> for Mapping {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct Visitor;

        impl<'de> serde::de::Visitor<'de> for Visitor {
            type Value = Mapping;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a YAML mapping")
            }

            #[inline]
            fn visit_unit<E>(self) -> Result<Self::Value, E>
            where
                E: serde::de::Error,
            {
                Ok(Mapping::new())
            }

            #[inline]
            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: serde::de::MapAccess<'de>,
            {
                let mut values = Mapping::new();
                while let Some((k, v)) = visitor.next_entry()? {
                    values.insert(k, v);
                }
                Ok(values)
            }
        }

        deserializer.deserialize_map(Visitor)
    }
}
<commit_msg>Ignore derive_hash_xor_eq Clippy lint<commit_after>//! A YAML mapping and its iterator types.

use crate::Value;
use indexmap::IndexMap;
use serde::{Deserialize, Deserializer, Serialize};
use std::cmp::Ordering;
use std::collections::hash_map::DefaultHasher;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
use std::ops::{Index, IndexMut};

/// A YAML mapping in which the keys and values are both `serde_yaml::Value`.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Mapping {
    map: IndexMap<Value, Value>,
}

impl Mapping {
    /// Creates an empty YAML map.
    #[inline]
    pub fn new() -> Self {
        Self::default()
    }

    /// Creates an empty YAML map with the given initial capacity.
    #[inline]
    pub fn with_capacity(capacity: usize) -> Self {
        Mapping {
            map: IndexMap::with_capacity(capacity),
        }
    }

    /// Reserves capacity for at least `additional` more elements to be inserted
    /// into the map. The map may reserve more space to avoid frequent
    /// allocations.
    ///
    /// # Panics
    ///
    /// Panics if the new allocation size overflows `usize`.
    #[inline]
    pub fn reserve(&mut self, additional: usize) {
        self.map.reserve(additional);
    }

    /// Shrinks the capacity of the map as much as possible. It will drop down
    /// as much as possible while maintaining the internal rules and possibly
    /// leaving some space in accordance with the resize policy.
    #[inline]
    pub fn shrink_to_fit(&mut self) {
        self.map.shrink_to_fit();
    }

    /// Inserts a key-value pair into the map. If the key already existed, the
    /// old value is returned.
    #[inline]
    pub fn insert(&mut self, k: Value, v: Value) -> Option<Value> {
        self.map.insert(k, v)
    }

    /// Checks if the map contains the given key.
    #[inline]
    pub fn contains_key(&self, k: &Value) -> bool {
        self.map.contains_key(k)
    }

    /// Returns the value corresponding to the key in the map.
    #[inline]
    pub fn get(&self, k: &Value) -> Option<&Value> {
        self.map.get(k)
    }

    /// Returns the mutable reference corresponding to the key in the map.
    #[inline]
    pub fn get_mut(&mut self, k: &Value) -> Option<&mut Value> {
        self.map.get_mut(k)
    }

    /// Removes and returns the value corresponding to the key from the map.
    #[inline]
    pub fn remove(&mut self, k: &Value) -> Option<Value> {
        self.map.remove(k)
    }

    /// Returns the maximum number of key-value pairs the map can hold without
    /// reallocating.
    #[inline]
    pub fn capacity(&self) -> usize {
        self.map.capacity()
    }

    /// Returns the number of key-value pairs in the map.
    #[inline]
    pub fn len(&self) -> usize {
        self.map.len()
    }

    /// Returns whether the map is currently empty.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.map.is_empty()
    }

    /// Clears the map of all key-value pairs.
    #[inline]
    pub fn clear(&mut self) {
        self.map.clear();
    }

    /// Returns a double-ended iterator visiting all key-value pairs in order of
    /// insertion. Iterator element type is `(&'a Value, &'a Value)`.
    #[inline]
    pub fn iter(&self) -> Iter {
        Iter {
            iter: self.map.iter(),
        }
    }

    /// Returns a double-ended iterator visiting all key-value pairs in order of
    /// insertion. Iterator element type is `(&'a Value, &'a mut ValuE)`.
    #[inline]
    pub fn iter_mut(&mut self) -> IterMut {
        IterMut {
            iter: self.map.iter_mut(),
        }
    }
}

#[allow(clippy::derive_hash_xor_eq)]
impl Hash for Mapping {
    fn hash<H: Hasher>(&self, state: &mut H) {
        // Hash the kv pairs in a way that is not sensitive to their order.
        let mut xor = 0;
        for (k, v) in self {
            let mut hasher = DefaultHasher::new();
            k.hash(&mut hasher);
            v.hash(&mut hasher);
            xor ^= hasher.finish();
        }
        xor.hash(state);
    }
}

impl PartialOrd for Mapping {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        let mut self_entries = Vec::from_iter(self);
        let mut other_entries = Vec::from_iter(other);

        // Sort in an arbitrary order that is consistent with Value's PartialOrd
        // impl.
        fn total_cmp(a: &Value, b: &Value) -> Ordering {
            match (a, b) {
                (Value::Null, Value::Null) => Ordering::Equal,
                (Value::Null, _) => Ordering::Less,
                (_, Value::Null) => Ordering::Greater,

                (Value::Bool(a), Value::Bool(b)) => a.cmp(b),
                (Value::Bool(_), _) => Ordering::Less,
                (_, Value::Bool(_)) => Ordering::Greater,

                (Value::Number(a), Value::Number(b)) => a.total_cmp(b),
                (Value::Number(_), _) => Ordering::Less,
                (_, Value::Number(_)) => Ordering::Greater,

                (Value::String(a), Value::String(b)) => a.cmp(b),
                (Value::String(_), _) => Ordering::Less,
                (_, Value::String(_)) => Ordering::Greater,

                (Value::Sequence(a), Value::Sequence(b)) => iter_cmp_by(a, b, total_cmp),
                (Value::Sequence(_), _) => Ordering::Less,
                (_, Value::Sequence(_)) => Ordering::Greater,

                (Value::Mapping(a), Value::Mapping(b)) => {
                    iter_cmp_by(a, b, |(ak, av), (bk, bv)| {
                        total_cmp(ak, bk).then_with(|| total_cmp(av, bv))
                    })
                }
            }
        }

        fn iter_cmp_by<I, F>(this: I, other: I, mut cmp: F) -> Ordering
        where
            I: IntoIterator,
            F: FnMut(I::Item, I::Item) -> Ordering,
        {
            let mut this = this.into_iter();
            let mut other = other.into_iter();

            loop {
                let x = match this.next() {
                    None => {
                        if other.next().is_none() {
                            return Ordering::Equal;
                        } else {
                            return Ordering::Less;
                        }
                    }
                    Some(val) => val,
                };

                let y = match other.next() {
                    None => return Ordering::Greater,
                    Some(val) => val,
                };

                match cmp(x, y) {
                    Ordering::Equal => {}
                    non_eq => return non_eq,
                }
            }
        }

        // While sorting by map key, we get to assume that no two keys are
        // equal, otherwise they wouldn't both be in the map. This is not a safe
        // assumption outside of this situation.
        let total_cmp = |&(a, _): &_, &(b, _): &_| total_cmp(a, b);
        self_entries.sort_by(total_cmp);
        other_entries.sort_by(total_cmp);
        self_entries.partial_cmp(&other_entries)
    }
}

impl<'a> Index<&'a Value> for Mapping {
    type Output = Value;
    #[inline]
    fn index(&self, index: &'a Value) -> &Value {
        self.map.index(index)
    }
}

impl<'a> IndexMut<&'a Value> for Mapping {
    #[inline]
    fn index_mut(&mut self, index: &'a Value) -> &mut Value {
        self.map.index_mut(index)
    }
}

impl Extend<(Value, Value)> for Mapping {
    #[inline]
    fn extend<I: IntoIterator<Item = (Value, Value)>>(&mut self, iter: I) {
        self.map.extend(iter);
    }
}

impl FromIterator<(Value, Value)> for Mapping {
    #[inline]
    fn from_iter<I: IntoIterator<Item = (Value, Value)>>(iter: I) -> Self {
        Mapping {
            map: IndexMap::from_iter(iter),
        }
    }
}

macro_rules! delegate_iterator {
    (($name:ident $($generics:tt)*) => $item:ty) => {
        impl $($generics)* Iterator for $name $($generics)* {
            type Item = $item;
            #[inline]
            fn next(&mut self) -> Option<Self::Item> {
                self.iter.next()
            }
            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                self.iter.size_hint()
            }
        }

        impl $($generics)* ExactSizeIterator for $name $($generics)* {
            #[inline]
            fn len(&self) -> usize {
                self.iter.len()
            }
        }
    }
}

/// Iterator over `&serde_yaml::Mapping`.
pub struct Iter<'a> {
    iter: indexmap::map::Iter<'a, Value, Value>,
}

delegate_iterator!((Iter<'a>) => (&'a Value, &'a Value));

impl<'a> IntoIterator for &'a Mapping {
    type Item = (&'a Value, &'a Value);
    type IntoIter = Iter<'a>;
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        Iter {
            iter: self.map.iter(),
        }
    }
}

/// Iterator over `&mut serde_yaml::Mapping`.
pub struct IterMut<'a> {
    iter: indexmap::map::IterMut<'a, Value, Value>,
}

delegate_iterator!((IterMut<'a>) => (&'a Value, &'a mut Value));

impl<'a> IntoIterator for &'a mut Mapping {
    type Item = (&'a Value, &'a mut Value);
    type IntoIter = IterMut<'a>;
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        IterMut {
            iter: self.map.iter_mut(),
        }
    }
}

/// Iterator over `serde_yaml::Mapping` by value.
pub struct IntoIter {
    iter: indexmap::map::IntoIter<Value, Value>,
}

delegate_iterator!((IntoIter) => (Value, Value));

impl IntoIterator for Mapping {
    type Item = (Value, Value);
    type IntoIter = IntoIter;
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        IntoIter {
            iter: self.map.into_iter(),
        }
    }
}

impl Serialize for Mapping {
    #[inline]
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        use serde::ser::SerializeMap;
        let mut map_serializer = serializer.serialize_map(Some(self.len()))?;
        for (k, v) in self {
            map_serializer.serialize_entry(k, v)?;
        }
        map_serializer.end()
    }
}

impl<'de> Deserialize<'de> for Mapping {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct Visitor;

        impl<'de> serde::de::Visitor<'de> for Visitor {
            type Value = Mapping;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("a YAML mapping")
            }

            #[inline]
            fn visit_unit<E>(self) -> Result<Self::Value, E>
            where
                E: serde::de::Error,
            {
                Ok(Mapping::new())
            }

            #[inline]
            fn visit_map<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
            where
                V: serde::de::MapAccess<'de>,
            {
                let mut values = Mapping::new();
                while let Some((k, v)) = visitor.next_entry()? {
                    values.insert(k, v);
                }
                Ok(values)
            }
        }

        deserializer.deserialize_map(Visitor)
    }
}
<|endoftext|>


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

use any_pointer;
use private::capability::ClientHook;
use private::units::*;
use private::arena::{BuilderArena, ReaderArena, SegmentBuilder, SegmentReader, NumWords, ZeroedWords};
use private::layout;
use traits::{FromPointerReader, FromPointerBuilder, SetPointerBuilder};
use Word;

#[derive(Copy)]
pub struct ReaderOptions {
    pub traversal_limit_in_words : u64,
    pub nesting_limit : i32,

    /// If true, malformed messages trigger task failure.
    /// If false, malformed messages fall back to default values.
    pub fail_fast : bool,
}

pub const DEFAULT_READER_OPTIONS : ReaderOptions =
    ReaderOptions { traversal_limit_in_words : 8 * 1024 * 1024, nesting_limit : 64,
                    fail_fast : true };

impl ReaderOptions {
    pub fn new() -> ReaderOptions { DEFAULT_READER_OPTIONS }

    pub fn nesting_limit<'a>(&'a mut self, value : i32) -> &'a mut ReaderOptions {
        self.nesting_limit = value;
        return self;
    }

    pub fn traversal_limit_in_words<'a>(&'a mut self, value : u64) -> &'a mut ReaderOptions {
        self.traversal_limit_in_words = value;
        return self;
    }

    pub fn fail_fast<'a>(&'a mut self, value : bool) -> &'a mut ReaderOptions {
        self.fail_fast = value;
        return self;
    }
}

type SegmentId = u32;

pub trait MessageReader {
    fn get_segment(&self, id : usize) -> &[Word];
    fn arena(&self) -> &ReaderArena;
    fn mut_arena(&mut self) -> &mut ReaderArena;
    fn get_options(&self) -> &ReaderOptions;

    fn get_root_internal(&self) -> any_pointer::Reader {
        unsafe {
            let segment : *const SegmentReader = &self.arena().segment0;

            let pointer_reader = layout::PointerReader::get_root(
                segment, (*segment).get_start_ptr(), self.get_options().nesting_limit);

            any_pointer::Reader::new(pointer_reader)
        }
    }

    fn get_root<'a, T : FromPointerReader<'a>>(&'a self) -> T {
        self.get_root_internal().get_as()
    }

    fn init_cap_table(&mut self, cap_table : Vec<Option<Box<ClientHook+Send>>>) {
        self.mut_arena().init_cap_table(cap_table);
    }
}

pub struct SegmentArrayMessageReader<'a> {
    segments : &'a [ &'a [Word]],
    options : ReaderOptions,
    arena : Box<ReaderArena>
}

impl <'a> MessageReader for SegmentArrayMessageReader<'a> {
    fn get_segment<'b>(&'b self, id : usize) -> &'b [Word] {
        self.segments[id]
    }

    fn arena<'b>(&'b self) -> &'b ReaderArena { &*self.arena }
    fn mut_arena<'b>(&'b mut self) -> &'b mut ReaderArena { &mut *self.arena }

    fn get_options<'b>(&'b self) -> &'b ReaderOptions {
        return &self.options;
    }
}

impl <'a> SegmentArrayMessageReader<'a> {

    pub fn new<'b>(segments : &'b [&'b [Word]], options : ReaderOptions) -> SegmentArrayMessageReader<'b> {
        assert!(segments.len() > 0);
        SegmentArrayMessageReader {
            segments : segments,
            arena : ReaderArena::new(segments, options),
            options : options
        }
    }
}

#[derive(Copy)]
pub enum AllocationStrategy {
    FixedSize,
    GrowHeuristically
}

pub const SUGGESTED_FIRST_SEGMENT_WORDS : u32 = 1024;
pub const SUGGESTED_ALLOCATION_STRATEGY : AllocationStrategy = AllocationStrategy::GrowHeuristically;

#[derive(Copy)]
pub struct BuilderOptions {
    pub first_segment_words : u32,
    pub allocation_strategy : AllocationStrategy,

    /// If true, malformed messages trigger task failure.
    /// If false, malformed messages fall back to default values.
    pub fail_fast : bool,
}

impl BuilderOptions {
    pub fn new() -> BuilderOptions {
        BuilderOptions {first_segment_words : SUGGESTED_FIRST_SEGMENT_WORDS,
                        allocation_strategy : AllocationStrategy::GrowHeuristically,
                        fail_fast : true }
    }

    pub fn first_segment_words<'a>(&'a mut self, value : u32) -> &'a mut BuilderOptions {
        self.first_segment_words = value;
        return self;
    }

    pub fn allocation_strategy<'a>(&'a mut self, value : AllocationStrategy) -> &'a mut BuilderOptions {
        self.allocation_strategy = value;
        return self;
    }

    pub fn fail_fast<'a>(&'a mut self, value : bool) -> &'a mut BuilderOptions {
        self.fail_fast = value;
        return self;
    }
}

pub trait MessageBuilder {
    fn mut_arena(&mut self) -> &mut BuilderArena;
    fn arena(&self) -> &BuilderArena;

    // XXX is there a way to make this private?
    fn get_root_internal<'a>(&mut self) -> any_pointer::Builder<'a> {
        let root_segment = &mut self.mut_arena().segment0 as *mut SegmentBuilder;

        if self.arena().segment0.current_size() == 0 {
            match self.mut_arena().segment0.allocate(WORDS_PER_POINTER as u32) {
                None => {panic!("could not allocate root pointer") }
                Some(location) => {
                    assert!(location == self.arena().segment0.get_ptr_unchecked(0),
                            "First allocated word of new segment was not at offset 0");

                    any_pointer::Builder::new(layout::PointerBuilder::get_root(root_segment, location))

                }
            }
        } else {
            any_pointer::Builder::new(
                layout::PointerBuilder::get_root(root_segment,
                                                 self.arena().segment0.get_ptr_unchecked(0)))
        }

    }

    fn init_root<'a, T : FromPointerBuilder<'a>>(&'a mut self) -> T {
        self.get_root_internal().init_as()
    }

    fn get_root<'a, T : FromPointerBuilder<'a>>(&'a mut self) -> T {
        self.get_root_internal().get_as()
    }

    fn set_root<To, From : SetPointerBuilder<To>>(&mut self, value : From) {
        self.get_root_internal().set_as(value);
    }

    fn get_segments_for_output<'a>(&'a mut self) -> &'a[&'a[Word]] {
        self.mut_arena().get_segments_for_output()
    }

    fn get_cap_table<'a>(&'a self) -> &'a [Option<Box<ClientHook+Send>>] {
        self.arena().get_cap_table()
    }
}

pub struct MallocMessageBuilder {
    arena : Box<BuilderArena>,
}

impl Drop for MallocMessageBuilder {
    fn drop(&mut self) { }
}

unsafe impl Send for MallocMessageBuilder {}

impl MallocMessageBuilder {

    pub fn new(options : BuilderOptions) -> MallocMessageBuilder {
        let arena = BuilderArena::new(options.allocation_strategy,
                                      NumWords(options.first_segment_words),
                                      options.fail_fast);

        MallocMessageBuilder { arena : arena }
    }

    pub fn new_default() -> MallocMessageBuilder {
        MallocMessageBuilder::new(BuilderOptions::new())
    }

}

impl MessageBuilder for MallocMessageBuilder {
    fn mut_arena(&mut self) -> &mut BuilderArena {
        &mut *self.arena
    }
    fn arena(&self) -> &BuilderArena {
        & *self.arena
    }
}

pub struct ScratchSpaceMallocMessageBuilder<'a> {
    arena : Box<BuilderArena>,
    scratch_space : &'a mut [Word],
}

// TODO: figure out why rust thinks this is unsafe.
#[unsafe_destructor]
impl <'a> Drop for ScratchSpaceMallocMessageBuilder<'a> {
    fn drop(&mut self) {
        let ptr = self.scratch_space.as_mut_ptr();
        let segments = self.get_segments_for_output();
        unsafe {
            ::std::ptr::zero_memory(ptr, segments[0].len());
        }
    }
}

impl <'a> ScratchSpaceMallocMessageBuilder<'a> {

    pub fn new<'b>(scratch_space : &'b mut [Word], options : BuilderOptions)
               -> ScratchSpaceMallocMessageBuilder<'b> {
        let arena = BuilderArena::new(options.allocation_strategy, ZeroedWords(scratch_space),
                                      options.fail_fast);

        ScratchSpaceMallocMessageBuilder { arena : arena, scratch_space : scratch_space }
    }

    pub fn new_default<'b>(scratch_space : &'b mut [Word]) -> ScratchSpaceMallocMessageBuilder<'b> {
        ScratchSpaceMallocMessageBuilder::new(scratch_space, BuilderOptions::new())
    }

}

impl <'b> MessageBuilder for ScratchSpaceMallocMessageBuilder<'b> {
    fn mut_arena(&mut self) -> &mut BuilderArena {
        &mut *self.arena
    }
    fn arena(&self) -> &BuilderArena {
        & *self.arena
    }
}
<commit_msg>some documentation<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use any_pointer;
use private::capability::ClientHook;
use private::units::*;
use private::arena::{BuilderArena, ReaderArena, SegmentBuilder, SegmentReader, NumWords, ZeroedWords};
use private::layout;
use traits::{FromPointerReader, FromPointerBuilder, SetPointerBuilder};
use Word;

#[derive(Copy)]
pub struct ReaderOptions {
    pub traversal_limit_in_words : u64,
    pub nesting_limit : i32,

    /// If true, malformed messages trigger task failure.
    /// If false, malformed messages fall back to default values.
    pub fail_fast : bool,
}

pub const DEFAULT_READER_OPTIONS : ReaderOptions =
    ReaderOptions { traversal_limit_in_words : 8 * 1024 * 1024, nesting_limit : 64,
                    fail_fast : true };

impl ReaderOptions {
    pub fn new() -> ReaderOptions { DEFAULT_READER_OPTIONS }

    pub fn nesting_limit<'a>(&'a mut self, value : i32) -> &'a mut ReaderOptions {
        self.nesting_limit = value;
        return self;
    }

    pub fn traversal_limit_in_words<'a>(&'a mut self, value : u64) -> &'a mut ReaderOptions {
        self.traversal_limit_in_words = value;
        return self;
    }

    pub fn fail_fast<'a>(&'a mut self, value : bool) -> &'a mut ReaderOptions {
        self.fail_fast = value;
        return self;
    }
}

type SegmentId = u32;

pub trait MessageReader {
    fn get_segment(&self, id : usize) -> &[Word];
    fn arena(&self) -> &ReaderArena;
    fn mut_arena(&mut self) -> &mut ReaderArena;
    fn get_options(&self) -> &ReaderOptions;

    fn get_root_internal(&self) -> any_pointer::Reader {
        unsafe {
            let segment : *const SegmentReader = &self.arena().segment0;

            let pointer_reader = layout::PointerReader::get_root(
                segment, (*segment).get_start_ptr(), self.get_options().nesting_limit);

            any_pointer::Reader::new(pointer_reader)
        }
    }

    fn get_root<'a, T : FromPointerReader<'a>>(&'a self) -> T {
        self.get_root_internal().get_as()
    }

    fn init_cap_table(&mut self, cap_table : Vec<Option<Box<ClientHook+Send>>>) {
        self.mut_arena().init_cap_table(cap_table);
    }
}

pub struct SegmentArrayMessageReader<'a> {
    segments : &'a [ &'a [Word]],
    options : ReaderOptions,
    arena : Box<ReaderArena>
}

impl <'a> MessageReader for SegmentArrayMessageReader<'a> {
    fn get_segment<'b>(&'b self, id : usize) -> &'b [Word] {
        self.segments[id]
    }

    fn arena<'b>(&'b self) -> &'b ReaderArena { &*self.arena }
    fn mut_arena<'b>(&'b mut self) -> &'b mut ReaderArena { &mut *self.arena }

    fn get_options<'b>(&'b self) -> &'b ReaderOptions {
        return &self.options;
    }
}

impl <'a> SegmentArrayMessageReader<'a> {

    pub fn new<'b>(segments : &'b [&'b [Word]], options : ReaderOptions) -> SegmentArrayMessageReader<'b> {
        assert!(segments.len() > 0);
        SegmentArrayMessageReader {
            segments : segments,
            arena : ReaderArena::new(segments, options),
            options : options
        }
    }
}

#[derive(Copy)]
pub enum AllocationStrategy {
    FixedSize,
    GrowHeuristically
}

pub const SUGGESTED_FIRST_SEGMENT_WORDS : u32 = 1024;
pub const SUGGESTED_ALLOCATION_STRATEGY : AllocationStrategy = AllocationStrategy::GrowHeuristically;

#[derive(Copy)]
pub struct BuilderOptions {
    pub first_segment_words : u32,
    pub allocation_strategy : AllocationStrategy,

    /// If true, malformed messages trigger task failure.
    /// If false, malformed messages fall back to default values.
    pub fail_fast : bool,
}

impl BuilderOptions {
    pub fn new() -> BuilderOptions {
        BuilderOptions {first_segment_words : SUGGESTED_FIRST_SEGMENT_WORDS,
                        allocation_strategy : AllocationStrategy::GrowHeuristically,
                        fail_fast : true }
    }

    pub fn first_segment_words<'a>(&'a mut self, value : u32) -> &'a mut BuilderOptions {
        self.first_segment_words = value;
        return self;
    }

    pub fn allocation_strategy<'a>(&'a mut self, value : AllocationStrategy) -> &'a mut BuilderOptions {
        self.allocation_strategy = value;
        return self;
    }

    pub fn fail_fast<'a>(&'a mut self, value : bool) -> &'a mut BuilderOptions {
        self.fail_fast = value;
        return self;
    }
}

pub trait MessageBuilder {
    fn mut_arena(&mut self) -> &mut BuilderArena;
    fn arena(&self) -> &BuilderArena;

    // XXX is there a way to make this private?
    fn get_root_internal<'a>(&mut self) -> any_pointer::Builder<'a> {
        let root_segment = &mut self.mut_arena().segment0 as *mut SegmentBuilder;

        if self.arena().segment0.current_size() == 0 {
            match self.mut_arena().segment0.allocate(WORDS_PER_POINTER as u32) {
                None => {panic!("could not allocate root pointer") }
                Some(location) => {
                    assert!(location == self.arena().segment0.get_ptr_unchecked(0),
                            "First allocated word of new segment was not at offset 0");

                    any_pointer::Builder::new(layout::PointerBuilder::get_root(root_segment, location))

                }
            }
        } else {
            any_pointer::Builder::new(
                layout::PointerBuilder::get_root(root_segment,
                                                 self.arena().segment0.get_ptr_unchecked(0)))
        }

    }

    fn init_root<'a, T : FromPointerBuilder<'a>>(&'a mut self) -> T {
        self.get_root_internal().init_as()
    }

    fn get_root<'a, T : FromPointerBuilder<'a>>(&'a mut self) -> T {
        self.get_root_internal().get_as()
    }

    fn set_root<To, From : SetPointerBuilder<To>>(&mut self, value : From) {
        self.get_root_internal().set_as(value);
    }

    /// Get the slices of memory that comprise this message. Typically, this method needs to
    /// construct these slices and stash them in some interior field before returning them. It
    /// therefore needs to take a mutable `self` parameter.
    fn get_segments_for_output<'a>(&'a mut self) -> &'a[&'a[Word]] {
        self.mut_arena().get_segments_for_output()
    }

    fn get_cap_table<'a>(&'a self) -> &'a [Option<Box<ClientHook+Send>>] {
        self.arena().get_cap_table()
    }
}

pub struct MallocMessageBuilder {
    arena : Box<BuilderArena>,
}

impl Drop for MallocMessageBuilder {
    fn drop(&mut self) { }
}

unsafe impl Send for MallocMessageBuilder {}

impl MallocMessageBuilder {

    pub fn new(options : BuilderOptions) -> MallocMessageBuilder {
        let arena = BuilderArena::new(options.allocation_strategy,
                                      NumWords(options.first_segment_words),
                                      options.fail_fast);

        MallocMessageBuilder { arena : arena }
    }

    pub fn new_default() -> MallocMessageBuilder {
        MallocMessageBuilder::new(BuilderOptions::new())
    }

}

impl MessageBuilder for MallocMessageBuilder {
    fn mut_arena(&mut self) -> &mut BuilderArena {
        &mut *self.arena
    }
    fn arena(&self) -> &BuilderArena {
        & *self.arena
    }
}

pub struct ScratchSpaceMallocMessageBuilder<'a> {
    arena : Box<BuilderArena>,
    scratch_space : &'a mut [Word],
}

// TODO: figure out why rust thinks this is unsafe.
#[unsafe_destructor]
impl <'a> Drop for ScratchSpaceMallocMessageBuilder<'a> {
    fn drop(&mut self) {
        let ptr = self.scratch_space.as_mut_ptr();
        let segments = self.get_segments_for_output();
        unsafe {
            ::std::ptr::zero_memory(ptr, segments[0].len());
        }
    }
}

impl <'a> ScratchSpaceMallocMessageBuilder<'a> {

    pub fn new<'b>(scratch_space : &'b mut [Word], options : BuilderOptions)
               -> ScratchSpaceMallocMessageBuilder<'b> {
        let arena = BuilderArena::new(options.allocation_strategy, ZeroedWords(scratch_space),
                                      options.fail_fast);

        ScratchSpaceMallocMessageBuilder { arena : arena, scratch_space : scratch_space }
    }

    pub fn new_default<'b>(scratch_space : &'b mut [Word]) -> ScratchSpaceMallocMessageBuilder<'b> {
        ScratchSpaceMallocMessageBuilder::new(scratch_space, BuilderOptions::new())
    }

}

impl <'b> MessageBuilder for ScratchSpaceMallocMessageBuilder<'b> {
    fn mut_arena(&mut self) -> &mut BuilderArena {
        &mut *self.arena
    }
    fn arena(&self) -> &BuilderArena {
        & *self.arena
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::io::File;

use error::{
    Error, ImapResult, InternalIoError, MessageDecodeError
};

#[deriving(Show)]
enum Flag {
    Answered,
    Draft,
    Flagged,
    Seen
}

#[deriving(Show)]
pub struct Message {
    uid: u32,
    pub path: String,
    headers: HashMap<String, String>,
    body: Vec<MIMEPart>,
    flags: Vec<Flag>,
    pub deleted: bool,
    raw_contents: String
}

#[deriving(Show)]
pub struct MIMEPart {
    mime_header: String,
    mime_body: String
}

impl Message {
    pub fn parse(arg_path: &Path) -> ImapResult<Message> {
        // Load the file contents.
        let file = match File::open(arg_path) {
            Ok(mut file) => match file.read_to_end() {
                Ok(contents) => contents,
                Err(e) => return Err(Error::simple(InternalIoError(e), "Failed to read mail file."))
            },
            Err(e) => return Err(Error::simple(InternalIoError(e), "Failed to open mail file."))
        };
        let raw_contents = String::from_utf8_lossy(file.as_slice()).to_string();

        let mut path = arg_path.filename_str().unwrap().splitn(1, ':');
        let filename = path.next().unwrap();
        let path_flags = path.next();

        // Retrieve the UID from the provided filename.
        let uid = match from_str::<u32>(filename) {
            Some(uid) => uid,
            None => return Err(Error::simple(MessageDecodeError, "Failed to retrieve UID from filename."))
        };
        // Parse the flags from the filename.

        let mut flags = match path_flags {
            None => Vec::new(),
            Some(flags) => {
                let unparsed_flags = flags.splitn(1, ',').skip(1).next().unwrap();
                let mut vec_flags: Vec<Flag> = Vec::new();
                for flag in unparsed_flags.chars() {
                    let parsed_flag = match flag {
                        'D' => Some(Draft),
                        'F' => Some(Flagged),
                        'R' => Some(Answered),
                        'S' => Some(Seen),
                        _ => None
                    };
                    match parsed_flag {
                        Some(enum_flag) => vec_flags.push(enum_flag),
                        None => { }
                    }
                }
                vec_flags
            }
        };

        let header_boundary = raw_contents.as_slice().find_str("\n\n").unwrap();
        let raw_header = raw_contents.as_slice().slice_to(header_boundary);
        let raw_body = raw_contents.as_slice().slice_from(header_boundary + 2);

        // Iterate over the lines of the header in reverse.
        // If a line with leading whitespace is detected, it is merged to the line before it.
        // This "unwraps" the header as indicated in RFC 2822 2.2.3
        let mut parsed_header: Vec<String> = Vec::new();
        let mut iterator = raw_header.lines().rev();
        loop {
            let line = match iterator.next() {
                Some(line) => line,
                None => break
            };
            let mut field = line.to_string();
            if line.as_slice().starts_with(" ") || line.as_slice().starts_with("\t") {
                field = field.as_slice().trim_left_chars(' ').trim_left_chars('\t').to_string();
                loop {
                    let next = iterator.next().unwrap().to_string();
                    let mut trimmed_next = next.as_slice().trim_left_chars(' ').trim_left_chars('\t').to_string();
                    // Add a space between the merged lines.
                    trimmed_next.push_str(" ".as_slice());
                    trimmed_next.push_str(field.as_slice());
                    field = trimmed_next;
                    if !next.as_slice().starts_with(" ") && !next.as_slice().starts_with("\t") {
                        break;
                    }
                }
            }

            parsed_header.push(field.to_string());
        }
        let parsed_header: Vec<&String> = parsed_header.iter().rev().collect();

        let mut headers = HashMap::new();
        for line in parsed_header.iter() {
            let split: Vec<&str> = line.as_slice().splitn(1, ':').collect();
            headers.insert(split[0].clone().to_string(), split[1].slice_from(1).clone().to_string());
        }
        // Remove the "Received" key from the HashMap.
        headers.remove(&"Received".to_string());

        // Determine whether the message is MULTIPART or not.
        let content_type = headers["Content-Type".to_string()].clone();
        let mut body = Vec::new();
        if content_type.as_slice().contains("MULTIPART") {
            let mime_boundary = {
                let value: Vec<&str> = content_type.as_slice().split_str("BOUNDARY=\"").collect();
                if value.len() < 2 { return Err(Error::simple(MessageDecodeError, "Failed to determine MULTIPART boundary.")) }
                let value: Vec<&str> = value[1].splitn(1, '"').collect();
                if value.len() < 1 { return Err(Error::simple(MessageDecodeError, "Failed to determine MULTIPART boundary.")) }
                format!("--{}--\n", value[0])
            };

            let first_content_type_index = match raw_body.find_str("Content-Type") {
                Some(val) => val,
                None => return Err(Error::simple(MessageDecodeError, "Missing Content-Type for body part"))
            };
            let raw_body = raw_body.slice_from(first_content_type_index);
            let raw_body: Vec<&str> = raw_body.split_str(mime_boundary.as_slice()).collect();
            let raw_body = raw_body.slice_to(raw_body.len() - 1);

            for part in raw_body.iter() {
                let header_boundary = part.as_slice().find_str("\n\n").unwrap();
                let header = part.as_slice().slice_to(header_boundary);
                let mut content_type = String::new();
                for line in header.lines() {
                    let split_line: Vec<&str> = line.splitn(1, ':').collect();
                    if split_line[0] == "Content-Type" {
                        let content_type_values: Vec<&str> = split_line[1].splitn(1, ';').collect();
                        content_type = content_type_values[0].slice_from(1).to_string();
                        break;
                    }
                }
                let body_part = MIMEPart {
                    mime_header: content_type.to_string(),
                    mime_body: raw_body.to_string()
                };
                body.push(body_part);
            }
        } else {
            let body_part = MIMEPart {
                mime_header: content_type.to_string(),
                mime_body: raw_body.to_string()
            };
            body.push(body_part);
        }

        let message = Message {
            uid: uid,
            path: arg_path.display().to_string(),
            headers: headers,
            body: body,
            flags: flags,
            deleted: false,
            raw_contents: raw_contents.clone()
        };

        Ok(message)
    }

    // TODO: Make sure that returning a pointer is fine.
    pub fn date_received(&self) -> &String {
        self.headers.find(&"Received-On-Date".to_string()).unwrap()
    }

    // TODO: Make sure that returning a pointer is fine.
    pub fn envelope_from(&self) -> &String {
        self.headers.find(&"From".to_string()).unwrap()
    }

    // TODO: Make sure that returning a pointer is fine.
    pub fn envelope_to(&self) -> &String {
        self.headers.find(&"To".to_string()).unwrap()
    }
}
<commit_msg>Remove unnecessary mut<commit_after>use std::collections::HashMap;
use std::io::File;

use error::{
    Error, ImapResult, InternalIoError, MessageDecodeError
};

#[deriving(Show)]
enum Flag {
    Answered,
    Draft,
    Flagged,
    Seen
}

#[deriving(Show)]
pub struct Message {
    uid: u32,
    pub path: String,
    headers: HashMap<String, String>,
    body: Vec<MIMEPart>,
    flags: Vec<Flag>,
    pub deleted: bool,
    raw_contents: String
}

#[deriving(Show)]
pub struct MIMEPart {
    mime_header: String,
    mime_body: String
}

impl Message {
    pub fn parse(arg_path: &Path) -> ImapResult<Message> {
        // Load the file contents.
        let file = match File::open(arg_path) {
            Ok(mut file) => match file.read_to_end() {
                Ok(contents) => contents,
                Err(e) => return Err(Error::simple(InternalIoError(e), "Failed to read mail file."))
            },
            Err(e) => return Err(Error::simple(InternalIoError(e), "Failed to open mail file."))
        };
        let raw_contents = String::from_utf8_lossy(file.as_slice()).to_string();

        let mut path = arg_path.filename_str().unwrap().splitn(1, ':');
        let filename = path.next().unwrap();
        let path_flags = path.next();

        // Retrieve the UID from the provided filename.
        let uid = match from_str::<u32>(filename) {
            Some(uid) => uid,
            None => return Err(Error::simple(MessageDecodeError, "Failed to retrieve UID from filename."))
        };
        // Parse the flags from the filename.
        let flags = match path_flags {
            None => Vec::new(),
            Some(flags) => {
                let unparsed_flags = flags.splitn(1, ',').skip(1).next().unwrap();
                let mut vec_flags: Vec<Flag> = Vec::new();
                for flag in unparsed_flags.chars() {
                    let parsed_flag = match flag {
                        'D' => Some(Draft),
                        'F' => Some(Flagged),
                        'R' => Some(Answered),
                        'S' => Some(Seen),
                        _ => None
                    };
                    match parsed_flag {
                        Some(enum_flag) => vec_flags.push(enum_flag),
                        None => { }
                    }
                }
                vec_flags
            }
        };

        let header_boundary = raw_contents.as_slice().find_str("\n\n").unwrap();
        let raw_header = raw_contents.as_slice().slice_to(header_boundary);
        let raw_body = raw_contents.as_slice().slice_from(header_boundary + 2);

        // Iterate over the lines of the header in reverse.
        // If a line with leading whitespace is detected, it is merged to the line before it.
        // This "unwraps" the header as indicated in RFC 2822 2.2.3
        let mut parsed_header: Vec<String> = Vec::new();
        let mut iterator = raw_header.lines().rev();
        loop {
            let line = match iterator.next() {
                Some(line) => line,
                None => break
            };
            let mut field = line.to_string();
            if line.as_slice().starts_with(" ") || line.as_slice().starts_with("\t") {
                field = field.as_slice().trim_left_chars(' ').trim_left_chars('\t').to_string();
                loop {
                    let next = iterator.next().unwrap().to_string();
                    let mut trimmed_next = next.as_slice().trim_left_chars(' ').trim_left_chars('\t').to_string();
                    // Add a space between the merged lines.
                    trimmed_next.push_str(" ".as_slice());
                    trimmed_next.push_str(field.as_slice());
                    field = trimmed_next;
                    if !next.as_slice().starts_with(" ") && !next.as_slice().starts_with("\t") {
                        break;
                    }
                }
            }

            parsed_header.push(field.to_string());
        }
        let parsed_header: Vec<&String> = parsed_header.iter().rev().collect();

        let mut headers = HashMap::new();
        for line in parsed_header.iter() {
            let split: Vec<&str> = line.as_slice().splitn(1, ':').collect();
            headers.insert(split[0].clone().to_string(), split[1].slice_from(1).clone().to_string());
        }
        // Remove the "Received" key from the HashMap.
        headers.remove(&"Received".to_string());

        // Determine whether the message is MULTIPART or not.
        let content_type = headers["Content-Type".to_string()].clone();
        let mut body = Vec::new();
        if content_type.as_slice().contains("MULTIPART") {
            let mime_boundary = {
                let value: Vec<&str> = content_type.as_slice().split_str("BOUNDARY=\"").collect();
                if value.len() < 2 { return Err(Error::simple(MessageDecodeError, "Failed to determine MULTIPART boundary.")) }
                let value: Vec<&str> = value[1].splitn(1, '"').collect();
                if value.len() < 1 { return Err(Error::simple(MessageDecodeError, "Failed to determine MULTIPART boundary.")) }
                format!("--{}--\n", value[0])
            };

            let first_content_type_index = match raw_body.find_str("Content-Type") {
                Some(val) => val,
                None => return Err(Error::simple(MessageDecodeError, "Missing Content-Type for body part"))
            };
            let raw_body = raw_body.slice_from(first_content_type_index);
            let raw_body: Vec<&str> = raw_body.split_str(mime_boundary.as_slice()).collect();
            let raw_body = raw_body.slice_to(raw_body.len() - 1);

            for part in raw_body.iter() {
                let header_boundary = part.as_slice().find_str("\n\n").unwrap();
                let header = part.as_slice().slice_to(header_boundary);
                let mut content_type = String::new();
                for line in header.lines() {
                    let split_line: Vec<&str> = line.splitn(1, ':').collect();
                    if split_line[0] == "Content-Type" {
                        let content_type_values: Vec<&str> = split_line[1].splitn(1, ';').collect();
                        content_type = content_type_values[0].slice_from(1).to_string();
                        break;
                    }
                }
                let body_part = MIMEPart {
                    mime_header: content_type.to_string(),
                    mime_body: raw_body.to_string()
                };
                body.push(body_part);
            }
        } else {
            let body_part = MIMEPart {
                mime_header: content_type.to_string(),
                mime_body: raw_body.to_string()
            };
            body.push(body_part);
        }

        let message = Message {
            uid: uid,
            path: arg_path.display().to_string(),
            headers: headers,
            body: body,
            flags: flags,
            deleted: false,
            raw_contents: raw_contents.clone()
        };

        Ok(message)
    }

    // TODO: Make sure that returning a pointer is fine.
    pub fn date_received(&self) -> &String {
        self.headers.find(&"Received-On-Date".to_string()).unwrap()
    }

    // TODO: Make sure that returning a pointer is fine.
    pub fn envelope_from(&self) -> &String {
        self.headers.find(&"From".to_string()).unwrap()
    }

    // TODO: Make sure that returning a pointer is fine.
    pub fn envelope_to(&self) -> &String {
        self.headers.find(&"To".to_string()).unwrap()
    }
}
<|endoftext|>


<commit_before>use rustc_front::hir::*;
use rustc::lint::*;
use rustc::middle::ty;
use rustc::middle::subst::Subst;
use std::iter;
use std::borrow::Cow;

use utils::{snippet, span_lint, match_path, match_type, walk_ptrs_ty_depth};
use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH};

use self::SelfKind::*;
use self::OutType::*;

#[derive(Copy,Clone)]
pub struct MethodsPass;

declare_lint!(pub OPTION_UNWRAP_USED, Allow,
              "using `Option.unwrap()`, which should at least get a better message using `expect()`");
declare_lint!(pub RESULT_UNWRAP_USED, Allow,
              "using `Result.unwrap()`, which might be better handled");
declare_lint!(pub STR_TO_STRING, Warn,
              "using `to_string()` on a str, which should be `to_owned()`");
declare_lint!(pub STRING_TO_STRING, Warn,
              "calling `String.to_string()` which is a no-op");
declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn,
              "defining a method that should be implementing a std trait");
declare_lint!(pub WRONG_SELF_CONVENTION, Warn,
              "defining a method named with an established prefix (like \"into_\") that takes \
               `self` with the wrong convention");
declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow,
              "defining a public method named with an established prefix (like \"into_\") that takes \
               `self` with the wrong convention");

impl LintPass for MethodsPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING,
                    SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION)
    }
}

impl LateLintPass for MethodsPass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if let ExprMethodCall(ref ident, _, ref args) = expr.node {
            let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0]));
            if ident.node.name == "unwrap" {
                if match_type(cx, obj_ty, &OPTION_PATH) {
                    span_lint(cx, OPTION_UNWRAP_USED, expr.span,
                              "used unwrap() on an Option value. If you don't want \
                               to handle the None case gracefully, consider using \
                               expect() to provide a better panic message");
                } else if match_type(cx, obj_ty, &RESULT_PATH) {
                    span_lint(cx, RESULT_UNWRAP_USED, expr.span,
                              "used unwrap() on a Result value. Graceful handling \
                               of Err values is preferred");
                }
            }
            else if ident.node.name == "to_string" {
                if obj_ty.sty == ty::TyStr {
                    let mut arg_str = snippet(cx, args[0].span, "_");
                    if ptr_depth > 1 {
                        arg_str = Cow::Owned(format!(
                            "({}{})",
                            iter::repeat('*').take(ptr_depth - 1).collect::<String>(),
                            arg_str));
                    }
                    span_lint(cx, STR_TO_STRING, expr.span, &format!(
                        "`{}.to_owned()` is faster", arg_str));
                } else if match_type(cx, obj_ty, &STRING_PATH) {
                    span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op; use \
                                                                `clone()` to make a copy");
                }
            }
        }
    }

    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        if let ItemImpl(_, _, _, None, ref ty, ref items) = item.node {
            for implitem in items {
                let name = implitem.ident.name;
                if let MethodImplItem(ref sig, _) = implitem.node {
                    // check missing trait implementations
                    for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS {
                        if_let_chain! {
                            [
                                name == method_name,
                                sig.decl.inputs.len() == n_args,
                                out_type.matches(&sig.decl.output),
                                self_kind.matches(&sig.explicit_self.node, false)
                            ], {
                                span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!(
                                    "defining a method called `{}` on this type; consider implementing \
                                     the `{}` trait or choosing a less ambiguous name", name, trait_name));
                            }
                        }
                    }
                    // check conventions w.r.t. conversion method names and predicates
                    let is_copy = is_copy(cx, &ty, &item);
                    for &(prefix, self_kinds) in &CONVENTIONS {
                        if name.as_str().starts_with(prefix) &&
                                !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) {
                            let lint = if item.vis == Visibility::Public {
                                WRONG_PUB_SELF_CONVENTION
                            } else {
                                WRONG_SELF_CONVENTION
                            };
                            span_lint(cx, lint, sig.explicit_self.span, &format!(
                                "methods called `{}*` usually take {}; consider choosing a less \
                                 ambiguous name", prefix,
                                &self_kinds.iter().map(|k| k.description()).collect::<Vec<_>>().join(" or ")));
                        }
                    }
                }
            }
        }
    }
}

const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [
    ("into_", &[ValueSelf]),
    ("to_",   &[RefSelf]),
    ("as_",   &[RefSelf, RefMutSelf]),
    ("is_",   &[RefSelf, NoSelf]),
    ("from_", &[NoSelf]),
];

const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [
    ("add",        2, ValueSelf,  AnyType,  "std::ops::Add`"),
    ("sub",        2, ValueSelf,  AnyType,  "std::ops::Sub"),
    ("mul",        2, ValueSelf,  AnyType,  "std::ops::Mul"),
    ("div",        2, ValueSelf,  AnyType,  "std::ops::Div"),
    ("rem",        2, ValueSelf,  AnyType,  "std::ops::Rem"),
    ("shl",        2, ValueSelf,  AnyType,  "std::ops::Shl"),
    ("shr",        2, ValueSelf,  AnyType,  "std::ops::Shr"),
    ("bitand",     2, ValueSelf,  AnyType,  "std::ops::BitAnd"),
    ("bitor",      2, ValueSelf,  AnyType,  "std::ops::BitOr"),
    ("bitxor",     2, ValueSelf,  AnyType,  "std::ops::BitXor"),
    ("neg",        1, ValueSelf,  AnyType,  "std::ops::Neg"),
    ("not",        1, ValueSelf,  AnyType,  "std::ops::Not"),
    ("drop",       1, RefMutSelf, UnitType, "std::ops::Drop"),
    ("index",      2, RefSelf,    RefType,  "std::ops::Index"),
    ("index_mut",  2, RefMutSelf, RefType,  "std::ops::IndexMut"),
    ("deref",      1, RefSelf,    RefType,  "std::ops::Deref"),
    ("deref_mut",  1, RefMutSelf, RefType,  "std::ops::DerefMut"),
    ("clone",      1, RefSelf,    AnyType,  "std::clone::Clone"),
    ("borrow",     1, RefSelf,    RefType,  "std::borrow::Borrow"),
    ("borrow_mut", 1, RefMutSelf, RefType,  "std::borrow::BorrowMut"),
    ("as_ref",     1, RefSelf,    RefType,  "std::convert::AsRef"),
    ("as_mut",     1, RefMutSelf, RefType,  "std::convert::AsMut"),
    ("eq",         2, RefSelf,    BoolType, "std::cmp::PartialEq"),
    ("cmp",        2, RefSelf,    AnyType,  "std::cmp::Ord"),
    ("default",    0, NoSelf,     AnyType,  "std::default::Default"),
    ("hash",       2, RefSelf,    UnitType, "std::hash::Hash"),
    ("next",       1, RefMutSelf, AnyType,  "std::iter::Iterator"),
    ("into_iter",  1, ValueSelf,  AnyType,  "std::iter::IntoIterator"),
    ("from_iter",  1, NoSelf,     AnyType,  "std::iter::FromIterator"),
    ("from_str",   1, NoSelf,     AnyType,  "std::str::FromStr"),
];

#[derive(Clone, Copy)]
enum SelfKind {
    ValueSelf,
    RefSelf,
    RefMutSelf,
    NoSelf,
}

impl SelfKind {
    fn matches(&self, slf: &ExplicitSelf_, allow_value_for_ref: bool) -> bool {
        match (self, slf) {
            (&ValueSelf, &SelfValue(_)) => true,
            (&RefSelf, &SelfRegion(_, Mutability::MutImmutable, _)) => true,
            (&RefMutSelf, &SelfRegion(_, Mutability::MutMutable, _)) => true,
            (&RefSelf, &SelfValue(_)) => allow_value_for_ref,
            (&RefMutSelf, &SelfValue(_)) => allow_value_for_ref,
            (&NoSelf, &SelfStatic) => true,
            (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref),
            _ => false
        }
    }

    fn matches_explicit_type(&self, ty: &Ty, allow_value_for_ref: bool) -> bool {
        match (self, &ty.node) {
            (&ValueSelf, &TyPath(..)) => true,
            (&RefSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) => true,
            (&RefMutSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true,
            (&RefSelf, &TyPath(..)) => allow_value_for_ref,
            (&RefMutSelf, &TyPath(..)) => allow_value_for_ref,
            _ => false
        }
    }

    fn description(&self) -> &'static str {
        match *self {
            ValueSelf => "self by value",
            RefSelf => "self by reference",
            RefMutSelf => "self by mutable reference",
            NoSelf => "no self",
        }
    }
}

#[derive(Clone, Copy)]
enum OutType {
    UnitType,
    BoolType,
    AnyType,
    RefType,
}

impl OutType {
    fn matches(&self, ty: &FunctionRetTy) -> bool {
        match (self, ty) {
            (&UnitType, &DefaultReturn(_)) => true,
            (&UnitType, &Return(ref ty)) if ty.node == TyTup(vec![]) => true,
            (&BoolType, &Return(ref ty)) if is_bool(ty) => true,
            (&AnyType, &Return(ref ty)) if ty.node != TyTup(vec![])  => true,
            (&RefType, &Return(ref ty)) => {
                if let TyRptr(_, _) = ty.node { true } else { false }
            }
            _ => false
        }
    }
}

fn is_bool(ty: &Ty) -> bool {
    if let TyPath(None, ref p) = ty.node {
        if match_path(p, &["bool"]) {
            return true;
        }
    }
    false
}

fn is_copy(cx: &LateContext, ast_ty: &Ty, item: &Item) -> bool {
    match cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) {
        None => false,
        Some(ty) => {
            let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id);
            !ty.subst(cx.tcx, &env.free_substs).moves_by_default(&env, ast_ty.span)
        }
    }
}
<commit_msg>Fix stray backquote.<commit_after>use rustc_front::hir::*;
use rustc::lint::*;
use rustc::middle::ty;
use rustc::middle::subst::Subst;
use std::iter;
use std::borrow::Cow;

use utils::{snippet, span_lint, match_path, match_type, walk_ptrs_ty_depth};
use utils::{OPTION_PATH, RESULT_PATH, STRING_PATH};

use self::SelfKind::*;
use self::OutType::*;

#[derive(Copy,Clone)]
pub struct MethodsPass;

declare_lint!(pub OPTION_UNWRAP_USED, Allow,
              "using `Option.unwrap()`, which should at least get a better message using `expect()`");
declare_lint!(pub RESULT_UNWRAP_USED, Allow,
              "using `Result.unwrap()`, which might be better handled");
declare_lint!(pub STR_TO_STRING, Warn,
              "using `to_string()` on a str, which should be `to_owned()`");
declare_lint!(pub STRING_TO_STRING, Warn,
              "calling `String.to_string()` which is a no-op");
declare_lint!(pub SHOULD_IMPLEMENT_TRAIT, Warn,
              "defining a method that should be implementing a std trait");
declare_lint!(pub WRONG_SELF_CONVENTION, Warn,
              "defining a method named with an established prefix (like \"into_\") that takes \
               `self` with the wrong convention");
declare_lint!(pub WRONG_PUB_SELF_CONVENTION, Allow,
              "defining a public method named with an established prefix (like \"into_\") that takes \
               `self` with the wrong convention");

impl LintPass for MethodsPass {
    fn get_lints(&self) -> LintArray {
        lint_array!(OPTION_UNWRAP_USED, RESULT_UNWRAP_USED, STR_TO_STRING, STRING_TO_STRING,
                    SHOULD_IMPLEMENT_TRAIT, WRONG_SELF_CONVENTION)
    }
}

impl LateLintPass for MethodsPass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if let ExprMethodCall(ref ident, _, ref args) = expr.node {
            let (obj_ty, ptr_depth) = walk_ptrs_ty_depth(cx.tcx.expr_ty(&args[0]));
            if ident.node.name == "unwrap" {
                if match_type(cx, obj_ty, &OPTION_PATH) {
                    span_lint(cx, OPTION_UNWRAP_USED, expr.span,
                              "used unwrap() on an Option value. If you don't want \
                               to handle the None case gracefully, consider using \
                               expect() to provide a better panic message");
                } else if match_type(cx, obj_ty, &RESULT_PATH) {
                    span_lint(cx, RESULT_UNWRAP_USED, expr.span,
                              "used unwrap() on a Result value. Graceful handling \
                               of Err values is preferred");
                }
            }
            else if ident.node.name == "to_string" {
                if obj_ty.sty == ty::TyStr {
                    let mut arg_str = snippet(cx, args[0].span, "_");
                    if ptr_depth > 1 {
                        arg_str = Cow::Owned(format!(
                            "({}{})",
                            iter::repeat('*').take(ptr_depth - 1).collect::<String>(),
                            arg_str));
                    }
                    span_lint(cx, STR_TO_STRING, expr.span, &format!(
                        "`{}.to_owned()` is faster", arg_str));
                } else if match_type(cx, obj_ty, &STRING_PATH) {
                    span_lint(cx, STRING_TO_STRING, expr.span, "`String.to_string()` is a no-op; use \
                                                                `clone()` to make a copy");
                }
            }
        }
    }

    fn check_item(&mut self, cx: &LateContext, item: &Item) {
        if let ItemImpl(_, _, _, None, ref ty, ref items) = item.node {
            for implitem in items {
                let name = implitem.ident.name;
                if let MethodImplItem(ref sig, _) = implitem.node {
                    // check missing trait implementations
                    for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS {
                        if_let_chain! {
                            [
                                name == method_name,
                                sig.decl.inputs.len() == n_args,
                                out_type.matches(&sig.decl.output),
                                self_kind.matches(&sig.explicit_self.node, false)
                            ], {
                                span_lint(cx, SHOULD_IMPLEMENT_TRAIT, implitem.span, &format!(
                                    "defining a method called `{}` on this type; consider implementing \
                                     the `{}` trait or choosing a less ambiguous name", name, trait_name));
                            }
                        }
                    }
                    // check conventions w.r.t. conversion method names and predicates
                    let is_copy = is_copy(cx, &ty, &item);
                    for &(prefix, self_kinds) in &CONVENTIONS {
                        if name.as_str().starts_with(prefix) &&
                                !self_kinds.iter().any(|k| k.matches(&sig.explicit_self.node, is_copy)) {
                            let lint = if item.vis == Visibility::Public {
                                WRONG_PUB_SELF_CONVENTION
                            } else {
                                WRONG_SELF_CONVENTION
                            };
                            span_lint(cx, lint, sig.explicit_self.span, &format!(
                                "methods called `{}*` usually take {}; consider choosing a less \
                                 ambiguous name", prefix,
                                &self_kinds.iter().map(|k| k.description()).collect::<Vec<_>>().join(" or ")));
                        }
                    }
                }
            }
        }
    }
}

const CONVENTIONS: [(&'static str, &'static [SelfKind]); 5] = [
    ("into_", &[ValueSelf]),
    ("to_",   &[RefSelf]),
    ("as_",   &[RefSelf, RefMutSelf]),
    ("is_",   &[RefSelf, NoSelf]),
    ("from_", &[NoSelf]),
];

const TRAIT_METHODS: [(&'static str, usize, SelfKind, OutType, &'static str); 30] = [
    ("add",        2, ValueSelf,  AnyType,  "std::ops::Add"),
    ("sub",        2, ValueSelf,  AnyType,  "std::ops::Sub"),
    ("mul",        2, ValueSelf,  AnyType,  "std::ops::Mul"),
    ("div",        2, ValueSelf,  AnyType,  "std::ops::Div"),
    ("rem",        2, ValueSelf,  AnyType,  "std::ops::Rem"),
    ("shl",        2, ValueSelf,  AnyType,  "std::ops::Shl"),
    ("shr",        2, ValueSelf,  AnyType,  "std::ops::Shr"),
    ("bitand",     2, ValueSelf,  AnyType,  "std::ops::BitAnd"),
    ("bitor",      2, ValueSelf,  AnyType,  "std::ops::BitOr"),
    ("bitxor",     2, ValueSelf,  AnyType,  "std::ops::BitXor"),
    ("neg",        1, ValueSelf,  AnyType,  "std::ops::Neg"),
    ("not",        1, ValueSelf,  AnyType,  "std::ops::Not"),
    ("drop",       1, RefMutSelf, UnitType, "std::ops::Drop"),
    ("index",      2, RefSelf,    RefType,  "std::ops::Index"),
    ("index_mut",  2, RefMutSelf, RefType,  "std::ops::IndexMut"),
    ("deref",      1, RefSelf,    RefType,  "std::ops::Deref"),
    ("deref_mut",  1, RefMutSelf, RefType,  "std::ops::DerefMut"),
    ("clone",      1, RefSelf,    AnyType,  "std::clone::Clone"),
    ("borrow",     1, RefSelf,    RefType,  "std::borrow::Borrow"),
    ("borrow_mut", 1, RefMutSelf, RefType,  "std::borrow::BorrowMut"),
    ("as_ref",     1, RefSelf,    RefType,  "std::convert::AsRef"),
    ("as_mut",     1, RefMutSelf, RefType,  "std::convert::AsMut"),
    ("eq",         2, RefSelf,    BoolType, "std::cmp::PartialEq"),
    ("cmp",        2, RefSelf,    AnyType,  "std::cmp::Ord"),
    ("default",    0, NoSelf,     AnyType,  "std::default::Default"),
    ("hash",       2, RefSelf,    UnitType, "std::hash::Hash"),
    ("next",       1, RefMutSelf, AnyType,  "std::iter::Iterator"),
    ("into_iter",  1, ValueSelf,  AnyType,  "std::iter::IntoIterator"),
    ("from_iter",  1, NoSelf,     AnyType,  "std::iter::FromIterator"),
    ("from_str",   1, NoSelf,     AnyType,  "std::str::FromStr"),
];

#[derive(Clone, Copy)]
enum SelfKind {
    ValueSelf,
    RefSelf,
    RefMutSelf,
    NoSelf,
}

impl SelfKind {
    fn matches(&self, slf: &ExplicitSelf_, allow_value_for_ref: bool) -> bool {
        match (self, slf) {
            (&ValueSelf, &SelfValue(_)) => true,
            (&RefSelf, &SelfRegion(_, Mutability::MutImmutable, _)) => true,
            (&RefMutSelf, &SelfRegion(_, Mutability::MutMutable, _)) => true,
            (&RefSelf, &SelfValue(_)) => allow_value_for_ref,
            (&RefMutSelf, &SelfValue(_)) => allow_value_for_ref,
            (&NoSelf, &SelfStatic) => true,
            (_, &SelfExplicit(ref ty, _)) => self.matches_explicit_type(ty, allow_value_for_ref),
            _ => false
        }
    }

    fn matches_explicit_type(&self, ty: &Ty, allow_value_for_ref: bool) -> bool {
        match (self, &ty.node) {
            (&ValueSelf, &TyPath(..)) => true,
            (&RefSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutImmutable, .. })) => true,
            (&RefMutSelf, &TyRptr(_, MutTy { mutbl: Mutability::MutMutable, .. })) => true,
            (&RefSelf, &TyPath(..)) => allow_value_for_ref,
            (&RefMutSelf, &TyPath(..)) => allow_value_for_ref,
            _ => false
        }
    }

    fn description(&self) -> &'static str {
        match *self {
            ValueSelf => "self by value",
            RefSelf => "self by reference",
            RefMutSelf => "self by mutable reference",
            NoSelf => "no self",
        }
    }
}

#[derive(Clone, Copy)]
enum OutType {
    UnitType,
    BoolType,
    AnyType,
    RefType,
}

impl OutType {
    fn matches(&self, ty: &FunctionRetTy) -> bool {
        match (self, ty) {
            (&UnitType, &DefaultReturn(_)) => true,
            (&UnitType, &Return(ref ty)) if ty.node == TyTup(vec![]) => true,
            (&BoolType, &Return(ref ty)) if is_bool(ty) => true,
            (&AnyType, &Return(ref ty)) if ty.node != TyTup(vec![])  => true,
            (&RefType, &Return(ref ty)) => {
                if let TyRptr(_, _) = ty.node { true } else { false }
            }
            _ => false
        }
    }
}

fn is_bool(ty: &Ty) -> bool {
    if let TyPath(None, ref p) = ty.node {
        if match_path(p, &["bool"]) {
            return true;
        }
    }
    false
}

fn is_copy(cx: &LateContext, ast_ty: &Ty, item: &Item) -> bool {
    match cx.tcx.ast_ty_to_ty_cache.borrow().get(&ast_ty.id) {
        None => false,
        Some(ty) => {
            let env = ty::ParameterEnvironment::for_item(cx.tcx, item.id);
            !ty.subst(cx.tcx, &env.free_substs).moves_by_default(&env, ast_ty.span)
        }
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::iter::range_inclusive;

const DSFMT_MEXP:uint = 19937;
const DSFMT_N:   uint = ((DSFMT_MEXP - 128) / 104 + 1);
const DSFMT_N64: uint = (DSFMT_N * 2);
const DSFMT_SR:  uint = 12;

const DSFMT_LOW_MASK:   u64 = 0x000FFFFFFFFFFFFF;
const DSFMT_HIGH_CONST: u64 = 0x3FF0000000000000;

const DSFMT_POS1: uint = 117;
const DSFMT_SL1:  uint = 19;
const DSFMT_PCV1: u64  = 0x3d84e1ac0dc82880;
const DSFMT_PCV2: u64  = 0x0000000000000001;
const DSFMT_FIX1: u64  = 0x90014964b32f4329;
const DSFMT_FIX2: u64  = 0x3b8d12ac548a7c7a;
const DSFMT_MSK1: u64  = 0x000ffafffffffb3f;
const DSFMT_MSK2: u64  = 0x000ffdfffc90fffd;

const SSE2_SHUFF: u8 = 0x1b;
const SSE2_PARAMS_MASK: u64x2 = u64x2{x: DSFMT_MSK1, y: DSFMT_MSK2};

pub struct DSFMTRng{
    status: [u64x2, ..DSFMT_N + 1],
    idx: uint,
}

#[repr(C)]
#[simd]
#[deriving(Show)]
struct u32x4{
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}

#[repr(C)]
#[simd]
#[deriving(Show)]
struct u64x2{
    x: u64,
    y: u64,
}

impl Index<uint, u64> for u64x2{
    fn index(&self, _rhs: &uint) -> &u64{
        match *_rhs{
            0 => &self.x,
            _ => &self.y,
        }
    }
}

impl IndexMut<uint, u64> for u64x2{
    fn index_mut(&mut self, _rhs: &uint) -> &mut u64{
        match *_rhs{
            0 => &mut self.x,
            _ => &mut self.y,
        }
    }
}

impl Index<uint, u32> for u32x4{
    fn index(&self, _rhs: &uint) -> &u32{
        match *_rhs{
            0 => &self.x,
            1 => &self.y,
            2 => &self.z,
            _ => &self.w,
        }
    }
}

impl IndexMut<uint, u32> for u32x4{
    fn index_mut(&mut self, _rhs: &uint) -> &mut u32{
        match *_rhs{
            0 => &mut self.x,
            1 => &mut self.y,
            2 => &mut self.z,
            _ => &mut self.w,
        }
    }
}

#[cfg(target_endian = "big")]
fn idxof(i: uint) -> uint {
    i ^ 1
}

#[cfg(target_endian = "little")]
fn idxof(i: uint) -> uint {
    i
}

//fn do_recursion(r: &mut u64x2, a: u64x2, b: u64x2, lung: &mut u64x2){
//
//    let u64x2{x: t0, y: t1} = a;
//    let u64x2{x: l0, y: l1} = *lung;
//
//    lung[0] = (t0 << DSFMT_SL1) ^ (l1 >> 32) ^ (l1 << 32) ^ b[0];
//    lung[1] = (t1 << DSFMT_SL1) ^ (l0 >> 32) ^ (l0 << 32) ^ b[1];
//
//    r[0] = ((*lung)[0] >> DSFMT_SR) ^ ((*lung)[0] & DSFMT_MSK1) ^ t0;
//    r[1] = ((*lung)[1] >> DSFMT_SR) ^ ((*lung)[1] & DSFMT_MSK2) ^ t1;
//}

#[allow(unused)]
#[inline(always)]
fn do_recursion(r: &mut u64x2, a: u64x2, b: u64x2, u: &mut u64x2){
    let mut z = a;
    unsafe{asm!(
        "psllq  $4, $0\n\t
         pxor   $8, $0\n\t
         pshufd $3, $1, $1\n\t
         pxor   $0, $1\n\t
         movaps $1, $0\n\t
         movaps $1, $2\n\t
         pand   $6, $0\n\t
         psrlq  $5, $2\n\t
         pxor   $7, $2\n\t
         pxor   $0, $2\n\t
        "
        :"+x"(z), "+x"(*u), "=x"(*r)
        :"i"(SSE2_SHUFF), "i"(DSFMT_SL1), "i"(DSFMT_SR), "x"(SSE2_PARAMS_MASK), "m"(a), "x"(b)
    )};
}

impl DSFMTRng{
    /// Create a new unseeded DSFMTRng instance
    pub fn new() -> DSFMTRng {
        DSFMTRng{status: [u64x2{x: 0, y: 0}, ..DSFMT_N + 1], idx: 0}
    }

    /// Returns a new DSFMTRng seeded by seed
    pub fn from_seed(seed: u32) -> DSFMTRng {
        let mut rng = DSFMTRng::new();
        rng.init(seed);
        rng
    }

    /// Initializes the internal state array to fit the IEEE 754 format.
    fn initial_mask(&mut self){
        for i in range(0, DSFMT_N * 2){
            let (n, m) = (i / 2, i % 2);
            self.status[n][m] = (self.status[n][m] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST;
        }
    }

    /// Certifies the period of 2^{SFMT_MEXP}-1.
    fn period_certification(&mut self) {
        let pcv: [u64, ..2] = [DSFMT_PCV1, DSFMT_PCV2];

        {
            let tmp = [self.status[DSFMT_N][0] ^ DSFMT_FIX1, self.status[DSFMT_N][1] ^ DSFMT_FIX2];
            let mut inner = (tmp[0] & pcv[0]) ^ (tmp[1] & pcv[1]);

            let mut i = 32u;
            while i > 0 {
                inner ^= inner >> i;
                i >>= 1;
            }
            inner &= 1;
            /* check OK */
            if inner == 1 {
                return;
            }
        }

        /* check NG, and modification */
        if (DSFMT_PCV2 & 1) == 1 {
            self.status[DSFMT_N][1] ^= 1;
        }
        else{
            for i in range_inclusive(1, 0){
                let mut work = 1u64;
                for _ in range(0i, 64){
                    if (work & pcv[i]) != 0 {
                        self.status[DSFMT_N][i] ^= work;
                        return;
                    }
                    work <<= 1;
                }
            }
        }
    }

    pub fn init(&mut self, seed: u32) {
        let psfmt: &mut [u32x4, ..DSFMT_N + 1] = unsafe{mem::transmute(&mut self.status)};
        let i = idxof(0);
        psfmt[i / 4][i % 4] = seed;

        for i in range(1u, 4 * (DSFMT_N + 1)){
            let idx1 = idxof(i);
            let idx2 = idxof(i - 1);
            psfmt[idx1 / 4][idx1 % 4] = 1812433253u32 * (psfmt[idx2 / 4][idx2 % 4] ^ (psfmt[idx2 / 4][idx2 % 4] >> 30)) + (i as u32);
        }

        self.initial_mask();
        self.period_certification();
        self.idx = DSFMT_N64;
    }

    fn gen_rand_all(&mut self){
        let mut lung = self.status[DSFMT_N];
        {
            let a = self.status[0];
            let b = self.status[DSFMT_POS1];
            do_recursion(&mut self.status[0], a, b, &mut lung);
        }
        let mut i = 1u;
        while i < DSFMT_N - DSFMT_POS1 {
            let a = self.status[i];
            let b = self.status[i + DSFMT_POS1];
            do_recursion(&mut self.status[i], a, b, &mut lung);
            i += 1;
        }
        while i < DSFMT_N {
            let a = self.status[i];
            let b = self.status[i + DSFMT_POS1 - DSFMT_N];
            do_recursion(&mut self.status[i], a, b, &mut lung);
            i += 1;
        }
        self.status[DSFMT_N] = lung;
    }

    #[inline]
    pub fn genrand_close1_open2(&mut self) -> f64 {
        if self.idx >= DSFMT_N64 {
            self.gen_rand_all();
            self.idx = 0;
        }

        let (n, m) = (self.idx / 2, self.idx % 2);
        self.idx += 1;

        unsafe{mem::transmute(self.status[n][m])}
    }

    #[inline]
    pub fn genrand_close_open(&mut self) -> f64 {
        self.genrand_close1_open2() - 1.0
    }

    #[inline]
    pub fn genrand_u32(&mut self) -> u32 {
        if self.idx >= DSFMT_N64 {
            self.gen_rand_all();
            self.idx = 0;
        }

        let (n, m) = (self.idx / 2, self.idx % 2);
        self.idx += 1;
        (self.status[n][m] & 0xffffffffu64) as u32
    }

    #[inline]
    pub fn genrand_open_open(&mut self) -> f64 {
        if self.idx >= DSFMT_N64 {
            self.gen_rand_all();
            self.idx = 0;
        }

        let (n, m) = (self.idx / 2, self.idx % 2);
        self.idx += 1;

        unsafe{mem::transmute::<u64, f64>(self.status[n][m] | 1u64) - 1.0f64}
    }
}

<commit_msg>Implemented std::rand traits. These are implemented for convenience; the DSFMTRng methods should be used directly for maximum performance.<commit_after>use std::mem;
use std::iter::range_inclusive;

use std::rand::{Rng, SeedableRng, Rand};

const DSFMT_MEXP:uint = 19937;
const DSFMT_N:   uint = ((DSFMT_MEXP - 128) / 104 + 1);
const DSFMT_N64: uint = (DSFMT_N * 2);
const DSFMT_SR:  uint = 12;

const DSFMT_LOW_MASK:   u64 = 0x000FFFFFFFFFFFFF;
const DSFMT_HIGH_CONST: u64 = 0x3FF0000000000000;

const DSFMT_POS1: uint = 117;
const DSFMT_SL1:  uint = 19;
const DSFMT_PCV1: u64  = 0x3d84e1ac0dc82880;
const DSFMT_PCV2: u64  = 0x0000000000000001;
const DSFMT_FIX1: u64  = 0x90014964b32f4329;
const DSFMT_FIX2: u64  = 0x3b8d12ac548a7c7a;
const DSFMT_MSK1: u64  = 0x000ffafffffffb3f;
const DSFMT_MSK2: u64  = 0x000ffdfffc90fffd;

const SSE2_SHUFF: u8 = 0x1b;
const SSE2_PARAMS_MASK: u64x2 = u64x2{x: DSFMT_MSK1, y: DSFMT_MSK2};

pub struct DSFMTRng{
    status: [u64x2, ..DSFMT_N + 1],
    idx: uint,
}

#[repr(C)]
#[simd]
#[deriving(Show)]
struct u32x4{
    x: u32,
    y: u32,
    z: u32,
    w: u32,
}

#[repr(C)]
#[simd]
#[deriving(Show)]
struct u64x2{
    x: u64,
    y: u64,
}

impl Index<uint, u64> for u64x2{
    fn index(&self, _rhs: &uint) -> &u64{
        match *_rhs{
            0 => &self.x,
            _ => &self.y,
        }
    }
}

impl IndexMut<uint, u64> for u64x2{
    fn index_mut(&mut self, _rhs: &uint) -> &mut u64{
        match *_rhs{
            0 => &mut self.x,
            _ => &mut self.y,
        }
    }
}

impl Index<uint, u32> for u32x4{
    fn index(&self, _rhs: &uint) -> &u32{
        match *_rhs{
            0 => &self.x,
            1 => &self.y,
            2 => &self.z,
            _ => &self.w,
        }
    }
}

impl IndexMut<uint, u32> for u32x4{
    fn index_mut(&mut self, _rhs: &uint) -> &mut u32{
        match *_rhs{
            0 => &mut self.x,
            1 => &mut self.y,
            2 => &mut self.z,
            _ => &mut self.w,
        }
    }
}

#[cfg(target_endian = "big")]
fn idxof(i: uint) -> uint {
    i ^ 1
}

#[cfg(target_endian = "little")]
fn idxof(i: uint) -> uint {
    i
}

//fn do_recursion(r: &mut u64x2, a: u64x2, b: u64x2, lung: &mut u64x2){
//
//    let u64x2{x: t0, y: t1} = a;
//    let u64x2{x: l0, y: l1} = *lung;
//
//    lung[0] = (t0 << DSFMT_SL1) ^ (l1 >> 32) ^ (l1 << 32) ^ b[0];
//    lung[1] = (t1 << DSFMT_SL1) ^ (l0 >> 32) ^ (l0 << 32) ^ b[1];
//
//    r[0] = ((*lung)[0] >> DSFMT_SR) ^ ((*lung)[0] & DSFMT_MSK1) ^ t0;
//    r[1] = ((*lung)[1] >> DSFMT_SR) ^ ((*lung)[1] & DSFMT_MSK2) ^ t1;
//}

#[allow(unused)]
#[inline(always)]
fn do_recursion(r: &mut u64x2, a: u64x2, b: u64x2, u: &mut u64x2){
    let mut z = a;
    unsafe{asm!(
        "psllq  $4, $0\n\t
         pxor   $8, $0\n\t
         pshufd $3, $1, $1\n\t
         pxor   $0, $1\n\t
         movaps $1, $0\n\t
         movaps $1, $2\n\t
         pand   $6, $0\n\t
         psrlq  $5, $2\n\t
         pxor   $7, $2\n\t
         pxor   $0, $2\n\t
        "
        :"+x"(z), "+x"(*u), "=x"(*r)
        :"i"(SSE2_SHUFF), "i"(DSFMT_SL1), "i"(DSFMT_SR), "x"(SSE2_PARAMS_MASK), "m"(a), "x"(b)
    )};
}

impl DSFMTRng{
    /// Create a new unseeded DSFMTRng instance
    pub fn new() -> DSFMTRng {
        DSFMTRng{status: [u64x2{x: 0, y: 0}, ..DSFMT_N + 1], idx: 0}
    }

    /// Returns a new DSFMTRng seeded by seed
    pub fn from_seed(seed: u32) -> DSFMTRng {
        let mut rng = DSFMTRng::new();
        rng.init(seed);
        rng
    }

    /// Initializes the internal state array to fit the IEEE 754 format.
    fn initial_mask(&mut self){
        for i in range(0, DSFMT_N * 2){
            let (n, m) = (i / 2, i % 2);
            self.status[n][m] = (self.status[n][m] & DSFMT_LOW_MASK) | DSFMT_HIGH_CONST;
        }
    }

    /// Certifies the period of 2^{SFMT_MEXP}-1.
    fn period_certification(&mut self) {
        let pcv: [u64, ..2] = [DSFMT_PCV1, DSFMT_PCV2];

        {
            let tmp = [self.status[DSFMT_N][0] ^ DSFMT_FIX1, self.status[DSFMT_N][1] ^ DSFMT_FIX2];
            let mut inner = (tmp[0] & pcv[0]) ^ (tmp[1] & pcv[1]);

            let mut i = 32u;
            while i > 0 {
                inner ^= inner >> i;
                i >>= 1;
            }
            inner &= 1;
            /* check OK */
            if inner == 1 {
                return;
            }
        }

        /* check NG, and modification */
        if (DSFMT_PCV2 & 1) == 1 {
            self.status[DSFMT_N][1] ^= 1;
        }
        else{
            for i in range_inclusive(1, 0){
                let mut work = 1u64;
                for _ in range(0i, 64){
                    if (work & pcv[i]) != 0 {
                        self.status[DSFMT_N][i] ^= work;
                        return;
                    }
                    work <<= 1;
                }
            }
        }
    }

    pub fn init(&mut self, seed: u32) {
        let psfmt: &mut [u32x4, ..DSFMT_N + 1] = unsafe{mem::transmute(&mut self.status)};
        let i = idxof(0);
        psfmt[i / 4][i % 4] = seed;

        for i in range(1u, 4 * (DSFMT_N + 1)){
            let idx1 = idxof(i);
            let idx2 = idxof(i - 1);
            psfmt[idx1 / 4][idx1 % 4] = 1812433253u32 * (psfmt[idx2 / 4][idx2 % 4] ^ (psfmt[idx2 / 4][idx2 % 4] >> 30)) + (i as u32);
        }

        self.initial_mask();
        self.period_certification();
        self.idx = DSFMT_N64;
    }

    fn gen_rand_all(&mut self){
        let mut lung = self.status[DSFMT_N];
        {
            let a = self.status[0];
            let b = self.status[DSFMT_POS1];
            do_recursion(&mut self.status[0], a, b, &mut lung);
        }
        let mut i = 1u;
        while i < DSFMT_N - DSFMT_POS1 {
            let a = self.status[i];
            let b = self.status[i + DSFMT_POS1];
            do_recursion(&mut self.status[i], a, b, &mut lung);
            i += 1;
        }
        while i < DSFMT_N {
            let a = self.status[i];
            let b = self.status[i + DSFMT_POS1 - DSFMT_N];
            do_recursion(&mut self.status[i], a, b, &mut lung);
            i += 1;
        }
        self.status[DSFMT_N] = lung;
    }

    #[inline]
    pub fn genrand_close1_open2(&mut self) -> f64 {
        if self.idx >= DSFMT_N64 {
            self.gen_rand_all();
            self.idx = 0;
        }

        let (n, m) = (self.idx / 2, self.idx % 2);
        self.idx += 1;

        unsafe{mem::transmute(self.status[n][m])}
    }

    #[inline]
    pub fn genrand_close_open(&mut self) -> f64 {
        self.genrand_close1_open2() - 1.0
    }

    #[inline]
    pub fn genrand_u32(&mut self) -> u32 {
        if self.idx >= DSFMT_N64 {
            self.gen_rand_all();
            self.idx = 0;
        }

        let (n, m) = (self.idx / 2, self.idx % 2);
        self.idx += 1;
        (self.status[n][m] & 0xffffffffu64) as u32
    }

    #[inline]
    pub fn genrand_open_open(&mut self) -> f64 {
        if self.idx >= DSFMT_N64 {
            self.gen_rand_all();
            self.idx = 0;
        }

        let (n, m) = (self.idx / 2, self.idx % 2);
        self.idx += 1;

        unsafe{mem::transmute::<u64, f64>(self.status[n][m] | 1u64) - 1.0f64}
    }
}

impl Rng for DSFMTRng {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        if self.idx >= DSFMT_N64 {
            self.gen_rand_all();
            self.idx = 0;
        }

        let (n, m) = (self.idx / 2, self.idx % 2);
        self.idx += 1;
        (self.status[n][m] & 0xffffffffu64) as u32
    }
}

impl SeedableRng<u32> for DSFMTRng {
    fn reseed(&mut self, seed: u32){
        self.init(seed);
    }

    fn from_seed(seed: u32) -> DSFMTRng {
        let mut rng = DSFMTRng::new();
        rng.init(seed);
        rng
    }
}

impl Rand for DSFMTRng {
    fn rand<R: Rng>(other: &mut R) -> DSFMTRng {
        SeedableRng::from_seed(other.next_u32())
    }
}

<|endoftext|>