<commit_before>use std::slice;
use std::option;
use std::default::Default;
use std::fmt;
use std::mem;

use clear::Clear;

pub struct SingularField<T> {
    value: T,
    set: bool,
}

pub struct SingularPtrField<T> {
    value: Option<Box<T>>,
    set: bool,
}

impl<T> SingularField<T> {
    #[inline]
    pub fn some(value: T) -> SingularField<T> {
        SingularField {
            value: value,
            set: true,
        }
    }

    #[inline]
    pub fn is_some(&self) -> bool {
        self.set
    }

    #[inline]
    pub fn is_none(&self) -> bool {
        !self.is_some()
    }

    #[inline]
    pub fn into_option(self) -> Option<T> {
        if self.set {
            Some(self.value)
        } else {
            None
        }
    }

    #[inline]
    pub fn as_ref<'a>(&'a self) -> Option<&'a T> {
        if self.set {
            Some(&self.value)
        } else {
            None
        }
    }

    #[inline]
    pub fn as_mut<'a>(&'a mut self) -> Option<&'a mut T> {
        if self.set {
            Some(&mut self.value)
        } else {
            None
        }
    }

    #[inline]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        self.as_ref().unwrap()
    }

    #[inline]
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
        self.as_mut().unwrap()
    }

    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        // XXX: workaround since returning &[] doesn't seem to work
        let tmp: &[T] = &[];
        match self.as_ref() {
            Some(x) => slice::ref_slice(x),
            None => tmp,
        }
    }

    #[inline]
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        match self.as_mut() {
            //Some(x) => slice::mut_ref_slice(x), // doesn't work I have no idea why
            Some(_) => panic!(),
            None => &mut []
        }
    }

    #[inline]
    pub fn unwrap(self) -> T {
        if self.set {
            self.value
        } else {
            panic!();
        }
    }

    #[inline]
    pub fn unwrap_or(self, def: T) -> T {
        if self.set {
            self.value
        } else {
            def
        }
    }

    #[inline]
    pub fn unwrap_or_else(self, f: || -> T) -> T {
        if self.set {
            self.value
        } else {
            f()
        }
    }

    #[inline]
    pub fn map<U, F>(self, f: F) -> SingularPtrField<U> where F: FnOnce(T) -> U {
        SingularPtrField::from_option(self.into_option().map(f))
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> option::Item<&'a T> {
        self.as_ref().into_iter()
    }

    #[inline]
    pub fn mut_iter<'a>(&'a mut self) -> option::Item<&'a mut T> {
        self.as_mut().into_iter()
    }

    #[inline]
    pub fn clear(&mut self) {
        self.set = false;
    }
}

impl<T : Default> SingularField<T> {
    #[inline]
    pub fn none() -> SingularField<T> {
        SingularField {
            value: Default::default(),
            set: false,
        }
    }

    #[inline]
    pub fn from_option(option: Option<T>) -> SingularField<T> {
        match option {
            Some(x) => SingularField::some(x),
            None => SingularField::none(),
        }
    }

    #[inline]
    pub fn take(&mut self) -> Option<T> {
        if self.set {
            self.set = false;
            Some(mem::replace(&mut self.value, Default::default()))
        } else {
            None
        }
    }
}

impl<T> SingularPtrField<T> {
    #[inline]
    pub fn some(value: T) -> SingularPtrField<T> {
        SingularPtrField {
            value: Some(box value),
            set: true,
        }
    }

    #[inline]
    pub fn none() -> SingularPtrField<T> {
        SingularPtrField {
            value: None,
            set: false,
        }
    }

    #[inline]
    pub fn from_option(option: Option<T>) -> SingularPtrField<T> {
        match option {
            Some(x) => SingularPtrField::some(x),
            None => SingularPtrField::none(),
        }
    }

    #[inline]
    pub fn is_some(&self) -> bool {
        self.set
    }

    #[inline]
    pub fn is_none(&self) -> bool {
        !self.is_some()
    }

    #[inline]
    pub fn into_option(self) -> Option<T> {
        if self.set {
            Some(*self.value.unwrap())
        } else {
            None
        }
    }

    #[inline]
    pub fn as_ref<'a>(&'a self) -> Option<&'a T> {
        if self.set {
            Some(&**self.value.as_ref().unwrap())
        } else {
            None
        }
    }

    #[inline]
    pub fn as_mut<'a>(&'a mut self) -> Option<&'a mut T> {
        if self.set {
            Some(&mut **self.value.as_mut().unwrap())
        } else {
            None
        }
    }

    #[inline]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        self.as_ref().unwrap()
    }

    #[inline]
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
        self.as_mut().unwrap()
    }

    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        // XXX: workaround since returning &[] doesn't seem to work
        let tmp: &[T] = &[];
        match self.as_ref() {
            Some(x) => slice::ref_slice(x),
            None => tmp,
        }
    }

    #[inline]
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        match self.as_mut() {
            //Some(x) => slice::mut_ref_slice(x), // doesn't work I have no idea why
            Some(_) => panic!(),
            None => &mut []
        }
    }

    #[inline]
    pub fn unwrap(self) -> T {
        if self.set {
            *self.value.unwrap()
        } else {
            panic!();
        }
    }

    #[inline]
    pub fn unwrap_or(self, def: T) -> T {
        if self.set {
            *self.value.unwrap()
        } else {
            def
        }
    }

    #[inline]
    pub fn unwrap_or_else(self, f: || -> T) -> T {
        if self.set {
            *self.value.unwrap()
        } else {
            f()
        }
    }

    #[inline]
    pub fn map<U, F>(self, f: F) -> SingularPtrField<U> where F: FnOnce(T) -> U {
        SingularPtrField::from_option(self.into_option().map(f))
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> option::Item<&'a T> {
        self.as_ref().into_iter()
    }

    #[inline]
    pub fn mut_iter<'a>(&'a mut self) -> option::Item<&'a mut T> {
        self.as_mut().into_iter()
    }

    #[inline]
    pub fn take(&mut self) -> Option<T> {
        if self.set {
            self.set = false;
            Some(*self.value.take().unwrap())
        } else {
            None
        }
    }

    #[inline]
    pub fn clear(&mut self) {
        self.set = false;
    }
}

impl<T : Default+Clear> SingularField<T> {
    #[inline]
    pub fn unwrap_or_default(mut self) -> T {
        self.value.clear();
        self.value
    }

    #[inline]
    pub fn set_default<'a>(&'a mut self) -> &'a mut T {
        self.set = true;
        self.value.clear();
        &mut self.value
    }
}

impl<T : Default+Clear> SingularPtrField<T> {
    #[inline]
    pub fn unwrap_or_default(mut self) -> T {
        if self.set {
            self.unwrap()
        } else if self.value.is_some() {
            self.value.clear();
            *self.value.unwrap()
        } else {
            Default::default()
        }
    }

    #[inline]
    pub fn set_default<'a>(&'a mut self) -> &'a mut T {
        self.set = true;
        if self.value.is_some() {
            self.value.as_mut().unwrap().clear();
        } else {
            self.value = Some(box Default::default());
        }
        self.as_mut().unwrap()
    }
}

impl<T : Default> Default for SingularField<T> {
    #[inline]
    fn default() -> SingularField<T> {
        SingularField::none()
    }
}

impl<T> Default for SingularPtrField<T> {
    #[inline]
    fn default() -> SingularPtrField<T> {
        SingularPtrField::none()
    }
}

impl<T : Clone+Default> Clone for SingularField<T> {
    #[inline]
    fn clone(&self) -> SingularField<T> {
        if self.set {
            SingularField::some(self.value.clone())
        } else {
            SingularField::none()
        }
    }
}

impl<T : Clone> Clone for SingularPtrField<T> {
    #[inline]
    fn clone(&self) -> SingularPtrField<T> {
        if self.set {
            SingularPtrField::some(self.as_ref().unwrap().clone())
        } else {
            SingularPtrField::none()
        }
    }
}

impl<T : fmt::Show> fmt::Show for SingularField<T> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.is_some() {
            write!(f, "Some({})", *self.as_ref().unwrap())
        } else {
            write!(f, "None")
        }
    }
}

impl<T : fmt::Show> fmt::Show for SingularPtrField<T> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.is_some() {
            write!(f, "Some({})", *self.as_ref().unwrap())
        } else {
            write!(f, "None")
        }
    }
}

impl<T : PartialEq> PartialEq for SingularField<T> {
    #[inline]
    fn eq(&self, other: &SingularField<T>) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl<T : Eq> Eq for SingularField<T> {}

impl<T : PartialEq> PartialEq for SingularPtrField<T> {
    #[inline]
    fn eq(&self, other: &SingularPtrField<T>) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl<T : Eq> Eq for SingularPtrField<T> {}

#[cfg(test)]
mod test {
    use clear::Clear;
    use super::SingularField;

    #[test]
    fn test_set_default_clears() {
        #[deriving(Default)]
        struct Foo {
            b: int,
        }

        impl Clear for Foo {
            fn clear(&mut self) {
                self.b = 0;
            }
        }

        let mut x = SingularField::some(Foo { b: 10 });
        x.clear();
        x.set_default();
        assert_eq!(0, x.as_ref().unwrap().b);

        x.as_mut().unwrap().b = 11;
        // without clear
        x.set_default();
        assert_eq!(0, x.as_ref().unwrap().b);
    }
}
<commit_msg>Fix compilation<commit_after>use std::slice;
use std::option;
use std::default::Default;
use std::fmt;
use std::mem;

use clear::Clear;

pub struct SingularField<T> {
    value: T,
    set: bool,
}

pub struct SingularPtrField<T> {
    value: Option<Box<T>>,
    set: bool,
}

impl<T> SingularField<T> {
    #[inline]
    pub fn some(value: T) -> SingularField<T> {
        SingularField {
            value: value,
            set: true,
        }
    }

    #[inline]
    pub fn is_some(&self) -> bool {
        self.set
    }

    #[inline]
    pub fn is_none(&self) -> bool {
        !self.is_some()
    }

    #[inline]
    pub fn into_option(self) -> Option<T> {
        if self.set {
            Some(self.value)
        } else {
            None
        }
    }

    #[inline]
    pub fn as_ref<'a>(&'a self) -> Option<&'a T> {
        if self.set {
            Some(&self.value)
        } else {
            None
        }
    }

    #[inline]
    pub fn as_mut<'a>(&'a mut self) -> Option<&'a mut T> {
        if self.set {
            Some(&mut self.value)
        } else {
            None
        }
    }

    #[inline]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        self.as_ref().unwrap()
    }

    #[inline]
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
        self.as_mut().unwrap()
    }

    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        // XXX: workaround since returning &[] doesn't seem to work
        let tmp: &[T] = &[];
        match self.as_ref() {
            Some(x) => slice::ref_slice(x),
            None => tmp,
        }
    }

    #[inline]
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        match self.as_mut() {
            //Some(x) => slice::mut_ref_slice(x), // doesn't work I have no idea why
            Some(_) => panic!(),
            None => &mut []
        }
    }

    #[inline]
    pub fn unwrap(self) -> T {
        if self.set {
            self.value
        } else {
            panic!();
        }
    }

    #[inline]
    pub fn unwrap_or(self, def: T) -> T {
        if self.set {
            self.value
        } else {
            def
        }
    }

    #[inline]
    pub fn unwrap_or_else(self, f: || -> T) -> T {
        if self.set {
            self.value
        } else {
            f()
        }
    }

    #[inline]
    pub fn map<U, F>(self, f: F) -> SingularPtrField<U> where F: FnOnce(T) -> U {
        SingularPtrField::from_option(self.into_option().map(f))
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> option::IntoIter<&'a T> {
        self.as_ref().into_iter()
    }

    #[inline]
    pub fn mut_iter<'a>(&'a mut self) -> option::IntoIter<&'a mut T> {
        self.as_mut().into_iter()
    }

    #[inline]
    pub fn clear(&mut self) {
        self.set = false;
    }
}

impl<T : Default> SingularField<T> {
    #[inline]
    pub fn none() -> SingularField<T> {
        SingularField {
            value: Default::default(),
            set: false,
        }
    }

    #[inline]
    pub fn from_option(option: Option<T>) -> SingularField<T> {
        match option {
            Some(x) => SingularField::some(x),
            None => SingularField::none(),
        }
    }

    #[inline]
    pub fn take(&mut self) -> Option<T> {
        if self.set {
            self.set = false;
            Some(mem::replace(&mut self.value, Default::default()))
        } else {
            None
        }
    }
}

impl<T> SingularPtrField<T> {
    #[inline]
    pub fn some(value: T) -> SingularPtrField<T> {
        SingularPtrField {
            value: Some(box value),
            set: true,
        }
    }

    #[inline]
    pub fn none() -> SingularPtrField<T> {
        SingularPtrField {
            value: None,
            set: false,
        }
    }

    #[inline]
    pub fn from_option(option: Option<T>) -> SingularPtrField<T> {
        match option {
            Some(x) => SingularPtrField::some(x),
            None => SingularPtrField::none(),
        }
    }

    #[inline]
    pub fn is_some(&self) -> bool {
        self.set
    }

    #[inline]
    pub fn is_none(&self) -> bool {
        !self.is_some()
    }

    #[inline]
    pub fn into_option(self) -> Option<T> {
        if self.set {
            Some(*self.value.unwrap())
        } else {
            None
        }
    }

    #[inline]
    pub fn as_ref<'a>(&'a self) -> Option<&'a T> {
        if self.set {
            Some(&**self.value.as_ref().unwrap())
        } else {
            None
        }
    }

    #[inline]
    pub fn as_mut<'a>(&'a mut self) -> Option<&'a mut T> {
        if self.set {
            Some(&mut **self.value.as_mut().unwrap())
        } else {
            None
        }
    }

    #[inline]
    pub fn get_ref<'a>(&'a self) -> &'a T {
        self.as_ref().unwrap()
    }

    #[inline]
    pub fn get_mut_ref<'a>(&'a mut self) -> &'a mut T {
        self.as_mut().unwrap()
    }

    #[inline]
    pub fn as_slice<'a>(&'a self) -> &'a [T] {
        // XXX: workaround since returning &[] doesn't seem to work
        let tmp: &[T] = &[];
        match self.as_ref() {
            Some(x) => slice::ref_slice(x),
            None => tmp,
        }
    }

    #[inline]
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        match self.as_mut() {
            //Some(x) => slice::mut_ref_slice(x), // doesn't work I have no idea why
            Some(_) => panic!(),
            None => &mut []
        }
    }

    #[inline]
    pub fn unwrap(self) -> T {
        if self.set {
            *self.value.unwrap()
        } else {
            panic!();
        }
    }

    #[inline]
    pub fn unwrap_or(self, def: T) -> T {
        if self.set {
            *self.value.unwrap()
        } else {
            def
        }
    }

    #[inline]
    pub fn unwrap_or_else(self, f: || -> T) -> T {
        if self.set {
            *self.value.unwrap()
        } else {
            f()
        }
    }

    #[inline]
    pub fn map<U, F>(self, f: F) -> SingularPtrField<U> where F: FnOnce(T) -> U {
        SingularPtrField::from_option(self.into_option().map(f))
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> option::IntoIter<&'a T> {
        self.as_ref().into_iter()
    }

    #[inline]
    pub fn mut_iter<'a>(&'a mut self) -> option::IntoIter<&'a mut T> {
        self.as_mut().into_iter()
    }

    #[inline]
    pub fn take(&mut self) -> Option<T> {
        if self.set {
            self.set = false;
            Some(*self.value.take().unwrap())
        } else {
            None
        }
    }

    #[inline]
    pub fn clear(&mut self) {
        self.set = false;
    }
}

impl<T : Default+Clear> SingularField<T> {
    #[inline]
    pub fn unwrap_or_default(mut self) -> T {
        self.value.clear();
        self.value
    }

    #[inline]
    pub fn set_default<'a>(&'a mut self) -> &'a mut T {
        self.set = true;
        self.value.clear();
        &mut self.value
    }
}

impl<T : Default+Clear> SingularPtrField<T> {
    #[inline]
    pub fn unwrap_or_default(mut self) -> T {
        if self.set {
            self.unwrap()
        } else if self.value.is_some() {
            self.value.clear();
            *self.value.unwrap()
        } else {
            Default::default()
        }
    }

    #[inline]
    pub fn set_default<'a>(&'a mut self) -> &'a mut T {
        self.set = true;
        if self.value.is_some() {
            self.value.as_mut().unwrap().clear();
        } else {
            self.value = Some(box Default::default());
        }
        self.as_mut().unwrap()
    }
}

impl<T : Default> Default for SingularField<T> {
    #[inline]
    fn default() -> SingularField<T> {
        SingularField::none()
    }
}

impl<T> Default for SingularPtrField<T> {
    #[inline]
    fn default() -> SingularPtrField<T> {
        SingularPtrField::none()
    }
}

impl<T : Clone+Default> Clone for SingularField<T> {
    #[inline]
    fn clone(&self) -> SingularField<T> {
        if self.set {
            SingularField::some(self.value.clone())
        } else {
            SingularField::none()
        }
    }
}

impl<T : Clone> Clone for SingularPtrField<T> {
    #[inline]
    fn clone(&self) -> SingularPtrField<T> {
        if self.set {
            SingularPtrField::some(self.as_ref().unwrap().clone())
        } else {
            SingularPtrField::none()
        }
    }
}

impl<T : fmt::Show> fmt::Show for SingularField<T> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.is_some() {
            write!(f, "Some({})", *self.as_ref().unwrap())
        } else {
            write!(f, "None")
        }
    }
}

impl<T : fmt::Show> fmt::Show for SingularPtrField<T> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.is_some() {
            write!(f, "Some({})", *self.as_ref().unwrap())
        } else {
            write!(f, "None")
        }
    }
}

impl<T : PartialEq> PartialEq for SingularField<T> {
    #[inline]
    fn eq(&self, other: &SingularField<T>) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl<T : Eq> Eq for SingularField<T> {}

impl<T : PartialEq> PartialEq for SingularPtrField<T> {
    #[inline]
    fn eq(&self, other: &SingularPtrField<T>) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl<T : Eq> Eq for SingularPtrField<T> {}

#[cfg(test)]
mod test {
    use clear::Clear;
    use super::SingularField;

    #[test]
    fn test_set_default_clears() {
        #[deriving(Default)]
        struct Foo {
            b: int,
        }

        impl Clear for Foo {
            fn clear(&mut self) {
                self.b = 0;
            }
        }

        let mut x = SingularField::some(Foo { b: 10 });
        x.clear();
        x.set_default();
        assert_eq!(0, x.as_ref().unwrap().b);

        x.as_mut().unwrap().b = 11;
        // without clear
        x.set_default();
        assert_eq!(0, x.as_ref().unwrap().b);
    }
}
<|endoftext|>


<commit_before>iface iterable<A> {
    fn iter(blk: fn(A));
}

impl<A> of iterable<A> for fn@(fn(A)) {
    fn iter(blk: fn(A)) {
        self(blk);
    }
}

// accomodate the fact that int/uint are passed by value by default:
impl of iterable<int> for fn@(fn(int)) {
    fn iter(blk: fn(&&int)) {
        self {|i| blk(i)}
    }
}

impl of iterable<uint> for fn@(fn(uint)) {
    fn iter(blk: fn(&&uint)) {
        self {|i| blk(i)}
    }
}

impl<A> of iterable<A> for [A] {
    fn iter(blk: fn(A)) {
        vec::iter(self, blk)
    }
}

impl<A> of iterable<A> for option<A> {
    fn iter(blk: fn(A)) {
        option::may(self, blk)
    }
}

fn enumerate<A,IA:iterable<A>>(self: IA, blk: fn(uint, A)) {
    let i = 0u;
    self.iter {|a|
        blk(i, a);
        i += 1u;
    }
}

// Here: we have to use fn@ for predicates and map functions, because
// we will be binding them up into a closure.  Disappointing.  A true
// region type system might be able to do better than this.

fn filter<A,IA:iterable<A>>(self: IA, prd: fn@(A) -> bool, blk: fn(A)) {
    self.iter {|a|
        if prd(a) { blk(a) }
    }
}

fn map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> B, blk: fn(B)) {
    self.iter {|a|
        let b = cnv(a);
        blk(b);
    }
}

fn flat_map<A,B,IA:iterable<A>,IB:iterable<B>>(
    self: IA, cnv: fn@(A) -> IB, blk: fn(B)) {
    self.iter {|a|
        cnv(a).iter(blk)
    }
}

fn foldl<A,B,IA:iterable<A>>(self: IA, +b0: B, blk: fn(-B, A) -> B) -> B {
    let b <- b0;
    self.iter {|a|
        b = blk(b, a);
    }
    ret b;
}

fn foldr<A:copy,B,IA:iterable<A>>(
    self: IA, +b0: B, blk: fn(A, -B) -> B) -> B {

    let b <- b0;
    reverse(self) {|a|
        b = blk(a, b);
    }
    ret b;
}

fn to_list<A:copy,IA:iterable<A>>(self: IA) -> [A] {
    foldl::<A,[A],IA>(self, [], {|r, a| r + [a]})
}

// FIXME: This could be made more efficient with an riterable interface
fn reverse<A:copy,IA:iterable<A>>(self: IA, blk: fn(A)) {
    vec::riter(to_list(self), blk)
}

fn count<A,IA:iterable<A>>(self: IA, x: A) -> uint {
    foldl(self, 0u) {|count, value|
        if value == x {
            count + 1u
        } else {
            count
        }
    }
}

fn repeat(times: uint, blk: fn()) {
    let i = 0u;
    while i < times {
        blk();
        i += 1u;
    }
}

fn min<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ < b {
            // FIXME: Not sure if this is successfully optimized to a move
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "min called on empty iterator" }
    }
}

fn max<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ > b {
            // FIXME: Not sure if this is successfully optimized to a move
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "max called on empty iterator" }
    }
}

#[test]
fn test_enumerate() {
    enumerate(["0", "1", "2"]) {|i,j|
        assert #fmt["%u",i] == j;
    }
}

#[test]
fn test_map_and_to_list() {
    let a = bind vec::iter([0, 1, 2], _);
    let b = bind map(a, {|i| i*2}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_map_directly_on_vec() {
    let b = bind map([0, 1, 2], {|i| i*2}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_filter_on_int_range() {
    fn is_even(&&i: int) -> bool {
        ret (i % 2) == 0;
    }

    let l = to_list(bind filter(bind int::range(0, 10, _), is_even, _));
    assert l == [0, 2, 4, 6, 8];
}

#[test]
fn test_filter_on_uint_range() {
    fn is_even(&&i: uint) -> bool {
        ret (i % 2u) == 0u;
    }

    let l = to_list(bind filter(bind uint::range(0u, 10u, _), is_even, _));
    assert l == [0u, 2u, 4u, 6u, 8u];
}

#[test]
fn test_flat_map_with_option() {
    fn if_even(&&i: int) -> option<int> {
        if (i % 2) == 0 { some(i) }
        else { none }
    }

    let a = bind vec::iter([0, 1, 2], _);
    let b = bind flat_map(a, if_even, _);
    let c = to_list(b);
    assert c == [0, 2];
}

#[test]
fn test_flat_map_with_list() {
    fn repeat(&&i: int) -> [int] {
        let r = [];
        int::range(0, i) {|_j| r += [i]; }
        r
    }

    let a = bind vec::iter([0, 1, 2, 3], _);
    let b = bind flat_map(a, repeat, _);
    let c = to_list(b);
    #debug["c = %?", c];
    assert c == [1, 2, 2, 3, 3, 3];
}

#[test]
fn test_repeat() {
    let c = [],
        i = 0u;
    repeat(5u) {||
        c += [(i * i)];
        i += 1u;
    };
    #debug["c = %?", c];
    assert c == [0u, 1u, 4u, 9u, 16u];
}

#[test]
fn test_min() {
    assert min([5, 4, 1, 2, 3]) == 1;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_min_empty() {
    min::<int, [int]>([]);
}

#[test]
fn test_max() {
    assert max([1, 2, 4, 2, 3]) == 4;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_max_empty() {
    max::<int, [int]>([]);
}

#[test]
fn test_reverse() {
    assert to_list(bind reverse([1, 2, 3], _)) == [3, 2, 1];
}

#[test]
fn test_count() {
    assert count([1, 2, 1, 2, 1], 1) == 3u;
}

#[test]
fn test_foldr() {
    fn sub(&&a: int, -b: int) -> int {
        a - b
    }
    let sum = foldr([1, 2, 3, 4], 0, sub);
    assert sum == -2;
}<commit_msg>core: Rename iter::reverse to iter::reversed for consistency with vec mod<commit_after>iface iterable<A> {
    fn iter(blk: fn(A));
}

impl<A> of iterable<A> for fn@(fn(A)) {
    fn iter(blk: fn(A)) {
        self(blk);
    }
}

// accomodate the fact that int/uint are passed by value by default:
impl of iterable<int> for fn@(fn(int)) {
    fn iter(blk: fn(&&int)) {
        self {|i| blk(i)}
    }
}

impl of iterable<uint> for fn@(fn(uint)) {
    fn iter(blk: fn(&&uint)) {
        self {|i| blk(i)}
    }
}

impl<A> of iterable<A> for [A] {
    fn iter(blk: fn(A)) {
        vec::iter(self, blk)
    }
}

impl<A> of iterable<A> for option<A> {
    fn iter(blk: fn(A)) {
        option::may(self, blk)
    }
}

fn enumerate<A,IA:iterable<A>>(self: IA, blk: fn(uint, A)) {
    let i = 0u;
    self.iter {|a|
        blk(i, a);
        i += 1u;
    }
}

// Here: we have to use fn@ for predicates and map functions, because
// we will be binding them up into a closure.  Disappointing.  A true
// region type system might be able to do better than this.

fn filter<A,IA:iterable<A>>(self: IA, prd: fn@(A) -> bool, blk: fn(A)) {
    self.iter {|a|
        if prd(a) { blk(a) }
    }
}

fn map<A,B,IA:iterable<A>>(self: IA, cnv: fn@(A) -> B, blk: fn(B)) {
    self.iter {|a|
        let b = cnv(a);
        blk(b);
    }
}

fn flat_map<A,B,IA:iterable<A>,IB:iterable<B>>(
    self: IA, cnv: fn@(A) -> IB, blk: fn(B)) {
    self.iter {|a|
        cnv(a).iter(blk)
    }
}

fn foldl<A,B,IA:iterable<A>>(self: IA, +b0: B, blk: fn(-B, A) -> B) -> B {
    let b <- b0;
    self.iter {|a|
        b = blk(b, a);
    }
    ret b;
}

fn foldr<A:copy,B,IA:iterable<A>>(
    self: IA, +b0: B, blk: fn(A, -B) -> B) -> B {

    let b <- b0;
    reversed(self) {|a|
        b = blk(a, b);
    }
    ret b;
}

fn to_list<A:copy,IA:iterable<A>>(self: IA) -> [A] {
    foldl::<A,[A],IA>(self, [], {|r, a| r + [a]})
}

// FIXME: This could be made more efficient with an riterable interface
fn reversed<A:copy,IA:iterable<A>>(self: IA, blk: fn(A)) {
    vec::riter(to_list(self), blk)
}

fn count<A,IA:iterable<A>>(self: IA, x: A) -> uint {
    foldl(self, 0u) {|count, value|
        if value == x {
            count + 1u
        } else {
            count
        }
    }
}

fn repeat(times: uint, blk: fn()) {
    let i = 0u;
    while i < times {
        blk();
        i += 1u;
    }
}

fn min<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ < b {
            // FIXME: Not sure if this is successfully optimized to a move
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "min called on empty iterator" }
    }
}

fn max<A:copy,IA:iterable<A>>(self: IA) -> A {
    alt foldl::<A,option<A>,IA>(self, none) {|a, b|
        alt a {
          some(a_) if a_ > b {
            // FIXME: Not sure if this is successfully optimized to a move
            a
          }
          _ { some(b) }
        }
    } {
        some(val) { val }
        none { fail "max called on empty iterator" }
    }
}

#[test]
fn test_enumerate() {
    enumerate(["0", "1", "2"]) {|i,j|
        assert #fmt["%u",i] == j;
    }
}

#[test]
fn test_map_and_to_list() {
    let a = bind vec::iter([0, 1, 2], _);
    let b = bind map(a, {|i| i*2}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_map_directly_on_vec() {
    let b = bind map([0, 1, 2], {|i| i*2}, _);
    let c = to_list(b);
    assert c == [0, 2, 4];
}

#[test]
fn test_filter_on_int_range() {
    fn is_even(&&i: int) -> bool {
        ret (i % 2) == 0;
    }

    let l = to_list(bind filter(bind int::range(0, 10, _), is_even, _));
    assert l == [0, 2, 4, 6, 8];
}

#[test]
fn test_filter_on_uint_range() {
    fn is_even(&&i: uint) -> bool {
        ret (i % 2u) == 0u;
    }

    let l = to_list(bind filter(bind uint::range(0u, 10u, _), is_even, _));
    assert l == [0u, 2u, 4u, 6u, 8u];
}

#[test]
fn test_flat_map_with_option() {
    fn if_even(&&i: int) -> option<int> {
        if (i % 2) == 0 { some(i) }
        else { none }
    }

    let a = bind vec::iter([0, 1, 2], _);
    let b = bind flat_map(a, if_even, _);
    let c = to_list(b);
    assert c == [0, 2];
}

#[test]
fn test_flat_map_with_list() {
    fn repeat(&&i: int) -> [int] {
        let r = [];
        int::range(0, i) {|_j| r += [i]; }
        r
    }

    let a = bind vec::iter([0, 1, 2, 3], _);
    let b = bind flat_map(a, repeat, _);
    let c = to_list(b);
    #debug["c = %?", c];
    assert c == [1, 2, 2, 3, 3, 3];
}

#[test]
fn test_repeat() {
    let c = [],
        i = 0u;
    repeat(5u) {||
        c += [(i * i)];
        i += 1u;
    };
    #debug["c = %?", c];
    assert c == [0u, 1u, 4u, 9u, 16u];
}

#[test]
fn test_min() {
    assert min([5, 4, 1, 2, 3]) == 1;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_min_empty() {
    min::<int, [int]>([]);
}

#[test]
fn test_max() {
    assert max([1, 2, 4, 2, 3]) == 4;
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_max_empty() {
    max::<int, [int]>([]);
}

#[test]
fn test_reversed() {
    assert to_list(bind reversed([1, 2, 3], _)) == [3, 2, 1];
}

#[test]
fn test_count() {
    assert count([1, 2, 1, 2, 1], 1) == 3u;
}

#[test]
fn test_foldr() {
    fn sub(&&a: int, -b: int) -> int {
        a - b
    }
    let sum = foldr([1, 2, 3, 4], 0, sub);
    assert sum == -2;
}<|endoftext|>


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

use std::ops::{DerefMut, Deref};
use std::result::Result;
use handle_table::{Handle};
use ::io::{AsyncRead, AsyncWrite, try_read_internal, write_internal,
           FdObserver, HasHandle, register_new_handle,
           Error};
use {Promise};
use private::{with_current_event_loop};

pub struct Stream {
    stream: ::mio::tcp::TcpStream,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Stream
}

pub struct Listener {
    listener: ::mio::tcp::TcpListener,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Listener
}

impl Drop for Listener {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Listener {
    pub fn bind(addr: ::std::net::SocketAddr) -> Result<Listener, ::std::io::Error> {
        let listener = try!(::mio::tcp::TcpListener::bind(&addr));
        let handle = FdObserver::new();

        with_current_event_loop(move |event_loop| {
            try!(event_loop.event_port.borrow_mut().reactor.register(&listener, ::mio::Token(handle.val),
                                                                     ::mio::EventSet::readable(),
                                                                     ::mio::PollOpt::edge()));
            Ok(Listener { listener: listener, handle: handle, no_send: ::std::marker::PhantomData })
        })
    }

    fn accept_internal(self) -> Result<Promise<(Listener, Stream), Error<Listener>>, Error<Listener>> {
        let accept_result = match self.listener.accept() {
            Err(e) => return Err(Error::new(self, e)),
            Ok(v) => v,
        };
        match accept_result {
            Some((stream, _)) => {
                let handle = match register_new_handle(&stream) {
                    Err(e) => return Err(Error::new(self, e)),
                    Ok(v) => v,
                };
                Ok(Promise::fulfilled((self, Stream::new(stream, handle))))
            }
            None => {
                with_current_event_loop(move |event_loop| {
                    let promise =
                        event_loop.event_port.borrow_mut().handler.observers[self.handle].when_becomes_readable();
                    Ok(promise.then_else(move |r| match r {
                        Ok(()) => self.accept_internal(),
                        Err(e) => Err(Error::new(self, e))
                    }))
                })
            }
        }
    }

    pub fn accept(self) -> Promise<(Listener, Stream), Error<Listener>> {
        Promise::fulfilled(()).then(move |()| self.accept_internal())
    }
}

impl ::mio::TryRead for Stream {
    fn try_read(&mut self, buf: &mut [u8]) -> ::std::io::Result<Option<usize>> {
        use mio::TryRead;
        self.stream.try_read(buf)
    }
}

impl ::mio::TryWrite for Stream {
    fn try_write(&mut self, buf: &[u8]) -> ::std::io::Result<Option<usize>> {
        use mio::TryWrite;
        self.stream.try_write(buf)
    }
}

impl HasHandle for Stream {
    fn get_handle(&self) -> Handle { self.handle }
}

impl Drop for Stream {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Stream {
    fn new(stream: ::mio::tcp::TcpStream, handle: Handle) -> Stream {
        Stream { stream: stream, handle: handle, no_send: ::std::marker::PhantomData }
    }

    pub fn connect(addr: ::std::net::SocketAddr) -> Promise<Stream, ::std::io::Error> {
        Promise::fulfilled(()).then(move |()| {
            let stream = try!(::mio::tcp::TcpStream::connect(&addr));

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let handle = try!(register_new_handle(&stream));

            with_current_event_loop(move |event_loop| {
                let promise =
                    event_loop.event_port.borrow_mut().handler.observers[handle].when_becomes_writable();
                Ok(promise.map(move |()| {
                    // TODO how to test for error?
                    //try!(stream.take_socket_error());
                    Ok(Stream::new(stream, handle))
                }))
            })
        })
    }

    pub fn try_clone(&self) -> Result<Stream, ::std::io::Error> {
        let stream = try!(self.stream.try_clone());
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }

    #[cfg(unix)]
    pub unsafe fn from_raw_fd(fd: ::std::os::unix::io::RawFd) -> Result<Stream, ::std::io::Error> {
        let stream = ::std::os::unix::io::FromRawFd::from_raw_fd(fd);
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }
}

impl AsyncRead for Stream {
    fn try_read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: DerefMut<Target=[u8]>
    {
        Promise::fulfilled(()).then(move |()| {
            try_read_internal(self, buf, 0, min_bytes)
        })
    }
}

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

use std::ops::{DerefMut, Deref};
use std::result::Result;
use handle_table::{Handle};
use ::io::{AsyncRead, AsyncWrite, try_read_internal, write_internal,
           FdObserver, HasHandle, register_new_handle,
           Error};
use {Promise};
use private::{with_current_event_loop};

pub struct Stream {
    stream: ::mio::tcp::TcpStream,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Stream
}

pub struct Listener {
    listener: ::mio::tcp::TcpListener,
    handle: Handle,
    no_send: ::std::marker::PhantomData<*mut ()>, // impl !Send for Listener
}

impl Drop for Listener {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Listener {
    pub fn bind(addr: ::std::net::SocketAddr) -> Result<Listener, ::std::io::Error> {
        let listener = try!(::mio::tcp::TcpListener::bind(&addr));
        let handle = FdObserver::new();

        with_current_event_loop(move |event_loop| {
            try!(event_loop.event_port.borrow_mut().reactor.register(&listener, ::mio::Token(handle.val),
                                                                     ::mio::EventSet::readable(),
                                                                     ::mio::PollOpt::edge()));
            Ok(Listener { listener: listener, handle: handle, no_send: ::std::marker::PhantomData })
        })
    }

    fn accept_internal(self) -> Result<Promise<(Listener, Stream), Error<Listener>>, Error<Listener>> {
        let accept_result = match self.listener.accept() {
            Err(e) => return Err(Error::new(self, e)),
            Ok(v) => v,
        };
        match accept_result {
            Some((stream, _)) => {
                let handle = match register_new_handle(&stream) {
                    Err(e) => return Err(Error::new(self, e)),
                    Ok(v) => v,
                };
                Ok(Promise::fulfilled((self, Stream::new(stream, handle))))
            }
            None => {
                with_current_event_loop(move |event_loop| {
                    let promise =
                        event_loop.event_port.borrow_mut().handler.observers[self.handle].when_becomes_readable();
                    Ok(promise.then_else(move |r| match r {
                        Ok(()) => self.accept_internal(),
                        Err(e) => Err(Error::new(self, e))
                    }))
                })
            }
        }
    }

    pub fn accept(self) -> Promise<(Listener, Stream), Error<Listener>> {
        Promise::fulfilled(()).then(move |()| self.accept_internal())
    }
}

impl ::mio::TryRead for Stream {
    fn try_read(&mut self, buf: &mut [u8]) -> ::std::io::Result<Option<usize>> {
        use mio::TryRead;
        self.stream.try_read(buf)
    }
}

impl ::mio::TryWrite for Stream {
    fn try_write(&mut self, buf: &[u8]) -> ::std::io::Result<Option<usize>> {
        use mio::TryWrite;
        self.stream.try_write(buf)
    }
}

impl HasHandle for Stream {
    fn get_handle(&self) -> Handle { self.handle }
}

impl Drop for Stream {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
        })
    }
}

impl Stream {
    fn new(stream: ::mio::tcp::TcpStream, handle: Handle) -> Stream {
        Stream { stream: stream, handle: handle, no_send: ::std::marker::PhantomData }
    }

    pub fn connect(addr: ::std::net::SocketAddr) -> Promise<Stream, ::std::io::Error> {
        Promise::fulfilled(()).then(move |()| {
            let stream = try!(::mio::tcp::TcpStream::connect(&addr));

            // TODO: if we're not already connected, maybe only register writable interest,
            // and then reregister with read/write interested once we successfully connect.

            let handle = try!(register_new_handle(&stream));

            with_current_event_loop(move |event_loop| {
                let promise =
                    event_loop.event_port.borrow_mut().handler.observers[handle].when_becomes_writable();
                Ok(promise.map(move |()| {
                    try!(stream.take_socket_error());
                    Ok(Stream::new(stream, handle))
                }))
            })
        })
    }

    pub fn try_clone(&self) -> Result<Stream, ::std::io::Error> {
        let stream = try!(self.stream.try_clone());
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }

    #[cfg(unix)]
    pub unsafe fn from_raw_fd(fd: ::std::os::unix::io::RawFd) -> Result<Stream, ::std::io::Error> {
        let stream = ::std::os::unix::io::FromRawFd::from_raw_fd(fd);
        let handle = try!(register_new_handle(&stream));
        Ok(Stream::new(stream, handle))
    }
}

impl AsyncRead for Stream {
    fn try_read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize), Error<(Self, T)>>
        where T: DerefMut<Target=[u8]>
    {
        Promise::fulfilled(()).then(move |()| {
            try_read_internal(self, buf, 0, min_bytes)
        })
    }
}

impl AsyncWrite for Stream {
    fn write<T>(self, buf: T) -> Promise<(Self, T), Error<(Self, T)>> where T: Deref<Target=[u8]> {
        Promise::fulfilled(()).then(move |()| {
            write_internal(self, buf, 0)
        })
    }
}
<|endoftext|>


<commit_before>// based on define_flags by lexs
#[macro_escape];

macro_rules! define_flags (
    (
        $name:ident {
            $($flag:ident = $value:expr),+
        }
    ) => {
        define_flags!($name: u32 { $($flag = $value),+ })
    };

    (
        $name:ident: $T:ty {
            $($flag:ident $(= $v:expr)*),*
        }
    ) => {
        #[packed]
        pub struct $name($T);

        impl $name {
            /// Return the value.
            pub fn get(self) -> $T {
                match self { $name(x) => x }
            }

            /// Maps by applying a function to a contained value.
            pub fn map(self, f: |$T| -> $T) -> $name {
                match self { $name(x) => $name(f(x)) }
            }

            pub fn zero() -> $name {
                $name(0)
            }
        }

        impl core::ops::BitOr<$name, $name> for $name {
            #[inline(always)]
            fn bitor(&self, other: &$name) -> $name {
                match (self, other) {
                    (&$name(flags1), &$name(flags2)) => $name(flags1 | flags2)
                }
            }
        }

        impl core::ops::BitAnd<$name, bool> for $name {
            #[inline(always)]
            fn bitand(&self, other: &$name) -> bool {
                match (self, other) {
                    (&$name(flags1), &$name(flags2)) => flags1 & flags2 != 0
                }
            }
        }

        impl core::ops::Not<$name> for $name {
            #[inline(always)]
            fn not(&self) -> $name {
                match self {
                    &$name(flags) => $name(!flags)
                }
            }
        }

        define_flags_rec!($name, 1, $( $flag $(= $v)* ),+)
    };
)
macro_rules! define_flags_rec (
    // full list (original behavior)
    (
        $name:ident,
        $default:expr,
        $($flag:ident = $value:expr),*
    ) => (
        $( pub static $flag: $name = $name($value); )+
    );
    // ----------
    // only one default value
    (
        $name:ident,
        $default:expr,
        $flag:ident
    ) => (
        pub static $flag: $name = $name($default);
    );
    // only one value
    (
        $name:ident,
        $default:expr,
        $flag:ident = $value:expr
    ) => (
        pub static $flag: $name = $name($value);
    );
    // ----------
    // without value (default)
    (
        $name:ident,
        $default:expr,
        $flag:ident,
        $($f:ident $(= $v:expr)*),*
    ) => (
        pub static $flag: $name = $name($default);
        define_flags_rec!($name, $default << 1, $($f $(= $v)*),+)
    );
    // with value
    (
        $name:ident,
        $default:expr,
        $flag:ident = $value:expr,
        $($f:ident $(= $v:expr)*),*
    ) => (
        pub static $flag: $name = $name($value);
        define_flags_rec!($name, $value << 1, $( $f $(= $v)* ),+)
    );
)
<commit_msg>Update macros<commit_after>// based on define_flags by lexs
#[macro_escape];

macro_rules! define_flags (
    (
        $name:ident {
            $($flag:ident = $value:expr),+
        }
    ) => {
        define_flags!($name: uint { $($flag = $value),+ })
    };

    (
        $name:ident: $T:ty {
            $($flag:ident $(= $v:expr)*),*
        }
    ) => {
        #[allow(dead_code)]
        pub struct $name($T);

        #[allow(dead_code)]
        impl $name {
            /// Return the value.
            pub fn get(self) -> $T {
                match self { $name(x) => x }
            }

            /// Maps by applying a function to a contained value.
            pub fn map(self, f: |$T| -> $T) -> $name {
                match self { $name(x) => $name(f(x)) }
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_zero(&self) -> bool {
                match *self {
                    $name(0) => true,
                    _ => false
                }
            }

            pub fn zero() -> $name {
                $name(0)
            }
        }

        impl_ops!($name, $name)

        impl core::ops::Not<$name> for $name {
            #[inline(always)]
            fn not(&self) -> $name {
                match self {
                    &$name(flags) => $name(!flags)
                }
            }
        }

        define_flags_rec!($name, 1, $( $flag $(= $v)* ),+)
    };
)
macro_rules! define_flags_rec (
    // full list (original behavior)
    (
        $name:ident,
        $default:expr,
        $($flag:ident = $value:expr),*
    ) => (
        $( #[allow(dead_code)] pub static $flag: $name = $name($value); )+
    );
    // ----------
    // only one default value
    (
        $name:ident,
        $default:expr,
        $flag:ident
    ) => (
        #[allow(dead_code)]
        pub static $flag: $name = $name($default);
    );
    // only one value
    (
        $name:ident,
        $default:expr,
        $flag:ident = $value:expr
    ) => (
        #[allow(dead_code)]
        pub static $flag: $name = $name($value);
    );
    // ----------
    // without value (default)
    (
        $name:ident,
        $default:expr,
        $flag:ident,
        $($f:ident $(= $v:expr)*),*
    ) => (
        #[allow(dead_code)]
        pub static $flag: $name = $name($default);
        define_flags_rec!($name, $default << 1, $($f $(= $v)*),+)
    );
    // with value
    (
        $name:ident,
        $default:expr,
        $flag:ident = $value:expr,
        $($f:ident $(= $v:expr)*),*
    ) => (
        #[allow(dead_code)]
        pub static $flag: $name = $name($value);
        define_flags_rec!($name, $value << 1, $( $f $(= $v)* ),+)
    );
)

macro_rules! define_reg (
    (
        $Reg:ident, $flags:ident: $T:ty {
            $($flag:ident $(= $v:expr)*),*
        }
    ) => (
        define_flags!($flags: $T { $( $flag $(= $v)* ),* })

        pub struct $Reg;

        impl_ops!($Reg, $flags, $flags, $Reg::read(), $flags)
    )
)

macro_rules! impl_ops (
    ($T:ident, $RHS:ident) => (
        impl_ops!($T, $RHS, $T, *self, $T)
    );

    ($LHS:ident, $RHS:ident, $T:ident, $e:expr, $X:ident) => (
        impl core::ops::BitOr<$RHS, $T> for $LHS {
            #[inline(always)]
            fn bitor(&self, other: &$RHS) -> $T {
                match ($e, other) {
                    ($X(p), &$RHS(f)) => $T(p | f)
                }
            }
        }

        impl core::ops::BitAnd<$RHS, $T> for $LHS {
            #[inline(always)]
            fn bitand(&self, other: &$RHS) -> $T {
                match ($e, other) {
                    ($X(p), &$RHS(f)) => $T(p & f)
                }
            }
        }

        impl core::ops::Sub<$RHS, $T> for $LHS {
            #[inline(always)]
            fn sub(&self, other: &$RHS) -> $T {
                match ($e, other) {
                    ($X(flags1), &$RHS(flags2)) => $T(flags1 & !flags2)
                }
            }
        }
    )
)
<|endoftext|>


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

use cpuio;

static mut SCHUTDOWN_PORT: cpuio::Port<u8> = unsafe { cpuio::Port::new(0xf4) };

pub fn halt() {
	loop {
		unsafe {
			asm!("hlt" :::: "volatile");
		}
	}
}

pub fn shutdown() {
	// shutdown, works only on Qemu
	unsafe {
		SCHUTDOWN_PORT.write(0x00);
	};

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

use cpuio;

pub fn halt() {
	loop {
		unsafe {
			asm!("hlt" :::: "volatile");
		}
	}
}

pub fn shutdown() {
	// shutdown, works only on Qemu
	unsafe {
		let mut shutdown_port : cpuio::Port<u8> = cpuio::Port::new(0xf4);
		shutdown_port.write(0x00);
	};

	halt();
}
<|endoftext|>


<commit_before>#[macro_use] extern crate clap;

// `name` and `long` have the same lifetime
fn named_usize_arg<'n, 'h, 'g, 'p, 'r>(name: &'n str, help: &'h str) -> clap::Arg<'n, 'n, 'h, 'g, 'p, 'r> {
    // we don't own `name` but we now own `error_message`
    // which contains `name`.
    let error_message = format!(
        "value provided for argument `{}` is not a valid unsigned integer number",
        name);
    clap::Arg::with_name(name)
         .long(name)
         .help(help)
         // `move` makes it such that the  closure owns `error_message`
         .validator(move |val| {
             match val.parse::<usize>() {
                 Ok(_) => Ok(()),
                 // the closure owns `error_message`.
                 // we can't move `error_message` out of the closure.
                 // we have to clone it instead.
                 Err(_) => Err(error_message.clone())
             }
         })
         .takes_value(true)
}

fn main() {
    let default_nhidden: usize = 10;
    let help_nhidden = format!("number of hidden (latent) variables to find (defaults to `{}`)", default_nhidden);

    let help_input_image_path = "path to image on the the grayscale amounts in the columns of which the NMF should be applied";

    let matches =
        clap::App::new("image-columns-nmf")
            .version(&crate_version!()[..])
            .about("applies NMF on the grayscale amounts of the columns of an image")
            .arg(clap::Arg::with_name("input-image-path")
                 .index(1)
                 .help(&help_input_image_path)
                 .required(true))
            .arg(named_usize_arg("nhidden", &help_nhidden))
            .get_matches();

    let nhidden: usize = value_t!(matches.value_of("nhidden"), usize).unwrap_or(default_nhidden);
    let input_image_path = matches.value_of("input-image-path").unwrap();

    println!("nhidden = {}", nhidden);
    println!("input_image_path = {}", input_image_path);
}
<commit_msg>image-columns-nmf: split path into parts<commit_after>use std::path::Path;

#[macro_use] extern crate clap;

extern crate onmf;

// `name` and `long` have the same lifetime
fn named_usize_arg<'n, 'h, 'g, 'p, 'r>(name: &'n str, help: &'h str) -> clap::Arg<'n, 'n, 'h, 'g, 'p, 'r> {
    // we don't own `name` but we now own `error_message`
    // which contains `name`.
    let error_message = format!(
        "value provided for argument `{}` is not a valid unsigned integer number",
        name);
    clap::Arg::with_name(name)
         .long(name)
         .help(help)
         // `move` makes it such that the  closure owns `error_message`
         .validator(move |val| {
             match val.parse::<usize>() {
                 Ok(_) => Ok(()),
                 // the closure owns `error_message`.
                 // we can't move `error_message` out of the closure.
                 // we have to clone it instead.
                 Err(_) => Err(error_message.clone())
             }
         })
         .takes_value(true)
}

fn main() {
    let default_nhidden: usize = 10;
    let help_nhidden = format!("number of hidden (latent) variables to find (defaults to `{}`)", default_nhidden);

    let help_input_image_path = "path to image on the the grayscale amounts in the columns of which the NMF should be applied";

    let matches =
        clap::App::new("image-columns-nmf")
            .version(&crate_version!()[..])
            .about("applies NMF on the grayscale amounts of the columns of an image")
            .arg(clap::Arg::with_name("input-image-path")
                 .index(1)
                 .help(&help_input_image_path)
                 .required(true))
            .arg(named_usize_arg("nhidden", &help_nhidden))
            .get_matches();

    let nhidden: usize = value_t!(matches.value_of("nhidden"), usize).unwrap_or(default_nhidden);
    let input_image_path_string = matches.value_of("input-image-path").unwrap();
    let input_image_path = Path::new(input_image_path_string);

    println!("nhidden = {}", nhidden);
    println!("input_image_path = {:?}", input_image_path);
    println!("input_image_path.parent() = {:?}", input_image_path.parent());
    println!("input_image_path.file_name() = {:?}", input_image_path.file_name());
    println!("input_image_path.file_stem() = {:?}", input_image_path.file_stem());
    println!("input_image_path.extension() = {:?}", input_image_path.extension());

    // TODO make it possible to switch orthogonalization on and off

    // TODO open file

    // TODO error if file doesnt exist
    //
    // TODO read the file into an array you can pass into nmf

    // TODO
    // let mut ortho_nmf = onmf::OrthogonalNMFBlas::new_random01(
    //     nhidden, nobserved, nsamples);

    // TODO iterate nmf
}
<|endoftext|>


<commit_before>extern crate time;
extern crate toml;
extern crate docopt;

use std::process::*;
use std::fs;
use std::path::Path;
use std::io::{Read, Write};

use docopt::Docopt;

mod config;

const USAGE: &'static str = "
Usage:
    compare_tool [options] <config_file> <profile>
    compare_tool [--help]
    compare_tool [--version]

Options:
    -m, --with_mem        Also profile memory
    -i, --iterations=<n>  Number of iterations for measuring runtime.
        --help            This screen
        --version         Version of this tool
";

const VERSION: &'static str = "v0.1";

fn main() {
    let arguments = Docopt::new(USAGE)
        .and_then(|d| {
            d.help(true)
             .version(Some(VERSION.into()))
             .parse()
        })
        .unwrap_or_else(|e| e.exit());

    let arg = arguments.get_str("<config_file>");
    let profile_name = arguments.get_str("<profile>");

    let mut config = load_config(&arg);
    if config.profiles.get(profile_name).is_none()
    {
        let ps = config.profiles
            .iter()
            .map(|s| "- ".to_owned() + &s.0 + "\n")
            .collect::<Vec<_>>();
        let ps = ps.concat();
        panic!("need to be given one of the following profiles:\n{}", ps);
    };

    {
        let profile = config.profiles.get_mut(profile_name).unwrap();
        if arguments.get_bool("--with_mem") {
            profile.with_mem = true;
        }
    }
    let profile = &config.profiles[profile_name];

    let inputs = profile.inputs.iter().map(|input| {
        let input_expanded = bash_expand(&input);
        let input_size = fs::metadata(&input_expanded)
            .ok()
            .expect(&format!("input file '{}' does not exist", input_expanded))
            .len();
        InputData {
            unexpanded: input.clone(),
            expanded: input_expanded,
            size: input_size,
        }
    }).collect::<Vec<_>>();

    let commands: Vec<_> = profile.commands.iter().map(
        |&(ref cmd, ref cargs, ref ending)|{
            CommandData {
                unexpanded_visible: cmd.clone(),
                unexpanded_hidden: cargs.clone(),
                output_extension: ending.clone(),
            }
        }
    ).collect();

    let headers = inputs.iter().map(|x| x.unexpanded.len());
    let rows = commands.iter().map(|x| x.unexpanded_visible.len());

    let padding = headers.chain(rows).max().unwrap_or(0);
    let padding = (padding,);

    let run_row = |kind: &str, label: &str, command: &CommandData, input: &InputData| {
        let output = &(
            file_name(&input.expanded).to_owned()
            + "."
            + &command.output_extension
        );

        bash_run(&format!("rm {}", output));

        fn build_cmd(valgrind: bool, output: &str, command: &CommandData) -> String {
            let measure_pages = false;
            let max_detail = true;

            let measure_pages_opt = if measure_pages {
                " --pages-as-heap=yes "
            } else {
                ""
            };

            let max_details_opt = if max_detail {
                " --detailed-freq=1 "
            } else {
                ""
            };

            let valgrind_cmd = if valgrind {
                format!("valgrind -q --tool=massif --massif-out-file={} {}{}",
                        output,
                        measure_pages_opt,
                        max_details_opt)
            } else {
                "".into()
            };

            format!("{}{} {}",
                    valgrind_cmd,
                    command.unexpanded_visible,
                    command.unexpanded_hidden)
        }

        let output_massif = &(output.to_string() + ".massif");

        let script = &bash_in_out_script(&input.expanded,
                                         output,
                                         &build_cmd(profile.with_mem,
                                                    output_massif,
                                                    command));

        let time_start = time::precise_time_ns();
        let out = bash_run(script);

        let cmd_out: &str = &String::from_utf8_lossy(&out.stdout);
        let cmd_err: &str = &String::from_utf8_lossy(&out.stderr);

        let time_end = time::precise_time_ns();

        let time_span = ((time_end - time_start) as f64)
            / 1000.0
            / 1000.0
            / 1000.0;
        let inp_size = &nice_size(input.size);

        if out.status.success() {
            let out_size = fs::metadata(output).unwrap().len();
            let comp_size = &nice_size(out_size);
            let ratio = (out_size as f64) / (input.size as f64) * 100.0;

            let mem_peak = if profile.with_mem {
                use std::fs::File;
                use std::io::BufReader;
                use std::io::BufRead;

                let report_file = File::open(output_massif).unwrap();
                let report_file = BufReader::new(report_file);

                let peak = report_file.lines().filter_map(|line| {
                    let line = line.unwrap();
                    let p = "mem_heap_B=";
                    if line.starts_with(p) {
                        Some(line[p.len()..].to_owned())
                    } else {
                        None
                    }
                })
                .map(|size| size.parse::<u64>().unwrap())
                .max().unwrap();

                let peak = nice_size(peak);
                Some(peak)
            } else {
                None
            };
            let mem_peak = mem_peak.as_ref().map(|s| &**s);

            print_line(
                (kind, label, time_span, inp_size, comp_size, ratio, mem_peak),
                padding
            );
            if !cmd_out.is_empty() {
                print_sep(padding);
                print!("{}", cmd_out);
                print_sep(padding);
            }
        } else {
            print_line(
                ("ERR", label, time_span, inp_size, "", 0.0/0.0, None),
                padding
            );
            let a = !cmd_out.is_empty();
            let b = !cmd_err.is_empty();
            if a {
                print_sep(padding);
                print!("{}", cmd_out);
            }
            if a || b {
                print_sep(padding);
            }
            if b {
                print!("{}", cmd_err);
                print_sep(padding);
            }
        }
    };

    println!("");
    println!("Profile: {}", profile_name);
    println!("");

    if profile.compare_commands {
        for input in &inputs {
            print_header("file", &input.unexpanded, padding);
            print_sep(padding);
            for command in &commands {
                run_row("cmd", &command.unexpanded_visible, &command, &input);
            }
            print_sep(padding);
        }
    } else {
        for command in &commands {
            print_header("cmd", &command.unexpanded_visible, padding);
            print_sep(padding);
            for input in &inputs {
                run_row("file", &input.unexpanded, &command, &input);
            }
            print_sep(padding);
        }
    }

}

fn nice_size(size: u64) -> String {
    if size >= 1024 * 1024 {
        format!("{:6.2} MiB", (size as f64) / 1024.0 / 1024.0)
    } else if size >= 1024 {
        format!("{:6.2} KiB", (size as f64) / 1024.0)
    } else {
        format!("{:6.2} B  ", (size as f64))
    }
}

fn load_config(arg: &str) -> config::Config {
    let mut toml = String::new();
    fs::File::open(&arg)
        .ok()
        .expect("config file not found")
        .read_to_string(&mut toml)
        .unwrap();
    let toml = toml::Parser::new(&toml)
        .parse()
        .expect("config file not in valid TOML format");

    config::parse_config(toml)
        .ok()
        .expect("Invalid config file")
}

// type, value, time, size, compsize, compratio
type Line<'a> = (&'a str, &'a str, f64, &'a str, &'a str, f64, Option<&'a str>);
type LinePad = (usize,);

fn print_header(kind: &str, value: &str, padding: LinePad) {
    println!("{:4} | {:7$} | {:^9} | {:^12} | {:^12} | {:^8} | {:^12}",
        kind, value, "time", "size", "comp. size", "ratio", "mem", padding.0);
}

fn print_line(line: Line, padding: LinePad) {
    let mem = line.6.unwrap_or("-");
    println!("{:4} | {:7$} | {:7.3} s | {:>12} | {:>12} | {:6.2} % | {:^12}",
        line.0, line.1, line.2, line.3, line.4, line.5, mem, padding.0);
}

fn print_sep(padding: LinePad) {
    println!("{:-^4}---{:-^7$}---{:-^7}-----{:-^12}---{:-^12}---{:-^6}---{:-^12}--",
        "", "", "", "", "", "", "", padding.0);
}

// let mem_cmd = r##"valgrind --tool=massif --pages-as-heap=yes --massif-out-file=${mofile} ${cmd}; grep mem_heap_B ${mofile} | sed -e 's/mem_heap_B=\(.*\)/\1/' | sort -g | tail -n 1"##;

/// Run the argument as a bash script
fn bash_run(command_line: &str) -> Output {
    let mut cmd = Command::new("sh");
    cmd.stdin(Stdio::piped());
    cmd.stdout(Stdio::piped());
    cmd.stderr(Stdio::piped());
    let mut handles = cmd.spawn().unwrap();

    let mut stdin = handles.stdin.take().unwrap();
    stdin.write_all(command_line.as_bytes()).unwrap();
    drop(stdin);

    handles.wait_with_output().unwrap()
}

/// Expand the argument through bash, substituting environment variables.
fn bash_expand(s: &str) -> String {
    let out = bash_run(&format!("echo {}", s));
    assert!(out.status.success());
    String::from_utf8(out.stdout).unwrap().trim().to_owned()
}

fn _alphabet_size(file: &str) -> usize {
    let mut bytes = [0u64; 256];
    let file = fs::File::open(file).unwrap();
    for b in file.bytes() {
        bytes[b.unwrap() as usize] += 1;
    }
    let mut counter = 0;
    for &count in &bytes[..] {
        if count > 0 {
            counter += 1;
        }
    }
    counter
}

/// Data that describes a single input file
struct InputData {
    unexpanded: String,
    expanded: String,
    size: u64,
}

/// Data that describes a single command
struct CommandData {
    unexpanded_visible: String,
    unexpanded_hidden: String,
    output_extension: String,
}

fn bash_in_out_script(input: &str, output: &str, command: &str) -> String {
    format!("IN={}
             OUT={}
             {}", input, output, command)
}

fn file_name(file: &str) -> &str {
    Path::new(file).file_name().unwrap().to_str().unwrap()
}
<commit_msg>Added support for actually running more than one iteration in the compare_tool<commit_after>extern crate time;
extern crate toml;
extern crate docopt;

use std::process::*;
use std::fs;
use std::path::Path;
use std::io::{Read, Write};

use docopt::Docopt;

mod config;

const USAGE: &'static str = "
Usage:
    compare_tool [options] <config_file> <profile>
    compare_tool [--help]
    compare_tool [--version]

Options:
    -m, --with_mem        Also profile memory
    -i, --iterations=<n>  Number of iterations for measuring runtime.
        --help            This screen
        --version         Version of this tool
";

const VERSION: &'static str = "v0.1";

fn main() {
    let arguments = Docopt::new(USAGE)
        .and_then(|d| {
            d.help(true)
             .version(Some(VERSION.into()))
             .parse()
        })
        .unwrap_or_else(|e| e.exit());

    let arg = arguments.get_str("<config_file>");
    let profile_name = arguments.get_str("<profile>");

    let mut config = load_config(&arg);
    if config.profiles.get(profile_name).is_none()
    {
        let ps = config.profiles
            .iter()
            .map(|s| "- ".to_owned() + &s.0 + "\n")
            .collect::<Vec<_>>();
        let ps = ps.concat();
        panic!("need to be given one of the following profiles:\n{}", ps);
    };

    {
        let profile = config.profiles.get_mut(profile_name).unwrap();
        if arguments.get_bool("--with_mem") {
            profile.with_mem = true;
        }
        if let Some(s) = arguments.find("--iterations") {
            profile.runtime_iterations
                = Some(s.as_str()
                        .parse()
                        .expect("iterations needs to be an integer"));
        }
    }

    let profile = &config.profiles[profile_name];

    let inputs = profile.inputs.iter().map(|input| {
        let input_expanded = bash_expand(&input);
        let input_size = fs::metadata(&input_expanded)
            .ok()
            .expect(&format!("input file '{}' does not exist", input_expanded))
            .len();
        InputData {
            unexpanded: input.clone(),
            expanded: input_expanded,
            size: input_size,
        }
    }).collect::<Vec<_>>();

    let commands: Vec<_> = profile.commands.iter().map(
        |&(ref cmd, ref cargs, ref ending)|{
            CommandData {
                unexpanded_visible: cmd.clone(),
                unexpanded_hidden: cargs.clone(),
                output_extension: ending.clone(),
            }
        }
    ).collect();

    let headers = inputs.iter().map(|x| x.unexpanded.len());
    let rows = commands.iter().map(|x| x.unexpanded_visible.len());

    let padding = headers.chain(rows).max().unwrap_or(0);
    let padding = (padding,);

    let run_row = |kind: &str, label: &str, command: &CommandData, input: &InputData| {
        let output = &(
            file_name(&input.expanded).to_owned()
            + "."
            + &command.output_extension
        );

        fn build_cmd(valgrind: bool, output: &str, command: &CommandData) -> String {
            let measure_pages = false;
            let max_detail = true;

            let measure_pages_opt = if measure_pages {
                " --pages-as-heap=yes "
            } else {
                ""
            };

            let max_details_opt = if max_detail {
                " --detailed-freq=1 "
            } else {
                ""
            };

            let valgrind_cmd = if valgrind {
                format!("valgrind -q --tool=massif --massif-out-file={} {}{}",
                        output,
                        measure_pages_opt,
                        max_details_opt)
            } else {
                "".into()
            };

            format!("{}{} {}",
                    valgrind_cmd,
                    command.unexpanded_visible,
                    command.unexpanded_hidden)
        }

        let mut iter_count = profile.runtime_iterations.unwrap_or(1);
        let do_mem = profile.with_mem;
        if do_mem {
            iter_count += 1;
        }
        let mut with_mem = false;

        let mut runtimes = vec![];
        for iter_i in 0..iter_count {
            let is_last_iter = iter_i == iter_count - 1;

            if do_mem && is_last_iter {
                with_mem = true;
            }

            bash_run(&format!("rm {}", output));

            let output_massif = &(output.to_string() + ".massif");

            let script = &bash_in_out_script(&input.expanded,
                                            output,
                                            &build_cmd(with_mem,
                                                        output_massif,
                                                        command));

            let time_start = time::precise_time_ns();
            let out = bash_run(script);

            let cmd_out: &str = &String::from_utf8_lossy(&out.stdout);
            let cmd_err: &str = &String::from_utf8_lossy(&out.stderr);

            let time_end = time::precise_time_ns();

            let mut time_span = ((time_end - time_start) as f64)
                / 1000.0
                / 1000.0
                / 1000.0;
            runtimes.push(time_span);

            if is_last_iter {
                if do_mem {
                    runtimes.pop();
                    time_span = -runtimes.iter().fold(0.0, |a, &b| a + b)
                        / (iter_count - 1) as f64;
                } else {
                    time_span = -runtimes.iter().fold(0.0, |a, &b| a + b)
                        / iter_count as f64;
                }
            }

            let inp_size = &nice_size(input.size);

            if out.status.success() {
                let out_size = fs::metadata(output).unwrap().len();
                let comp_size = &nice_size(out_size);
                let ratio = (out_size as f64) / (input.size as f64) * 100.0;

                let mem_peak = if with_mem {
                    use std::fs::File;
                    use std::io::BufReader;
                    use std::io::BufRead;

                    let report_file = File::open(output_massif).unwrap();
                    let report_file = BufReader::new(report_file);

                    let peak = report_file.lines().filter_map(|line| {
                        let line = line.unwrap();
                        let p = "mem_heap_B=";
                        if line.starts_with(p) {
                            Some(line[p.len()..].to_owned())
                        } else {
                            None
                        }
                    })
                    .map(|size| size.parse::<u64>().unwrap())
                    .max().unwrap();

                    let peak = nice_size(peak);
                    Some(peak)
                } else {
                    None
                };
                let mem_peak = mem_peak.as_ref().map(|s| &**s);

                let label = &if iter_i == iter_count - 1 {
                    format!("{}", label)
                } else {
                    format!("  {} {}", iter_i, label)
                };

                print_line(
                    (kind, label, time_span, inp_size, comp_size, ratio, mem_peak),
                    padding
                );
                if !cmd_out.is_empty() {
                    print_sep(padding);
                    print!("{}", cmd_out);
                    print_sep(padding);
                }
            } else {
                print_line(
                    ("ERR", label, time_span, inp_size, "", 0.0/0.0, None),
                    padding
                );
                let a = !cmd_out.is_empty();
                let b = !cmd_err.is_empty();
                if a {
                    print_sep(padding);
                    print!("{}", cmd_out);
                }
                if a || b {
                    print_sep(padding);
                }
                if b {
                    print!("{}", cmd_err);
                    print_sep(padding);
                }
            }

            with_mem = false;
        }
    };

    println!("");
    println!("Profile: {}", profile_name);
    println!("");

    if profile.compare_commands {
        for input in &inputs {
            print_header("file", &input.unexpanded, padding);
            print_sep(padding);
            for command in &commands {
                run_row("cmd", &command.unexpanded_visible, &command, &input);
            }
            print_sep(padding);
        }
    } else {
        for command in &commands {
            print_header("cmd", &command.unexpanded_visible, padding);
            print_sep(padding);
            for input in &inputs {
                run_row("file", &input.unexpanded, &command, &input);
            }
            print_sep(padding);
        }
    }

}

fn nice_size(size: u64) -> String {
    if size >= 1024 * 1024 {
        format!("{:6.2} MiB", (size as f64) / 1024.0 / 1024.0)
    } else if size >= 1024 {
        format!("{:6.2} KiB", (size as f64) / 1024.0)
    } else {
        format!("{:6.2} B  ", (size as f64))
    }
}

fn load_config(arg: &str) -> config::Config {
    let mut toml = String::new();
    fs::File::open(&arg)
        .ok()
        .expect("config file not found")
        .read_to_string(&mut toml)
        .unwrap();
    let toml = toml::Parser::new(&toml)
        .parse()
        .expect("config file not in valid TOML format");

    config::parse_config(toml)
        .ok()
        .expect("Invalid config file")
}

// type, value, time, size, compsize, compratio
type Line<'a> = (&'a str, &'a str, f64, &'a str, &'a str, f64, Option<&'a str>);
type LinePad = (usize,);

fn print_header(kind: &str, value: &str, padding: LinePad) {
    println!("{:4} | {:7$} | {:^9} | {:^12} | {:^12} | {:^8} | {:^12}",
        kind, value, "time", "size", "comp. size", "ratio", "mem", padding.0);
}

fn print_line(line: Line, padding: LinePad) {
    let mem = line.6.unwrap_or("-");
    if line.2 >= 0.0 {
        println!("{:4} | {:7$} | {:7.3} s | {:>12} | {:>12} | {:6.2} % | {:^12}",
            line.0, line.1, line.2, line.3, line.4, line.5, mem, padding.0);
    } else {
        println!("{:4} | {:7$} |~{:7.3} s | {:>12} | {:>12} | {:6.2} % | {:^12}",
            line.0, line.1, -line.2, line.3, line.4, line.5, mem, padding.0);
    }
}

fn print_sep(padding: LinePad) {
    println!("{:-^4}---{:-^7$}---{:-^7}-----{:-^12}---{:-^12}---{:-^6}---{:-^12}--",
        "", "", "", "", "", "", "", padding.0);
}

// let mem_cmd = r##"valgrind --tool=massif --pages-as-heap=yes --massif-out-file=${mofile} ${cmd}; grep mem_heap_B ${mofile} | sed -e 's/mem_heap_B=\(.*\)/\1/' | sort -g | tail -n 1"##;

/// Run the argument as a bash script
fn bash_run(command_line: &str) -> Output {
    let mut cmd = Command::new("sh");
    cmd.stdin(Stdio::piped());
    cmd.stdout(Stdio::piped());
    cmd.stderr(Stdio::piped());
    let mut handles = cmd.spawn().unwrap();

    let mut stdin = handles.stdin.take().unwrap();
    stdin.write_all(command_line.as_bytes()).unwrap();
    drop(stdin);

    handles.wait_with_output().unwrap()
}

/// Expand the argument through bash, substituting environment variables.
fn bash_expand(s: &str) -> String {
    let out = bash_run(&format!("echo {}", s));
    assert!(out.status.success());
    String::from_utf8(out.stdout).unwrap().trim().to_owned()
}

fn _alphabet_size(file: &str) -> usize {
    let mut bytes = [0u64; 256];
    let file = fs::File::open(file).unwrap();
    for b in file.bytes() {
        bytes[b.unwrap() as usize] += 1;
    }
    let mut counter = 0;
    for &count in &bytes[..] {
        if count > 0 {
            counter += 1;
        }
    }
    counter
}

/// Data that describes a single input file
struct InputData {
    unexpanded: String,
    expanded: String,
    size: u64,
}

/// Data that describes a single command
struct CommandData {
    unexpanded_visible: String,
    unexpanded_hidden: String,
    output_extension: String,
}

fn bash_in_out_script(input: &str, output: &str, command: &str) -> String {
    format!("IN={}
             OUT={}
             {}", input, output, command)
}

fn file_name(file: &str) -> &str {
    Path::new(file).file_name().unwrap().to_str().unwrap()
}
<|endoftext|>


<commit_before>//! An SSL implementation of Hamelin.
#![cfg_attr(feature = "openssl", feature(env, io, old_io))]
extern crate hamelin;
#[cfg(feature = "openssl")] extern crate openssl;

#[cfg(feature = "openssl")] use std::env::args;
#[cfg(feature = "openssl")] use std::old_io::{Acceptor, BufferedStream, Listener, TcpListener};
#[cfg(feature = "openssl")] use std::sync::Arc;
#[cfg(feature = "openssl")] use std::thread::spawn;
#[cfg(feature = "openssl")] use hamelin::Hamelin;
#[cfg(feature = "openssl")] use openssl::ssl::{SslContext, SslMethod, SslStream};

#[cfg(feature = "openssl")]
fn main() {
    let args: Vec<_> = args().skip(1).collect();
    if args.len() < 3 {
        println!("Usage: hamelin host port command [args]");
        return;
    }
    let hamelin = Arc::new(Hamelin::new(&args[2], if args.len() > 3 {
        Some(&args[3..])
    } else {
        None
    }));
    let listener = TcpListener::bind(&format!("{}:{}", args[0], args[1])[..]);
    let mut acceptor = listener.listen();
    for stream in acceptor.incoming() {
        let ctx = SslContext::new(SslMethod::Sslv23).unwrap();
        let mut stream = stream.unwrap();
        stream.set_timeout(Some(1));
        let stream = SslStream::new_server(&ctx, stream).unwrap();
        let hamelin = hamelin.clone();
        spawn(move || {
            let mut stream = BufferedStream::new(stream);
            let mut guard = hamelin.spawn().unwrap();
            loop {
                if let Ok(line) = guard.read_line() {
                    let _ = stream.write_line(&line);
                    let _ = stream.flush();
                }
                if let Ok(line) = stream.read_line() {
                    let _ = guard.write_line(&line);
                }
            }
        });
    }
}

#[cfg(not(feature = "openssl"))]
fn main() {
    println!("SSL daemon must be compiled with OpenSSL.");
}
<commit_msg>Removed SSL implementation since it uses neither mio nor std::net.<commit_after><|endoftext|>


<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    try!(l[0].atom()).i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string());
    Ok(Element::Net(Net { name:name, num:num }))
}

/* busy
fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&'static str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string());
    let desc = try!(l[1].string());
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    for x in &l[2..] {
        let xn = &try!(x.list_name())[..];
        match xn {
            "add_net" =>
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
        }
    }
}*/

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(parse_other(e)), // TODO
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>parse net and net_class<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    try!(l[0].atom()).i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string());
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string());
    let desc = try!(l[1].string());
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()))
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>