<commit_before>// Copyright (c) 2020 rust-mysql-simple contributors
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use mysql_common::row::convert::FromRowError;

use std::{borrow::Cow, result::Result as StdResult};

use crate::{
    conn::query_result::{Binary, Text},
    from_row, from_row_opt,
    prelude::FromRow,
    Params, QueryResult, Result, Statement,
};

/// Something, that eventualy is a `Statement` in the context of a `T: Queryable`.
pub trait AsStatement {
    /// Make a statement out of `Self`.
    fn as_statement<Q: Queryable>(&self, queryable: &mut Q) -> Result<Cow<'_, Statement>>;
}

/// Queryable object.
pub trait Queryable {
    /// Perfoms text query.
    fn query_iter<Q: AsRef<str>>(&mut self, query: Q) -> Result<QueryResult<'_, '_, '_, Text>>;

    /// Performs text query and collects the first result set.
    fn query<T, Q>(&mut self, query: Q) -> Result<Vec<T>>
    where
        Q: AsRef<str>,
        T: FromRow,
    {
        self.query_map(query, from_row)
    }

    /// Same as [`Queryable::query`] but useful when you not sure what your schema is.
    fn query_opt<T, Q>(&mut self, query: Q) -> Result<Vec<StdResult<T, FromRowError>>>
    where
        Q: AsRef<str>,
        T: FromRow,
    {
        self.query_map(query, from_row_opt)
    }

    /// Performs text query and returns the firt row of the first result set.
    fn query_first<T, Q>(&mut self, query: Q) -> Result<Option<T>>
    where
        Q: AsRef<str>,
        T: FromRow,
    {
        self.query_iter(query)?
            .next()
            .map(|row| row.map(from_row))
            .transpose()
    }

    /// Same as [`Queryable::query_first`] but useful when you not sure what your schema is.
    fn query_first_opt<T, Q>(&mut self, query: Q) -> Result<Option<StdResult<T, FromRowError>>>
    where
        Q: AsRef<str>,
        T: FromRow,
    {
        self.query_iter(query)?
            .next()
            .map(|row| row.map(from_row_opt))
            .transpose()
    }

    /// Performs text query and maps each row of the first result set.
    fn query_map<T, F, Q, U>(&mut self, query: Q, mut f: F) -> Result<Vec<U>>
    where
        Q: AsRef<str>,
        T: FromRow,
        F: FnMut(T) -> U,
    {
        self.query_fold(query, Vec::new(), |mut acc, row| {
            acc.push(f(row));
            acc
        })
    }

    /// Same as [`Queryable::query_map`] but useful when you not sure what your schema is.
    fn query_map_opt<T, F, Q, U>(&mut self, query: Q, mut f: F) -> Result<Vec<U>>
    where
        Q: AsRef<str>,
        T: FromRow,
        F: FnMut(StdResult<T, FromRowError>) -> U,
    {
        self.query_fold_opt(query, Vec::new(), |mut acc, row| {
            acc.push(f(row));
            acc
        })
    }

    /// Performs text query and folds the first result set to a single value.
    fn query_fold<T, F, Q, U>(&mut self, query: Q, init: U, mut f: F) -> Result<U>
    where
        Q: AsRef<str>,
        T: FromRow,
        F: FnMut(U, T) -> U,
    {
        self.query_iter(query)?
            .map(|row| row.map(from_row::<T>))
            .try_fold(init, |acc, row: Result<T>| row.map(|row| f(acc, row)))
    }

    /// Same as [`Queryable::query_fold`] but useful when you not sure what your schema is.
    fn query_fold_opt<T, F, Q, U>(&mut self, query: Q, init: U, mut f: F) -> Result<U>
    where
        Q: AsRef<str>,
        T: FromRow,
        F: FnMut(U, StdResult<T, FromRowError>) -> U,
    {
        self.query_iter(query)?
            .map(|row| row.map(from_row_opt::<T>))
            .try_fold(init, |acc, row: Result<StdResult<T, FromRowError>>| {
                row.map(|row| f(acc, row))
            })
    }

    /// Performs text query and drops the query result.
    fn query_drop<Q>(&mut self, query: Q) -> Result<()>
    where
        Q: AsRef<str>,
    {
        self.query_iter(query).map(drop)
    }

    /// Prepares the given `query` as a prepared statement.
    fn prep<Q: AsRef<str>>(&mut self, query: Q) -> Result<crate::Statement>;

    /// This function will close the given statement on the server side.
    fn close(&mut self, stmt: Statement) -> Result<()>;

    /// Exectues the given `stmt` with the given `params`.
    fn exec_iter<S, P>(&mut self, stmt: S, params: P) -> Result<QueryResult<'_, '_, '_, Binary>>
    where
        S: AsStatement,
        P: Into<Params>;

    /// Prepares the given statement, and exectues it with each item in the given params iterator.
    fn exec_batch<S, P, I>(&mut self, stmt: S, params: I) -> Result<()>
    where
        Self: Sized,
        S: AsStatement,
        P: Into<Params>,
        I: IntoIterator<Item = P>,
    {
        let stmt = stmt.as_statement(self)?;
        for params in params {
            self.exec_drop(stmt.as_ref(), params)?;
        }

        Ok(())
    }

    /// Exectues the given `stmt` and collects the first result set.
    fn exec<T, S, P>(&mut self, stmt: S, params: P) -> Result<Vec<T>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
    {
        self.exec_map(stmt, params, from_row)
    }

    /// Same as [`Queryable::exec`] but useful when you not sure what your schema is.
    fn exec_opt<T, S, P>(&mut self, stmt: S, params: P) -> Result<Vec<StdResult<T, FromRowError>>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
    {
        self.exec_map(stmt, params, from_row_opt)
    }

    /// Exectues the given `stmt` and returns the first row of the first result set.
    fn exec_first<T, S, P>(&mut self, stmt: S, params: P) -> Result<Option<T>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
    {
        self.exec_iter(stmt, params)?
            .next()
            .map(|row| row.map(crate::from_row))
            .transpose()
    }

    /// Same as [`Queryable::exec_first`] but useful when you not sure what your schema is.
    fn exec_first_opt<T, S, P>(
        &mut self,
        stmt: S,
        params: P,
    ) -> Result<Option<StdResult<T, FromRowError>>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
    {
        self.exec_iter(stmt, params)?
            .next()
            .map(|row| row.map(from_row_opt))
            .transpose()
    }

    /// Exectues the given `stmt` and maps each row of the first result set.
    fn exec_map<T, S, P, F, U>(&mut self, stmt: S, params: P, mut f: F) -> Result<Vec<U>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
        F: FnMut(T) -> U,
    {
        self.exec_fold(stmt, params, Vec::new(), |mut acc, row| {
            acc.push(f(row));
            acc
        })
    }

    /// Same as [`Queryable::exec_map`] but useful when you not sure what your schema is.
    fn exec_map_opt<T, S, P, F, U>(&mut self, stmt: S, params: P, mut f: F) -> Result<Vec<U>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
        F: FnMut(StdResult<T, FromRowError>) -> U,
    {
        self.exec_fold_opt(stmt, params, Vec::new(), |mut acc, row| {
            acc.push(f(row));
            acc
        })
    }

    /// Exectues the given `stmt` and folds the first result set to a signel value.
    fn exec_fold<T, S, P, U, F>(&mut self, stmt: S, params: P, init: U, mut f: F) -> Result<U>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
        F: FnMut(U, T) -> U,
    {
        let mut result = self.exec_iter(stmt, params)?;
        let output = result.try_fold(init, |init, row| row.map(|row| f(init, from_row(row))));
        output
    }

    /// Same as [`Queryable::exec_fold`] but useful when you not sure what your schema is.
    fn exec_fold_opt<T, S, P, U, F>(&mut self, stmt: S, params: P, init: U, mut f: F) -> Result<U>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
        F: FnMut(U, StdResult<T, FromRowError>) -> U,
    {
        let mut result = self.exec_iter(stmt, params)?;
        let output = result.try_fold(init, |init, row| row.map(|row| f(init, from_row_opt(row))));
        output
    }

    /// Exectues the given `stmt` and drops the result.
    fn exec_drop<S, P>(&mut self, stmt: S, params: P) -> Result<()>
    where
        S: AsStatement,
        P: Into<Params>,
    {
        self.exec_iter(stmt, params).map(drop)
    }
}
<commit_msg>Fix typo<commit_after>// Copyright (c) 2020 rust-mysql-simple contributors
//
// 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. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use mysql_common::row::convert::FromRowError;

use std::{borrow::Cow, result::Result as StdResult};

use crate::{
    conn::query_result::{Binary, Text},
    from_row, from_row_opt,
    prelude::FromRow,
    Params, QueryResult, Result, Statement,
};

/// Something, that eventualy is a `Statement` in the context of a `T: Queryable`.
pub trait AsStatement {
    /// Make a statement out of `Self`.
    fn as_statement<Q: Queryable>(&self, queryable: &mut Q) -> Result<Cow<'_, Statement>>;
}

/// Queryable object.
pub trait Queryable {
    /// Perfoms text query.
    fn query_iter<Q: AsRef<str>>(&mut self, query: Q) -> Result<QueryResult<'_, '_, '_, Text>>;

    /// Performs text query and collects the first result set.
    fn query<T, Q>(&mut self, query: Q) -> Result<Vec<T>>
    where
        Q: AsRef<str>,
        T: FromRow,
    {
        self.query_map(query, from_row)
    }

    /// Same as [`Queryable::query`] but useful when you not sure what your schema is.
    fn query_opt<T, Q>(&mut self, query: Q) -> Result<Vec<StdResult<T, FromRowError>>>
    where
        Q: AsRef<str>,
        T: FromRow,
    {
        self.query_map(query, from_row_opt)
    }

    /// Performs text query and returns the firt row of the first result set.
    fn query_first<T, Q>(&mut self, query: Q) -> Result<Option<T>>
    where
        Q: AsRef<str>,
        T: FromRow,
    {
        self.query_iter(query)?
            .next()
            .map(|row| row.map(from_row))
            .transpose()
    }

    /// Same as [`Queryable::query_first`] but useful when you not sure what your schema is.
    fn query_first_opt<T, Q>(&mut self, query: Q) -> Result<Option<StdResult<T, FromRowError>>>
    where
        Q: AsRef<str>,
        T: FromRow,
    {
        self.query_iter(query)?
            .next()
            .map(|row| row.map(from_row_opt))
            .transpose()
    }

    /// Performs text query and maps each row of the first result set.
    fn query_map<T, F, Q, U>(&mut self, query: Q, mut f: F) -> Result<Vec<U>>
    where
        Q: AsRef<str>,
        T: FromRow,
        F: FnMut(T) -> U,
    {
        self.query_fold(query, Vec::new(), |mut acc, row| {
            acc.push(f(row));
            acc
        })
    }

    /// Same as [`Queryable::query_map`] but useful when you not sure what your schema is.
    fn query_map_opt<T, F, Q, U>(&mut self, query: Q, mut f: F) -> Result<Vec<U>>
    where
        Q: AsRef<str>,
        T: FromRow,
        F: FnMut(StdResult<T, FromRowError>) -> U,
    {
        self.query_fold_opt(query, Vec::new(), |mut acc, row| {
            acc.push(f(row));
            acc
        })
    }

    /// Performs text query and folds the first result set to a single value.
    fn query_fold<T, F, Q, U>(&mut self, query: Q, init: U, mut f: F) -> Result<U>
    where
        Q: AsRef<str>,
        T: FromRow,
        F: FnMut(U, T) -> U,
    {
        self.query_iter(query)?
            .map(|row| row.map(from_row::<T>))
            .try_fold(init, |acc, row: Result<T>| row.map(|row| f(acc, row)))
    }

    /// Same as [`Queryable::query_fold`] but useful when you not sure what your schema is.
    fn query_fold_opt<T, F, Q, U>(&mut self, query: Q, init: U, mut f: F) -> Result<U>
    where
        Q: AsRef<str>,
        T: FromRow,
        F: FnMut(U, StdResult<T, FromRowError>) -> U,
    {
        self.query_iter(query)?
            .map(|row| row.map(from_row_opt::<T>))
            .try_fold(init, |acc, row: Result<StdResult<T, FromRowError>>| {
                row.map(|row| f(acc, row))
            })
    }

    /// Performs text query and drops the query result.
    fn query_drop<Q>(&mut self, query: Q) -> Result<()>
    where
        Q: AsRef<str>,
    {
        self.query_iter(query).map(drop)
    }

    /// Prepares the given `query` as a prepared statement.
    fn prep<Q: AsRef<str>>(&mut self, query: Q) -> Result<crate::Statement>;

    /// This function will close the given statement on the server side.
    fn close(&mut self, stmt: Statement) -> Result<()>;

    /// Executes the given `stmt` with the given `params`.
    fn exec_iter<S, P>(&mut self, stmt: S, params: P) -> Result<QueryResult<'_, '_, '_, Binary>>
    where
        S: AsStatement,
        P: Into<Params>;

    /// Prepares the given statement, and executes it with each item in the given params iterator.
    fn exec_batch<S, P, I>(&mut self, stmt: S, params: I) -> Result<()>
    where
        Self: Sized,
        S: AsStatement,
        P: Into<Params>,
        I: IntoIterator<Item = P>,
    {
        let stmt = stmt.as_statement(self)?;
        for params in params {
            self.exec_drop(stmt.as_ref(), params)?;
        }

        Ok(())
    }

    /// Executes the given `stmt` and collects the first result set.
    fn exec<T, S, P>(&mut self, stmt: S, params: P) -> Result<Vec<T>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
    {
        self.exec_map(stmt, params, from_row)
    }

    /// Same as [`Queryable::exec`] but useful when you not sure what your schema is.
    fn exec_opt<T, S, P>(&mut self, stmt: S, params: P) -> Result<Vec<StdResult<T, FromRowError>>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
    {
        self.exec_map(stmt, params, from_row_opt)
    }

    /// Executes the given `stmt` and returns the first row of the first result set.
    fn exec_first<T, S, P>(&mut self, stmt: S, params: P) -> Result<Option<T>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
    {
        self.exec_iter(stmt, params)?
            .next()
            .map(|row| row.map(crate::from_row))
            .transpose()
    }

    /// Same as [`Queryable::exec_first`] but useful when you not sure what your schema is.
    fn exec_first_opt<T, S, P>(
        &mut self,
        stmt: S,
        params: P,
    ) -> Result<Option<StdResult<T, FromRowError>>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
    {
        self.exec_iter(stmt, params)?
            .next()
            .map(|row| row.map(from_row_opt))
            .transpose()
    }

    /// Executes the given `stmt` and maps each row of the first result set.
    fn exec_map<T, S, P, F, U>(&mut self, stmt: S, params: P, mut f: F) -> Result<Vec<U>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
        F: FnMut(T) -> U,
    {
        self.exec_fold(stmt, params, Vec::new(), |mut acc, row| {
            acc.push(f(row));
            acc
        })
    }

    /// Same as [`Queryable::exec_map`] but useful when you not sure what your schema is.
    fn exec_map_opt<T, S, P, F, U>(&mut self, stmt: S, params: P, mut f: F) -> Result<Vec<U>>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
        F: FnMut(StdResult<T, FromRowError>) -> U,
    {
        self.exec_fold_opt(stmt, params, Vec::new(), |mut acc, row| {
            acc.push(f(row));
            acc
        })
    }

    /// Executes the given `stmt` and folds the first result set to a signel value.
    fn exec_fold<T, S, P, U, F>(&mut self, stmt: S, params: P, init: U, mut f: F) -> Result<U>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
        F: FnMut(U, T) -> U,
    {
        let mut result = self.exec_iter(stmt, params)?;
        let output = result.try_fold(init, |init, row| row.map(|row| f(init, from_row(row))));
        output
    }

    /// Same as [`Queryable::exec_fold`] but useful when you not sure what your schema is.
    fn exec_fold_opt<T, S, P, U, F>(&mut self, stmt: S, params: P, init: U, mut f: F) -> Result<U>
    where
        S: AsStatement,
        P: Into<Params>,
        T: FromRow,
        F: FnMut(U, StdResult<T, FromRowError>) -> U,
    {
        let mut result = self.exec_iter(stmt, params)?;
        let output = result.try_fold(init, |init, row| row.map(|row| f(init, from_row_opt(row))));
        output
    }

    /// Executes the given `stmt` and drops the result.
    fn exec_drop<S, P>(&mut self, stmt: S, params: P) -> Result<()>
    where
        S: AsStatement,
        P: Into<Params>,
    {
        self.exec_iter(stmt, params).map(drop)
    }
}
<|endoftext|>


<commit_before>use arena::{TypedArena, DroplessArena};
use std::mem;
use std::ptr;
use std::slice;
use std::cell::RefCell;
use std::marker::PhantomData;
use smallvec::SmallVec;

#[macro_export]
macro_rules! arena_types {
    ($macro:path, $args:tt, $tcx:lifetime) => (
        $macro!($args, [
            [] vtable_method: Option<(
                rustc::hir::def_id::DefId,
                rustc::ty::subst::SubstsRef<$tcx>
            )>,
            [few] mir_keys: rustc::util::nodemap::DefIdSet,
            [decode] specialization_graph: rustc::traits::specialization_graph::Graph,
        ], $tcx);
    )
}

macro_rules! arena_for_type {
    ([][$ty:ty]) => {
        TypedArena<$ty>
    };
    ([few $(, $attrs:ident)*][$ty:ty]) => {
        PhantomData<$ty>
    };
    ([$ignore:ident $(, $attrs:ident)*]$args:tt) => {
        arena_for_type!([$($attrs),*]$args)
    };
}

macro_rules! declare_arena {
    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
        #[derive(Default)]
        pub struct Arena<$tcx> {
            dropless: DroplessArena,
            drop: DropArena,
            $($name: arena_for_type!($a[$ty]),)*
        }
    }
}

macro_rules! which_arena_for_type {
    ([][$arena:expr]) => {
        Some($arena)
    };
    ([few$(, $attrs:ident)*][$arena:expr]) => {
        None
    };
    ([$ignore:ident$(, $attrs:ident)*]$args:tt) => {
        which_arena_for_type!([$($attrs),*]$args)
    };
}

macro_rules! impl_arena_allocatable {
    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
        $(
            impl ArenaAllocatable for $ty {}
            unsafe impl<$tcx> ArenaField<$tcx> for $ty {
                #[inline]
                fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a TypedArena<Self>> {
                    which_arena_for_type!($a[&_arena.$name])
                }
            }
        )*
    }
}

arena_types!(declare_arena, [], 'tcx);

arena_types!(impl_arena_allocatable, [], 'tcx);

pub trait ArenaAllocatable {}

impl<T: Copy> ArenaAllocatable for T {}

pub unsafe trait ArenaField<'tcx>: Sized {
    /// Returns a specific arena to allocate from.
    /// If None is returned, the DropArena will be used.
    fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>>;
}

unsafe impl<'tcx, T> ArenaField<'tcx> for T {
    #[inline]
    default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>> {
        panic!()
    }
}

impl<'tcx> Arena<'tcx> {
    #[inline]
    pub fn alloc<T: ArenaAllocatable>(&self, value: T) -> &mut T {
        if !mem::needs_drop::<T>() {
            return self.dropless.alloc(value);
        }
        match <T as ArenaField<'tcx>>::arena(self) {
            Some(arena) => arena.alloc(value),
            None => unsafe { self.drop.alloc(value) },
        }
    }

    pub fn alloc_from_iter<
        T: ArenaAllocatable,
        I: IntoIterator<Item = T>
    >(
        &'a self,
        iter: I
    ) -> &'a mut [T] {
        if !mem::needs_drop::<T>() {
            return self.dropless.alloc_from_iter(iter);
        }
        match <T as ArenaField<'tcx>>::arena(self) {
            Some(arena) => arena.alloc_from_iter(iter),
            None => unsafe { self.drop.alloc_from_iter(iter) },
        }
    }
}

/// Calls the destructor for an object when dropped.
struct DropType {
    drop_fn: unsafe fn(*mut u8),
    obj: *mut u8,
}

unsafe fn drop_for_type<T>(to_drop: *mut u8) {
    std::ptr::drop_in_place(to_drop as *mut T)
}

impl Drop for DropType {
    fn drop(&mut self) {
        unsafe {
            (self.drop_fn)(self.obj)
        }
    }
}

/// An arena which can be used to allocate any type.
/// Allocating in this arena is unsafe since the type system
/// doesn't know which types it contains. In order to
/// allocate safetly, you must store a PhantomData<T>
/// alongside this arena for each type T you allocate.
#[derive(Default)]
struct DropArena {
    /// A list of destructors to run when the arena drops.
    /// Ordered so `destructors` gets dropped before the arena
    /// since its destructor can reference memory in the arena.
    destructors: RefCell<Vec<DropType>>,
    arena: DroplessArena,
}

impl DropArena {
    #[inline]
    unsafe fn alloc<T>(&self, object: T) -> &mut T {
        let mem = self.arena.alloc_raw(
            mem::size_of::<T>(),
            mem::align_of::<T>()
        ) as *mut _ as *mut T;
        // Write into uninitialized memory.
        ptr::write(mem, object);
        let result = &mut *mem;
        // Record the destructor after doing the allocation as that may panic
        // and would cause `object`'s destuctor to run twice if it was recorded before
        self.destructors.borrow_mut().push(DropType {
            drop_fn: drop_for_type::<T>,
            obj: result as *mut T as *mut u8,
        });
        result
    }

    #[inline]
    unsafe fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
        let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect();
        if vec.is_empty() {
            return &mut [];
        }
        let len = vec.len();

        let start_ptr = self.arena.alloc_raw(
            len.checked_mul(mem::size_of::<T>()).unwrap(),
            mem::align_of::<T>()
        ) as *mut _ as *mut T;

        let mut destructors = self.destructors.borrow_mut();
        // Reserve space for the destructors so we can't panic while adding them
        destructors.reserve(len);

        // Move the content to the arena by copying it and then forgetting
        // the content of the SmallVec
        vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
        mem::forget(vec.drain());

        // Record the destructors after doing the allocation as that may panic
        // and would cause `object`'s destuctor to run twice if it was recorded before
        for i in 0..len {
            destructors.push(DropType {
                drop_fn: drop_for_type::<T>,
                obj: start_ptr.offset(i as isize) as *mut u8,
            });
        }

        slice::from_raw_parts_mut(start_ptr, len)
    }
}
<commit_msg>Fix a typo<commit_after>use arena::{TypedArena, DroplessArena};
use std::mem;
use std::ptr;
use std::slice;
use std::cell::RefCell;
use std::marker::PhantomData;
use smallvec::SmallVec;

#[macro_export]
macro_rules! arena_types {
    ($macro:path, $args:tt, $tcx:lifetime) => (
        $macro!($args, [
            [] vtable_method: Option<(
                rustc::hir::def_id::DefId,
                rustc::ty::subst::SubstsRef<$tcx>
            )>,
            [few] mir_keys: rustc::util::nodemap::DefIdSet,
            [decode] specialization_graph: rustc::traits::specialization_graph::Graph,
        ], $tcx);
    )
}

macro_rules! arena_for_type {
    ([][$ty:ty]) => {
        TypedArena<$ty>
    };
    ([few $(, $attrs:ident)*][$ty:ty]) => {
        PhantomData<$ty>
    };
    ([$ignore:ident $(, $attrs:ident)*]$args:tt) => {
        arena_for_type!([$($attrs),*]$args)
    };
}

macro_rules! declare_arena {
    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
        #[derive(Default)]
        pub struct Arena<$tcx> {
            dropless: DroplessArena,
            drop: DropArena,
            $($name: arena_for_type!($a[$ty]),)*
        }
    }
}

macro_rules! which_arena_for_type {
    ([][$arena:expr]) => {
        Some($arena)
    };
    ([few$(, $attrs:ident)*][$arena:expr]) => {
        None
    };
    ([$ignore:ident$(, $attrs:ident)*]$args:tt) => {
        which_arena_for_type!([$($attrs),*]$args)
    };
}

macro_rules! impl_arena_allocatable {
    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
        $(
            impl ArenaAllocatable for $ty {}
            unsafe impl<$tcx> ArenaField<$tcx> for $ty {
                #[inline]
                fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a TypedArena<Self>> {
                    which_arena_for_type!($a[&_arena.$name])
                }
            }
        )*
    }
}

arena_types!(declare_arena, [], 'tcx);

arena_types!(impl_arena_allocatable, [], 'tcx);

pub trait ArenaAllocatable {}

impl<T: Copy> ArenaAllocatable for T {}

pub unsafe trait ArenaField<'tcx>: Sized {
    /// Returns a specific arena to allocate from.
    /// If None is returned, the DropArena will be used.
    fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>>;
}

unsafe impl<'tcx, T> ArenaField<'tcx> for T {
    #[inline]
    default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a TypedArena<Self>> {
        panic!()
    }
}

impl<'tcx> Arena<'tcx> {
    #[inline]
    pub fn alloc<T: ArenaAllocatable>(&self, value: T) -> &mut T {
        if !mem::needs_drop::<T>() {
            return self.dropless.alloc(value);
        }
        match <T as ArenaField<'tcx>>::arena(self) {
            Some(arena) => arena.alloc(value),
            None => unsafe { self.drop.alloc(value) },
        }
    }

    pub fn alloc_from_iter<
        T: ArenaAllocatable,
        I: IntoIterator<Item = T>
    >(
        &'a self,
        iter: I
    ) -> &'a mut [T] {
        if !mem::needs_drop::<T>() {
            return self.dropless.alloc_from_iter(iter);
        }
        match <T as ArenaField<'tcx>>::arena(self) {
            Some(arena) => arena.alloc_from_iter(iter),
            None => unsafe { self.drop.alloc_from_iter(iter) },
        }
    }
}

/// Calls the destructor for an object when dropped.
struct DropType {
    drop_fn: unsafe fn(*mut u8),
    obj: *mut u8,
}

unsafe fn drop_for_type<T>(to_drop: *mut u8) {
    std::ptr::drop_in_place(to_drop as *mut T)
}

impl Drop for DropType {
    fn drop(&mut self) {
        unsafe {
            (self.drop_fn)(self.obj)
        }
    }
}

/// An arena which can be used to allocate any type.
/// Allocating in this arena is unsafe since the type system
/// doesn't know which types it contains. In order to
/// allocate safely, you must store a PhantomData<T>
/// alongside this arena for each type T you allocate.
#[derive(Default)]
struct DropArena {
    /// A list of destructors to run when the arena drops.
    /// Ordered so `destructors` gets dropped before the arena
    /// since its destructor can reference memory in the arena.
    destructors: RefCell<Vec<DropType>>,
    arena: DroplessArena,
}

impl DropArena {
    #[inline]
    unsafe fn alloc<T>(&self, object: T) -> &mut T {
        let mem = self.arena.alloc_raw(
            mem::size_of::<T>(),
            mem::align_of::<T>()
        ) as *mut _ as *mut T;
        // Write into uninitialized memory.
        ptr::write(mem, object);
        let result = &mut *mem;
        // Record the destructor after doing the allocation as that may panic
        // and would cause `object`'s destuctor to run twice if it was recorded before
        self.destructors.borrow_mut().push(DropType {
            drop_fn: drop_for_type::<T>,
            obj: result as *mut T as *mut u8,
        });
        result
    }

    #[inline]
    unsafe fn alloc_from_iter<T, I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
        let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect();
        if vec.is_empty() {
            return &mut [];
        }
        let len = vec.len();

        let start_ptr = self.arena.alloc_raw(
            len.checked_mul(mem::size_of::<T>()).unwrap(),
            mem::align_of::<T>()
        ) as *mut _ as *mut T;

        let mut destructors = self.destructors.borrow_mut();
        // Reserve space for the destructors so we can't panic while adding them
        destructors.reserve(len);

        // Move the content to the arena by copying it and then forgetting
        // the content of the SmallVec
        vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
        mem::forget(vec.drain());

        // Record the destructors after doing the allocation as that may panic
        // and would cause `object`'s destuctor to run twice if it was recorded before
        for i in 0..len {
            destructors.push(DropType {
                drop_fn: drop_for_type::<T>,
                obj: start_ptr.offset(i as isize) as *mut u8,
            });
        }

        slice::from_raw_parts_mut(start_ptr, len)
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-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.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::Result::{Ok, Err};
    use slice::SliceExt;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v.slice_from_mut(read));
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0u8; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0u8; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL;
        static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::Sync;
    use mem;
    use os;
    use rand::Rng;
    use result::Result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::SliceExt;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    #[allow(missing_copy_implementations)]
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside of this module
        _dummy: (),
    }

    #[repr(C)]
    struct SecRandom;

    unsafe impl Sync for *const SecRandom {}

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::Result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::SliceExt;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use thread::Thread;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8; 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);

            Thread::spawn(move|| {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                Thread::yield_now();
                let mut v = [0u8; 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    Thread::yield_now();
                    r.next_u64();
                    Thread::yield_now();
                    r.fill_bytes(&mut v);
                    Thread::yield_now();
                }
            }).detach();
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>std: Second pass stabilization of sync<commit_after>// Copyright 2013-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.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::Result::{Ok, Err};
    use slice::SliceExt;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v.slice_from_mut(read));
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as uint;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0u8; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0u8; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = ATOMIC_BOOL_INIT;
        static GETRANDOM_AVAILABLE: AtomicBool = ATOMIC_BOOL_INIT;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open(&Path::new("/dev/urandom")));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::Sync;
    use mem;
    use os;
    use rand::Rng;
    use result::Result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::SliceExt;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    #[allow(missing_copy_implementations)]
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside of this module
        _dummy: (),
    }

    #[repr(C)]
    struct SecRandom;

    unsafe impl Sync for *const SecRandom {}

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::Result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::SliceExt;

    type HCRYPTPROV = LONG_PTR;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> IoResult<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                CryptAcquireContextA(&mut hcp, 0 as LPCSTR, 0 as LPCSTR,
                                     PROV_RSA_FULL,
                                     CRYPT_VERIFYCONTEXT | CRYPT_SILENT)
            };

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                CryptGenRandom(self.hcryptprov, v.len() as DWORD,
                               v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}", os::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}", os::last_os_error());
            }
        }
    }
}

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

    use super::OsRng;
    use rand::Rng;
    use thread::Thread;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0u8; 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in range(0u, 20) {
            let (tx, rx) = channel();
            txs.push(tx);

            Thread::spawn(move|| {
                // wait until all the tasks are ready to go.
                rx.recv();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                Thread::yield_now();
                let mut v = [0u8; 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    Thread::yield_now();
                    r.next_u64();
                    Thread::yield_now();
                    r.fill_bytes(&mut v);
                    Thread::yield_now();
                }
            }).detach();
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>


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

#[derive(PartialEq, PartialOrd)]
pub struct Point {
    pub x : f64,
    pub y : f64,
}

pub struct Entry {
    pub position: Point,
    pub data: String,
}

impl Entry {
    pub fn new(position: Point, data: String) -> Entry {
        Entry {
            position: position,
            data: data
        }
    }
}

pub type Id = i64;

pub struct Database {
    data: HashMap<Id, Entry>,
    last_id: Id,
}

fn distance(a: &Point, b: &Point) -> f64 {
    distance_sq(a, b).sqrt()
}

fn distance_sq(a: &Point, b: &Point) -> f64 {
    (a.x-b.x).powf(2.) + (a.y-b.y).powf(2.)
}

fn distance_between_internal(a: &Entry, b: &Entry) -> f64 {
    distance(&a.position, &b.position)
}

impl Database {
    pub fn insert(&mut self, e: Entry) -> Id {
        self.last_id += 1;
        self.data.insert(self.last_id, e);
        return self.last_id;
    }

    pub fn new() -> Database {
        Database {
            data: HashMap::new(),
            last_id: 0
        }
    }

    pub fn in_radius_from(&self, from: Point, radius: f64) -> Vec<Id> {
        let radius_sq = radius.powf(2.);
        let mut items = Vec::new();
        for (id, entity) in self.data.iter() {
            if distance_sq(&from, &entity.position) < radius_sq {
                items.push(id.clone());
            }
        }
        return items;
    }

    fn lift_from_ids2<T, F>(&self, f: F, a: Id, b: Id) -> Option<T>
        where
            F : Fn(&Entry, &Entry) -> T,
    {
        let ma = self.data.get(&a);
        let mb = self.data.get(&b);

        match (ma,mb) {
            (Some(a), Some (b)) => Some(f(&a, &b)),
            _ => None
        }
    }

    pub fn distance_between(&self, a: Id, b: Id) -> Option<f64> {
        self.lift_from_ids2(distance_between_internal, a, b)
    }
}
<commit_msg>Bartek cannot into formatting<commit_after>use std::collections::HashMap;

#[derive(PartialEq, PartialOrd)]
pub struct Point {
    pub x : f64,
    pub y : f64,
}

pub struct Entry {
    pub position: Point,
    pub data: String,
}

impl Entry {
    pub fn new(position: Point, data: String) -> Entry {
        Entry {
            position: position,
            data: data
        }
    }
}

pub type Id = i64;

pub struct Database {
    data: HashMap<Id, Entry>,
    last_id: Id,
}

fn distance(a: &Point, b: &Point) -> f64 {
    distance_sq(a, b).sqrt()
}

fn distance_sq(a: &Point, b: &Point) -> f64 {
    (a.x-b.x).powf(2.) + (a.y-b.y).powf(2.)
}

fn distance_between_internal(a: &Entry, b: &Entry) -> f64 {
    distance(&a.position, &b.position)
}

impl Database {
    pub fn insert(&mut self, e: Entry) -> Id {
        self.last_id += 1;
        self.data.insert(self.last_id, e);
        return self.last_id;
    }

    pub fn new() -> Database {
        Database {
            data: HashMap::new(),
            last_id: 0
        }
    }

    pub fn in_radius_from(&self, from: Point, radius: f64) -> Vec<Id> {
        let radius_sq = radius.powf(2.);
        let mut items = Vec::new();
        for (id, entity) in self.data.iter() {
            if distance_sq(&from, &entity.position) < radius_sq {
                items.push(id.clone());
            }
        }
        return items;
    }

    fn lift_from_ids2<T, F>(&self, f: F, a: Id, b: Id) -> Option<T>
        where
            F : Fn(&Entry, &Entry) -> T,
    {
        let ma = self.data.get(&a);
        let mb = self.data.get(&b);

        match (ma,mb) {
            (Some(a), Some(b)) => Some(f(&a, &b)),
            _ => None
        }
    }

    pub fn distance_between(&self, a: Id, b: Id) -> Option<f64> {
        self.lift_from_ids2(distance_between_internal, a, b)
    }
}
<|endoftext|>


<commit_before>// Super unsafe due to page table switching and raw pointers!
pub unsafe fn debugger() {
    println!("DEBUGGER START");
    println!();

    let mut active_table = crate::paging::ActivePageTable::new(crate::paging::TableKind::User);
    for (id, context_lock) in crate::context::contexts().iter() {
        let context = context_lock.read();
        println!("{}: {}", (*id).into(), context.name.read());

        // Switch to context page table to ensure syscall debug and stack dump will work
        let new_table = crate::paging::InactivePageTable::from_address(context.arch.get_page_utable());
        let old_table = active_table.switch(new_table);

        println!("status: {:?}", context.status);
        if ! context.status_reason.is_empty() {
            println!("reason: {}", context.status_reason);
        }
        if let Some((a, b, c, d, e, f)) = context.syscall {
            println!("syscall: {}", crate::syscall::debug::format_call(a, b, c, d, e, f));
        }
        if let Some(ref addr_space) = context.addr_space {
            let addr_space = addr_space.read();
            if ! addr_space.grants.is_empty() {
                println!("grants:");
                for grant in addr_space.grants.iter() {
                    let region = grant.region();
                    println!(
                        "    virt 0x{:016x}:0x{:016x} size 0x{:08x} {}",
                        region.start_address().data(), region.final_address().data(), region.size(),
                        if grant.is_owned() { "owned" } else { "borrowed" },
                    );
                }
            }
        }
        if let Some(regs) = unsafe { crate::ptrace::regs_for(&context) } {
            println!("regs:");
            regs.dump();

            let mut rsp = regs.iret.rsp;
            println!("stack: {:>016x}", rsp);
            //Maximum 64 qwords
            for i in 0..64 {
                if active_table.translate(crate::paging::VirtualAddress::new(rsp)).is_some() {
                    let value = *(rsp as *const usize);
                    println!("    {:>016x}: {:>016x}", rsp, value);
                    if let Some(next_rsp) = rsp.checked_add(core::mem::size_of::<usize>()) {
                        rsp = next_rsp;
                    } else {
                        println!("    {:>016x}: OVERFLOW", rsp);
                        break;
                    }
                } else {
                    println!("    {:>016x}: GUARD PAGE", rsp);
                    break;
                }
            }
        }

        // Switch to original page table
        active_table.switch(old_table);

        println!();
    }

    println!("DEBUGGER END");
}
<commit_msg>Partial: migrate debugger, add consistency check.<commit_after>use crate::paging::{RmmA, RmmArch};

// Super unsafe due to page table switching and raw pointers!
pub unsafe fn debugger(target_id: Option<crate::context::ContextId>) {
    println!("DEBUGGER START");
    println!();

    let old_table = RmmA::table();

    for (id, context_lock) in crate::context::contexts().iter() {
        if target_id.map_or(false, |target_id| *id != target_id) { continue; }
        let context = context_lock.read();
        println!("{}: {}", (*id).into(), context.name.read());

        // Switch to context page table to ensure syscall debug and stack dump will work
        if let Some(ref space) = context.addr_space {
            RmmA::set_table(space.read().table.utable.table().phys());
        }

        check_consistency(&mut context.addr_space.as_ref().unwrap().write());

        println!("status: {:?}", context.status);
        if ! context.status_reason.is_empty() {
            println!("reason: {}", context.status_reason);
        }
        if let Some((a, b, c, d, e, f)) = context.syscall {
            println!("syscall: {}", crate::syscall::debug::format_call(a, b, c, d, e, f));
        }
        if let Some(ref addr_space) = context.addr_space {
            let addr_space = addr_space.read();
            if ! addr_space.grants.is_empty() {
                println!("grants:");
                for grant in addr_space.grants.iter() {
                    let region = grant.region();
                    println!(
                        "    virt 0x{:016x}:0x{:016x} size 0x{:08x} {}",
                        region.start_address().data(), region.final_address().data(), region.size(),
                        if grant.is_owned() { "owned" } else { "borrowed" },
                    );
                }
            }
        }
        if let Some(regs) = unsafe { crate::ptrace::regs_for(&context) } {
            println!("regs:");
            regs.dump();

            let mut rsp = regs.iret.rsp;
            println!("stack: {:>016x}", rsp);
            //Maximum 64 qwords
            for i in 0..64 {
                if context.addr_space.as_ref().map_or(false, |space| space.read().table.utable.translate(crate::paging::VirtualAddress::new(rsp)).is_some()) {
                    let value = *(rsp as *const usize);
                    println!("    {:>016x}: {:>016x}", rsp, value);
                    if let Some(next_rsp) = rsp.checked_add(core::mem::size_of::<usize>()) {
                        rsp = next_rsp;
                    } else {
                        println!("    {:>016x}: OVERFLOW", rsp);
                        break;
                    }
                } else {
                    println!("    {:>016x}: GUARD PAGE", rsp);
                    break;
                }
            }
        }

        // Switch to original page table
        RmmA::set_table(old_table);

        println!();
    }

    println!("DEBUGGER END");
}

pub unsafe fn check_consistency(addr_space: &mut crate::context::memory::AddrSpace) {
    use crate::paging::*;

    let p4 = addr_space.table.utable.table();

    for p4i in 0..256 {
        let p3 = match p4.next(p4i) {
            Some(p3) => p3,
            None => continue,
        };

        for p3i in 0..512 {
            let p2 = match p3.next(p3i) {
                Some(p2) => p2,
                None => continue,
            };

            for p2i in 0..512 {
                let p1 = match p2.next(p2i) {
                    Some(p1) => p1,
                    None => continue,
                };

                for p1i in 0..512 {
                    let (physaddr, flags) = match p1.entry(p1i) {
                        Some(e) => if let Ok(address) = e.address() {
                            (address, e.flags())
                        } else {
                            continue;
                        }
                        _ => continue,
                    };
                    let address = VirtualAddress::new((p1i << 12) | (p2i << 21) | (p3i << 30) | (p4i << 39));

                    let grant = match addr_space.grants.contains(address) {
                        Some(g) => g,
                        None => {
                            log::error!("ADDRESS {:p} LACKING GRANT BUT MAPPED TO {:#0x} FLAGS {:?}!", address.data() as *const u8, physaddr.data(), flags);
                            continue;
                        }
                    };
                    const STICKY: usize = (1 << 5) | (1 << 6); // accessed+dirty
                    if grant.flags().data() & !STICKY != flags.data() & !STICKY {
                        log::error!("FLAG MISMATCH: {:?} != {:?}, address {:p} in grant at {:?}", grant.flags(), flags, address.data() as *const u8, grant.region());
                    }
                }
            }
        }
    }

    for grant in addr_space.grants.iter() {
        for page in grant.pages() {
            let entry = match addr_space.table.utable.translate(page.start_address()) {
                Some(e) => e,
                None => {
                    log::error!("GRANT AT {:?} LACKING MAPPING AT PAGE {:p}", grant.region(), page.start_address().data() as *const u8);
                    continue;
                }
            };
        }
    }
}
<|endoftext|>


<commit_before>extern crate websocket;

use self::websocket::WebSocketError;
use futures::future::Future;
use futures::stream::Stream;

use std::cell::RefCell;
use std::rc::Rc;

use self::websocket::server::upgrade::async::IntoWs;

use super::ws_peer::{Mode1, PeerForWs, WsReadWrapper, WsWriteWrapper};
use super::{box_up_err, io_other_error, BoxedNewPeerFuture, Peer};
use super::{Handle, Options, PeerConstructor, ProgramState, Specifier};

#[derive(Debug)]
pub struct WsServer<T: Specifier>(pub T);
impl<T: Specifier> Specifier for WsServer<T> {
    fn construct(&self, h: &Handle, ps: &mut ProgramState, opts: Rc<Options>) -> PeerConstructor {
        let mode1 = if opts.websocket_text_mode {
            Mode1::Text
        } else {
            Mode1::Binary
        };
        let inner = self.0.construct(h, ps, opts);
        inner.map(move |p| ws_upgrade_peer(p, mode1))
    }
    specifier_boilerplate!(typ=Other noglobalstate has_subspec);
    self_0_is_subspecifier!(proxy_is_multiconnect);
}
specifier_class!(
    name=WsServerClass,
    target=WsServer,
    prefixes=["ws-l:","l-ws:","ws-listen:","listen-ws:"],
    arg_handling={
        fn construct(self:&WsServerClass, _full:&str, just_arg:&str) -> super::Result<Rc<Specifier>> {
            if just_arg == "" {
                Err("Specify underlying protocol for ws-l:")?;
            }
            if let Some(c) = just_arg.chars().next() {
                if c.is_numeric() || c == '[' {
                    // Assuming user uses old format like ws-l:127.0.0.1:8080
                    return super::spec(&("ws-l:tcp-l:".to_owned() + just_arg));
                }
            }
            Ok(Rc::new(WsServer(super::spec(just_arg)?)))
        }
    },
    help=r#"
WebSocket server. Argument is either IPv4 host and port to listen
or a subspecifier.

Example: Dump all incoming websocket data to console

    websocat ws-l:127.0.0.1:8808 -

Example: the same, but more verbose:

    websocat ws-l:tcp-l:127.0.0.1:8808 reuse:-TODO
"#
);

/*

     if x == "" {
                Err("Specify underlying protocol for ws-l:")?;
            }
            if let Some(c) = x.chars().next() {
                if c.is_numeric() || c == '[' {
                    // Assuming user uses old format like ws-l:127.0.0.1:8080
                    return spec(&("ws-l:tcp-l:".to_owned() + x));
                }
            }
            boxup(super::ws_server_peer::WsUpgrade(spec(x)?))
*/

pub fn ws_upgrade_peer(inner_peer: Peer, mode1: Mode1) -> BoxedNewPeerFuture {
    let step1 = PeerForWs(inner_peer);
    let step2: Box<
        Future<Item = self::websocket::server::upgrade::async::Upgrade<_>, Error = _>,
    > = step1.into_ws();
    let step3 = step2
        .map_err(|(_, _, _, e)| WebSocketError::IoError(io_other_error(e)))
        .and_then(move |x| {
            info!("Incoming connection to websocket: {}", x.request.subject.1);
            debug!("{:?}", x.request);
            debug!("{:?}", x.headers);
            x.accept().map(move |(y, headers)| {
                debug!("{:?}", headers);
                info!("Upgraded");
                let (sink, stream) = y.split();
                let mpsink = Rc::new(RefCell::new(sink));

                let ws_str = WsReadWrapper {
                    s: stream,
                    pingreply: mpsink.clone(),
                    debt: Default::default(),
                };
                let ws_sin = WsWriteWrapper(mpsink, mode1);

                let ws = Peer::new(ws_str, ws_sin);
                ws
            })
        });
    let step4 = step3.map_err(box_up_err);
    Box::new(step4) as BoxedNewPeerFuture
}
<commit_msg>Remove stray leftover text<commit_after>extern crate websocket;

use self::websocket::WebSocketError;
use futures::future::Future;
use futures::stream::Stream;

use std::cell::RefCell;
use std::rc::Rc;

use self::websocket::server::upgrade::async::IntoWs;

use super::ws_peer::{Mode1, PeerForWs, WsReadWrapper, WsWriteWrapper};
use super::{box_up_err, io_other_error, BoxedNewPeerFuture, Peer};
use super::{Handle, Options, PeerConstructor, ProgramState, Specifier};

#[derive(Debug)]
pub struct WsServer<T: Specifier>(pub T);
impl<T: Specifier> Specifier for WsServer<T> {
    fn construct(&self, h: &Handle, ps: &mut ProgramState, opts: Rc<Options>) -> PeerConstructor {
        let mode1 = if opts.websocket_text_mode {
            Mode1::Text
        } else {
            Mode1::Binary
        };
        let inner = self.0.construct(h, ps, opts);
        inner.map(move |p| ws_upgrade_peer(p, mode1))
    }
    specifier_boilerplate!(typ=Other noglobalstate has_subspec);
    self_0_is_subspecifier!(proxy_is_multiconnect);
}
specifier_class!(
    name=WsServerClass,
    target=WsServer,
    prefixes=["ws-l:","l-ws:","ws-listen:","listen-ws:"],
    arg_handling={
        fn construct(self:&WsServerClass, _full:&str, just_arg:&str) -> super::Result<Rc<Specifier>> {
            if just_arg == "" {
                Err("Specify underlying protocol for ws-l:")?;
            }
            if let Some(c) = just_arg.chars().next() {
                if c.is_numeric() || c == '[' {
                    // Assuming user uses old format like ws-l:127.0.0.1:8080
                    return super::spec(&("ws-l:tcp-l:".to_owned() + just_arg));
                }
            }
            Ok(Rc::new(WsServer(super::spec(just_arg)?)))
        }
    },
    help=r#"
WebSocket server. Argument is either IPv4 host and port to listen
or a subspecifier.

Example: Dump all incoming websocket data to console

    websocat ws-l:127.0.0.1:8808 -

Example: the same, but more verbose:

    websocat ws-l:tcp-l:127.0.0.1:8808 reuse:-
"#
);

/*

     if x == "" {
                Err("Specify underlying protocol for ws-l:")?;
            }
            if let Some(c) = x.chars().next() {
                if c.is_numeric() || c == '[' {
                    // Assuming user uses old format like ws-l:127.0.0.1:8080
                    return spec(&("ws-l:tcp-l:".to_owned() + x));
                }
            }
            boxup(super::ws_server_peer::WsUpgrade(spec(x)?))
*/

pub fn ws_upgrade_peer(inner_peer: Peer, mode1: Mode1) -> BoxedNewPeerFuture {
    let step1 = PeerForWs(inner_peer);
    let step2: Box<
        Future<Item = self::websocket::server::upgrade::async::Upgrade<_>, Error = _>,
    > = step1.into_ws();
    let step3 = step2
        .map_err(|(_, _, _, e)| WebSocketError::IoError(io_other_error(e)))
        .and_then(move |x| {
            info!("Incoming connection to websocket: {}", x.request.subject.1);
            debug!("{:?}", x.request);
            debug!("{:?}", x.headers);
            x.accept().map(move |(y, headers)| {
                debug!("{:?}", headers);
                info!("Upgraded");
                let (sink, stream) = y.split();
                let mpsink = Rc::new(RefCell::new(sink));

                let ws_str = WsReadWrapper {
                    s: stream,
                    pingreply: mpsink.clone(),
                    debt: Default::default(),
                };
                let ws_sin = WsWriteWrapper(mpsink, mode1);

                let ws = Peer::new(ws_str, ws_sin);
                ws
            })
        });
    let step4 = step3.map_err(box_up_err);
    Box::new(step4) as BoxedNewPeerFuture
}
<|endoftext|>