<commit_before>use ffi;
use any::AnyLuaValue;

use Push;
use PushGuard;
use PushOne;
use AsMutLua;
use TuplePushError;
use LuaRead;

use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::Hash;
use std::iter;

#[inline]
fn push_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
    where L: AsMutLua<'lua>,
          V: for<'b> Push<&'b mut L, Err = E>,
          I: Iterator<Item = V>
{
    // creating empty table
    unsafe { ffi::lua_newtable(lua.as_mut_lua().0) };

    for (elem, index) in iterator.zip((1..)) {
        let size = match elem.push_to_lua(&mut lua) {
            Ok(pushed) => pushed.forget(),
            Err((_err, _lua)) => panic!(),     // TODO: wrong   return Err((err, lua)),      // FIXME: destroy the temporary table
        };

        match size {
            0 => continue,
            1 => {
                let index = index as u32;
                match index.push_to_lua(&mut lua) {
                    Ok(pushed) => pushed.forget(),
                    Err(_) => unreachable!(),
                };
                unsafe { ffi::lua_insert(lua.as_mut_lua().0, -2) }
                unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) }
            }
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!(),
        }
    }

    let raw_lua = lua.as_lua();
    Ok(PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    })
}

#[inline]
fn push_rec_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
    where L: AsMutLua<'lua>,
          V: for<'a> Push<&'a mut L, Err = E>,
          I: Iterator<Item = V>
{
    let (nrec, _) = iterator.size_hint();

    // creating empty table with pre-allocated non-array elements
    unsafe { ffi::lua_createtable(lua.as_mut_lua().0, 0, nrec as i32) };

    for elem in iterator {
        let size = match elem.push_to_lua(&mut lua) {
            Ok(pushed) => pushed.forget(),
            Err((_err, _lua)) => panic!(),     // TODO: wrong   return Err((err, lua)),      // FIXME: destroy the temporary table
        };

        match size {
            0 => continue,
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!(),
        }
    }

    let raw_lua = lua.as_lua();
    Ok(PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    })
}

impl<'lua, L, T, E> Push<L> for Vec<T>
    where L: AsMutLua<'lua>,
          T: for<'a> Push<&'a mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        push_iter(lua, self.into_iter())
    }
}

impl<'lua, L, T, E> PushOne<L> for Vec<T>
    where L: AsMutLua<'lua>,
          T: for<'a> Push<&'a mut L, Err = E>
{
}

impl<'lua, L> LuaRead<L> for Vec<AnyLuaValue>
    where L: AsMutLua<'lua>
{
    fn lua_read_at_position(lua: L, index: i32) -> Result<Self, L> {
        // We need this as iteration order isn't guaranteed to match order of
        // keys, even if they're numeric
        // https://www.lua.org/manual/5.2/manual.html#pdf-next
        let mut dict: BTreeMap<i32, AnyLuaValue> = BTreeMap::new();

        let mut me = lua;
        unsafe { ffi::lua_pushnil(me.as_mut_lua().0) };
        let index = index - 1;

        loop {
            if unsafe { ffi::lua_next(me.as_mut_lua().0, index) } == 0 {
                break;
            }

            let key;

            {
                let maybe_key: Option<i32> =
                    LuaRead::lua_read_at_position(&mut me, -2).ok();
                match maybe_key {
                    None => return Err(me),
                    Some(k) => key = k,
                }
            }

            let value: AnyLuaValue =
                LuaRead::lua_read_at_position(&mut me, -1).ok().unwrap();

            unsafe { ffi::lua_pop(me.as_mut_lua().0, 1) };

            dict.insert(key, value);
        }

        let (maximum_key, minimum_key) =
            (*dict.keys().max().unwrap_or(&1), *dict.keys().min().unwrap_or(&1));

        if minimum_key != 1 {
            // Rust doesn't support sparse arrays or arrays with negative
            // indices
            return Err(me);
        }

        let mut result =
            Vec::with_capacity(maximum_key as usize);

        // We expect to start with first element of table and have this
        // be smaller that first key by one
        let mut previous_key = 0;

        // By this point, we actually iterate the map to move values to Vec
        // and check that table represented non-sparse 1-indexed array
        for (k, v) in dict {
            if previous_key + 1 != k {
                return Err(me)
            } else {
                // We just push, thus converting Lua 1-based indexing
                // to Rust 0-based indexing
                result.push(v);
                previous_key = k;
            }
        }

        Ok(result)
    }
}

impl<'a, 'lua, L, T, E> Push<L> for &'a [T]
    where L: AsMutLua<'lua>,
          T: Clone + for<'b> Push<&'b mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        push_iter(lua, self.iter().map(|e| e.clone()))
    }
}

impl<'a, 'lua, L, T, E> PushOne<L> for &'a [T]
    where L: AsMutLua<'lua>,
          T: Clone + for<'b> Push<&'b mut L, Err = E>
{
}

// TODO: use an enum for the error to allow different error types for K and V
impl<'lua, L, K, V, E> Push<L> for HashMap<K, V>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
          V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        match push_rec_iter(lua, self.into_iter()) {
            Ok(g) => Ok(g),
            Err((TuplePushError::First(err), lua)) => Err((err, lua)),
            Err((TuplePushError::Other(err), lua)) => Err((err, lua)),
        }
    }
}

impl<'lua, L, K, V, E> PushOne<L> for HashMap<K, V>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
          V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
{
}

impl<'lua, L, K, E> Push<L> for HashSet<K>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        match push_rec_iter(lua, self.into_iter().zip(iter::repeat(true))) {
            Ok(g) => Ok(g),
            Err((TuplePushError::First(err), lua)) => Err((err, lua)),
            Err((TuplePushError::Other(_), _)) => unreachable!(),
        }
    }
}

impl<'lua, L, K, E> PushOne<L> for HashSet<K>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
{
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::collections::HashSet;
    use Lua;
    use LuaTable;
    use AnyLuaValue;

    #[test]
    fn write() {
        let mut lua = Lua::new();

        lua.set("a", vec![9, 8, 7]);

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: Vec<(i32, i32)> = table.iter().filter_map(|e| e).collect();
        assert_eq!(values, vec![(1, 9), (2, 8), (3, 7)]);
    }

    #[test]
    fn write_map() {
        let mut lua = Lua::new();

        let mut map = HashMap::new();
        map.insert(5, 8);
        map.insert(13, 21);
        map.insert(34, 55);

        lua.set("a", map.clone());

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: HashMap<i32, i32> = table.iter().filter_map(|e| e).collect();
        assert_eq!(values, map);
    }

    #[test]
    fn write_set() {
        let mut lua = Lua::new();

        let mut set = HashSet::new();
        set.insert(5);
        set.insert(8);
        set.insert(13);
        set.insert(21);
        set.insert(34);
        set.insert(55);

        lua.set("a", set.clone());

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: HashSet<i32> = table.iter()
            .filter_map(|e| e)
            .map(|(elem, set): (i32, bool)| {
                assert!(set);
                elem
            })
            .collect();

        assert_eq!(values, set);
    }

    #[test]
    fn globals_table() {
        let mut lua = Lua::new();

        lua.globals_table().set("a", 12);

        let val: i32 = lua.get("a").unwrap();
        assert_eq!(val, 12);
    }

    #[test]
    fn reading_vec_works() {
        let mut lua = Lua::new();

        let orig = [1., 2., 3.];

        lua.set("v", &orig[..]);

        let read: Vec<_> = lua.get("v").unwrap();
        for (o, r) in orig.iter().zip(read.iter()) {
            if let AnyLuaValue::LuaNumber(ref n) = *r {
                assert_eq!(o, n);
            } else {
                panic!("Unexpected variant");
            }
        }
    }

    #[test]
    fn reading_vec_from_sparse_table_doesnt_work() {
        let mut lua = Lua::new();

        lua.execute::<()>(r#"v = { [-1] = -1, [2] = 2, [42] = 42 }"#).unwrap();

        let read: Option<Vec<_>> = lua.get("v");
        if read.is_some() {
            panic!("Unexpected success");
        }
    }

    #[test]
    fn reading_vec_with_empty_table_works() {
        let mut lua = Lua::new();

        lua.execute::<()>(r#"v = { }"#).unwrap();

        let read: Vec<_> = lua.get("v").unwrap();
        assert_eq!(read.len(), 0);
    }

    #[test]
    fn reading_vec_with_complex_indexes_doesnt_work() {
        let mut lua = Lua::new();

        lua.execute::<()>(r#"v = { [-1] = -1, ["foo"] = 2, [{}] = 42 }"#).unwrap();

        let read: Option<Vec<_>> = lua.get("v");
        if read.is_some() {
            panic!("Unexpected success");
        }
    }

    #[test]
    fn reading_heterogenous_vec_works() {
        let mut lua = Lua::new();

        let orig = [
            AnyLuaValue::LuaNumber(1.),
            AnyLuaValue::LuaBoolean(false),
            AnyLuaValue::LuaNumber(3.),
            // Pushing String to and reading it from makes it a number
            //AnyLuaValue::LuaString(String::from("3"))
        ];

        lua.set("v", &orig[..]);

        let read: Vec<_> = lua.get("v").unwrap();
        assert_eq!(read, orig);
    }
}
<commit_msg>Fix the cleanup<commit_after>use ffi;
use any::AnyLuaValue;

use Push;
use PushGuard;
use PushOne;
use AsMutLua;
use TuplePushError;
use LuaRead;

use std::collections::{BTreeMap, HashMap, HashSet};
use std::hash::Hash;
use std::iter;

#[inline]
fn push_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
    where L: AsMutLua<'lua>,
          V: for<'b> Push<&'b mut L, Err = E>,
          I: Iterator<Item = V>
{
    // creating empty table
    unsafe { ffi::lua_newtable(lua.as_mut_lua().0) };

    for (elem, index) in iterator.zip((1..)) {
        let size = match elem.push_to_lua(&mut lua) {
            Ok(pushed) => pushed.forget(),
            Err((_err, _lua)) => panic!(),     // TODO: wrong   return Err((err, lua)),      // FIXME: destroy the temporary table
        };

        match size {
            0 => continue,
            1 => {
                let index = index as u32;
                match index.push_to_lua(&mut lua) {
                    Ok(pushed) => pushed.forget(),
                    Err(_) => unreachable!(),
                };
                unsafe { ffi::lua_insert(lua.as_mut_lua().0, -2) }
                unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) }
            }
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!(),
        }
    }

    let raw_lua = lua.as_lua();
    Ok(PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    })
}

#[inline]
fn push_rec_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
    where L: AsMutLua<'lua>,
          V: for<'a> Push<&'a mut L, Err = E>,
          I: Iterator<Item = V>
{
    let (nrec, _) = iterator.size_hint();

    // creating empty table with pre-allocated non-array elements
    unsafe { ffi::lua_createtable(lua.as_mut_lua().0, 0, nrec as i32) };

    for elem in iterator {
        let size = match elem.push_to_lua(&mut lua) {
            Ok(pushed) => pushed.forget(),
            Err((_err, _lua)) => panic!(),     // TODO: wrong   return Err((err, lua)),      // FIXME: destroy the temporary table
        };

        match size {
            0 => continue,
            2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
            _ => unreachable!(),
        }
    }

    let raw_lua = lua.as_lua();
    Ok(PushGuard {
        lua: lua,
        size: 1,
        raw_lua: raw_lua,
    })
}

impl<'lua, L, T, E> Push<L> for Vec<T>
    where L: AsMutLua<'lua>,
          T: for<'a> Push<&'a mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        push_iter(lua, self.into_iter())
    }
}

impl<'lua, L, T, E> PushOne<L> for Vec<T>
    where L: AsMutLua<'lua>,
          T: for<'a> Push<&'a mut L, Err = E>
{
}

impl<'lua, L> LuaRead<L> for Vec<AnyLuaValue>
    where L: AsMutLua<'lua>
{
    fn lua_read_at_position(lua: L, index: i32) -> Result<Self, L> {
        // We need this as iteration order isn't guaranteed to match order of
        // keys, even if they're numeric
        // https://www.lua.org/manual/5.2/manual.html#pdf-next
        let mut dict: BTreeMap<i32, AnyLuaValue> = BTreeMap::new();

        let mut me = lua;
        unsafe { ffi::lua_pushnil(me.as_mut_lua().0) };
        let index = index - 1;

        loop {
            if unsafe { ffi::lua_next(me.as_mut_lua().0, index) } == 0 {
                break;
            }

            let key;

            {
                let maybe_key: Option<i32> =
                    LuaRead::lua_read_at_position(&mut me, -2).ok();
                match maybe_key {
                    None => {
                        // Cleaning up after ourselves
                        unsafe { ffi::lua_pop(me.as_mut_lua().0, 2) };
                        return Err(me)
                    }
                    Some(k) => key = k,
                }
            }

            let value: AnyLuaValue =
                LuaRead::lua_read_at_position(&mut me, -1).ok().unwrap();

            unsafe { ffi::lua_pop(me.as_mut_lua().0, 1) };

            dict.insert(key, value);
        }

        let (maximum_key, minimum_key) =
            (*dict.keys().max().unwrap_or(&1), *dict.keys().min().unwrap_or(&1));

        if minimum_key != 1 {
            // Rust doesn't support sparse arrays or arrays with negative
            // indices
            return Err(me);
        }

        let mut result =
            Vec::with_capacity(maximum_key as usize);

        // We expect to start with first element of table and have this
        // be smaller that first key by one
        let mut previous_key = 0;

        // By this point, we actually iterate the map to move values to Vec
        // and check that table represented non-sparse 1-indexed array
        for (k, v) in dict {
            if previous_key + 1 != k {
                return Err(me)
            } else {
                // We just push, thus converting Lua 1-based indexing
                // to Rust 0-based indexing
                result.push(v);
                previous_key = k;
            }
        }

        Ok(result)
    }
}

impl<'a, 'lua, L, T, E> Push<L> for &'a [T]
    where L: AsMutLua<'lua>,
          T: Clone + for<'b> Push<&'b mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        push_iter(lua, self.iter().map(|e| e.clone()))
    }
}

impl<'a, 'lua, L, T, E> PushOne<L> for &'a [T]
    where L: AsMutLua<'lua>,
          T: Clone + for<'b> Push<&'b mut L, Err = E>
{
}

// TODO: use an enum for the error to allow different error types for K and V
impl<'lua, L, K, V, E> Push<L> for HashMap<K, V>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
          V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        match push_rec_iter(lua, self.into_iter()) {
            Ok(g) => Ok(g),
            Err((TuplePushError::First(err), lua)) => Err((err, lua)),
            Err((TuplePushError::Other(err), lua)) => Err((err, lua)),
        }
    }
}

impl<'lua, L, K, V, E> PushOne<L> for HashMap<K, V>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
          V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
{
}

impl<'lua, L, K, E> Push<L> for HashSet<K>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
{
    type Err = E;

    #[inline]
    fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
        match push_rec_iter(lua, self.into_iter().zip(iter::repeat(true))) {
            Ok(g) => Ok(g),
            Err((TuplePushError::First(err), lua)) => Err((err, lua)),
            Err((TuplePushError::Other(_), _)) => unreachable!(),
        }
    }
}

impl<'lua, L, K, E> PushOne<L> for HashSet<K>
    where L: AsMutLua<'lua>,
          K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
{
}

#[cfg(test)]
mod tests {
    use std::collections::HashMap;
    use std::collections::HashSet;
    use Lua;
    use LuaTable;
    use AnyLuaValue;

    #[test]
    fn write() {
        let mut lua = Lua::new();

        lua.set("a", vec![9, 8, 7]);

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: Vec<(i32, i32)> = table.iter().filter_map(|e| e).collect();
        assert_eq!(values, vec![(1, 9), (2, 8), (3, 7)]);
    }

    #[test]
    fn write_map() {
        let mut lua = Lua::new();

        let mut map = HashMap::new();
        map.insert(5, 8);
        map.insert(13, 21);
        map.insert(34, 55);

        lua.set("a", map.clone());

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: HashMap<i32, i32> = table.iter().filter_map(|e| e).collect();
        assert_eq!(values, map);
    }

    #[test]
    fn write_set() {
        let mut lua = Lua::new();

        let mut set = HashSet::new();
        set.insert(5);
        set.insert(8);
        set.insert(13);
        set.insert(21);
        set.insert(34);
        set.insert(55);

        lua.set("a", set.clone());

        let mut table: LuaTable<_> = lua.get("a").unwrap();

        let values: HashSet<i32> = table.iter()
            .filter_map(|e| e)
            .map(|(elem, set): (i32, bool)| {
                assert!(set);
                elem
            })
            .collect();

        assert_eq!(values, set);
    }

    #[test]
    fn globals_table() {
        let mut lua = Lua::new();

        lua.globals_table().set("a", 12);

        let val: i32 = lua.get("a").unwrap();
        assert_eq!(val, 12);
    }

    #[test]
    fn reading_vec_works() {
        let mut lua = Lua::new();

        let orig = [1., 2., 3.];

        lua.set("v", &orig[..]);

        let read: Vec<_> = lua.get("v").unwrap();
        for (o, r) in orig.iter().zip(read.iter()) {
            if let AnyLuaValue::LuaNumber(ref n) = *r {
                assert_eq!(o, n);
            } else {
                panic!("Unexpected variant");
            }
        }
    }

    #[test]
    fn reading_vec_from_sparse_table_doesnt_work() {
        let mut lua = Lua::new();

        lua.execute::<()>(r#"v = { [-1] = -1, [2] = 2, [42] = 42 }"#).unwrap();

        let read: Option<Vec<_>> = lua.get("v");
        if read.is_some() {
            panic!("Unexpected success");
        }
    }

    #[test]
    fn reading_vec_with_empty_table_works() {
        let mut lua = Lua::new();

        lua.execute::<()>(r#"v = { }"#).unwrap();

        let read: Vec<_> = lua.get("v").unwrap();
        assert_eq!(read.len(), 0);
    }

    #[test]
    fn reading_vec_with_complex_indexes_doesnt_work() {
        let mut lua = Lua::new();

        lua.execute::<()>(r#"v = { [-1] = -1, ["foo"] = 2, [{}] = 42 }"#).unwrap();

        let read: Option<Vec<_>> = lua.get("v");
        if read.is_some() {
            panic!("Unexpected success");
        }
    }

    #[test]
    fn reading_heterogenous_vec_works() {
        let mut lua = Lua::new();

        let orig = [
            AnyLuaValue::LuaNumber(1.),
            AnyLuaValue::LuaBoolean(false),
            AnyLuaValue::LuaNumber(3.),
            // Pushing String to and reading it from makes it a number
            //AnyLuaValue::LuaString(String::from("3"))
        ];

        lua.set("v", &orig[..]);

        let read: Vec<_> = lua.get("v").unwrap();
        assert_eq!(read, orig);
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Various helper macros.

mod pso;
mod structure;

#[macro_export]
macro_rules! gfx_format {
    ($name:ident : $surface:ident = $container:ident<$channel:ident>) => {
        impl $crate::format::Formatted for $name {
            type Surface = $crate::format::$surface;
            type Channel = $crate::format::$channel;
            type View = $crate::format::$container<
                <$crate::format::$channel as $crate::format::ChannelTyped>::ShaderType
                >;
        }
    }
}

/// Defines vertex, constant and pipeline formats in one block
#[macro_export]
macro_rules! gfx_defines {
    ($(#[$attr:meta])* vertex $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_vertex_struct_meta!($(#[$attr])* vertex_struct_meta $name {$($field:$ty = $e,)+});
    };

    ($(#[$attr:meta])* constant $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_constant_struct_meta!($(#[$attr])* constant_struct_meta $name {$($field:$ty = $e,)+});
    };

    (pipeline $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_pipeline!($name {$($field:$ty = $e,)+});
    };

    // The recursive case for vertex structs
    ($(#[$attr:meta])* vertex $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    } $($tail:tt)+) => {
        gfx_defines! {
            $(#[$attr])*
            vertex $name { $($field : $ty = $e,)+ }
        }
        gfx_defines!($($tail)+);
    };

    // The recursive case for constant structs
    ($(#[$attr:meta])* constant $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    } $($tail:tt)+) => {
        gfx_defines! {
            $(#[$attr])*
            constant $name { $($field : $ty = $e,)+ }
        }
        gfx_defines!($($tail)+);
    };

    // The recursive case for the other keywords
    ($keyword:ident $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    } $($tail:tt)+) => {
        gfx_defines! {
            $keyword $name { $($field : $ty = $e,)+ }
        }
        gfx_defines!($($tail)+);
    };
}
<commit_msg>Auto merge of #1151 - Anttonii:master, r=kvark<commit_after>// Copyright 2015 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Various helper macros.

mod pso;
mod structure;

#[macro_export]
macro_rules! gfx_format {
    ($name:ident : $surface:ident = $container:ident<$channel:ident>) => {
        impl $crate::format::Formatted for $name {
            type Surface = $crate::format::$surface;
            type Channel = $crate::format::$channel;
            type View = $crate::format::$container<
                <$crate::format::$channel as $crate::format::ChannelTyped>::ShaderType
                >;
        }
    }
}

/// Defines vertex, constant and pipeline formats in one block.
///
/// # Example
///
/// ```{.rust}
/// #[macro_use]
/// extern crate gfx;
///
/// gfx_defines! {
///     vertex Vertex {
///         pos: [f32; 4] = "a_Pos",
///         tex_coord: [f32; 2] = "a_TexCoord",
///     }
///
///     constant Locals {
///         transform: [[f32; 4]; 4] = "u_Transform",
///     }
///
///     pipeline pipe {
///         vbuf: gfx::VertexBuffer<Vertex> = (),
///         // Global buffers are added for compatibility when
///         // constant buffers are not supported.
///         transform: gfx::Global<[[f32; 4]; 4]> = "u_Transform",
///         locals: gfx::ConstantBuffer<Locals> = "Locals",
///         color: gfx::TextureSampler<[f32; 4]> = "t_Color",
///         out_color: gfx::RenderTarget<gfx::format::Rgba8> = "Target0",
///         out_depth: gfx::DepthTarget<gfx::format::DepthStencil> =
///             gfx::preset::depth::LESS_EQUAL_WRITE,
///     }
/// }
///
/// impl Vertex {
///     fn new(p: [i8; 3], tex: [i8; 2]) -> Vertex {
///         Vertex {
///             pos: [p[0] as f32, p[1] as f32, p[2] as f32, 1.0f32],
///             tex_coord: [tex[0] as f32, tex[1] as f32],
///         }
///     }
/// }
///
/// fn main() {
///     let vertex_data = [
///         Vertex::new([-1, -1, 1], [0, 0]),
///         Vertex::new([ 1, -1, 1], [1, 0]),
///         // Add more vertices..
///     ];
/// }
/// ```
/// `vertex` and `constant` structures defined with `gfx_defines!`
/// can be extended with attributes:
///
/// ```{.rust}
/// #[macro_use]
/// extern crate gfx;
///
/// gfx_defines! {
///     #[derive(Default)]
///     vertex Vertex {
///         pos: [f32; 4] = "a_Pos",
///         tex_coord: [f32; 2] = "a_TexCoord",
///     }
/// }
///
/// fn main() {
///     let vertex = Vertex::default();
///     assert_eq!(vertex.pos[0], 0f32);
///     assert_eq!(vertex.tex_coord[0], 0f32);
/// }
/// ```
///
/// # `pipe`
///
/// The `pipeline state object` or `pso` can consist of the following
/// `pso` components:
///
/// - A [vertex buffer](pso/buffer/type.VertexBuffer.html) component to hold the vertices.
/// - An [instance buffer](pso/buffer/type.InstanceBuffer.html) component.
/// - Single or multiple [constant buffer](pso/buffer/struct.ConstantBuffer.html) components. (DX11 and OpenGL3)
/// - Single or multiple [global buffer](pso/buffer/struct.Global.html) components.
/// - Single or multiple [samplers](pso/resource/struct.Sampler.html).
/// - [Render](pso/target/struct.RenderTarget.html), [blend](pso/target/struct.BlendTarget.html),
///   [depth](pso/target/struct.DepthTarget.html), [stencil](pso/target/struct.StencilTarget.html) targets.
/// - A [shader resource view](pso/resource/struct.ShaderResource.html) (SRV, DX11)
/// - An [unordered access view](pso/resource/struct.UnorderedAccess.html) (UAV, DX11, not yet implemented in the OpenGL backend)
/// - A [scissor](pso/target/struct.Scissor.html) rectangle value (DX11)
///
/// Structure of a `pipeline state object` can be defined freely.
///
/// It should be noted however, that you can have multiple objects of everything but
/// depth/stencil and scissor objects in a `pipeline state object`, which is the only
/// restriction in the freedom of defining a `pipeline state object`.
///
/// # `vertex`
///
/// Defines a vertex format to be passed onto a vertex buffer. Similar
/// to `pipeline state objects` multiple vertex formats can be set.
///
/// # `constant`
///
/// Defines a structure for shader constant data. This constant data
/// is then appended into a constant buffer in the `pso`. Constant buffers
/// are supported by DirectX 11 and OpenGL3 backend, but in OpenGL they
/// are called `Uniform Buffer Object`s or `UBO`s.
#[macro_export]
macro_rules! gfx_defines {
    ($(#[$attr:meta])* vertex $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_vertex_struct_meta!($(#[$attr])* vertex_struct_meta $name {$($field:$ty = $e,)+});
    };

    ($(#[$attr:meta])* constant $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_constant_struct_meta!($(#[$attr])* constant_struct_meta $name {$($field:$ty = $e,)+});
    };

    (pipeline $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    }) => {
        gfx_pipeline!($name {$($field:$ty = $e,)+});
    };

    // The recursive case for vertex structs
    ($(#[$attr:meta])* vertex $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    } $($tail:tt)+) => {
        gfx_defines! {
            $(#[$attr])*
            vertex $name { $($field : $ty = $e,)+ }
        }
        gfx_defines!($($tail)+);
    };

    // The recursive case for constant structs
    ($(#[$attr:meta])* constant $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    } $($tail:tt)+) => {
        gfx_defines! {
            $(#[$attr])*
            constant $name { $($field : $ty = $e,)+ }
        }
        gfx_defines!($($tail)+);
    };

    // The recursive case for the other keywords
    ($keyword:ident $name:ident {
            $( $field:ident : $ty:ty = $e:expr, )+
    } $($tail:tt)+) => {
        gfx_defines! {
            $keyword $name { $($field : $ty = $e,)+ }
        }
        gfx_defines!($($tail)+);
    };
}
<|endoftext|>


<commit_before>use calx::color::*;
use calx::{Context, V2};
use view::tilecache;
use view::main::State;
use view::gamestate::GameState;

/// Title screen.
pub struct TitleState {
    running: bool,
}

impl TitleState {
    pub fn new() -> TitleState {
        TitleState {
            running: true,
        }
    }
}

/*
impl App for TitleState {
    fn setup(&mut self, _ctx: &mut Context) {
    }

    fn draw(&mut self, ctx: &mut Context) {
        let logo = tilecache::get(tilecache::LOGO);
        ctx.set_color(&FIREBRICK);
        ctx.draw_image(&logo, &Vector2::new(280f32, 180f32));
    }

    fn char_typed(&mut self, _ctx: &mut Engine, _ch: char) {
        self.running = false;
    }

    fn key_pressed(&mut self, _ctx: &mut Engine, _key: Key) {}
    fn key_released(&mut self, _ctx: &mut Engine, _key: Key) {}
}

impl State for TitleState {
    fn next_state(&self) -> Option<Box<State>> {
        if !self.running {
            Some(box GameState::new() as Box<State>)
        } else {
            None
        }
    }
}
*/
<commit_msg>Old src cleanup<commit_after><|endoftext|>


<commit_before>use nix::mq::{mq_open, mq_close, mq_send, mq_receive};
use nix::mq::{O_CREAT, O_WRONLY, O_RDONLY};
use nix::mq::MqAttr;
use nix::sys::stat::{S_IWUSR, S_IRUSR, S_IRGRP, S_IROTH};
use std::ffi::CString;
use libc::{c_long, strlen};

use nix::unistd::{fork, read, write, pipe};
use nix::unistd::Fork::{Child, Parent};
use nix::sys::wait::*;

#[test]
fn mq_send_and_receive() {

    const MSG_SIZE: c_long =  32;

    let attr =  MqAttr { mq_flags: 0, mq_maxmsg: 10, mq_msgsize: MSG_SIZE, mq_curmsgs: 0 };
    let mq_name_in_parent = &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
    let mqd_in_parent = mq_open(mq_name_in_parent, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &attr).unwrap();
    let msg_to_send = &CString::new("msg_1").unwrap();
    let len = unsafe { strlen(msg_to_send.as_ptr()) as usize };

    mq_send(mqd_in_parent, msg_to_send, 1).unwrap();

    let (reader, writer) = pipe().unwrap();

    let pid = fork();
    match pid {
        Ok(Child) => {
            let mq_name_in_child =  &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
            let mqd_in_child = mq_open(mq_name_in_child, O_CREAT | O_RDONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &attr).unwrap();
            let mut buf = [0u8; 32];
            let length_msg_received = mq_receive(mqd_in_child, &mut buf, 1).unwrap();
            assert!(length_msg_received == len);
            let message_str = String::from_utf8_lossy(&buf[0 .. len]);
            let expected_str = String::from_utf8_lossy(msg_to_send.as_bytes());
            assert!(message_str == expected_str);
            write(writer, &buf).unwrap();  // pipe result to parent process. Otherwise cargo does not report test failures correctly
            mq_close(mqd_in_child).unwrap();
      }
      Ok(Parent(child_pid)) => {
          mq_close(mqd_in_parent).unwrap();

          // Wait for the child to exit.
          waitpid(child_pid, None).unwrap();
          // Read 1024 bytes.
          let mut read_buf = [0u8; 32];
          read(reader, &mut read_buf).unwrap();
          let message_str = String::from_utf8_lossy(&read_buf);
          assert!(message_str.contains("msg_1"));
      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}

// cargo clean; cargo test -- --nocapture
<commit_msg>cleaned up mq unit tests<commit_after>use nix::mq::{mq_open, mq_close, mq_send, mq_receive};
use nix::mq::{O_CREAT, O_WRONLY, O_RDONLY};
use nix::mq::MqAttr;
use nix::sys::stat::{S_IWUSR, S_IRUSR, S_IRGRP, S_IROTH};
use std::ffi::CString;
use std::str;
use libc::c_long;

use nix::unistd::{fork, read, write, pipe};
use nix::unistd::Fork::{Child, Parent};
use nix::sys::wait::*;

#[test]
fn mq_send_and_receive() {

    const MSG_SIZE: c_long =  32;

    let attr =  MqAttr { mq_flags: 0, mq_maxmsg: 10, mq_msgsize: MSG_SIZE, mq_curmsgs: 0 };
    let mq_name_in_parent = &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
    let mqd_in_parent = mq_open(mq_name_in_parent, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &attr).unwrap();
    let msg_to_send = &CString::new("msg_1").unwrap();

    mq_send(mqd_in_parent, msg_to_send, 1).unwrap();

    let (reader, writer) = pipe().unwrap();

    let pid = fork();
    match pid {
        Ok(Child) => {
            let mq_name_in_child =  &CString::new(b"/a_nix_test_queue".as_ref()).unwrap();
            let mqd_in_child = mq_open(mq_name_in_child, O_CREAT | O_RDONLY, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, &attr).unwrap();
            let mut buf = [0u8; 32];
            mq_receive(mqd_in_child, &mut buf, 1).unwrap();
            write(writer, &buf).unwrap();  // pipe result to parent process. Otherwise cargo does not report test failures correctly
            mq_close(mqd_in_child).unwrap();
      }
      Ok(Parent(child_pid)) => {
          mq_close(mqd_in_parent).unwrap();

          // Wait for the child to exit.
          waitpid(child_pid, None).unwrap();
          // Read 1024 bytes.
          let mut read_buf = [0u8; 32];
          read(reader, &mut read_buf).unwrap();
          let message_str = str::from_utf8(&read_buf).unwrap();
          assert_eq!(&message_str[.. message_str.char_indices().nth(5).unwrap().0], "msg_1");
      },
      // panic, fork should never fail unless there is a serious problem with the OS
      Err(_) => panic!("Error: Fork Failed")
    }
}
<|endoftext|>


<commit_before>use crate::errno::errno;

/*
    Helper function to get errno
*/
pub fn get_errno_with_message(ret: i32) -> String {
    let e = errno();
    let code = e.0 as i32;
    format!("return code = {}, errno = {}, message = '{}'", ret, code, e)
}

/// Helper function that depending on the `ret` value:
/// - is negative or 0, then form an error message from the `errno` value
/// - is positive, take `ret` as the length of the success message in `buf` in bytes
pub fn check_errno(ret: i32, buf: &mut Vec<u8>) -> Result<String, String> {
    if ret <= 0 {
        Err(get_errno_with_message(ret))
    } else {
        unsafe {
            buf.set_len(ret as usize);
        }

        match String::from_utf8(buf.to_vec()) {
            Ok(return_value) => Ok(return_value),
            Err(e) => Err(format!("Invalid UTF-8 sequence: {}", e))
        }
    }
}

#[cfg(test)]
mod test {
    use crate::errno::{set_errno, Errno};
    use super::check_errno;

    #[test]
    fn invalid_utf8() {
        let mut buf: Vec<u8> = vec!(255, 0, 0);

        // Test
        match check_errno(buf.len() as i32, &mut buf) {
            Err(msg) => assert_eq!(msg, "Invalid UTF-8 sequence: invalid utf-8 sequence of 1 bytes from index 0"),
            Ok(_) => panic!("Unexpected success"),
        }
    }

    #[test]
    fn positive_ret() {
        let message = "custom message";
        let mut buf: Vec<u8> = Vec::from(message.as_bytes());

        // Test
        match check_errno(buf.len() as i32, &mut buf) {
            Err(e) => panic!("Unexpected error {}", e),
            Ok(mes) => assert_eq!(mes, message)
        }
    }

    #[test]
    fn negative_ret() {
        let mut buf: Vec<u8> = vec!();
        set_errno(Errno(-1));

        // Test
        match check_errno(-1, &mut buf) {
            Err(mes) => assert_eq!(mes, "return code = -1, errno = -1, message = 'Unknown error: -1'"),
            Ok(_) => panic!("Unexpected success")
        }
    }

    #[test]
    fn zero_ret() {
        let mut buf: Vec<u8> = vec!();
        set_errno(Errno(0));

        // Test
        match check_errno(0, &mut buf) {
            Err(mes) => assert_eq!(mes, "return code = 0, errno = 0, message = 'Undefined error: 0'"),
            Ok(_) => panic!("Unexpected success")
        }
    }

}<commit_msg>Differences in errno handling on mac and linux<commit_after>use crate::errno::errno;

/*
    Helper function to get errno
*/
pub fn get_errno_with_message(ret: i32) -> String {
    let e = errno();
    let code = e.0 as i32;
    format!("return code = {}, errno = {}, message = '{}'", ret, code, e)
}

/// Helper function that depending on the `ret` value:
/// - is negative or 0, then form an error message from the `errno` value
/// - is positive, take `ret` as the length of the success message in `buf` in bytes
pub fn check_errno(ret: i32, buf: &mut Vec<u8>) -> Result<String, String> {
    if ret <= 0 {
        Err(get_errno_with_message(ret))
    } else {
        unsafe {
            buf.set_len(ret as usize);
        }

        match String::from_utf8(buf.to_vec()) {
            Ok(return_value) => Ok(return_value),
            Err(e) => Err(format!("Invalid UTF-8 sequence: {}", e))
        }
    }
}

#[cfg(test)]
mod test {
    use crate::errno::{set_errno, Errno};
    use super::check_errno;

    #[test]
    fn invalid_utf8() {
        let mut buf: Vec<u8> = vec!(255, 0, 0);

        // Test
        match check_errno(buf.len() as i32, &mut buf) {
            Err(msg) => assert_eq!(msg, "Invalid UTF-8 sequence: invalid utf-8 sequence of 1 bytes from index 0"),
            Ok(_) => panic!("Unexpected success"),
        }
    }

    #[test]
    fn positive_ret() {
        let message = "custom message";
        let mut buf: Vec<u8> = Vec::from(message.as_bytes());

        // Test
        match check_errno(buf.len() as i32, &mut buf) {
            Err(e) => panic!("Unexpected error {}", e),
            Ok(mes) => assert_eq!(mes, message)
        }
    }

    #[test]
    fn negative_ret() {
        let mut buf: Vec<u8> = vec!();
        set_errno(Errno(-1));

        // Test
        match check_errno(-1, &mut buf) {
            #[cfg(target_os = "macos")]
            Err(mes) => assert_eq!(mes, "return code = -1, errno = -1, message = 'Unknown error: -1'"),
            #[cfg(target_os = "linux")]
            Err(mes) => assert_eq!(mes, "return code = -1, errno = -1, message = 'Unknown error -1'"),
            Ok(_) => panic!("Unexpected success")
        }
    }

    #[test]
    fn zero_ret() {
        let mut buf: Vec<u8> = vec!();
        set_errno(Errno(0));

        // Test
        match check_errno(0, &mut buf) {
            #[cfg(target_os = "macos")]
            Err(mes) => assert_eq!(mes, "return code = 0, errno = 0, message = 'Undefined error: 0'"),
            #[cfg(target_os = "macos")]
            Ok(_) => panic!("Unexpected success"),
            #[cfg(target_os = "linux")]
            Err(_) => panic!("Unexpected failure"),
            #[cfg(target_os = "linux")]
            Ok(mesg) => assert_eq!(msg, "return code = 0, errno = 0, message = 'Success'")
        }
    }

}<|endoftext|>


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

/*!
 * Generic hashing support.
 *
 * This module provides a generic way to compute the hash of a value. The
 * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
 *
 * # Example
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 *
 * #[deriving(Hash)]
 * struct Person {
 *     id: uint,
 *     name: ~str,
 *     phone: uint,
 * }
 *
 * let person1 = Person { id: 5, name: ~"Janet", phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: ~"Bob", phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) != hash::hash(&person2));
 * ```
 *
 * If you need more control over how a value is hashed, you need to implement
 * the trait `Hash`:
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 * use std::hash::sip::SipState;
 *
 * struct Person {
 *     id: uint,
 *     name: ~str,
 *     phone: uint,
 * }
 *
 * impl Hash for Person {
 *     fn hash(&self, state: &mut SipState) {
 *         self.id.hash(state);
 *         self.phone.hash(state);
 *     }
 * }
 *
 * let person1 = Person { id: 5, name: ~"Janet", phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: ~"Bob", phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) == hash::hash(&person2));
 * ```
 */

#[allow(unused_must_use)];

use container::Container;
use io::Writer;
use iter::Iterator;
use option::{Option, Some, None};
use rc::Rc;
use str::{Str, StrSlice};
use vec::{Vector, ImmutableVector};

/// Reexport the `sip::hash` function as our default hasher.
pub use hash = self::sip::hash;

pub mod sip;

/// A trait that represents a hashable type. The `S` type parameter is an
/// abstract hash state that is used by the `Hash` to compute the hash.
/// It defaults to `std::hash::sip::SipState`.
pub trait Hash<S = sip::SipState> {
    /// Compute a hash of the value.
    fn hash(&self, state: &mut S);
}

/// A trait that computes a hash for a value. The main users of this trait are
/// containers like `HashMap`, which need a generic way hash multiple types.
pub trait Hasher<S> {
    /// Compute a hash of the value.
    fn hash<T: Hash<S>>(&self, value: &T) -> u64;
}

//////////////////////////////////////////////////////////////////////////////

macro_rules! impl_hash(
    ( $( $ty:ty => $method:ident;)* ) => (
        $(
            impl<S: Writer> Hash<S> for $ty {
                #[inline]
                fn hash(&self, state: &mut S) {
                    state.$method(*self);
                }
            }
        )*
    )
)

impl_hash!(
    u8 => write_u8;
    u16 => write_le_u16;
    u32 => write_le_u32;
    u64 => write_le_u64;
    uint => write_le_uint;
    i8 => write_i8;
    i16 => write_le_i16;
    i32 => write_le_i32;
    i64 => write_le_i64;
    int => write_le_int;
)

impl<S: Writer> Hash<S> for bool {
    #[inline]
    fn hash(&self, state: &mut S) {
        (*self as u8).hash(state);
    }
}

impl<S: Writer> Hash<S> for char {
    #[inline]
    fn hash(&self, state: &mut S) {
        (*self as u32).hash(state);
    }
}

impl<'a, S: Writer> Hash<S> for &'a str {
    #[inline]
    fn hash(&self, state: &mut S) {
        state.write(self.as_bytes());
        state.write_u8(0xFF);
    }
}

impl<S: Writer> Hash<S> for ~str {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

macro_rules! impl_hash_tuple(
    () => (
        impl<S: Writer> Hash<S> for () {
            #[inline]
            fn hash(&self, state: &mut S) {
                state.write([]);
            }
        }
    );

    ($A:ident $($B:ident)*) => (
        impl<
            S: Writer,
            $A: Hash<S> $(, $B: Hash<S>)*
        > Hash<S> for ($A, $($B),*) {
            #[inline]
            fn hash(&self, state: &mut S) {
                match *self {
                    (ref $A, $(ref $B),*) => {
                        $A.hash(state);
                        $(
                            $B.hash(state);
                        )*
                    }
                }
            }
        }

        impl_hash_tuple!($($B)*)
    );
)

impl_hash_tuple!(A0 A1 A2 A3 A4 A5 A6 A7)

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.len().hash(state);
        for elt in self.iter() {
            elt.hash(state);
        }
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for ~[T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for ~T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for @T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.borrow().hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        match *self {
            Some(ref x) => {
                0u8.hash(state);
                x.hash(state);
            }
            None => {
                1u8.hash(state);
            }
        }
    }
}

impl<S: Writer, T> Hash<S> for *T {
    #[inline]
    fn hash(&self, state: &mut S) {
        // NB: raw-pointer Hash does _not_ dereference
        // to the target; it just gives you the pointer-bytes.
        (*self as uint).hash(state);
    }
}

impl<S: Writer, T> Hash<S> for *mut T {
    #[inline]
    fn hash(&self, state: &mut S) {
        // NB: raw-pointer Hash does _not_ dereference
        // to the target; it just gives you the pointer-bytes.
        (*self as uint).hash(state);
    }
}

//////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use cast;
    use io::{IoResult, Writer};
    use iter::{Iterator};
    use option::{Some, None};
    use result::Ok;
    use vec::ImmutableVector;

    use super::{Hash, Hasher};

    struct MyWriterHasher;

    impl Hasher<MyWriter> for MyWriterHasher {
        fn hash<T: Hash<MyWriter>>(&self, value: &T) -> u64 {
            let mut state = MyWriter { hash: 0 };
            value.hash(&mut state);
            state.hash
        }
    }

    struct MyWriter {
        hash: u64,
    }

    impl Writer for MyWriter {
        // Most things we'll just add up the bytes.
        fn write(&mut self, buf: &[u8]) -> IoResult<()> {
            for byte in buf.iter() {
                self.hash += *byte as u64;
            }
            Ok(())
        }
    }

    #[test]
    fn test_writer_hasher() {
        let hasher = MyWriterHasher;

        assert_eq!(hasher.hash(&()), 0);

        assert_eq!(hasher.hash(&5u8), 5);
        assert_eq!(hasher.hash(&5u16), 5);
        assert_eq!(hasher.hash(&5u32), 5);
        assert_eq!(hasher.hash(&5u64), 5);
        assert_eq!(hasher.hash(&5u), 5);

        assert_eq!(hasher.hash(&5i8), 5);
        assert_eq!(hasher.hash(&5i16), 5);
        assert_eq!(hasher.hash(&5i32), 5);
        assert_eq!(hasher.hash(&5i64), 5);
        assert_eq!(hasher.hash(&5i), 5);

        assert_eq!(hasher.hash(&false), 0);
        assert_eq!(hasher.hash(&true), 1);

        assert_eq!(hasher.hash(&'a'), 97);

        assert_eq!(hasher.hash(& &"a"), 97 + 0xFF);
        assert_eq!(hasher.hash(& &[1u8, 2u8, 3u8]), 9);

        unsafe {
            let ptr: *int = cast::transmute(5);
            assert_eq!(hasher.hash(&ptr), 5);
        }

        unsafe {
            let ptr: *mut int = cast::transmute(5);
            assert_eq!(hasher.hash(&ptr), 5);
        }
    }

    struct Custom {
        hash: u64
    }

    impl Hash<u64> for Custom {
        fn hash(&self, state: &mut u64) {
            *state = self.hash;
        }
    }

    #[test]
    fn test_custom_state() {
        let custom = Custom { hash: 5 };
        let mut state = 0;
        custom.hash(&mut state);
        assert_eq!(state, 5);
    }
}
<commit_msg>std: fix the hash doctest<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * Generic hashing support.
 *
 * This module provides a generic way to compute the hash of a value. The
 * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
 *
 * # Example
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 *
 * #[deriving(Hash)]
 * struct Person {
 *     id: uint,
 *     name: ~str,
 *     phone: u64,
 * }
 *
 * let person1 = Person { id: 5, name: ~"Janet", phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: ~"Bob", phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) != hash::hash(&person2));
 * ```
 *
 * If you need more control over how a value is hashed, you need to implement
 * the trait `Hash`:
 *
 * ```rust
 * use std::hash;
 * use std::hash::Hash;
 * use std::hash::sip::SipState;
 *
 * struct Person {
 *     id: uint,
 *     name: ~str,
 *     phone: u64,
 * }
 *
 * impl Hash for Person {
 *     fn hash(&self, state: &mut SipState) {
 *         self.id.hash(state);
 *         self.phone.hash(state);
 *     }
 * }
 *
 * let person1 = Person { id: 5, name: ~"Janet", phone: 555_666_7777 };
 * let person2 = Person { id: 5, name: ~"Bob", phone: 555_666_7777 };
 *
 * assert!(hash::hash(&person1) == hash::hash(&person2));
 * ```
 */

#[allow(unused_must_use)];

use container::Container;
use io::Writer;
use iter::Iterator;
use option::{Option, Some, None};
use rc::Rc;
use str::{Str, StrSlice};
use vec::{Vector, ImmutableVector};

/// Reexport the `sip::hash` function as our default hasher.
pub use hash = self::sip::hash;

pub mod sip;

/// A trait that represents a hashable type. The `S` type parameter is an
/// abstract hash state that is used by the `Hash` to compute the hash.
/// It defaults to `std::hash::sip::SipState`.
pub trait Hash<S = sip::SipState> {
    /// Compute a hash of the value.
    fn hash(&self, state: &mut S);
}

/// A trait that computes a hash for a value. The main users of this trait are
/// containers like `HashMap`, which need a generic way hash multiple types.
pub trait Hasher<S> {
    /// Compute a hash of the value.
    fn hash<T: Hash<S>>(&self, value: &T) -> u64;
}

//////////////////////////////////////////////////////////////////////////////

macro_rules! impl_hash(
    ( $( $ty:ty => $method:ident;)* ) => (
        $(
            impl<S: Writer> Hash<S> for $ty {
                #[inline]
                fn hash(&self, state: &mut S) {
                    state.$method(*self);
                }
            }
        )*
    )
)

impl_hash!(
    u8 => write_u8;
    u16 => write_le_u16;
    u32 => write_le_u32;
    u64 => write_le_u64;
    uint => write_le_uint;
    i8 => write_i8;
    i16 => write_le_i16;
    i32 => write_le_i32;
    i64 => write_le_i64;
    int => write_le_int;
)

impl<S: Writer> Hash<S> for bool {
    #[inline]
    fn hash(&self, state: &mut S) {
        (*self as u8).hash(state);
    }
}

impl<S: Writer> Hash<S> for char {
    #[inline]
    fn hash(&self, state: &mut S) {
        (*self as u32).hash(state);
    }
}

impl<'a, S: Writer> Hash<S> for &'a str {
    #[inline]
    fn hash(&self, state: &mut S) {
        state.write(self.as_bytes());
        state.write_u8(0xFF);
    }
}

impl<S: Writer> Hash<S> for ~str {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

macro_rules! impl_hash_tuple(
    () => (
        impl<S: Writer> Hash<S> for () {
            #[inline]
            fn hash(&self, state: &mut S) {
                state.write([]);
            }
        }
    );

    ($A:ident $($B:ident)*) => (
        impl<
            S: Writer,
            $A: Hash<S> $(, $B: Hash<S>)*
        > Hash<S> for ($A, $($B),*) {
            #[inline]
            fn hash(&self, state: &mut S) {
                match *self {
                    (ref $A, $(ref $B),*) => {
                        $A.hash(state);
                        $(
                            $B.hash(state);
                        )*
                    }
                }
            }
        }

        impl_hash_tuple!($($B)*)
    );
)

impl_hash_tuple!(A0 A1 A2 A3 A4 A5 A6 A7)

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a [T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.len().hash(state);
        for elt in self.iter() {
            elt.hash(state);
        }
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut [T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for ~[T] {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.as_slice().hash(state);
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<'a, S: Writer, T: Hash<S>> Hash<S> for &'a mut T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for ~T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for @T {
    #[inline]
    fn hash(&self, state: &mut S) {
        (**self).hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        self.borrow().hash(state);
    }
}

impl<S: Writer, T: Hash<S>> Hash<S> for Option<T> {
    #[inline]
    fn hash(&self, state: &mut S) {
        match *self {
            Some(ref x) => {
                0u8.hash(state);
                x.hash(state);
            }
            None => {
                1u8.hash(state);
            }
        }
    }
}

impl<S: Writer, T> Hash<S> for *T {
    #[inline]
    fn hash(&self, state: &mut S) {
        // NB: raw-pointer Hash does _not_ dereference
        // to the target; it just gives you the pointer-bytes.
        (*self as uint).hash(state);
    }
}

impl<S: Writer, T> Hash<S> for *mut T {
    #[inline]
    fn hash(&self, state: &mut S) {
        // NB: raw-pointer Hash does _not_ dereference
        // to the target; it just gives you the pointer-bytes.
        (*self as uint).hash(state);
    }
}

//////////////////////////////////////////////////////////////////////////////

#[cfg(test)]
mod tests {
    use cast;
    use io::{IoResult, Writer};
    use iter::{Iterator};
    use option::{Some, None};
    use result::Ok;
    use vec::ImmutableVector;

    use super::{Hash, Hasher};

    struct MyWriterHasher;

    impl Hasher<MyWriter> for MyWriterHasher {
        fn hash<T: Hash<MyWriter>>(&self, value: &T) -> u64 {
            let mut state = MyWriter { hash: 0 };
            value.hash(&mut state);
            state.hash
        }
    }

    struct MyWriter {
        hash: u64,
    }

    impl Writer for MyWriter {
        // Most things we'll just add up the bytes.
        fn write(&mut self, buf: &[u8]) -> IoResult<()> {
            for byte in buf.iter() {
                self.hash += *byte as u64;
            }
            Ok(())
        }
    }

    #[test]
    fn test_writer_hasher() {
        let hasher = MyWriterHasher;

        assert_eq!(hasher.hash(&()), 0);

        assert_eq!(hasher.hash(&5u8), 5);
        assert_eq!(hasher.hash(&5u16), 5);
        assert_eq!(hasher.hash(&5u32), 5);
        assert_eq!(hasher.hash(&5u64), 5);
        assert_eq!(hasher.hash(&5u), 5);

        assert_eq!(hasher.hash(&5i8), 5);
        assert_eq!(hasher.hash(&5i16), 5);
        assert_eq!(hasher.hash(&5i32), 5);
        assert_eq!(hasher.hash(&5i64), 5);
        assert_eq!(hasher.hash(&5i), 5);

        assert_eq!(hasher.hash(&false), 0);
        assert_eq!(hasher.hash(&true), 1);

        assert_eq!(hasher.hash(&'a'), 97);

        assert_eq!(hasher.hash(& &"a"), 97 + 0xFF);
        assert_eq!(hasher.hash(& &[1u8, 2u8, 3u8]), 9);

        unsafe {
            let ptr: *int = cast::transmute(5);
            assert_eq!(hasher.hash(&ptr), 5);
        }

        unsafe {
            let ptr: *mut int = cast::transmute(5);
            assert_eq!(hasher.hash(&ptr), 5);
        }
    }

    struct Custom {
        hash: u64
    }

    impl Hash<u64> for Custom {
        fn hash(&self, state: &mut u64) {
            *state = self.hash;
        }
    }

    #[test]
    fn test_custom_state() {
        let custom = Custom { hash: 5 };
        let mut state = 0;
        custom.hash(&mut state);
        assert_eq!(state, 5);
    }
}
<|endoftext|>


<commit_before>use std::env;

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    let target = env::var("TARGET").expect("TARGET was not set");

    if cfg!(feature = "llvm-libunwind")
        && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
    {
        // Build the unwinding from libunwind C/C++ source code.
        llvm_libunwind::compile();
    } else if target.contains("linux") {
        if target.contains("musl") {
            // linking for musl is handled in lib.rs
            llvm_libunwind::compile();
        } else if !target.contains("android") {
            println!("cargo:rustc-link-lib=gcc_s");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("rumprun") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("netbsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("openbsd") {
        if target.contains("sparc64") {
            println!("cargo:rustc-link-lib=gcc");
        } else {
            println!("cargo:rustc-link-lib=c++abi");
        }
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("illumos") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("dragonfly") {
        println!("cargo:rustc-link-lib=gcc_pic");
    } else if target.contains("pc-windows-gnu") {
        // This is handled in the target spec with late_link_args_[static|dynamic]

        // cfg!(bootstrap) doesn't work in build scripts
        if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) {
            println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
            println!("cargo:rustc-link-lib=static-nobundle=pthread");
        }
    } else if target.contains("uwp-windows-gnu") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("fuchsia") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("haiku") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("redox") {
        // redox is handled in lib.rs
    } else if target.contains("cloudabi") {
        println!("cargo:rustc-link-lib=unwind");
    }
}

mod llvm_libunwind {
    use std::env;
    use std::path::Path;

    /// Compile the libunwind C/C++ source code.
    pub fn compile() {
        let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
        let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
        let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big";
        let cfg = &mut cc::Build::new();

        cfg.cpp(true);
        cfg.cpp_set_stdlib(None);
        cfg.warnings(false);

        // libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
        if target_endian_little {
            cfg.define("__LITTLE_ENDIAN__", Some("1"));
        }

        if target_env == "msvc" {
            // Don't pull in extra libraries on MSVC
            cfg.flag("/Zl");
            cfg.flag("/EHsc");
            cfg.define("_CRT_SECURE_NO_WARNINGS", None);
            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
        } else {
            cfg.flag("-std=c99");
            cfg.flag("-std=c++11");
            cfg.flag("-nostdinc++");
            cfg.flag("-fno-exceptions");
            cfg.flag("-fno-rtti");
            cfg.flag("-fstrict-aliasing");
            cfg.flag("-funwind-tables");
            cfg.flag("-fvisibility=hidden");
        }

        let mut unwind_sources = vec![
            "Unwind-EHABI.cpp",
            "Unwind-seh.cpp",
            "Unwind-sjlj.c",
            "UnwindLevel1-gcc-ext.c",
            "UnwindLevel1.c",
            "UnwindRegistersRestore.S",
            "UnwindRegistersSave.S",
            "libunwind.cpp",
        ];

        if target_vendor == "apple" {
            unwind_sources.push("Unwind_AppleExtras.cpp");
        }

        let root = Path::new("../llvm-project/libunwind");
        cfg.include(root.join("include"));
        for src in unwind_sources {
            cfg.file(root.join("src").join(src));
        }

        if target_env == "musl" {
            // use the same C compiler command to compile C++ code so we do not need to setup the
            // C++ compiler env variables on the builders
            cfg.cpp(false);
            // linking for musl is handled in lib.rs
            cfg.cargo_metadata(false);
            println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
        }

        cfg.compile("unwind");
    }
}
<commit_msg>Remove missed `cfg(bootstrap)`<commit_after>use std::env;

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    let target = env::var("TARGET").expect("TARGET was not set");

    if cfg!(feature = "llvm-libunwind")
        && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
    {
        // Build the unwinding from libunwind C/C++ source code.
        llvm_libunwind::compile();
    } else if target.contains("linux") {
        if target.contains("musl") {
            // linking for musl is handled in lib.rs
            llvm_libunwind::compile();
        } else if !target.contains("android") {
            println!("cargo:rustc-link-lib=gcc_s");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("rumprun") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("netbsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("openbsd") {
        if target.contains("sparc64") {
            println!("cargo:rustc-link-lib=gcc");
        } else {
            println!("cargo:rustc-link-lib=c++abi");
        }
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("illumos") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("dragonfly") {
        println!("cargo:rustc-link-lib=gcc_pic");
    } else if target.contains("pc-windows-gnu") {
        // This is handled in the target spec with late_link_args_[static|dynamic]
    } else if target.contains("uwp-windows-gnu") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("fuchsia") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("haiku") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("redox") {
        // redox is handled in lib.rs
    } else if target.contains("cloudabi") {
        println!("cargo:rustc-link-lib=unwind");
    }
}

mod llvm_libunwind {
    use std::env;
    use std::path::Path;

    /// Compile the libunwind C/C++ source code.
    pub fn compile() {
        let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
        let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
        let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big";
        let cfg = &mut cc::Build::new();

        cfg.cpp(true);
        cfg.cpp_set_stdlib(None);
        cfg.warnings(false);

        // libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
        if target_endian_little {
            cfg.define("__LITTLE_ENDIAN__", Some("1"));
        }

        if target_env == "msvc" {
            // Don't pull in extra libraries on MSVC
            cfg.flag("/Zl");
            cfg.flag("/EHsc");
            cfg.define("_CRT_SECURE_NO_WARNINGS", None);
            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
        } else {
            cfg.flag("-std=c99");
            cfg.flag("-std=c++11");
            cfg.flag("-nostdinc++");
            cfg.flag("-fno-exceptions");
            cfg.flag("-fno-rtti");
            cfg.flag("-fstrict-aliasing");
            cfg.flag("-funwind-tables");
            cfg.flag("-fvisibility=hidden");
        }

        let mut unwind_sources = vec![
            "Unwind-EHABI.cpp",
            "Unwind-seh.cpp",
            "Unwind-sjlj.c",
            "UnwindLevel1-gcc-ext.c",
            "UnwindLevel1.c",
            "UnwindRegistersRestore.S",
            "UnwindRegistersSave.S",
            "libunwind.cpp",
        ];

        if target_vendor == "apple" {
            unwind_sources.push("Unwind_AppleExtras.cpp");
        }

        let root = Path::new("../llvm-project/libunwind");
        cfg.include(root.join("include"));
        for src in unwind_sources {
            cfg.file(root.join("src").join(src));
        }

        if target_env == "musl" {
            // use the same C compiler command to compile C++ code so we do not need to setup the
            // C++ compiler env variables on the builders
            cfg.cpp(false);
            // linking for musl is handled in lib.rs
            cfg.cargo_metadata(false);
            println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
        }

        cfg.compile("unwind");
    }
}
<|endoftext|>


<commit_before>use core::ops::{Add, Mul, Sub};

macro_rules! overflowing_impl {
    ($trait_name:ident, $method:ident, $t:ty) => {
        impl $trait_name for $t {
            #[inline]
            fn $method(&self, v: &Self) -> (Self, bool) {
                <$t>::$method(*self, *v)
            }
        }
    };
}

/// If an overflow would have occurred then the wrapped value is returned.
pub trait OverflowingAdd: Sized + Add<Self, Output = Self> {
    /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
    fn overflowing_add(&self, v: &Self) -> (Self, bool);
}

overflowing_impl!(OverflowingAdd, overflowing_add, u8);
overflowing_impl!(OverflowingAdd, overflowing_add, u16);
overflowing_impl!(OverflowingAdd, overflowing_add, u32);
overflowing_impl!(OverflowingAdd, overflowing_add, u64);
overflowing_impl!(OverflowingAdd, overflowing_add, usize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingAdd, overflowing_add, u128);

overflowing_impl!(OverflowingAdd, overflowing_add, i8);
overflowing_impl!(OverflowingAdd, overflowing_add, i16);
overflowing_impl!(OverflowingAdd, overflowing_add, i32);
overflowing_impl!(OverflowingAdd, overflowing_add, i64);
overflowing_impl!(OverflowingAdd, overflowing_add, isize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingAdd, overflowing_add, i128);

/// If an overflow would have occurred then the wrapped value is returned.
pub trait OverflowingSub: Sized + Sub<Self, Output = Self> {
    /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
    fn overflowing_sub(&self, v: &Self) -> (Self, bool);
}

overflowing_impl!(OverflowingSub, overflowing_sub, u8);
overflowing_impl!(OverflowingSub, overflowing_sub, u16);
overflowing_impl!(OverflowingSub, overflowing_sub, u32);
overflowing_impl!(OverflowingSub, overflowing_sub, u64);
overflowing_impl!(OverflowingSub, overflowing_sub, usize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingSub, overflowing_sub, u128);

overflowing_impl!(OverflowingSub, overflowing_sub, i8);
overflowing_impl!(OverflowingSub, overflowing_sub, i16);
overflowing_impl!(OverflowingSub, overflowing_sub, i32);
overflowing_impl!(OverflowingSub, overflowing_sub, i64);
overflowing_impl!(OverflowingSub, overflowing_sub, isize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingSub, overflowing_sub, i128);

/// If an overflow would have occurred then the wrapped value is returned.
pub trait OverflowingMul: Sized + Mul<Self, Output = Self> {
    /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
    fn overflowing_mul(&self, v: &Self) -> (Self, bool);
}

overflowing_impl!(OverflowingMul, overflowing_mul, u8);
overflowing_impl!(OverflowingMul, overflowing_mul, u16);
overflowing_impl!(OverflowingMul, overflowing_mul, u32);
overflowing_impl!(OverflowingMul, overflowing_mul, u64);
overflowing_impl!(OverflowingMul, overflowing_mul, usize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingMul, overflowing_mul, u128);

overflowing_impl!(OverflowingMul, overflowing_mul, i8);
overflowing_impl!(OverflowingMul, overflowing_mul, i16);
overflowing_impl!(OverflowingMul, overflowing_mul, i32);
overflowing_impl!(OverflowingMul, overflowing_mul, i64);
overflowing_impl!(OverflowingMul, overflowing_mul, isize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingMul, overflowing_mul, i128);

#[test]
fn test_overflowing_traits() {
    fn overflowing_add<T: OverflowingAdd>(a: T, b: T) -> (T, bool) {
        a.overflowing_add(&b)
    }
    fn overflowing_sub<T: OverflowingSub>(a: T, b: T) -> (T, bool) {
        a.overflowing_sub(&b)
    }
    fn overflowing_mul<T: OverflowingMul>(a: T, b: T) -> (T, bool) {
        a.overflowing_mul(&b)
    }
    assert_eq!(overflowing_add(5i16, 2), (7, false));
    assert_eq!(overflowing_add(std::i16::MAX, 1), (std::i16::MIN, true));
    assert_eq!(overflowing_sub(5i16, 2), (3, false));
    assert_eq!(overflowing_sub(std::i16::MIN, 1), (std::i16::MAX, true));
    assert_eq!(overflowing_mul(5i16, 2), (10, false));
    assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true));
}
<commit_msg>Remove std dep from integer MAX, MIN<commit_after>use core::ops::{Add, Mul, Sub};
#[cfg(has_i128)]
use core::{i128, u128};
use core::{i16, i32, i64, i8, isize};
use core::{u16, u32, u64, u8, usize};

macro_rules! overflowing_impl {
    ($trait_name:ident, $method:ident, $t:ty) => {
        impl $trait_name for $t {
            #[inline]
            fn $method(&self, v: &Self) -> (Self, bool) {
                <$t>::$method(*self, *v)
            }
        }
    };
}

/// If an overflow would have occurred then the wrapped value is returned.
pub trait OverflowingAdd: Sized + Add<Self, Output = Self> {
    /// Returns a tuple of the addition along with a boolean indicating whether an arithmetic overflow would occur.
    fn overflowing_add(&self, v: &Self) -> (Self, bool);
}

overflowing_impl!(OverflowingAdd, overflowing_add, u8);
overflowing_impl!(OverflowingAdd, overflowing_add, u16);
overflowing_impl!(OverflowingAdd, overflowing_add, u32);
overflowing_impl!(OverflowingAdd, overflowing_add, u64);
overflowing_impl!(OverflowingAdd, overflowing_add, usize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingAdd, overflowing_add, u128);

overflowing_impl!(OverflowingAdd, overflowing_add, i8);
overflowing_impl!(OverflowingAdd, overflowing_add, i16);
overflowing_impl!(OverflowingAdd, overflowing_add, i32);
overflowing_impl!(OverflowingAdd, overflowing_add, i64);
overflowing_impl!(OverflowingAdd, overflowing_add, isize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingAdd, overflowing_add, i128);

/// If an overflow would have occurred then the wrapped value is returned.
pub trait OverflowingSub: Sized + Sub<Self, Output = Self> {
    /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
    fn overflowing_sub(&self, v: &Self) -> (Self, bool);
}

overflowing_impl!(OverflowingSub, overflowing_sub, u8);
overflowing_impl!(OverflowingSub, overflowing_sub, u16);
overflowing_impl!(OverflowingSub, overflowing_sub, u32);
overflowing_impl!(OverflowingSub, overflowing_sub, u64);
overflowing_impl!(OverflowingSub, overflowing_sub, usize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingSub, overflowing_sub, u128);

overflowing_impl!(OverflowingSub, overflowing_sub, i8);
overflowing_impl!(OverflowingSub, overflowing_sub, i16);
overflowing_impl!(OverflowingSub, overflowing_sub, i32);
overflowing_impl!(OverflowingSub, overflowing_sub, i64);
overflowing_impl!(OverflowingSub, overflowing_sub, isize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingSub, overflowing_sub, i128);

/// If an overflow would have occurred then the wrapped value is returned.
pub trait OverflowingMul: Sized + Mul<Self, Output = Self> {
    /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow would occur.
    fn overflowing_mul(&self, v: &Self) -> (Self, bool);
}

overflowing_impl!(OverflowingMul, overflowing_mul, u8);
overflowing_impl!(OverflowingMul, overflowing_mul, u16);
overflowing_impl!(OverflowingMul, overflowing_mul, u32);
overflowing_impl!(OverflowingMul, overflowing_mul, u64);
overflowing_impl!(OverflowingMul, overflowing_mul, usize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingMul, overflowing_mul, u128);

overflowing_impl!(OverflowingMul, overflowing_mul, i8);
overflowing_impl!(OverflowingMul, overflowing_mul, i16);
overflowing_impl!(OverflowingMul, overflowing_mul, i32);
overflowing_impl!(OverflowingMul, overflowing_mul, i64);
overflowing_impl!(OverflowingMul, overflowing_mul, isize);
#[cfg(has_i128)]
overflowing_impl!(OverflowingMul, overflowing_mul, i128);

#[test]
fn test_overflowing_traits() {
    fn overflowing_add<T: OverflowingAdd>(a: T, b: T) -> (T, bool) {
        a.overflowing_add(&b)
    }
    fn overflowing_sub<T: OverflowingSub>(a: T, b: T) -> (T, bool) {
        a.overflowing_sub(&b)
    }
    fn overflowing_mul<T: OverflowingMul>(a: T, b: T) -> (T, bool) {
        a.overflowing_mul(&b)
    }
    assert_eq!(overflowing_add(5i16, 2), (7, false));
    assert_eq!(overflowing_add(i16::MAX, 1), (i16::MIN, true));
    assert_eq!(overflowing_sub(5i16, 2), (3, false));
    assert_eq!(overflowing_sub(i16::MIN, 1), (i16::MAX, true));
    assert_eq!(overflowing_mul(5i16, 2), (10, false));
    assert_eq!(overflowing_mul(1_000_000_000i32, 10), (1410065408, true));
}
<|endoftext|>


<commit_before>use super::internal::*;
use super::*;
use std::cmp::min;

/// Test if a byte is the start of a UTF-8 character.
/// (extracted from `str::is_char_boundary`)
fn is_char_boundary(b: u8) -> bool {
    // This is bit magic equivalent to: b < 128 || b >= 192
    (b as i8) >= -0x40
}

/// Find the index of a character boundary near the midpoint.
fn find_char_midpoint(chars: &str) -> usize {
    let mid = chars.len() / 2;

    // We want to split near the midpoint, but we need to find an actual
    // character boundary.  So we look at the raw bytes, first scanning
    // forward from the midpoint for a boundary, then trying backward.
    let (left, right) = chars.as_bytes().split_at(mid);
    right.iter()
        .cloned()
        .position(is_char_boundary)
        .map(|i| mid + i)
        .or_else(|| left.iter().cloned().rposition(is_char_boundary))
        .unwrap_or(0)
}

/// Parallel extensions for strings.
pub trait ParallelString {
    /// Returns a parallel iterator over the characters of a string.
    fn par_chars(&self) -> ParChars;

    /// Returns a parallel iterator over substrings separated by a
    /// given character, similar to `str::split`.
    fn par_split(&self, char) -> ParSplit;

    /// Returns a parallel iterator over substrings terminated by a
    /// given character, similar to `str::split_terminator`.  It's
    /// equivalent to `par_split`, except it doesn't produce an empty
    /// substring after a trailing terminator.
    fn par_split_terminator(&self, char) -> ParSplitTerminator;

    /// Returns a parallel iterator over the lines of a string, ending with an
    /// optional carriage return and with a newline (`\r\n` or just `\n`).
    /// The final line ending is optional, and line endings are not included in
    /// the output strings.
    fn par_lines(&self) -> ParLines;
}

impl ParallelString for str {
    fn par_chars(&self) -> ParChars {
        ParChars { chars: self }
    }

    fn par_split(&self, separator: char) -> ParSplit {
        ParSplit::new(self, separator)
    }

    fn par_split_terminator(&self, terminator: char) -> ParSplitTerminator {
        ParSplitTerminator::new(self, terminator)
    }

    fn par_lines(&self) -> ParLines {
        ParLines(self)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParChars<'ch> {
    chars: &'ch str,
}

impl<'ch> ParallelIterator for ParChars<'ch> {
    type Item = char;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'ch> UnindexedProducer for ParChars<'ch> {
    type Item = char;

    fn split(&mut self) -> Option<Self> {
        let index = find_char_midpoint(self.chars);
        if index > 0 {
            let (left, right) = self.chars.split_at(index);
            self.chars = left;
            Some(ParChars { chars: right })
        } else {
            None
        }
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        folder.consume_iter(self.chars.chars())
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplit<'ch> {
    chars: &'ch str,
    separator: char,
}

pub struct ParSplitProducer<'ch, 'sep> {
    chars: &'ch str,
    separator: &'sep char,

    /// Marks the endpoint beyond which we've already found no separators.
    tail: usize,
}

impl<'ch> ParSplit<'ch> {
    fn new(chars: &'ch str, separator: char) -> Self {
        ParSplit {
            chars: chars,
            separator: separator,
        }
    }
}

impl<'ch, 'sep> ParSplitProducer<'ch, 'sep> {
    fn new(split: &'sep ParSplit<'ch>) -> Self {
        ParSplitProducer {
            chars: split.chars,
            separator: &split.separator,
            tail: split.chars.len(),
        }
    }

    /// Common `fold_with` implementation, integrating `ParSplitTerminator`'s
    /// need to sometimes skip its final empty item.
    fn fold_with<F>(self, folder: F, skip_last: bool) -> F
        where F: Folder<<Self as UnindexedProducer>::Item>
    {
        let ParSplitProducer { chars, separator, tail } = self;

        if tail == chars.len() {
            // No tail section, so just let `str::split` handle it.
            let mut split = chars.split(*separator);
            if skip_last {
                split.next_back();
            }
            folder.consume_iter(split)

        } else if let Some(index) = chars[..tail].rfind(*separator) {
            // We found the last separator to complete the tail, so
            // end with that slice after `str::split` finds the rest.
            let head = &chars[..index];
            let folder = folder.consume_iter(head.split(*separator));
            if skip_last || folder.full() {
                folder
            } else {
                let last = &chars[index + separator.len_utf8()..];
                folder.consume(last)
            }

        } else {
            // We know there are no separators at all.  Return our whole string.
            if skip_last {
                folder
            } else {
                folder.consume(chars)
            }
        }
    }
}

impl<'ch> ParallelIterator for ParSplit<'ch> {
    type Item = &'ch str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let producer = ParSplitProducer::new(&self);
        bridge_unindexed(producer, consumer)
    }
}

impl<'ch, 'sep> UnindexedProducer for ParSplitProducer<'ch, 'sep> {
    type Item = &'ch str;

    fn split(&mut self) -> Option<Self> {
        let ParSplitProducer { chars, separator, tail } = *self;

        // First find a suitable UTF-8 boundary in the unsearched region.
        let char_index = find_char_midpoint(&chars[..tail]);

        // Look forward for the separator, and failing that look backward.
        let index = chars[char_index..tail]
            .find(*separator)
            .map(|i| char_index + i)
            .or_else(|| chars[..char_index].rfind(*separator));

        if let Some(index) = index {
            // Update `self` as the region before the separator.
            self.chars = &chars[..index];
            self.tail = min(char_index, index);

            // Create the right split following the separator.
            let right_index = index + separator.len_utf8();
            let mut right = ParSplitProducer {
                chars: &chars[right_index..],
                separator: separator,
                tail: tail - right_index,
            };

            // If we scanned backwards to find the separator, everything in
            // the right side is exhausted, with no separators left to find.
            if index < char_index {
                right.tail = 0;
            }

            Some(right)

        } else {
            self.tail = 0;
            None
        }
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        self.fold_with(folder, false)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplitTerminator<'ch> {
    splitter: ParSplit<'ch>,
}

pub struct ParSplitTerminatorProducer<'ch, 'sep> {
    splitter: ParSplitProducer<'ch, 'sep>,
    endpoint: bool,
}

impl<'ch> ParSplitTerminator<'ch> {
    fn new(chars: &'ch str, terminator: char) -> Self {
        ParSplitTerminator {
            splitter: ParSplit::new(chars, terminator),
        }
    }
}

impl<'ch, 'sep> ParSplitTerminatorProducer<'ch, 'sep> {
    fn new(split: &'sep ParSplitTerminator<'ch>) -> Self {
        ParSplitTerminatorProducer {
            splitter: ParSplitProducer::new(&split.splitter),
            endpoint: true,
        }
    }
}

impl<'ch> ParallelIterator for ParSplitTerminator<'ch> {
    type Item = &'ch str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let producer = ParSplitTerminatorProducer::new(&self);
        bridge_unindexed(producer, consumer)
    }
}

impl<'ch, 'sep> UnindexedProducer for ParSplitTerminatorProducer<'ch, 'sep> {
    type Item = &'ch str;

    fn split(&mut self) -> Option<Self> {
        self.splitter.split().map(|right| {
            let endpoint = self.endpoint;
            self.endpoint = false;
            ParSplitTerminatorProducer {
                splitter: right,
                endpoint: endpoint,
            }
        })
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        // See if we need to eat the empty trailing substring
        let skip_last = if self.endpoint {
            let chars = self.splitter.chars;
            let terminator = self.splitter.separator;
            chars.is_empty() || chars.ends_with(*terminator)
        } else {
            false
        };

        self.splitter.fold_with(folder, skip_last)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParLines<'ch>(&'ch str);

impl<'ch> ParallelIterator for ParLines<'ch> {
    type Item = &'ch str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        self.0
            .par_split_terminator('\n')
            .map(|line| {
                if line.ends_with('\r') {
                    &line[..line.len() - 1]
                } else {
                    line
                }
            })
            .drive_unindexed(consumer)
    }
}
<commit_msg>Add a Pattern abstraction to the ParSplit separator<commit_after>use super::internal::*;
use super::*;
use std::cmp::min;

/// Test if a byte is the start of a UTF-8 character.
/// (extracted from `str::is_char_boundary`)
fn is_char_boundary(b: u8) -> bool {
    // This is bit magic equivalent to: b < 128 || b >= 192
    (b as i8) >= -0x40
}

/// Find the index of a character boundary near the midpoint.
fn find_char_midpoint(chars: &str) -> usize {
    let mid = chars.len() / 2;

    // We want to split near the midpoint, but we need to find an actual
    // character boundary.  So we look at the raw bytes, first scanning
    // forward from the midpoint for a boundary, then trying backward.
    let (left, right) = chars.as_bytes().split_at(mid);
    right.iter()
        .cloned()
        .position(is_char_boundary)
        .map(|i| mid + i)
        .or_else(|| left.iter().cloned().rposition(is_char_boundary))
        .unwrap_or(0)
}

/// Parallel extensions for strings.
pub trait ParallelString {
    /// Returns a parallel iterator over the characters of a string.
    fn par_chars(&self) -> ParChars;

    /// Returns a parallel iterator over substrings separated by a
    /// given character, similar to `str::split`.
    fn par_split<P: Pattern>(&self, P) -> ParSplit<P>;

    /// Returns a parallel iterator over substrings terminated by a
    /// given character, similar to `str::split_terminator`.  It's
    /// equivalent to `par_split`, except it doesn't produce an empty
    /// substring after a trailing terminator.
    fn par_split_terminator<P: Pattern>(&self, P) -> ParSplitTerminator<P>;

    /// Returns a parallel iterator over the lines of a string, ending with an
    /// optional carriage return and with a newline (`\r\n` or just `\n`).
    /// The final line ending is optional, and line endings are not included in
    /// the output strings.
    fn par_lines(&self) -> ParLines;
}

impl ParallelString for str {
    fn par_chars(&self) -> ParChars {
        ParChars { chars: self }
    }

    fn par_split<P: Pattern>(&self, separator: P) -> ParSplit<P> {
        ParSplit::new(self, separator)
    }

    fn par_split_terminator<P: Pattern>(&self, terminator: P) -> ParSplitTerminator<P> {
        ParSplitTerminator::new(self, terminator)
    }

    fn par_lines(&self) -> ParLines {
        ParLines(self)
    }
}

// /////////////////////////////////////////////////////////////////////////

/// Pattern-matching trait for `ParallelString`, somewhat like a mix of
/// `std::str::pattern::{Pattern, Searcher}`.
pub trait Pattern: Sized + Sync {
    fn find_in(&self, &str) -> Option<usize>;
    fn rfind_in(&self, &str) -> Option<usize>;
    fn is_suffix_of(&self, &str) -> bool;
    fn fold_with<'ch, F>(&self, &'ch str, folder: F, skip_last: bool) -> F
        where F: Folder<&'ch str>;
}

impl Pattern for char {
    fn find_in(&self, chars: &str) -> Option<usize> {
        chars.find(*self)
    }

    fn rfind_in(&self, chars: &str) -> Option<usize> {
        chars.rfind(*self)
    }

    fn is_suffix_of(&self, chars: &str) -> bool {
        chars.ends_with(*self)
    }

    fn fold_with<'ch, F>(&self, chars: &'ch str, folder: F, skip_last: bool) -> F
        where F: Folder<&'ch str>
    {
        let mut split = chars.split(*self);
        if skip_last {
            split.next_back();
        }
        folder.consume_iter(split)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParChars<'ch> {
    chars: &'ch str,
}

impl<'ch> ParallelIterator for ParChars<'ch> {
    type Item = char;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'ch> UnindexedProducer for ParChars<'ch> {
    type Item = char;

    fn split(&mut self) -> Option<Self> {
        let index = find_char_midpoint(self.chars);
        if index > 0 {
            let (left, right) = self.chars.split_at(index);
            self.chars = left;
            Some(ParChars { chars: right })
        } else {
            None
        }
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        folder.consume_iter(self.chars.chars())
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplit<'ch, P: Pattern> {
    chars: &'ch str,
    separator: P,
}

pub struct ParSplitProducer<'ch, 'sep, P: Pattern + 'sep> {
    chars: &'ch str,
    separator: &'sep P,

    /// Marks the endpoint beyond which we've already found no separators.
    tail: usize,
}

impl<'ch, P: Pattern> ParSplit<'ch, P> {
    fn new(chars: &'ch str, separator: P) -> Self {
        ParSplit {
            chars: chars,
            separator: separator,
        }
    }
}

impl<'ch, 'sep, P: Pattern + 'sep> ParSplitProducer<'ch, 'sep, P> {
    fn new(split: &'sep ParSplit<'ch, P>) -> Self {
        ParSplitProducer {
            chars: split.chars,
            separator: &split.separator,
            tail: split.chars.len(),
        }
    }

    /// Common `fold_with` implementation, integrating `ParSplitTerminator`'s
    /// need to sometimes skip its final empty item.
    fn fold_with<F>(self, folder: F, skip_last: bool) -> F
        where F: Folder<<Self as UnindexedProducer>::Item>
    {
        let ParSplitProducer { chars, separator, tail } = self;

        if tail == chars.len() {
            // No tail section, so just let `str::split` handle it.
            separator.fold_with(chars, folder, skip_last)

        } else if let Some(index) = separator.rfind_in(&chars[..tail]) {
            // We found the last separator to complete the tail, so
            // end with that slice after `str::split` finds the rest.
            let (left, right) = chars.split_at(index);
            let folder = separator.fold_with(left, folder, false);
            if skip_last || folder.full() {
                folder
            } else {
                let mut right_iter = right.chars();
                right_iter.next(); // skip the separator
                folder.consume(right_iter.as_str())
            }

        } else {
            // We know there are no separators at all.  Return our whole string.
            if skip_last {
                folder
            } else {
                folder.consume(chars)
            }
        }
    }
}

impl<'ch, P: Pattern> ParallelIterator for ParSplit<'ch, P> {
    type Item = &'ch str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let producer = ParSplitProducer::new(&self);
        bridge_unindexed(producer, consumer)
    }
}

impl<'ch, 'sep, P: Pattern + 'sep> UnindexedProducer for ParSplitProducer<'ch, 'sep, P> {
    type Item = &'ch str;

    fn split(&mut self) -> Option<Self> {
        let ParSplitProducer { chars, separator, tail } = *self;

        // First find a suitable UTF-8 boundary in the unsearched region.
        let char_index = find_char_midpoint(&chars[..tail]);

        // Look forward for the separator, and failing that look backward.
        let index = separator.find_in(&chars[char_index..tail])
            .map(|i| char_index + i)
            .or_else(|| separator.rfind_in(&chars[..char_index]));

        if let Some(index) = index {
            let (left, right) = chars.split_at(index);

            // Update `self` as the region before the separator.
            self.chars = left;
            self.tail = min(char_index, index);

            // Create the right split following the separator.
            let mut right_iter = right.chars();
            right_iter.next(); // skip the separator
            let right_chars = right_iter.as_str();
            let right_index = chars.len() - right_chars.len();

            let mut right = ParSplitProducer {
                chars: right_chars,
                separator: separator,
                tail: tail - right_index,
            };

            // If we scanned backwards to find the separator, everything in
            // the right side is exhausted, with no separators left to find.
            if index < char_index {
                right.tail = 0;
            }

            Some(right)

        } else {
            self.tail = 0;
            None
        }
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        self.fold_with(folder, false)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplitTerminator<'ch, P: Pattern> {
    splitter: ParSplit<'ch, P>,
}

pub struct ParSplitTerminatorProducer<'ch, 'sep, P: Pattern + 'sep> {
    splitter: ParSplitProducer<'ch, 'sep, P>,
    endpoint: bool,
}

impl<'ch, P: Pattern> ParSplitTerminator<'ch, P> {
    fn new(chars: &'ch str, terminator: P) -> Self {
        ParSplitTerminator {
            splitter: ParSplit::new(chars, terminator),
        }
    }
}

impl<'ch, 'sep, P: Pattern + 'sep> ParSplitTerminatorProducer<'ch, 'sep, P> {
    fn new(split: &'sep ParSplitTerminator<'ch, P>) -> Self {
        ParSplitTerminatorProducer {
            splitter: ParSplitProducer::new(&split.splitter),
            endpoint: true,
        }
    }
}

impl<'ch, P: Pattern> ParallelIterator for ParSplitTerminator<'ch, P> {
    type Item = &'ch str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let producer = ParSplitTerminatorProducer::new(&self);
        bridge_unindexed(producer, consumer)
    }
}

impl<'ch, 'sep, P: Pattern + 'sep> UnindexedProducer for ParSplitTerminatorProducer<'ch, 'sep, P> {
    type Item = &'ch str;

    fn split(&mut self) -> Option<Self> {
        self.splitter.split().map(|right| {
            let endpoint = self.endpoint;
            self.endpoint = false;
            ParSplitTerminatorProducer {
                splitter: right,
                endpoint: endpoint,
            }
        })
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        // See if we need to eat the empty trailing substring
        let skip_last = if self.endpoint {
            let chars = self.splitter.chars;
            let terminator = self.splitter.separator;
            chars.is_empty() || terminator.is_suffix_of(chars)
        } else {
            false
        };

        self.splitter.fold_with(folder, skip_last)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParLines<'ch>(&'ch str);

impl<'ch> ParallelIterator for ParLines<'ch> {
    type Item = &'ch str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        self.0
            .par_split_terminator('\n')
            .map(|line| {
                if line.ends_with('\r') {
                    &line[..line.len() - 1]
                } else {
                    line
                }
            })
            .drive_unindexed(consumer)
    }
}
<|endoftext|>