<commit_before>// Adapton uses memoization under the covers, which needs an efficient
// mechanism to search for function pointers and compare them for
// equality.
//
// Meanwhile, Rust does not provide Eq and Hash implementations for
// trait Fn.  So, to identify Rust functions as values that we can
// hash and compare, we need to bundle additional static information
// along with the function pointer as use this data as a proxy for the
// function itself.  The idea is that this information uniquely
// identifies the function pointer (i.e., two distinct functions will
// always have two distinct identities).
//
use std::hash::{Hash,Hasher,SipHasher};
//use std::rc::Rc;
//use std::mem::replace;

#[derive(PartialEq,Eq,Clone,Hash,Debug)]
pub struct ProgPt {
    // Symbolic identity, in Rust semantics:
    pub symbol:&'static str, // via stringify!(...)
    // module:Rc<String>, // via module!()

    // Location in local filesystem:
    //pub file:&'static str,   // via file!()
    //pub line:u32,        // via line!()
    //pub column:u32,      // via column!()
}

pub fn my_hash<T>(obj: T) -> u64
    where T: Hash
{
    let mut hasher = SipHasher::new();
    obj.hash(&mut hasher);
    hasher.finish()
}

#[macro_export]
macro_rules! prog_pt {
    ($symbol:ident) => {{
        ProgPt{
            symbol:stringify!($symbol),
            //file:file!(),
            //line:line!(),
            //column:column!(),
        }
    }}
}

#[macro_export]
macro_rules! thunk {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, ) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             )
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:ident , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             )
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             )
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f ( st, $( $lab ),* () )
                 })),
             ( $( $arg ),* ),
             ()
             )
    }}
    ;
}

#[macro_export]
macro_rules! memo {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab1:ident : $arg1:expr ),* ;; $( $lab2:ident : $arg2:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args1, args2|{
                     let ($( $lab1 ),*, _) = args1 ;
                     let ($( $lab2 ),*, _) = args2 ;
                     $f ( st, $( $lab1 ),* , $( $lab2 ),* )
                 })),
             ( $( $arg1 ),*, () ),
             ( $( $arg2 ),*, () ),
             );
        ($st).force(&t)
    }}
    ;
}

// https://doc.rust-lang.org/book/macros.html
//
// macro_rules! o_O {
//     (
//         $(
//             $x:expr; [ $( $y:expr ),* ]
//          );*
//     ) => {
//         &[ $($( $x + $y ),*),* ]
//     }
// }
//
// fn main() {
//     let a: &[i32]
//         = o_O!(10; [1, 2, 3];
//                20; [4, 5, 6]);
//
//     assert_eq!(a, [11, 12, 13, 24, 25, 26]);
// }

// TODO: Need to gensym a variable for each argument below:
//
// macro_rules! thunk {
//     ( $f:ident , $st:expr , $( $arg:expr ),* ) => {
//         let fval = Rc::new(Box::new(
//             |st, args|{
//                 let ($( $arg ),*) = args ;
//                 f( st, $( $arg ),* )
//             })) ;
//         ($st).thunk (ArtId::Eager, prog_pt!(f), fval, $( $arg ),* )
//     }}
<commit_msg>trying to fix the thunk! macro<commit_after>// Adapton uses memoization under the covers, which needs an efficient
// mechanism to search for function pointers and compare them for
// equality.
//
// Meanwhile, Rust does not provide Eq and Hash implementations for
// trait Fn.  So, to identify Rust functions as values that we can
// hash and compare, we need to bundle additional static information
// along with the function pointer as use this data as a proxy for the
// function itself.  The idea is that this information uniquely
// identifies the function pointer (i.e., two distinct functions will
// always have two distinct identities).
//
use std::hash::{Hash,Hasher,SipHasher};
//use std::rc::Rc;
//use std::mem::replace;

#[derive(PartialEq,Eq,Clone,Hash,Debug)]
pub struct ProgPt {
    // Symbolic identity, in Rust semantics:
    pub symbol:&'static str, // via stringify!(...)
    // module:Rc<String>, // via module!()

    // Location in local filesystem:
    //pub file:&'static str,   // via file!()
    //pub line:u32,        // via line!()
    //pub column:u32,      // via column!()
}

pub fn my_hash<T>(obj: T) -> u64
    where T: Hash
{
    let mut hasher = SipHasher::new();
    obj.hash(&mut hasher);
    hasher.finish()
}

#[macro_export]
macro_rules! prog_pt {
    ($symbol:ident) => {{
        ProgPt{
            symbol:stringify!($symbol),
            //file:file!(),
            //line:line!(),
            //column:column!(),
        }
    }}
}

#[macro_export]
macro_rules! thunk {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, ()),
             ()
             )
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:ident , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             )
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             )
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             )
    }}
    ;
}

#[macro_export]
macro_rules! memo {
    ( $st:expr , $nm:expr =>> $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $f:ident :: < $( $ty:ty ),* > , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*) = args ;
                     $f :: < $( $ty ),* >( st, $( $lab ),* )
                 })),
             ( $( $arg ),* ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $f:path , $( $lab:ident : $arg:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Structural,
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args, _|{
                     let ($( $lab ),*, _) = args ;
                     $f ( st, $( $lab ),* )
                 })),
             ( $( $arg ),*, () ),
             ()
             );
        ($st).force(&t)
    }}
    ;
    ( $st:expr , $nm:expr =>> $f:path , $( $lab1:ident : $arg1:expr ),* ;; $( $lab2:ident : $arg2:expr ),* ) => {{
        let t = ($st).thunk
            (ArtIdChoice::Nominal($nm),
             prog_pt!(f),
             Rc::new(Box::new(
                 |st, args1, args2|{
                     let ($( $lab1 ),*, _) = args1 ;
                     let ($( $lab2 ),*, _) = args2 ;
                     $f ( st, $( $lab1 ),* , $( $lab2 ),* )
                 })),
             ( $( $arg1 ),*, () ),
             ( $( $arg2 ),*, () ),
             );
        ($st).force(&t)
    }}
    ;
}

// https://doc.rust-lang.org/book/macros.html
//
// macro_rules! o_O {
//     (
//         $(
//             $x:expr; [ $( $y:expr ),* ]
//          );*
//     ) => {
//         &[ $($( $x + $y ),*),* ]
//     }
// }
//
// fn main() {
//     let a: &[i32]
//         = o_O!(10; [1, 2, 3];
//                20; [4, 5, 6]);
//
//     assert_eq!(a, [11, 12, 13, 24, 25, 26]);
// }

// TODO: Need to gensym a variable for each argument below:
//
// macro_rules! thunk {
//     ( $f:ident , $st:expr , $( $arg:expr ),* ) => {
//         let fval = Rc::new(Box::new(
//             |st, args|{
//                 let ($( $arg ),*) = args ;
//                 f( st, $( $arg ),* )
//             })) ;
//         ($st).thunk (ArtId::Eager, prog_pt!(f), fval, $( $arg ),* )
//     }}
<|endoftext|>


<commit_before>use convert::TryFrom;
use mem;
use ops::{self, Add, Sub, Try};
use usize;

use super::{FusedIterator, TrustedLen};

/// Objects that can be stepped over in both directions.
///
/// The `steps_between` function provides a way to efficiently compare
/// two `Step` objects.
#[unstable(feature = "step_trait",
           reason = "likely to be replaced by finer-grained traits",
           issue = "42168")]
pub trait Step: Clone + PartialOrd + Sized {
    /// Returns the number of steps between two step objects. The count is
    /// inclusive of `start` and exclusive of `end`.
    ///
    /// Returns `None` if it is not possible to calculate `steps_between`
    /// without overflow.
    fn steps_between(start: &Self, end: &Self) -> Option<usize>;

    /// Replaces this step with `1`, returning itself.
    fn replace_one(&mut self) -> Self;

    /// Replaces this step with `0`, returning itself.
    fn replace_zero(&mut self) -> Self;

    /// Adds one to this step, returning the result.
    fn add_one(&self) -> Self;

    /// Subtracts one to this step, returning the result.
    fn sub_one(&self) -> Self;

    /// Adds a `usize`, returning `None` on overflow.
    fn add_usize(&self, n: usize) -> Option<Self>;
}

// These are still macro-generated because the integer literals resolve to different types.
macro_rules! step_identical_methods {
    () => {
        #[inline]
        fn replace_one(&mut self) -> Self {
            mem::replace(self, 1)
        }

        #[inline]
        fn replace_zero(&mut self) -> Self {
            mem::replace(self, 0)
        }

        #[inline]
        fn add_one(&self) -> Self {
            Add::add(*self, 1)
        }

        #[inline]
        fn sub_one(&self) -> Self {
            Sub::sub(*self, 1)
        }
    }
}

macro_rules! step_impl_unsigned {
    ($($t:ty)*) => ($(
        #[unstable(feature = "step_trait",
                   reason = "likely to be replaced by finer-grained traits",
                   issue = "42168")]
        impl Step for $t {
            #[inline]
            fn steps_between(start: &$t, end: &$t) -> Option<usize> {
                if *start < *end {
                    usize::try_from(*end - *start).ok()
                } else {
                    Some(0)
                }
            }

            #[inline]
            #[allow(unreachable_patterns)]
            fn add_usize(&self, n: usize) -> Option<Self> {
                match <$t>::try_from(n) {
                    Ok(n_as_t) => self.checked_add(n_as_t),
                    Err(_) => None,
                }
            }

            step_identical_methods!();
        }
    )*)
}
macro_rules! step_impl_signed {
    ($( [$t:ty : $unsigned:ty] )*) => ($(
        #[unstable(feature = "step_trait",
                   reason = "likely to be replaced by finer-grained traits",
                   issue = "42168")]
        impl Step for $t {
            #[inline]
            fn steps_between(start: &$t, end: &$t) -> Option<usize> {
                if *start < *end {
                    // Use .wrapping_sub and cast to unsigned to compute the
                    // difference that may not fit inside the range of $t.
                    usize::try_from(end.wrapping_sub(*start) as $unsigned).ok()
                } else {
                    Some(0)
                }
            }

            #[inline]
            #[allow(unreachable_patterns)]
            fn add_usize(&self, n: usize) -> Option<Self> {
                match <$unsigned>::try_from(n) {
                    Ok(n_as_unsigned) => {
                        // Wrapping in unsigned space handles cases like
                        // `-120_i8.add_usize(200) == Some(80_i8)`,
                        // even though 200_usize is out of range for i8.
                        let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t;
                        if wrapped >= *self {
                            Some(wrapped)
                        } else {
                            None  // Addition overflowed
                        }
                    }
                    Err(_) => None,
                }
            }

            step_identical_methods!();
        }
    )*)
}

step_impl_unsigned!(usize u8 u16 u32 u64 u128);
step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
step_impl_signed!([i32: u32] [i64: u64] [i128: u128]);

macro_rules! range_exact_iter_impl {
    ($($t:ty)*) => ($(
        #[stable(feature = "rust1", since = "1.0.0")]
        impl ExactSizeIterator for ops::Range<$t> { }
    )*)
}

macro_rules! range_incl_exact_iter_impl {
    ($($t:ty)*) => ($(
        #[stable(feature = "inclusive_range", since = "1.26.0")]
        impl ExactSizeIterator for ops::RangeInclusive<$t> { }
    )*)
}

macro_rules! range_trusted_len_impl {
    ($($t:ty)*) => ($(
        #[unstable(feature = "trusted_len", issue = "37572")]
        unsafe impl TrustedLen for ops::Range<$t> { }
    )*)
}

macro_rules! range_incl_trusted_len_impl {
    ($($t:ty)*) => ($(
        #[unstable(feature = "trusted_len", issue = "37572")]
        unsafe impl TrustedLen for ops::RangeInclusive<$t> { }
    )*)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> Iterator for ops::Range<A> {
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option<A> {
        if self.start < self.end {
            // We check for overflow here, even though it can't actually
            // happen. Adding this check does however help llvm vectorize loops
            // for some ranges that don't get vectorized otherwise,
            // and this won't actually result in an extra check in an optimized build.
            if let Some(mut n) = self.start.add_usize(1) {
                mem::swap(&mut n, &mut self.start);
                Some(n)
            } else {
                None
            }
        } else {
            None
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match Step::steps_between(&self.start, &self.end) {
            Some(hint) => (hint, Some(hint)),
            None => (usize::MAX, None)
        }
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<A> {
        if let Some(plus_n) = self.start.add_usize(n) {
            if plus_n < self.end {
                self.start = plus_n.add_one();
                return Some(plus_n)
            }
        }

        self.start = self.end.clone();
        None
    }

    #[inline]
    fn last(mut self) -> Option<A> {
        self.next_back()
    }

    #[inline]
    fn min(mut self) -> Option<A> {
        self.next()
    }

    #[inline]
    fn max(mut self) -> Option<A> {
        self.next_back()
    }
}

// These macros generate `ExactSizeIterator` impls for various range types.
// Range<{u,i}64> and RangeInclusive<{u,i}{32,64,size}> are excluded
// because they cannot guarantee having a length <= usize::MAX, which is
// required by ExactSizeIterator.
range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32);
range_incl_exact_iter_impl!(u8 u16 i8 i16);

// These macros generate `TrustedLen` impls.
//
// They need to guarantee that .size_hint() is either exact, or that
// the upper bound is None when it does not fit the type limits.
range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);
range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 i64 u64);

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
    #[inline]
    fn next_back(&mut self) -> Option<A> {
        if self.start < self.end {
            self.end = self.end.sub_one();
            Some(self.end.clone())
        } else {
            None
        }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<A: Step> FusedIterator for ops::Range<A> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> Iterator for ops::RangeFrom<A> {
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option<A> {
        let mut n = self.start.add_one();
        mem::swap(&mut n, &mut self.start);
        Some(n)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (usize::MAX, None)
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<A> {
        let plus_n = self.start.add_usize(n).expect("overflow in RangeFrom::nth");
        self.start = plus_n.add_one();
        Some(plus_n)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<A: Step> FusedIterator for ops::RangeFrom<A> {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A: Step> TrustedLen for ops::RangeFrom<A> {}

#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<A: Step> Iterator for ops::RangeInclusive<A> {
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option<A> {
        self.compute_is_empty();
        if self.is_empty.unwrap_or_default() {
            return None;
        }
        let is_iterating = self.start < self.end;
        self.is_empty = Some(!is_iterating);
        Some(if is_iterating {
            let n = self.start.add_one();
            mem::replace(&mut self.start, n)
        } else {
            self.start.clone()
        })
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_empty() {
            return (0, Some(0));
        }

        match Step::steps_between(&self.start, &self.end) {
            Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
            None => (usize::MAX, None),
        }
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<A> {
        self.compute_is_empty();
        if self.is_empty.unwrap_or_default() {
            return None;
        }

        if let Some(plus_n) = self.start.add_usize(n) {
            use cmp::Ordering::*;

            match plus_n.partial_cmp(&self.end) {
                Some(Less) => {
                    self.is_empty = Some(false);
                    self.start = plus_n.add_one();
                    return Some(plus_n);
                }
                Some(Equal) => {
                    self.is_empty = Some(true);
                    return Some(plus_n);
                }
                _ => {}
            }
        }

        self.is_empty = Some(true);
        None
    }

    #[inline]
    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
    where
        Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
    {
        self.compute_is_empty();

        if self.is_empty() {
            return Try::from_ok(init);
        }

        let mut accum = init;

        while self.start < self.end {
            let n = self.start.add_one();
            let n = mem::replace(&mut self.start, n);
            accum = f(accum, n)?;
        }

        self.is_empty = Some(true);

        if self.start == self.end {
            accum = f(accum, self.start.clone())?;
        }

        Try::from_ok(accum)
    }

    #[inline]
    fn last(mut self) -> Option<A> {
        self.next_back()
    }

    #[inline]
    fn min(mut self) -> Option<A> {
        self.next()
    }

    #[inline]
    fn max(mut self) -> Option<A> {
        self.next_back()
    }
}

#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
    #[inline]
    fn next_back(&mut self) -> Option<A> {
        self.compute_is_empty();
        if self.is_empty.unwrap_or_default() {
            return None;
        }
        let is_iterating = self.start < self.end;
        self.is_empty = Some(!is_iterating);
        Some(if is_iterating {
            let n = self.end.sub_one();
            mem::replace(&mut self.end, n)
        } else {
            self.end.clone()
        })
    }

    #[inline]
    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
        Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
    {
        self.compute_is_empty();

        if self.is_empty() {
            return Try::from_ok(init);
        }

        let mut accum = init;

        while self.start < self.end {
            let n = self.end.sub_one();
            let n = mem::replace(&mut self.end, n);
            accum = f(accum, n)?;
        }

        self.is_empty = Some(true);

        if self.start == self.end {
            accum = f(accum, self.start.clone())?;
        }

        Try::from_ok(accum)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}
<commit_msg>impl TrustedLen for 128-bit ranges too<commit_after>use convert::TryFrom;
use mem;
use ops::{self, Add, Sub, Try};
use usize;

use super::{FusedIterator, TrustedLen};

/// Objects that can be stepped over in both directions.
///
/// The `steps_between` function provides a way to efficiently compare
/// two `Step` objects.
#[unstable(feature = "step_trait",
           reason = "likely to be replaced by finer-grained traits",
           issue = "42168")]
pub trait Step: Clone + PartialOrd + Sized {
    /// Returns the number of steps between two step objects. The count is
    /// inclusive of `start` and exclusive of `end`.
    ///
    /// Returns `None` if it is not possible to calculate `steps_between`
    /// without overflow.
    fn steps_between(start: &Self, end: &Self) -> Option<usize>;

    /// Replaces this step with `1`, returning itself.
    fn replace_one(&mut self) -> Self;

    /// Replaces this step with `0`, returning itself.
    fn replace_zero(&mut self) -> Self;

    /// Adds one to this step, returning the result.
    fn add_one(&self) -> Self;

    /// Subtracts one to this step, returning the result.
    fn sub_one(&self) -> Self;

    /// Adds a `usize`, returning `None` on overflow.
    fn add_usize(&self, n: usize) -> Option<Self>;
}

// These are still macro-generated because the integer literals resolve to different types.
macro_rules! step_identical_methods {
    () => {
        #[inline]
        fn replace_one(&mut self) -> Self {
            mem::replace(self, 1)
        }

        #[inline]
        fn replace_zero(&mut self) -> Self {
            mem::replace(self, 0)
        }

        #[inline]
        fn add_one(&self) -> Self {
            Add::add(*self, 1)
        }

        #[inline]
        fn sub_one(&self) -> Self {
            Sub::sub(*self, 1)
        }
    }
}

macro_rules! step_impl_unsigned {
    ($($t:ty)*) => ($(
        #[unstable(feature = "step_trait",
                   reason = "likely to be replaced by finer-grained traits",
                   issue = "42168")]
        impl Step for $t {
            #[inline]
            fn steps_between(start: &$t, end: &$t) -> Option<usize> {
                if *start < *end {
                    usize::try_from(*end - *start).ok()
                } else {
                    Some(0)
                }
            }

            #[inline]
            #[allow(unreachable_patterns)]
            fn add_usize(&self, n: usize) -> Option<Self> {
                match <$t>::try_from(n) {
                    Ok(n_as_t) => self.checked_add(n_as_t),
                    Err(_) => None,
                }
            }

            step_identical_methods!();
        }
    )*)
}
macro_rules! step_impl_signed {
    ($( [$t:ty : $unsigned:ty] )*) => ($(
        #[unstable(feature = "step_trait",
                   reason = "likely to be replaced by finer-grained traits",
                   issue = "42168")]
        impl Step for $t {
            #[inline]
            fn steps_between(start: &$t, end: &$t) -> Option<usize> {
                if *start < *end {
                    // Use .wrapping_sub and cast to unsigned to compute the
                    // difference that may not fit inside the range of $t.
                    usize::try_from(end.wrapping_sub(*start) as $unsigned).ok()
                } else {
                    Some(0)
                }
            }

            #[inline]
            #[allow(unreachable_patterns)]
            fn add_usize(&self, n: usize) -> Option<Self> {
                match <$unsigned>::try_from(n) {
                    Ok(n_as_unsigned) => {
                        // Wrapping in unsigned space handles cases like
                        // `-120_i8.add_usize(200) == Some(80_i8)`,
                        // even though 200_usize is out of range for i8.
                        let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t;
                        if wrapped >= *self {
                            Some(wrapped)
                        } else {
                            None  // Addition overflowed
                        }
                    }
                    Err(_) => None,
                }
            }

            step_identical_methods!();
        }
    )*)
}

step_impl_unsigned!(usize u8 u16 u32 u64 u128);
step_impl_signed!([isize: usize] [i8: u8] [i16: u16]);
step_impl_signed!([i32: u32] [i64: u64] [i128: u128]);

macro_rules! range_exact_iter_impl {
    ($($t:ty)*) => ($(
        #[stable(feature = "rust1", since = "1.0.0")]
        impl ExactSizeIterator for ops::Range<$t> { }
    )*)
}

macro_rules! range_incl_exact_iter_impl {
    ($($t:ty)*) => ($(
        #[stable(feature = "inclusive_range", since = "1.26.0")]
        impl ExactSizeIterator for ops::RangeInclusive<$t> { }
    )*)
}

macro_rules! range_trusted_len_impl {
    ($($t:ty)*) => ($(
        #[unstable(feature = "trusted_len", issue = "37572")]
        unsafe impl TrustedLen for ops::Range<$t> { }
    )*)
}

macro_rules! range_incl_trusted_len_impl {
    ($($t:ty)*) => ($(
        #[unstable(feature = "trusted_len", issue = "37572")]
        unsafe impl TrustedLen for ops::RangeInclusive<$t> { }
    )*)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> Iterator for ops::Range<A> {
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option<A> {
        if self.start < self.end {
            // We check for overflow here, even though it can't actually
            // happen. Adding this check does however help llvm vectorize loops
            // for some ranges that don't get vectorized otherwise,
            // and this won't actually result in an extra check in an optimized build.
            if let Some(mut n) = self.start.add_usize(1) {
                mem::swap(&mut n, &mut self.start);
                Some(n)
            } else {
                None
            }
        } else {
            None
        }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        match Step::steps_between(&self.start, &self.end) {
            Some(hint) => (hint, Some(hint)),
            None => (usize::MAX, None)
        }
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<A> {
        if let Some(plus_n) = self.start.add_usize(n) {
            if plus_n < self.end {
                self.start = plus_n.add_one();
                return Some(plus_n)
            }
        }

        self.start = self.end.clone();
        None
    }

    #[inline]
    fn last(mut self) -> Option<A> {
        self.next_back()
    }

    #[inline]
    fn min(mut self) -> Option<A> {
        self.next()
    }

    #[inline]
    fn max(mut self) -> Option<A> {
        self.next_back()
    }
}

// These macros generate `ExactSizeIterator` impls for various range types.
// Range<{u,i}64> and RangeInclusive<{u,i}{32,64,size}> are excluded
// because they cannot guarantee having a length <= usize::MAX, which is
// required by ExactSizeIterator.
range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32);
range_incl_exact_iter_impl!(u8 u16 i8 i16);

// These macros generate `TrustedLen` impls.
//
// They need to guarantee that .size_hint() is either exact, or that
// the upper bound is None when it does not fit the type limits.
range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128);
range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128);

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
    #[inline]
    fn next_back(&mut self) -> Option<A> {
        if self.start < self.end {
            self.end = self.end.sub_one();
            Some(self.end.clone())
        } else {
            None
        }
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<A: Step> FusedIterator for ops::Range<A> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<A: Step> Iterator for ops::RangeFrom<A> {
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option<A> {
        let mut n = self.start.add_one();
        mem::swap(&mut n, &mut self.start);
        Some(n)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        (usize::MAX, None)
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<A> {
        let plus_n = self.start.add_usize(n).expect("overflow in RangeFrom::nth");
        self.start = plus_n.add_one();
        Some(plus_n)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<A: Step> FusedIterator for ops::RangeFrom<A> {}

#[unstable(feature = "trusted_len", issue = "37572")]
unsafe impl<A: Step> TrustedLen for ops::RangeFrom<A> {}

#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<A: Step> Iterator for ops::RangeInclusive<A> {
    type Item = A;

    #[inline]
    fn next(&mut self) -> Option<A> {
        self.compute_is_empty();
        if self.is_empty.unwrap_or_default() {
            return None;
        }
        let is_iterating = self.start < self.end;
        self.is_empty = Some(!is_iterating);
        Some(if is_iterating {
            let n = self.start.add_one();
            mem::replace(&mut self.start, n)
        } else {
            self.start.clone()
        })
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        if self.is_empty() {
            return (0, Some(0));
        }

        match Step::steps_between(&self.start, &self.end) {
            Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
            None => (usize::MAX, None),
        }
    }

    #[inline]
    fn nth(&mut self, n: usize) -> Option<A> {
        self.compute_is_empty();
        if self.is_empty.unwrap_or_default() {
            return None;
        }

        if let Some(plus_n) = self.start.add_usize(n) {
            use cmp::Ordering::*;

            match plus_n.partial_cmp(&self.end) {
                Some(Less) => {
                    self.is_empty = Some(false);
                    self.start = plus_n.add_one();
                    return Some(plus_n);
                }
                Some(Equal) => {
                    self.is_empty = Some(true);
                    return Some(plus_n);
                }
                _ => {}
            }
        }

        self.is_empty = Some(true);
        None
    }

    #[inline]
    fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
    where
        Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
    {
        self.compute_is_empty();

        if self.is_empty() {
            return Try::from_ok(init);
        }

        let mut accum = init;

        while self.start < self.end {
            let n = self.start.add_one();
            let n = mem::replace(&mut self.start, n);
            accum = f(accum, n)?;
        }

        self.is_empty = Some(true);

        if self.start == self.end {
            accum = f(accum, self.start.clone())?;
        }

        Try::from_ok(accum)
    }

    #[inline]
    fn last(mut self) -> Option<A> {
        self.next_back()
    }

    #[inline]
    fn min(mut self) -> Option<A> {
        self.next()
    }

    #[inline]
    fn max(mut self) -> Option<A> {
        self.next_back()
    }
}

#[stable(feature = "inclusive_range", since = "1.26.0")]
impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
    #[inline]
    fn next_back(&mut self) -> Option<A> {
        self.compute_is_empty();
        if self.is_empty.unwrap_or_default() {
            return None;
        }
        let is_iterating = self.start < self.end;
        self.is_empty = Some(!is_iterating);
        Some(if is_iterating {
            let n = self.end.sub_one();
            mem::replace(&mut self.end, n)
        } else {
            self.end.clone()
        })
    }

    #[inline]
    fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R where
        Self: Sized, F: FnMut(B, Self::Item) -> R, R: Try<Ok=B>
    {
        self.compute_is_empty();

        if self.is_empty() {
            return Try::from_ok(init);
        }

        let mut accum = init;

        while self.start < self.end {
            let n = self.end.sub_one();
            let n = mem::replace(&mut self.end, n);
            accum = f(accum, n)?;
        }

        self.is_empty = Some(true);

        if self.start == self.end {
            accum = f(accum, self.start.clone())?;
        }

        Try::from_ok(accum)
    }
}

#[stable(feature = "fused", since = "1.26.0")]
impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}
<|endoftext|>


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

use std::io::Result as IoResult;
use std::io::Write;

/// Splits the incoming data into HTTP chunks.
///
/// # Example
///
/// ```
/// use chunked_transfer::Encoder;
/// use std::io::Write;
///
/// let mut decoded = "hello world";
/// let mut encoded: Vec<u8> = vec![];
///
/// {
///     let mut encoder = Encoder::with_chunks_size(&mut encoded, 5);
///     encoder.write_all(decoded.as_bytes());
/// }
///
/// assert_eq!(encoded, b"5\r\nhello\r\n5\r\n worl\r\n1\r\nd\r\n0\r\n\r\n");
/// ```
pub struct Encoder<W>
where
    W: Write,
{
    // where to send the result
    output: W,

    // size of each chunk
    chunks_size: usize,

    // data waiting to be sent is stored here
    // This will always be at least 6 bytes long. The first 6 bytes
    // are reserved for the chunk size and \r\n.
    buffer: Vec<u8>,

    // Flushes the internal buffer after each write. This might be useful
    // if data should be sent immediately to downstream consumers
    flush_after_write: bool,
}

const MAX_CHUNK_SIZE: usize = std::u32::MAX as usize;
const PLACEHOLDER_HEADER_SIZE: usize = 6;

impl<W> Encoder<W>
where
    W: Write,
{
    pub fn new(output: W) -> Encoder<W> {
        Encoder::with_chunks_size(output, 8192)
    }

    pub fn with_chunks_size(output: W, chunks: usize) -> Encoder<W> {
        let chunks_size = chunks.min(MAX_CHUNK_SIZE);
        let mut encoder = Encoder {
            output,
            chunks_size,
            buffer: Vec::with_capacity(0),
            flush_after_write: false,
        };
        encoder.reset_buffer();
        encoder
    }

    pub fn with_flush_after_write(output: W) -> Encoder<W> {
        let mut encoder = Encoder {
            output,
            chunks_size: 8192,
            buffer: Vec::with_capacity(0),
            flush_after_write: true,
        };
        encoder.reset_buffer();
        encoder
    }

    fn reset_buffer(&mut self) {
        // Reset buffer
        self.buffer.clear();
        // Reserve space for the chunk size. This space will be populated once
        // we know the size of the chunk.
        self.buffer.resize(PLACEHOLDER_HEADER_SIZE, 0);
    }

    fn is_buffer_empty(&self) -> bool {
        self.buffer.len() == PLACEHOLDER_HEADER_SIZE
    }

    fn buffer_len(&self) -> usize {
        self.buffer.len() - PLACEHOLDER_HEADER_SIZE
    }

    fn send(&mut self) -> IoResult<()> {
        // Never send an empty buffer, because that would be interpreted
        // as the end of the stream, which we indicate explicitly on drop.
        if self.is_buffer_empty() {
            return Ok(());
        }
        // Prepend the length and \r\n to the buffer.
        let prelude = format!("{:x}\r\n", self.buffer_len());
        let prelude = prelude.as_bytes();

        // This should never happen because MAX_CHUNK_SIZE of u32::MAX
        // can always be encoded in 4 hex bytes.
        assert!(PLACEHOLDER_HEADER_SIZE <= prelude.len(), "invariant failed: prelude longer than PLACEHOLDER_HEADER_SIZE");

        // Copy the prelude into the buffer. For small chunks, this won't necessarily
        // take up all the space that was reserved for the prelude.
        let offset = PLACEHOLDER_HEADER_SIZE - prelude.len();
        self.buffer[offset..PLACEHOLDER_HEADER_SIZE].clone_from_slice(&prelude);

        // Append the chunk-finishing \r\n to the buffer.
        self.buffer.write_all(b"\r\n")?;

        self.output.write_all(&self.buffer[offset..])?;
        self.reset_buffer();

        Ok(())
    }
}

impl<W> Write for Encoder<W>
where
    W: Write,
{
    fn write(&mut self, data: &[u8]) -> IoResult<usize> {
        let remaining_buffer_space = self.chunks_size - self.buffer_len();
        let bytes_to_buffer = std::cmp::min(remaining_buffer_space, data.len());
        self.buffer.extend_from_slice(&data[0..bytes_to_buffer]);
        let more_to_write: bool = bytes_to_buffer < data.len();
        if self.flush_after_write || more_to_write {
            self.send()?;
        }

        // If we didn't write the whole thing, keep working on it.
        if more_to_write {
            self.write_all(&data[bytes_to_buffer..])?;
        }
        Ok(data.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        self.send()
    }
}

impl<W> Drop for Encoder<W>
where
    W: Write,
{
    fn drop(&mut self) {
        self.flush().ok();
        write!(self.output, "0\r\n\r\n").ok();
    }
}

#[cfg(test)]
mod test {
    use super::Encoder;
    use std::io;
    use std::io::Write;
    use std::str::from_utf8;

    #[test]
    fn test() {
        let mut source = io::Cursor::new("hello world".to_string().into_bytes());
        let mut dest: Vec<u8> = vec![];

        {
            let mut encoder = Encoder::with_chunks_size(dest.by_ref(), 5);
            io::copy(&mut source, &mut encoder).unwrap();
            assert!(!encoder.is_buffer_empty());
        }

        let output = from_utf8(&dest).unwrap();

        assert_eq!(output, "5\r\nhello\r\n5\r\n worl\r\n1\r\nd\r\n0\r\n\r\n");
    }
    #[test]
    fn flush_after_write() {
        let mut source = io::Cursor::new("hello world".to_string().into_bytes());
        let mut dest: Vec<u8> = vec![];

        {
            let mut encoder = Encoder::with_flush_after_write(dest.by_ref());
            io::copy(&mut source, &mut encoder).unwrap();
            // The internal buffer has been flushed.
            assert!(encoder.is_buffer_empty());
        }

        let output = from_utf8(&dest).unwrap();

        assert_eq!(output, "b\r\nhello world\r\n0\r\n\r\n");
    }
}
<commit_msg>Fix bug with reversed assertion condition<commit_after>// Copyright 2015 The tiny-http Contributors
// Copyright 2015 The rust-chunked-transfer Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::Result as IoResult;
use std::io::Write;

/// Splits the incoming data into HTTP chunks.
///
/// # Example
///
/// ```
/// use chunked_transfer::Encoder;
/// use std::io::Write;
///
/// let mut decoded = "hello world";
/// let mut encoded: Vec<u8> = vec![];
///
/// {
///     let mut encoder = Encoder::with_chunks_size(&mut encoded, 5);
///     encoder.write_all(decoded.as_bytes());
/// }
///
/// assert_eq!(encoded, b"5\r\nhello\r\n5\r\n worl\r\n1\r\nd\r\n0\r\n\r\n");
/// ```
pub struct Encoder<W>
where
    W: Write,
{
    // where to send the result
    output: W,

    // size of each chunk
    chunks_size: usize,

    // data waiting to be sent is stored here
    // This will always be at least 6 bytes long. The first 6 bytes
    // are reserved for the chunk size and \r\n.
    buffer: Vec<u8>,

    // Flushes the internal buffer after each write. This might be useful
    // if data should be sent immediately to downstream consumers
    flush_after_write: bool,
}

const MAX_CHUNK_SIZE: usize = std::u32::MAX as usize;
const PLACEHOLDER_HEADER_SIZE: usize = 6;

impl<W> Encoder<W>
where
    W: Write,
{
    pub fn new(output: W) -> Encoder<W> {
        Encoder::with_chunks_size(output, 8192)
    }

    pub fn with_chunks_size(output: W, chunks: usize) -> Encoder<W> {
        let chunks_size = chunks.min(MAX_CHUNK_SIZE);
        let mut encoder = Encoder {
            output,
            chunks_size,
            buffer: Vec::with_capacity(0),
            flush_after_write: false,
        };
        encoder.reset_buffer();
        encoder
    }

    pub fn with_flush_after_write(output: W) -> Encoder<W> {
        let mut encoder = Encoder {
            output,
            chunks_size: 8192,
            buffer: Vec::with_capacity(0),
            flush_after_write: true,
        };
        encoder.reset_buffer();
        encoder
    }

    fn reset_buffer(&mut self) {
        // Reset buffer
        self.buffer.clear();
        // Reserve space for the chunk size. This space will be populated once
        // we know the size of the chunk.
        self.buffer.resize(PLACEHOLDER_HEADER_SIZE, 0);
    }

    fn is_buffer_empty(&self) -> bool {
        self.buffer.len() == PLACEHOLDER_HEADER_SIZE
    }

    fn buffer_len(&self) -> usize {
        self.buffer.len() - PLACEHOLDER_HEADER_SIZE
    }

    fn send(&mut self) -> IoResult<()> {
        // Never send an empty buffer, because that would be interpreted
        // as the end of the stream, which we indicate explicitly on drop.
        if self.is_buffer_empty() {
            return Ok(());
        }
        // Prepend the length and \r\n to the buffer.
        let prelude = format!("{:x}\r\n", self.buffer_len());
        let prelude = prelude.as_bytes();

        // This should never happen because MAX_CHUNK_SIZE of u32::MAX
        // can always be encoded in 4 hex bytes.
        assert!(prelude.len() <= PLACEHOLDER_HEADER_SIZE, "invariant failed: prelude longer than PLACEHOLDER_HEADER_SIZE");

        // Copy the prelude into the buffer. For small chunks, this won't necessarily
        // take up all the space that was reserved for the prelude.
        let offset = PLACEHOLDER_HEADER_SIZE - prelude.len();
        self.buffer[offset..PLACEHOLDER_HEADER_SIZE].clone_from_slice(&prelude);

        // Append the chunk-finishing \r\n to the buffer.
        self.buffer.write_all(b"\r\n")?;

        self.output.write_all(&self.buffer[offset..])?;
        self.reset_buffer();

        Ok(())
    }
}

impl<W> Write for Encoder<W>
where
    W: Write,
{
    fn write(&mut self, data: &[u8]) -> IoResult<usize> {
        let remaining_buffer_space = self.chunks_size - self.buffer_len();
        let bytes_to_buffer = std::cmp::min(remaining_buffer_space, data.len());
        self.buffer.extend_from_slice(&data[0..bytes_to_buffer]);
        let more_to_write: bool = bytes_to_buffer < data.len();
        if self.flush_after_write || more_to_write {
            self.send()?;
        }

        // If we didn't write the whole thing, keep working on it.
        if more_to_write {
            self.write_all(&data[bytes_to_buffer..])?;
        }
        Ok(data.len())
    }

    fn flush(&mut self) -> IoResult<()> {
        self.send()
    }
}

impl<W> Drop for Encoder<W>
where
    W: Write,
{
    fn drop(&mut self) {
        self.flush().ok();
        write!(self.output, "0\r\n\r\n").ok();
    }
}

#[cfg(test)]
mod test {
    use super::Encoder;
    use std::io;
    use std::io::Write;
    use std::str::from_utf8;

    #[test]
    fn test() {
        let mut source = io::Cursor::new("hello world".to_string().into_bytes());
        let mut dest: Vec<u8> = vec![];

        {
            let mut encoder = Encoder::with_chunks_size(dest.by_ref(), 5);
            io::copy(&mut source, &mut encoder).unwrap();
            assert!(!encoder.is_buffer_empty());
        }

        let output = from_utf8(&dest).unwrap();

        assert_eq!(output, "5\r\nhello\r\n5\r\n worl\r\n1\r\nd\r\n0\r\n\r\n");
    }
    #[test]
    fn flush_after_write() {
        let mut source = io::Cursor::new("hello world".to_string().into_bytes());
        let mut dest: Vec<u8> = vec![];

        {
            let mut encoder = Encoder::with_flush_after_write(dest.by_ref());
            io::copy(&mut source, &mut encoder).unwrap();
            // The internal buffer has been flushed.
            assert!(encoder.is_buffer_empty());
        }

        let output = from_utf8(&dest).unwrap();

        assert_eq!(output, "b\r\nhello world\r\n0\r\n\r\n");
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Entropy
extern crate collections;

use std::str::StrSlice;
use collections::hashmap::HashMap;

pub fn shannon_entropy(s: &str) -> f64 {
    let mut map = HashMap::<char, uint>::new();

    // Count occurrences of each char
    for c in s.chars() {
        map.insert_or_update_with(c, 1, |_,v| *v += 1);
    }

    // Calculate the entropy
    let len = s.len() as f64;
    map.iter().fold(0f64, |mut acc, (_, nb)| {
        let p = (*nb as f64) / len;
        acc -= p * p.log2();
        acc
    })
}
// Needed so fibonacci_word compiles cleanly, because fibonacci_word
// uses this code as a library
#[allow(dead_code)]
#[cfg(not(test))]
fn main() {
    println!("{:f}", shannon_entropy("1223334444"));
}

#[test]
fn test_entropy() {
    let tests = vec![
        ("1223334444", 1.846439344671f64),
        ("1223334444555555555", 1.969811065121),
        ("122333", 1.459147917061),
        ("1227774444", 1.846439344671),
        ("aaBBcccDDDD", 1.936260027482),
        ("1234567890abcdefghijklmnopqrstuvwxyz", 5.169925004424),
        ("Rosetta Code", 3.084962500407)];
    // Good enough, actual float epsilon is much smaller
    let epsilon: f64 = 0.0000001;
    for (input, expected) in tests.move_iter() {
        let output = shannon_entropy(input);
        assert!((output - expected).abs() < epsilon);
    }
}
<commit_msg>No need to modify accumulator in `fold` iterator.<commit_after>// Implements http://rosettacode.org/wiki/Entropy
extern crate collections;

use std::str::StrSlice;
use collections::hashmap::HashMap;

pub fn shannon_entropy(s: &str) -> f64 {
    let mut map = HashMap::<char, uint>::new();

    // Count occurrences of each char
    for c in s.chars() {
        map.insert_or_update_with(c, 1, |_,v| *v += 1);
    }

    // Calculate the entropy
    let len = s.len() as f64;
    map.iter().fold(0f64, |acc, (_, nb)| {
        let p = (*nb as f64) / len;
        acc - p * p.log2()
    })
}
// Needed so fibonacci_word compiles cleanly, because fibonacci_word
// uses this code as a library
#[allow(dead_code)]
#[cfg(not(test))]
fn main() {
    println!("{:f}", shannon_entropy("1223334444"));
}

#[test]
fn test_entropy() {
    let tests = vec![
        ("1223334444", 1.846439344671f64),
        ("1223334444555555555", 1.969811065121),
        ("122333", 1.459147917061),
        ("1227774444", 1.846439344671),
        ("aaBBcccDDDD", 1.936260027482),
        ("1234567890abcdefghijklmnopqrstuvwxyz", 5.169925004424),
        ("Rosetta Code", 3.084962500407)];
    // Good enough, actual float epsilon is much smaller
    let epsilon: f64 = 0.0000001;
    for (input, expected) in tests.move_iter() {
        let output = shannon_entropy(input);
        assert!((output - expected).abs() < epsilon);
    }
}
<|endoftext|>


<commit_before>//! Implements a simple linear finite element solver

#![allow(dead_code)]
#![allow(unused_variables)]

// macro_rules! print_bc {
//     ($b:expr, $c:expr, $k:expr, $g:expr, $t:expr, $x:expr, $f:expr) => {{
//         println!("{} {} k:{:?} g:{} p:{} t:{} x:{:?} f:{}", $b, $c, $k, $g, 0, $t, $x, $f);
//     }};
// }

use crate::mesh::{EdgeKey, Index, Mesh};
use crate::StrError;
use russell_lab::{Matrix, Vector};
use russell_sparse::{SparseTriplet, Symmetry};

#[derive(Clone, Copy)]
pub enum DOF {
    T,     // temperature or any other scalar such as hydraulic head
    Pl,    // liquid pressure
    Pg,    // gas pressure
    Ux,    // displacement along x
    Uy,    // displacement along y
    Uz,    // displacement along z
    Rx,    // rotation around x
    Ry,    // rotation around y
    Rz,    // rotation around z
    Wlx,   // relative liquid velocity along x
    Wly,   // relative liquid velocity along y
    Wlz,   // relative liquid velocity along z
    Extra, // extra (enriched) degree of freedom
}

pub type FnTimeSpace = fn(f64, &[f64]) -> f64;

#[derive(Clone, Copy)]
pub enum BC {
    Essential,
    Natural,
}

#[derive(Clone, Copy)]
pub struct PointBC {
    bc: BC,
    dof: DOF,
    f: FnTimeSpace,
    id: Index,
}

#[derive(Clone, Copy)]
pub struct EdgeBC {
    bc: BC,
    dof: DOF,
    f: FnTimeSpace,
    key: EdgeKey,
}

pub struct Node {
    dofs: Vec<DOF>,
}

pub struct Element {
    //
}

impl Element {
    fn compute_ke(&mut self) -> Result<(), StrError> {
        Ok(())
    }
    fn add_ke_to_kk(&self, kk: &mut SparseTriplet) -> Result<(), StrError> {
        Ok(())
    }
    fn add_fe_to_ff(&self, ff: &mut Vector) -> Result<(), StrError> {
        Ok(())
    }
}

pub struct Simulation {
    mesh: Mesh,
    point_bcs: Vec<PointBC>,
    edge_bcs: Vec<EdgeBC>,
    elements: Vec<Element>,
}

impl Simulation {
    pub fn new(mesh: Mesh) -> Result<Self, StrError> {
        Ok(Simulation {
            mesh,
            point_bcs: Vec::new(),
            edge_bcs: Vec::new(),
            elements: Vec::new(),
        })
    }

    pub fn add_point_bc(&mut self, group: &str, bc: BC, dof: DOF, f: FnTimeSpace) -> &mut Self {
        let ids = self.mesh.get_boundary_point_ids_sorted(group);
        for id in ids {
            self.point_bcs.push(PointBC { bc, dof, f, id });
        }
        self
    }

    pub fn add_edge_bc(&mut self, group: &str, bc: BC, dof: DOF, f: FnTimeSpace) -> &mut Self {
        let keys = self.mesh.get_boundary_edge_keys_sorted(group);
        for key in keys {
            self.edge_bcs.push(EdgeBC { bc, dof, f, key });
        }
        self
    }

    pub fn run(&mut self) -> Result<(), StrError> {
        let time = 0.0; // time

        let n = 2;
        let nnz = 2;
        let mut uu = Vector::new(n);
        let mut ff = Vector::new(n);
        let mut kk = SparseTriplet::new(n, n, nnz, Symmetry::No)?;

        // assemble element Ke matrices (can be done in parallel)
        for element in &mut self.elements {
            element.compute_ke()?;
        }

        // add element Ke matrix to global K matrix (must be serial)
        for element in &self.elements {
            element.add_ke_to_kk(&mut kk)?;
        }

        // add element Fe vector to global F vector (must be serial)
        for element in &self.elements {
            element.add_fe_to_ff(&mut ff)?;
        }

        let i = 0;

        // handle point boundary conditions
        for item in &self.point_bcs {
            let x = &self.mesh.points[item.id].coords;
            let val = (item.f)(time, x);
            match item.bc {
                BC::Essential => {
                    kk.put(i, i, 1.0);
                    uu[i] = val;
                    ff[i] = val;
                }
                BC::Natural => {
                    ff[i] = val;
                }
            }
        }

        // handle edge boundary conditions
        for item in &self.edge_bcs {
            let edge = match self.mesh.boundary_edges.get(&item.key) {
                Some(e) => e,
                None => return Err("cannot find boundary edge"),
            };
            match item.bc {
                BC::Essential => {
                    for id in &edge.points {
                        let x = &self.mesh.points[*id].coords;
                        let val = (item.f)(time, x);
                        kk.put(i, i, 1.0);
                        uu[i] = val;
                        ff[i] = val;
                    }
                }
                BC::Natural => {
                    // perform integration
                }
            }
        }

        Ok(())
    }
}

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

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

    #[test]
    fn run_works() -> Result<(), StrError> {
        // create mesh
        let mut mesh = Mesh::from_text(
            r"
            # header
            # ndim npoint ncell
            2 6 2

            # points
            # id x y
            0  0.0 0.0
            1  1.0 0.0
            2  1.0 1.0
            3  0.0 1.0
            4  2.0 0.0
            5  2.0 1.0

            # cells
            # id attribute ndim npoint point_ids...
            0 1  2 4  0 1 2 3
            1 0  2 4  1 4 5 2
            ",
        )?;

        // set groups of points and edges at boundaries
        mesh.set_points("origin", At::XY(0.0, 0.0))?
            .set_edges("left", At::X(0.0))?
            .set_edges("right", At::X(1.0))?
            .set_edges("bottom", At::Y(0.0))?
            .set_edges("top", At::Y(1.0))?;

        // create simulation
        let mut sim = Simulation::new(mesh)?;

        // set boundary conditions
        sim.add_point_bc("origin", BC::Essential, DOF::Ux, |_, _| 0.0)
            .add_point_bc("origin", BC::Essential, DOF::Uy, |_, _| 0.0)
            .add_edge_bc("left", BC::Essential, DOF::Ux, |_, _| 0.0)
            .add_edge_bc("right", BC::Essential, DOF::Ux, |_, _| 0.0)
            .add_edge_bc("bottom", BC::Essential, DOF::Uy, |_, _| 0.0);

        // run simulation
        sim.run();

        Ok(())
    }
}
<commit_msg>[wip] Draft FEM<commit_after>//! Implements a simple linear finite element solver

#![allow(dead_code)]
#![allow(unused_variables)]

// macro_rules! print_bc {
//     ($b:expr, $c:expr, $k:expr, $g:expr, $t:expr, $x:expr, $f:expr) => {{
//         println!("{} {} k:{:?} g:{} p:{} t:{} x:{:?} f:{}", $b, $c, $k, $g, 0, $t, $x, $f);
//     }};
// }

use std::collections::HashMap;

use crate::mesh::{EdgeKey, Index, Mesh};
use crate::StrError;
use russell_lab::{Matrix, Vector};
use russell_sparse::{SparseTriplet, Symmetry};

#[derive(Clone, Copy)]
pub enum DOF {
    T,     // temperature or any other scalar such as hydraulic head
    Pl,    // liquid pressure
    Pg,    // gas pressure
    Ux,    // displacement along x
    Uy,    // displacement along y
    Uz,    // displacement along z
    Rx,    // rotation around x
    Ry,    // rotation around y
    Rz,    // rotation around z
    Wlx,   // relative liquid velocity along x
    Wly,   // relative liquid velocity along y
    Wlz,   // relative liquid velocity along z
    Extra, // extra (enriched) degree of freedom
}

pub type FnTimeSpace = fn(f64, &[f64]) -> f64;

#[derive(Clone, Copy)]
pub enum BC {
    Essential,
    Natural,
}

#[derive(Clone, Copy)]
pub struct PointBC {
    bc: BC,
    dof: DOF,
    f: FnTimeSpace,
    id: Index,
}

#[derive(Clone, Copy)]
pub struct EdgeBC {
    bc: BC,
    dof: DOF,
    f: FnTimeSpace,
    key: EdgeKey,
}

pub struct Node {
    dofs: Vec<DOF>,
}

pub struct Element {
    //
}

impl Element {
    fn compute_ke(&mut self) -> Result<(), StrError> {
        Ok(())
    }
    fn add_ke_to_kk(&self, kk: &mut SparseTriplet) -> Result<(), StrError> {
        Ok(())
    }
    fn add_fe_to_ff(&self, ff: &mut Vector) -> Result<(), StrError> {
        Ok(())
    }
}

pub enum ProblemElement {
    MechanicalBeam,
    MechanicalTruss,
    MechanicalSolid,
    PorousLiquid,
    PorousLiquidGas,
    PorousSolidLiquidGas,
    DiffusionTemperature,
}

pub struct Attribute {
    inactive: bool,
    kind: ProblemElement,
    properties: HashMap<String, f64>,
}

pub struct Simulation {
    mesh: Mesh,
    point_bcs: Vec<PointBC>,
    edge_bcs: Vec<EdgeBC>,
    elements: Vec<Element>,
    attributes: HashMap<usize, Attribute>,
}

impl Simulation {
    pub fn new(mesh: Mesh) -> Result<Self, StrError> {
        Ok(Simulation {
            mesh,
            point_bcs: Vec::new(),
            edge_bcs: Vec::new(),
            elements: Vec::new(),
            attributes: HashMap::new(),
        })
    }

    pub fn add_point_bc(&mut self, group: &str, bc: BC, dof: DOF, f: FnTimeSpace) -> &mut Self {
        let ids = self.mesh.get_boundary_point_ids_sorted(group);
        for id in ids {
            self.point_bcs.push(PointBC { bc, dof, f, id });
        }
        self
    }

    pub fn add_edge_bc(&mut self, group: &str, bc: BC, dof: DOF, f: FnTimeSpace) -> &mut Self {
        let keys = self.mesh.get_boundary_edge_keys_sorted(group);
        for key in keys {
            self.edge_bcs.push(EdgeBC { bc, dof, f, key });
        }
        self
    }

    pub fn initialize(&mut self) -> Result<(), StrError> {
        // allocate all elements and assign numbers to the DOFs
        for cell in &self.mesh.cells {
            let props = match self.attributes.get(&cell.attribute_id) {
                Some(a) => {
                    if a.inactive {
                        continue;
                    }
                    &a.properties
                }
                None => return Err("cannot find cell with a specific attribute id"),
            };
            // how to get tne DOFs for each element/problem?
        }
        Ok(())
    }

    pub fn run(&mut self) -> Result<(), StrError> {
        let time = 0.0; // time

        let n = 2;
        let nnz = 2;
        let mut uu = Vector::new(n);
        let mut ff = Vector::new(n);
        let mut kk = SparseTriplet::new(n, n, nnz, Symmetry::No)?;

        // assemble element Ke matrices (can be done in parallel)
        for element in &mut self.elements {
            element.compute_ke()?;
        }

        // add element Ke matrix to global K matrix (must be serial)
        for element in &self.elements {
            element.add_ke_to_kk(&mut kk)?;
        }

        // add element Fe vector to global F vector (must be serial)
        for element in &self.elements {
            element.add_fe_to_ff(&mut ff)?;
        }

        let i = 0;

        // handle point boundary conditions
        for item in &self.point_bcs {
            let x = &self.mesh.points[item.id].coords;
            let val = (item.f)(time, x);
            match item.bc {
                BC::Essential => {
                    kk.put(i, i, 1.0);
                    uu[i] = val;
                    ff[i] = val;
                }
                BC::Natural => {
                    ff[i] = val;
                }
            }
        }

        // handle edge boundary conditions
        for item in &self.edge_bcs {
            let edge = match self.mesh.boundary_edges.get(&item.key) {
                Some(e) => e,
                None => return Err("cannot find boundary edge"),
            };
            match item.bc {
                BC::Essential => {
                    for id in &edge.points {
                        let x = &self.mesh.points[*id].coords;
                        let val = (item.f)(time, x);
                        kk.put(i, i, 1.0);
                        uu[i] = val;
                        ff[i] = val;
                    }
                }
                BC::Natural => {
                    // perform integration
                }
            }
        }

        Ok(())
    }
}

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

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

    #[test]
    fn run_works() -> Result<(), StrError> {
        // create mesh
        let mut mesh = Mesh::from_text(
            r"
            # header
            # ndim npoint ncell
            2 6 2

            # points
            # id x y
            0  0.0 0.0
            1  1.0 0.0
            2  1.0 1.0
            3  0.0 1.0
            4  2.0 0.0
            5  2.0 1.0

            # cells
            # id attribute ndim npoint point_ids...
            0 1  2 4  0 1 2 3
            1 0  2 4  1 4 5 2
            ",
        )?;

        // set groups of points and edges at boundaries
        mesh.set_points("origin", At::XY(0.0, 0.0))?
            .set_edges("left", At::X(0.0))?
            .set_edges("right", At::X(1.0))?
            .set_edges("bottom", At::Y(0.0))?
            .set_edges("top", At::Y(1.0))?;

        // create simulation
        let mut sim = Simulation::new(mesh)?;

        // set boundary conditions
        sim.add_point_bc("origin", BC::Essential, DOF::Ux, |_, _| 0.0)
            .add_point_bc("origin", BC::Essential, DOF::Uy, |_, _| 0.0)
            .add_edge_bc("left", BC::Essential, DOF::Ux, |_, _| 0.0)
            .add_edge_bc("right", BC::Essential, DOF::Ux, |_, _| 0.0)
            .add_edge_bc("bottom", BC::Essential, DOF::Uy, |_, _| 0.0);

        // run simulation
        sim.run();

        Ok(())
    }
}
<|endoftext|>


<commit_before>use coordinates::{CoordinateSystem, Point};
use std::ops::{Index, IndexMut, Add};
use std::marker::PhantomData;
use typenum::uint::Unsigned;
use typenum::consts::U1;
use typenum::Pow;
use generic_array::{GenericArray, ArrayLength};

/// This enum serves to represent the type of a tensor. A tensor can have any number of indices, and each one can be either
/// covariant (a lower index), or contravariant (an upper index). For example, a vector is a tensor with only one contravariant index.
#[derive(Clone, Copy)]
pub enum IndexType {
       Covariant,
       Contravariant
}

pub trait TensorIndex {
	fn index_type() -> IndexType;
}

pub struct ContravariantIndex;
impl TensorIndex for ContravariantIndex {
	fn index_type() -> IndexType { IndexType::Contravariant }
}

pub struct CovariantIndex;
impl TensorIndex for CovariantIndex {
	fn index_type() -> IndexType { IndexType::Covariant }
}

pub trait Variance {
	type Rank: Unsigned + Add<U1>;
	fn rank() -> usize { Self::Rank::to_usize() }
	fn variance() -> Vec<IndexType>;
}

impl Variance for ContravariantIndex {
	type Rank = U1;
	fn variance() -> Vec<IndexType> { vec![IndexType::Contravariant] }
}

impl Variance for CovariantIndex {
	type Rank = U1;
	fn variance() -> Vec<IndexType> { vec![IndexType::Covariant] }
}

impl<T, U> Variance for (T, U)
	where
		T: Variance,
		<T::Rank as Add<U1>>::Output: Unsigned + Add<U1>,
		U: TensorIndex
{
	type Rank = <T::Rank as Add<U1>>::Output;

	fn variance() -> Vec<IndexType> {
		let mut result = T::variance();
		result.push(U::index_type());
		result
	}
}

/// This is a struct that represents a generic tensor
pub struct Tensor<T: CoordinateSystem, U: Variance>
    where T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
	p: Point<T>,
	x: GenericArray<f64, <T::Dimension as Pow<U::Rank>>::Output>,
	phantom: PhantomData<U>
}

impl<T, U> Tensor<T, U>
    where T: CoordinateSystem, U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{

	/// Returns the point at which the tensor is defined.
	pub fn get_point(&self) -> &Point<T> {
		&self.p
	}

	/// Returns a reference to a coordinate of the tensor, at indices specified by the slice.
	/// The length of the slice (the number of indices) has to be compatible with the rank of the tensor.
	pub fn get_coord(&self, i: &[usize]) -> &f64 {
		assert_eq!(i.len(), U::rank());
		let dim = T::dimension();
		let index = i.into_iter().fold(0, |res, idx| { assert!(*idx < dim); res*dim + idx });
		&self.x[index]
	}

	/// Returns a mutable reference to a coordinate of the tensor, at indices specified by the slice.
	/// The length of the slice (the number of indices) has to be compatible with the rank of the tensor.
	pub fn get_coord_mut(&mut self, i: &[usize]) -> &mut f64 {
		assert_eq!(i.len(), U::rank());
		let dim = T::dimension();
		let index = i.into_iter().fold(0, |res, idx| { assert!(*idx < dim); res*dim + idx });
		&mut self.x[index]
	}

	/// Returns the variance of the tensor, that is, the list of the index types.
	/// A vector would return vec![Contravariant], a metric tensor: vec![Covariant, Covariant].
	pub fn get_variance() -> Vec<IndexType> { U::variance() }

	/// Returns the rank of the tensor
	pub fn get_rank() -> usize { U::rank() }

	pub fn new(point: Point<T>) -> Tensor<T, U> {
		Tensor {
			p: point,
			x: GenericArray::new(),
			phantom: PhantomData
		}
	}
}

impl<'a, T, U> Index<&'a [usize]> for Tensor<T, U>
    where T: CoordinateSystem, U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
	type Output = f64;

	fn index(&self, idx: &'a [usize]) -> &f64 {
		self.get_coord(idx)
	}
}

impl<'a, T, U> IndexMut<&'a [usize]> for Tensor<T, U>
    where T: CoordinateSystem, U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
	fn index_mut(&mut self, idx: &'a [usize]) -> &mut f64 {
		self.get_coord_mut(idx)
	}
}

pub type Vector<T> = Tensor<T, ContravariantIndex>;
pub type Covector<T> = Tensor<T, CovariantIndex>;
pub type Matrix<T> = Tensor<T, (ContravariantIndex, CovariantIndex)>;

#[cfg(test)]
mod test {
	use typenum::consts::U4;
	use typenum::uint::Unsigned;
	use coordinates::CoordinateSystem;
	use super::{Vector, Matrix, NCoords};

	struct Test;
	impl CoordinateSystem for Test {
		type Dimension = U4;
	}

	#[test]
	fn test_ranks() {
		assert_eq!(Vector::<Test>::get_rank(), 1);
		assert_eq!(Matrix::<Test>::get_rank(), 2);
	}

	#[test]
	fn test_num_coords() {
		assert_eq!(<Vector<Test> as NCoords>::Output::to_usize(), 4);
		assert_eq!(<Matrix<Test> as NCoords>::Output::to_usize(), 16);
	}
}
<commit_msg>Updated tests<commit_after>use coordinates::{CoordinateSystem, Point};
use std::ops::{Index, IndexMut, Add};
use std::marker::PhantomData;
use typenum::uint::Unsigned;
use typenum::consts::U1;
use typenum::Pow;
use generic_array::{GenericArray, ArrayLength};

/// This enum serves to represent the type of a tensor. A tensor can have any number of indices, and each one can be either
/// covariant (a lower index), or contravariant (an upper index). For example, a vector is a tensor with only one contravariant index.
#[derive(Clone, Copy)]
pub enum IndexType {
       Covariant,
       Contravariant
}

pub trait TensorIndex {
	fn index_type() -> IndexType;
}

pub struct ContravariantIndex;
impl TensorIndex for ContravariantIndex {
	fn index_type() -> IndexType { IndexType::Contravariant }
}

pub struct CovariantIndex;
impl TensorIndex for CovariantIndex {
	fn index_type() -> IndexType { IndexType::Covariant }
}

pub trait Variance {
	type Rank: Unsigned + Add<U1>;
	fn rank() -> usize { Self::Rank::to_usize() }
	fn variance() -> Vec<IndexType>;
}

impl Variance for ContravariantIndex {
	type Rank = U1;
	fn variance() -> Vec<IndexType> { vec![IndexType::Contravariant] }
}

impl Variance for CovariantIndex {
	type Rank = U1;
	fn variance() -> Vec<IndexType> { vec![IndexType::Covariant] }
}

impl<T, U> Variance for (T, U)
	where
		T: Variance,
		<T::Rank as Add<U1>>::Output: Unsigned + Add<U1>,
		U: TensorIndex
{
	type Rank = <T::Rank as Add<U1>>::Output;

	fn variance() -> Vec<IndexType> {
		let mut result = T::variance();
		result.push(U::index_type());
		result
	}
}

/// This is a struct that represents a generic tensor
pub struct Tensor<T: CoordinateSystem, U: Variance>
    where T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
	p: Point<T>,
	x: GenericArray<f64, <T::Dimension as Pow<U::Rank>>::Output>,
	phantom: PhantomData<U>
}

impl<T, U> Tensor<T, U>
    where T: CoordinateSystem, U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{

	/// Returns the point at which the tensor is defined.
	pub fn get_point(&self) -> &Point<T> {
		&self.p
	}

	/// Returns a reference to a coordinate of the tensor, at indices specified by the slice.
	/// The length of the slice (the number of indices) has to be compatible with the rank of the tensor.
	pub fn get_coord(&self, i: &[usize]) -> &f64 {
		assert_eq!(i.len(), U::rank());
		let dim = T::dimension();
		let index = i.into_iter().fold(0, |res, idx| { assert!(*idx < dim); res*dim + idx });
		&self.x[index]
	}

	/// Returns a mutable reference to a coordinate of the tensor, at indices specified by the slice.
	/// The length of the slice (the number of indices) has to be compatible with the rank of the tensor.
	pub fn get_coord_mut(&mut self, i: &[usize]) -> &mut f64 {
		assert_eq!(i.len(), U::rank());
		let dim = T::dimension();
		let index = i.into_iter().fold(0, |res, idx| { assert!(*idx < dim); res*dim + idx });
		&mut self.x[index]
	}

	/// Returns the variance of the tensor, that is, the list of the index types.
	/// A vector would return vec![Contravariant], a metric tensor: vec![Covariant, Covariant].
	pub fn get_variance() -> Vec<IndexType> { U::variance() }

	/// Returns the rank of the tensor
	pub fn get_rank() -> usize { U::rank() }

    /// Returns the number of coordinates of the tensor
    pub fn get_num_coords() -> usize { <T::Dimension as Pow<U::Rank>>::Output::to_usize() }

	pub fn new(point: Point<T>) -> Tensor<T, U> {
		Tensor {
			p: point,
			x: GenericArray::new(),
			phantom: PhantomData
		}
	}
}

impl<'a, T, U> Index<&'a [usize]> for Tensor<T, U>
    where T: CoordinateSystem, U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
	type Output = f64;

	fn index(&self, idx: &'a [usize]) -> &f64 {
		self.get_coord(idx)
	}
}

impl<'a, T, U> IndexMut<&'a [usize]> for Tensor<T, U>
    where T: CoordinateSystem, U: Variance,
          T::Dimension: Pow<U::Rank>,
          <T::Dimension as Pow<U::Rank>>::Output: ArrayLength<f64>
{
	fn index_mut(&mut self, idx: &'a [usize]) -> &mut f64 {
		self.get_coord_mut(idx)
	}
}

pub type Vector<T> = Tensor<T, ContravariantIndex>;
pub type Covector<T> = Tensor<T, CovariantIndex>;
pub type Matrix<T> = Tensor<T, (ContravariantIndex, CovariantIndex)>;

#[cfg(test)]
mod test {
	use typenum::consts::U4;
	use coordinates::CoordinateSystem;
	use super::{Vector, Matrix};

	struct Test;
	impl CoordinateSystem for Test {
		type Dimension = U4;
	}

	#[test]
	fn test_ranks() {
		assert_eq!(Vector::<Test>::get_rank(), 1);
		assert_eq!(Matrix::<Test>::get_rank(), 2);
	}

	#[test]
	fn test_num_coords() {
		assert_eq!(Vector::<Test>::get_num_coords(), 4);
		assert_eq!(Matrix::<Test>::get_num_coords(), 16);
	}
}
<|endoftext|>


<commit_before>#[derive(Debug, Serialize, Deserialize)]
pub struct CsvParams {
    #[serde(rename = "quoteChar")]
    pub quote_char: Option<String>,

    #[serde(rename = "escapeChar")]
    pub escape_char: Option<String>,

    #[serde(rename = "separatorChar")]
    pub separator_char: Option<String>,

    #[serde(rename = "endOfLine")]
    pub end_of_line: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Part {
    #[serde(rename = "columnName")]
    pub column_name: Option<String>,

    pub mode: Option<String>,

    pub populates: Option<Vec<String>>,

    #[serde(rename = "referenceKey")]
    pub reference_key: Option<u32>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DataSetSLIManifest {
    #[serde(rename = "dataSet")]
    pub dataset: Option<String>,

    pub file: Option<String>,

    #[serde(rename = "csvParams")]
    pub csv_params: Option<CsvParams>,

    pub parts: Option<Vec<Part>>

}

#[derive(Debug, Serialize, Deserialize)]
pub struct Manifest {
    #[serde(rename = "dataSetSLIManifest")]
    pub manifest: Option<DataSetSLIManifest>
}
<commit_msg>Load constraints<commit_after>use std::collections::BTreeMap;

#[derive(Debug, Serialize, Deserialize)]
pub struct CsvParams {
    #[serde(rename = "quoteChar")]
    pub quote_char: Option<String>,

    #[serde(rename = "escapeChar")]
    pub escape_char: Option<String>,

    #[serde(rename = "separatorChar")]
    pub separator_char: Option<String>,

    #[serde(rename = "endOfLine")]
    pub end_of_line: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Part {
    #[serde(rename = "columnName")]
    pub column_name: Option<String>,

    pub mode: Option<String>,

    pub populates: Option<Vec<String>>,

    pub constraints: Option<BTreeMap<String, String>>,

    #[serde(rename = "referenceKey")]
    pub reference_key: Option<u32>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct DataSetSLIManifest {
    #[serde(rename = "dataSet")]
    pub dataset: Option<String>,

    pub file: Option<String>,

    #[serde(rename = "csvParams")]
    pub csv_params: Option<CsvParams>,

    pub parts: Option<Vec<Part>>

}

#[derive(Debug, Serialize, Deserialize)]
pub struct Manifest {
    #[serde(rename = "dataSetSLIManifest")]
    pub manifest: Option<DataSetSLIManifest>
}
<|endoftext|>


<commit_before>#![feature(associated_consts)]

pub extern crate futures;
extern crate c3po;
extern crate mainsail;
extern crate rigging;
extern crate cargonauts_config;
pub extern crate serde;
pub extern crate serde_json as json;
pub extern crate tokio_redis as redis;
extern crate tokio_service;

#[allow(unused_imports)]
#[macro_use] extern crate compass_rose;
#[macro_use] extern crate proc_macro_hack;

#[doc(hidden)]
pub use compass_rose::*;

proc_macro_item_decl! {
    /// The routes DSL
    routes! => routes_impl
}

pub mod config {
    pub use cargonauts_config::CargonautsConfig;
}

#[macro_use]
pub mod resources {
    pub use rigging::Error;
    pub use rigging::environment::Environment;

    pub use rigging::resource::{Resource, Relationship};

    #[macro_export]
    macro_rules! relation {
        ($rel:ident => $resource:ident) => {
            pub struct $rel;

            impl $crate::resources::Relationship for $rel {
                type Related = $resource;
            }
        }
    }
}

pub mod methods {
    pub use rigging::method::Method;
    pub use rigging::routes::{Route, Kind};
    pub use mainsail::methods::*;
}

pub mod formats {

    pub use rigging::format::{Format, BuildFormat, Template, TemplateKey};
    pub use mainsail::formats::Debug;
    pub use mainsail::formats::jsonapi::JsonApi;
    pub use mainsail::formats::handlebars::Handlebars;

    pub mod jsonapi {
        pub use mainsail::formats::jsonapi::{ApiSerialize, ApiDeserialize, Fields, ClientIdPolicy};
    }
}

#[doc(hidden)]
pub mod routing {
    pub use rigging::resource::{ResourceEndpoint, RelationEndpoint, RelationshipLink, RelIds, HasOneEndpoint, HasManyEndpoint};
    pub use rigging::endpoint::{Endpoint, EndpointService};
    pub use rigging::routes::{RoutingTable, RouteBuilder, Handler, path};
    pub use rigging::routes::{AssetHandler, default_asset_handler};
    pub use rigging::environment::EnvBuilder;
    pub use rigging::http::BoxFuture as HttpFuture;
    pub use rigging::format::FormatLender;
}

pub use server::serve;

pub mod server {
    pub use rigging::http::{Request, Response, Error, Service, NewService, serve, Handle, Method, StatusCode};

    pub mod pool {
        pub use rigging::connections::Configure;
        pub use c3po::{Pool, Config};
    }
}

pub mod clients {
    pub use rigging::connections::{Client, ConnectClient, Configure, NewServiceLike};
    pub use c3po::{Config as PoolConfig, Conn};

    pub mod mock {
        pub use rigging::connections::mock::MockConnection;
    }
}

pub mod middleware {
    pub use rigging::endpoint::Request;

    pub mod http {
        pub use rigging::http::{Request, Response, Error, BoxFuture};
    }

    pub use tokio_service::Service;

    pub trait Middleware<S>: Default
    where
        S: Service<Request = Request, Response = http::Response, Error = http::Error, Future = http::BoxFuture>
    {
        type WrappedService: Service<Request = Request, Response = http::Response, Error = http::Error, Future = http::BoxFuture>;

        fn wrap(self, service: S) -> Self::WrappedService;
    }
}
<commit_msg>Export proper method traits.<commit_after>#![feature(associated_consts)]

pub extern crate futures;
extern crate c3po;
extern crate mainsail;
extern crate rigging;
extern crate cargonauts_config;
pub extern crate serde;
pub extern crate serde_json as json;
pub extern crate tokio_redis as redis;
extern crate tokio_service;

#[allow(unused_imports)]
#[macro_use] extern crate compass_rose;
#[macro_use] extern crate proc_macro_hack;

#[doc(hidden)]
pub use compass_rose::*;

proc_macro_item_decl! {
    /// The routes DSL
    routes! => routes_impl
}

pub mod config {
    pub use cargonauts_config::CargonautsConfig;
}

#[macro_use]
pub mod resources {
    pub use rigging::Error;
    pub use rigging::environment::Environment;

    pub use rigging::resource::{Resource, Relationship};

    #[macro_export]
    macro_rules! relation {
        ($rel:ident => $resource:ident) => {
            pub struct $rel;

            impl $crate::resources::Relationship for $rel {
                type Related = $resource;
            }
        }
    }
}

pub mod methods {
    pub use rigging::method::*;
    pub use rigging::routes::{Route, Kind};
    pub use mainsail::methods::*;
}

pub mod formats {

    pub use rigging::format::{Format, BuildFormat, Template, TemplateKey};
    pub use mainsail::formats::Debug;
    pub use mainsail::formats::jsonapi::JsonApi;
    pub use mainsail::formats::handlebars::Handlebars;

    pub mod jsonapi {
        pub use mainsail::formats::jsonapi::{ApiSerialize, ApiDeserialize, Fields, ClientIdPolicy};
    }
}

#[doc(hidden)]
pub mod routing {
    pub use rigging::resource::{ResourceEndpoint, RelationEndpoint, RelationshipLink, RelIds, HasOneEndpoint, HasManyEndpoint};
    pub use rigging::endpoint::{Endpoint, EndpointService};
    pub use rigging::routes::{RoutingTable, RouteBuilder, Handler, path};
    pub use rigging::routes::{AssetHandler, default_asset_handler};
    pub use rigging::environment::EnvBuilder;
    pub use rigging::http::BoxFuture as HttpFuture;
    pub use rigging::format::FormatLender;
}

pub use server::serve;

pub mod server {
    pub use rigging::http::{Request, Response, Error, Service, NewService, serve, Handle, Method, StatusCode};

    pub mod pool {
        pub use rigging::connections::Configure;
        pub use c3po::{Pool, Config};
    }
}

pub mod clients {
    pub use rigging::connections::{Client, ConnectClient, Configure, NewServiceLike};
    pub use c3po::{Config as PoolConfig, Conn};

    pub mod mock {
        pub use rigging::connections::mock::MockConnection;
    }
}

pub mod middleware {
    pub use rigging::endpoint::Request;

    pub mod http {
        pub use rigging::http::{Request, Response, Error, BoxFuture};
    }

    pub use tokio_service::Service;

    pub trait Middleware<S>: Default
    where
        S: Service<Request = Request, Response = http::Response, Error = http::Error, Future = http::BoxFuture>
    {
        type WrappedService: Service<Request = Request, Response = http::Response, Error = http::Error, Future = http::BoxFuture>;

        fn wrap(self, service: S) -> Self::WrappedService;
    }
}
<|endoftext|>