<commit_before>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : Debug+Hash+PartialEq+Eq+Clone {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Box<Self::List>) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Box<Self::List>) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    // ** Want/need to express a negative product here among Nil, Cons and Name!
    fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res ;

    // Derived from `elim` above:
    fn is_empty (self:&Self, st:&mut A, list:&Self::List) -> bool {
        self.elim(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

#[allow(dead_code)]
fn list_merge<A:Adapton,X:Ord+Clone,L:ListT<A,X>>
    (st:&mut A, l:&L,
     n1:Option<&A::Name>, l1:&L::List,
     n2:Option<&A::Name>, l2:&L::List  ) -> L::List
{
    l.elim(st, l1,
           |_| l2.clone(),
           |st,h1,t1| {
               l.elim(st, l2,
                      |st| L::nil(st),
                      |st, h2, t2| {
                          if h1 <= h2 {
                              let rest = list_merge(st, l, None, t1, n2, l2);
                              L::cons(st, (*h1).clone(), Box::new(rest))
                          }
                          else {
                              let rest = list_merge(st, l, n1, l1, None, t2);
                              L::cons(st, (*h2).clone(), Box::new(rest))
                          }
                      },
                      |st, m2, t2| list_merge(st, l, n1, l1, Some(m2), t2)
                      )},
           |st,n1,t1| list_merge(st, l, Some(n1), t1, n2, l2)
           )
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : Debug+Hash+PartialEq+Eq+Clone {
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Self::Tree, Self::Tree) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::Tree, Self::Tree) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Arg,Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+Debug+Hash+PartialEq+Eq+Clone,Hd:Debug+Hash+PartialEq+Eq+Clone> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                                  -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Box<Self::List>)       -> Self::List { List::Cons(hd,tl) }
    fn name (_:&mut A, nm:A::Name, tl:Box<Self::List>)  -> Self::List { List::Name(nm, tl) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)               -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>)      -> Self::List { List::Art(art) }

    fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Box<Self::List>) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Box<Self::List>) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, tl),
            List::Name(ref nm, ref tl) => namef(st, nm, tl),
            List::Rc(ref rc) => self.elim(st, &*rc, nilf, consf, namef),
            List::Art(ref art) => {
                let list = st.force(art);
                self.elim(st, &list, nilf, consf, namef)
            }
        }
    }
}

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

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

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager,
                      prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (l, list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, l, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (l, list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    l.elim (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), left_tree.clone(), right_tree ) ;
                tree_of_list_rec::<A,X,T,L> ( st, l, &rest, &tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations (not Boxes), named by name.
                let tree = T::name( st, nm.clone(), left_tree.clone(), right_tree ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, l, &rest, &tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (l:&L, st:&mut A, list:&L::List) -> T::Tree
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, l, list, &nil, 0 as u32, u32::max_value()) ;
    assert!( l.is_empty( st, &rest ) );
    tree
}
<commit_msg>elim2 shows that elim doesnt need a &Self<commit_after>use std::fmt::Debug;
use std::hash::Hash;
use std::rc::Rc;
use std::mem::replace;

use adapton_syntax::* ;
use adapton_sigs::* ;

pub trait ListT<A:Adapton,Hd> : Debug+Hash+PartialEq+Eq+Clone {
    type List : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::List ;
    fn cons (&mut A, Hd, Self::List) -> Self::List ;
    fn rc   (&mut A, Rc<Self::List>) -> Self::List ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::List) -> Self::List ;
    fn art  (&mut A, Art<Self::List,A::Loc>) -> Self::List ;

    // ** Want/need to express a negative product here among Nil, Cons and Name!
    // fn elim<Res,Nil,Cons,Name> (self:&Self, &mut A, &Self::List, Nil, Cons, Name) -> Res
    //     where Nil:FnOnce(&mut A) -> Res
    //     ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
    //     ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res ;

    // Derived from `cons` and `nil` above:
    fn singleton (st:&mut A, hd:Hd) -> Self::List {
        let nil = Self::nil(st);
        Self::cons(st, hd, nil)
    }

    fn elim2<Res,Nil,Cons,Name> (&mut A, &Self::List, Nil, Cons, Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res ;

    // Derived from `elim` above:
    fn is_empty (self:&Self, st:&mut A, list:&Self::List) -> bool {
        Self::elim2(st, &list, |_|true, |_,_,_|false, |_,_,_|false)
    }
}

#[allow(dead_code)]
fn list_merge<A:Adapton,X:Ord+Clone,L:ListT<A,X>>
    (st:&mut A, l:&L,
     xo:Option<&X>, // xo is useful for merging binary trees.
     n1:Option<&A::Name>, l1:&L::List,
     n2:Option<&A::Name>, l2:&L::List  ) -> L::List
{
    L::elim2(st, l1,
            |_| l2.clone(),
            |st,h1,t1|
            L::elim2(st, l2,
                    |st| L::nil(st),
                    |st, h2, t2|
                    if match xo {
                        None => false,
                        Some(x) => ( x <= h1 && x <= h2 ) }
                    {
                        let rest = list_merge(st, l, None, n1, l1, n2, l2);
                        L::cons(st, xo.unwrap().clone(), rest)
                    }
                    else if h1 <= h2 {
                        //TODO: Nominal memoization with n1:
                        let rest = list_merge(st, l, xo, None, t1, n2, l2);
                        L::cons(st, (*h1).clone(), rest)
                    }
                    else {
                        //TODO: Nominal memoization with n2:
                        let rest = list_merge(st, l, xo, n1, l1, None, t2);
                        L::cons(st, (*h2).clone(), rest)
                    },
                    |st, m2, t2| list_merge(st, l, xo, n1, l1, Some(m2), t2)
                    ),
            |st,n1,t1| list_merge(st, l, xo, Some(n1), t1, n2, l2)
            )
}

fn list_merge_sort<A:Adapton,X:Ord+Hash+Clone,L:ListT<A,X>,T:TreeT<A,X,X>>
    (st:&mut A, l:&L, list:&L::List) -> L::List
{
    let tree = tree_of_list::<A,X,T,L>(st, l, list);
    T::fold_up (st, tree,
                |st, x|
                L::singleton(st, x),

                |st, x, left, right|
                list_merge(st, l, Some(&x), None, &left, None, &right)
                )
}

// Questions:
//  - Should `Name`s always be passed by reference?
//  - Do these Fn argss for fold need to be passed in `Rc<Box<_>>`s ?

pub trait TreeT<A:Adapton,Leaf,Bin:Hash> : Debug+Hash+PartialEq+Eq+Clone {
    type Tree : Debug+Hash+PartialEq+Eq+Clone ;

    fn nil  (&mut A) -> Self::Tree ;
    fn leaf (&mut A, Leaf) -> Self::Tree ;
    fn bin  (&mut A, Bin, Self::Tree, Self::Tree) -> Self::Tree ;

    // requisite "adaptonic" constructors: `name` and `art`:
    fn name (&mut A, A::Name, Self::Tree, Self::Tree) -> Self::Tree ;
    fn art  (&mut A, Art<Self::Tree,A::Loc>) -> Self::Tree ;

    fn fold<Res,LeafC,BinC> (&mut A, Self::Tree, Res, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Res, Leaf) -> Res
        ,      BinC:Fn(&mut A, Res, Bin ) -> Res ;

    fn fold_up<Res,LeafC,BinC> (&mut A, Self::Tree, LeafC, BinC) -> Res
        where LeafC:Fn(&mut A, Leaf) -> Res
        ,      BinC:Fn(&mut A, Bin, Res, Res ) -> Res ;

    // TODO: Add derived operations (max, min, sum, etc.) for fold_up.
}

#[derive(Debug,PartialEq,Eq,Hash,Clone)]
enum List<A:Adapton,Hd> {
    Nil,
    Cons(Hd,      Box<List<A,Hd>>),
    Rc(           Rc<List<A,Hd>>),
    Name(A::Name, Box<List<A,Hd>>),
    Art(          Art<List<A,Hd>, A::Loc>),
}

// TODO: Why Does Adapton have to implement all of these?
//       It's not actually *contained* within the List structure; it cannot be ecountered there.
//       It's only ever present in a negative position (as a function parameter).
impl<A:Adapton+Debug+Hash+PartialEq+Eq+Clone,Hd:Debug+Hash+PartialEq+Eq+Clone> ListT<A,Hd> for List<A,Hd> {
    type List = List<A,Hd>;

    fn nil  (_:&mut A)                             -> Self::List { List::Nil }
    fn cons (_:&mut A, hd:Hd, tl:Self::List)       -> Self::List { List::Cons(hd,Box::new(tl)) }
    fn name (_:&mut A, nm:A::Name, tl:Self::List)  -> Self::List { List::Name(nm, Box::new(tl)) }
    fn rc   (_:&mut A, rc:Rc<List<A,Hd>>)          -> Self::List { List::Rc(rc) }
    fn art  (_:&mut A, art:Art<List<A,Hd>,A::Loc>) -> Self::List { List::Art(art) }

    // fn elim<Res,Nil,Cons,Name> (self:&Self, st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
    //     where Nil:FnOnce(&mut A) -> Res
    //     ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
    //     ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res
    // {
    //     match *list {
    //         List::Nil => nilf(st),
    //         List::Cons(ref hd, ref tl) => consf(st, hd, &*tl),
    //         List::Name(ref nm, ref tl) => namef(st, nm, &*tl),
    //         List::Rc(ref rc) => self.elim(st, &*rc, nilf, consf, namef),
    //         List::Art(ref art) => {
    //             let list = st.force(art);
    //             self.elim(st, &list, nilf, consf, namef)
    //         }
    //     }
    // }

    fn elim2<Res,Nil,Cons,Name> (st:&mut A, list:&Self::List, nilf:Nil, consf:Cons, namef:Name) -> Res
        where Nil:FnOnce(&mut A) -> Res
        ,    Cons:FnOnce(&mut A, &Hd, &Self::List) -> Res
        ,    Name:FnOnce(&mut A, &A::Name, &Self::List) -> Res
    {
        match *list {
            List::Nil => nilf(st),
            List::Cons(ref hd, ref tl) => consf(st, hd, &*tl),
            List::Name(ref nm, ref tl) => namef(st, nm, &*tl),
            List::Rc(ref rc) => Self::elim2(st, &*rc, nilf, consf, namef),
            List::Art(ref art) => {
                let list = st.force(art);
                Self::elim2(st, &list, nilf, consf, namef)
            }
        }
    }

}

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

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

fn tree_of_list_rec_memo <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32) ->
    (T::Tree, L::List)
{
    let t = st.thunk (ArtId::Eager,
                      prog_pt!(tree_of_list_rec),
                      Rc::new(Box::new(|st, args|{
                          let (l, list, left_tree, left_tree_lev, parent_lev) = args ;
                          tree_of_list_rec::<A,X,T,L>
                              (st, l, list, left_tree, left_tree_lev, parent_lev)
                      })),
                      (l, list, left_tree, left_tree_lev, parent_lev)
                      ) ;
    st.force( &t )
}

fn tree_of_list_rec <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List, left_tree:&T::Tree, left_tree_lev:u32, parent_lev:u32)
     -> (T::Tree, L::List)
{
    L::elim2 (
        st, &list,
        /* Nil */  |st| ( T::nil(st), L::nil(st) ),
        /* Cons */ |st, hd, rest| {
            let lev_hd = (1 + (my_hash(hd).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_hd && lev_hd <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_hd ) ;
                let tree = T::bin ( st, hd.clone(), left_tree.clone(), right_tree ) ;
                tree_of_list_rec::<A,X,T,L> ( st, l, &rest, &tree, lev_hd, parent_lev )
            }
            else {
                let rest = L::cons(st, hd.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }},
        /* Name */ |st, nm, rest| {
            let lev_nm = (1 + 64 + (my_hash(nm).leading_zeros())) as u32 ;
            if left_tree_lev <= lev_nm && lev_nm <= parent_lev {
                let nil = T::nil(st) ;
                let (right_tree, rest) = tree_of_list_rec_memo::<A,X,T,L> ( st, l, rest, &nil, 0 as u32, lev_nm ) ;
                // TODO: Place left_ and right_ trees into articulations (not Boxes), named by name.
                let tree = T::name( st, nm.clone(), left_tree.clone(), right_tree ) ;
                tree_of_list_rec_memo::<A,X,T,L> ( st, l, &rest, &tree, lev_nm, parent_lev )
            }
            else {
                let rest = L::name(st, nm.clone(), rest.clone()) ;
                (left_tree.clone(), rest)
            }}
        )
}

pub fn tree_of_list <A:Adapton, X:Hash+Clone, T:TreeT<A,X,X>, L:ListT<A,X>>
    (st:&mut A, l:&L, list:&L::List) -> T::Tree
{
    let nil = T::nil(st) ;
    let (tree, rest) = tree_of_list_rec::<A,X,T,L> (st, l, list, &nil, 0 as u32, u32::max_value()) ;
    assert!( l.is_empty( st, &rest ) );
    tree
}
<|endoftext|>


<commit_before>use slack_hook::{Attachment, AttachmentBuilder, Field, PayloadBuilder, Slack, SlackText, SlackLink};
use slack_hook::SlackTextContent::{Text, Link};

use taste::{BenchmarkResult, TastingResult};

pub struct SlackNotifier {
    conn: Slack,
    channel: String,
    github_repo: String,
}

impl SlackNotifier {
    pub fn new(hook_url: &str, channel: &str, repo_url: &str) -> SlackNotifier {
        SlackNotifier {
            conn: Slack::new(hook_url).unwrap(),
            channel: String::from(channel),
            github_repo: String::from(repo_url),
        }
    }

    pub fn notify(&self, res: &TastingResult) -> Result<(), String> {
        let payload = PayloadBuilder::new()
            .text(vec![Text("I've tasted commit _".into()),
                       Text(format!("\"{}\"_ -- ", res.commit_msg.lines().next().unwrap())
                           .into()),
                       Link(SlackLink::new(&res.commit_url, &res.commit_id[0..6]))]
                .as_slice())
            .attachments(result_to_attachments(&res))
            .channel(self.channel.clone())
            .username("taster")
            .icon_emoji(":tea:")
            .build()
            .unwrap();

        match self.conn.send(&payload) {
            Ok(_) => Ok(()),
            Err(e) => Err(format!("{:?}", e)),
        }
    }
}

fn result_to_attachments(res: &TastingResult) -> Vec<Attachment> {
    let color = if !res.build || !res.tests || !res.bench {
        "danger"
    } else {
        "good"
    };

    let title = if !res.build {
        "Build failure!"
    } else if !res.test {
        "Test failure!"
    } else if !res.bench {
        "Benchmark failure!"
    } else {
        "Performance results:"
    };

    let taste = if !res.build || !res.bench {
        "was inedible"
    } else if !res.tests {
        "had a mixed palate"
    } else {
        "tasted nice"
    };

    let check = |title: &str, result: bool| {
        let mut out = format!("{}: ", title);
        if result {
            out.push_str(":white_check_mark:");
        } else {
            out.push_str(":x:");
        }
        out
    };

    let mut attachments = Vec::new();
    let build_att = AttachmentBuilder::new("")
        .title(format!("It {}.", taste))
        .text(format!("{} {} {}",
                      check("Build", res.build),
                      check("Tests", res.test),
                      check("Benchmark", res.bench)))
        .color(color)
        .build()
        .unwrap();
    attachments.push(build_att);

    match res.results {
        None => (),
        Some(ref r) => {
            for res in r {
                let mut nv = res.iter()
                    .map(|(k, v)| {
                        let val = match v {
                            &BenchmarkResult::Neutral(ref s, _) => s,
                            _ => unimplemented!(),
                        };
                        Field {
                            title: k.clone(),
                            value: SlackText::new(val.clone()),
                            short: Some(true),
                        }
                    })
                    .collect::<Vec<_>>();
                nv.sort_by(|a, b| b.title.cmp(&a.title));
                let att = AttachmentBuilder::new("")
                    .color(color)
                    .fields(nv)
                    .build()
                    .unwrap();
                attachments.push(att);
            }
        }
    }
    attachments
}
<commit_msg>It helps to push code that compiles...<commit_after>use slack_hook::{Attachment, AttachmentBuilder, Field, PayloadBuilder, Slack, SlackText, SlackLink};
use slack_hook::SlackTextContent::{Text, Link};

use taste::{BenchmarkResult, TastingResult};

pub struct SlackNotifier {
    conn: Slack,
    channel: String,
    github_repo: String,
}

impl SlackNotifier {
    pub fn new(hook_url: &str, channel: &str, repo_url: &str) -> SlackNotifier {
        SlackNotifier {
            conn: Slack::new(hook_url).unwrap(),
            channel: String::from(channel),
            github_repo: String::from(repo_url),
        }
    }

    pub fn notify(&self, res: &TastingResult) -> Result<(), String> {
        let payload = PayloadBuilder::new()
            .text(vec![Text("I've tasted commit _".into()),
                       Text(format!("\"{}\"_ -- ", res.commit_msg.lines().next().unwrap())
                           .into()),
                       Link(SlackLink::new(&res.commit_url, &res.commit_id[0..6]))]
                .as_slice())
            .attachments(result_to_attachments(&res))
            .channel(self.channel.clone())
            .username("taster")
            .icon_emoji(":tea:")
            .build()
            .unwrap();

        match self.conn.send(&payload) {
            Ok(_) => Ok(()),
            Err(e) => Err(format!("{:?}", e)),
        }
    }
}

fn result_to_attachments(res: &TastingResult) -> Vec<Attachment> {
    let color = if !res.build || !res.test || !res.bench {
        "danger"
    } else {
        "good"
    };

    let title = if !res.build {
        "Build failure!"
    } else if !res.test {
        "Test failure!"
    } else if !res.bench {
        "Benchmark failure!"
    } else {
        "Performance results:"
    };

    let taste = if !res.build || !res.bench {
        "was inedible"
    } else if !res.test {
        "had a mixed palate"
    } else {
        "tasted nice"
    };

    let check = |title: &str, result: bool| {
        let mut out = format!("{}: ", title);
        if result {
            out.push_str(":white_check_mark:");
        } else {
            out.push_str(":x:");
        }
        out
    };

    let mut attachments = Vec::new();
    let build_att = AttachmentBuilder::new("")
        .title(format!("It {}.", taste))
        .text(format!("{} {} {}",
                      check("Build", res.build),
                      check("Tests", res.test),
                      check("Benchmark", res.bench)))
        .color(color)
        .build()
        .unwrap();
    attachments.push(build_att);

    match res.results {
        None => (),
        Some(ref r) => {
            for res in r {
                let mut nv = res.iter()
                    .map(|(k, v)| {
                        let val = match v {
                            &BenchmarkResult::Neutral(ref s, _) => s,
                            _ => unimplemented!(),
                        };
                        Field {
                            title: k.clone(),
                            value: SlackText::new(val.clone()),
                            short: Some(true),
                        }
                    })
                    .collect::<Vec<_>>();
                nv.sort_by(|a, b| b.title.cmp(&a.title));
                let att = AttachmentBuilder::new("")
                    .color(color)
                    .fields(nv)
                    .build()
                    .unwrap();
                attachments.push(att);
            }
        }
    }
    attachments
}
<|endoftext|>


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

//! Finding C declarations.

use std::vec;
use std::collections::{HashSet};
use std::str::{FromStr};

use super::{Entity, EntityKind, Type, TypeKind};

type Seen = HashSet<String>;

//================================================
// Enums
//================================================

// DefinitionValue _______________________________

/// The value of a C preprocessor definition.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum DefinitionValue {
    /// An integer.
    Integer(bool, u64),
    /// A floating point number.
    Real(f64),
}

impl DefinitionValue {
    //- Constructors -----------------------------

    fn from_entity(entity: Entity) -> Option<DefinitionValue> {
        let mut tokens = entity.get_range().unwrap().tokenize();
        if tokens.last().map_or(false, |t| t.get_spelling() == "#") {
            tokens.pop();
        }

        let (negated, number) = if tokens.len() == 2 {
            (false, tokens[1].get_spelling())
        } else if tokens.len() == 3 && tokens[1].get_spelling() == "-" {
            (true, tokens[2].get_spelling())
        } else {
            return None;
        };

        if let Ok(integer) = u64::from_str(&number) {
            Some(DefinitionValue::Integer(negated, integer))
        } else if let Ok(real) = f64::from_str(&number) {
            if negated {
                Some(DefinitionValue::Real(-real))
            } else {
                Some(DefinitionValue::Real(real))
            }
        } else {
            None
        }
    }
}

//================================================
// Structs
//================================================

// Declaration ___________________________________

/// A C declaration.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Declaration<'tu> {
    /// The name of the declaration.
    pub name: String,
    /// The entity that describes the declaration (e.g., contains the fields of a struct).
    pub entity: Entity<'tu>,
    /// The entity the declaration originated from if it differs from `entity`.
    pub source: Option<Entity<'tu>>,
}

impl<'tu> Declaration<'tu> {
    //- Constructors -----------------------------

    fn new(name: String, entity: Entity<'tu>, source: Option<Entity<'tu>>) -> Declaration<'tu> {
        Declaration { name: name, entity: entity, source: source }
    }
}

// Definition ____________________________________

/// A C preprocessor definition.
#[derive(Clone, Debug, PartialEq)]
pub struct Definition<'tu> {
    /// The name of the definition.
    pub name: String,
    /// The value of the definition.
    pub value: DefinitionValue,
    /// The entity that describes the definition.
    pub entity: Entity<'tu>,
}

impl<'tu> Definition<'tu> {
    //- Constructors -----------------------------

    fn new(name: String, value: DefinitionValue, entity: Entity<'tu>) -> Definition<'tu> {
        Definition { name: name, value: value, entity: entity }
    }
}

// Definitions ___________________________________

/// An iterator over preprocessor definition declarations.
#[allow(missing_debug_implementations)]
pub struct Definitions<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Definitions<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Definitions<'tu> {
        Definitions { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Definitions<'tu> {
    type Item = Definition<'tu>;

    fn next(&mut self) -> Option<Definition<'tu>> {
        for entity in &mut self.entities {
            if entity.get_kind() == EntityKind::MacroDefinition {
                let name = entity.get_name().unwrap();
                if !self.seen.contains(&name) {
                    if let Some(value) = DefinitionValue::from_entity(entity) {
                        self.seen.insert(name.clone());
                        return Some(Definition::new(name, value, entity));
                    }
                }
            }
        }
        None
    }
}

// Enums _________________________________________

/// An iterator over enum declarations.
#[allow(missing_debug_implementations)]
pub struct Enums<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Enums<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Enums<'tu> {
        Enums { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Enums<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        next(&mut self.entities, &mut self.seen, EntityKind::EnumDecl, "enum ")
    }
}

// Functions _____________________________________

/// An iterator over function declarations.
#[allow(missing_debug_implementations)]
pub struct Functions<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Functions<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Functions<'tu> {
        Functions { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Functions<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        for entity in &mut self.entities {
            if entity.get_kind() == EntityKind::FunctionDecl {
                let name = entity.get_name().unwrap();
                if !self.seen.contains(&name) {
                    self.seen.insert(name.clone());
                    return Some(Declaration::new(name, entity, None));
                }
            }
        }
        None
    }
}

// Structs _______________________________________

/// An iterator over struct declarations.
#[allow(missing_debug_implementations)]
pub struct Structs<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Structs<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Structs<'tu> {
        Structs { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Structs<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        next(&mut self.entities, &mut self.seen, EntityKind::StructDecl, "struct ")
    }
}

// Typedefs ______________________________________

/// An iterator over typedef declarations.
#[allow(missing_debug_implementations)]
pub struct Typedefs<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Typedefs<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Typedefs<'tu> {
        Typedefs { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Typedefs<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        for entity in &mut self.entities {
            if entity.get_kind() == EntityKind::TypedefDecl {
                let name = entity.get_name().unwrap();
                if !self.seen.contains(&name) {
                    let underlying = entity.get_typedef_underlying_type().unwrap();
                    let display = entity.get_type().unwrap().get_display_name();

                    let typedef = !is_elaborated(underlying) ||
                        underlying.get_result_type().is_some() ||
                        is_alias(underlying, &display);

                    if typedef {
                        self.seen.insert(name.clone());
                        return Some(Declaration::new(name, entity, None));
                    }
                }
            }
        }
        None
    }
}

// Unions ________________________________________

/// An iterator over struct declarations.
#[allow(missing_debug_implementations)]
pub struct Unions<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Unions<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Unions<'tu> {
        Unions { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Unions<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        next(&mut self.entities, &mut self.seen, EntityKind::UnionDecl, "union ")
    }
}

//================================================
// Functions
//================================================

fn is(type_: Type, prefix: &str) -> bool {
    is_elaborated(type_) && type_.get_display_name().starts_with(prefix)
}

fn is_alias(type_: Type, name: &str) -> bool {
    for prefix in &["enum ", "struct ", "union "] {
        let display = type_.get_display_name();

        if display.starts_with(prefix) && &display[prefix.len()..] != name {
            return true;
        }
    }

    false
}

fn is_elaborated(type_: Type) -> bool {
    type_.is_elaborated().unwrap_or(type_.get_kind() == TypeKind::Unexposed)
}

fn next<'tu>(
    entities: &mut vec::IntoIter<Entity<'tu>>,
    seen: &mut HashSet<String>,
    kind: EntityKind,
    prefix: &str,
) -> Option<Declaration<'tu>> {
    for entity in entities {
        if entity.get_kind() == kind {
            if let Some(name) = entity.get_name() {
                if !seen.contains(&name) {
                    seen.insert(name);
                    if !entity.get_children().is_empty() {
                        return Some(Declaration::new(entity.get_name().unwrap(), entity, None));
                    }
                }
            }
        } else if entity.get_kind() == EntityKind::TypedefDecl {
            let underlying = entity.get_typedef_underlying_type().unwrap();
            let name = entity.get_name().unwrap();

            if is(underlying, prefix) && !seen.contains(&name) {
                let declaration = underlying.get_declaration().unwrap();

                let complete = declaration.get_type().map_or(false, |t| t.get_sizeof().is_ok());
                let anonymous = declaration.get_display_name().is_none();
                let same = entity.get_display_name() == declaration.get_display_name();

                seen.insert(name);
                if complete && (anonymous || same) {
                    let name = entity.get_name().unwrap();
                    return Some(Declaration::new(name, declaration, Some(entity)));
                }
            }
        }
    }
    None
}

/// Returns an iterator over the simple preprocessor definitions in the supplied entities.
///
/// Simple preprocessor definitions are those that consist only of a single integer or floating
/// point literal, optionally negated.
///
/// If a preprocessor definition is encountered multiple times, only the first instance is included.
pub fn find_definitions<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Definitions<'tu> {
    Definitions::new(entities.into().into_iter())
}

/// Returns an iterator over the enums in the supplied entities.
///
/// If an enum is encountered multiple times, only the first instance is included.
pub fn find_enums<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Enums<'tu> {
    Enums::new(entities.into().into_iter())
}

/// Returns an iterator over the functions in the supplied entities.
///
/// If a function is encountered multiple times, only the first instance is included.
pub fn find_functions<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Functions<'tu> {
    Functions::new(entities.into().into_iter())
}

/// Returns an iterator over the structs in the supplied entities.
///
/// If a struct is encountered multiple times, only the first instance is included.
pub fn find_structs<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Structs<'tu> {
    Structs::new(entities.into().into_iter())
}

/// Returns an iterator over the typedefs in the supplied entities.
///
/// If a typedef is encountered multiple times, only the first instance is included.
pub fn find_typedefs<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Typedefs<'tu> {
    Typedefs::new(entities.into().into_iter())
}

/// Returns an iterator over the unions in the supplied entities.
///
/// If a union is encountered multiple times, only the first instance is included.
pub fn find_unions<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Unions<'tu> {
    Unions::new(entities.into().into_iter())
}
<commit_msg>Add Entity::get_child usage<commit_after>// Copyright 2016 Kyle Mayes
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Finding C declarations.

use std::vec;
use std::collections::{HashSet};
use std::str::{FromStr};

use super::{Entity, EntityKind, Type, TypeKind};

type Seen = HashSet<String>;

//================================================
// Enums
//================================================

// DefinitionValue _______________________________

/// The value of a C preprocessor definition.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum DefinitionValue {
    /// An integer.
    Integer(bool, u64),
    /// A floating point number.
    Real(f64),
}

impl DefinitionValue {
    //- Constructors -----------------------------

    fn from_entity(entity: Entity) -> Option<DefinitionValue> {
        let mut tokens = entity.get_range().unwrap().tokenize();
        if tokens.last().map_or(false, |t| t.get_spelling() == "#") {
            tokens.pop();
        }

        let (negated, number) = if tokens.len() == 2 {
            (false, tokens[1].get_spelling())
        } else if tokens.len() == 3 && tokens[1].get_spelling() == "-" {
            (true, tokens[2].get_spelling())
        } else {
            return None;
        };

        if let Ok(integer) = u64::from_str(&number) {
            Some(DefinitionValue::Integer(negated, integer))
        } else if let Ok(real) = f64::from_str(&number) {
            if negated {
                Some(DefinitionValue::Real(-real))
            } else {
                Some(DefinitionValue::Real(real))
            }
        } else {
            None
        }
    }
}

//================================================
// Structs
//================================================

// Declaration ___________________________________

/// A C declaration.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Declaration<'tu> {
    /// The name of the declaration.
    pub name: String,
    /// The entity that describes the declaration (e.g., contains the fields of a struct).
    pub entity: Entity<'tu>,
    /// The entity the declaration originated from if it differs from `entity`.
    pub source: Option<Entity<'tu>>,
}

impl<'tu> Declaration<'tu> {
    //- Constructors -----------------------------

    fn new(name: String, entity: Entity<'tu>, source: Option<Entity<'tu>>) -> Declaration<'tu> {
        Declaration { name: name, entity: entity, source: source }
    }
}

// Definition ____________________________________

/// A C preprocessor definition.
#[derive(Clone, Debug, PartialEq)]
pub struct Definition<'tu> {
    /// The name of the definition.
    pub name: String,
    /// The value of the definition.
    pub value: DefinitionValue,
    /// The entity that describes the definition.
    pub entity: Entity<'tu>,
}

impl<'tu> Definition<'tu> {
    //- Constructors -----------------------------

    fn new(name: String, value: DefinitionValue, entity: Entity<'tu>) -> Definition<'tu> {
        Definition { name: name, value: value, entity: entity }
    }
}

// Definitions ___________________________________

/// An iterator over preprocessor definition declarations.
#[allow(missing_debug_implementations)]
pub struct Definitions<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Definitions<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Definitions<'tu> {
        Definitions { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Definitions<'tu> {
    type Item = Definition<'tu>;

    fn next(&mut self) -> Option<Definition<'tu>> {
        for entity in &mut self.entities {
            if entity.get_kind() == EntityKind::MacroDefinition {
                let name = entity.get_name().unwrap();
                if !self.seen.contains(&name) {
                    if let Some(value) = DefinitionValue::from_entity(entity) {
                        self.seen.insert(name.clone());
                        return Some(Definition::new(name, value, entity));
                    }
                }
            }
        }
        None
    }
}

// Enums _________________________________________

/// An iterator over enum declarations.
#[allow(missing_debug_implementations)]
pub struct Enums<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Enums<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Enums<'tu> {
        Enums { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Enums<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        next(&mut self.entities, &mut self.seen, EntityKind::EnumDecl, "enum ")
    }
}

// Functions _____________________________________

/// An iterator over function declarations.
#[allow(missing_debug_implementations)]
pub struct Functions<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Functions<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Functions<'tu> {
        Functions { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Functions<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        for entity in &mut self.entities {
            if entity.get_kind() == EntityKind::FunctionDecl {
                let name = entity.get_name().unwrap();
                if !self.seen.contains(&name) {
                    self.seen.insert(name.clone());
                    return Some(Declaration::new(name, entity, None));
                }
            }
        }
        None
    }
}

// Structs _______________________________________

/// An iterator over struct declarations.
#[allow(missing_debug_implementations)]
pub struct Structs<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Structs<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Structs<'tu> {
        Structs { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Structs<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        next(&mut self.entities, &mut self.seen, EntityKind::StructDecl, "struct ")
    }
}

// Typedefs ______________________________________

/// An iterator over typedef declarations.
#[allow(missing_debug_implementations)]
pub struct Typedefs<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Typedefs<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Typedefs<'tu> {
        Typedefs { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Typedefs<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        for entity in &mut self.entities {
            if entity.get_kind() == EntityKind::TypedefDecl {
                let name = entity.get_name().unwrap();
                if !self.seen.contains(&name) {
                    let underlying = entity.get_typedef_underlying_type().unwrap();
                    let display = entity.get_type().unwrap().get_display_name();

                    let typedef = !is_elaborated(underlying) ||
                        underlying.get_result_type().is_some() ||
                        is_alias(underlying, &display);

                    if typedef {
                        self.seen.insert(name.clone());
                        return Some(Declaration::new(name, entity, None));
                    }
                }
            }
        }
        None
    }
}

// Unions ________________________________________

/// An iterator over struct declarations.
#[allow(missing_debug_implementations)]
pub struct Unions<'tu> {
    entities: vec::IntoIter<Entity<'tu>>,
    seen: HashSet<String>,
}

impl<'tu> Unions<'tu> {
    //- Constructors -----------------------------

    fn new(entities: vec::IntoIter<Entity<'tu>>) -> Unions<'tu> {
        Unions { entities: entities, seen: HashSet::new() }
    }
}

impl<'tu> Iterator for Unions<'tu> {
    type Item = Declaration<'tu>;

    fn next(&mut self) -> Option<Declaration<'tu>> {
        next(&mut self.entities, &mut self.seen, EntityKind::UnionDecl, "union ")
    }
}

//================================================
// Functions
//================================================

fn is(type_: Type, prefix: &str) -> bool {
    is_elaborated(type_) && type_.get_display_name().starts_with(prefix)
}

fn is_alias(type_: Type, name: &str) -> bool {
    for prefix in &["enum ", "struct ", "union "] {
        let display = type_.get_display_name();

        if display.starts_with(prefix) && &display[prefix.len()..] != name {
            return true;
        }
    }

    false
}

fn is_elaborated(type_: Type) -> bool {
    type_.is_elaborated().unwrap_or(type_.get_kind() == TypeKind::Unexposed)
}

fn next<'tu>(
    entities: &mut vec::IntoIter<Entity<'tu>>,
    seen: &mut HashSet<String>,
    kind: EntityKind,
    prefix: &str,
) -> Option<Declaration<'tu>> {
    for entity in entities {
        if entity.get_kind() == kind {
            if let Some(name) = entity.get_name() {
                if !seen.contains(&name) {
                    seen.insert(name);
                    if entity.get_child(0).is_some() {
                        return Some(Declaration::new(entity.get_name().unwrap(), entity, None));
                    }
                }
            }
        } else if entity.get_kind() == EntityKind::TypedefDecl {
            let underlying = entity.get_typedef_underlying_type().unwrap();
            let name = entity.get_name().unwrap();

            if is(underlying, prefix) && !seen.contains(&name) {
                let declaration = underlying.get_declaration().unwrap();

                let complete = declaration.get_type().map_or(false, |t| t.get_sizeof().is_ok());
                let anonymous = declaration.get_display_name().is_none();
                let same = entity.get_display_name() == declaration.get_display_name();

                seen.insert(name);
                if complete && (anonymous || same) {
                    let name = entity.get_name().unwrap();
                    return Some(Declaration::new(name, declaration, Some(entity)));
                }
            }
        }
    }
    None
}

/// Returns an iterator over the simple preprocessor definitions in the supplied entities.
///
/// Simple preprocessor definitions are those that consist only of a single integer or floating
/// point literal, optionally negated.
///
/// If a preprocessor definition is encountered multiple times, only the first instance is included.
pub fn find_definitions<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Definitions<'tu> {
    Definitions::new(entities.into().into_iter())
}

/// Returns an iterator over the enums in the supplied entities.
///
/// If an enum is encountered multiple times, only the first instance is included.
pub fn find_enums<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Enums<'tu> {
    Enums::new(entities.into().into_iter())
}

/// Returns an iterator over the functions in the supplied entities.
///
/// If a function is encountered multiple times, only the first instance is included.
pub fn find_functions<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Functions<'tu> {
    Functions::new(entities.into().into_iter())
}

/// Returns an iterator over the structs in the supplied entities.
///
/// If a struct is encountered multiple times, only the first instance is included.
pub fn find_structs<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Structs<'tu> {
    Structs::new(entities.into().into_iter())
}

/// Returns an iterator over the typedefs in the supplied entities.
///
/// If a typedef is encountered multiple times, only the first instance is included.
pub fn find_typedefs<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Typedefs<'tu> {
    Typedefs::new(entities.into().into_iter())
}

/// Returns an iterator over the unions in the supplied entities.
///
/// If a union is encountered multiple times, only the first instance is included.
pub fn find_unions<'tu, E: Into<Vec<Entity<'tu>>>>(entities: E) -> Unions<'tu> {
    Unions::new(entities.into().into_iter())
}
<|endoftext|>


<commit_before>extern crate rand;

const ROWS: u8 = 9;
const COLS: u8 = 12;
const TILES: u8 = 108;
const PLAYERS: u8 = 4;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Game {
    players: Vec<Player>,
    board: Board,
    turn: PlayerId,
    merge_decision: Option<PlayerId>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Player {
    id: PlayerId,
    money: i32,
    shares: PlayerShares,
    tiles: Vec<Tile>
}

type PlayerId = u8;

#[derive(RustcDecodable, RustcEncodable)]
struct PlayerShares {
    luxor: u8,
    tower: u8,
    american: u8,
    festival: u8,
    worldwide: u8,
    continental: u8,
    imperial: u8
}

#[derive(RustcDecodable, RustcEncodable, Clone, Debug)]
struct Tile { row: u8, col: u8 }

#[derive(RustcDecodable, RustcEncodable)]
struct Board {
    slots: Vec<Slot>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Slot {
    row: u8,
    col: u8,
    has_tile: bool,
    hotel: Option<Hotel>
}

enum Action {
    PlaceTile,
    HandleMergeStocks,
    BuyStocks,
    DrawTile,
    EndGame
}

pub struct PlaceTile {
    player: PlayerId,
    tile: Tile
}

pub struct HandleMergeStocks {
    hold: u8,
    sell: u8,
    trade: u8
}

type BuyStocks = PlayerShares;

#[derive(RustcDecodable, RustcEncodable)]
enum Hotel { Luxor, Tower, American, Festival, Worldwide, Continental, Imperial }

fn empty_shares() -> PlayerShares {
    PlayerShares { luxor: 0, tower: 0, american: 0, festival: 0, worldwide: 0, continental: 0, imperial: 0 }
}

fn new_player(id: PlayerId, tiles: Vec<Tile>) -> Player {
    Player { id: id, money: 6000, shares: empty_shares(), tiles: tiles }
}

fn choose_tiles(tiles: Vec<Tile>, count: u8) -> (Vec<Tile>, Vec<Tile>) {
    let mut remaining_tiles = tiles;
    let mut random_tiles = Vec::new();
    for _ in 0..count {
        let random_index = (rand::random::<u8>() as usize) % remaining_tiles.len();
        random_tiles.push(remaining_tiles.remove(random_index));
    }
    (random_tiles, remaining_tiles)
}

fn new_players(tiles: Vec<Tile>) -> Vec<Player>{
    let init_players: Vec<Player> = Vec::new();
    let (players, _) = (0..PLAYERS)
        .fold( (init_players, tiles), | (mut v, remaining), i | {
            let (player_tiles, new_remaining) = choose_tiles(remaining, 6);
            let player = new_player(i, player_tiles);
            v.push(player);
            (v, new_remaining)
        });
    players
}

fn has_tile_on_slot(tiles: & Vec<Tile>, row: u8, col: u8) -> bool {
    tiles.iter().any(|t| t.row == row && t.col == col)
}

fn initial_slots(starting_tiles: Vec<Tile>) -> Vec<Slot> {
    let slots: Vec<Slot> = (0..COLS)
        .flat_map(|col| {
            let rows = 0..ROWS;
            let res: Vec<Slot> = rows.map(|row| {
                let has_tile = has_tile_on_slot(&starting_tiles, row, col);
                Slot { row: row, col: col, hotel: None, has_tile: has_tile }
            }).collect();
            res
        }).collect();
    slots
}

pub fn initial_state() -> Game {
    let all_tiles = (0..TILES).map(|i| Tile { row: i / COLS, col: i % ROWS }).collect();
    let (starting_tiles, remaining_tiles) = choose_tiles(all_tiles, PLAYERS);
    let players = new_players(remaining_tiles);
    let slots = initial_slots(starting_tiles);
    Game {
        board: Board { slots: slots },
        players: players,
        turn: 1,
        merge_decision: None
    }
}

#[test]
fn players_start_with_six_tiles() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.tiles.len(), 6);
    }
}

#[test]
fn players_start_with_6000_in_cash() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.money, 6000);
    }
}

#[test]
fn players_start_with_zero_shares() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.shares.luxor, 0);
        assert_eq!(player.shares.tower, 0);
        assert_eq!(player.shares.american, 0);
        assert_eq!(player.shares.festival, 0);
        assert_eq!(player.shares.worldwide, 0);
        assert_eq!(player.shares.continental, 0);
        assert_eq!(player.shares.imperial, 0);
    }
}

#[test]
fn game_starts_with_four_placed_tiles() {
    let state = initial_state();
    let board_tiles = state.board.slots.iter().filter(|s| s.has_tile).count();
    assert_eq!(board_tiles, 4)
}
<commit_msg>Simplify initial slots creation<commit_after>extern crate rand;

const ROWS: u8 = 9;
const COLS: u8 = 12;
const TILES: u8 = 108;
const PLAYERS: u8 = 4;

#[derive(RustcDecodable, RustcEncodable)]
pub struct Game {
    players: Vec<Player>,
    board: Board,
    turn: PlayerId,
    merge_decision: Option<PlayerId>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Player {
    id: PlayerId,
    money: i32,
    shares: PlayerShares,
    tiles: Vec<Tile>
}

type PlayerId = u8;

#[derive(RustcDecodable, RustcEncodable)]
struct PlayerShares {
    luxor: u8,
    tower: u8,
    american: u8,
    festival: u8,
    worldwide: u8,
    continental: u8,
    imperial: u8
}

#[derive(RustcDecodable, RustcEncodable, Clone, Debug)]
struct Tile { row: u8, col: u8 }

#[derive(RustcDecodable, RustcEncodable)]
struct Board {
    slots: Vec<Slot>
}

#[derive(RustcDecodable, RustcEncodable)]
struct Slot {
    row: u8,
    col: u8,
    has_tile: bool,
    hotel: Option<Hotel>
}

enum Action {
    PlaceTile,
    HandleMergeStocks,
    BuyStocks,
    DrawTile,
    EndGame
}

pub struct PlaceTile {
    player: PlayerId,
    tile: Tile
}

pub struct HandleMergeStocks {
    hold: u8,
    sell: u8,
    trade: u8
}

type BuyStocks = PlayerShares;

#[derive(RustcDecodable, RustcEncodable)]
enum Hotel { Luxor, Tower, American, Festival, Worldwide, Continental, Imperial }

fn empty_shares() -> PlayerShares {
    PlayerShares { luxor: 0, tower: 0, american: 0, festival: 0, worldwide: 0, continental: 0, imperial: 0 }
}

fn new_player(id: PlayerId, tiles: Vec<Tile>) -> Player {
    Player { id: id, money: 6000, shares: empty_shares(), tiles: tiles }
}

fn choose_tiles(tiles: Vec<Tile>, count: u8) -> (Vec<Tile>, Vec<Tile>) {
    let mut remaining_tiles = tiles;
    let mut random_tiles = Vec::new();
    for _ in 0..count {
        let random_index = (rand::random::<u8>() as usize) % remaining_tiles.len();
        random_tiles.push(remaining_tiles.remove(random_index));
    }
    (random_tiles, remaining_tiles)
}

fn new_players(tiles: Vec<Tile>) -> Vec<Player>{
    let init_players: Vec<Player> = Vec::new();
    let (players, _) = (0..PLAYERS)
        .fold( (init_players, tiles), | (mut v, remaining), i | {
            let (player_tiles, new_remaining) = choose_tiles(remaining, 6);
            let player = new_player(i, player_tiles);
            v.push(player);
            (v, new_remaining)
        });
    players
}

fn has_tile_on_slot(tiles: & Vec<Tile>, row: u8, col: u8) -> bool {
    tiles.iter().any(|t| t.row == row && t.col == col)
}

fn initial_slots(starting_tiles: Vec<Tile>) -> Vec<Slot> {
    (0..COLS).flat_map(|col| -> Vec<Slot> {
        (0..ROWS).map(|row| {
            Slot {
                row: row,
                col: col,
                hotel: None,
                has_tile: has_tile_on_slot(&starting_tiles, row, col)
            }
        }).collect()
    }).collect()
}

pub fn initial_state() -> Game {
    let all_tiles = (0..TILES).map(|i| Tile { row: i / COLS, col: i % ROWS }).collect();
    let (starting_tiles, remaining_tiles) = choose_tiles(all_tiles, PLAYERS);
    let players = new_players(remaining_tiles);
    let slots = initial_slots(starting_tiles);
    Game {
        board: Board { slots: slots },
        players: players,
        turn: 1,
        merge_decision: None
    }
}

#[test]
fn players_start_with_six_tiles() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.tiles.len(), 6);
    }
}

#[test]
fn players_start_with_6000_in_cash() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.money, 6000);
    }
}

#[test]
fn players_start_with_zero_shares() {
    let state = initial_state();
    for player in state.players {
        assert_eq!(player.shares.luxor, 0);
        assert_eq!(player.shares.tower, 0);
        assert_eq!(player.shares.american, 0);
        assert_eq!(player.shares.festival, 0);
        assert_eq!(player.shares.worldwide, 0);
        assert_eq!(player.shares.continental, 0);
        assert_eq!(player.shares.imperial, 0);
    }
}

#[test]
fn game_starts_with_four_placed_tiles() {
    let state = initial_state();
    let board_tiles = state.board.slots.iter().filter(|s| s.has_tile).count();
    assert_eq!(board_tiles, 4)
}
<|endoftext|>


<commit_before>
use std;
use piston::{
    Event,
    Input,
    Update,
    UpdateArgs,
};
use piston::input;
use {
    Behavior,
    Status,
    Failure,
    Success,
    Running,
    Pressed,
    Released,
    WhenAll,
    While,
    Sequence,
    Select,
    Wait,
    WaitForever,
    Not,
    AlwaysSucceed,
    Action,
};

/// Keeps track of an event.
#[deriving(Clone)]
pub enum State<A> {
    /// Keeps track of whether a button was pressed.
    PressedState(input::Button),
    /// Keeps track of whether a button was released.
    ReleasedState(input::Button),
    /// Keeps track of an event where you have a state of an action.
    ActionState(A),
    /// Keeps track of converting `Success` into `Failure` and vice versa.
    NotState(Box<State<A>>),
    /// Keeps track of a behavior that ignore failures.
    AlwaysSucceedState(Box<State<A>>),
    /// Keeps track of an event where you wait and do nothing.
    WaitState(f64, f64),
    /// Keeps track of a behavior that waits forever.
    WaitForeverState,
    /// Keeps track of a `Select` event.
    SelectState(Vec<Behavior<A>>, uint, Box<State<A>>),
    /// Keeps track of an event where sub events happens sequentially.
    SequenceState(Vec<Behavior<A>>, uint, Box<State<A>>),
    /// Keeps track of an event where sub events are repeated sequentially.
    WhileState(Box<State<A>>, Vec<Behavior<A>>, uint, Box<State<A>>),
    /// Keeps track of an event where all sub events must happen.
    WhenAllState(Vec<Option<State<A>>>),
}

impl<A: Clone> State<A> {
    /// Creates a state from a behavior.
    pub fn new(behavior: Behavior<A>) -> State<A> {
        match behavior {
            Pressed(button) => PressedState(button),
            Released(button) => ReleasedState(button),
            Action(action) => ActionState(action),
            Not(ev) => NotState(box State::new(*ev)),
            AlwaysSucceed(ev) => AlwaysSucceedState(box State::new(*ev)),
            Wait(dt) => WaitState(dt, 0.0),
            WaitForever => WaitForeverState,
            Select(sel) => {
                let state = State::new(sel[0].clone());
                SelectState(sel, 0, box state)
            }
            Sequence(seq) => {
                let state = State::new(seq[0].clone());
                SequenceState(seq, 0, box state)
            }
            While(ev, rep) => {
                let state = State::new(rep[0].clone());
                WhileState(box State::new(*ev), rep, 0, box state)
            }
            WhenAll(all)
                => WhenAllState(all.move_iter().map(
                    |ev| Some(State::new(ev))).collect()),
        }
    }

    /// Updates the cursor that tracks an event.
    ///
    /// The action need to return status and remaining delta time.
    /// Returns status and the remaining delta time.
    pub fn update(
        &mut self,
        e: &Event,
        f: |dt: f64, action: &A| -> (Status, f64)
    ) -> (Status, f64) {
        match (e, self) {
            (&Input(input::Press(button_pressed)), &PressedState(button))
            if button_pressed == button => {
                // Button press is considered to happen instantly.
                // There is no remaining delta time because this is input event.
                (Success, 0.0)
            }
            (&Input(input::Release(button_released)), &ReleasedState(button))
            if button_released == button => {
                // Button release is considered to happen instantly.
                // There is no remaining delta time because this is input event.
                (Success, 0.0)
            }
            (&Update(UpdateArgs { dt }), &ActionState(ref action)) => {
                // Execute action.
                f(dt, action)
            }
            (_, &NotState(ref mut cur)) => {
                match cur.update(e, f) {
                    (Running, dt) => (Running, dt),
                    (Failure, dt) => (Success, dt),
                    (Success, dt) => (Failure, dt),
                }
            }
            (_, &AlwaysSucceedState(ref mut cur)) => {
                match cur.update(e, f) {
                    (Running, dt) => (Running, dt),
                    (_, dt) => (Success, dt),
                }
            }
            (&Update(UpdateArgs { dt }), &WaitState(wait_t, ref mut t)) => {
                if *t + dt >= wait_t {
                    let remaining_dt = *t + dt - wait_t;
                    *t = wait_t;
                    (Success, remaining_dt)
                } else {
                    *t += dt;
                    (Running, 0.0)
                }
            }
            (_, &SelectState(
                ref seq,
                ref mut i,
                ref mut cursor
            )) => {
                let mut remaining_dt = match *e {
                        Update(UpdateArgs { dt }) => dt,
                        _ => 0.0,
                    };
                let mut remaining_e;
                while *i < seq.len() {
                    match cursor.update(
                        match *e {
                            Update(_) => {
                                remaining_e = Update(UpdateArgs { dt: remaining_dt });
                                &remaining_e
                            }
                            _ => e
                        },
                        |dt, a| f(dt, a)) {
                        (Success, x) => { return (Success, x) }
                        (Running, _) => { break }
                        (Failure, new_dt) => { remaining_dt = new_dt }
                    };
                    *i += 1;
                    // If end of sequence,
                    // return the 'dt' that is left.
                    if *i >= seq.len() { return (Failure, remaining_dt); }
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    **cursor = State::new(seq[*i].clone());
                }
                (Running, 0.0)
            }
            (_, &SequenceState(
                ref seq,
                ref mut i,
                ref mut cursor
            )) => {
                let cur = cursor;
                let mut remaining_dt = match *e {
                        Update(UpdateArgs { dt }) => dt,
                        _ => 0.0,
                    };
                let mut remaining_e;
                while *i < seq.len() {
                    match cur.update(match *e {
                            Update(_) => {
                                remaining_e = Update(UpdateArgs { dt: remaining_dt });
                                &remaining_e
                            }
                            _ => e
                        },
                        |dt, a| f(dt, a)) {
                        (Failure, x) => return (Failure, x),
                        (Running, _) => { break },
                        (Success, new_dt) => {
                            remaining_dt = match *e {
                                // Change update event with remaining delta time.
                                Update(_) => new_dt,
                                // Other events are 'consumed' and not passed to next.
                                // If this is the last event, then the sequence succeeded.
                                _ => if *i == seq.len() - 1 {
                                        return (Success, new_dt)
                                    } else {
                                        return (Running, 0.0)
                                    }
                            }
                        }
                    };
                    *i += 1;
                    // If end of sequence,
                    // return the 'dt' that is left.
                    if *i >= seq.len() { return (Success, remaining_dt); }
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    **cur = State::new(seq[*i].clone());
                }
                (Running, 0.0)
            }
            (_, &WhileState(
                ref mut ev_cursor,
                ref rep,
                ref mut i,
                ref mut cursor
            )) => {
                // If the event terminates, do not execute the loop.
                match ev_cursor.update(e, |dt, a| f(dt, a)) {
                    (Running, _) => {}
                    x => return x,
                };
                let cur = cursor;
                let mut remaining_dt = match *e {
                        Update(UpdateArgs { dt }) => dt,
                        _ => 0.0,
                    };
                let mut remaining_e;
                loop {
                    match cur.update(match *e {
                            Update(_) => {
                                remaining_e = Update(UpdateArgs { dt: remaining_dt });
                                &remaining_e
                            }
                            _ => e
                        },
                        |dt, a| f(dt, a)) {
                        (Failure, x) => return (Failure, x),
                        (Running, _) => { break },
                        (Success, new_dt) => {
                            remaining_dt = match *e {
                                // Change update event with remaining delta time.
                                Update(_) => new_dt,
                                // Other events are 'consumed' and not passed to next.
                                _ => return (Running, 0.0)
                            }
                        }
                    };
                    *i += 1;
                    // If end of repeated events,
                    // start over from the first one.
                    if *i >= rep.len() { *i = 0; }
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    **cur = State::new(rep[*i].clone());
                }
                (Running, 0.0)
            }
            (_, &WhenAllState(ref mut cursors)) => {
                // Get the least delta time left over.
                let mut min_dt = std::f64::MAX_VALUE;
                // Count number of terminated events.
                let mut terminated = 0;
                for cur in cursors.mut_iter() {
                    match *cur {
                        None => terminated += 1,
                        Some(ref mut cur) => {
                            match cur.update(e, |dt, a| f(dt, a)) {
                                (Running, _) => {},
                                (Failure, new_dt) => return (Failure, new_dt),
                                (Success, new_dt) => {
                                    min_dt = min_dt.min(new_dt);
                                    terminated += 1;
                                }
                            }
                        }
                    }
                }
                match terminated {
                    // If there are no events, there is a whole 'dt' left.
                    0 if cursors.len() == 0 => (Success, match *e {
                            Update(UpdateArgs { dt }) => dt,
                            // Other kind of events happen instantly.
                            _ => 0.0
                        }),
                    // If all events terminated, the least delta time is left.
                    n if cursors.len() == n => (Success, min_dt),
                    _ => (Running, 0.0)
                }
            }
            _ => (Running, 0.0)
        }
    }
}
<commit_msg>Sorted use statements<commit_after>
use std;
use piston::{
    Event,
    Input,
    Update,
    UpdateArgs,
};
use piston::input;
use {
    Action,
    AlwaysSucceed,
    Behavior,
    Failure,
    Not,
    Pressed,
    Released,
    Running,
    Select,
    Sequence,
    Status,
    Success,
    Wait,
    WaitForever,
    WhenAll,
    While,
};

/// Keeps track of an event.
#[deriving(Clone)]
pub enum State<A> {
    /// Keeps track of whether a button was pressed.
    PressedState(input::Button),
    /// Keeps track of whether a button was released.
    ReleasedState(input::Button),
    /// Keeps track of an event where you have a state of an action.
    ActionState(A),
    /// Keeps track of converting `Success` into `Failure` and vice versa.
    NotState(Box<State<A>>),
    /// Keeps track of a behavior that ignore failures.
    AlwaysSucceedState(Box<State<A>>),
    /// Keeps track of an event where you wait and do nothing.
    WaitState(f64, f64),
    /// Keeps track of a behavior that waits forever.
    WaitForeverState,
    /// Keeps track of a `Select` event.
    SelectState(Vec<Behavior<A>>, uint, Box<State<A>>),
    /// Keeps track of an event where sub events happens sequentially.
    SequenceState(Vec<Behavior<A>>, uint, Box<State<A>>),
    /// Keeps track of an event where sub events are repeated sequentially.
    WhileState(Box<State<A>>, Vec<Behavior<A>>, uint, Box<State<A>>),
    /// Keeps track of an event where all sub events must happen.
    WhenAllState(Vec<Option<State<A>>>),
}

impl<A: Clone> State<A> {
    /// Creates a state from a behavior.
    pub fn new(behavior: Behavior<A>) -> State<A> {
        match behavior {
            Pressed(button) => PressedState(button),
            Released(button) => ReleasedState(button),
            Action(action) => ActionState(action),
            Not(ev) => NotState(box State::new(*ev)),
            AlwaysSucceed(ev) => AlwaysSucceedState(box State::new(*ev)),
            Wait(dt) => WaitState(dt, 0.0),
            WaitForever => WaitForeverState,
            Select(sel) => {
                let state = State::new(sel[0].clone());
                SelectState(sel, 0, box state)
            }
            Sequence(seq) => {
                let state = State::new(seq[0].clone());
                SequenceState(seq, 0, box state)
            }
            While(ev, rep) => {
                let state = State::new(rep[0].clone());
                WhileState(box State::new(*ev), rep, 0, box state)
            }
            WhenAll(all)
                => WhenAllState(all.move_iter().map(
                    |ev| Some(State::new(ev))).collect()),
        }
    }

    /// Updates the cursor that tracks an event.
    ///
    /// The action need to return status and remaining delta time.
    /// Returns status and the remaining delta time.
    pub fn update(
        &mut self,
        e: &Event,
        f: |dt: f64, action: &A| -> (Status, f64)
    ) -> (Status, f64) {
        match (e, self) {
            (&Input(input::Press(button_pressed)), &PressedState(button))
            if button_pressed == button => {
                // Button press is considered to happen instantly.
                // There is no remaining delta time because this is input event.
                (Success, 0.0)
            }
            (&Input(input::Release(button_released)), &ReleasedState(button))
            if button_released == button => {
                // Button release is considered to happen instantly.
                // There is no remaining delta time because this is input event.
                (Success, 0.0)
            }
            (&Update(UpdateArgs { dt }), &ActionState(ref action)) => {
                // Execute action.
                f(dt, action)
            }
            (_, &NotState(ref mut cur)) => {
                match cur.update(e, f) {
                    (Running, dt) => (Running, dt),
                    (Failure, dt) => (Success, dt),
                    (Success, dt) => (Failure, dt),
                }
            }
            (_, &AlwaysSucceedState(ref mut cur)) => {
                match cur.update(e, f) {
                    (Running, dt) => (Running, dt),
                    (_, dt) => (Success, dt),
                }
            }
            (&Update(UpdateArgs { dt }), &WaitState(wait_t, ref mut t)) => {
                if *t + dt >= wait_t {
                    let remaining_dt = *t + dt - wait_t;
                    *t = wait_t;
                    (Success, remaining_dt)
                } else {
                    *t += dt;
                    (Running, 0.0)
                }
            }
            (_, &SelectState(
                ref seq,
                ref mut i,
                ref mut cursor
            )) => {
                let mut remaining_dt = match *e {
                        Update(UpdateArgs { dt }) => dt,
                        _ => 0.0,
                    };
                let mut remaining_e;
                while *i < seq.len() {
                    match cursor.update(
                        match *e {
                            Update(_) => {
                                remaining_e = Update(UpdateArgs { dt: remaining_dt });
                                &remaining_e
                            }
                            _ => e
                        },
                        |dt, a| f(dt, a)) {
                        (Success, x) => { return (Success, x) }
                        (Running, _) => { break }
                        (Failure, new_dt) => { remaining_dt = new_dt }
                    };
                    *i += 1;
                    // If end of sequence,
                    // return the 'dt' that is left.
                    if *i >= seq.len() { return (Failure, remaining_dt); }
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    **cursor = State::new(seq[*i].clone());
                }
                (Running, 0.0)
            }
            (_, &SequenceState(
                ref seq,
                ref mut i,
                ref mut cursor
            )) => {
                let cur = cursor;
                let mut remaining_dt = match *e {
                        Update(UpdateArgs { dt }) => dt,
                        _ => 0.0,
                    };
                let mut remaining_e;
                while *i < seq.len() {
                    match cur.update(match *e {
                            Update(_) => {
                                remaining_e = Update(UpdateArgs { dt: remaining_dt });
                                &remaining_e
                            }
                            _ => e
                        },
                        |dt, a| f(dt, a)) {
                        (Failure, x) => return (Failure, x),
                        (Running, _) => { break },
                        (Success, new_dt) => {
                            remaining_dt = match *e {
                                // Change update event with remaining delta time.
                                Update(_) => new_dt,
                                // Other events are 'consumed' and not passed to next.
                                // If this is the last event, then the sequence succeeded.
                                _ => if *i == seq.len() - 1 {
                                        return (Success, new_dt)
                                    } else {
                                        return (Running, 0.0)
                                    }
                            }
                        }
                    };
                    *i += 1;
                    // If end of sequence,
                    // return the 'dt' that is left.
                    if *i >= seq.len() { return (Success, remaining_dt); }
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    **cur = State::new(seq[*i].clone());
                }
                (Running, 0.0)
            }
            (_, &WhileState(
                ref mut ev_cursor,
                ref rep,
                ref mut i,
                ref mut cursor
            )) => {
                // If the event terminates, do not execute the loop.
                match ev_cursor.update(e, |dt, a| f(dt, a)) {
                    (Running, _) => {}
                    x => return x,
                };
                let cur = cursor;
                let mut remaining_dt = match *e {
                        Update(UpdateArgs { dt }) => dt,
                        _ => 0.0,
                    };
                let mut remaining_e;
                loop {
                    match cur.update(match *e {
                            Update(_) => {
                                remaining_e = Update(UpdateArgs { dt: remaining_dt });
                                &remaining_e
                            }
                            _ => e
                        },
                        |dt, a| f(dt, a)) {
                        (Failure, x) => return (Failure, x),
                        (Running, _) => { break },
                        (Success, new_dt) => {
                            remaining_dt = match *e {
                                // Change update event with remaining delta time.
                                Update(_) => new_dt,
                                // Other events are 'consumed' and not passed to next.
                                _ => return (Running, 0.0)
                            }
                        }
                    };
                    *i += 1;
                    // If end of repeated events,
                    // start over from the first one.
                    if *i >= rep.len() { *i = 0; }
                    // Create a new cursor for next event.
                    // Use the same pointer to avoid allocation.
                    **cur = State::new(rep[*i].clone());
                }
                (Running, 0.0)
            }
            (_, &WhenAllState(ref mut cursors)) => {
                // Get the least delta time left over.
                let mut min_dt = std::f64::MAX_VALUE;
                // Count number of terminated events.
                let mut terminated = 0;
                for cur in cursors.mut_iter() {
                    match *cur {
                        None => terminated += 1,
                        Some(ref mut cur) => {
                            match cur.update(e, |dt, a| f(dt, a)) {
                                (Running, _) => {},
                                (Failure, new_dt) => return (Failure, new_dt),
                                (Success, new_dt) => {
                                    min_dt = min_dt.min(new_dt);
                                    terminated += 1;
                                }
                            }
                        }
                    }
                }
                match terminated {
                    // If there are no events, there is a whole 'dt' left.
                    0 if cursors.len() == 0 => (Success, match *e {
                            Update(UpdateArgs { dt }) => dt,
                            // Other kind of events happen instantly.
                            _ => 0.0
                        }),
                    // If all events terminated, the least delta time is left.
                    n if cursors.len() == n => (Success, min_dt),
                    _ => (Running, 0.0)
                }
            }
            _ => (Running, 0.0)
        }
    }
}
<|endoftext|>


<commit_before>//	MIT License
//
//  Copyright © 2017 Michael J Simms. All rights reserved.
//
//	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::collections::HashSet;
use std::collections::HashMap;

/// Each feature has a name and value.
pub struct Feature {
    name: String,
    value: u64,
}

impl Feature {
    pub fn new (name: &str, value: u64) -> Feature {
        Feature { name: name.to_string(), value: value }
    }

    pub fn set_name(&mut self, name: String) {
        self.name = name;
    }

    pub fn get_name(&self) -> String {
        self.name
    }

    pub fn set_value(&mut self, value: u64) {
        self.value = value;
    }

    pub fn get_value(&self) -> u64 {
        self.value
    }
}

pub type FeatureList = Vec<Feature>;
pub type Uint64Set = HashSet<u64>;
pub type FeatureNameToValuesMap<'a> = HashMap<&'a str, Uint64Set>;

/// This class represents a sample.
/// Each sample has a name and list of features.
pub struct Sample {
    name: String,
    features: FeatureList,
}

impl Sample {
    pub fn new (name: &str) -> Sample {
        Sample { name: name.to_string(), features: Sample::create_feature_list() }
    }

    fn create_feature_list() -> FeatureList {
        let mut v: FeatureList = vec![];
        v
    }

    pub fn add_features(&mut self, features: &mut FeatureList) {
        self.features.append(features);
    }

    pub fn add_feature(&mut self, feature: Feature) {
        self.features.push(feature);
    }

    pub fn features(&self) -> FeatureList {
        self.features
    }
}

pub type SampleList = Vec<Sample>;

/// Tree node, used internally.
struct Node<'a> {
    feature_name: String,
    left: NodeLink<'a>,
    right: NodeLink<'a>,
}

impl<'a> Node<'a> {
    pub fn new (feature_name: &str) -> Node {
        Node { feature_name: feature_name.to_string(), left: None, right: None }
    }

    fn get_feature_name(&self) -> String {
        self.feature_name
    }

	fn set_left_subtree(&mut self, subtree: NodeLink<'a>) {
		self.left = subtree;
	}

    fn get_left_subtree(&self) -> NodeLink<'a> {
        self.left
    }

	fn set_right_subtree(&mut self, subtree: NodeLink<'a>) {
		self.right = subtree;
	}

    fn get_right_subtree(&self) -> NodeLink<'a> {
        self.right
    }
}

pub type NodeLink<'a> = Option<Box<Node<'a>>>;
pub type NodeList<'a> = Vec<Node<'a>>;

/// Isolation Forest implementation.
pub struct Forest<'a> {
    feature_values: FeatureNameToValuesMap<'a>, // Lists each feature and maps it to all unique values in the training set
    trees: NodeList<'a>, // The decision trees that comprise the forest
    num_trees_to_create: u32, // The maximum number of trees to create
    sub_sampling_size: u32, // The maximum depth of a tree
}

impl<'a> Forest<'a> {
    pub fn new (num_trees_to_create: u32, sub_sampling_size: u32) -> Forest<'a> {
        Forest { num_trees_to_create: num_trees_to_create, sub_sampling_size: sub_sampling_size, trees: Forest::initialize_trees(), feature_values: Forest::create_feature_name_to_values_map() }
    }

    fn initialize_trees() -> NodeList<'a> {
        let mut v: NodeList = vec![];
        v
    }

    fn create_feature_name_to_values_map() -> FeatureNameToValuesMap<'a> {
        let mut m = HashMap::new();
        m
    }

    pub fn add_sample(&self, sample: Sample) {
		// Add each of this sample's features to the list of known features
		// with the corresponding set of unique values.
		let mut features = sample.features();
        for feature in &features {
            let mut found_feature = false;
        }
    }

    pub fn create_tree(&self, feature_values: FeatureNameToValuesMap<'a>, depth: u32) -> NodeList {
        let mut tree = NodeList::new();

		// Sanity check.
		if feature_values.len() <= 1 {
			return tree;
		}

		// If we've exceeded the maximum desired depth, then stop.
		if (self.sub_sampling_size > 0) && (depth >= self.sub_sampling_size) {
			return tree;
		}

		// Randomly select a feature.
		let mut selected_feature_index = 0;
		if feature_values.len() > 1 {
			return tree;
		}

		// Get the value list to split on.

		// Randomly select a split value.
		let mut split_value_index = 0;

		// Create a tree node to hold the split value.

        tree
    }

    pub fn create(&self) {
    	for _i in 0..self.num_trees_to_create {
            let tree = self.create_tree(self.feature_values, 0);
            if tree.len() > 0 {
            }
        }
    }

    fn score_tree(&self, sample: Sample, tree: NodeLink) -> f64 {
        let mut depth = 0.0;
        let mut current_node = tree;
        let mut done = false;

        while !done {
            let mut found_feature = false;
            let current_node_deref = current_node.deref();
            let node_feature_name = current_node_deref.get_feature_name();
            let features = sample.features();

            for feature in features {
                let feature_name = feature.get_name();

                if feature_name == node_feature_name {
					if feature.get_value() < current_node_deref.split_value() {
						current_node = current_node_deref.get_left_subtree();
                    } else {
						current_node = current_node_deref.get_right_subtree();
                    }
                    found_feature = false;
                }
            }
        }
        depth
    }

    pub fn score(&self, sample: Sample) -> f64 {
        let mut score = 0.0;

        if self.trees.len() > 0 {
            for tree in self.trees {
                score += self.score_tree(sample, tree);
            }
            score /= self.trees.len() as f64;
        }
        score
    }
}
<commit_msg>Backup commit.<commit_after>//	MIT License
//
//  Copyright © 2017 Michael J Simms. All rights reserved.
//
//	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::collections::HashSet;
use std::collections::HashMap;

/// Each feature has a name and value.
pub struct Feature {
    name: String,
    value: u64,
}

impl Feature {
    pub fn new (name: &str, value: u64) -> Feature {
        Feature { name: name.to_string(), value: value }
    }

    pub fn set_name(&mut self, name: String) {
        self.name = name;
    }

    pub fn get_name(&self) -> String {
        self.name
    }

    pub fn set_value(&mut self, value: u64) {
        self.value = value;
    }

    pub fn get_value(&self) -> u64 {
        self.value
    }
}

pub type FeatureList = Vec<Feature>;
pub type Uint64Set = HashSet<u64>;
pub type FeatureNameToValuesMap<'a> = HashMap<&'a str, Uint64Set>;

/// This class represents a sample.
/// Each sample has a name and list of features.
pub struct Sample {
    name: String,
    features: FeatureList,
}

impl Sample {
    pub fn new (name: &str) -> Sample {
        Sample { name: name.to_string(), features: Sample::create_feature_list() }
    }

    fn create_feature_list() -> FeatureList {
        let mut v: FeatureList = vec![];
        v
    }

    pub fn add_features(&mut self, features: &mut FeatureList) {
        self.features.append(features);
    }

    pub fn add_feature(&mut self, feature: Feature) {
        self.features.push(feature);
    }

    pub fn features(&self) -> FeatureList {
        self.features
    }
}

pub type SampleList = Vec<Sample>;

/// Tree node, used internally.
struct Node {
    feature_name: String,
    left: NodeLink,
    right: NodeLink,
}

impl Node {
    pub fn new (feature_name: &str) -> Node {
        Node { feature_name: feature_name.to_string(), left: None, right: None }
    }

    fn get_feature_name(&self) -> String {
        self.feature_name
    }

	fn set_left_subtree(&mut self, subtree: NodeLink) {
		self.left = subtree;
	}

    fn get_left_subtree(&self) -> NodeLink {
        self.left
    }

	fn set_right_subtree(&mut self, subtree: NodeLink) {
		self.right = subtree;
	}

    fn get_right_subtree(&self) -> NodeLink {
        self.right
    }
}

pub type NodeLink = Option<Box<Node>>;
pub type NodeList = Vec<Box<Node>>;

/// Isolation Forest implementation.
pub struct Forest<'a> {
    feature_values: FeatureNameToValuesMap<'a>, // Lists each feature and maps it to all unique values in the training set
    trees: NodeList, // The decision trees that comprise the forest
    num_trees_to_create: u32, // The maximum number of trees to create
    sub_sampling_size: u32, // The maximum depth of a tree
}

impl<'a> Forest<'a> {
    pub fn new (num_trees_to_create: u32, sub_sampling_size: u32) -> Forest<'a> {
        Forest { num_trees_to_create: num_trees_to_create, sub_sampling_size: sub_sampling_size, trees: Forest::initialize_trees(), feature_values: Forest::create_feature_name_to_values_map() }
    }

    fn initialize_trees() -> NodeList {
        let mut v: NodeList = vec![];
        v
    }

    fn create_feature_name_to_values_map() -> FeatureNameToValuesMap<'a> {
        let mut m = HashMap::new();
        m
    }

    pub fn add_sample(&self, sample: Sample) {
		// Add each of this sample's features to the list of known features
		// with the corresponding set of unique values.
		let mut features = sample.features();
        for feature in &features {
            let mut found_feature = false;
        }
    }

    pub fn create_tree(&self, feature_values: FeatureNameToValuesMap<'a>, depth: u32) -> NodeLink {
		// Sanity check.
		if feature_values.len() <= 1 {
			return None;
		}

		// If we've exceeded the maximum desired depth, then stop.
		if (self.sub_sampling_size > 0) && (depth >= self.sub_sampling_size) {
			return None;
		}

		// Randomly select a feature.
		let mut selected_feature_index = 0;
		if feature_values.len() > 1 {
			return None;
		}

		// Get the value list to split on.

		// Randomly select a split value.
		let mut split_value_index = 0;

		// Create a tree node to hold the split value.
        let mut tree = Some(Box::new(Node::new("")));

        tree
    }

    pub fn create(&self) {
    	for _i in 0..self.num_trees_to_create {
            let tree = self.create_tree(self.feature_values, 0);
            if tree.len() > 0 {
            }
        }
    }

    fn score_tree(&self, sample: Sample, tree: NodeLink) -> f64 {
        let mut depth = 0.0;
        let mut current_node = tree;
        let mut done = false;

        while !done {
            let mut found_feature = false;
            let current_node_deref = current_node;
            let node_feature_name = current_node_deref.get_feature_name();
            let features = sample.features();

            for feature in features {
                let feature_name = feature.get_name();

                if feature_name == node_feature_name {
					if feature.get_value() < current_node_deref.split_value() {
						current_node = current_node_deref.get_left_subtree();
                    } else {
						current_node = current_node_deref.get_right_subtree();
                    }
                    found_feature = false;
                }
            }
        }
        depth
    }

    pub fn score(&self, sample: Sample) -> f64 {
        let mut score = 0.0;

        if self.trees.len() > 0 {
            for tree in self.trees {
                score += self.score_tree(sample, Some(tree));
            }
            score /= self.trees.len() as f64;
        }
        score
    }
}
<|endoftext|>