<commit_before>use std::iter::{Iterator, IntoIterator};
use std::error;
use std::cmp;
use std::fmt;
use std::time::{Duration, Instant};

use futures::{Async, Future, Poll};
use tokio_timer::{Delay, Error as TimerError};
use tokio_timer::timer::Handle;

use super::action::Action;
use super::condition::Condition;

/// Represents the errors possible during the execution of the `RetryFuture`.
#[derive(Debug)]
pub enum Error<E> {
    OperationError(E),
    TimerError(TimerError)
}

impl<E: cmp::PartialEq> cmp::PartialEq for Error<E> {
    fn eq(&self, other: &Error<E>) -> bool  {
        match (self, other) {
            (&Error::TimerError(_), _) => false,
            (_, &Error::TimerError(_)) => false,
            (&Error::OperationError(ref left_err), &Error::OperationError(ref right_err)) =>
                left_err.eq(right_err)
        }
    }
}

impl<E: fmt::Display> fmt::Display for Error<E> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::OperationError(ref err) => err.fmt(formatter),
            Error::TimerError(ref err) => err.fmt(formatter)
        }
    }
}

impl<E: error::Error> error::Error for Error<E> {
    fn description(&self) -> &str {
        match *self {
            Error::OperationError(ref err) => err.description(),
            Error::TimerError(ref err) => err.description()
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::OperationError(ref err) => Some(err),
            Error::TimerError(ref err) => Some(err)
        }
    }
}

enum RetryState<A> where A: Action {
    Running(A::Future),
    Sleeping(Delay)
}

impl<A: Action> RetryState<A> {
    fn poll(&mut self) -> RetryFuturePoll<A> {
        match *self {
            RetryState::Running(ref mut future) =>
                RetryFuturePoll::Running(future.poll()),
            RetryState::Sleeping(ref mut future) =>
                RetryFuturePoll::Sleeping(future.poll())
        }
    }
}

enum RetryFuturePoll<A> where A: Action {
    Running(Poll<A::Item, A::Error>),
    Sleeping(Poll<(), TimerError>)
}

/// Future that drives multiple attempts at an action via a retry strategy.
pub struct Retry<I, A> where I: Iterator<Item=Duration>, A: Action {
    retry_if: RetryIf<I, A, fn(&A::Error) -> bool>
}

impl<I, A> Retry<I, A> where I: Iterator<Item=Duration>, A: Action {
    pub fn spawn<T: IntoIterator<IntoIter=I, Item=Duration>>(strategy: T, action: A) -> Retry<I, A> {
        Retry::new(None, strategy, action)
    }

    pub fn spawn_with_handle<T: IntoIterator<IntoIter=I, Item=Duration>>(handle: Handle, strategy: T, action: A) -> Retry<I, A> {
        Retry::new(Some(handle), strategy, action)
    }

    fn new<T: IntoIterator<IntoIter=I, Item=Duration>>(handle: Option<Handle>, strategy: T, action: A) -> Retry<I, A> {
        Retry {
            retry_if: RetryIf::new(handle, strategy, action, (|_| true) as fn(&A::Error) -> bool)
        }
    }
}

impl<I, A> Future for Retry<I, A> where I: Iterator<Item=Duration>, A: Action {
    type Item = A::Item;
    type Error = Error<A::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.retry_if.poll()
    }
}

/// Future that drives multiple attempts at an action via a retry strategy. Retries are only attempted if
/// the `Error` returned by the future satisfies a given condition.
pub struct RetryIf<I, A, C> where I: Iterator<Item=Duration>, A: Action, C: Condition<A::Error> {
    strategy: I,
    state: RetryState<A>,
    action: A,
    handle: Option<Handle>,
    condition: C
}

impl<I, A, C> RetryIf<I, A, C> where I: Iterator<Item=Duration>, A: Action, C: Condition<A::Error> {
    pub fn spawn<T: IntoIterator<IntoIter=I, Item=Duration>>(
        strategy: T,
        action: A,
        condition: C
    ) -> RetryIf<I, A, C> {
        RetryIf::new(None, strategy, action, condition)
    }

    pub fn spawn_with_handle<T: IntoIterator<IntoIter=I, Item=Duration>>(
        handle: Handle,
        strategy: T,
        action: A,
        condition: C
    ) -> RetryIf<I, A, C> {
        RetryIf::new(Some(handle), strategy, action, condition)
    }

    pub fn new<T: IntoIterator<IntoIter=I, Item=Duration>>(
        handle: Option<Handle>,
        strategy: T,
        mut action: A,
        condition: C
    ) -> RetryIf<I, A, C> {
        RetryIf {
            strategy: strategy.into_iter(),
            state: RetryState::Running(action.run()),
            action: action,
            handle: handle,
            condition: condition,
        }
    }

    fn attempt(&mut self) -> Poll<A::Item, Error<A::Error>> {
        let future = self.action.run();
        self.state = RetryState::Running(future);
        self.poll()
    }

    fn retry(&mut self, err: A::Error) -> Poll<A::Item, Error<A::Error>> {
        match self.strategy.next() {
            None => Err(Error::OperationError(err)),
            Some(duration) => {
                let deadline = Instant::now() + duration;
                let handle = self.handle.clone().unwrap_or_else(Handle::current);
                let future = handle.delay(deadline);
                self.state = RetryState::Sleeping(future);
                self.poll()
            }
        }
    }
}

impl<I, A, C> Future for RetryIf<I, A, C> where I: Iterator<Item=Duration>, A: Action, C: Condition<A::Error> {
    type Item = A::Item;
    type Error = Error<A::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.state.poll() {
            RetryFuturePoll::Running(poll_result) => match poll_result {
                Ok(async) => Ok(async),
                Err(err) => {
                    if self.condition.should_retry(&err) {
                        self.retry(err)
                    } else {
                        Err(Error::OperationError(err))
                    }
                }
            },
            RetryFuturePoll::Sleeping(poll_result) => match poll_result {
                Ok(Async::NotReady) => Ok(Async::NotReady),
                Ok(Async::Ready(_)) => self.attempt(),
                Err(err) => Err(Error::TimerError(err))
            }
        }
    }
}
<commit_msg>make RetryIf::new private<commit_after>use std::iter::{Iterator, IntoIterator};
use std::error;
use std::cmp;
use std::fmt;
use std::time::{Duration, Instant};

use futures::{Async, Future, Poll};
use tokio_timer::{Delay, Error as TimerError};
use tokio_timer::timer::Handle;

use super::action::Action;
use super::condition::Condition;

/// Represents the errors possible during the execution of the `RetryFuture`.
#[derive(Debug)]
pub enum Error<E> {
    OperationError(E),
    TimerError(TimerError)
}

impl<E: cmp::PartialEq> cmp::PartialEq for Error<E> {
    fn eq(&self, other: &Error<E>) -> bool  {
        match (self, other) {
            (&Error::TimerError(_), _) => false,
            (_, &Error::TimerError(_)) => false,
            (&Error::OperationError(ref left_err), &Error::OperationError(ref right_err)) =>
                left_err.eq(right_err)
        }
    }
}

impl<E: fmt::Display> fmt::Display for Error<E> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Error::OperationError(ref err) => err.fmt(formatter),
            Error::TimerError(ref err) => err.fmt(formatter)
        }
    }
}

impl<E: error::Error> error::Error for Error<E> {
    fn description(&self) -> &str {
        match *self {
            Error::OperationError(ref err) => err.description(),
            Error::TimerError(ref err) => err.description()
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::OperationError(ref err) => Some(err),
            Error::TimerError(ref err) => Some(err)
        }
    }
}

enum RetryState<A> where A: Action {
    Running(A::Future),
    Sleeping(Delay)
}

impl<A: Action> RetryState<A> {
    fn poll(&mut self) -> RetryFuturePoll<A> {
        match *self {
            RetryState::Running(ref mut future) =>
                RetryFuturePoll::Running(future.poll()),
            RetryState::Sleeping(ref mut future) =>
                RetryFuturePoll::Sleeping(future.poll())
        }
    }
}

enum RetryFuturePoll<A> where A: Action {
    Running(Poll<A::Item, A::Error>),
    Sleeping(Poll<(), TimerError>)
}

/// Future that drives multiple attempts at an action via a retry strategy.
pub struct Retry<I, A> where I: Iterator<Item=Duration>, A: Action {
    retry_if: RetryIf<I, A, fn(&A::Error) -> bool>
}

impl<I, A> Retry<I, A> where I: Iterator<Item=Duration>, A: Action {
    pub fn spawn<T: IntoIterator<IntoIter=I, Item=Duration>>(strategy: T, action: A) -> Retry<I, A> {
        Retry::new(None, strategy, action)
    }

    pub fn spawn_with_handle<T: IntoIterator<IntoIter=I, Item=Duration>>(handle: Handle, strategy: T, action: A) -> Retry<I, A> {
        Retry::new(Some(handle), strategy, action)
    }

    fn new<T: IntoIterator<IntoIter=I, Item=Duration>>(handle: Option<Handle>, strategy: T, action: A) -> Retry<I, A> {
        Retry {
            retry_if: RetryIf::new(handle, strategy, action, (|_| true) as fn(&A::Error) -> bool)
        }
    }
}

impl<I, A> Future for Retry<I, A> where I: Iterator<Item=Duration>, A: Action {
    type Item = A::Item;
    type Error = Error<A::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        self.retry_if.poll()
    }
}

/// Future that drives multiple attempts at an action via a retry strategy. Retries are only attempted if
/// the `Error` returned by the future satisfies a given condition.
pub struct RetryIf<I, A, C> where I: Iterator<Item=Duration>, A: Action, C: Condition<A::Error> {
    strategy: I,
    state: RetryState<A>,
    action: A,
    handle: Option<Handle>,
    condition: C
}

impl<I, A, C> RetryIf<I, A, C> where I: Iterator<Item=Duration>, A: Action, C: Condition<A::Error> {
    pub fn spawn<T: IntoIterator<IntoIter=I, Item=Duration>>(
        strategy: T,
        action: A,
        condition: C
    ) -> RetryIf<I, A, C> {
        RetryIf::new(None, strategy, action, condition)
    }

    pub fn spawn_with_handle<T: IntoIterator<IntoIter=I, Item=Duration>>(
        handle: Handle,
        strategy: T,
        action: A,
        condition: C
    ) -> RetryIf<I, A, C> {
        RetryIf::new(Some(handle), strategy, action, condition)
    }

    fn new<T: IntoIterator<IntoIter=I, Item=Duration>>(
        handle: Option<Handle>,
        strategy: T,
        mut action: A,
        condition: C
    ) -> RetryIf<I, A, C> {
        RetryIf {
            strategy: strategy.into_iter(),
            state: RetryState::Running(action.run()),
            action: action,
            handle: handle,
            condition: condition,
        }
    }

    fn attempt(&mut self) -> Poll<A::Item, Error<A::Error>> {
        let future = self.action.run();
        self.state = RetryState::Running(future);
        self.poll()
    }

    fn retry(&mut self, err: A::Error) -> Poll<A::Item, Error<A::Error>> {
        match self.strategy.next() {
            None => Err(Error::OperationError(err)),
            Some(duration) => {
                let deadline = Instant::now() + duration;
                let handle = self.handle.clone().unwrap_or_else(Handle::current);
                let future = handle.delay(deadline);
                self.state = RetryState::Sleeping(future);
                self.poll()
            }
        }
    }
}

impl<I, A, C> Future for RetryIf<I, A, C> where I: Iterator<Item=Duration>, A: Action, C: Condition<A::Error> {
    type Item = A::Item;
    type Error = Error<A::Error>;

    fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
        match self.state.poll() {
            RetryFuturePoll::Running(poll_result) => match poll_result {
                Ok(async) => Ok(async),
                Err(err) => {
                    if self.condition.should_retry(&err) {
                        self.retry(err)
                    } else {
                        Err(Error::OperationError(err))
                    }
                }
            },
            RetryFuturePoll::Sleeping(poll_result) => match poll_result {
                Ok(Async::NotReady) => Ok(Async::NotReady),
                Ok(Async::Ready(_)) => self.attempt(),
                Err(err) => Err(Error::TimerError(err))
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::mem;
use std::num;
use std::num::SignedInt;
use std::raw;

use super::{Ix, Ixs};

/// Calculate offset from `Ix` stride converting sign properly
#[inline]
pub fn stride_offset(n: Ix, stride: Ix) -> int
{
    (n as int) * ((stride as Ixs) as int)
}

/*
#[inline]
pub fn stride_as_int(stride: Ix) -> int
{
    (stride as Ixs) as int
}
*/

/// Trait for the shape and index types of arrays.
pub trait Dimension : Clone + Eq {
    fn ndim(&self) -> uint;
    fn slice<'a>(&'a self) -> &'a [Ix] {
        unsafe {
            mem::transmute(raw::Slice {
                data: self as *const _ as *const Ix,
                len: self.ndim(),
            })
        }
    }

    fn slice_mut<'a>(&'a mut self) -> &'a mut [Ix] {
        unsafe {
            mem::transmute(raw::Slice {
                data: self as *mut _ as *const Ix,
                len: self.ndim(),
            })
        }
    }

    fn size(&self) -> uint {
        self.slice().iter().fold(1u, |s, &a| s * a as uint)
    }

    fn default_strides(&self) -> Self {
        // Compute default array strides
        // Shape (a, b, c) => Give strides (b * c, c, 1)
        let mut strides = self.clone();
        {
            let mut it = strides.slice_mut().iter_mut().rev();
            // Set first element to 1
            for rs in it {
                *rs = 1;
                break;
            }
            let mut cum_prod = 1;
            for (rs, dim) in it.zip(self.slice().iter().rev()) {
                cum_prod *= *dim;
                *rs = cum_prod;
            }
        }
        strides
    }

    #[inline]
    fn first_index(&self) -> Option<Self>
    {
        for ax in self.slice().iter() {
            if *ax == 0 {
                return None
            }
        }
        let mut index = self.clone();
        for rr in index.slice_mut().iter_mut() {
            *rr = 0;
        }
        Some(index)
    }

    /// Iteration -- Use self as size, and return next index after `index`
    /// or None if there are no more.
    // FIXME: use &Self for index or even &mut?
    #[inline]
    fn next_for(&self, index: Self) -> Option<Self> {
        let mut index = index;
        let mut done = false;
        for (&dim, ix) in self.slice().iter().rev()
                            .zip(index.slice_mut().iter_mut().rev())
        {
            *ix += 1;
            if *ix == dim {
                *ix = 0;
            } else {
                done = true;
                break;
            }
        }
        if done {
            Some(index)
        } else { None }
    }

    /// Return stride offset for index.
    fn stride_offset(index: &Self, strides: &Self) -> int
    {
        let mut offset = 0;
        for (&i, &s) in index.slice().iter()
                            .zip(strides.slice().iter()) {
            offset += stride_offset(i, s);
        }
        offset
    }

    /// Return stride offset for this dimension and index.
    fn stride_offset_checked(&self, strides: &Self, index: &Self) -> Option<int>
    {
        let mut offset = 0;
        for ((&d, &i), &s) in self.slice().iter()
                                .zip(index.slice().iter())
                                .zip(strides.slice().iter())
        {
            if i >= d {
                return None;
            }
            offset += stride_offset(i, s);
        }
        Some(offset)
    }

    /// Modify dimension, strides and return data pointer offset
    ///
    /// **Panics** if `slices` does not correspond to the number of axes,
    /// if any stride is 0, or if any index is out of bounds.
    fn do_slices(dim: &mut Self, strides: &mut Self, slices: &[Si]) -> int
    {
        let mut offset = 0;
        assert!(slices.len() == dim.slice().len());
        for ((dr, sr), &slc) in dim.slice_mut().iter_mut()
                                .zip(strides.slice_mut().iter_mut())
                                .zip(slices.iter())
        {
            let m = *dr;
            let mi = m as Ixs;
            let Si(b1, opt_e1, s1) = slc;
            let e1 = opt_e1.unwrap_or(mi);

            let b1 = abs_index(mi, b1);
            let mut e1 = abs_index(mi, e1);
            if e1 < b1 { e1 = b1; }

            assert!(b1 <= m);
            assert!(e1 <= m);

            let m = e1 - b1;
            // stride
            let s = (*sr) as Ixs;

            // Data pointer offset
            offset += stride_offset(b1, *sr);
            // Adjust for strides
            assert!(s1 != 0);
            // How to implement negative strides:
            //
            // Increase start pointer by
            // old stride * (old dim - 1)
            // to put the pointer completely in the other end
            if s1 < 0 {
                offset += stride_offset(m - 1, *sr);
            }

            let s_prim = s * s1;

            let (d, r) = num::div_rem(m, s1.abs() as Ix);
            let m_prim = d + if r > 0 { 1 } else { 0 };

            // Update dimension and stride coordinate
            *dr = m_prim;
            *sr = s_prim as Ix;
        }
        offset
    }
}

fn abs_index(len: Ixs, index: Ixs) -> Ix {
    if index < 0 {
        (len + index) as Ix
    } else { index as Ix }
}

/// Collapse axis `axis` and shift so that only subarray `index` is
/// available.
///
/// **Panics** if `index` is larger than the size of the axis
// FIXME: Move to Dimension trait
pub fn do_sub<A, D: Dimension, P: Copy + RawPtr<A>>(dims: &mut D, ptr: &mut P, strides: &D,
                           axis: uint, index: Ix)
{
    let dim = dims.slice()[axis];
    let stride = strides.slice()[axis];
    assert!(index < dim);
    dims.slice_mut()[axis] = 1;
    let off = stride_offset(index, stride);
    unsafe {
        *ptr = ptr.offset(off);
    }
}

impl Dimension for () {
    // empty product is 1 -> size is 1
    #[inline]
    fn ndim(&self) -> uint { 0 }
    fn slice(&self) -> &[Ix] { &[] }
    fn slice_mut(&mut self) -> &mut [Ix] { &mut [] }
}

impl Dimension for Ix {
    #[inline]
    fn ndim(&self) -> uint { 1 }
    #[inline]
    fn size(&self) -> uint { *self as uint }
    #[inline]
    fn first_index(&self) -> Option<Ix> {
        if *self != 0 {
            Some(0)
        } else { None }
    }
    #[inline]
    fn next_for(&self, mut index: Ix) -> Option<Ix> {
        index += 1;
        if index < *self {
            Some(index)
        } else { None }
    }

    /// Self is an index, return the stride offset
    #[inline]
    fn stride_offset(index: &Ix, stride: &Ix) -> int
    {
        stride_offset(*index, *stride)
    }

    /// Return stride offset for this dimension and index.
    fn stride_offset_checked(&self, stride: &Ix, index: &Ix) -> Option<int>
    {
        if *index < *self {
            Some(stride_offset(*index, *stride))
        } else {
            None
        }
    }
}

impl Dimension for (Ix, Ix) {
    #[inline]
    fn ndim(&self) -> uint { 2 }
    #[inline]
    fn size(&self) -> uint { let (m, n) = *self; m as uint * n as uint }
    #[inline]
    fn first_index(&self) -> Option<(Ix, Ix)> {
        let (m, n) = *self;
        if m != 0 && n != 0 {
            Some((0, 0))
        } else { None }
    }
    #[inline]
    fn next_for(&self, index: (Ix, Ix)) -> Option<(Ix, Ix)> {
        let (mut i, mut j) = index;
        let (imax, jmax) = *self;
        j += 1;
        if j == jmax {
            j = 0;
            i += 1;
            if i == imax {
                return None;
            }
        }
        Some((i, j))
    }

    /// Self is an index, return the stride offset
    #[inline]
    fn stride_offset(index: &(Ix, Ix), strides: &(Ix, Ix)) -> int
    {
        let (i, j) = *index;
        let (s, t) = *strides;
        stride_offset(i, s) + stride_offset(j, t)
    }

    /// Return stride offset for this dimension and index.
    fn stride_offset_checked(&self, strides: &(Ix, Ix), index: &(Ix, Ix)) -> Option<int>
    {
        let (m, n) = *self;
        let (i, j) = *index;
        let (s, t) = *strides;
        if i < m && j < n {
            Some(stride_offset(i, s) + stride_offset(j, t))
        } else {
            None
        }
    }
}

impl Dimension for (Ix, Ix, Ix) {
    #[inline]
    fn ndim(&self) -> uint { 3 }
    #[inline]
    fn size(&self) -> uint { let (m, n, o) = *self; m as uint * n as uint * o as uint }
    #[inline]
    fn next_for(&self, index: (Ix, Ix, Ix)) -> Option<(Ix, Ix, Ix)> {
        let (mut i, mut j, mut k) = index;
        let (imax, jmax, kmax) = *self;
        k += 1;
        if k == kmax {
            k = 0;
            j += 1;
            if j == jmax {
                j = 0;
                i += 1;
                if i == imax {
                    return None;
                }
            }
        }
        Some((i, j, k))
    }

    /// Self is an index, return the stride offset
    #[inline]
    fn stride_offset(index: &(Ix, Ix, Ix), strides: &(Ix, Ix, Ix)) -> int
    {
        let (i, j, k) = *index;
        let (s, t, u) = *strides;
        stride_offset(i, s) + stride_offset(j, t) + stride_offset(k, u)
    }
}

impl Dimension for (Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 4 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 5 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 6 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 7 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 8 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 9 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 10 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 11 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 12 } }

// Vec<Ix> is a "dynamic" index, pretty hard to use when indexing,
// and memory wasteful, but it allows an arbitrary number of dimensions.
//
// NOTE: No Shrink impl for Vec<Ix> yet.
impl Dimension for Vec<Ix>
{
    fn ndim(&self) -> uint { self.len() }
    fn slice(&self) -> &[Ix] { self[] }
    fn slice_mut(&mut self) -> &mut [Ix] { self.as_mut_slice() }
}

/// Construct one-dimensional array shape. Helper function to use where
/// integer literal inference isn't working.
#[inline]
pub fn d1(a: Ix) -> Ix { a }
/// Construct two-dimensional array shape. Helper function to use where
/// integer literal inference isn't working.
#[inline]
pub fn d2(a: Ix, b: Ix) -> (Ix, Ix) { (a, b) }
/// Construct three-dimensional array shape. Helper function to use where
/// integer literal inference isn't working.
#[inline]
pub fn d3(a: Ix, b: Ix, c: Ix) -> (Ix, Ix, Ix) { (a, b, c) }
/// Construct four-dimensional array shape. Helper function to use where
/// integer literal inference isn't working.
#[inline]
pub fn d4(a: Ix, b: Ix, c: Ix, d: Ix) -> (Ix, Ix, Ix, Ix) { (a, b, c, d) }

/// Helper trait to define a larger-than relation for array shapes:
/// removing one axis from *Self* gives smaller dimension *E*.
pub trait RemoveAxis<E: Dimension> : Dimension {
    fn remove_axis(&self, axis: uint) -> E;
}

macro_rules! impl_shrink(
    ($from:ident $(,$more:ident)*) => (
impl RemoveAxis<($($more),*)> for ($from $(,$more)*)
{
    #[allow(unused_parens)]
    fn remove_axis(&self, axis: uint) -> ($($more),*) {
        let mut tup = ($(0 as $more),*);
        {
            let mut it = tup.slice_mut().iter_mut();
            for (i, &d) in self.slice().iter().enumerate() {
                if i == axis {
                    continue;
                }
                for rr in it {
                    *rr = d;
                    break
                }
            }
        }
        tup
    }
}
    )
)

macro_rules! impl_shrink_recursive(
    ($ix:ident) => (impl_shrink!($ix));
    ($ix1:ident $(,$ix:ident)*) => (
        impl_shrink_recursive!($($ix),*)
        impl_shrink!($ix1 $(,$ix)*)
    )
)

// 12 is the maximum number for having the Eq trait from libstd
impl_shrink_recursive!(Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix)

// [a:b:s] syntax for example [:3], [::-1]
// [0,:] -- first row of matrix
// [:,0] -- first column of matrix

#[deriving(Clone, PartialEq, Eq, Hash, Show)]
/// A slice, a description of a range of an array axis.
///
/// Fields are `begin`, `end` and `stride`, where
/// negative `begin` or `end` indexes are counted from the back
/// of the axis.
///
/// If `end` is `None`, the slice extends to the end of the axis.
///
/// ## Examples
///
/// `Si(0, None, 1)` is the full range of an axis.
/// Python equivalent is `[:]`.
///
/// `Si(a, Some(b), 2)` is every second element from `a` until `b`.
/// Python equivalent is `[a:b:2]`.
///
/// `Si(a, None, -1)` is every element, in reverse order, from `a`
/// until the end. Python equivalent is `[a::-1]`
pub struct Si(pub Ixs, pub Option<Ixs>, pub Ixs);

/// Slice value for the full range of an axis.
pub static S: Si = Si(0, None, 1);

<commit_msg>num::div_rem is deprecated<commit_after>use std::mem;
use std::num::SignedInt;
use std::raw;

use super::{Ix, Ixs};

/// Calculate offset from `Ix` stride converting sign properly
#[inline]
pub fn stride_offset(n: Ix, stride: Ix) -> int
{
    (n as int) * ((stride as Ixs) as int)
}

/*
#[inline]
pub fn stride_as_int(stride: Ix) -> int
{
    (stride as Ixs) as int
}
*/

/// Trait for the shape and index types of arrays.
pub trait Dimension : Clone + Eq {
    fn ndim(&self) -> uint;
    fn slice<'a>(&'a self) -> &'a [Ix] {
        unsafe {
            mem::transmute(raw::Slice {
                data: self as *const _ as *const Ix,
                len: self.ndim(),
            })
        }
    }

    fn slice_mut<'a>(&'a mut self) -> &'a mut [Ix] {
        unsafe {
            mem::transmute(raw::Slice {
                data: self as *mut _ as *const Ix,
                len: self.ndim(),
            })
        }
    }

    fn size(&self) -> uint {
        self.slice().iter().fold(1u, |s, &a| s * a as uint)
    }

    fn default_strides(&self) -> Self {
        // Compute default array strides
        // Shape (a, b, c) => Give strides (b * c, c, 1)
        let mut strides = self.clone();
        {
            let mut it = strides.slice_mut().iter_mut().rev();
            // Set first element to 1
            for rs in it {
                *rs = 1;
                break;
            }
            let mut cum_prod = 1;
            for (rs, dim) in it.zip(self.slice().iter().rev()) {
                cum_prod *= *dim;
                *rs = cum_prod;
            }
        }
        strides
    }

    #[inline]
    fn first_index(&self) -> Option<Self>
    {
        for ax in self.slice().iter() {
            if *ax == 0 {
                return None
            }
        }
        let mut index = self.clone();
        for rr in index.slice_mut().iter_mut() {
            *rr = 0;
        }
        Some(index)
    }

    /// Iteration -- Use self as size, and return next index after `index`
    /// or None if there are no more.
    // FIXME: use &Self for index or even &mut?
    #[inline]
    fn next_for(&self, index: Self) -> Option<Self> {
        let mut index = index;
        let mut done = false;
        for (&dim, ix) in self.slice().iter().rev()
                            .zip(index.slice_mut().iter_mut().rev())
        {
            *ix += 1;
            if *ix == dim {
                *ix = 0;
            } else {
                done = true;
                break;
            }
        }
        if done {
            Some(index)
        } else { None }
    }

    /// Return stride offset for index.
    fn stride_offset(index: &Self, strides: &Self) -> int
    {
        let mut offset = 0;
        for (&i, &s) in index.slice().iter()
                            .zip(strides.slice().iter()) {
            offset += stride_offset(i, s);
        }
        offset
    }

    /// Return stride offset for this dimension and index.
    fn stride_offset_checked(&self, strides: &Self, index: &Self) -> Option<int>
    {
        let mut offset = 0;
        for ((&d, &i), &s) in self.slice().iter()
                                .zip(index.slice().iter())
                                .zip(strides.slice().iter())
        {
            if i >= d {
                return None;
            }
            offset += stride_offset(i, s);
        }
        Some(offset)
    }

    /// Modify dimension, strides and return data pointer offset
    ///
    /// **Panics** if `slices` does not correspond to the number of axes,
    /// if any stride is 0, or if any index is out of bounds.
    fn do_slices(dim: &mut Self, strides: &mut Self, slices: &[Si]) -> int
    {
        let mut offset = 0;
        assert!(slices.len() == dim.slice().len());
        for ((dr, sr), &slc) in dim.slice_mut().iter_mut()
                                .zip(strides.slice_mut().iter_mut())
                                .zip(slices.iter())
        {
            let m = *dr;
            let mi = m as Ixs;
            let Si(b1, opt_e1, s1) = slc;
            let e1 = opt_e1.unwrap_or(mi);

            let b1 = abs_index(mi, b1);
            let mut e1 = abs_index(mi, e1);
            if e1 < b1 { e1 = b1; }

            assert!(b1 <= m);
            assert!(e1 <= m);

            let m = e1 - b1;
            // stride
            let s = (*sr) as Ixs;

            // Data pointer offset
            offset += stride_offset(b1, *sr);
            // Adjust for strides
            assert!(s1 != 0);
            // How to implement negative strides:
            //
            // Increase start pointer by
            // old stride * (old dim - 1)
            // to put the pointer completely in the other end
            if s1 < 0 {
                offset += stride_offset(m - 1, *sr);
            }

            let s_prim = s * s1;

            let d = m / s1.abs() as Ix;
            let r = m % s1.abs() as Ix;
            let m_prim = d + if r > 0 { 1 } else { 0 };

            // Update dimension and stride coordinate
            *dr = m_prim;
            *sr = s_prim as Ix;
        }
        offset
    }
}

fn abs_index(len: Ixs, index: Ixs) -> Ix {
    if index < 0 {
        (len + index) as Ix
    } else { index as Ix }
}

/// Collapse axis `axis` and shift so that only subarray `index` is
/// available.
///
/// **Panics** if `index` is larger than the size of the axis
// FIXME: Move to Dimension trait
pub fn do_sub<A, D: Dimension, P: Copy + RawPtr<A>>(dims: &mut D, ptr: &mut P, strides: &D,
                           axis: uint, index: Ix)
{
    let dim = dims.slice()[axis];
    let stride = strides.slice()[axis];
    assert!(index < dim);
    dims.slice_mut()[axis] = 1;
    let off = stride_offset(index, stride);
    unsafe {
        *ptr = ptr.offset(off);
    }
}

impl Dimension for () {
    // empty product is 1 -> size is 1
    #[inline]
    fn ndim(&self) -> uint { 0 }
    fn slice(&self) -> &[Ix] { &[] }
    fn slice_mut(&mut self) -> &mut [Ix] { &mut [] }
}

impl Dimension for Ix {
    #[inline]
    fn ndim(&self) -> uint { 1 }
    #[inline]
    fn size(&self) -> uint { *self as uint }
    #[inline]
    fn first_index(&self) -> Option<Ix> {
        if *self != 0 {
            Some(0)
        } else { None }
    }
    #[inline]
    fn next_for(&self, mut index: Ix) -> Option<Ix> {
        index += 1;
        if index < *self {
            Some(index)
        } else { None }
    }

    /// Self is an index, return the stride offset
    #[inline]
    fn stride_offset(index: &Ix, stride: &Ix) -> int
    {
        stride_offset(*index, *stride)
    }

    /// Return stride offset for this dimension and index.
    fn stride_offset_checked(&self, stride: &Ix, index: &Ix) -> Option<int>
    {
        if *index < *self {
            Some(stride_offset(*index, *stride))
        } else {
            None
        }
    }
}

impl Dimension for (Ix, Ix) {
    #[inline]
    fn ndim(&self) -> uint { 2 }
    #[inline]
    fn size(&self) -> uint { let (m, n) = *self; m as uint * n as uint }
    #[inline]
    fn first_index(&self) -> Option<(Ix, Ix)> {
        let (m, n) = *self;
        if m != 0 && n != 0 {
            Some((0, 0))
        } else { None }
    }
    #[inline]
    fn next_for(&self, index: (Ix, Ix)) -> Option<(Ix, Ix)> {
        let (mut i, mut j) = index;
        let (imax, jmax) = *self;
        j += 1;
        if j == jmax {
            j = 0;
            i += 1;
            if i == imax {
                return None;
            }
        }
        Some((i, j))
    }

    /// Self is an index, return the stride offset
    #[inline]
    fn stride_offset(index: &(Ix, Ix), strides: &(Ix, Ix)) -> int
    {
        let (i, j) = *index;
        let (s, t) = *strides;
        stride_offset(i, s) + stride_offset(j, t)
    }

    /// Return stride offset for this dimension and index.
    fn stride_offset_checked(&self, strides: &(Ix, Ix), index: &(Ix, Ix)) -> Option<int>
    {
        let (m, n) = *self;
        let (i, j) = *index;
        let (s, t) = *strides;
        if i < m && j < n {
            Some(stride_offset(i, s) + stride_offset(j, t))
        } else {
            None
        }
    }
}

impl Dimension for (Ix, Ix, Ix) {
    #[inline]
    fn ndim(&self) -> uint { 3 }
    #[inline]
    fn size(&self) -> uint { let (m, n, o) = *self; m as uint * n as uint * o as uint }
    #[inline]
    fn next_for(&self, index: (Ix, Ix, Ix)) -> Option<(Ix, Ix, Ix)> {
        let (mut i, mut j, mut k) = index;
        let (imax, jmax, kmax) = *self;
        k += 1;
        if k == kmax {
            k = 0;
            j += 1;
            if j == jmax {
                j = 0;
                i += 1;
                if i == imax {
                    return None;
                }
            }
        }
        Some((i, j, k))
    }

    /// Self is an index, return the stride offset
    #[inline]
    fn stride_offset(index: &(Ix, Ix, Ix), strides: &(Ix, Ix, Ix)) -> int
    {
        let (i, j, k) = *index;
        let (s, t, u) = *strides;
        stride_offset(i, s) + stride_offset(j, t) + stride_offset(k, u)
    }
}

impl Dimension for (Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 4 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 5 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 6 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 7 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 8 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 9 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 10 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 11 } }
impl Dimension for (Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix) { fn ndim(&self) -> uint { 12 } }

// Vec<Ix> is a "dynamic" index, pretty hard to use when indexing,
// and memory wasteful, but it allows an arbitrary number of dimensions.
//
// NOTE: No Shrink impl for Vec<Ix> yet.
impl Dimension for Vec<Ix>
{
    fn ndim(&self) -> uint { self.len() }
    fn slice(&self) -> &[Ix] { self[] }
    fn slice_mut(&mut self) -> &mut [Ix] { self.as_mut_slice() }
}

/// Construct one-dimensional array shape. Helper function to use where
/// integer literal inference isn't working.
#[inline]
pub fn d1(a: Ix) -> Ix { a }
/// Construct two-dimensional array shape. Helper function to use where
/// integer literal inference isn't working.
#[inline]
pub fn d2(a: Ix, b: Ix) -> (Ix, Ix) { (a, b) }
/// Construct three-dimensional array shape. Helper function to use where
/// integer literal inference isn't working.
#[inline]
pub fn d3(a: Ix, b: Ix, c: Ix) -> (Ix, Ix, Ix) { (a, b, c) }
/// Construct four-dimensional array shape. Helper function to use where
/// integer literal inference isn't working.
#[inline]
pub fn d4(a: Ix, b: Ix, c: Ix, d: Ix) -> (Ix, Ix, Ix, Ix) { (a, b, c, d) }

/// Helper trait to define a larger-than relation for array shapes:
/// removing one axis from *Self* gives smaller dimension *E*.
pub trait RemoveAxis<E: Dimension> : Dimension {
    fn remove_axis(&self, axis: uint) -> E;
}

macro_rules! impl_shrink(
    ($from:ident $(,$more:ident)*) => (
impl RemoveAxis<($($more),*)> for ($from $(,$more)*)
{
    #[allow(unused_parens)]
    fn remove_axis(&self, axis: uint) -> ($($more),*) {
        let mut tup = ($(0 as $more),*);
        {
            let mut it = tup.slice_mut().iter_mut();
            for (i, &d) in self.slice().iter().enumerate() {
                if i == axis {
                    continue;
                }
                for rr in it {
                    *rr = d;
                    break
                }
            }
        }
        tup
    }
}
    )
)

macro_rules! impl_shrink_recursive(
    ($ix:ident) => (impl_shrink!($ix));
    ($ix1:ident $(,$ix:ident)*) => (
        impl_shrink_recursive!($($ix),*)
        impl_shrink!($ix1 $(,$ix)*)
    )
)

// 12 is the maximum number for having the Eq trait from libstd
impl_shrink_recursive!(Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix, Ix)

// [a:b:s] syntax for example [:3], [::-1]
// [0,:] -- first row of matrix
// [:,0] -- first column of matrix

#[deriving(Clone, PartialEq, Eq, Hash, Show)]
/// A slice, a description of a range of an array axis.
///
/// Fields are `begin`, `end` and `stride`, where
/// negative `begin` or `end` indexes are counted from the back
/// of the axis.
///
/// If `end` is `None`, the slice extends to the end of the axis.
///
/// ## Examples
///
/// `Si(0, None, 1)` is the full range of an axis.
/// Python equivalent is `[:]`.
///
/// `Si(a, Some(b), 2)` is every second element from `a` until `b`.
/// Python equivalent is `[a:b:2]`.
///
/// `Si(a, None, -1)` is every element, in reverse order, from `a`
/// until the end. Python equivalent is `[a::-1]`
pub struct Si(pub Ixs, pub Option<Ixs>, pub Ixs);

/// Slice value for the full range of an axis.
pub static S: Si = Si(0, None, 1);

<|endoftext|>


<commit_before>extern crate time;

use kissrng::KissRng;

pub fn rand_dna(n: usize) -> String {
    let mut sequence = String::new();
    let mut rng = KissRng::new();

    for _ in 0..n {
        sequence.push(
            match rng.next() % 4 {
                0 => 'A',
                1 => 'C',
                2 => 'G',
                _ => 'T'
            }
        );
    }

    return sequence;
}

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

    #[test]
    fn test_rand_dna() {
        let seq_len = 1000;
        let seq = rand_dna(seq_len);
        println!("{:?}",&seq);
        assert_eq!(seq_len, seq.len());
    }
}
<commit_msg>Upped test generation to 1000000<commit_after>extern crate time;

use kissrng::KissRng;

pub fn rand_dna(n: usize) -> String {
    let mut sequence = String::new();
    let mut rng = KissRng::new();

    for _ in 0..n {
        sequence.push(
            match rng.next() % 4 {
                0 => 'A',
                1 => 'C',
                2 => 'G',
                _ => 'T'
            }
        );
    }

    return sequence;
}

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

    #[test]
    fn test_rand_dna() {
        let seq_len = 1000000;
        let seq = rand_dna(seq_len);
        println!("{:?}",&seq);
        assert_eq!(seq_len, seq.len());
    }
}
<|endoftext|>


<commit_before>use std::ffi::CString;
use std::fmt;
use std::path::Path;

use curl_sys;
use easy::{list, List};
use FormError;

/// Multipart/formdata for an HTTP POST request.
///
/// This structure is built up and then passed to the `Easy::httppost` method to
/// be sent off with a request.
pub struct Form {
    head: *mut curl_sys::curl_httppost,
    tail: *mut curl_sys::curl_httppost,
    headers: Vec<List>,
    buffers: Vec<Vec<u8>>,
    strings: Vec<CString>,
}

/// One part in a multipart upload, added to a `Form`.
pub struct Part<'form, 'data> {
    form: &'form mut Form,
    name: &'data str,
    array: Vec<curl_sys::curl_forms>,
    error: Option<FormError>,
}

pub fn raw(form: &Form) -> *mut curl_sys::curl_httppost {
    form.head
}

impl Form {
    /// Creates a new blank form ready for the addition of new data.
    pub fn new() -> Form {
        Form {
            head: 0 as *mut _,
            tail: 0 as *mut _,
            headers: Vec::new(),
            buffers: Vec::new(),
            strings: Vec::new(),
        }
    }

    /// Prepares adding a new part to this `Form`
    ///
    /// Note that the part is not actually added to the form until the `add`
    /// method is called on `Part`, which may or may not fail.
    pub fn part<'a, 'data>(&'a mut self, name: &'data str) -> Part<'a, 'data> {
        Part {
            error: None,
            form: self,
            name: name,
            array: vec![curl_sys::curl_forms {
                option: curl_sys::CURLFORM_END,
                value: 0 as *mut _,
            }],
        }
    }
}

impl fmt::Debug for Form {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: fill this out more
        f.debug_struct("Form").field("fields", &"...").finish()
    }
}

impl Drop for Form {
    fn drop(&mut self) {
        unsafe {
            curl_sys::curl_formfree(self.head);
        }
    }
}

impl<'form, 'data> Part<'form, 'data> {
    /// A pointer to the contents of this part, the actual data to send away.
    pub fn contents(&mut self, contents: &'data [u8]) -> &mut Self {
        let pos = self.array.len() - 1;

        // curl has an oddity where if the length if 0 it will call strlen
        // on the value.  This means that if someone wants to add empty form
        // contents we need to make sure the buffer contains a null byte.
        let ptr = if contents.is_empty() {
            b"\x00"
        } else {
            contents
        }
        .as_ptr();

        self.array.insert(
            pos,
            curl_sys::curl_forms {
                option: curl_sys::CURLFORM_COPYCONTENTS,
                value: ptr as *mut _,
            },
        );
        self.array.insert(
            pos + 1,
            curl_sys::curl_forms {
                option: curl_sys::CURLFORM_CONTENTSLENGTH,
                value: contents.len() as *mut _,
            },
        );
        self
    }

    /// Causes this file to be read and its contents used as data in this part
    ///
    /// This part does not automatically become a file upload part simply
    /// because its data was read from a file.
    ///
    /// # Errors
    ///
    /// If the filename has any internal nul bytes or if on Windows it does not
    /// contain a unicode filename then the `add` function will eventually
    /// return an error.
    pub fn file_content<P>(&mut self, file: P) -> &mut Self
    where
        P: AsRef<Path>,
    {
        self._file_content(file.as_ref())
    }

    fn _file_content(&mut self, file: &Path) -> &mut Self {
        if let Some(bytes) = self.path2cstr(file) {
            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_FILECONTENT,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
        }
        self
    }

    /// Makes this part a file upload part of the given file.
    ///
    /// Sets the filename field to the basename of the provided file name, and
    /// it reads the contents of the file and passes them as data and sets the
    /// content type if the given file matches one of the internally known file
    /// extensions.
    ///
    /// The given upload file must exist entirely on the filesystem before the
    /// upload is started because libcurl needs to read the size of it
    /// beforehand.
    ///
    /// Multiple files can be uploaded by calling this method multiple times and
    /// content types can also be configured for each file (by calling that
    /// next).
    ///
    /// # Errors
    ///
    /// If the filename has any internal nul bytes or if on Windows it does not
    /// contain a unicode filename then this function will cause `add` to return
    /// an error when called.
    pub fn file<P: ?Sized>(&mut self, file: &'data P) -> &mut Self
    where
        P: AsRef<Path>,
    {
        self._file(file.as_ref())
    }

    fn _file(&mut self, file: &'data Path) -> &mut Self {
        if let Some(bytes) = self.path2cstr(file) {
            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_FILE,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
        }
        self
    }

    /// Used in combination with `Part::file`, provides the content-type for
    /// this part, possibly instead of choosing an internal one.
    ///
    /// # Panics
    ///
    /// This function will panic if `content_type` contains an internal nul
    /// byte.
    pub fn content_type(&mut self, content_type: &'data str) -> &mut Self {
        if let Some(bytes) = self.bytes2cstr(content_type.as_bytes()) {
            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_CONTENTTYPE,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
        }
        self
    }

    /// Used in combination with `Part::file`, provides the filename for
    /// this part instead of the actual one.
    ///
    /// # Errors
    ///
    /// If `name` contains an internal nul byte, or if on Windows the path is
    /// not valid unicode then this function will return an error when `add` is
    /// called.
    pub fn filename<P: ?Sized>(&mut self, name: &'data P) -> &mut Self
    where
        P: AsRef<Path>,
    {
        self._filename(name.as_ref())
    }

    fn _filename(&mut self, name: &'data Path) -> &mut Self {
        if let Some(bytes) = self.path2cstr(name) {
            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_FILENAME,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
        }
        self
    }

    /// This is used to provide a custom file upload part without using the
    /// `file` method above.
    ///
    /// The first parameter is for the filename field and the second is the
    /// in-memory contents.
    ///
    /// # Errors
    ///
    /// If `name` contains an internal nul byte, or if on Windows the path is
    /// not valid unicode then this function will return an error when `add` is
    /// called.
    pub fn buffer<P: ?Sized>(&mut self, name: &'data P, data: Vec<u8>) -> &mut Self
    where
        P: AsRef<Path>,
    {
        self._buffer(name.as_ref(), data)
    }

    fn _buffer(&mut self, name: &'data Path, data: Vec<u8>) -> &mut Self {
        if let Some(bytes) = self.path2cstr(name) {
            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_BUFFER,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
            self.array.insert(
                pos + 1,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_BUFFERPTR,
                    value: data.as_ptr() as *mut _,
                },
            );
            self.array.insert(
                pos + 2,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_BUFFERLENGTH,
                    value: data.len() as *mut _,
                },
            );
            self.form.buffers.push(data);
        }
        self
    }

    /// Specifies extra headers for the form POST section.
    ///
    /// Appends the list of headers to those libcurl automatically generates.
    pub fn content_header(&mut self, headers: List) -> &mut Self {
        let pos = self.array.len() - 1;
        self.array.insert(
            pos,
            curl_sys::curl_forms {
                option: curl_sys::CURLFORM_CONTENTHEADER,
                value: list::raw(&headers) as *mut _,
            },
        );
        self.form.headers.push(headers);
        self
    }

    /// Attempts to add this part to the `Form` that it was created from.
    ///
    /// If any error happens while adding, that error is returned, otherwise
    /// `Ok(())` is returned.
    pub fn add(&mut self) -> Result<(), FormError> {
        if let Some(err) = self.error.clone() {
            return Err(err);
        }
        let rc = unsafe {
            curl_sys::curl_formadd(
                &mut self.form.head,
                &mut self.form.tail,
                curl_sys::CURLFORM_COPYNAME,
                self.name.as_ptr(),
                curl_sys::CURLFORM_NAMELENGTH,
                self.name.len(),
                curl_sys::CURLFORM_ARRAY,
                self.array.as_ptr(),
                curl_sys::CURLFORM_END,
            )
        };
        if rc == curl_sys::CURL_FORMADD_OK {
            Ok(())
        } else {
            Err(FormError::new(rc))
        }
    }

    #[cfg(unix)]
    fn path2cstr(&mut self, p: &Path) -> Option<CString> {
        use std::os::unix::prelude::*;
        self.bytes2cstr(p.as_os_str().as_bytes())
    }

    #[cfg(windows)]
    fn path2cstr(&mut self, p: &Path) -> Option<CString> {
        match p.to_str() {
            Some(bytes) => self.bytes2cstr(bytes.as_bytes()),
            None if self.error.is_none() => {
                // TODO: better error code
                self.error = Some(FormError::new(curl_sys::CURL_FORMADD_INCOMPLETE));
                None
            }
            None => None,
        }
    }

    fn bytes2cstr(&mut self, bytes: &[u8]) -> Option<CString> {
        match CString::new(bytes) {
            Ok(c) => Some(c),
            Err(..) if self.error.is_none() => {
                // TODO: better error code
                self.error = Some(FormError::new(curl_sys::CURL_FORMADD_INCOMPLETE));
                None
            }
            Err(..) => None,
        }
    }
}

impl<'form, 'data> fmt::Debug for Part<'form, 'data> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: fill this out more
        f.debug_struct("Part")
            .field("name", &self.name)
            .field("form", &self.form)
            .finish()
    }
}
<commit_msg>Do not crash with a segfault if empty buffer is passed<commit_after>use std::ffi::CString;
use std::fmt;
use std::path::Path;

use curl_sys;
use easy::{list, List};
use FormError;

/// Multipart/formdata for an HTTP POST request.
///
/// This structure is built up and then passed to the `Easy::httppost` method to
/// be sent off with a request.
pub struct Form {
    head: *mut curl_sys::curl_httppost,
    tail: *mut curl_sys::curl_httppost,
    headers: Vec<List>,
    buffers: Vec<Vec<u8>>,
    strings: Vec<CString>,
}

/// One part in a multipart upload, added to a `Form`.
pub struct Part<'form, 'data> {
    form: &'form mut Form,
    name: &'data str,
    array: Vec<curl_sys::curl_forms>,
    error: Option<FormError>,
}

pub fn raw(form: &Form) -> *mut curl_sys::curl_httppost {
    form.head
}

impl Form {
    /// Creates a new blank form ready for the addition of new data.
    pub fn new() -> Form {
        Form {
            head: 0 as *mut _,
            tail: 0 as *mut _,
            headers: Vec::new(),
            buffers: Vec::new(),
            strings: Vec::new(),
        }
    }

    /// Prepares adding a new part to this `Form`
    ///
    /// Note that the part is not actually added to the form until the `add`
    /// method is called on `Part`, which may or may not fail.
    pub fn part<'a, 'data>(&'a mut self, name: &'data str) -> Part<'a, 'data> {
        Part {
            error: None,
            form: self,
            name: name,
            array: vec![curl_sys::curl_forms {
                option: curl_sys::CURLFORM_END,
                value: 0 as *mut _,
            }],
        }
    }
}

impl fmt::Debug for Form {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: fill this out more
        f.debug_struct("Form").field("fields", &"...").finish()
    }
}

impl Drop for Form {
    fn drop(&mut self) {
        unsafe {
            curl_sys::curl_formfree(self.head);
        }
    }
}

impl<'form, 'data> Part<'form, 'data> {
    /// A pointer to the contents of this part, the actual data to send away.
    pub fn contents(&mut self, contents: &'data [u8]) -> &mut Self {
        let pos = self.array.len() - 1;

        // curl has an oddity where if the length if 0 it will call strlen
        // on the value.  This means that if someone wants to add empty form
        // contents we need to make sure the buffer contains a null byte.
        let ptr = if contents.is_empty() {
            b"\x00"
        } else {
            contents
        }
        .as_ptr();

        self.array.insert(
            pos,
            curl_sys::curl_forms {
                option: curl_sys::CURLFORM_COPYCONTENTS,
                value: ptr as *mut _,
            },
        );
        self.array.insert(
            pos + 1,
            curl_sys::curl_forms {
                option: curl_sys::CURLFORM_CONTENTSLENGTH,
                value: contents.len() as *mut _,
            },
        );
        self
    }

    /// Causes this file to be read and its contents used as data in this part
    ///
    /// This part does not automatically become a file upload part simply
    /// because its data was read from a file.
    ///
    /// # Errors
    ///
    /// If the filename has any internal nul bytes or if on Windows it does not
    /// contain a unicode filename then the `add` function will eventually
    /// return an error.
    pub fn file_content<P>(&mut self, file: P) -> &mut Self
    where
        P: AsRef<Path>,
    {
        self._file_content(file.as_ref())
    }

    fn _file_content(&mut self, file: &Path) -> &mut Self {
        if let Some(bytes) = self.path2cstr(file) {
            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_FILECONTENT,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
        }
        self
    }

    /// Makes this part a file upload part of the given file.
    ///
    /// Sets the filename field to the basename of the provided file name, and
    /// it reads the contents of the file and passes them as data and sets the
    /// content type if the given file matches one of the internally known file
    /// extensions.
    ///
    /// The given upload file must exist entirely on the filesystem before the
    /// upload is started because libcurl needs to read the size of it
    /// beforehand.
    ///
    /// Multiple files can be uploaded by calling this method multiple times and
    /// content types can also be configured for each file (by calling that
    /// next).
    ///
    /// # Errors
    ///
    /// If the filename has any internal nul bytes or if on Windows it does not
    /// contain a unicode filename then this function will cause `add` to return
    /// an error when called.
    pub fn file<P: ?Sized>(&mut self, file: &'data P) -> &mut Self
    where
        P: AsRef<Path>,
    {
        self._file(file.as_ref())
    }

    fn _file(&mut self, file: &'data Path) -> &mut Self {
        if let Some(bytes) = self.path2cstr(file) {
            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_FILE,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
        }
        self
    }

    /// Used in combination with `Part::file`, provides the content-type for
    /// this part, possibly instead of choosing an internal one.
    ///
    /// # Panics
    ///
    /// This function will panic if `content_type` contains an internal nul
    /// byte.
    pub fn content_type(&mut self, content_type: &'data str) -> &mut Self {
        if let Some(bytes) = self.bytes2cstr(content_type.as_bytes()) {
            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_CONTENTTYPE,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
        }
        self
    }

    /// Used in combination with `Part::file`, provides the filename for
    /// this part instead of the actual one.
    ///
    /// # Errors
    ///
    /// If `name` contains an internal nul byte, or if on Windows the path is
    /// not valid unicode then this function will return an error when `add` is
    /// called.
    pub fn filename<P: ?Sized>(&mut self, name: &'data P) -> &mut Self
    where
        P: AsRef<Path>,
    {
        self._filename(name.as_ref())
    }

    fn _filename(&mut self, name: &'data Path) -> &mut Self {
        if let Some(bytes) = self.path2cstr(name) {
            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_FILENAME,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
        }
        self
    }

    /// This is used to provide a custom file upload part without using the
    /// `file` method above.
    ///
    /// The first parameter is for the filename field and the second is the
    /// in-memory contents.
    ///
    /// # Errors
    ///
    /// If `name` contains an internal nul byte, or if on Windows the path is
    /// not valid unicode then this function will return an error when `add` is
    /// called.
    pub fn buffer<P: ?Sized>(&mut self, name: &'data P, data: Vec<u8>) -> &mut Self
    where
        P: AsRef<Path>,
    {
        self._buffer(name.as_ref(), data)
    }

    fn _buffer(&mut self, name: &'data Path, mut data: Vec<u8>) -> &mut Self {
        if let Some(bytes) = self.path2cstr(name) {
            // If `CURLFORM_BUFFERLENGTH` is set to `0`, libcurl will instead do a strlen() on the
            // contents to figure out the size so we need to make sure the buffer is actually
            // zero terminated.
            let length = data.len();
            if length == 0 {
                data.push(0);
            }

            let pos = self.array.len() - 1;
            self.array.insert(
                pos,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_BUFFER,
                    value: bytes.as_ptr() as *mut _,
                },
            );
            self.form.strings.push(bytes);
            self.array.insert(
                pos + 1,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_BUFFERPTR,
                    value: data.as_ptr() as *mut _,
                },
            );
            self.array.insert(
                pos + 2,
                curl_sys::curl_forms {
                    option: curl_sys::CURLFORM_BUFFERLENGTH,
                    value: length as *mut _,
                },
            );
            self.form.buffers.push(data);
        }
        self
    }

    /// Specifies extra headers for the form POST section.
    ///
    /// Appends the list of headers to those libcurl automatically generates.
    pub fn content_header(&mut self, headers: List) -> &mut Self {
        let pos = self.array.len() - 1;
        self.array.insert(
            pos,
            curl_sys::curl_forms {
                option: curl_sys::CURLFORM_CONTENTHEADER,
                value: list::raw(&headers) as *mut _,
            },
        );
        self.form.headers.push(headers);
        self
    }

    /// Attempts to add this part to the `Form` that it was created from.
    ///
    /// If any error happens while adding, that error is returned, otherwise
    /// `Ok(())` is returned.
    pub fn add(&mut self) -> Result<(), FormError> {
        if let Some(err) = self.error.clone() {
            return Err(err);
        }
        let rc = unsafe {
            curl_sys::curl_formadd(
                &mut self.form.head,
                &mut self.form.tail,
                curl_sys::CURLFORM_COPYNAME,
                self.name.as_ptr(),
                curl_sys::CURLFORM_NAMELENGTH,
                self.name.len(),
                curl_sys::CURLFORM_ARRAY,
                self.array.as_ptr(),
                curl_sys::CURLFORM_END,
            )
        };
        if rc == curl_sys::CURL_FORMADD_OK {
            Ok(())
        } else {
            Err(FormError::new(rc))
        }
    }

    #[cfg(unix)]
    fn path2cstr(&mut self, p: &Path) -> Option<CString> {
        use std::os::unix::prelude::*;
        self.bytes2cstr(p.as_os_str().as_bytes())
    }

    #[cfg(windows)]
    fn path2cstr(&mut self, p: &Path) -> Option<CString> {
        match p.to_str() {
            Some(bytes) => self.bytes2cstr(bytes.as_bytes()),
            None if self.error.is_none() => {
                // TODO: better error code
                self.error = Some(FormError::new(curl_sys::CURL_FORMADD_INCOMPLETE));
                None
            }
            None => None,
        }
    }

    fn bytes2cstr(&mut self, bytes: &[u8]) -> Option<CString> {
        match CString::new(bytes) {
            Ok(c) => Some(c),
            Err(..) if self.error.is_none() => {
                // TODO: better error code
                self.error = Some(FormError::new(curl_sys::CURL_FORMADD_INCOMPLETE));
                None
            }
            Err(..) => None,
        }
    }
}

impl<'form, 'data> fmt::Debug for Part<'form, 'data> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // TODO: fill this out more
        f.debug_struct("Part")
            .field("name", &self.name)
            .field("form", &self.form)
            .finish()
    }
}
<|endoftext|>


<commit_before>use gen::GenError;

pub trait SerializeFn<I>: Fn(I) -> Result<I, GenError> {}

impl<I, F:  Fn(I) ->Result<I, GenError>> SerializeFn<I> for F {}

pub fn slice<'a, S: 'a + AsRef<[u8]>>(data: S) -> impl SerializeFn<&'a mut [u8]> {
    let len = data.as_ref().len();

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            (&mut out[..len]).copy_from_slice(data.as_ref());
            Ok(&mut out[len..])
        }
    }
}

pub fn string<'a, S: 'a+AsRef<str>>(data: S) -> impl SerializeFn<&'a mut [u8]> {

    let len = data.as_ref().len();
    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            (&mut out[..len]).copy_from_slice(data.as_ref().as_bytes());
            Ok(&mut out[len..])
        }
    }
}

pub fn skip<'a>(len: usize) -> impl SerializeFn<&'a mut [u8]> {

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            Ok(&mut out[len..])
        }
    }
}

pub fn position<'a, F>(f: F) -> impl Fn(&'a mut [u8]) -> Result<(&'a mut [u8], &'a mut [u8]), GenError>
  where F: SerializeFn<&'a mut [u8]> {

    move |out: &'a mut [u8]| {
        unsafe {
            let ptr = out.as_mut_ptr();
            let out = f(out)?;
            let len = out.as_ptr() as usize - ptr as usize;

            Ok((std::slice::from_raw_parts_mut(ptr, len), out))
        }
    }
}

fn pair<F, G, I>(first: F, second: G) -> impl SerializeFn<I>
where F: SerializeFn<I>,
      G: SerializeFn<I> {

  move |out: I| {
    let out = first(out)?;
    second(out)
  }
}

fn cond<F, G, I>(condition: bool, f: F) -> impl SerializeFn<I>
where F: SerializeFn<I>, {

  move |out: I| {
    if condition {
      f(out)
    } else {
      Ok(out)
    }
  }
}

pub fn _all<'a, 'b, G, I, It: Iterator<Item=G>, Arg: 'a+Clone+IntoIterator<Item=G, IntoIter=It>>(values: Arg) -> impl SerializeFn<I> + 'a
  where G: SerializeFn<I> + 'b {

  move |mut out: I| {
    let mut it = values.clone().into_iter();

    for v in it {
      out = v(out)?;
    }

    Ok(out)
  }
}

pub fn separated_list<'a, 'b, 'c, F, G, I, It: Iterator<Item=G>, Arg: 'a+Clone+IntoIterator<Item=G, IntoIter=It>>(sep: F, values: Arg) -> impl SerializeFn<I> + 'a
  where F: SerializeFn<I> + 'b + 'a,
        G: SerializeFn<I> + 'c {

  move |mut out: I| {
    let mut it = values.clone().into_iter();
    match it.next() {
      None => return Ok(out),
      Some(first) => {
        out = first(out)?;
      }
    }

    for v in it {
      out = sep(out)?;
      out = v(out)?;
    }

    Ok(out)
  }
}

pub fn be_u8<'a>(i: u8) -> impl SerializeFn<&'a mut [u8]> {
   let len = 1;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = i;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u16<'a>(i: u16) -> impl SerializeFn<&'a mut [u8]> {
   let len = 2;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 8) & 0xff) as u8;
            out[1] = (i        & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u32<'a>(i: u32) -> impl SerializeFn<&'a mut [u8]> {
   let len = 4;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 24) & 0xff) as u8;
            out[1] = ((i >> 16) & 0xff) as u8;
            out[2] = ((i >> 8)  & 0xff) as u8;
            out[3] = (i         & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u64<'a>(i: u64) -> impl SerializeFn<&'a mut [u8]> {
   let len = 8;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 56) & 0xff) as u8;
            out[1] = ((i >> 48) & 0xff) as u8;
            out[2] = ((i >> 40) & 0xff) as u8;
            out[3] = ((i >> 32) & 0xff) as u8;
            out[4] = ((i >> 24) & 0xff) as u8;
            out[5] = ((i >> 16) & 0xff) as u8;
            out[6] = ((i >> 8)  & 0xff) as u8;
            out[7] = (i         & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u8<'a>(i: u8) -> impl SerializeFn<&'a mut [u8]> {
   let len = 1;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = i;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u16<'a>(i: u16) -> impl SerializeFn<&'a mut [u8]> {
   let len = 2;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i        & 0xff) as u8;
            out[1] = ((i >> 8) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u32<'a>(i: u32) -> impl SerializeFn<&'a mut [u8]> {
   let len = 4;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i         & 0xff) as u8;
            out[1] = ((i >> 8)  & 0xff) as u8;
            out[2] = ((i >> 16) & 0xff) as u8;
            out[3] = ((i >> 24) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u64<'a>(i: u64) -> impl SerializeFn<&'a mut [u8]> {
   let len = 8;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i         & 0xff) as u8;
            out[1] = ((i >> 8)  & 0xff) as u8;
            out[2] = ((i >> 16) & 0xff) as u8;
            out[3] = ((i >> 24) & 0xff) as u8;
            out[4] = ((i >> 32) & 0xff) as u8;
            out[5] = ((i >> 40) & 0xff) as u8;
            out[6] = ((i >> 48) & 0xff) as u8;
            out[7] = ((i >> 56) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}
///missing combinators:
///or
///empty
///then
///stream
///length_value
///text print
///text upperhex
///text lowerhex
struct Dummy;
<commit_msg>add the hex serializer<commit_after>use gen::GenError;

pub trait SerializeFn<I>: Fn(I) -> Result<I, GenError> {}

impl<I, F:  Fn(I) ->Result<I, GenError>> SerializeFn<I> for F {}

pub fn slice<'a, S: 'a + AsRef<[u8]>>(data: S) -> impl SerializeFn<&'a mut [u8]> {
    let len = data.as_ref().len();

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            (&mut out[..len]).copy_from_slice(data.as_ref());
            Ok(&mut out[len..])
        }
    }
}

pub fn string<'a, S: 'a+AsRef<str>>(data: S) -> impl SerializeFn<&'a mut [u8]> {

    let len = data.as_ref().len();
    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            (&mut out[..len]).copy_from_slice(data.as_ref().as_bytes());
            Ok(&mut out[len..])
        }
    }
}

use std::io::{Cursor, Write};
use std::fmt;
pub fn hex<'a, S: 'a + fmt::UpperHex>(data: S) -> impl SerializeFn<&'a mut [u8]> {

  move |out: &'a mut [u8]| {
    let mut c = Cursor::new(out);
    match write!(&mut c, "{:X}", data) {
      Err(_) => Err(GenError::CustomError(42)),
      Ok(_) => {
        let pos = c.position() as usize;
        let out = c.into_inner();
        Ok(&mut out[pos..])
      }
    }
  }
}

pub fn skip<'a>(len: usize) -> impl SerializeFn<&'a mut [u8]> {

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            Ok(&mut out[len..])
        }
    }
}

pub fn position<'a, F>(f: F) -> impl Fn(&'a mut [u8]) -> Result<(&'a mut [u8], &'a mut [u8]), GenError>
  where F: SerializeFn<&'a mut [u8]> {

    move |out: &'a mut [u8]| {
        unsafe {
            let ptr = out.as_mut_ptr();
            let out = f(out)?;
            let len = out.as_ptr() as usize - ptr as usize;

            Ok((std::slice::from_raw_parts_mut(ptr, len), out))
        }
    }
}

fn pair<F, G, I>(first: F, second: G) -> impl SerializeFn<I>
where F: SerializeFn<I>,
      G: SerializeFn<I> {

  move |out: I| {
    let out = first(out)?;
    second(out)
  }
}

fn cond<F, G, I>(condition: bool, f: F) -> impl SerializeFn<I>
where F: SerializeFn<I>, {

  move |out: I| {
    if condition {
      f(out)
    } else {
      Ok(out)
    }
  }
}

pub fn _all<'a, 'b, G, I, It: Iterator<Item=G>, Arg: 'a+Clone+IntoIterator<Item=G, IntoIter=It>>(values: Arg) -> impl SerializeFn<I> + 'a
  where G: SerializeFn<I> + 'b {

  move |mut out: I| {
    let mut it = values.clone().into_iter();

    for v in it {
      out = v(out)?;
    }

    Ok(out)
  }
}

pub fn separated_list<'a, 'b, 'c, F, G, I, It: Iterator<Item=G>, Arg: 'a+Clone+IntoIterator<Item=G, IntoIter=It>>(sep: F, values: Arg) -> impl SerializeFn<I> + 'a
  where F: SerializeFn<I> + 'b + 'a,
        G: SerializeFn<I> + 'c {

  move |mut out: I| {
    let mut it = values.clone().into_iter();
    match it.next() {
      None => return Ok(out),
      Some(first) => {
        out = first(out)?;
      }
    }

    for v in it {
      out = sep(out)?;
      out = v(out)?;
    }

    Ok(out)
  }
}

pub fn be_u8<'a>(i: u8) -> impl SerializeFn<&'a mut [u8]> {
   let len = 1;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = i;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u16<'a>(i: u16) -> impl SerializeFn<&'a mut [u8]> {
   let len = 2;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 8) & 0xff) as u8;
            out[1] = (i        & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u32<'a>(i: u32) -> impl SerializeFn<&'a mut [u8]> {
   let len = 4;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 24) & 0xff) as u8;
            out[1] = ((i >> 16) & 0xff) as u8;
            out[2] = ((i >> 8)  & 0xff) as u8;
            out[3] = (i         & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn be_u64<'a>(i: u64) -> impl SerializeFn<&'a mut [u8]> {
   let len = 8;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = ((i >> 56) & 0xff) as u8;
            out[1] = ((i >> 48) & 0xff) as u8;
            out[2] = ((i >> 40) & 0xff) as u8;
            out[3] = ((i >> 32) & 0xff) as u8;
            out[4] = ((i >> 24) & 0xff) as u8;
            out[5] = ((i >> 16) & 0xff) as u8;
            out[6] = ((i >> 8)  & 0xff) as u8;
            out[7] = (i         & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u8<'a>(i: u8) -> impl SerializeFn<&'a mut [u8]> {
   let len = 1;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = i;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u16<'a>(i: u16) -> impl SerializeFn<&'a mut [u8]> {
   let len = 2;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i        & 0xff) as u8;
            out[1] = ((i >> 8) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u32<'a>(i: u32) -> impl SerializeFn<&'a mut [u8]> {
   let len = 4;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i         & 0xff) as u8;
            out[1] = ((i >> 8)  & 0xff) as u8;
            out[2] = ((i >> 16) & 0xff) as u8;
            out[3] = ((i >> 24) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}

pub fn le_u64<'a>(i: u64) -> impl SerializeFn<&'a mut [u8]> {
   let len = 8;

    move |out: &'a mut [u8]| {
        if out.len() < len {
            Err(GenError::BufferTooSmall(len))
        } else {
            out[0] = (i         & 0xff) as u8;
            out[1] = ((i >> 8)  & 0xff) as u8;
            out[2] = ((i >> 16) & 0xff) as u8;
            out[3] = ((i >> 24) & 0xff) as u8;
            out[4] = ((i >> 32) & 0xff) as u8;
            out[5] = ((i >> 40) & 0xff) as u8;
            out[6] = ((i >> 48) & 0xff) as u8;
            out[7] = ((i >> 56) & 0xff) as u8;
            Ok(&mut out[len..])
        }
    }
}
///missing combinators:
///or
///empty
///then
///stream
///length_value
///text print
///text upperhex
///text lowerhex
struct Dummy;
<|endoftext|>


<commit_before>extern crate regex;

use colored::*;
use std::process::exit;
use regex::RegexSet;
use nom::IResult;
use std::path::PathBuf;

pub fn file_contents_to_regex(file: &str, file_path: &PathBuf) -> RegexSet {
    let processed_vec: Vec<&str> = process_to_vector(file);
    let processed_str: String = processed_vec.join("");
    let lines = processed_str.split_whitespace();

    debugln!("{:?}", lines.clone().collect::<Vec<&str>>());

    let maybe_set = RegexSet::new(lines);
    if let Ok(s) = maybe_set {
        s
    }
    else {
        eprintln!("{}: failed to parse .gitignore at {:?}, ignoring", "Warning".yellow(), file_path);
        let empty: Vec<&str> = Vec::new();
        RegexSet::new(empty)
            .expect("Error creating regex from empty vector")
    }
}

pub fn process_to_vector(input: &str) -> Vec<&str> {
    match process(input) {
        IResult::Done(_, result) => result,
        _ => { eprintln!("{}: Failed to parse gitignore", "Error".red()) ; exit(0xf001) }
    }
}

named!(process<&str, Vec<&str>>,
    do_parse!(
        opt!(first_line) >>
        r: many0!(options) >>
        (r)
    )
);

named!(options<&str, &str>,
    alt!(
        gitignore_comment |
        is_not!("*?.#") |
        parse_asterix |
        parse_period |
        parse_questionmark |
        parse_not_comment
    )
);

named!(parse_not_comment<&str, &str>,
    do_parse!(
        is_not!("\n#") >>
        ("#")
    )
);

named!(first_line<&str, &str>,
    do_parse!(
        tag!("#") >>
        is_not!("\n") >>
        tag!("\n") >>
        ("\n")
    )
);

named!(gitignore_comment<&str, &str>,
    do_parse!(
        tag!("\n#") >>
        is_not!("\n") >>
        //tag!("\n") >>
        ("\n")
    )
);

named!(parse_period<&str, &str>,
    do_parse!(
        tag!(".") >>
        ("\\.")
    )
);

named!(parse_asterix<&str, &str>,
    do_parse!(
        tag!("*") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".*")
    )
);

named!(parse_questionmark<&str, &str>,
    do_parse!(
        tag!("?") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".")
    )
);
<commit_msg>bug fixed except for # at end of file<commit_after>extern crate regex;

use colored::*;
use std::process::exit;
use regex::RegexSet;
use nom::IResult;
use std::path::PathBuf;

pub fn file_contents_to_regex(file: &str, file_path: &PathBuf) -> RegexSet {
    let processed_vec: Vec<&str> = process_to_vector(file);
    let processed_str: String = processed_vec.join("");
    let lines = processed_str.split_whitespace();

    debugln!("{:?}", lines.clone().collect::<Vec<&str>>());

    let maybe_set = RegexSet::new(lines);
    if let Ok(s) = maybe_set {
        s
    }
    else {
        eprintln!("{}: failed to parse .gitignore at {:?}, ignoring", "Warning".yellow(), file_path);
        let empty: Vec<&str> = Vec::new();
        RegexSet::new(empty)
            .expect("Error creating regex from empty vector")
    }
}

pub fn process_to_vector(input: &str) -> Vec<&str> {
    match process(input) {
        IResult::Done(_, result) => result,
        _ => { eprintln!("{}: Failed to parse gitignore", "Error".red()) ; exit(0xf001) }
    }
}

named!(process<&str, Vec<&str>>,
    do_parse!(
        opt!(first_line) >>
        r: many0!(options) >>
        (r)
    )
);

named!(options<&str, &str>,
    alt!(
        gitignore_comment |
        is_not!("*?.#") |
        parse_asterix |
        parse_period |
        parse_questionmark |
        parse_not_comment
    )
);

named!(parse_not_comment<&str, &str>,
    do_parse!(
        is_not!("\n") >>
        ("#")
    )
);

named!(first_line<&str, &str>,
    do_parse!(
        tag!("#") >>
        is_not!("\n") >>
        tag!("\n") >>
        ("\n")
    )
);

named!(gitignore_comment<&str, &str>,
    do_parse!(
        tag!("\n#") >>
        is_not!("\n") >>
        //tag!("\n") >>
        ("\n")
    )
);

named!(parse_period<&str, &str>,
    do_parse!(
        tag!(".") >>
        ("\\.")
    )
);

named!(parse_asterix<&str, &str>,
    do_parse!(
        tag!("*") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".*")
    )
);

named!(parse_questionmark<&str, &str>,
    do_parse!(
        tag!("?") >>
        opt!(do_parse!(tag!("\n") >> eof!() >> (""))) >>
        (".")
    )
);
<|endoftext|>


<commit_before>use crate::{
    compat::{AllowStd, SetWaker},
    WebSocketStream,
};
use log::*;
use pin_project::pin_project;
use std::{
    future::Future,
    io::{Read, Write},
    pin::Pin,
    task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite};
use tungstenite::{
    handshake::{
        client::Response, server::Callback, HandshakeError as Error, HandshakeRole,
        MidHandshake as WsHandshake,
    },
    ClientHandshake, ServerHandshake, WebSocket,
};

pub(crate) async fn without_handshake<F, S>(stream: S, f: F) -> WebSocketStream<S>
where
    F: FnOnce(AllowStd<S>) -> WebSocket<AllowStd<S>> + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let start = SkippedHandshakeFuture(Some(SkippedHandshakeFutureInner { f, stream }));

    let ws = start.await;

    WebSocketStream::new(ws)
}

struct SkippedHandshakeFuture<F, S>(Option<SkippedHandshakeFutureInner<F, S>>);
struct SkippedHandshakeFutureInner<F, S> {
    f: F,
    stream: S,
}

impl<F, S> Future for SkippedHandshakeFuture<F, S>
where
    F: FnOnce(AllowStd<S>) -> WebSocket<AllowStd<S>> + Unpin,
    S: Unpin,
    AllowStd<S>: Read + Write,
{
    type Output = WebSocket<AllowStd<S>>;

    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
        let inner = self.get_mut().0.take().expect("future polled after completion");
        trace!("Setting context when skipping handshake");
        let stream = AllowStd::new(inner.stream, ctx.waker());

        Poll::Ready((inner.f)(stream))
    }
}

#[pin_project]
struct MidHandshake<Role: HandshakeRole>(Option<WsHandshake<Role>>);

enum StartedHandshake<Role: HandshakeRole> {
    Done(Role::FinalResult),
    Mid(WsHandshake<Role>),
}

struct StartedHandshakeFuture<F, S>(Option<StartedHandshakeFutureInner<F, S>>);
struct StartedHandshakeFutureInner<F, S> {
    f: F,
    stream: S,
}

async fn handshake<Role, F, S>(stream: S, f: F) -> Result<Role::FinalResult, Error<Role>>
where
    Role: HandshakeRole + Unpin,
    Role::InternalStream: SetWaker,
    F: FnOnce(AllowStd<S>) -> Result<Role::FinalResult, Error<Role>> + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let start = StartedHandshakeFuture(Some(StartedHandshakeFutureInner { f, stream }));

    match start.await? {
        StartedHandshake::Done(r) => Ok(r),
        StartedHandshake::Mid(s) => {
            let res: Result<Role::FinalResult, Error<Role>> = MidHandshake::<Role>(Some(s)).await;
            res
        }
    }
}

pub(crate) async fn client_handshake<F, S>(
    stream: S,
    f: F,
) -> Result<(WebSocketStream<S>, Response), Error<ClientHandshake<AllowStd<S>>>>
where
    F: FnOnce(
        AllowStd<S>,
    ) -> Result<
        <ClientHandshake<AllowStd<S>> as HandshakeRole>::FinalResult,
        Error<ClientHandshake<AllowStd<S>>>,
    > + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let result = handshake(stream, f).await?;
    let (s, r) = result;
    Ok((WebSocketStream::new(s), r))
}

pub(crate) async fn server_handshake<C, F, S>(
    stream: S,
    f: F,
) -> Result<WebSocketStream<S>, Error<ServerHandshake<AllowStd<S>, C>>>
where
    C: Callback + Unpin,
    F: FnOnce(
        AllowStd<S>,
    ) -> Result<
        <ServerHandshake<AllowStd<S>, C> as HandshakeRole>::FinalResult,
        Error<ServerHandshake<AllowStd<S>, C>>,
    > + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let s: WebSocket<AllowStd<S>> = handshake(stream, f).await?;
    Ok(WebSocketStream::new(s))
}

impl<Role, F, S> Future for StartedHandshakeFuture<F, S>
where
    Role: HandshakeRole,
    Role::InternalStream: SetWaker,
    F: FnOnce(AllowStd<S>) -> Result<Role::FinalResult, Error<Role>> + Unpin,
    S: Unpin,
    AllowStd<S>: Read + Write,
{
    type Output = Result<StartedHandshake<Role>, Error<Role>>;

    fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
        let inner = self.0.take().expect("future polled after completion");
        trace!("Setting ctx when starting handshake");
        let stream = AllowStd::new(inner.stream, ctx.waker());

        match (inner.f)(stream) {
            Ok(r) => Poll::Ready(Ok(StartedHandshake::Done(r))),
            Err(Error::Interrupted(mid)) => Poll::Ready(Ok(StartedHandshake::Mid(mid))),
            Err(Error::Failure(e)) => Poll::Ready(Err(Error::Failure(e))),
        }
    }
}

impl<Role> Future for MidHandshake<Role>
where
    Role: HandshakeRole + Unpin,
    Role::InternalStream: SetWaker,
{
    type Output = Result<Role::FinalResult, Error<Role>>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let this = self.project();
        let mut s = this.0.take().expect("future polled after completion");

        let machine = s.get_mut();
        trace!("Setting context in handshake");
        machine.get_mut().set_waker(cx.waker());

        match s.handshake() {
            Ok(stream) => Poll::Ready(Ok(stream)),
            Err(Error::Failure(e)) => Poll::Ready(Err(Error::Failure(e))),
            Err(Error::Interrupted(mid)) => {
                *this.0 = Some(mid);
                Poll::Pending
            }
        }
    }
}
<commit_msg>Fix formatting errors<commit_after>use crate::{
    compat::{AllowStd, SetWaker},
    WebSocketStream,
};
use log::*;
use pin_project::pin_project;
use std::{
    future::Future,
    io::{Read, Write},
    pin::Pin,
    task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite};
use tungstenite::{
    handshake::{
        client::Response, server::Callback, HandshakeError as Error, HandshakeRole,
        MidHandshake as WsHandshake,
    },
    ClientHandshake, ServerHandshake, WebSocket,
};

pub(crate) async fn without_handshake<F, S>(stream: S, f: F) -> WebSocketStream<S>
where
    F: FnOnce(AllowStd<S>) -> WebSocket<AllowStd<S>> + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let start = SkippedHandshakeFuture(Some(SkippedHandshakeFutureInner { f, stream }));

    let ws = start.await;

    WebSocketStream::new(ws)
}

struct SkippedHandshakeFuture<F, S>(Option<SkippedHandshakeFutureInner<F, S>>);
struct SkippedHandshakeFutureInner<F, S> {
    f: F,
    stream: S,
}

impl<F, S> Future for SkippedHandshakeFuture<F, S>
where
    F: FnOnce(AllowStd<S>) -> WebSocket<AllowStd<S>> + Unpin,
    S: Unpin,
    AllowStd<S>: Read + Write,
{
    type Output = WebSocket<AllowStd<S>>;

    fn poll(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
        let inner = self.get_mut().0.take().expect("future polled after completion");
        trace!("Setting context when skipping handshake");
        let stream = AllowStd::new(inner.stream, ctx.waker());

        Poll::Ready((inner.f)(stream))
    }
}

#[pin_project]
struct MidHandshake<Role: HandshakeRole>(Option<WsHandshake<Role>>);

enum StartedHandshake<Role: HandshakeRole> {
    Done(Role::FinalResult),
    Mid(WsHandshake<Role>),
}

struct StartedHandshakeFuture<F, S>(Option<StartedHandshakeFutureInner<F, S>>);
struct StartedHandshakeFutureInner<F, S> {
    f: F,
    stream: S,
}

async fn handshake<Role, F, S>(stream: S, f: F) -> Result<Role::FinalResult, Error<Role>>
where
    Role: HandshakeRole + Unpin,
    Role::InternalStream: SetWaker,
    F: FnOnce(AllowStd<S>) -> Result<Role::FinalResult, Error<Role>> + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let start = StartedHandshakeFuture(Some(StartedHandshakeFutureInner { f, stream }));

    match start.await? {
        StartedHandshake::Done(r) => Ok(r),
        StartedHandshake::Mid(s) => {
            let res: Result<Role::FinalResult, Error<Role>> = MidHandshake::<Role>(Some(s)).await;
            res
        }
    }
}

pub(crate) async fn client_handshake<F, S>(
    stream: S,
    f: F,
) -> Result<(WebSocketStream<S>, Response), Error<ClientHandshake<AllowStd<S>>>>
where
    F: FnOnce(
            AllowStd<S>,
        ) -> Result<
            <ClientHandshake<AllowStd<S>> as HandshakeRole>::FinalResult,
            Error<ClientHandshake<AllowStd<S>>>,
        > + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let result = handshake(stream, f).await?;
    let (s, r) = result;
    Ok((WebSocketStream::new(s), r))
}

pub(crate) async fn server_handshake<C, F, S>(
    stream: S,
    f: F,
) -> Result<WebSocketStream<S>, Error<ServerHandshake<AllowStd<S>, C>>>
where
    C: Callback + Unpin,
    F: FnOnce(
            AllowStd<S>,
        ) -> Result<
            <ServerHandshake<AllowStd<S>, C> as HandshakeRole>::FinalResult,
            Error<ServerHandshake<AllowStd<S>, C>>,
        > + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let s: WebSocket<AllowStd<S>> = handshake(stream, f).await?;
    Ok(WebSocketStream::new(s))
}

impl<Role, F, S> Future for StartedHandshakeFuture<F, S>
where
    Role: HandshakeRole,
    Role::InternalStream: SetWaker,
    F: FnOnce(AllowStd<S>) -> Result<Role::FinalResult, Error<Role>> + Unpin,
    S: Unpin,
    AllowStd<S>: Read + Write,
{
    type Output = Result<StartedHandshake<Role>, Error<Role>>;

    fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Self::Output> {
        let inner = self.0.take().expect("future polled after completion");
        trace!("Setting ctx when starting handshake");
        let stream = AllowStd::new(inner.stream, ctx.waker());

        match (inner.f)(stream) {
            Ok(r) => Poll::Ready(Ok(StartedHandshake::Done(r))),
            Err(Error::Interrupted(mid)) => Poll::Ready(Ok(StartedHandshake::Mid(mid))),
            Err(Error::Failure(e)) => Poll::Ready(Err(Error::Failure(e))),
        }
    }
}

impl<Role> Future for MidHandshake<Role>
where
    Role: HandshakeRole + Unpin,
    Role::InternalStream: SetWaker,
{
    type Output = Result<Role::FinalResult, Error<Role>>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let this = self.project();
        let mut s = this.0.take().expect("future polled after completion");

        let machine = s.get_mut();
        trace!("Setting context in handshake");
        machine.get_mut().set_waker(cx.waker());

        match s.handshake() {
            Ok(stream) => Poll::Ready(Ok(stream)),
            Err(Error::Failure(e)) => Poll::Ready(Err(Error::Failure(e))),
            Err(Error::Interrupted(mid)) => {
                *this.0 = Some(mid);
                Poll::Pending
            }
        }
    }
}
<|endoftext|>


<commit_before>
use ring::digest::{ Algorithm, Context };

/// The sole purpose of this trait is to extend the standard
/// `ring::algo::Algorithm` type with a couple utility functions.
pub trait HashUtils {

    /// Compute the hash the given byte array
    fn hash_bytes(&'static self, bytes: &[u8]) -> Vec<u8>;

    /// Compute the hash of the concatenation of `left` and `right`
    fn combine_hashes(&'static self, left: &[u8], right: &[u8]) -> Vec<u8>;
}

impl HashUtils for Algorithm {

    fn hash_bytes(&'static self, bytes: &[u8]) -> Vec<u8> {
        let mut context = Context::new(self);
        context.update(bytes);
        context.finish().as_ref().into()
    }

    fn combine_hashes(&'static self, left: &[u8], right: &[u8]) -> Vec<u8> {
        let mut context = Context::new(self);
        let combined = [left, right].concat();
        context.update(&combined);
        context.finish().as_ref().into()
    }
}

<commit_msg>Simplify code in HashUtils.<commit_after>
use ring::digest::{ Algorithm, digest };

/// The sole purpose of this trait is to extend the standard
/// `ring::algo::Algorithm` type with a couple utility functions.
pub trait HashUtils {

    /// Compute the hash the given byte array
    fn hash_bytes(&'static self, bytes: &[u8]) -> Vec<u8>;

    /// Compute the hash of the concatenation of `left` and `right`
    fn combine_hashes(&'static self, left: &[u8], right: &[u8]) -> Vec<u8>;
}

impl HashUtils for Algorithm {

    fn hash_bytes(&'static self, bytes: &[u8]) -> Vec<u8> {
        digest(self, bytes).as_ref().into()
    }

    fn combine_hashes(&'static self, left: &[u8], right: &[u8]) -> Vec<u8> {
        let combined = [left, right].concat();
        digest(self, &combined).as_ref().into()
    }
}

<|endoftext|>


<commit_before>use std::string::String;
use js_types::js_obj::JsObjStruct;
use js_types::js_str::JsStrStruct;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use uuid::Uuid;

use alloc::Alloc;

#[derive(Clone)]
pub struct JsVar {
    pub binding: Option<String>,
    pub uuid: Uuid,
    pub t: JsType,
}

impl JsVar {
    pub fn new(t: JsType) -> JsVar {
        JsVar {
            binding: None,
            uuid: Uuid::new_v4(),
            t: t,
        }
    }

    pub fn bind(binding: &str, t: JsType) -> JsVar {
        JsVar {
            binding: Some(String::from(binding)),
            uuid: Uuid::new_v4(),
            t: t,
        }
    }
}

impl PartialEq for JsVar {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsVar {}

#[derive(Clone)]
pub enum JsPtrEnum {
    JsNull,
    JsSym(String),
    JsStr(JsStrStruct),
    JsObj(JsObjStruct),
}

#[derive(Clone)]
pub enum JsType {
    JsUndef,
    JsNum(f64),
    JsBool(bool),
    JsPtr,
}

#[derive(Clone)]
pub enum JsKeyEnum {
    JsNum(f64),
    JsBool(bool),
    JsStr(JsStrStruct),
    JsSym(String),
}

#[derive(Clone)]
pub struct JsKey {
    pub uuid: Uuid,
    pub k: JsKeyEnum,
}

impl JsKey {
    pub fn new(k: JsKeyEnum) -> JsKey {
        JsKey {
            uuid: Uuid::new_v4(),
            k: k,
        }
    }
}

impl PartialEq for JsKey {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsKey {}

impl Hash for JsKey {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uuid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uuid.hash(state);
        }
    }
}

// `array`
pub type JsArr = Vec<JsType>;
<commit_msg>Move JsNull under JsType and implement PartialEq & Eq for JsType<commit_after>use std::string::String;
use js_types::js_obj::JsObjStruct;
use js_types::js_str::JsStrStruct;
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
use uuid::Uuid;

use alloc::Alloc;

#[derive(Clone)]
pub struct JsVar {
    pub binding: Option<String>,
    pub uuid: Uuid,
    pub t: JsType,
}

impl JsVar {
    pub fn new(t: JsType) -> JsVar {
        JsVar {
            binding: None,
            uuid: Uuid::new_v4(),
            t: t,
        }
    }

    pub fn bind(binding: &str, t: JsType) -> JsVar {
        JsVar {
            binding: Some(String::from(binding)),
            uuid: Uuid::new_v4(),
            t: t,
        }
    }
}

impl PartialEq for JsVar {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsVar {}

#[derive(Clone)]
pub enum JsPtrEnum {
    JsSym(String),
    JsStr(JsStrStruct),
    JsObj(JsObjStruct),
}

#[derive(Clone)]
pub enum JsType {
    JsUndef,
    JsNum(f64),
    JsBool(bool),
    JsPtr,
    JsNull,
}

impl PartialEq for JsType {
    fn eq(&self, other: &Self) -> bool {
        match (self, other) {
            (&JsType::JsUndef, &JsType::JsUndef) => true,
            (&JsType::JsNum(x), &JsType::JsNum(y)) => x == y,
            (&JsType::JsBool(b1), &JsType::JsBool(b2)) => b1 == b2,
            (&JsType::JsNull, &JsType::JsNull) => true,
            (_, _) => false,
        }
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsType {}

#[derive(Clone)]
pub enum JsKeyEnum {
    JsNum(f64),
    JsBool(bool),
    JsStr(JsStrStruct),
    JsSym(String),
}

#[derive(Clone)]
pub struct JsKey {
    pub uuid: Uuid,
    pub k: JsKeyEnum,
}

impl JsKey {
    pub fn new(k: JsKeyEnum) -> JsKey {
        JsKey {
            uuid: Uuid::new_v4(),
            k: k,
        }
    }
}

impl PartialEq for JsKey {
    fn eq(&self, other: &Self) -> bool {
        self.uuid == other.uuid
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }
}

impl Eq for JsKey {}

impl Hash for JsKey {
    fn hash<H>(&self, state: &mut H) where H: Hasher {
        self.uuid.hash(state);
    }

    fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher {
        for ref d in data {
            d.uuid.hash(state);
        }
    }
}

// `array`
pub type JsArr = Vec<JsType>;
<|endoftext|>