<commit_before>#![feature(test)]
#![feature(alloc)]
#![feature(heap_api)]
#[macro_use]
extern crate adapton ;

mod fib {
    const INPUT_SIZE:u64 = 20;
    const REPEAT_COUNT:u64 = 100;

    #[cfg(test)]
    mod rust {
        use super::INPUT_SIZE;
        use super::REPEAT_COUNT;

        extern crate test;
        use self::test::Bencher;

        pub fn fib (x:u64) -> u64 { test::black_box (
            match x {
                0 => 0,
                1 => 1,
                x => fib(x-1) + fib(x-2)
            })
        }

        pub fn fib_repeat (x:u64, n:u64) -> u64 {
            for _ in 1..(n-1) {
                test::black_box(fib(x));
            }
            test::black_box(fib(x))
        }

        #[test]
        fn it_works() {
            assert_eq!(5 as u64, fib(5));
        }

        #[bench]
        fn bench_fib(b: &mut Bencher) {
            b.iter(|| test::black_box(fib(INPUT_SIZE)));
        }

        #[bench]
        fn bench_fib_repeat(b: &mut Bencher) {
            b.iter(|| test::black_box(fib_repeat(INPUT_SIZE, REPEAT_COUNT)));
        }
    }

    #[cfg(test)]
    mod adapton {
        mod fs {
            extern crate test;
            use self::test::Bencher;

            extern crate alloc;
            use std::rc::Rc;
            use adapton::macros::* ;
            use adapton::adapton_sigs::* ;
            //use adapton::adapton_state::* ;
            use adapton::naive::* ;
            use super::super::INPUT_SIZE;
            use super::super::REPEAT_COUNT;

            pub fn fib<A:Adapton> (st:&mut A, x:u64 ) -> u64 {
                match x {
                    0 => 0,
                    1 => 1,
                    x => { memo!(st, fib, x:x-1)
                           +
                           memo!(st, fib, x:x-2) }}
            }

            pub fn run_fib (x:u64) -> u64 {
                let mut st = &mut AdaptonFromScratch::new() ;
                memo!(st, fib, x:x )
            }

            pub fn run_fib_repeat (x:u64, n:u64) -> u64 {
                let mut st = &mut AdaptonFromScratch::new() ;
                for _ in 1..(n-1) {
                    memo!(st, fib, x:x );
                }
                memo!(st, fib, x:x )
            }

            #[test]
            fn it_works() {
                assert_eq!(5 as u64, run_fib(5));
            }

            #[bench]
            fn bench_fib(b: &mut Bencher) {
                b.iter(|| test::black_box(run_fib(INPUT_SIZE)));
            }

            //#[bench]
            //fn bench_fib_repeat(b: &mut Bencher) {
            //    b.iter(|| test::black_box(run_fib_repeat(INPUT_SIZE, REPEAT_COUNT)));
            //}

        }

        mod engine {
            extern crate test;
            use self::test::Bencher;

            extern crate alloc;
            use std::rc::Rc;
            use adapton::macros::* ;
            use adapton::adapton_sigs::* ;
            use adapton::engine::* ;
            //use adapton::naive::* ;
            use super::super::INPUT_SIZE;
            use super::super::REPEAT_COUNT;

            pub fn fib<A:Adapton> (st:&mut A, x:u64 ) -> u64 {
                match x {
                    0 => 0,
                    1 => 1,
                    x => { memo!(st, fib, x:x-1)
                           +
                           memo!(st, fib, x:x-2) }}
            }

            pub fn run_fib (x:u64) -> u64 {
                let mut st = &mut Engine::new() ;
                memo!(st, fib, x:x )
            }

            pub fn run_fib_repeat (x:u64, n:u64) -> u64 {
                let mut st = &mut Engine::new() ;
                for _ in 1..(n-1) {
                    memo!(st, fib, x:x );
                }
                memo!(st, fib, x:x )
            }

            #[test]
            fn it_works() {
                assert_eq!(5 as u64, run_fib(5));
            }

            #[bench]
            fn bench_fib(b: &mut Bencher) {
                b.iter(|| test::black_box(run_fib(INPUT_SIZE)));
            }

            #[bench]
            fn bench_fib_repeat(b: &mut Bencher) {
                b.iter(|| test::black_box(run_fib_repeat(INPUT_SIZE, REPEAT_COUNT)));
            }
        }
    }
}

mod fact {
    const INPUT_SIZE:u64 = 100;
    const REPEAT_COUNT:u64 = 100;

    #[cfg(test)]
    mod no_caching {
        use super::INPUT_SIZE;
        use super::REPEAT_COUNT;

        extern crate test;
        use self::test::Bencher;

        pub fn fact (x:u64) -> u64 {
            if x == 0 { 1 } else { test::black_box(x) * fact(x-1) }
        }

        pub fn fact_repeat (x:u64, n:u64) -> u64 {
            for _ in 1..(n-1) {
                test::black_box(fact(x));
            }
            fact(x)
        }

        #[test]
        fn it_works() {
            assert_eq!(120 as u64, fact(5));
        }

        #[bench]
        fn bench_fact(b: &mut Bencher) {
            b.iter(|| test::black_box(fact(INPUT_SIZE)));
        }

        #[bench]
        fn bench_fact_repeat(b: &mut Bencher) {
            b.iter(|| test::black_box(fact_repeat(INPUT_SIZE, REPEAT_COUNT)));
        }
    }

    #[cfg(test)]
    mod pure_caching {
        use super::INPUT_SIZE;
        use super::REPEAT_COUNT;

        extern crate test;
        use self::test::Bencher;

        use std::rc::Rc;

        use adapton::macros::* ;
        use adapton::adapton_sigs::* ;
        use adapton::engine::* ;

        pub fn fact<A:Adapton> (st:&mut A, x:u64 ) -> u64 {
            if x == 0 { 1 } else { x * (memo!(st, fact, x:x-1 )) }
        }

        pub fn run_fact (x:u64) -> u64 {
            let mut st = &mut (Engine::new()) ;
            memo!(st, fact, x:x )
        }

        pub fn run_fact_repeat (x:u64, n:u64) -> u64 {
            let mut st = &mut (Engine::new()) ;
            for _ in 1..(n-1) {
                memo!(st, fact, x:x );
            }
            memo!(st, fact, x:x )
        }

        #[test]
        fn it_works() {
            assert_eq!(120 as u64, run_fact(5));
        }

        #[bench]
        fn bench_fact(b: &mut Bencher) {
            b.iter(|| test::black_box(run_fact(INPUT_SIZE)));
        }

        #[bench]
        fn bench_fact_repeat(b: &mut Bencher) {
            b.iter(|| test::black_box(run_fact_repeat(INPUT_SIZE, REPEAT_COUNT)));
        }
    }
}

mod hourglass {
    //const INPUT_ARRAY:Vec<u64> = vec![2; 64];
    const REPEAT_COUNT:u64 = 100;

    #[cfg(test)]
    mod eager_ids {
        //use super::INPUT_ARRAY;
        use super::REPEAT_COUNT;

        extern crate test;
        use self::test::Bencher;

        use std::rc::Rc;

        use adapton::macros::* ;
        use adapton::adapton_sigs::* ;
        //use adapton::naive::* ;
        use adapton::engine::* ;
        use adapton::collection::* ;

        // Thunks needs to *own* the arguments we give them.
        fn ident<A:Adapton,T>(st:&mut A, x:T) -> T {x}
        fn depend_mult<A:Adapton>(st:&mut A, x: Art<u64,A::Loc>,y: Art<u64,A::Loc>) -> u64 {
            st.force(&x) * st.force(&y)
        }
        fn depend_add<A:Adapton>(st:&mut A, x: Art<u64,A::Loc>,y: Art<u64,A::Loc>) -> u64 {
            //println!("depend_add:({:?},{:?})", x, y);
            st.force(&x) + st.force(&y)
        }

        pub fn hourglass<A:Adapton> (st:&mut A) -> u64 {
            let cells = vec![2;64];
            let mut nodes = vec![];
            for i in 0..64 {
                nodes.push(thunk!(st, ident, x:cells[i]));
            }
            let mut item_num = 0;
            loop {
                if nodes.len() == 126 { break; }
                let first = nodes[item_num].clone();
                let second = nodes[item_num+1].clone();
                nodes.push(thunk!(st, depend_add, x:first, y:second));
                //println!("{} --> {}, {}", nodes.len()-1, item_num, item_num+1);
                if item_num < 122 { item_num += 2 } else { item_num += 1 }
            }
            let thk = &nodes[nodes.len()-1];
            //println!("past checkpoint");
            st.force(thk)
        }

        pub fn run_hourglass () -> u64 {
            let mut st = &mut (Engine::new());
            let res = hourglass(st);
            //assert!(res == );
            res
        }

        pub fn run_hourglass_repeat (n:u64) -> u64 {
            let mut st = &mut (Engine::new());
            for _ in 1..(n-1) {
                test::black_box(hourglass(st));
            }
            hourglass(st)
        }

        // output value uncertain, test is changing
        // #[test]
        // fn it_works() {
        //     assert_eq!(2 as u64, run_hourglass());
        // }

        #[bench]
        fn bench_hourglass(b: &mut Bencher) {
            b.iter(|| test::black_box(run_hourglass()));
        }

        // Rewrite this as multiple changes in the input list
        // #[bench]
        // fn bench_hourglass_repeat(b: &mut Bencher) {
        //     b.iter(|| test::black_box(run_hourglass_repeat(REPEAT_COUNT)));
        // }
    }
}
<commit_msg>commented out obsolete benches code; it needs to be revised for new API; not a high priority right now<commit_after>// #![feature(test)]
// #![feature(alloc)]
// #![feature(heap_api)]
// #[macro_use]
// extern crate adapton ;

// mod fib {
//     const INPUT_SIZE:u64 = 20;
//     const REPEAT_COUNT:u64 = 100;

//     #[cfg(test)]
//     mod rust {
//         use super::INPUT_SIZE;
//         use super::REPEAT_COUNT;

//         extern crate test;
//         use self::test::Bencher;

//         pub fn fib (x:u64) -> u64 { test::black_box (
//             match x {
//                 0 => 0,
//                 1 => 1,
//                 x => fib(x-1) + fib(x-2)
//             })
//         }

//         pub fn fib_repeat (x:u64, n:u64) -> u64 {
//             for _ in 1..(n-1) {
//                 test::black_box(fib(x));
//             }
//             test::black_box(fib(x))
//         }

//         #[test]
//         fn it_works() {
//             assert_eq!(5 as u64, fib(5));
//         }

//         #[bench]
//         fn bench_fib(b: &mut Bencher) {
//             b.iter(|| test::black_box(fib(INPUT_SIZE)));
//         }

//         #[bench]
//         fn bench_fib_repeat(b: &mut Bencher) {
//             b.iter(|| test::black_box(fib_repeat(INPUT_SIZE, REPEAT_COUNT)));
//         }
//     }

//     #[cfg(test)]
//     mod adapton {
//         mod fs {
//             extern crate test;
//             use self::test::Bencher;

//             extern crate alloc;
//             use std::rc::Rc;
//             use adapton::macros::* ;
//             use adapton::adapton_sigs::* ;
//             //use adapton::adapton_state::* ;
//             use adapton::naive::* ;
//             use super::super::INPUT_SIZE;
//             use super::super::REPEAT_COUNT;

//             pub fn fib<A:Adapton> (st:&mut A, x:u64 ) -> u64 {
//                 match x {
//                     0 => 0,
//                     1 => 1,
//                     x => { memo!(st, fib, x:x-1)
//                            +
//                            memo!(st, fib, x:x-2) }}
//             }

//             pub fn run_fib (x:u64) -> u64 {
//                 let mut st = &mut AdaptonFromScratch::new() ;
//                 memo!(st, fib, x:x )
//             }

//             pub fn run_fib_repeat (x:u64, n:u64) -> u64 {
//                 let mut st = &mut AdaptonFromScratch::new() ;
//                 for _ in 1..(n-1) {
//                     memo!(st, fib, x:x );
//                 }
//                 memo!(st, fib, x:x )
//             }

//             #[test]
//             fn it_works() {
//                 assert_eq!(5 as u64, run_fib(5));
//             }

//             #[bench]
//             fn bench_fib(b: &mut Bencher) {
//                 b.iter(|| test::black_box(run_fib(INPUT_SIZE)));
//             }

//             //#[bench]
//             //fn bench_fib_repeat(b: &mut Bencher) {
//             //    b.iter(|| test::black_box(run_fib_repeat(INPUT_SIZE, REPEAT_COUNT)));
//             //}

//         }

//         mod engine {
//             extern crate test;
//             use self::test::Bencher;

//             extern crate alloc;
//             use std::rc::Rc;
//             use adapton::macros::* ;
//             use adapton::adapton_sigs::* ;
//             use adapton::engine::* ;
//             //use adapton::naive::* ;
//             use super::super::INPUT_SIZE;
//             use super::super::REPEAT_COUNT;

//             pub fn fib<A:Adapton> (st:&mut A, x:u64 ) -> u64 {
//                 match x {
//                     0 => 0,
//                     1 => 1,
//                     x => { memo!(st, fib, x:x-1)
//                            +
//                            memo!(st, fib, x:x-2) }}
//             }

//             pub fn run_fib (x:u64) -> u64 {
//                 let mut st = &mut Engine::new() ;
//                 memo!(st, fib, x:x )
//             }

//             pub fn run_fib_repeat (x:u64, n:u64) -> u64 {
//                 let mut st = &mut Engine::new() ;
//                 for _ in 1..(n-1) {
//                     memo!(st, fib, x:x );
//                 }
//                 memo!(st, fib, x:x )
//             }

//             #[test]
//             fn it_works() {
//                 assert_eq!(5 as u64, run_fib(5));
//             }

//             #[bench]
//             fn bench_fib(b: &mut Bencher) {
//                 b.iter(|| test::black_box(run_fib(INPUT_SIZE)));
//             }

//             #[bench]
//             fn bench_fib_repeat(b: &mut Bencher) {
//                 b.iter(|| test::black_box(run_fib_repeat(INPUT_SIZE, REPEAT_COUNT)));
//             }
//         }
//     }
// }

// mod fact {
//     const INPUT_SIZE:u64 = 100;
//     const REPEAT_COUNT:u64 = 100;

//     #[cfg(test)]
//     mod no_caching {
//         use super::INPUT_SIZE;
//         use super::REPEAT_COUNT;

//         extern crate test;
//         use self::test::Bencher;

//         pub fn fact (x:u64) -> u64 {
//             if x == 0 { 1 } else { test::black_box(x) * fact(x-1) }
//         }

//         pub fn fact_repeat (x:u64, n:u64) -> u64 {
//             for _ in 1..(n-1) {
//                 test::black_box(fact(x));
//             }
//             fact(x)
//         }

//         #[test]
//         fn it_works() {
//             assert_eq!(120 as u64, fact(5));
//         }

//         #[bench]
//         fn bench_fact(b: &mut Bencher) {
//             b.iter(|| test::black_box(fact(INPUT_SIZE)));
//         }

//         #[bench]
//         fn bench_fact_repeat(b: &mut Bencher) {
//             b.iter(|| test::black_box(fact_repeat(INPUT_SIZE, REPEAT_COUNT)));
//         }
//     }

//     #[cfg(test)]
//     mod pure_caching {
//         use super::INPUT_SIZE;
//         use super::REPEAT_COUNT;

//         extern crate test;
//         use self::test::Bencher;

//         use std::rc::Rc;

//         use adapton::macros::* ;
//         use adapton::adapton_sigs::* ;
//         use adapton::engine::* ;

//         pub fn fact<A:Adapton> (st:&mut A, x:u64 ) -> u64 {
//             if x == 0 { 1 } else { x * (memo!(st, fact, x:x-1 )) }
//         }

//         pub fn run_fact (x:u64) -> u64 {
//             let mut st = &mut (Engine::new()) ;
//             memo!(st, fact, x:x )
//         }

//         pub fn run_fact_repeat (x:u64, n:u64) -> u64 {
//             let mut st = &mut (Engine::new()) ;
//             for _ in 1..(n-1) {
//                 memo!(st, fact, x:x );
//             }
//             memo!(st, fact, x:x )
//         }

//         #[test]
//         fn it_works() {
//             assert_eq!(120 as u64, run_fact(5));
//         }

//         #[bench]
//         fn bench_fact(b: &mut Bencher) {
//             b.iter(|| test::black_box(run_fact(INPUT_SIZE)));
//         }

//         #[bench]
//         fn bench_fact_repeat(b: &mut Bencher) {
//             b.iter(|| test::black_box(run_fact_repeat(INPUT_SIZE, REPEAT_COUNT)));
//         }
//     }
// }

// mod hourglass {
//     //const INPUT_ARRAY:Vec<u64> = vec![2; 64];
//     const REPEAT_COUNT:u64 = 100;

//     #[cfg(test)]
//     mod eager_ids {
//         //use super::INPUT_ARRAY;
//         use super::REPEAT_COUNT;

//         extern crate test;
//         use self::test::Bencher;

//         use std::rc::Rc;

//         use adapton::macros::* ;
//         use adapton::adapton_sigs::* ;
//         //use adapton::naive::* ;
//         use adapton::engine::* ;
//         use adapton::collection::* ;

//         // Thunks needs to *own* the arguments we give them.
//         fn ident<A:Adapton,T>(st:&mut A, x:T) -> T {x}
//         fn depend_mult<A:Adapton>(st:&mut A, x: Art<u64,A::Loc>,y: Art<u64,A::Loc>) -> u64 {
//             st.force(&x) * st.force(&y)
//         }
//         fn depend_add<A:Adapton>(st:&mut A, x: Art<u64,A::Loc>,y: Art<u64,A::Loc>) -> u64 {
//             //println!("depend_add:({:?},{:?})", x, y);
//             st.force(&x) + st.force(&y)
//         }

//         pub fn hourglass<A:Adapton> (st:&mut A) -> u64 {
//             let cells = vec![2;64];
//             let mut nodes = vec![];
//             for i in 0..64 {
//                 nodes.push(thunk!(st, ident, x:cells[i]));
//             }
//             let mut item_num = 0;
//             loop {
//                 if nodes.len() == 126 { break; }
//                 let first = nodes[item_num].clone();
//                 let second = nodes[item_num+1].clone();
//                 nodes.push(thunk!(st, depend_add, x:first, y:second));
//                 //println!("{} --> {}, {}", nodes.len()-1, item_num, item_num+1);
//                 if item_num < 122 { item_num += 2 } else { item_num += 1 }
//             }
//             let thk = &nodes[nodes.len()-1];
//             //println!("past checkpoint");
//             st.force(thk)
//         }

//         pub fn run_hourglass () -> u64 {
//             let mut st = &mut (Engine::new());
//             let res = hourglass(st);
//             //assert!(res == );
//             res
//         }

//         pub fn run_hourglass_repeat (n:u64) -> u64 {
//             let mut st = &mut (Engine::new());
//             for _ in 1..(n-1) {
//                 test::black_box(hourglass(st));
//             }
//             hourglass(st)
//         }

//         // output value uncertain, test is changing
//         // #[test]
//         // fn it_works() {
//         //     assert_eq!(2 as u64, run_hourglass());
//         // }

//         #[bench]
//         fn bench_hourglass(b: &mut Bencher) {
//             b.iter(|| test::black_box(run_hourglass()));
//         }

//         // Rewrite this as multiple changes in the input list
//         // #[bench]
//         // fn bench_hourglass_repeat(b: &mut Bencher) {
//         //     b.iter(|| test::black_box(run_hourglass_repeat(REPEAT_COUNT)));
//         // }
//     }
// }
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CSSRuleListBinding;
use dom::bindings::codegen::Bindings::CSSRuleListBinding::CSSRuleListMethods;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::js::{JS, MutNullableJS, Root};
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::csskeyframerule::CSSKeyframeRule;
use dom::cssrule::CSSRule;
use dom::cssstylesheet::CSSStyleSheet;
use dom::window::Window;
use dom_struct::dom_struct;
use std::sync::Arc;
use style::shared_lock::Locked;
use style::stylesheets::{CssRules, KeyframesRule, RulesMutateError};

#[allow(unsafe_code)]
unsafe_no_jsmanaged_fields!(RulesSource);

unsafe_no_jsmanaged_fields!(CssRules);

impl From<RulesMutateError> for Error {
    fn from(other: RulesMutateError) -> Self {
        match other {
            RulesMutateError::Syntax => Error::Syntax,
            RulesMutateError::IndexSize => Error::IndexSize,
            RulesMutateError::HierarchyRequest => Error::HierarchyRequest,
            RulesMutateError::InvalidState => Error::InvalidState,
        }
    }
}

#[dom_struct]
pub struct CSSRuleList {
    reflector_: Reflector,
    parent_stylesheet: JS<CSSStyleSheet>,
    #[ignore_heap_size_of = "Arc"]
    rules: RulesSource,
    dom_rules: DOMRefCell<Vec<MutNullableJS<CSSRule>>>
}

pub enum RulesSource {
    Rules(Arc<Locked<CssRules>>),
    Keyframes(Arc<Locked<KeyframesRule>>),
}

impl CSSRuleList {
    #[allow(unrooted_must_root)]
    pub fn new_inherited(parent_stylesheet: &CSSStyleSheet, rules: RulesSource) -> CSSRuleList {
        let guard = parent_stylesheet.shared_lock().read();
        let dom_rules = match rules {
            RulesSource::Rules(ref rules) => {
                rules.read_with(&guard).0.iter().map(|_| MutNullableJS::new(None)).collect()
            }
            RulesSource::Keyframes(ref rules) => {
                rules.read_with(&guard).keyframes.iter().map(|_| MutNullableJS::new(None)).collect()
            }
        };

        CSSRuleList {
            reflector_: Reflector::new(),
            parent_stylesheet: JS::from_ref(parent_stylesheet),
            rules: rules,
            dom_rules: DOMRefCell::new(dom_rules),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
               rules: RulesSource) -> Root<CSSRuleList> {
        reflect_dom_object(box CSSRuleList::new_inherited(parent_stylesheet, rules),
                           window,
                           CSSRuleListBinding::Wrap)
    }

    /// Should only be called for CssRules-backed rules. Use append_lazy_rule
    /// for keyframes-backed rules.
    pub fn insert_rule(&self, rule: &str, idx: u32, nested: bool) -> Fallible<u32> {
        let css_rules = if let RulesSource::Rules(ref rules) = self.rules {
            rules
        } else {
            panic!("Called insert_rule on non-CssRule-backed CSSRuleList");
        };

        let global = self.global();
        let window = global.as_window();
        let index = idx as usize;

        let parent_stylesheet = self.parent_stylesheet.style_stylesheet();
        let mut guard = parent_stylesheet.shared_lock.write();
        let new_rule = css_rules.write_with(&mut guard)
            .insert_rule(rule, parent_stylesheet, index, nested)?;

        let parent_stylesheet = &*self.parent_stylesheet;
        let dom_rule = CSSRule::new_specific(&window, parent_stylesheet, new_rule);
        self.dom_rules.borrow_mut().insert(index, MutNullableJS::new(Some(&*dom_rule)));
        Ok((idx))
    }

    // In case of a keyframe rule, index must be valid.
    pub fn remove_rule(&self, index: u32) -> ErrorResult {
        let index = index as usize;
        let mut guard = self.parent_stylesheet.shared_lock().write();

        match self.rules {
            RulesSource::Rules(ref css_rules) => {
                css_rules.write_with(&mut guard).remove_rule(index)?;
                let mut dom_rules = self.dom_rules.borrow_mut();
                dom_rules[index].get().map(|r| r.detach());
                dom_rules.remove(index);
                Ok(())
            }
            RulesSource::Keyframes(ref kf) => {
                // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-deleterule
                let mut dom_rules = self.dom_rules.borrow_mut();
                dom_rules[index].get().map(|r| r.detach());
                dom_rules.remove(index);
                kf.write_with(&mut guard).keyframes.remove(index);
                Ok(())
            }
        }
    }

    // Remove parent stylesheets from all children
    pub fn deparent_all(&self) {
        for rule in self.dom_rules.borrow().iter() {
            rule.get().map(|r| Root::upcast(r).deparent());
        }
    }

    pub fn item(&self, idx: u32) -> Option<Root<CSSRule>> {
        self.dom_rules.borrow().get(idx as usize).map(|rule| {
            rule.or_init(|| {
                let parent_stylesheet = &self.parent_stylesheet;
                let guard = parent_stylesheet.shared_lock().read();
                match self.rules {
                    RulesSource::Rules(ref rules) => {
                        CSSRule::new_specific(self.global().as_window(),
                                             parent_stylesheet,
                                             rules.read_with(&guard).0[idx as usize].clone())
                    }
                    RulesSource::Keyframes(ref rules) => {
                        Root::upcast(CSSKeyframeRule::new(self.global().as_window(),
                                                          parent_stylesheet,
                                                          rules.read_with(&guard)
                                                                .keyframes[idx as usize]
                                                                .clone()))
                    }
                }

            })
        })
    }

    /// Add a rule to the list of DOM rules. This list is lazy,
    /// so we just append a placeholder.
    ///
    /// Should only be called for keyframes-backed rules, use insert_rule
    /// for CssRules-backed rules
    pub fn append_lazy_dom_rule(&self) {
        if let RulesSource::Rules(..) = self.rules {
            panic!("Can only call append_lazy_rule with keyframes-backed CSSRules");
        }
        self.dom_rules.borrow_mut().push(MutNullableJS::new(None));
    }
}

impl CSSRuleListMethods for CSSRuleList {
    // https://drafts.csswg.org/cssom/#ref-for-dom-cssrulelist-item-1
    fn Item(&self, idx: u32) -> Option<Root<CSSRule>> {
        self.item(idx)
    }

    // https://drafts.csswg.org/cssom/#dom-cssrulelist-length
    fn Length(&self) -> u32 {
        self.dom_rules.borrow().len() as u32
    }

    // check-tidy: no specs after this line
    fn IndexedGetter(&self, index: u32) -> Option<Root<CSSRule>> {
        self.Item(index)
    }
}

<commit_msg>Fix another deadlock<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::CSSRuleListBinding;
use dom::bindings::codegen::Bindings::CSSRuleListBinding::CSSRuleListMethods;
use dom::bindings::error::{Error, ErrorResult, Fallible};
use dom::bindings::js::{JS, MutNullableJS, Root};
use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::csskeyframerule::CSSKeyframeRule;
use dom::cssrule::CSSRule;
use dom::cssstylesheet::CSSStyleSheet;
use dom::window::Window;
use dom_struct::dom_struct;
use std::sync::Arc;
use style::shared_lock::Locked;
use style::stylesheets::{CssRules, KeyframesRule, RulesMutateError};

#[allow(unsafe_code)]
unsafe_no_jsmanaged_fields!(RulesSource);

unsafe_no_jsmanaged_fields!(CssRules);

impl From<RulesMutateError> for Error {
    fn from(other: RulesMutateError) -> Self {
        match other {
            RulesMutateError::Syntax => Error::Syntax,
            RulesMutateError::IndexSize => Error::IndexSize,
            RulesMutateError::HierarchyRequest => Error::HierarchyRequest,
            RulesMutateError::InvalidState => Error::InvalidState,
        }
    }
}

#[dom_struct]
pub struct CSSRuleList {
    reflector_: Reflector,
    parent_stylesheet: JS<CSSStyleSheet>,
    #[ignore_heap_size_of = "Arc"]
    rules: RulesSource,
    dom_rules: DOMRefCell<Vec<MutNullableJS<CSSRule>>>
}

pub enum RulesSource {
    Rules(Arc<Locked<CssRules>>),
    Keyframes(Arc<Locked<KeyframesRule>>),
}

impl CSSRuleList {
    #[allow(unrooted_must_root)]
    pub fn new_inherited(parent_stylesheet: &CSSStyleSheet, rules: RulesSource) -> CSSRuleList {
        let guard = parent_stylesheet.shared_lock().read();
        let dom_rules = match rules {
            RulesSource::Rules(ref rules) => {
                rules.read_with(&guard).0.iter().map(|_| MutNullableJS::new(None)).collect()
            }
            RulesSource::Keyframes(ref rules) => {
                rules.read_with(&guard).keyframes.iter().map(|_| MutNullableJS::new(None)).collect()
            }
        };

        CSSRuleList {
            reflector_: Reflector::new(),
            parent_stylesheet: JS::from_ref(parent_stylesheet),
            rules: rules,
            dom_rules: DOMRefCell::new(dom_rules),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet,
               rules: RulesSource) -> Root<CSSRuleList> {
        reflect_dom_object(box CSSRuleList::new_inherited(parent_stylesheet, rules),
                           window,
                           CSSRuleListBinding::Wrap)
    }

    /// Should only be called for CssRules-backed rules. Use append_lazy_rule
    /// for keyframes-backed rules.
    pub fn insert_rule(&self, rule: &str, idx: u32, nested: bool) -> Fallible<u32> {
        let css_rules = if let RulesSource::Rules(ref rules) = self.rules {
            rules
        } else {
            panic!("Called insert_rule on non-CssRule-backed CSSRuleList");
        };

        let global = self.global();
        let window = global.as_window();
        let index = idx as usize;

        let parent_stylesheet = self.parent_stylesheet.style_stylesheet();
        let new_rule = {
            let mut guard = parent_stylesheet.shared_lock.write();
            css_rules.write_with(&mut guard).insert_rule(rule, parent_stylesheet, index, nested)?
            // Drop `guard` here,
            // CSSRule::new_specific re-acquires the lock for @support and @media.
        };

        let parent_stylesheet = &*self.parent_stylesheet;
        let dom_rule = CSSRule::new_specific(&window, parent_stylesheet, new_rule);
        self.dom_rules.borrow_mut().insert(index, MutNullableJS::new(Some(&*dom_rule)));
        Ok((idx))
    }

    // In case of a keyframe rule, index must be valid.
    pub fn remove_rule(&self, index: u32) -> ErrorResult {
        let index = index as usize;
        let mut guard = self.parent_stylesheet.shared_lock().write();

        match self.rules {
            RulesSource::Rules(ref css_rules) => {
                css_rules.write_with(&mut guard).remove_rule(index)?;
                let mut dom_rules = self.dom_rules.borrow_mut();
                dom_rules[index].get().map(|r| r.detach());
                dom_rules.remove(index);
                Ok(())
            }
            RulesSource::Keyframes(ref kf) => {
                // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-deleterule
                let mut dom_rules = self.dom_rules.borrow_mut();
                dom_rules[index].get().map(|r| r.detach());
                dom_rules.remove(index);
                kf.write_with(&mut guard).keyframes.remove(index);
                Ok(())
            }
        }
    }

    // Remove parent stylesheets from all children
    pub fn deparent_all(&self) {
        for rule in self.dom_rules.borrow().iter() {
            rule.get().map(|r| Root::upcast(r).deparent());
        }
    }

    pub fn item(&self, idx: u32) -> Option<Root<CSSRule>> {
        self.dom_rules.borrow().get(idx as usize).map(|rule| {
            rule.or_init(|| {
                let parent_stylesheet = &self.parent_stylesheet;
                let guard = parent_stylesheet.shared_lock().read();
                match self.rules {
                    RulesSource::Rules(ref rules) => {
                        CSSRule::new_specific(self.global().as_window(),
                                             parent_stylesheet,
                                             rules.read_with(&guard).0[idx as usize].clone())
                    }
                    RulesSource::Keyframes(ref rules) => {
                        Root::upcast(CSSKeyframeRule::new(self.global().as_window(),
                                                          parent_stylesheet,
                                                          rules.read_with(&guard)
                                                                .keyframes[idx as usize]
                                                                .clone()))
                    }
                }

            })
        })
    }

    /// Add a rule to the list of DOM rules. This list is lazy,
    /// so we just append a placeholder.
    ///
    /// Should only be called for keyframes-backed rules, use insert_rule
    /// for CssRules-backed rules
    pub fn append_lazy_dom_rule(&self) {
        if let RulesSource::Rules(..) = self.rules {
            panic!("Can only call append_lazy_rule with keyframes-backed CSSRules");
        }
        self.dom_rules.borrow_mut().push(MutNullableJS::new(None));
    }
}

impl CSSRuleListMethods for CSSRuleList {
    // https://drafts.csswg.org/cssom/#ref-for-dom-cssrulelist-item-1
    fn Item(&self, idx: u32) -> Option<Root<CSSRule>> {
        self.item(idx)
    }

    // https://drafts.csswg.org/cssom/#dom-cssrulelist-length
    fn Length(&self) -> u32 {
        self.dom_rules.borrow().len() as u32
    }

    // check-tidy: no specs after this line
    fn IndexedGetter(&self, index: u32) -> Option<Root<CSSRule>> {
        self.Item(index)
    }
}

<|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(missing_docs)]
#![unstable(feature = "core")]

//! Contains struct definitions for the layout of compiler built-in types.
//!
//! They can be used as targets of transmutes in unsafe code for manipulating
//! the raw representations directly.
//!
//! Their definition should always match the ABI defined in `rustc::back::abi`.

use mem;

/// The representation of a slice like `&[T]`.
///
/// This struct is guaranteed to have the layout of types like `&[T]`,
/// `&str`, and `Box<[T]>`, but is not the type of such slices
/// (e.g. the fields are not directly accessible on a `&[T]`) nor does
/// it control that layout (changing the definition will not change
/// the layout of a `&[T]`). It is only designed to be used by unsafe
/// code that needs to manipulate the low-level details.
///
/// However, it is not recommended to use this type for such code,
/// since there are alternatives which may be safer:
///
/// - Creating a slice from a data pointer and length can be done with
///   `std::slice::from_raw_parts` or `std::slice::from_raw_parts_mut`
///   instead of `std::mem::transmute`ing a value of type `Slice`.
/// - Extracting the data pointer and length from a slice can be
///   performed with the `as_ptr` (or `as_mut_ptr`) and `len`
///   methods.
///
/// If one does decide to convert a slice value to a `Slice`, the
/// `Repr` trait in this module provides a method for a safe
/// conversion from `&[T]` (and `&str`) to a `Slice`, more type-safe
/// than a call to `transmute`.
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::raw::{self, Repr};
///
/// let slice: &[u16] = &[1, 2, 3, 4];
///
/// let repr: raw::Slice<u16> = slice.repr();
/// println!("data pointer = {:?}, length = {}", repr.data, repr.len);
/// ```
#[repr(C)]
pub struct Slice<T> {
    pub data: *const T,
    pub len: usize,
}

impl<T> Copy for Slice<T> {}
impl<T> Clone for Slice<T> {
    fn clone(&self) -> Slice<T> { *self }
}

/// The representation of a trait object like `&SomeTrait`.
///
/// This struct has the same layout as types like `&SomeTrait` and
/// `Box<AnotherTrait>`. The [Static and Dynamic Dispatch chapter of the
/// Book][moreinfo] contains more details about the precise nature of
/// these internals.
///
/// [moreinfo]: ../../book/static-and-dynamic-dispatch.html#representation
///
/// `TraitObject` is guaranteed to match layouts, but it is not the
/// type of trait objects (e.g. the fields are not directly accessible
/// on a `&SomeTrait`) nor does it control that layout (changing the
/// definition will not change the layout of a `&SometTrait`). It is
/// only designed to be used by unsafe code that needs to manipulate
/// the low-level details.
///
/// There is no `Repr` implementation for `TraitObject` because there
/// is no way to refer to all trait objects generically, so the only
/// way to create values of this type is with functions like
/// `std::mem::transmute`. Similarly, the only way to create a true
/// trait object from a `TraitObject` value is with `transmute`.
///
/// Synthesizing a trait object with mismatched types—one where the
/// vtable does not correspond to the type of the value to which the
/// data pointer points—is highly likely to lead to undefined
/// behaviour.
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::mem;
/// use std::raw;
///
/// // an example trait
/// trait Foo {
///     fn bar(&self) -> i32;
/// }
/// impl Foo for i32 {
///     fn bar(&self) -> i32 {
///          *self + 1
///     }
/// }
///
/// let value: i32 = 123;
///
/// // let the compiler make a trait object
/// let object: &Foo = &value;
///
/// // look at the raw representation
/// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
///
/// // the data pointer is the address of `value`
/// assert_eq!(raw_object.data as *const i32, &value as *const _);
///
///
/// let other_value: i32 = 456;
///
/// // construct a new object, pointing to a different `i32`, being
/// // careful to use the `i32` vtable from `object`
/// let synthesized: &Foo = unsafe {
///      mem::transmute(raw::TraitObject {
///          data: &other_value as *const _ as *mut (),
///          vtable: raw_object.vtable
///      })
/// };
///
/// // it should work just like we constructed a trait object out of
/// // `other_value` directly
/// assert_eq!(synthesized.bar(), 457);
/// ```
#[repr(C)]
#[derive(Copy, Clone)]
pub struct TraitObject {
    pub data: *mut (),
    pub vtable: *mut (),
}

/// This trait is meant to map equivalences between raw structs and their
/// corresponding rust values.
pub unsafe trait Repr<T> {
    /// This function "unwraps" a rust value (without consuming it) into its raw
    /// struct representation. This can be used to read/write different values
    /// for the struct. This is a safe method because by default it does not
    /// enable write-access to the fields of the return value in safe code.
    #[inline]
    fn repr(&self) -> T { unsafe { mem::transmute_copy(&self) } }
}

unsafe impl<T> Repr<Slice<T>> for [T] {}
unsafe impl Repr<Slice<u8>> for str {}
<commit_msg>Missing imports<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![allow(missing_docs)]
#![unstable(feature = "core")]

//! Contains struct definitions for the layout of compiler built-in types.
//!
//! They can be used as targets of transmutes in unsafe code for manipulating
//! the raw representations directly.
//!
//! Their definition should always match the ABI defined in `rustc::back::abi`.

use clone::Clone;
use marker::Copy;
use mem;

/// The representation of a slice like `&[T]`.
///
/// This struct is guaranteed to have the layout of types like `&[T]`,
/// `&str`, and `Box<[T]>`, but is not the type of such slices
/// (e.g. the fields are not directly accessible on a `&[T]`) nor does
/// it control that layout (changing the definition will not change
/// the layout of a `&[T]`). It is only designed to be used by unsafe
/// code that needs to manipulate the low-level details.
///
/// However, it is not recommended to use this type for such code,
/// since there are alternatives which may be safer:
///
/// - Creating a slice from a data pointer and length can be done with
///   `std::slice::from_raw_parts` or `std::slice::from_raw_parts_mut`
///   instead of `std::mem::transmute`ing a value of type `Slice`.
/// - Extracting the data pointer and length from a slice can be
///   performed with the `as_ptr` (or `as_mut_ptr`) and `len`
///   methods.
///
/// If one does decide to convert a slice value to a `Slice`, the
/// `Repr` trait in this module provides a method for a safe
/// conversion from `&[T]` (and `&str`) to a `Slice`, more type-safe
/// than a call to `transmute`.
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::raw::{self, Repr};
///
/// let slice: &[u16] = &[1, 2, 3, 4];
///
/// let repr: raw::Slice<u16> = slice.repr();
/// println!("data pointer = {:?}, length = {}", repr.data, repr.len);
/// ```
#[repr(C)]
pub struct Slice<T> {
    pub data: *const T,
    pub len: usize,
}

impl<T> Copy for Slice<T> {}
impl<T> Clone for Slice<T> {
    fn clone(&self) -> Slice<T> { *self }
}

/// The representation of a trait object like `&SomeTrait`.
///
/// This struct has the same layout as types like `&SomeTrait` and
/// `Box<AnotherTrait>`. The [Static and Dynamic Dispatch chapter of the
/// Book][moreinfo] contains more details about the precise nature of
/// these internals.
///
/// [moreinfo]: ../../book/static-and-dynamic-dispatch.html#representation
///
/// `TraitObject` is guaranteed to match layouts, but it is not the
/// type of trait objects (e.g. the fields are not directly accessible
/// on a `&SomeTrait`) nor does it control that layout (changing the
/// definition will not change the layout of a `&SometTrait`). It is
/// only designed to be used by unsafe code that needs to manipulate
/// the low-level details.
///
/// There is no `Repr` implementation for `TraitObject` because there
/// is no way to refer to all trait objects generically, so the only
/// way to create values of this type is with functions like
/// `std::mem::transmute`. Similarly, the only way to create a true
/// trait object from a `TraitObject` value is with `transmute`.
///
/// Synthesizing a trait object with mismatched types—one where the
/// vtable does not correspond to the type of the value to which the
/// data pointer points—is highly likely to lead to undefined
/// behaviour.
///
/// # Examples
///
/// ```
/// # #![feature(core)]
/// use std::mem;
/// use std::raw;
///
/// // an example trait
/// trait Foo {
///     fn bar(&self) -> i32;
/// }
/// impl Foo for i32 {
///     fn bar(&self) -> i32 {
///          *self + 1
///     }
/// }
///
/// let value: i32 = 123;
///
/// // let the compiler make a trait object
/// let object: &Foo = &value;
///
/// // look at the raw representation
/// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
///
/// // the data pointer is the address of `value`
/// assert_eq!(raw_object.data as *const i32, &value as *const _);
///
///
/// let other_value: i32 = 456;
///
/// // construct a new object, pointing to a different `i32`, being
/// // careful to use the `i32` vtable from `object`
/// let synthesized: &Foo = unsafe {
///      mem::transmute(raw::TraitObject {
///          data: &other_value as *const _ as *mut (),
///          vtable: raw_object.vtable
///      })
/// };
///
/// // it should work just like we constructed a trait object out of
/// // `other_value` directly
/// assert_eq!(synthesized.bar(), 457);
/// ```
#[repr(C)]
#[derive(Copy, Clone)]
pub struct TraitObject {
    pub data: *mut (),
    pub vtable: *mut (),
}

/// This trait is meant to map equivalences between raw structs and their
/// corresponding rust values.
pub unsafe trait Repr<T> {
    /// This function "unwraps" a rust value (without consuming it) into its raw
    /// struct representation. This can be used to read/write different values
    /// for the struct. This is a safe method because by default it does not
    /// enable write-access to the fields of the return value in safe code.
    #[inline]
    fn repr(&self) -> T { unsafe { mem::transmute_copy(&self) } }
}

unsafe impl<T> Repr<Slice<T>> for [T] {}
unsafe impl Repr<Slice<u8>> for str {}
<|endoftext|>


<commit_before>// Support code for rustc's built in test runner generator. Currently,
// none of this is meant for users. It is intended to support the
// simplest interface possible for representing and running tests
// while providing a base that other test frameworks may build off of.

import result::{ok, err};

export test_name;
export test_fn;
export default_test_fn;
export test_desc;
export test_main;
export test_result;
export test_opts;
export tr_ok;
export tr_failed;
export tr_ignored;
export run_tests_console;
export run_tests_console_;
export run_test;
export filter_tests;
export parse_opts;
export test_to_task;
export default_test_to_task;
export configure_test_task;
export joinable;

#[abi = "cdecl"]
native mod rustrt {
    fn sched_threads() -> uint;
}

// FIXME Kludge to work around issue #1494 . Simply import io::writer_util
// after the next snapshot.
impl writer_util for io::writer {
    fn write_str(s: str) { self.write(str::bytes(s)); }
    fn write_line(s: str) { self.write(str::bytes(s + "\n")); }
}

// The name of a test. By convention this follows the rules for rust
// paths; i.e. it should be a series of identifiers seperated by double
// colons. This way if some test runner wants to arrange the tests
// hierarchically it may.
type test_name = str;

// A function that runs a test. If the function returns successfully,
// the test succeeds; if the function fails then the test fails. We
// may need to come up with a more clever definition of test in order
// to support isolation of tests into tasks.
type test_fn<T> = T;

type default_test_fn = test_fn<fn~()>;

// The definition of a single test. A test runner will run a list of
// these.
type test_desc<T> = {
    name: test_name,
    fn: test_fn<T>,
    ignore: bool,
    should_fail: bool
};

// The default console test runner. It accepts the command line
// arguments and a vector of test_descs (generated at compile time).
fn test_main(args: [str], tests: [test_desc<default_test_fn>]) {
    check (vec::is_not_empty(args));
    let opts =
        alt parse_opts(args) {
          either::left(o) { o }
          either::right(m) { fail m }
        };
    if !run_tests_console(opts, tests) { fail "Some tests failed"; }
}

type test_opts = {filter: option::t<str>, run_ignored: bool};

type opt_res = either::t<test_opts, str>;

// Parses command line arguments into test options
fn parse_opts(args: [str]) : vec::is_not_empty(args) -> opt_res {

    let args_ = vec::tail(args);
    let opts = [getopts::optflag("ignored")];
    let match =
        alt getopts::getopts(args_, opts) {
          ok(m) { m }
          err(f) { ret either::right(getopts::fail_str(f)) }
        };

    let filter =
        if vec::len(match.free) > 0u {
            option::some(match.free[0])
        } else { option::none };

    let run_ignored = getopts::opt_present(match, "ignored");

    let test_opts = {filter: filter, run_ignored: run_ignored};

    ret either::left(test_opts);
}

tag test_result { tr_ok; tr_failed; tr_ignored; }

type joinable = (task::task, comm::port<task::task_notification>);

// To get isolation and concurrency tests have to be run in their own tasks.
// In cases where test functions are closures it is not ok to just dump them
// into a task and run them, so this transformation gives the caller a chance
// to create the test task.
type test_to_task<T> = fn@(test_fn<T>) -> joinable;

// A simple console test runner
fn run_tests_console(opts: test_opts,
                         tests: [test_desc<default_test_fn>]) -> bool {
    run_tests_console_(opts, tests, default_test_to_task)
}

fn run_tests_console_<T: copy>(opts: test_opts, tests: [test_desc<T>],
                              to_task: test_to_task<T>) -> bool {

    type test_state =
        @{out: io::writer,
          use_color: bool,
          mutable total: uint,
          mutable passed: uint,
          mutable failed: uint,
          mutable ignored: uint,
          mutable failures: [test_desc<T>]};

    fn callback<T: copy>(event: testevent<T>, st: test_state) {
        alt event {
          te_filtered(filtered_tests) {
            st.total = vec::len(filtered_tests);
            st.out.write_line(#fmt["\nrunning %u tests", st.total]);
          }
          te_wait(test) { st.out.write_str(#fmt["test %s ... ", test.name]); }
          te_result(test, result) {
            alt result {
              tr_ok. {
                st.passed += 1u;
                write_ok(st.out, st.use_color);
                st.out.write_line("");
              }
              tr_failed. {
                st.failed += 1u;
                write_failed(st.out, st.use_color);
                st.out.write_line("");
                st.failures += [test];
              }
              tr_ignored. {
                st.ignored += 1u;
                write_ignored(st.out, st.use_color);
                st.out.write_line("");
              }
            }
          }
        }
    }

    let st =
        @{out: io::stdout(),
          use_color: use_color(),
          mutable total: 0u,
          mutable passed: 0u,
          mutable failed: 0u,
          mutable ignored: 0u,
          mutable failures: []};

    run_tests(opts, tests, to_task, bind callback(_, st));

    assert (st.passed + st.failed + st.ignored == st.total);
    let success = st.failed == 0u;

    if !success {
        st.out.write_line("\nfailures:");
        for test: test_desc<T> in st.failures {
            let testname = test.name; // Satisfy alias analysis
            st.out.write_line(#fmt["    %s", testname]);
        }
    }

    st.out.write_str(#fmt["\nresult: "]);
    if success {
        // There's no parallelism at this point so it's safe to use color
        write_ok(st.out, true);
    } else { write_failed(st.out, true); }
    st.out.write_str(#fmt[". %u passed; %u failed; %u ignored\n\n", st.passed,
                          st.failed, st.ignored]);

    ret success;

    fn write_ok(out: io::writer, use_color: bool) {
        write_pretty(out, "ok", term::color_green, use_color);
    }

    fn write_failed(out: io::writer, use_color: bool) {
        write_pretty(out, "FAILED", term::color_red, use_color);
    }

    fn write_ignored(out: io::writer, use_color: bool) {
        write_pretty(out, "ignored", term::color_yellow, use_color);
    }

    fn write_pretty(out: io::writer, word: str, color: u8, use_color: bool) {
        if use_color && term::color_supported() {
            term::fg(out, color);
        }
        out.write_str(word);
        if use_color && term::color_supported() {
            term::reset(out);
        }
    }
}

fn use_color() -> bool { ret get_concurrency() == 1u; }

tag testevent<T> {
    te_filtered([test_desc<T>]);
    te_wait(test_desc<T>);
    te_result(test_desc<T>, test_result);
}

fn run_tests<T: copy>(opts: test_opts, tests: [test_desc<T>],
                     to_task: test_to_task<T>,
                     callback: fn@(testevent<T>)) {

    let filtered_tests = filter_tests(opts, tests);
    callback(te_filtered(filtered_tests));

    // It's tempting to just spawn all the tests at once but that doesn't
    // provide a great user experience because you might sit waiting for the
    // result of a particular test for an unusually long amount of time.
    let concurrency = get_concurrency();
    #debug("using %u test tasks", concurrency);
    let total = vec::len(filtered_tests);
    let run_idx = 0u;
    let wait_idx = 0u;
    let futures = [];

    while wait_idx < total {
        while vec::len(futures) < concurrency && run_idx < total {
            futures += [run_test(filtered_tests[run_idx], to_task)];
            run_idx += 1u;
        }

        let future = futures[0];
        callback(te_wait(future.test));
        let result = future.wait();
        callback(te_result(future.test, result));
        futures = vec::slice(futures, 1u, vec::len(futures));
        wait_idx += 1u;
    }
}

fn get_concurrency() -> uint { rustrt::sched_threads() }

fn filter_tests<T: copy>(opts: test_opts,
                        tests: [test_desc<T>]) -> [test_desc<T>] {
    let filtered = tests;

    // Remove tests that don't match the test filter
    filtered = if option::is_none(opts.filter) {
        filtered
    } else {
        let filter_str =
            alt opts.filter {
          option::some(f) { f }
          option::none. { "" }
        };

        fn filter_fn<T: copy>(test: test_desc<T>, filter_str: str) ->
            option::t<test_desc<T>> {
            if str::find(test.name, filter_str) >= 0 {
                ret option::some(test);
            } else { ret option::none; }
        }

        let filter = bind filter_fn(_, filter_str);

        vec::filter_map(filtered, filter)
    };

    // Maybe pull out the ignored test and unignore them
    filtered = if !opts.run_ignored {
        filtered
    } else {
        fn filter<T: copy>(test: test_desc<T>) -> option::t<test_desc<T>> {
            if test.ignore {
                ret option::some({name: test.name,
                                  fn: test.fn,
                                  ignore: false,
                                  should_fail: test.should_fail});
            } else { ret option::none; }
        };

        vec::filter_map(filtered, bind filter(_))
    };

    // Sort the tests alphabetically
    filtered =
        {
            fn lteq<T>(t1: test_desc<T>, t2: test_desc<T>) -> bool {
                str::lteq(t1.name, t2.name)
            }
            sort::merge_sort(bind lteq(_, _), filtered)
        };

    ret filtered;
}

type test_future<T> = {test: test_desc<T>, wait: fn@() -> test_result};

fn run_test<T: copy>(test: test_desc<T>,
                    to_task: test_to_task<T>) -> test_future<T> {
    if test.ignore {
        ret {test: test, wait: fn@() -> test_result { tr_ignored }};
    }

    let test_task = to_task(test.fn);
    ret {test: test,
         wait: fn@() -> test_result {
             alt task::join(test_task) {
               task::tr_success. {
                 if test.should_fail { tr_failed }
                 else { tr_ok }
               }
               task::tr_failure. {
                 if test.should_fail { tr_ok }
                 else { tr_failed }
               }
             }
         }
        };
}

// We need to run our tests in another task in order to trap test failures.
// This function only works with functions that don't contain closures.
fn default_test_to_task(&&f: default_test_fn) -> joinable {
    ret task::spawn_joinable(fn~[copy f]() {
        configure_test_task();
        f();
    });
}

// Call from within a test task to make sure it's set up correctly
fn configure_test_task() {
    // If this task fails we don't want that failure to propagate to the
    // test runner or else we couldn't keep running tests
    task::unsupervise();
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>Remove workaround for issue #1494<commit_after>// Support code for rustc's built in test runner generator. Currently,
// none of this is meant for users. It is intended to support the
// simplest interface possible for representing and running tests
// while providing a base that other test frameworks may build off of.

import result::{ok, err};
import io::writer_util;

export test_name;
export test_fn;
export default_test_fn;
export test_desc;
export test_main;
export test_result;
export test_opts;
export tr_ok;
export tr_failed;
export tr_ignored;
export run_tests_console;
export run_tests_console_;
export run_test;
export filter_tests;
export parse_opts;
export test_to_task;
export default_test_to_task;
export configure_test_task;
export joinable;

#[abi = "cdecl"]
native mod rustrt {
    fn sched_threads() -> uint;
}

// The name of a test. By convention this follows the rules for rust
// paths; i.e. it should be a series of identifiers seperated by double
// colons. This way if some test runner wants to arrange the tests
// hierarchically it may.
type test_name = str;

// A function that runs a test. If the function returns successfully,
// the test succeeds; if the function fails then the test fails. We
// may need to come up with a more clever definition of test in order
// to support isolation of tests into tasks.
type test_fn<T> = T;

type default_test_fn = test_fn<fn~()>;

// The definition of a single test. A test runner will run a list of
// these.
type test_desc<T> = {
    name: test_name,
    fn: test_fn<T>,
    ignore: bool,
    should_fail: bool
};

// The default console test runner. It accepts the command line
// arguments and a vector of test_descs (generated at compile time).
fn test_main(args: [str], tests: [test_desc<default_test_fn>]) {
    check (vec::is_not_empty(args));
    let opts =
        alt parse_opts(args) {
          either::left(o) { o }
          either::right(m) { fail m }
        };
    if !run_tests_console(opts, tests) { fail "Some tests failed"; }
}

type test_opts = {filter: option::t<str>, run_ignored: bool};

type opt_res = either::t<test_opts, str>;

// Parses command line arguments into test options
fn parse_opts(args: [str]) : vec::is_not_empty(args) -> opt_res {

    let args_ = vec::tail(args);
    let opts = [getopts::optflag("ignored")];
    let match =
        alt getopts::getopts(args_, opts) {
          ok(m) { m }
          err(f) { ret either::right(getopts::fail_str(f)) }
        };

    let filter =
        if vec::len(match.free) > 0u {
            option::some(match.free[0])
        } else { option::none };

    let run_ignored = getopts::opt_present(match, "ignored");

    let test_opts = {filter: filter, run_ignored: run_ignored};

    ret either::left(test_opts);
}

tag test_result { tr_ok; tr_failed; tr_ignored; }

type joinable = (task::task, comm::port<task::task_notification>);

// To get isolation and concurrency tests have to be run in their own tasks.
// In cases where test functions are closures it is not ok to just dump them
// into a task and run them, so this transformation gives the caller a chance
// to create the test task.
type test_to_task<T> = fn@(test_fn<T>) -> joinable;

// A simple console test runner
fn run_tests_console(opts: test_opts,
                         tests: [test_desc<default_test_fn>]) -> bool {
    run_tests_console_(opts, tests, default_test_to_task)
}

fn run_tests_console_<T: copy>(opts: test_opts, tests: [test_desc<T>],
                              to_task: test_to_task<T>) -> bool {

    type test_state =
        @{out: io::writer,
          use_color: bool,
          mutable total: uint,
          mutable passed: uint,
          mutable failed: uint,
          mutable ignored: uint,
          mutable failures: [test_desc<T>]};

    fn callback<T: copy>(event: testevent<T>, st: test_state) {
        alt event {
          te_filtered(filtered_tests) {
            st.total = vec::len(filtered_tests);
            st.out.write_line(#fmt["\nrunning %u tests", st.total]);
          }
          te_wait(test) { st.out.write_str(#fmt["test %s ... ", test.name]); }
          te_result(test, result) {
            alt result {
              tr_ok. {
                st.passed += 1u;
                write_ok(st.out, st.use_color);
                st.out.write_line("");
              }
              tr_failed. {
                st.failed += 1u;
                write_failed(st.out, st.use_color);
                st.out.write_line("");
                st.failures += [test];
              }
              tr_ignored. {
                st.ignored += 1u;
                write_ignored(st.out, st.use_color);
                st.out.write_line("");
              }
            }
          }
        }
    }

    let st =
        @{out: io::stdout(),
          use_color: use_color(),
          mutable total: 0u,
          mutable passed: 0u,
          mutable failed: 0u,
          mutable ignored: 0u,
          mutable failures: []};

    run_tests(opts, tests, to_task, bind callback(_, st));

    assert (st.passed + st.failed + st.ignored == st.total);
    let success = st.failed == 0u;

    if !success {
        st.out.write_line("\nfailures:");
        for test: test_desc<T> in st.failures {
            let testname = test.name; // Satisfy alias analysis
            st.out.write_line(#fmt["    %s", testname]);
        }
    }

    st.out.write_str(#fmt["\nresult: "]);
    if success {
        // There's no parallelism at this point so it's safe to use color
        write_ok(st.out, true);
    } else { write_failed(st.out, true); }
    st.out.write_str(#fmt[". %u passed; %u failed; %u ignored\n\n", st.passed,
                          st.failed, st.ignored]);

    ret success;

    fn write_ok(out: io::writer, use_color: bool) {
        write_pretty(out, "ok", term::color_green, use_color);
    }

    fn write_failed(out: io::writer, use_color: bool) {
        write_pretty(out, "FAILED", term::color_red, use_color);
    }

    fn write_ignored(out: io::writer, use_color: bool) {
        write_pretty(out, "ignored", term::color_yellow, use_color);
    }

    fn write_pretty(out: io::writer, word: str, color: u8, use_color: bool) {
        if use_color && term::color_supported() {
            term::fg(out, color);
        }
        out.write_str(word);
        if use_color && term::color_supported() {
            term::reset(out);
        }
    }
}

fn use_color() -> bool { ret get_concurrency() == 1u; }

tag testevent<T> {
    te_filtered([test_desc<T>]);
    te_wait(test_desc<T>);
    te_result(test_desc<T>, test_result);
}

fn run_tests<T: copy>(opts: test_opts, tests: [test_desc<T>],
                     to_task: test_to_task<T>,
                     callback: fn@(testevent<T>)) {

    let filtered_tests = filter_tests(opts, tests);
    callback(te_filtered(filtered_tests));

    // It's tempting to just spawn all the tests at once but that doesn't
    // provide a great user experience because you might sit waiting for the
    // result of a particular test for an unusually long amount of time.
    let concurrency = get_concurrency();
    #debug("using %u test tasks", concurrency);
    let total = vec::len(filtered_tests);
    let run_idx = 0u;
    let wait_idx = 0u;
    let futures = [];

    while wait_idx < total {
        while vec::len(futures) < concurrency && run_idx < total {
            futures += [run_test(filtered_tests[run_idx], to_task)];
            run_idx += 1u;
        }

        let future = futures[0];
        callback(te_wait(future.test));
        let result = future.wait();
        callback(te_result(future.test, result));
        futures = vec::slice(futures, 1u, vec::len(futures));
        wait_idx += 1u;
    }
}

fn get_concurrency() -> uint { rustrt::sched_threads() }

fn filter_tests<T: copy>(opts: test_opts,
                        tests: [test_desc<T>]) -> [test_desc<T>] {
    let filtered = tests;

    // Remove tests that don't match the test filter
    filtered = if option::is_none(opts.filter) {
        filtered
    } else {
        let filter_str =
            alt opts.filter {
          option::some(f) { f }
          option::none. { "" }
        };

        fn filter_fn<T: copy>(test: test_desc<T>, filter_str: str) ->
            option::t<test_desc<T>> {
            if str::find(test.name, filter_str) >= 0 {
                ret option::some(test);
            } else { ret option::none; }
        }

        let filter = bind filter_fn(_, filter_str);

        vec::filter_map(filtered, filter)
    };

    // Maybe pull out the ignored test and unignore them
    filtered = if !opts.run_ignored {
        filtered
    } else {
        fn filter<T: copy>(test: test_desc<T>) -> option::t<test_desc<T>> {
            if test.ignore {
                ret option::some({name: test.name,
                                  fn: test.fn,
                                  ignore: false,
                                  should_fail: test.should_fail});
            } else { ret option::none; }
        };

        vec::filter_map(filtered, bind filter(_))
    };

    // Sort the tests alphabetically
    filtered =
        {
            fn lteq<T>(t1: test_desc<T>, t2: test_desc<T>) -> bool {
                str::lteq(t1.name, t2.name)
            }
            sort::merge_sort(bind lteq(_, _), filtered)
        };

    ret filtered;
}

type test_future<T> = {test: test_desc<T>, wait: fn@() -> test_result};

fn run_test<T: copy>(test: test_desc<T>,
                    to_task: test_to_task<T>) -> test_future<T> {
    if test.ignore {
        ret {test: test, wait: fn@() -> test_result { tr_ignored }};
    }

    let test_task = to_task(test.fn);
    ret {test: test,
         wait: fn@() -> test_result {
             alt task::join(test_task) {
               task::tr_success. {
                 if test.should_fail { tr_failed }
                 else { tr_ok }
               }
               task::tr_failure. {
                 if test.should_fail { tr_ok }
                 else { tr_failed }
               }
             }
         }
        };
}

// We need to run our tests in another task in order to trap test failures.
// This function only works with functions that don't contain closures.
fn default_test_to_task(&&f: default_test_fn) -> joinable {
    ret task::spawn_joinable(fn~[copy f]() {
        configure_test_task();
        f();
    });
}

// Call from within a test task to make sure it's set up correctly
fn configure_test_task() {
    // If this task fails we don't want that failure to propagate to the
    // test runner or else we couldn't keep running tests
    task::unsupervise();
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


<commit_before>/// Metadata on devices
pub mod devices;

/// Public-facing API
pub mod api;

/// Requests for specific devices
pub mod requests;

pub mod values;
<commit_msg>[fxbox/taxonomy] Introducing values<commit_after>/// Metadata on devices
pub mod devices;

/// Public-facing API
pub mod api;

/// Requests for specific devices
pub mod requests;

pub mod values;<|endoftext|>


<commit_before>extern crate regex;
use self::regex::Regex;
use std::io::prelude::*;
use std::fs::File;
use std::convert::AsRef;
use std::path::Path;
use std::io::Error;
use std::process::Command;

pub struct LsbRelease {
    pub distro: Option<String>,
    pub version: Option<String>
}

pub fn retrieve() -> Option<LsbRelease> {
    let output = match Command::new("lsb_release").arg("-a").output() {
        Ok(o)  => o,
        Err(_) =>return None
    };
    let stdout = String::from_utf8_lossy(&output.stdout);
    Some(parse(stdout.to_string()))
}

pub fn is_available() -> bool {
    match Command::new("lsb_release").output() {
        Ok(_) => true,
        Err(_) => false
    }
}

pub fn from_file<P: AsRef<Path>>(path: P) -> Result<LsbRelease, Error> {
    let mut handle = match File::open(path) {
        Ok(h) => h,
        Err(err) => return Err(err)
    };

    let mut file_content = String::new();

    match handle.read_to_string(&mut file_content) {
        Ok(_) => {
            let release = parse(file_content);
            Ok(release)
        },
        Err(err) => {
            Err(err)
        }
    }
}

pub fn parse(file: String) -> LsbRelease {
    let distrib_regex = Regex::new(r"Distributor ID:\s(\w+)").unwrap();
    let distrib_release_regex = Regex::new(r"Release:\s([\w\.]+)").unwrap();

    let distro = match distrib_regex.captures_iter(&file).next() {
        Some(m) => {
            match m.at(1) {
                Some(distro) => {
                    Some(distro.to_string())
                },
                None => None
            }
        },
        None => None
    };

    let version = match distrib_release_regex.captures_iter(&file).next() {
        Some(m) => {
            match m.at(1) {
                Some(version) => Some(version.to_string()),
                None => None
            }
        },
        None => None
    };

    LsbRelease {
        distro: distro,
        version: version
    }
}
<commit_msg>remove unused from_file method<commit_after>extern crate regex;
use self::regex::Regex;
use std::io::prelude::*;
use std::fs::File;
use std::convert::AsRef;
use std::path::Path;
use std::io::Error;
use std::process::Command;

pub struct LsbRelease {
    pub distro: Option<String>,
    pub version: Option<String>
}

pub fn retrieve() -> Option<LsbRelease> {
    let output = match Command::new("lsb_release").arg("-a").output() {
        Ok(o)  => o,
        Err(_) =>return None
    };
    let stdout = String::from_utf8_lossy(&output.stdout);
    Some(parse(stdout.to_string()))
}

pub fn is_available() -> bool {
    match Command::new("lsb_release").output() {
        Ok(_) => true,
        Err(_) => false
    }
}

pub fn parse(file: String) -> LsbRelease {
    let distrib_regex = Regex::new(r"Distributor ID:\s(\w+)").unwrap();
    let distrib_release_regex = Regex::new(r"Release:\s([\w\.]+)").unwrap();

    let distro = match distrib_regex.captures_iter(&file).next() {
        Some(m) => {
            match m.at(1) {
                Some(distro) => {
                    Some(distro.to_string())
                },
                None => None
            }
        },
        None => None
    };

    let version = match distrib_release_regex.captures_iter(&file).next() {
        Some(m) => {
            match m.at(1) {
                Some(version) => Some(version.to_string()),
                None => None
            }
        },
        None => None
    };

    LsbRelease {
        distro: distro,
        version: version
    }
}
<|endoftext|>


<commit_before>
//==============================================================================
struct Complex {
    real : f32,
    imag : f32
}

impl Complex {
    fn new(real: f32, imag: f32) -> Complex {
        Complex { real: real, imag: imag }
    }

    fn to_string(&self) -> String {
        format!("{}{:+}i", self.real, self.imag)
    }

    fn add(&self, v: Complex) -> Complex {
        Complex { real: self.real + v.real, imag: self.imag + v.imag }
    }

    fn times_ten(&mut self) {
        self.real *= 10.0;
        self.imag *= 10.0;
    }

    fn abs(&self) -> f32 {
        (self.real * self.real + self.imag * self.imag).sqrt()
    }
}

fn ex_5_1() {
    println!("\n#### ex_5_1() ####");

    let a = Complex::new(1.0, 2.0);
    println!("a = {}", a.to_string());

    let b = Complex::new(2.0, 4.0);
    println!("b = {}", b.to_string());

    let mut c = a.add(b);
    println!("c = {}", c.to_string());

    c.times_ten();
    println!("c*10 = {}", c.to_string());

    let d = Complex::new(-3.0, -4.0);
    println!("d = {}", d.to_string());
    println!("abs(d) = {}", d.abs());
}

//==============================================================================
trait Draw {
    fn draw(&self);
}

struct S1 {
    val : u32
}

struct S2 {
    val : f32
}

impl Draw for S1 {
    fn draw(&self) {
        println!("*** {} ***", self.val);
    }
}

impl Draw for S2 {
    fn draw(&self) {
        println!("*** {} ***", self.val);
    }
}

fn draw_object(obj : &Draw) {
    obj.draw();
}

fn ex_5_2() {
    println!("\n#### ex_5_2 ####");
    let s1 = S1 { val : 10 };
    draw_object(&s1);

    let s2 = S2 { val : 3.14 };
    draw_object(&s2);
}

//==============================================================================
// Eq and Ord trait example

#[derive(Eq)]
struct Position {
    x : u32,
    y : u32
}

impl PartialEq for Position {
    fn eq(&self, other: &Position) -> bool {
        self.x == other.x && self.y == other.y
    }
}

impl std::cmp::Ord for Position {
    fn cmp(&self, other: &Position) -> std::cmp::Ordering {
        let abs = self.x * self.x + self.y * self.y;
        let abs_other = other.x * other.x + other.y * other.y;

        abs.cmp(&abs_other)
    }
}

impl std::cmp::PartialOrd for Position {
    fn partial_cmp(&self, other: &Position) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

fn ex_5_3() {
    println!("\n#### ex_5_3 (Eq, PartialEq traits) ####");
    let pos1 = Position { x: 10, y: 20 };
    let pos2 = Position { x: 10, y: 20 };
    let pos3 = Position { x: 20, y: 40 };
    let pos4 = Position { x: 20, y: 10 };

    println!("pos1 == pos2 : {}", pos1 == pos2);
    println!("pos1 == pos3 : {}", pos1 == pos3);
    println!("pos1 != pos3 : {}", pos1 != pos3);
    println!("pos1 == pos4 : {}", pos1 == pos4);
    println!("pos1 < pos3 : {}", pos1 < pos3);
    println!("pos1 > pos3 : {}", pos1 > pos3);
}

//==============================================================================
fn main() {
    ex_5_1();
    ex_5_2();
    ex_5_3();
}
<commit_msg>Rust_EssentialNoteBook: add Default, Debug trait example.<commit_after>
//==============================================================================
struct Complex {
    real : f32,
    imag : f32
}

impl Complex {
    fn new(real: f32, imag: f32) -> Complex {
        Complex { real: real, imag: imag }
    }

    fn to_string(&self) -> String {
        format!("{}{:+}i", self.real, self.imag)
    }

    fn add(&self, v: Complex) -> Complex {
        Complex { real: self.real + v.real, imag: self.imag + v.imag }
    }

    fn times_ten(&mut self) {
        self.real *= 10.0;
        self.imag *= 10.0;
    }

    fn abs(&self) -> f32 {
        (self.real * self.real + self.imag * self.imag).sqrt()
    }
}

fn ex_5_1() {
    println!("\n#### ex_5_1() ####");

    let a = Complex::new(1.0, 2.0);
    println!("a = {}", a.to_string());

    let b = Complex::new(2.0, 4.0);
    println!("b = {}", b.to_string());

    let mut c = a.add(b);
    println!("c = {}", c.to_string());

    c.times_ten();
    println!("c*10 = {}", c.to_string());

    let d = Complex::new(-3.0, -4.0);
    println!("d = {}", d.to_string());
    println!("abs(d) = {}", d.abs());
}

//==============================================================================
trait Draw {
    fn draw(&self);
}

struct S1 {
    val : u32
}

struct S2 {
    val : f32
}

impl Draw for S1 {
    fn draw(&self) {
        println!("*** {} ***", self.val);
    }
}

impl Draw for S2 {
    fn draw(&self) {
        println!("*** {} ***", self.val);
    }
}

fn draw_object(obj : &Draw) {
    obj.draw();
}

fn ex_5_2() {
    println!("\n#### ex_5_2 ####");
    let s1 = S1 { val : 10 };
    draw_object(&s1);

    let s2 = S2 { val : 3.14 };
    draw_object(&s2);
}

//==============================================================================
// Eq and Ord trait example

#[derive(Eq)]
struct Position {
    x : u32,
    y : u32
}

impl PartialEq for Position {
    fn eq(&self, other: &Position) -> bool {
        self.x == other.x && self.y == other.y
    }
}

impl std::cmp::Ord for Position {
    fn cmp(&self, other: &Position) -> std::cmp::Ordering {
        let abs = self.x * self.x + self.y * self.y;
        let abs_other = other.x * other.x + other.y * other.y;

        abs.cmp(&abs_other)
    }
}

impl std::cmp::PartialOrd for Position {
    fn partial_cmp(&self, other: &Position) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

fn ex_5_3() {
    println!("\n#### ex_5_3 (Eq, PartialEq traits) ####");
    let pos1 = Position { x: 10, y: 20 };
    let pos2 = Position { x: 10, y: 20 };
    let pos3 = Position { x: 20, y: 40 };
    let pos4 = Position { x: 20, y: 10 };

    println!("pos1 == pos2 : {}", pos1 == pos2);
    println!("pos1 == pos3 : {}", pos1 == pos3);
    println!("pos1 != pos3 : {}", pos1 != pos3);
    println!("pos1 == pos4 : {}", pos1 == pos4);
    println!("pos1 < pos3 : {}", pos1 < pos3);
    println!("pos1 > pos3 : {}", pos1 > pos3);
}

//==============================================================================
// Default, Debug trait

enum ButtonState {
    CLICKED,
    RELEASED
}

impl Default for ButtonState {
    fn default() -> ButtonState {
        ButtonState::CLICKED
    }
}

impl std::fmt::Debug for ButtonState {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        let state = match *self {
            ButtonState::CLICKED => "CLICKED",
            ButtonState::RELEASED => "RELEASED",
        };
        write!(f, "{}", state)
    }
}

fn ex_5_4() {
    let mut btn : ButtonState = Default::default();
    println!("btn = {:?}", btn);

    btn = ButtonState::RELEASED;
    println!("btn = {:?}", btn);
}

//==============================================================================
fn main() {
    ex_5_1();
    ex_5_2();
    ex_5_3();
    ex_5_4();
}
<|endoftext|>


<commit_before>use std::io;

use super::iokit::*;
use core_foundation_sys::base::*;
use core_foundation_sys::dictionary::*;
use core_foundation_sys::number::*;
use core_foundation_sys::runloop::*;
use core_foundation_sys::string::*;

extern crate libc;
extern crate mach;
use mach::kern_return::KERN_SUCCESS;

use ::consts::{FIDO_USAGE_PAGE, FIDO_USAGE_U2FHID};

pub struct IOHIDDeviceID {
    pub device_id: u64 // TODO: Does this work on non-64-bit systems?
}

impl IOHIDDeviceID {
    pub fn from_ref(device_ref: IOHIDDeviceRef) -> IOHIDDeviceID {
        IOHIDDeviceID{ device_id: device_ref as u64 }
    }

    pub fn as_ref(&self) -> IOHIDDeviceRef {
        self.device_id as IOHIDDeviceRef
    }
}

pub struct IOHIDDeviceMatcher {
    dict: CFDictionaryRef,
    keys: Vec<CFStringRef>,
    values: Vec<CFNumberRef>
}

impl IOHIDDeviceMatcher {
    pub fn new() -> Self {
        let keys = vec!(
            IOHIDDeviceMatcher::cf_string("DeviceUsage"),
            IOHIDDeviceMatcher::cf_string("DeviceUsagePage")
        );

        let values = vec!(
            IOHIDDeviceMatcher::cf_number(FIDO_USAGE_U2FHID as i32),
            IOHIDDeviceMatcher::cf_number(FIDO_USAGE_PAGE as i32)
        );

        let dict = unsafe {
              CFDictionaryCreate(kCFAllocatorDefault,
                                 keys.as_ptr() as *const *const libc::c_void,
                                 values.as_ptr() as *const *const libc::c_void,
                                 keys.len() as CFIndex,
                                 &kCFTypeDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks) };

        Self { dict, keys, values }
    }

    fn cf_number(number: i32) -> CFNumberRef {
        let nbox = Box::new(number as i32);
        let nptr = Box::into_raw(nbox) as *mut libc::c_void;

        unsafe {
            // Drop when out of scope.
            let _num = Box::from_raw(nptr);
            CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, nptr)
        }
    }

    fn cf_string(string: &str) -> CFStringRef {
        unsafe { CFStringCreateWithBytes(kCFAllocatorDefault,
                                         string.as_ptr(),
                                         string.len() as CFIndex,
                                         kCFStringEncodingUTF8,
                                         false as Boolean,
                                         kCFAllocatorNull) }
    }

    pub fn get(&self) -> CFDictionaryRef {
        self.dict
    }
}

impl Drop for IOHIDDeviceMatcher {
    fn drop(&mut self) {
        unsafe { CFRelease(self.dict as *mut libc::c_void) };

        for key in &self.keys {
            unsafe { CFRelease(*key as *mut libc::c_void) };
        }

        for value in &self.values {
            unsafe { CFRelease(*value as *mut libc::c_void) };
        }
    }
}

pub struct IOHIDManager {
    manager: IOHIDManagerRef
}

impl IOHIDManager {
    pub fn new() -> io::Result<Self> {
        let manager = unsafe { IOHIDManagerCreate(kCFAllocatorDefault,
                                                  kIOHIDManagerOptionNone) };

        let rv = unsafe { IOHIDManagerOpen(manager, kIOHIDManagerOptionNone) };
        if rv != KERN_SUCCESS {
            return Err(io::Error::new(io::ErrorKind::Other,
                                      "Couldn't open HID Manager"));
        }

        unsafe { IOHIDManagerScheduleWithRunLoop(manager, CFRunLoopGetCurrent(),
                                                 kCFRunLoopDefaultMode) };

        Ok(Self { manager })
    }

    pub fn get(&self) -> IOHIDManagerRef {
        self.manager
    }
}

impl Drop for IOHIDManager {
    fn drop(&mut self) {
        let rv = unsafe { IOHIDManagerClose(self.manager,
                                            kIOHIDManagerOptionNone) };
        if rv != KERN_SUCCESS {
            println!("Couldn't close the HID Manager");
        }
    }
}
<commit_msg>Small follow-up / cleanup<commit_after>use std::io;

use super::iokit::*;
use core_foundation_sys::base::*;
use core_foundation_sys::dictionary::*;
use core_foundation_sys::number::*;
use core_foundation_sys::runloop::*;
use core_foundation_sys::string::*;

extern crate libc;
extern crate mach;
use mach::kern_return::KERN_SUCCESS;

use ::consts::{FIDO_USAGE_PAGE, FIDO_USAGE_U2FHID};

pub struct IOHIDDeviceID {
    pub device_id: u64 // TODO: Does this work on non-64-bit systems?
}

impl IOHIDDeviceID {
    pub fn from_ref(device_ref: IOHIDDeviceRef) -> IOHIDDeviceID {
        IOHIDDeviceID{ device_id: device_ref as u64 }
    }

    pub fn as_ref(&self) -> IOHIDDeviceRef {
        self.device_id as IOHIDDeviceRef
    }
}

pub struct IOHIDDeviceMatcher {
    dict: CFDictionaryRef,
    keys: Vec<CFStringRef>,
    values: Vec<CFNumberRef>
}

impl IOHIDDeviceMatcher {
    pub fn new() -> Self {
        let keys = vec!(
            IOHIDDeviceMatcher::cf_string("DeviceUsage"),
            IOHIDDeviceMatcher::cf_string("DeviceUsagePage")
        );

        let values = vec!(
            IOHIDDeviceMatcher::cf_number(FIDO_USAGE_U2FHID as i32),
            IOHIDDeviceMatcher::cf_number(FIDO_USAGE_PAGE as i32)
        );

        let dict = unsafe {
              CFDictionaryCreate(kCFAllocatorDefault,
                                 keys.as_ptr() as *const *const libc::c_void,
                                 values.as_ptr() as *const *const libc::c_void,
                                 keys.len() as CFIndex,
                                 &kCFTypeDictionaryKeyCallBacks,
                                 &kCFTypeDictionaryValueCallBacks) };

        Self { dict, keys, values }
    }

    fn cf_number(number: i32) -> CFNumberRef {
        let nbox = Box::new(number);
        let nptr = Box::into_raw(nbox) as *mut libc::c_void;

        unsafe {
            // Drop when out of scope.
            let _num = Box::from_raw(nptr);
            CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, nptr)
        }
    }

    fn cf_string(string: &str) -> CFStringRef {
        unsafe { CFStringCreateWithBytes(kCFAllocatorDefault,
                                         string.as_ptr(),
                                         string.len() as CFIndex,
                                         kCFStringEncodingUTF8,
                                         false as Boolean,
                                         kCFAllocatorNull) }
    }

    pub fn get(&self) -> CFDictionaryRef {
        self.dict
    }
}

impl Drop for IOHIDDeviceMatcher {
    fn drop(&mut self) {
        unsafe { CFRelease(self.dict as *mut libc::c_void) };

        for key in &self.keys {
            unsafe { CFRelease(*key as *mut libc::c_void) };
        }

        for value in &self.values {
            unsafe { CFRelease(*value as *mut libc::c_void) };
        }
    }
}

pub struct IOHIDManager {
    manager: IOHIDManagerRef
}

impl IOHIDManager {
    pub fn new() -> io::Result<Self> {
        let manager = unsafe { IOHIDManagerCreate(kCFAllocatorDefault,
                                                  kIOHIDManagerOptionNone) };

        let rv = unsafe { IOHIDManagerOpen(manager, kIOHIDManagerOptionNone) };
        if rv != KERN_SUCCESS {
            return Err(io::Error::new(io::ErrorKind::Other,
                                      "Couldn't open HID Manager"));
        }

        unsafe { IOHIDManagerScheduleWithRunLoop(manager, CFRunLoopGetCurrent(),
                                                 kCFRunLoopDefaultMode) };

        Ok(Self { manager })
    }

    pub fn get(&self) -> IOHIDManagerRef {
        self.manager
    }
}

impl Drop for IOHIDManager {
    fn drop(&mut self) {
        let rv = unsafe { IOHIDManagerClose(self.manager,
                                            kIOHIDManagerOptionNone) };
        if rv != KERN_SUCCESS {
            println!("Couldn't close the HID Manager");
        }
    }
}
<|endoftext|>


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

use std::ffi::CStr;
use std::sync::Arc;

use futures::future;
use futures::future::BoxFuture;
use futures::stream::BoxStream;
use futures::FutureExt;

use crate::help::Spawner;
use crate::Framing;
use crate::FramingDecoded;
use crate::FramingEncodedFinal;
use crate::Protocol;

pub trait ClientFactory {
    type Api: ?Sized;

    fn new<P, T>(protocol: P, transport: T) -> Arc<Self::Api>
    where
        P: Protocol<Frame = T> + 'static,
        T: Transport + Sync,
        P::Deserializer: Send,
    {
        let spawner = crate::NoopSpawner;
        Self::with_spawner(protocol, transport, spawner)
    }

    fn with_spawner<P, T, S>(protocol: P, transport: T, spawner: S) -> Arc<Self::Api>
    where
        P: Protocol<Frame = T> + 'static,
        T: Transport + Sync,
        P::Deserializer: Send,
        S: Spawner;
}

pub trait Transport: Framing + Send + Sized + 'static {
    type RpcOptions: Default;

    fn call(
        &self,
        service_name: &'static CStr,
        fn_name: &'static CStr,
        req: FramingEncodedFinal<Self>,
        rpc_options: Self::RpcOptions,
    ) -> BoxFuture<'static, anyhow::Result<FramingDecoded<Self>>>;

    fn call_stream(
        &self,
        _service_name: &'static CStr,
        _fn_name: &'static CStr,
        _req: FramingEncodedFinal<Self>,
        _rpc_options: Self::RpcOptions,
    ) -> BoxFuture<
        'static,
        anyhow::Result<(
            FramingDecoded<Self>,
            BoxStream<'static, anyhow::Result<FramingDecoded<Self>>>,
        )>,
    > {
        future::err(anyhow::Error::msg(
            "Streaming is not supported by this transport",
        ))
        .boxed()
    }

    fn create_interaction(&self, _method_name: &'static CStr) -> Result<Self, anyhow::Error> {
        anyhow::bail!("Interactions are not supported by this transport");
    }
}
<commit_msg>Make transport sync<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

use std::ffi::CStr;
use std::sync::Arc;

use futures::future;
use futures::future::BoxFuture;
use futures::stream::BoxStream;
use futures::FutureExt;

use crate::help::Spawner;
use crate::Framing;
use crate::FramingDecoded;
use crate::FramingEncodedFinal;
use crate::Protocol;

pub trait ClientFactory {
    type Api: ?Sized;

    fn new<P, T>(protocol: P, transport: T) -> Arc<Self::Api>
    where
        P: Protocol<Frame = T> + 'static,
        T: Transport,
        P::Deserializer: Send,
    {
        let spawner = crate::NoopSpawner;
        Self::with_spawner(protocol, transport, spawner)
    }

    fn with_spawner<P, T, S>(protocol: P, transport: T, spawner: S) -> Arc<Self::Api>
    where
        P: Protocol<Frame = T> + 'static,
        T: Transport,
        P::Deserializer: Send,
        S: Spawner;
}

pub trait Transport: Framing + Send + Sync + Sized + 'static {
    type RpcOptions: Default;

    fn call(
        &self,
        service_name: &'static CStr,
        fn_name: &'static CStr,
        req: FramingEncodedFinal<Self>,
        rpc_options: Self::RpcOptions,
    ) -> BoxFuture<'static, anyhow::Result<FramingDecoded<Self>>>;

    fn call_stream(
        &self,
        _service_name: &'static CStr,
        _fn_name: &'static CStr,
        _req: FramingEncodedFinal<Self>,
        _rpc_options: Self::RpcOptions,
    ) -> BoxFuture<
        'static,
        anyhow::Result<(
            FramingDecoded<Self>,
            BoxStream<'static, anyhow::Result<FramingDecoded<Self>>>,
        )>,
    > {
        future::err(anyhow::Error::msg(
            "Streaming is not supported by this transport",
        ))
        .boxed()
    }

    fn create_interaction(&self, _method_name: &'static CStr) -> Result<Self, anyhow::Error> {
        anyhow::bail!("Interactions are not supported by this transport");
    }
}
<|endoftext|>


<commit_before>use {
    BackEnd,
    Borrowed,
    Clear,
    Color,
    Field,
    Fill,
    Matrix2d,
    Value,
};
use triangulation::{
    with_lerp_polygons_tri_list_xy_f32_rgba_f32
};
use internal::{
    CanColor,
    CanTransform,
    CanViewTransform,
    HasColor,
    HasTransform,
    HasViewTransform,
};

/// An animation inbetweening context with color.
pub struct TweenPolygonsColorContext<'a, 'b> {
    /// Base/origin transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current color.
    pub color: Field<'a, Color>,
    /// Animation inbetweening factor.
    pub tween_factor: Field<'a, f64>,
    /// The animated polygons.
    pub polygons: Field<'a, &'b [&'b [f64]]>,
}

impl<'a, 'b> Clone for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn clone(&self) -> TweenPolygonsColorContext<'static, 'b> {
        TweenPolygonsColorContext {
            base: self.base.clone(),
            transform: self.transform.clone(),
            color: self.color.clone(),
            tween_factor: self.tween_factor.clone(),
            polygons: self.polygons.clone(),
        }
    }
}

impl<'a, 'b> HasColor<'a, Color> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn get_color(&'a self) -> &'a Color {
        self.color.get()
    }
}

impl<'a, 'b> CanColor<'a, TweenPolygonsColorContext<'a, 'b>, Color> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn color(&'a self, value: Color) -> TweenPolygonsColorContext<'a, 'b> {
        TweenPolygonsColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value(value),
            tween_factor: Borrowed(self.tween_factor.get()),
            polygons: Borrowed(self.polygons.get()),
        }
    }
}

impl<'a, 'b> HasTransform<'a, Matrix2d> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(alwyas)]
    fn get_transform(&'a self) -> &'a Matrix2d {
        self.transform.get()
    }
}

impl<'a, 'b> CanTransform<'a, TweenPolygonsColorContext<'a, 'b>, Matrix2d> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn transform(&'a self, value: Matrix2d) -> TweenPolygonsColorContext<'a, 'b> {
        TweenPolygonsColorContext {
            base: Borrowed(self.base.get()),
            transform: Value(value),
            color: Borrowed(self.color.get()),
            tween_factor: Borrowed(self.tween_factor.get()),
            polygons: Borrowed(self.polygons.get()),
        }
    }
}

impl<'a, 'b> HasViewTransform<'a, Matrix2d> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn get_view_transform(&'a self) -> &'a Matrix2d {
        self.base.get()
    }
}

impl<'a, 'b> CanViewTransform<'a, TweenPolygonsColorContext<'a, 'b>, Matrix2d>
for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn view_transform(&'a self, value: Matrix2d) -> TweenPolygonsColorContext<'a, 'b> {
        TweenPolygonsColorContext {
            base: Value(value),
            transform: Borrowed(self.transform.get()),
            tween_factor: Borrowed(self.tween_factor.get()),
            polygons: Borrowed(self.polygons.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a, 'b> Fill<'a> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_f32_rgba_f32() {
            let polygons = self.polygons.get();
            let &Color(color) = self.color.get();
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque.
            let needs_alpha = color[3] != 1.0;
            if needs_alpha { back_end.enable_alpha_blend(); }
            with_lerp_polygons_tri_list_xy_f32_rgba_f32(
                self.transform.get(),
                *polygons,
                *self.tween_factor.get(),
                &Color(color),
                |vertices, colors| {
                    back_end.tri_list_xy_f32_rgba_f32(vertices, colors)
                }
            );
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}

impl<'a, 'b> Clear for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let &Color(color) = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        }
    }
}

<commit_msg>Using type alias for `Polygons` in `TweenPolygonsColorContext`<commit_after>use {
    BackEnd,
    Borrowed,
    Clear,
    Color,
    Field,
    Fill,
    Matrix2d,
    Polygons,
    Value,
};
use triangulation::{
    with_lerp_polygons_tri_list_xy_f32_rgba_f32
};
use internal::{
    CanColor,
    CanTransform,
    CanViewTransform,
    HasColor,
    HasTransform,
    HasViewTransform,
};

/// An animation inbetweening context with color.
pub struct TweenPolygonsColorContext<'a, 'b> {
    /// Base/origin transform.
    pub base: Field<'a, Matrix2d>,
    /// Current transform.
    pub transform: Field<'a, Matrix2d>,
    /// Current color.
    pub color: Field<'a, Color>,
    /// Animation inbetweening factor.
    pub tween_factor: Field<'a, f64>,
    /// The animated polygons.
    pub polygons: Field<'a, Polygons<'b>>,
}

impl<'a, 'b> Clone for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn clone(&self) -> TweenPolygonsColorContext<'static, 'b> {
        TweenPolygonsColorContext {
            base: self.base.clone(),
            transform: self.transform.clone(),
            color: self.color.clone(),
            tween_factor: self.tween_factor.clone(),
            polygons: self.polygons.clone(),
        }
    }
}

impl<'a, 'b> HasColor<'a, Color> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn get_color(&'a self) -> &'a Color {
        self.color.get()
    }
}

impl<'a, 'b> CanColor<'a, TweenPolygonsColorContext<'a, 'b>, Color> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn color(&'a self, value: Color) -> TweenPolygonsColorContext<'a, 'b> {
        TweenPolygonsColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value(value),
            tween_factor: Borrowed(self.tween_factor.get()),
            polygons: Borrowed(self.polygons.get()),
        }
    }
}

impl<'a, 'b> HasTransform<'a, Matrix2d> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(alwyas)]
    fn get_transform(&'a self) -> &'a Matrix2d {
        self.transform.get()
    }
}

impl<'a, 'b> CanTransform<'a, TweenPolygonsColorContext<'a, 'b>, Matrix2d> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn transform(&'a self, value: Matrix2d) -> TweenPolygonsColorContext<'a, 'b> {
        TweenPolygonsColorContext {
            base: Borrowed(self.base.get()),
            transform: Value(value),
            color: Borrowed(self.color.get()),
            tween_factor: Borrowed(self.tween_factor.get()),
            polygons: Borrowed(self.polygons.get()),
        }
    }
}

impl<'a, 'b> HasViewTransform<'a, Matrix2d> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn get_view_transform(&'a self) -> &'a Matrix2d {
        self.base.get()
    }
}

impl<'a, 'b> CanViewTransform<'a, TweenPolygonsColorContext<'a, 'b>, Matrix2d>
for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn view_transform(&'a self, value: Matrix2d) -> TweenPolygonsColorContext<'a, 'b> {
        TweenPolygonsColorContext {
            base: Value(value),
            transform: Borrowed(self.transform.get()),
            tween_factor: Borrowed(self.tween_factor.get()),
            polygons: Borrowed(self.polygons.get()),
            color: Borrowed(self.color.get()),
        }
    }
}

impl<'a, 'b> Fill<'a> for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn fill<B: BackEnd>(&'a self, back_end: &mut B) {
        if back_end.supports_tri_list_xy_f32_rgba_f32() {
            let polygons = self.polygons.get();
            let &Color(color) = self.color.get();
            // Complete transparency does not need to be rendered.
            if color[3] == 0.0 { return; }
            // Turn on alpha blending if not completely opaque.
            let needs_alpha = color[3] != 1.0;
            if needs_alpha { back_end.enable_alpha_blend(); }
            with_lerp_polygons_tri_list_xy_f32_rgba_f32(
                self.transform.get(),
                *polygons,
                *self.tween_factor.get(),
                &Color(color),
                |vertices, colors| {
                    back_end.tri_list_xy_f32_rgba_f32(vertices, colors)
                }
            );
            if needs_alpha { back_end.disable_alpha_blend(); }
        } else {
            unimplemented!();
        }
    }
}

impl<'a, 'b> Clear for TweenPolygonsColorContext<'a, 'b> {
    #[inline(always)]
    fn clear<B: BackEnd>(&self, back_end: &mut B) {
        if back_end.supports_clear_rgba() {
            let &Color(color) = self.color.get();
            back_end.clear_rgba(color[0], color[1], color[2], color[3]);
        }
    }
}

<|endoftext|>