<commit_before>use super::*;

#[test]
fn macro_rules_are_globally_visible() {
    check(
        r#"
//- /lib.rs
macro_rules! structs {
    ($($i:ident),*) => {
        $(struct $i { field: u32 } )*
    }
}
structs!(Foo);
mod nested;

//- /nested.rs
structs!(Bar, Baz);
"#,
        expect![[r#"
            crate
            Foo: t
            nested: t

            crate::nested
            Bar: t
            Baz: t
        "#]],
    );
}

#[test]
fn macro_rules_can_define_modules() {
    check(
        r#"
//- /lib.rs
macro_rules! m {
    ($name:ident) => { mod $name;  }
}
m!(n1);
mod m { m!(n3) }

//- /n1.rs
m!(n2)
//- /n1/n2.rs
struct X;
//- /m/n3.rs
struct Y;
"#,
        expect![[r#"
            crate
            m: t
            n1: t

            crate::m
            n3: t

            crate::m::n3
            Y: t v

            crate::n1
            n2: t

            crate::n1::n2
            X: t v
        "#]],
    );
}

#[test]
fn macro_rules_from_other_crates_are_visible() {
    check(
        r#"
//- /main.rs crate:main deps:foo
foo::structs!(Foo, Bar)
mod bar;

//- /bar.rs
use crate::*;

//- /lib.rs crate:foo
#[macro_export]
macro_rules! structs {
    ($($i:ident),*) => {
        $(struct $i { field: u32 } )*
    }
}
"#,
        expect![[r#"
            crate
            Bar: t
            Foo: t
            bar: t

            crate::bar
            Bar: t
            Foo: t
            bar: t
        "#]],
    );
}

#[test]
fn macro_rules_export_with_local_inner_macros_are_visible() {
    check(
        r#"
//- /main.rs crate:main deps:foo
foo::structs!(Foo, Bar)
mod bar;

//- /bar.rs
use crate::*;

//- /lib.rs crate:foo
#[macro_export(local_inner_macros)]
macro_rules! structs {
    ($($i:ident),*) => {
        $(struct $i { field: u32 } )*
    }
}
"#,
        expect![[r#"
            crate
            Bar: t
            Foo: t
            bar: t

            crate::bar
            Bar: t
            Foo: t
            bar: t
        "#]],
    );
}

#[test]
fn local_inner_macros_makes_local_macros_usable() {
    check(
        r#"
//- /main.rs crate:main deps:foo
foo::structs!(Foo, Bar);
mod bar;

//- /bar.rs
use crate::*;

//- /lib.rs crate:foo
#[macro_export(local_inner_macros)]
macro_rules! structs {
    ($($i:ident),*) => {
        inner!($($i),*);
    }
}
#[macro_export]
macro_rules! inner {
    ($($i:ident),*) => {
        $(struct $i { field: u32 } )*
    }
}
"#,
        expect![[r#"
            crate
            Bar: t
            Foo: t
            bar: t

            crate::bar
            Bar: t
            Foo: t
            bar: t
        "#]],
    );
}

#[test]
fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
    check(
        r#"
//- /main.rs crate:main deps:foo
macro_rules! baz {
    () => {
        use foo::bar;
    }
}
foo!();
bar!();
baz!();

//- /lib.rs crate:foo
#[macro_export]
macro_rules! foo {
    () => {
        struct Foo { field: u32 }
    }
}
#[macro_export]
macro_rules! bar {
    () => {
        use foo::foo;
    }
}
"#,
        expect![[r#"
            crate
            Foo: t
            bar: m
            foo: m
        "#]],
    );
}

#[test]
fn macro_rules_from_other_crates_are_visible_with_macro_use() {
    mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use);
    check(
        r#"
//- /main.rs crate:main deps:foo
structs!(Foo);
structs_priv!(Bar);
structs_not_exported!(MacroNotResolved1);
crate::structs!(MacroNotResolved2);

mod bar;

#[macro_use]
extern crate foo;

//- /bar.rs
structs!(Baz);
crate::structs!(MacroNotResolved3);

//- /lib.rs crate:foo
#[macro_export]
macro_rules! structs {
    ($i:ident) => { struct $i; }
}

macro_rules! structs_not_exported {
    ($i:ident) => { struct $i; }
}

mod priv_mod {
    #[macro_export]
    macro_rules! structs_priv {
        ($i:ident) => { struct $i; }
    }
}
"#,
        expect![[r#"
            crate
            Bar: t v
            Foo: t v
            bar: t
            foo: t

            crate::bar
            Baz: t v
        "#]],
    );
}

#[test]
fn prelude_is_macro_use() {
    mark::check!(prelude_is_macro_use);
    check(
        r#"
//- /main.rs crate:main deps:foo
structs!(Foo);
structs_priv!(Bar);
structs_outside!(Out);
crate::structs!(MacroNotResolved2);

mod bar;

//- /bar.rs
structs!(Baz);
crate::structs!(MacroNotResolved3);

//- /lib.rs crate:foo
#[prelude_import]
use self::prelude::*;

mod prelude {
    #[macro_export]
    macro_rules! structs {
        ($i:ident) => { struct $i; }
    }

    mod priv_mod {
        #[macro_export]
        macro_rules! structs_priv {
            ($i:ident) => { struct $i; }
        }
    }
}

#[macro_export]
macro_rules! structs_outside {
    ($i:ident) => { struct $i; }
}
"#,
        expect![[r#"
            crate
            Bar: t v
            Foo: t v
            Out: t v
            bar: t

            crate::bar
            Baz: t v
        "#]],
    );
}

#[test]
fn prelude_cycle() {
    check(
        r#"
#[prelude_import]
use self::prelude::*;

declare_mod!();

mod prelude {
    macro_rules! declare_mod {
        () => (mod foo {})
    }
}
"#,
        expect![[r#"
            crate
            prelude: t

            crate::prelude
        "#]],
    );
}

#[test]
fn plain_macros_are_legacy_textual_scoped() {
    check(
        r#"
//- /main.rs
mod m1;
bar!(NotFoundNotMacroUse);

mod m2 { foo!(NotFoundBeforeInside2); }

macro_rules! foo {
    ($x:ident) => { struct $x; }
}
foo!(Ok);

mod m3;
foo!(OkShadowStop);
bar!(NotFoundMacroUseStop);

#[macro_use]
mod m5 {
    #[macro_use]
    mod m6 {
        macro_rules! foo {
            ($x:ident) => { fn $x() {} }
        }
    }
}
foo!(ok_double_macro_use_shadow);

baz!(NotFoundBefore);
#[macro_use]
mod m7 {
    macro_rules! baz {
        ($x:ident) => { struct $x; }
    }
}
baz!(OkAfter);

//- /m1.rs
foo!(NotFoundBeforeInside1);
macro_rules! bar {
    ($x:ident) => { struct $x; }
}

//- /m3/mod.rs
foo!(OkAfterInside);
macro_rules! foo {
    ($x:ident) => { fn $x() {} }
}
foo!(ok_shadow);

#[macro_use]
mod m4;
bar!(OkMacroUse);

//- /m3/m4.rs
foo!(ok_shadow_deep);
macro_rules! bar {
    ($x:ident) => { struct $x; }
}
"#,
        expect![[r#"
            crate
            Ok: t v
            OkAfter: t v
            OkShadowStop: t v
            m1: t
            m2: t
            m3: t
            m5: t
            m7: t
            ok_double_macro_use_shadow: v

            crate::m7

            crate::m1

            crate::m5
            m6: t

            crate::m5::m6

            crate::m2

            crate::m3
            OkAfterInside: t v
            OkMacroUse: t v
            m4: t
            ok_shadow: v

            crate::m3::m4
            ok_shadow_deep: v
        "#]],
    );
}

#[test]
fn type_value_macro_live_in_different_scopes() {
    check(
        r#"
#[macro_export]
macro_rules! foo {
    ($x:ident) => { type $x = (); }
}

foo!(foo);
use foo as bar;

use self::foo as baz;
fn baz() {}
"#,
        expect![[r#"
            crate
            bar: t m
            baz: t v m
            foo: t m
        "#]],
    );
}

#[test]
fn macro_use_can_be_aliased() {
    check(
        r#"
//- /main.rs crate:main deps:foo
#[macro_use]
extern crate foo;

foo!(Direct);
bar!(Alias);

//- /lib.rs crate:foo
use crate::foo as bar;

mod m {
    #[macro_export]
    macro_rules! foo {
        ($x:ident) => { struct $x; }
    }
}
"#,
        expect![[r#"
            crate
            Alias: t v
            Direct: t v
            foo: t
        "#]],
    );
}

#[test]
fn path_qualified_macros() {
    check(
        r#"
macro_rules! foo {
    ($x:ident) => { struct $x; }
}

crate::foo!(NotResolved);

crate::bar!(OkCrate);
bar!(OkPlain);
alias1!(NotHere);
m::alias1!(OkAliasPlain);
m::alias2!(OkAliasSuper);
m::alias3!(OkAliasCrate);
not_found!(NotFound);

mod m {
    #[macro_export]
    macro_rules! bar {
        ($x:ident) => { struct $x; }
    }
    pub use bar as alias1;
    pub use super::bar as alias2;
    pub use crate::bar as alias3;
    pub use self::bar as not_found;
}
"#,
        expect![[r#"
            crate
            OkAliasCrate: t v
            OkAliasPlain: t v
            OkAliasSuper: t v
            OkCrate: t v
            OkPlain: t v
            bar: m
            m: t

            crate::m
            alias1: m
            alias2: m
            alias3: m
            not_found: _
        "#]],
    );
}

#[test]
fn macro_dollar_crate_is_correct_in_item() {
    mark::check!(macro_dollar_crate_self);
    check(
        r#"
//- /main.rs crate:main deps:foo
#[macro_use]
extern crate foo;

#[macro_use]
mod m {
    macro_rules! current {
        () => {
            use $crate::Foo as FooSelf;
        }
    }
}

struct Foo;

current!();
not_current1!();
foo::not_current2!();

//- /lib.rs crate:foo
mod m {
    #[macro_export]
    macro_rules! not_current1 {
        () => {
            use $crate::Bar;
        }
    }
}

#[macro_export]
macro_rules! not_current2 {
    () => {
        use $crate::Baz;
    }
}

struct Bar;
struct Baz;
"#,
        expect![[r#"
            crate
            Bar: t v
            Baz: t v
            Foo: t v
            FooSelf: t v
            foo: t
            m: t

            crate::m
        "#]],
    );
}

#[test]
fn macro_dollar_crate_is_correct_in_indirect_deps() {
    mark::check!(macro_dollar_crate_other);
    // From std
    check(
        r#"
//- /main.rs crate:main deps:std
foo!();

//- /std.rs crate:std deps:core
#[prelude_import]
use self::prelude::*;

pub use core::foo;

mod prelude {}

#[macro_use]
mod std_macros;

//- /core.rs crate:core
#[macro_export]
macro_rules! foo {
    () => {
        use $crate::bar;
    }
}

pub struct bar;
"#,
        expect![[r#"
            crate
            bar: t v
        "#]],
    );
}

#[test]
fn expand_derive() {
    let map = compute_crate_def_map(
        "
        //- /main.rs
        #[derive(Copy, Clone)]
        struct Foo;
        ",
    );
    assert_eq!(map.modules[map.root].scope.impls().len(), 2);
}

#[test]
fn macro_expansion_overflow() {
    mark::check!(macro_expansion_overflow);
    check(
        r#"
macro_rules! a {
    ($e:expr; $($t:tt)*) => {
        b!($($t)*);
    };
    () => {};
}

macro_rules! b {
    (static = $e:expr; $($t:tt)*) => {
        a!($e; $($t)*);
    };
    () => {};
}

b! { static = #[] (); }
"#,
        expect![[r#"
            crate
        "#]],
    );
}
<commit_msg>Add test<commit_after>use super::*;

#[test]
fn macro_rules_are_globally_visible() {
    check(
        r#"
//- /lib.rs
macro_rules! structs {
    ($($i:ident),*) => {
        $(struct $i { field: u32 } )*
    }
}
structs!(Foo);
mod nested;

//- /nested.rs
structs!(Bar, Baz);
"#,
        expect![[r#"
            crate
            Foo: t
            nested: t

            crate::nested
            Bar: t
            Baz: t
        "#]],
    );
}

#[test]
fn macro_rules_can_define_modules() {
    check(
        r#"
//- /lib.rs
macro_rules! m {
    ($name:ident) => { mod $name;  }
}
m!(n1);
mod m { m!(n3) }

//- /n1.rs
m!(n2)
//- /n1/n2.rs
struct X;
//- /m/n3.rs
struct Y;
"#,
        expect![[r#"
            crate
            m: t
            n1: t

            crate::m
            n3: t

            crate::m::n3
            Y: t v

            crate::n1
            n2: t

            crate::n1::n2
            X: t v
        "#]],
    );
}

#[test]
fn macro_rules_from_other_crates_are_visible() {
    check(
        r#"
//- /main.rs crate:main deps:foo
foo::structs!(Foo, Bar)
mod bar;

//- /bar.rs
use crate::*;

//- /lib.rs crate:foo
#[macro_export]
macro_rules! structs {
    ($($i:ident),*) => {
        $(struct $i { field: u32 } )*
    }
}
"#,
        expect![[r#"
            crate
            Bar: t
            Foo: t
            bar: t

            crate::bar
            Bar: t
            Foo: t
            bar: t
        "#]],
    );
}

#[test]
fn macro_rules_export_with_local_inner_macros_are_visible() {
    check(
        r#"
//- /main.rs crate:main deps:foo
foo::structs!(Foo, Bar)
mod bar;

//- /bar.rs
use crate::*;

//- /lib.rs crate:foo
#[macro_export(local_inner_macros)]
macro_rules! structs {
    ($($i:ident),*) => {
        $(struct $i { field: u32 } )*
    }
}
"#,
        expect![[r#"
            crate
            Bar: t
            Foo: t
            bar: t

            crate::bar
            Bar: t
            Foo: t
            bar: t
        "#]],
    );
}

#[test]
fn local_inner_macros_makes_local_macros_usable() {
    check(
        r#"
//- /main.rs crate:main deps:foo
foo::structs!(Foo, Bar);
mod bar;

//- /bar.rs
use crate::*;

//- /lib.rs crate:foo
#[macro_export(local_inner_macros)]
macro_rules! structs {
    ($($i:ident),*) => {
        inner!($($i),*);
    }
}
#[macro_export]
macro_rules! inner {
    ($($i:ident),*) => {
        $(struct $i { field: u32 } )*
    }
}
"#,
        expect![[r#"
            crate
            Bar: t
            Foo: t
            bar: t

            crate::bar
            Bar: t
            Foo: t
            bar: t
        "#]],
    );
}

#[test]
fn unexpanded_macro_should_expand_by_fixedpoint_loop() {
    check(
        r#"
//- /main.rs crate:main deps:foo
macro_rules! baz {
    () => {
        use foo::bar;
    }
}
foo!();
bar!();
baz!();

//- /lib.rs crate:foo
#[macro_export]
macro_rules! foo {
    () => {
        struct Foo { field: u32 }
    }
}
#[macro_export]
macro_rules! bar {
    () => {
        use foo::foo;
    }
}
"#,
        expect![[r#"
            crate
            Foo: t
            bar: m
            foo: m
        "#]],
    );
}

#[test]
fn macro_rules_from_other_crates_are_visible_with_macro_use() {
    mark::check!(macro_rules_from_other_crates_are_visible_with_macro_use);
    check(
        r#"
//- /main.rs crate:main deps:foo
structs!(Foo);
structs_priv!(Bar);
structs_not_exported!(MacroNotResolved1);
crate::structs!(MacroNotResolved2);

mod bar;

#[macro_use]
extern crate foo;

//- /bar.rs
structs!(Baz);
crate::structs!(MacroNotResolved3);

//- /lib.rs crate:foo
#[macro_export]
macro_rules! structs {
    ($i:ident) => { struct $i; }
}

macro_rules! structs_not_exported {
    ($i:ident) => { struct $i; }
}

mod priv_mod {
    #[macro_export]
    macro_rules! structs_priv {
        ($i:ident) => { struct $i; }
    }
}
"#,
        expect![[r#"
            crate
            Bar: t v
            Foo: t v
            bar: t
            foo: t

            crate::bar
            Baz: t v
        "#]],
    );
}

#[test]
fn prelude_is_macro_use() {
    mark::check!(prelude_is_macro_use);
    check(
        r#"
//- /main.rs crate:main deps:foo
structs!(Foo);
structs_priv!(Bar);
structs_outside!(Out);
crate::structs!(MacroNotResolved2);

mod bar;

//- /bar.rs
structs!(Baz);
crate::structs!(MacroNotResolved3);

//- /lib.rs crate:foo
#[prelude_import]
use self::prelude::*;

mod prelude {
    #[macro_export]
    macro_rules! structs {
        ($i:ident) => { struct $i; }
    }

    mod priv_mod {
        #[macro_export]
        macro_rules! structs_priv {
            ($i:ident) => { struct $i; }
        }
    }
}

#[macro_export]
macro_rules! structs_outside {
    ($i:ident) => { struct $i; }
}
"#,
        expect![[r#"
            crate
            Bar: t v
            Foo: t v
            Out: t v
            bar: t

            crate::bar
            Baz: t v
        "#]],
    );
}

#[test]
fn prelude_cycle() {
    check(
        r#"
#[prelude_import]
use self::prelude::*;

declare_mod!();

mod prelude {
    macro_rules! declare_mod {
        () => (mod foo {})
    }
}
"#,
        expect![[r#"
            crate
            prelude: t

            crate::prelude
        "#]],
    );
}

#[test]
fn plain_macros_are_legacy_textual_scoped() {
    check(
        r#"
//- /main.rs
mod m1;
bar!(NotFoundNotMacroUse);

mod m2 { foo!(NotFoundBeforeInside2); }

macro_rules! foo {
    ($x:ident) => { struct $x; }
}
foo!(Ok);

mod m3;
foo!(OkShadowStop);
bar!(NotFoundMacroUseStop);

#[macro_use]
mod m5 {
    #[macro_use]
    mod m6 {
        macro_rules! foo {
            ($x:ident) => { fn $x() {} }
        }
    }
}
foo!(ok_double_macro_use_shadow);

baz!(NotFoundBefore);
#[macro_use]
mod m7 {
    macro_rules! baz {
        ($x:ident) => { struct $x; }
    }
}
baz!(OkAfter);

//- /m1.rs
foo!(NotFoundBeforeInside1);
macro_rules! bar {
    ($x:ident) => { struct $x; }
}

//- /m3/mod.rs
foo!(OkAfterInside);
macro_rules! foo {
    ($x:ident) => { fn $x() {} }
}
foo!(ok_shadow);

#[macro_use]
mod m4;
bar!(OkMacroUse);

//- /m3/m4.rs
foo!(ok_shadow_deep);
macro_rules! bar {
    ($x:ident) => { struct $x; }
}
"#,
        expect![[r#"
            crate
            Ok: t v
            OkAfter: t v
            OkShadowStop: t v
            m1: t
            m2: t
            m3: t
            m5: t
            m7: t
            ok_double_macro_use_shadow: v

            crate::m7

            crate::m1

            crate::m5
            m6: t

            crate::m5::m6

            crate::m2

            crate::m3
            OkAfterInside: t v
            OkMacroUse: t v
            m4: t
            ok_shadow: v

            crate::m3::m4
            ok_shadow_deep: v
        "#]],
    );
}

#[test]
fn type_value_macro_live_in_different_scopes() {
    check(
        r#"
#[macro_export]
macro_rules! foo {
    ($x:ident) => { type $x = (); }
}

foo!(foo);
use foo as bar;

use self::foo as baz;
fn baz() {}
"#,
        expect![[r#"
            crate
            bar: t m
            baz: t v m
            foo: t m
        "#]],
    );
}

#[test]
fn macro_use_can_be_aliased() {
    check(
        r#"
//- /main.rs crate:main deps:foo
#[macro_use]
extern crate foo;

foo!(Direct);
bar!(Alias);

//- /lib.rs crate:foo
use crate::foo as bar;

mod m {
    #[macro_export]
    macro_rules! foo {
        ($x:ident) => { struct $x; }
    }
}
"#,
        expect![[r#"
            crate
            Alias: t v
            Direct: t v
            foo: t
        "#]],
    );
}

#[test]
fn path_qualified_macros() {
    check(
        r#"
macro_rules! foo {
    ($x:ident) => { struct $x; }
}

crate::foo!(NotResolved);

crate::bar!(OkCrate);
bar!(OkPlain);
alias1!(NotHere);
m::alias1!(OkAliasPlain);
m::alias2!(OkAliasSuper);
m::alias3!(OkAliasCrate);
not_found!(NotFound);

mod m {
    #[macro_export]
    macro_rules! bar {
        ($x:ident) => { struct $x; }
    }
    pub use bar as alias1;
    pub use super::bar as alias2;
    pub use crate::bar as alias3;
    pub use self::bar as not_found;
}
"#,
        expect![[r#"
            crate
            OkAliasCrate: t v
            OkAliasPlain: t v
            OkAliasSuper: t v
            OkCrate: t v
            OkPlain: t v
            bar: m
            m: t

            crate::m
            alias1: m
            alias2: m
            alias3: m
            not_found: _
        "#]],
    );
}

#[test]
fn macro_dollar_crate_is_correct_in_item() {
    mark::check!(macro_dollar_crate_self);
    check(
        r#"
//- /main.rs crate:main deps:foo
#[macro_use]
extern crate foo;

#[macro_use]
mod m {
    macro_rules! current {
        () => {
            use $crate::Foo as FooSelf;
        }
    }
}

struct Foo;

current!();
not_current1!();
foo::not_current2!();

//- /lib.rs crate:foo
mod m {
    #[macro_export]
    macro_rules! not_current1 {
        () => {
            use $crate::Bar;
        }
    }
}

#[macro_export]
macro_rules! not_current2 {
    () => {
        use $crate::Baz;
    }
}

struct Bar;
struct Baz;
"#,
        expect![[r#"
            crate
            Bar: t v
            Baz: t v
            Foo: t v
            FooSelf: t v
            foo: t
            m: t

            crate::m
        "#]],
    );
}

#[test]
fn macro_dollar_crate_is_correct_in_indirect_deps() {
    mark::check!(macro_dollar_crate_other);
    // From std
    check(
        r#"
//- /main.rs crate:main deps:std
foo!();

//- /std.rs crate:std deps:core
#[prelude_import]
use self::prelude::*;

pub use core::foo;

mod prelude {}

#[macro_use]
mod std_macros;

//- /core.rs crate:core
#[macro_export]
macro_rules! foo {
    () => {
        use $crate::bar;
    }
}

pub struct bar;
"#,
        expect![[r#"
            crate
            bar: t v
        "#]],
    );
}

#[test]
fn expand_derive() {
    let map = compute_crate_def_map(
        "
        //- /main.rs
        #[derive(Copy, Clone)]
        struct Foo;
        ",
    );
    assert_eq!(map.modules[map.root].scope.impls().len(), 2);
}

#[test]
fn macro_expansion_overflow() {
    mark::check!(macro_expansion_overflow);
    check(
        r#"
macro_rules! a {
    ($e:expr; $($t:tt)*) => {
        b!($($t)*);
    };
    () => {};
}

macro_rules! b {
    (static = $e:expr; $($t:tt)*) => {
        a!($e; $($t)*);
    };
    () => {};
}

b! { static = #[] (); }
"#,
        expect![[r#"
            crate
        "#]],
    );
}

#[test]
fn resolves_proc_macros() {
    check(
        r"
        struct TokenStream;

        #[proc_macro]
        pub fn function_like_macro(args: TokenStream) -> TokenStream {
            args
        }

        #[proc_macro_attribute]
        pub fn attribute_macro(_args: TokenStream, item: TokenStream) -> TokenStream {
            item
        }

        #[proc_macro_derive(DummyTrait)]
        pub fn derive_macro(_item: TokenStream) -> TokenStream {
            TokenStream
        }
        ",
        expect![[r#"
            crate
            DummyTrait: m
            TokenStream: t v
            attribute_macro: v m
            derive_macro: v
            function_like_macro: v m
        "#]],
    );
}
<|endoftext|>


<commit_before>//! Loads a Cargo project into a static instance of analysis, without support
//! for incorporating changes.
use std::{path::Path, sync::Arc};

use anyhow::Result;
use crossbeam_channel::{unbounded, Receiver};
use ide::{AnalysisHost, Change};
use ide_db::base_db::CrateGraph;
use project_model::{
    BuildDataCollector, CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace,
};
use vfs::{loader::Handle, AbsPath, AbsPathBuf};

use crate::reload::{ProjectFolders, SourceRootConfig};

pub struct LoadCargoConfig {
    pub load_out_dirs_from_check: bool,
    pub wrap_rustc: bool,
    pub with_proc_macro: bool,
}

pub fn load_workspace_at(
    root: &Path,
    cargo_config: &CargoConfig,
    load_config: &LoadCargoConfig,
    progress: &dyn Fn(String),
) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> {
    let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
    let root = ProjectManifest::discover_single(&root)?;
    let workspace = ProjectWorkspace::load(root, cargo_config, progress)?;

    load_workspace(workspace, load_config, progress)
}

pub fn load_workspace(
    ws: ProjectWorkspace,
    config: &LoadCargoConfig,
    progress: &dyn Fn(String),
) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> {
    let (sender, receiver) = unbounded();
    let mut vfs = vfs::Vfs::default();
    let mut loader = {
        let loader =
            vfs_notify::NotifyHandle::spawn(Box::new(move |msg| sender.send(msg).unwrap()));
        Box::new(loader)
    };

    let proc_macro_client = if config.with_proc_macro {
        let path = std::env::current_exe()?;
        Some(ProcMacroClient::extern_process(path, &["proc-macro"]).unwrap())
    } else {
        None
    };

    let build_data = if config.load_out_dirs_from_check {
        let mut collector = BuildDataCollector::new(config.wrap_rustc);
        ws.collect_build_data_configs(&mut collector);
        Some(collector.collect(progress)?)
    } else {
        None
    };

    let crate_graph = ws.to_crate_graph(
        build_data.as_ref(),
        proc_macro_client.as_ref(),
        &mut |path: &AbsPath| {
            let contents = loader.load_sync(path);
            let path = vfs::VfsPath::from(path.to_path_buf());
            vfs.set_file_contents(path.clone(), contents);
            vfs.file_id(&path)
        },
    );

    let project_folders = ProjectFolders::new(&[ws], &[], build_data.as_ref());
    loader.set_config(vfs::loader::Config {
        load: project_folders.load,
        watch: vec![],
        version: 0,
    });

    log::debug!("crate graph: {:?}", crate_graph);
    let host =
        load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver);
    Ok((host, vfs, proc_macro_client))
}

fn load_crate_graph(
    crate_graph: CrateGraph,
    source_root_config: SourceRootConfig,
    vfs: &mut vfs::Vfs,
    receiver: &Receiver<vfs::loader::Message>,
) -> AnalysisHost {
    let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
    let mut host = AnalysisHost::new(lru_cap);
    let mut analysis_change = Change::new();

    // wait until Vfs has loaded all roots
    for task in receiver {
        match task {
            vfs::loader::Message::Progress { n_done, n_total, config_version: _ } => {
                if n_done == n_total {
                    break;
                }
            }
            vfs::loader::Message::Loaded { files } => {
                for (path, contents) in files {
                    vfs.set_file_contents(path.into(), contents);
                }
            }
        }
    }
    let changes = vfs.take_changes();
    for file in changes {
        if file.exists() {
            let contents = vfs.file_contents(file.file_id).to_vec();
            if let Ok(text) = String::from_utf8(contents) {
                analysis_change.change_file(file.file_id, Some(Arc::new(text)))
            }
        }
    }
    let source_roots = source_root_config.partition(&vfs);
    analysis_change.set_roots(source_roots);

    analysis_change.set_crate_graph(crate_graph);

    host.apply_change(analysis_change);
    host
}

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

    use hir::Crate;

    #[test]
    fn test_loading_rust_analyzer() -> Result<()> {
        let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
        let cargo_config = Default::default();
        let load_cargo_config = LoadCargoConfig {
            load_out_dirs_from_check: false,
            wrap_rustc: false,
            with_proc_macro: false,
        };
        let (host, _vfs, _proc_macro) =
            load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?;

        let n_crates = Crate::all(host.raw_database()).len();
        // RA has quite a few crates, but the exact count doesn't matter
        assert!(n_crates > 20);

        Ok(())
    }
}
<commit_msg>Enable attribute macro expansion in `analysis-stats`<commit_after>//! Loads a Cargo project into a static instance of analysis, without support
//! for incorporating changes.
use std::{path::Path, sync::Arc};

use anyhow::Result;
use crossbeam_channel::{unbounded, Receiver};
use hir::db::DefDatabase;
use ide::{AnalysisHost, Change};
use ide_db::base_db::CrateGraph;
use project_model::{
    BuildDataCollector, CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace,
};
use vfs::{loader::Handle, AbsPath, AbsPathBuf};

use crate::reload::{ProjectFolders, SourceRootConfig};

pub struct LoadCargoConfig {
    pub load_out_dirs_from_check: bool,
    pub wrap_rustc: bool,
    pub with_proc_macro: bool,
}

pub fn load_workspace_at(
    root: &Path,
    cargo_config: &CargoConfig,
    load_config: &LoadCargoConfig,
    progress: &dyn Fn(String),
) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> {
    let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
    let root = ProjectManifest::discover_single(&root)?;
    let workspace = ProjectWorkspace::load(root, cargo_config, progress)?;

    load_workspace(workspace, load_config, progress)
}

pub fn load_workspace(
    ws: ProjectWorkspace,
    config: &LoadCargoConfig,
    progress: &dyn Fn(String),
) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroClient>)> {
    let (sender, receiver) = unbounded();
    let mut vfs = vfs::Vfs::default();
    let mut loader = {
        let loader =
            vfs_notify::NotifyHandle::spawn(Box::new(move |msg| sender.send(msg).unwrap()));
        Box::new(loader)
    };

    let proc_macro_client = if config.with_proc_macro {
        let path = std::env::current_exe()?;
        Some(ProcMacroClient::extern_process(path, &["proc-macro"]).unwrap())
    } else {
        None
    };

    let build_data = if config.load_out_dirs_from_check {
        let mut collector = BuildDataCollector::new(config.wrap_rustc);
        ws.collect_build_data_configs(&mut collector);
        Some(collector.collect(progress)?)
    } else {
        None
    };

    let crate_graph = ws.to_crate_graph(
        build_data.as_ref(),
        proc_macro_client.as_ref(),
        &mut |path: &AbsPath| {
            let contents = loader.load_sync(path);
            let path = vfs::VfsPath::from(path.to_path_buf());
            vfs.set_file_contents(path.clone(), contents);
            vfs.file_id(&path)
        },
    );

    let project_folders = ProjectFolders::new(&[ws], &[], build_data.as_ref());
    loader.set_config(vfs::loader::Config {
        load: project_folders.load,
        watch: vec![],
        version: 0,
    });

    log::debug!("crate graph: {:?}", crate_graph);
    let host =
        load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver);
    Ok((host, vfs, proc_macro_client))
}

fn load_crate_graph(
    crate_graph: CrateGraph,
    source_root_config: SourceRootConfig,
    vfs: &mut vfs::Vfs,
    receiver: &Receiver<vfs::loader::Message>,
) -> AnalysisHost {
    let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
    let mut host = AnalysisHost::new(lru_cap);
    let mut analysis_change = Change::new();

    host.raw_database_mut().set_enable_proc_attr_macros(true);

    // wait until Vfs has loaded all roots
    for task in receiver {
        match task {
            vfs::loader::Message::Progress { n_done, n_total, config_version: _ } => {
                if n_done == n_total {
                    break;
                }
            }
            vfs::loader::Message::Loaded { files } => {
                for (path, contents) in files {
                    vfs.set_file_contents(path.into(), contents);
                }
            }
        }
    }
    let changes = vfs.take_changes();
    for file in changes {
        if file.exists() {
            let contents = vfs.file_contents(file.file_id).to_vec();
            if let Ok(text) = String::from_utf8(contents) {
                analysis_change.change_file(file.file_id, Some(Arc::new(text)))
            }
        }
    }
    let source_roots = source_root_config.partition(&vfs);
    analysis_change.set_roots(source_roots);

    analysis_change.set_crate_graph(crate_graph);

    host.apply_change(analysis_change);
    host
}

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

    use hir::Crate;

    #[test]
    fn test_loading_rust_analyzer() -> Result<()> {
        let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
        let cargo_config = Default::default();
        let load_cargo_config = LoadCargoConfig {
            load_out_dirs_from_check: false,
            wrap_rustc: false,
            with_proc_macro: false,
        };
        let (host, _vfs, _proc_macro) =
            load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?;

        let n_crates = Crate::all(host.raw_database()).len();
        // RA has quite a few crates, but the exact count doesn't matter
        assert!(n_crates > 20);

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


<commit_before>extern crate image;
extern crate vibrant;

use std::env;
use std::path::Path;

use image::GenericImage;
use vibrant::Vibrancy;

fn main() {
    let source = env::args().skip(1).next()
        .expect("No source image given.");
    let img = image::open(&Path::new(&source))
        .ok().expect(&format!("Could not load image {:?}", source));

    println!("{:?}", img.dimensions());

    println!("{}", Vibrancy::new(&img));
}
<commit_msg>Don't Output Image Dimensions<commit_after>extern crate image;
extern crate vibrant;

use std::env;
use std::path::Path;

use vibrant::Vibrancy;

fn main() {
    let source = env::args().skip(1).next()
        .expect("No source image given.");
    let img = image::open(&Path::new(&source))
        .ok().expect(&format!("Could not load image {:?}", source));

    println!("{}", Vibrancy::new(&img));
}
<|endoftext|>


<commit_before>use std::rc::Rc;

use super::{config, Conditions, Message, TimerEvent};

#[derive(Debug)]
pub struct Context {
    conditions: Conditions,
    opened: bool,
    patterns: Vec<String>,
    elapsed_time: u32,
    elapsed_time_since_last_message: u32,
    messages: Vec<Rc<Message>>
}

impl Context {
    pub fn new(conditions: Conditions) -> Context {
        Context {
            conditions: conditions,
            opened: false,
            elapsed_time: 0,
            elapsed_time_since_last_message: 0,
            messages: Vec::new(),
            patterns: Vec::new()
        }
    }

    pub fn on_timer(&mut self, event: &TimerEvent) {
        if self.opened {
            println!("timer event: {}", event.0);
            self.update_timers(event.0);
            self.opened = !self.is_any_timer_expired();
        }
    }

    fn process_message(&mut self, event: Rc<Message>) {
        println!("message event");
        self.elapsed_time_since_last_message = 0;
        self.messages.push(event);
        if self.is_closing() {
            println!("context closed");
            self.opened = false;
        }
    }

    pub fn on_message(&mut self, event: Rc<Message>) {
        if self.opened {
            self.process_message(event);
        } else {
            self.open_context_or_ignore_message(event);
        }
    }

    pub fn is_open(&self) -> bool {
        self.opened
    }

    fn open_context_or_ignore_message(&mut self, event: Rc<Message>) {
        if self.is_opening(&event) {
            println!("context opened");
            self.opened = true;
            self.process_message(event);
        } else {
            println!("not opening");
        }
    }

    fn is_max_size_reached(&self) -> bool {
        println!("self.messages: {:?}", &self.messages);
        self.conditions.max_size.map_or(false, |max_size| self.messages.len() >= max_size)
    }

    fn is_closing_message(&self) -> bool {
        self.conditions.last_closes.map_or(false, |closes| {
            if closes {
                self.patterns.last().map_or(false, |pattern| {
                    pattern == self.messages.last().unwrap().get("uuid").unwrap()
                })
            } else {
                false
            }
        })
    }

    fn is_opening(&self, message: &Message) -> bool {
        let found = self.patterns.contains(message.get("uuid").unwrap());
        println!("found: {}", found);
        self.conditions.first_opens.map_or(found, |first| {
            if first {
                self.patterns.first().map_or(false, |pattern| {
                    pattern == message.get("uuid").unwrap()
                })
            } else {
                found
            }
        })
    }

    fn is_closing(&self) -> bool {
        println!("checking close");
        self.is_max_size_reached() || self.is_closing_message()
    }

    fn is_timeout_expired(&self) -> bool {
        self.elapsed_time >= self.conditions.timeout
    }

    fn is_renew_timeout_expired(&self) -> bool {
        self.conditions.renew_timeout.map_or(false, |renew_timeout| {
            self.elapsed_time_since_last_message >= renew_timeout
        })
    }

    fn is_any_timer_expired(&self) -> bool {
        self.is_timeout_expired() || self.is_renew_timeout_expired()
    }

    fn update_timers(&mut self, elapsed_time: u32) {
        self.elapsed_time += elapsed_time;
        self.elapsed_time_since_last_message += elapsed_time;
    }
}

impl From<config::Context> for Context {
    fn from(context: config::Context) -> Context {
        let mut ctx = Context::new(context.conditions);
        ctx.patterns = context.patterns;
        ctx
    }
}

use conditions::Builder;

#[test]
fn test_given_close_condition_with_timeout_when_the_timeout_expires_then_the_condition_is_met() {
    let timeout = 100;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).build());
    context.patterns.push(msg_id.clone());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    println!("{:?}", &context);
    assert_false!(context.is_open());
    context.on_message(event);
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(50));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(49));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_false!(context.is_open());
}
#[test]
fn test_given_close_condition_with_max_size_when_the_max_size_reached_then_the_condition_is_met() {
    let timeout = 100;
    let max_size = 3;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).max_size(max_size).build());
    context.patterns.push(msg_id.clone());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    println!("{:?}", &context);
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_message(event.clone());
    println!("{:?}", &context);
    assert_false!(context.is_open());
}

/*
#[test]
fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_without_renewing_messages_then_the_condition_is_met() {
    let timeout = 100;
    let renew_timeout = 10;
    let mut context = Context::new(Builder::new(timeout).renew_timeout(renew_timeout).build());
    let msg1 = btreemap!{
        "uuid".to_string() => "1".to_string(),
    };
    let event = Rc::new(msg1);
    assert_false!(context.on_message(event.clone()));
    assert_false!(context.on_timer(&mut TimerEvent(8)));
    assert_false!(context.on_timer(&mut TimerEvent(1)));
    assert_true!(context.on_timer(&mut TimerEvent(1)));
}

#[test]
fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_with_renewing_messages_then_the_context_is_not_closed() {
    let timeout = 100;
    let renew_timeout = 10;
    let mut context = Context::new(Builder::new(timeout).renew_timeout(renew_timeout).build());
    let msg1 = btreemap!{
        "uuid".to_string() => "1".to_string(),
    };
    let event = Rc::new(msg1);
    assert_false!(context.on_message(event.clone()));
    assert_false!(context.on_timer(&mut TimerEvent(8)));
    assert_false!(context.on_timer(&mut TimerEvent(1)));
    assert_false!(context.on_message(event.clone()));
    assert_false!(context.on_timer(&mut TimerEvent(1)));
}*/
<commit_msg>all tests are ok<commit_after>use std::rc::Rc;

use super::{config, Conditions, Message, TimerEvent};

#[derive(Debug)]
pub struct Context {
    conditions: Conditions,
    opened: bool,
    patterns: Vec<String>,
    elapsed_time: u32,
    elapsed_time_since_last_message: u32,
    messages: Vec<Rc<Message>>
}

impl Context {
    pub fn new(conditions: Conditions) -> Context {
        Context {
            conditions: conditions,
            opened: false,
            elapsed_time: 0,
            elapsed_time_since_last_message: 0,
            messages: Vec::new(),
            patterns: Vec::new()
        }
    }

    pub fn on_timer(&mut self, event: &TimerEvent) {
        if self.opened {
            println!("timer event: {}", event.0);
            self.update_timers(event.0);
            self.opened = !self.is_any_timer_expired();
        }
    }

    fn process_message(&mut self, event: Rc<Message>) {
        println!("message event");
        self.elapsed_time_since_last_message = 0;
        self.messages.push(event);
        if self.is_closing() {
            println!("context closed");
            self.opened = false;
        }
    }

    pub fn on_message(&mut self, event: Rc<Message>) {
        if self.opened {
            self.process_message(event);
        } else {
            self.open_context_or_ignore_message(event);
        }
    }

    pub fn is_open(&self) -> bool {
        self.opened
    }

    fn open_context_or_ignore_message(&mut self, event: Rc<Message>) {
        if self.is_opening(&event) {
            println!("context opened");
            self.opened = true;
            self.process_message(event);
        } else {
            println!("not opening");
        }
    }

    fn is_max_size_reached(&self) -> bool {
        println!("self.messages: {:?}", &self.messages);
        self.conditions.max_size.map_or(false, |max_size| self.messages.len() >= max_size)
    }

    fn is_closing_message(&self) -> bool {
        self.conditions.last_closes.map_or(false, |closes| {
            if closes {
                self.patterns.last().map_or(false, |pattern| {
                    pattern == self.messages.last().unwrap().get("uuid").unwrap()
                })
            } else {
                false
            }
        })
    }

    fn is_opening(&self, message: &Message) -> bool {
        let found = self.patterns.contains(message.get("uuid").unwrap());
        println!("found: {}", found);
        self.conditions.first_opens.map_or(found, |first| {
            if first {
                self.patterns.first().map_or(false, |pattern| {
                    pattern == message.get("uuid").unwrap()
                })
            } else {
                found
            }
        })
    }

    fn is_closing(&self) -> bool {
        println!("checking close");
        self.is_max_size_reached() || self.is_closing_message()
    }

    fn is_timeout_expired(&self) -> bool {
        self.elapsed_time >= self.conditions.timeout
    }

    fn is_renew_timeout_expired(&self) -> bool {
        self.conditions.renew_timeout.map_or(false, |renew_timeout| {
            self.elapsed_time_since_last_message >= renew_timeout
        })
    }

    fn is_any_timer_expired(&self) -> bool {
        self.is_timeout_expired() || self.is_renew_timeout_expired()
    }

    fn update_timers(&mut self, elapsed_time: u32) {
        self.elapsed_time += elapsed_time;
        self.elapsed_time_since_last_message += elapsed_time;
    }
}

impl From<config::Context> for Context {
    fn from(context: config::Context) -> Context {
        let mut ctx = Context::new(context.conditions);
        ctx.patterns = context.patterns;
        ctx
    }
}

use conditions::Builder;

#[test]
fn test_given_close_condition_with_timeout_when_the_timeout_expires_then_the_condition_is_met() {
    let timeout = 100;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).build());
    context.patterns.push(msg_id.clone());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    println!("{:?}", &context);
    assert_false!(context.is_open());
    context.on_message(event);
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(50));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(49));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_false!(context.is_open());
}
#[test]
fn test_given_close_condition_with_max_size_when_the_max_size_reached_then_the_condition_is_met() {
    let timeout = 100;
    let max_size = 3;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).max_size(max_size).build());
    context.patterns.push(msg_id.clone());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    println!("{:?}", &context);
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_message(event.clone());
    println!("{:?}", &context);
    assert_false!(context.is_open());
}

#[test]
fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_without_renewing_messages_then_the_condition_is_met() {
    let timeout = 100;
    let renew_timeout = 10;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).renew_timeout(renew_timeout).build());
    context.patterns.push(msg_id.clone());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(8));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_false!(context.is_open());
}

#[test]
fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_with_renewing_messages_then_the_context_is_not_closed() {
    let timeout = 100;
    let renew_timeout = 10;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).renew_timeout(renew_timeout).build());
    context.patterns.push(msg_id.clone());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    assert_false!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(8));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_true!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_true!(context.is_open());
}
<|endoftext|>


<commit_before>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d};
use {ColorContext, EllipseContext, RectangleContext};
use {AddColor, AddEllipse, AddRectangle};

/// Drawing 2d context.
pub struct Context<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
}

impl<'a> Transform2d<'a> for Context<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans = translate(x, y);
                 multiply(&trans, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let rot = rotate_radians(angle);
                multiply(&rot, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale = scale(sx, sy);
                multiply(&scale, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear = shear(sx, sy);
                multiply(&shear, self.transform.get())
            }),
        }
    }
}

impl<'a> Context<'a> {
    /// Creates a new drawing context.
    pub fn new() -> Context {
        Context {
            base:  Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            transform: Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
        }
    }
}

#[test]
fn test_context() {
    let c = Context::new();
    {
        let d = c.trans(20.0, 40.0);
        let d = d.trans(10.0, 10.0);
        assert_eq!(d.transform.get()[2], 30.0);
        assert_eq!(d.transform.get()[5], 50.0);
    }
    assert_eq!(c.transform.get()[2], 0.0);
    assert_eq!(c.transform.get()[5], 0.0);

    let c = c.rot_deg(90.0);
    assert!((c.transform.get()[0] - 0.0).abs() < 0.00001);
    assert!((c.transform.get()[1] - 1.0).abs() < 0.00001);
}

#[test]
fn test_scale() {
    let c = Context::new();
    let c = c.scale(2.0, 3.0);
    assert!((c.transform.get()[0] - 2.0).abs() < 0.00001);
    assert!((c.transform.get()[4] - 3.0).abs() < 0.00001);
}

impl<'a> AddRectangle<'a, RectangleContext<'a>> for Context<'a> {
    #[inline(always)]
    fn rect(&'a self, x: f64, y: f64, w: f64, h: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value([x, y, w, h]),
        }
    }
}

#[test]
fn test_rect() {
    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 50.0);
    assert_eq!(d.rect.get()[2], 100.0);
}

impl<'a> AddColor<'a, ColorContext<'a>> for Context<'a> {
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
        }
    }
}

#[test]
fn test_rgba() {
    let c = Context::new();
    let d: ColorContext = c.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(d.color.get()[0], 1.0);
}

impl<'a> AddEllipse<'a, EllipseContext<'a>> for Context<'a> {
    #[inline(always)]
    fn ellipse(&'a self, x: f64, y: f64, w: f64, h: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value([x, y, w, h]),
        }
    }
}

#[test]
fn test_ellipse() {
    let c = Context::new();
    let d: EllipseContext = c.ellipse(0.0, 0.0, 100.0, 100.0);
    assert_eq!(d.rect.get()[2], 100.0);
}

<commit_msg>Implemented AddPolygon for Context<commit_after>
use {Field, Borrowed, Value};
use vecmath::{rotate_radians, multiply, translate, scale, shear};
use {Transform2d, Matrix2d};
use {ColorContext, EllipseContext, PolygonContext, RectangleContext};
use {AddColor, AddEllipse, AddPolygon, AddRectangle};

/// Drawing 2d context.
pub struct Context<'a> {
    /// Base/original transformation.
    pub base: Field<'a, Matrix2d>,
    /// Current transformation.
    pub transform: Field<'a, Matrix2d>,
}

impl<'a> Transform2d<'a> for Context<'a> {
    #[inline(always)]
    fn trans(&'a self, x: f64, y: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let trans = translate(x, y);
                 multiply(&trans, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn rot_rad(&'a self, angle: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let rot = rotate_radians(angle);
                multiply(&rot, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn scale(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let scale = scale(sx, sy);
                multiply(&scale, self.transform.get())
            }),
        }
    }

    #[inline(always)]
    fn shear(&'a self, sx: f64, sy: f64) -> Context<'a> {
        Context {
            base: Borrowed(self.base.get()),
            transform: Value({
                let shear = shear(sx, sy);
                multiply(&shear, self.transform.get())
            }),
        }
    }
}

impl<'a> Context<'a> {
    /// Creates a new drawing context.
    pub fn new() -> Context {
        Context {
            base:  Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
            transform: Value([1.0, 0.0, 0.0,
                          0.0, 1.0, 0.0]),
        }
    }
}

#[test]
fn test_context() {
    let c = Context::new();
    {
        let d = c.trans(20.0, 40.0);
        let d = d.trans(10.0, 10.0);
        assert_eq!(d.transform.get()[2], 30.0);
        assert_eq!(d.transform.get()[5], 50.0);
    }
    assert_eq!(c.transform.get()[2], 0.0);
    assert_eq!(c.transform.get()[5], 0.0);

    let c = c.rot_deg(90.0);
    assert!((c.transform.get()[0] - 0.0).abs() < 0.00001);
    assert!((c.transform.get()[1] - 1.0).abs() < 0.00001);
}

#[test]
fn test_scale() {
    let c = Context::new();
    let c = c.scale(2.0, 3.0);
    assert!((c.transform.get()[0] - 2.0).abs() < 0.00001);
    assert!((c.transform.get()[4] - 3.0).abs() < 0.00001);
}

impl<'a> AddRectangle<'a, RectangleContext<'a>> for Context<'a> {
    #[inline(always)]
    fn rect(&'a self, x: f64, y: f64, w: f64, h: f64) -> RectangleContext<'a> {
        RectangleContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value([x, y, w, h]),
        }
    }
}

#[test]
fn test_rect() {
    let c = Context::new();
    let d = c.rect(0.0, 0.0, 100.0, 50.0);
    assert_eq!(d.rect.get()[2], 100.0);
}

impl<'a> AddColor<'a, ColorContext<'a>> for Context<'a> {
    #[inline(always)]
    fn rgba(&'a self, r: f32, g: f32, b: f32, a: f32) -> ColorContext<'a> {
        ColorContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            color: Value([r, g, b, a]),
        }
    }
}

#[test]
fn test_rgba() {
    let c = Context::new();
    let d: ColorContext = c.rgba(1.0, 0.0, 0.0, 1.0);
    assert_eq!(d.color.get()[0], 1.0);
}

impl<'a> AddEllipse<'a, EllipseContext<'a>> for Context<'a> {
    #[inline(always)]
    fn ellipse(&'a self, x: f64, y: f64, w: f64, h: f64) -> EllipseContext<'a> {
        EllipseContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            rect: Value([x, y, w, h]),
        }
    }
}

#[test]
fn test_ellipse() {
    let c = Context::new();
    let d: EllipseContext = c.ellipse(0.0, 0.0, 100.0, 100.0);
    assert_eq!(d.rect.get()[2], 100.0);
}

impl<'a> AddPolygon<'a, PolygonContext<'a>> for Context<'a> {
    #[inline(always)]
    fn polygon(&'a self, polygon: &'a [f64]) -> PolygonContext<'a> {
        PolygonContext {
            base: Borrowed(self.base.get()),
            transform: Borrowed(self.transform.get()),
            polygon: Value(polygon),
        }
    }
}

<|endoftext|>


<commit_before>use ::monet::glium::{DisplayBuild, glutin};
use kay::{ActorSystem, ID, Individual, Recipient, Fate};
use descartes::{N, P2, P3, V3, Into2d, Shape};
use ::monet::{Renderer, Scene, GlutinFacade, MoveEye};
use ::monet::glium::glutin::{Event, MouseScrollDelta, ElementState, MouseButton};
pub use ::monet::glium::glutin::{VirtualKeyCode};
use core::geometry::AnyShape;
use ::std::collections::HashMap;

pub struct UserInterface {
    interactables_2d: HashMap<ID, (AnyShape, usize)>,
    interactables_3d: HashMap<ID, (AnyShape, usize)>,
    cursor_2d: P2,
    cursor_3d: P3,
    drag_start_2d: Option<P2>,
    drag_start_3d: Option<P3>,
    hovered_interactable: Option<ID>,
    active_interactable: Option<ID>,
    focused_interactable: Option<ID>,
    space_pressed: bool,
    alt_pressed: bool
}
impl Individual for UserInterface{}

impl UserInterface{
    fn new() -> UserInterface {
        UserInterface {
            interactables_2d: HashMap::new(),
            interactables_3d: HashMap::new(),
            cursor_2d: P2::new(0.0, 0.0),
            cursor_3d: P3::new(0.0, 0.0, 0.0),
            drag_start_2d: None,
            drag_start_3d: None,
            hovered_interactable: None,
            active_interactable: None,
            focused_interactable: None,
            space_pressed: false,
            alt_pressed: false
        }
    }
}

#[derive(Compact, Clone)]
pub enum Add{Interactable2d(ID, AnyShape, usize), Interactable3d(ID, AnyShape, usize)}

impl Recipient<Add> for UserInterface {
    fn receive(&mut self, msg: &Add) -> Fate {match *msg{
        Add::Interactable2d(_id, ref _shape, _z_index) => unimplemented!(),
        Add::Interactable3d(id, ref shape, z_index) => {
            self.interactables_3d.insert(id, (shape.clone(), z_index));
            Fate::Live
        }
    }}
}

#[derive(Copy, Clone)]
pub enum Remove{Interactable2d(ID), Interactable3d(ID)}

impl Recipient<Remove> for UserInterface {
    fn receive(&mut self, msg: &Remove) -> Fate {match *msg{
        Remove::Interactable2d(_id) => unimplemented!(),
        Remove::Interactable3d(id) => {
            self.interactables_3d.remove(&id);
            Fate::Live
        }
    }}
}

#[derive(Copy, Clone)]
pub struct Focus(pub ID);

impl Recipient<Focus> for UserInterface {
    fn receive(&mut self, msg: &Focus) -> Fate {match *msg{
        Focus(id) => {
            self.focused_interactable = Some(id);
            Fate::Live
        }
    }}
}

#[derive(Copy, Clone)]
enum Mouse{Moved(P2), Scrolled(P2), Down, Up}

use ::monet::Project2dTo3d;

#[derive(Copy, Clone)]
pub enum Event3d{
    DragStarted{at: P3},
    DragOngoing{from: P3, to: P3},
    DragFinished{from: P3, to: P3},
    DragAborted,
    HoverStarted{at: P3},
    HoverOngoing{at: P3},
    HoverStopped,
    KeyDown(VirtualKeyCode),
    KeyUp(VirtualKeyCode)
}

impl Recipient<Mouse> for UserInterface {
    fn receive(&mut self, msg: &Mouse) -> Fate {match *msg{
        Mouse::Moved(position) => {
            let delta = self.cursor_2d - position;
            if self.space_pressed {
                Renderer::id() << MoveEye{scene_id: 0, movement: ::monet::Movement::Shift(V3::new(-delta.y / 3.0, delta.x / 3.0, 0.0))};
                self.cursor_2d = position;
            } else if self.alt_pressed {
                Renderer::id() << MoveEye{scene_id: 0, movement: ::monet::Movement::Rotate(-delta.x/300.0)};
                Renderer::id() << MoveEye{scene_id: 0, movement: ::monet::Movement::Zoom(-delta.y)};
                self.cursor_2d = position;
            } else {
                self.cursor_2d = position;
                Renderer::id() << Project2dTo3d{
                    scene_id: 0,
                    position_2d: position,
                    requester: Self::id()
                };
            }
            Fate::Live
        },
        Mouse::Scrolled(delta) => {
            Renderer::id() << MoveEye{scene_id: 0, movement: ::monet::Movement::Shift(V3::new(delta.y / 5.0, -delta.x / 5.0, 0.0))};
            Fate::Live
        },
        Mouse::Down => {
            self.drag_start_2d = Some(self.cursor_2d);
            self.drag_start_3d = Some(self.cursor_3d);
            let cursor_3d = self.cursor_3d;
            self.receive(&Projected3d{position_3d: cursor_3d});
            self.active_interactable = self.hovered_interactable;
            if let Some(active_interactable) = self.active_interactable{
                active_interactable << Event3d::DragStarted{at: self.cursor_3d};
            }
            Fate::Live
        },
        Mouse::Up => {
            if let Some(active_interactable) = self.active_interactable {
                active_interactable << Event3d::DragFinished{
                    from: self.drag_start_3d.expect("active interactable but no drag start"),
                    to: self.cursor_3d
                };
            }
            self.drag_start_2d = None;
            self.drag_start_3d = None;
            self.active_interactable = None;
            Fate::Live
        }
    }}
}

#[derive(Copy, Clone)]
enum Key{Up(VirtualKeyCode), Down(VirtualKeyCode)}

impl Recipient<Key> for UserInterface {
    fn receive(&mut self, msg: &Key) -> Fate {match *msg {
        Key::Down(key_code) => {
            match key_code {
                VirtualKeyCode::Space => {
                    self.space_pressed = true;
                },
                VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => {
                    self.alt_pressed = true;
                },
                _ => {
                    self.focused_interactable.map(|interactable|
                        interactable << Event3d::KeyDown(key_code)
                    );
                }
            }
            Fate::Live
        },
        Key::Up(key_code) => {
            match key_code {
                VirtualKeyCode::Space => {
                    self.space_pressed = false;
                },
                VirtualKeyCode::LAlt | VirtualKeyCode::RAlt => {
                    self.alt_pressed = false;
                },
                _ => {
                    self.focused_interactable.map(|interactable|
                        interactable << Event3d::KeyUp(key_code)
                    );
                }
            }
            Fate::Live
        }
    }}
}

use ::monet::Projected3d;

impl Recipient<Projected3d> for UserInterface {
    fn receive(&mut self, msg: &Projected3d) -> Fate {match *msg{
        Projected3d{position_3d} => {
            self.cursor_3d = position_3d;
            if let Some(active_interactable) = self.active_interactable {
                active_interactable << Event3d::DragOngoing{
                    from: self.drag_start_3d.expect("active interactable but no drag start"),
                    to: position_3d
                };
            } else {
                let new_hovered_interactable = self.interactables_3d.iter().filter(|&(_id, &(ref shape, _z_index))|
                    shape.contains(position_3d.into_2d())
                ).max_by_key(|&(_id, &(ref _shape, z_index))|
                    z_index
                ).map(|(id, _shape)| *id);

                if self.hovered_interactable != new_hovered_interactable {
                    if let Some(previous) = self.hovered_interactable {
                        previous << Event3d::HoverStopped;
                    }
                    if let Some(next) = new_hovered_interactable {
                        next << Event3d::HoverStarted{at: self.cursor_3d};
                    }
                } else if let Some(hovered_interactable) = self.hovered_interactable {
                    hovered_interactable << Event3d::HoverOngoing{at: self.cursor_3d};
                }
                self.hovered_interactable = new_hovered_interactable;
            }
            Fate::Live
        }
    }}
}

pub fn setup_window_and_renderer(system: &mut ActorSystem, renderables: Vec<ID>) -> GlutinFacade {
    let window = glutin::WindowBuilder::new()
        .with_title("Citybound".to_string())
        .with_dimensions(1024, 512)
        .with_multitouch()
        .with_vsync().build_glium().unwrap();

    let ui = UserInterface::new();

    system.add_individual(ui);
    system.add_inbox::<Add, UserInterface>();
    system.add_inbox::<Remove, UserInterface>();
    system.add_inbox::<Focus, UserInterface>();
    system.add_unclearable_inbox::<Mouse, UserInterface>();
    system.add_unclearable_inbox::<Key, UserInterface>();
    system.add_unclearable_inbox::<Projected3d, UserInterface>();

    let mut renderer = Renderer::new(window.clone());
    let mut scene = Scene::new();
    scene.eye.position *= 30.0;
    scene.renderables = renderables;
    renderer.scenes.insert(0, scene);

    ::monet::setup(system, renderer);

    window
}

pub fn process_events(window: &GlutinFacade) -> bool {
    let mut cleaned_events = window.poll_events().collect::<Vec<_>>();
    if let Some(last_mouse_move_event_pos) = cleaned_events.iter().rposition(|event| match *event { Event::MouseMoved(..) => true, _ => false}) {
        let mut i = 0;
        cleaned_events.retain(|event| {
            let keep = match *event {
                Event::MouseMoved(..) => i == last_mouse_move_event_pos,
                _ => true
            };
            i += 1;
            keep
        });
    }
    for event in cleaned_events {
        match event {
            Event::Closed => return false,
            Event::MouseWheel(MouseScrollDelta::PixelDelta(x, y), _) =>
                UserInterface::id() << Mouse::Scrolled(P2::new(x as N, y as N)),
            Event::MouseMoved(x, y) =>
                UserInterface::id() << Mouse::Moved(P2::new(x as N, y as N)),
            Event::MouseInput(ElementState::Pressed, MouseButton::Left) =>
                UserInterface::id() << Mouse::Down,
            Event::MouseInput(ElementState::Released, MouseButton::Left) =>
                UserInterface::id() << Mouse::Up,
            Event::KeyboardInput(ElementState::Pressed, _, Some(key_code)) =>
                UserInterface::id() << Key::Down(key_code),
            Event::KeyboardInput(ElementState::Released, _, Some(key_code)) =>
                UserInterface::id() << Key::Up(key_code),
            _ => {}
        }
    }
    true
}<commit_msg>Change controls for zooming #22 #26<commit_after>use ::monet::glium::{DisplayBuild, glutin};
use kay::{ActorSystem, ID, Individual, Recipient, Fate};
use descartes::{N, P2, P3, V3, Into2d, Shape};
use ::monet::{Renderer, Scene, GlutinFacade, MoveEye};
use ::monet::glium::glutin::{Event, MouseScrollDelta, ElementState, MouseButton};
pub use ::monet::glium::glutin::{VirtualKeyCode};
use core::geometry::AnyShape;
use ::std::collections::HashMap;

pub struct UserInterface {
    interactables_2d: HashMap<ID, (AnyShape, usize)>,
    interactables_3d: HashMap<ID, (AnyShape, usize)>,
    cursor_2d: P2,
    cursor_3d: P3,
    drag_start_2d: Option<P2>,
    drag_start_3d: Option<P3>,
    hovered_interactable: Option<ID>,
    active_interactable: Option<ID>,
    focused_interactable: Option<ID>,
    space_pressed: bool,
    shift_pressed: bool
}
impl Individual for UserInterface{}

impl UserInterface{
    fn new() -> UserInterface {
        UserInterface {
            interactables_2d: HashMap::new(),
            interactables_3d: HashMap::new(),
            cursor_2d: P2::new(0.0, 0.0),
            cursor_3d: P3::new(0.0, 0.0, 0.0),
            drag_start_2d: None,
            drag_start_3d: None,
            hovered_interactable: None,
            active_interactable: None,
            focused_interactable: None,
            space_pressed: false,
            shift_pressed: false
        }
    }
}

#[derive(Compact, Clone)]
pub enum Add{Interactable2d(ID, AnyShape, usize), Interactable3d(ID, AnyShape, usize)}

impl Recipient<Add> for UserInterface {
    fn receive(&mut self, msg: &Add) -> Fate {match *msg{
        Add::Interactable2d(_id, ref _shape, _z_index) => unimplemented!(),
        Add::Interactable3d(id, ref shape, z_index) => {
            self.interactables_3d.insert(id, (shape.clone(), z_index));
            Fate::Live
        }
    }}
}

#[derive(Copy, Clone)]
pub enum Remove{Interactable2d(ID), Interactable3d(ID)}

impl Recipient<Remove> for UserInterface {
    fn receive(&mut self, msg: &Remove) -> Fate {match *msg{
        Remove::Interactable2d(_id) => unimplemented!(),
        Remove::Interactable3d(id) => {
            self.interactables_3d.remove(&id);
            Fate::Live
        }
    }}
}

#[derive(Copy, Clone)]
pub struct Focus(pub ID);

impl Recipient<Focus> for UserInterface {
    fn receive(&mut self, msg: &Focus) -> Fate {match *msg{
        Focus(id) => {
            self.focused_interactable = Some(id);
            Fate::Live
        }
    }}
}

#[derive(Copy, Clone)]
enum Mouse{Moved(P2), Scrolled(P2), Down, Up}

use ::monet::Project2dTo3d;

#[derive(Copy, Clone)]
pub enum Event3d{
    DragStarted{at: P3},
    DragOngoing{from: P3, to: P3},
    DragFinished{from: P3, to: P3},
    DragAborted,
    HoverStarted{at: P3},
    HoverOngoing{at: P3},
    HoverStopped,
    KeyDown(VirtualKeyCode),
    KeyUp(VirtualKeyCode)
}

impl Recipient<Mouse> for UserInterface {
    fn receive(&mut self, msg: &Mouse) -> Fate {match *msg{
        Mouse::Moved(position) => {
            let delta = self.cursor_2d - position;
            if self.space_pressed {
                if self.shift_pressed {
                    Renderer::id() << MoveEye{scene_id: 0, movement: ::monet::Movement::Rotate(-delta.x/300.0)};
                    Renderer::id() << MoveEye{scene_id: 0, movement: ::monet::Movement::Zoom(-delta.y)};
                    self.cursor_2d = position;
                } else {
                    Renderer::id() << MoveEye{scene_id: 0, movement: ::monet::Movement::Shift(V3::new(-delta.y / 3.0, delta.x / 3.0, 0.0))};
                    self.cursor_2d = position;
                }
            } else {
                self.cursor_2d = position;
                Renderer::id() << Project2dTo3d{
                    scene_id: 0,
                    position_2d: position,
                    requester: Self::id()
                };
            }
            Fate::Live
        },
        Mouse::Scrolled(delta) => {
            Renderer::id() << MoveEye{scene_id: 0, movement: ::monet::Movement::Shift(V3::new(delta.y / 5.0, -delta.x / 5.0, 0.0))};
            Fate::Live
        },
        Mouse::Down => {
            self.drag_start_2d = Some(self.cursor_2d);
            self.drag_start_3d = Some(self.cursor_3d);
            let cursor_3d = self.cursor_3d;
            self.receive(&Projected3d{position_3d: cursor_3d});
            self.active_interactable = self.hovered_interactable;
            if let Some(active_interactable) = self.active_interactable{
                active_interactable << Event3d::DragStarted{at: self.cursor_3d};
            }
            Fate::Live
        },
        Mouse::Up => {
            if let Some(active_interactable) = self.active_interactable {
                active_interactable << Event3d::DragFinished{
                    from: self.drag_start_3d.expect("active interactable but no drag start"),
                    to: self.cursor_3d
                };
            }
            self.drag_start_2d = None;
            self.drag_start_3d = None;
            self.active_interactable = None;
            Fate::Live
        }
    }}
}

#[derive(Copy, Clone)]
enum Key{Up(VirtualKeyCode), Down(VirtualKeyCode)}

impl Recipient<Key> for UserInterface {
    fn receive(&mut self, msg: &Key) -> Fate {match *msg {
        Key::Down(key_code) => {
            match key_code {
                VirtualKeyCode::Space => {
                    self.space_pressed = true;
                },
                VirtualKeyCode::LShift | VirtualKeyCode::RShift => {
                    self.shift_pressed = true;
                },
                _ => {}
            }
            self.focused_interactable.map(|interactable|
                interactable << Event3d::KeyDown(key_code)
            );
            Fate::Live
        },
        Key::Up(key_code) => {
            match key_code {
                VirtualKeyCode::Space => {
                    self.space_pressed = false;
                },
                VirtualKeyCode::LShift | VirtualKeyCode::RShift => {
                    self.shift_pressed = false;
                },
                _ => {}
            }
            self.focused_interactable.map(|interactable|
                interactable << Event3d::KeyUp(key_code)
            );
            Fate::Live
        }
    }}
}

use ::monet::Projected3d;

impl Recipient<Projected3d> for UserInterface {
    fn receive(&mut self, msg: &Projected3d) -> Fate {match *msg{
        Projected3d{position_3d} => {
            self.cursor_3d = position_3d;
            if let Some(active_interactable) = self.active_interactable {
                active_interactable << Event3d::DragOngoing{
                    from: self.drag_start_3d.expect("active interactable but no drag start"),
                    to: position_3d
                };
            } else {
                let new_hovered_interactable = self.interactables_3d.iter().filter(|&(_id, &(ref shape, _z_index))|
                    shape.contains(position_3d.into_2d())
                ).max_by_key(|&(_id, &(ref _shape, z_index))|
                    z_index
                ).map(|(id, _shape)| *id);

                if self.hovered_interactable != new_hovered_interactable {
                    if let Some(previous) = self.hovered_interactable {
                        previous << Event3d::HoverStopped;
                    }
                    if let Some(next) = new_hovered_interactable {
                        next << Event3d::HoverStarted{at: self.cursor_3d};
                    }
                } else if let Some(hovered_interactable) = self.hovered_interactable {
                    hovered_interactable << Event3d::HoverOngoing{at: self.cursor_3d};
                }
                self.hovered_interactable = new_hovered_interactable;
            }
            Fate::Live
        }
    }}
}

pub fn setup_window_and_renderer(system: &mut ActorSystem, renderables: Vec<ID>) -> GlutinFacade {
    let window = glutin::WindowBuilder::new()
        .with_title("Citybound".to_string())
        .with_dimensions(1024, 512)
        .with_multitouch()
        .with_vsync().build_glium().unwrap();

    let ui = UserInterface::new();

    system.add_individual(ui);
    system.add_inbox::<Add, UserInterface>();
    system.add_inbox::<Remove, UserInterface>();
    system.add_inbox::<Focus, UserInterface>();
    system.add_unclearable_inbox::<Mouse, UserInterface>();
    system.add_unclearable_inbox::<Key, UserInterface>();
    system.add_unclearable_inbox::<Projected3d, UserInterface>();

    let mut renderer = Renderer::new(window.clone());
    let mut scene = Scene::new();
    scene.eye.position *= 30.0;
    scene.renderables = renderables;
    renderer.scenes.insert(0, scene);

    ::monet::setup(system, renderer);

    window
}

pub fn process_events(window: &GlutinFacade) -> bool {
    let mut cleaned_events = window.poll_events().collect::<Vec<_>>();
    if let Some(last_mouse_move_event_pos) = cleaned_events.iter().rposition(|event| match *event { Event::MouseMoved(..) => true, _ => false}) {
        let mut i = 0;
        cleaned_events.retain(|event| {
            let keep = match *event {
                Event::MouseMoved(..) => i == last_mouse_move_event_pos,
                _ => true
            };
            i += 1;
            keep
        });
    }
    for event in cleaned_events {
        match event {
            Event::Closed => return false,
            Event::MouseWheel(MouseScrollDelta::PixelDelta(x, y), _) =>
                UserInterface::id() << Mouse::Scrolled(P2::new(x as N, y as N)),
            Event::MouseMoved(x, y) =>
                UserInterface::id() << Mouse::Moved(P2::new(x as N, y as N)),
            Event::MouseInput(ElementState::Pressed, MouseButton::Left) =>
                UserInterface::id() << Mouse::Down,
            Event::MouseInput(ElementState::Released, MouseButton::Left) =>
                UserInterface::id() << Mouse::Up,
            Event::KeyboardInput(ElementState::Pressed, _, Some(key_code)) =>
                UserInterface::id() << Key::Down(key_code),
            Event::KeyboardInput(ElementState::Released, _, Some(key_code)) =>
                UserInterface::id() << Key::Up(key_code),
            _ => {}
        }
    }
    true
}<|endoftext|>


<commit_before>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
#![feature(test)]
extern crate test;
extern crate fringe;
use fringe::Context;

static mut ctx_slot: *mut Context<'static, fringe::OsStack> = 0 as *mut Context<_>;

#[bench]
fn swap(b: &mut test::Bencher) {
  unsafe {
    let stack = fringe::OsStack::new(4 << 20).unwrap();

    let mut ctx = Context::new(stack, move || {
      let ctx_ptr = ctx_slot;
      loop {
        (*ctx_ptr).swap()
      }
    });

    ctx_slot = &mut ctx;

    ctx.swap();

    b.iter(|| ctx.swap());
  }
}
<commit_msg>only build benches/swap when OsStack is available<commit_after>// This file is part of libfringe, a low-level green threading library.
// Copyright (c) 2015, edef <edef@edef.eu>
// See the LICENSE file included in this distribution.
#![feature(test)]
#![cfg(feature = "os")]
extern crate test;
extern crate fringe;
use fringe::Context;

static mut ctx_slot: *mut Context<'static, fringe::OsStack> = 0 as *mut Context<_>;

#[bench]
fn swap(b: &mut test::Bencher) {
  unsafe {
    let stack = fringe::OsStack::new(4 << 20).unwrap();

    let mut ctx = Context::new(stack, move || {
      let ctx_ptr = ctx_slot;
      loop {
        (*ctx_ptr).swap()
      }
    });

    ctx_slot = &mut ctx;

    ctx.swap();

    b.iter(|| ctx.swap());
  }
}
<|endoftext|>


<commit_before>use interconnect::InterconnectWrite;
use glium::{self, DisplayBuild, Frame, Surface};
use glium::texture::RawImage2d;
use glium::texture::ClientFormat;
use utils::RGB;

pub struct Display {
    pub display: glium::backend::glutin_backend::GlutinFacade,
    pub program: glium::Program,
    pub buf: [u16; 240 * 160],
}

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
}

implement_vertex!(Vertex, position);

impl Display {
    pub fn new() -> Self {
        let display = glium::glutin::WindowBuilder::new()
            .with_dimensions(240 * 2, 160 * 2)
            .with_title("Game Boy Advance: Rusty Oxidation Action - The ROA Emulator")
            .build_glium()
            .unwrap();

        let width = 160;
        let height = 240;

        let vertex_shader_src = r#"
            in vec2 position;
            out vec2 vuv;

            void main() {
                vuv = position;
                gl_Position = vec4(position, 0.0, 1.0);
            }
        "#;

        let fragment_shader_src = r#"
            in vec2 vuv;
            out vec4 color;

            uniform sampler2D tex;

            void main() {
                color = texture(tex, vuv / 2.0 + 0.5);
            }
        "#;

        let program = glium::Program::from_source(&display,
                                                  vertex_shader_src,
                                                  fragment_shader_src,
                                                  None).unwrap();

        Display {
            display: display,
            program: program,
            buf: [0b0000_0000_0000_0000u16; 240 * 160],
        }
    }

    fn vsync(&self) {
        let shape = vec![
            Vertex { position: [-1.0, -1.0] },
            Vertex { position: [1.0, -1.0] },
            Vertex { position: [-1.0, 1.0] },
            Vertex { position: [-1.0, 1.0] },
            Vertex { position: [1.0, -1.0] },
            Vertex { position: [1.0, 1.0] },
        ];

        let vertex_buffer = glium::VertexBuffer::new(&self.display, &shape).unwrap();
        let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

        use std::borrow::Cow;
        let image = glium::texture::RawImage2d {
            data: Cow::from(&self.buf[..]),
            width: 240,
            height: 160,
            format: ClientFormat::U5U5U5U1,
        };

        let texture = glium::texture::Texture2d::new(&self.display, image).unwrap();
        let sampler = texture.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest);
        let uniforms = uniform! {
            tex: sampler,
        };

        let mut target = self.display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        target.draw(&vertex_buffer,
                    &indices,
                    &self.program,
                    &uniforms,
                    &Default::default()).unwrap();
        target.finish().unwrap();

    }
}

impl InterconnectWrite for Display {
    fn write(&mut self, address: u32, word: u32) {
        self.buf[address as usize] = word as u16;

        self.vsync();
    }
}
<commit_msg>Add version number to shaders<commit_after>use interconnect::InterconnectWrite;
use glium::{self, DisplayBuild, Frame, Surface};
use glium::texture::RawImage2d;
use glium::texture::ClientFormat;
use utils::RGB;

pub struct Display {
    pub display: glium::backend::glutin_backend::GlutinFacade,
    pub program: glium::Program,
    pub buf: [u16; 240 * 160],
}

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
}

implement_vertex!(Vertex, position);

impl Display {
    pub fn new() -> Self {
        let display = glium::glutin::WindowBuilder::new()
            .with_dimensions(240 * 2, 160 * 2)
            .with_title("Game Boy Advance: Rusty Oxidation Action - The ROA Emulator")
            .build_glium()
            .unwrap();

        let width = 160;
        let height = 240;

        let vertex_shader_src = r#"
            #version 140

            in vec2 position;
            out vec2 vuv;

            void main() {
                vuv = position;
                gl_Position = vec4(position, 0.0, 1.0);
            }
        "#;

        let fragment_shader_src = r#"
            #version 140

            in vec2 vuv;
            out vec4 color;

            uniform sampler2D tex;

            void main() {
                color = texture(tex, vuv / 2.0 + 0.5);
            }
        "#;

        let program = glium::Program::from_source(&display,
                                                  vertex_shader_src,
                                                  fragment_shader_src,
                                                  None).unwrap();

        Display {
            display: display,
            program: program,
            buf: [0b0000_0000_0000_0000u16; 240 * 160],
        }
    }

    fn vsync(&self) {
        let shape = vec![
            Vertex { position: [-1.0, -1.0] },
            Vertex { position: [1.0, -1.0] },
            Vertex { position: [-1.0, 1.0] },
            Vertex { position: [-1.0, 1.0] },
            Vertex { position: [1.0, -1.0] },
            Vertex { position: [1.0, 1.0] },
        ];

        let vertex_buffer = glium::VertexBuffer::new(&self.display, &shape).unwrap();
        let indices = glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList);

        use std::borrow::Cow;
        let image = glium::texture::RawImage2d {
            data: Cow::from(&self.buf[..]),
            width: 240,
            height: 160,
            format: ClientFormat::U5U5U5U1,
        };

        let texture = glium::texture::Texture2d::new(&self.display, image).unwrap();
        let sampler = texture.sampled().magnify_filter(glium::uniforms::MagnifySamplerFilter::Nearest);
        let uniforms = uniform! {
            tex: sampler,
        };

        let mut target = self.display.draw();
        target.clear_color(0.0, 0.0, 0.0, 1.0);
        target.draw(&vertex_buffer,
                    &indices,
                    &self.program,
                    &uniforms,
                    &Default::default()).unwrap();
        target.finish().unwrap();

    }
}

impl InterconnectWrite for Display {
    fn write(&mut self, address: u32, word: u32) {
        self.buf[address as usize] = word as u16;

        self.vsync();
    }
}
<|endoftext|>


<commit_before>extern crate postgres;
extern crate chrono;

#[cfg(test)]
mod tests;

use postgres::{Connection, SslMode, types};
use std::io::{self, Read};

#[derive(PartialEq, Debug)]
pub enum Align {
    Left,
    Right,
    Center,
}

#[allow(dead_code)]
#[derive(PartialEq, Debug)]
pub enum Color {
    White,
    BoldWhite,
    BoldRed,
    BoldGreen,
    BoldBlue,
}

pub fn color_text(text: &str, color: Color) -> String {
    let clrstr = match color {
        Color::White       => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[37m", text)        },
        Color::BoldWhite   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[37m", text) },
        Color::BoldRed     => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[31m", text) },
        Color::BoldGreen   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[32m", text) },
        Color::BoldBlue    => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[34m", text) },
    };

    clrstr
}

fn parse_result(column: &postgres::rows::Row, coltype: &Vec<types::Type>, colpos: usize) -> String {
    let val: String = match coltype[colpos] {
        types::Type::Text | types::Type::Varchar => column.get(colpos),
        types::Type::Bool => {
            let tmpbool: bool = column.get(colpos);
            match tmpbool {
                true  => String::from("true"),
                false => String::from("false"),
            }
        },
        types::Type::Int2 | types::Type::Int4 => {
            let tmpint: i32 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Int8 => {
            let tmpint: i64 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Float4 => {
            let tmpflt: f32 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Float8 => {
            let tmpflt: f64 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Timestamp => {
            let tmpdate: chrono::NaiveDateTime = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::TimestampTZ => {
            let tmpdate: chrono::DateTime<chrono::UTC> = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::Date => {
            let tmpdate: chrono::NaiveDate = column.get(colpos);
            tmpdate.format("%Y-%m-%d").to_string()
        },
        _ => String::from(""),
    };

    val
}

pub fn get_alignment(coltype: &types::Type) -> Align {
    match coltype {
        &types::Type::Int2          => Align::Right,
        &types::Type::Int4          => Align::Right,
        &types::Type::Int8          => Align::Right,
        &types::Type::Float4        => Align::Right,
        &types::Type::Float8        => Align::Right,
        &types::Type::Date          => Align::Right,
        &types::Type::Timestamp     => Align::Right,
        &types::Type::TimestampTZ   => Align::Right,
        _                           => Align::Left,
    }
}

pub fn pad_gen(len: usize, pad: &str) -> String {
    let mut padstr = String::from("");

    for _ in 0..len {
        padstr = padstr + pad;
    }

    padstr
}

pub fn format_field(column: &str, width: usize, align: Align) -> String {
    let padlen: usize = width - column.len();
    let extra: usize = padlen % 2;

    let ret: String = match align {
        Align::Center   => { format!("{}{}{}", pad_gen(padlen/2, " "), column, pad_gen((padlen/2)+extra, " ")) },
        Align::Right    => { format!("{}{}", pad_gen(padlen, " "), column) },
        Align::Left     => { format!("{}{}", column, pad_gen(padlen, " ")) },
    };

    ret
}

fn print_row(coltypes: &Vec<types::Type>, colwidths: &Vec<usize>, rowdata: &Vec<String>) {
    for (i, col) in rowdata.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!(" {} ", format_field(&col, colwidths[i], get_alignment(&coltypes[i])));
    }

    println!("");
}

fn print_header(colwidths: &Vec<usize>, colnames: &Vec<String>) {
    for (i, name) in colnames.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!(" {} ", color_text(&format_field(&name, colwidths[i], Align::Center), Color::BoldWhite));
    }

    println!("");
    for (i, col) in colwidths.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!("{}", color_text(&pad_gen(col+2, "-"), Color::BoldWhite));
    }

    println!("");
}

fn main() {
    let mut buf = String::new();
    let mut colnames: Vec<String> = Vec::new();
    let mut coldata: Vec<Vec<String>> = Vec::new();
    let mut colwidths: Vec<usize> = Vec::new();
    let mut coltypes: Vec<types::Type> = Vec::new();

    io::stdin().read_to_string(&mut buf);

    let conn = Connection::connect("postgres://jeff@localhost/feclink", SslMode::None).unwrap();
    let res = &conn.query(&mut buf, &[]).unwrap();
    let numcols = res.columns().len();

    for col in res.columns() {
        let colname = String::from(col.name());
        colwidths.push(colname.len());
        colnames.push(colname);
        coltypes.push(col.type_().clone());
    }

    for row in res.iter() {
        let mut colvals: Vec<String> = Vec::new();

        for i in 0..numcols {
            let ret = row.get_bytes(i);
            let col = if ret.is_some() { parse_result(&row, &coltypes, i) } else { String::from("") };

            if colwidths[i] < col.len() {
                colwidths[i] = col.len();
            }

            colvals.push(col);
        }

        coldata.push(colvals);
    }

    print_header(&colwidths, &colnames);
    for rowdata in coldata {
        print_row(&coltypes, &colwidths, &rowdata);
    }
}
<commit_msg>take a connection string on the command line<commit_after>extern crate postgres;
extern crate chrono;

#[cfg(test)]
mod tests;

use postgres::{Connection, SslMode, types};
use std::io::{self, Read};

#[derive(PartialEq, Debug)]
pub enum Align {
    Left,
    Right,
    Center,
}

#[allow(dead_code)]
#[derive(PartialEq, Debug)]
pub enum Color {
    White,
    BoldWhite,
    BoldRed,
    BoldGreen,
    BoldBlue,
}

pub fn color_text(text: &str, color: Color) -> String {
    let clrstr = match color {
        Color::White       => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[37m", text)        },
        Color::BoldWhite   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[37m", text) },
        Color::BoldRed     => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[31m", text) },
        Color::BoldGreen   => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[32m", text) },
        Color::BoldBlue    => { format!("{}{}\x1B[33m\x1B[0m", "\x1B[33m\x1B[1m\x1B[33m\x1B[34m", text) },
    };

    clrstr
}

fn parse_result(column: &postgres::rows::Row, coltype: &Vec<types::Type>, colpos: usize) -> String {
    let val: String = match coltype[colpos] {
        types::Type::Text | types::Type::Varchar => column.get(colpos),
        types::Type::Bool => {
            let tmpbool: bool = column.get(colpos);
            match tmpbool {
                true  => String::from("true"),
                false => String::from("false"),
            }
        },
        types::Type::Int2 | types::Type::Int4 => {
            let tmpint: i32 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Int8 => {
            let tmpint: i64 = column.get(colpos);
            tmpint.to_string()
        },
        types::Type::Float4 => {
            let tmpflt: f32 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Float8 => {
            let tmpflt: f64 = column.get(colpos);
            tmpflt.to_string()
        },
        types::Type::Timestamp => {
            let tmpdate: chrono::NaiveDateTime = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::TimestampTZ => {
            let tmpdate: chrono::DateTime<chrono::UTC> = column.get(colpos);
            tmpdate.format("%Y-%m-%d %H:%M:%s").to_string()
        },
        types::Type::Date => {
            let tmpdate: chrono::NaiveDate = column.get(colpos);
            tmpdate.format("%Y-%m-%d").to_string()
        },
        _ => String::from(""),
    };

    val
}

pub fn get_alignment(coltype: &types::Type) -> Align {
    match coltype {
        &types::Type::Int2          => Align::Right,
        &types::Type::Int4          => Align::Right,
        &types::Type::Int8          => Align::Right,
        &types::Type::Float4        => Align::Right,
        &types::Type::Float8        => Align::Right,
        &types::Type::Date          => Align::Right,
        &types::Type::Timestamp     => Align::Right,
        &types::Type::TimestampTZ   => Align::Right,
        _                           => Align::Left,
    }
}

pub fn pad_gen(len: usize, pad: &str) -> String {
    let mut padstr = String::from("");

    for _ in 0..len {
        padstr = padstr + pad;
    }

    padstr
}

pub fn format_field(column: &str, width: usize, align: Align) -> String {
    let padlen: usize = width - column.len();
    let extra: usize = padlen % 2;

    let ret: String = match align {
        Align::Center   => { format!("{}{}{}", pad_gen(padlen/2, " "), column, pad_gen((padlen/2)+extra, " ")) },
        Align::Right    => { format!("{}{}", pad_gen(padlen, " "), column) },
        Align::Left     => { format!("{}{}", column, pad_gen(padlen, " ")) },
    };

    ret
}

fn print_row(coltypes: &Vec<types::Type>, colwidths: &Vec<usize>, rowdata: &Vec<String>) {
    for (i, col) in rowdata.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!(" {} ", format_field(&col, colwidths[i], get_alignment(&coltypes[i])));
    }

    println!("");
}

fn print_header(colwidths: &Vec<usize>, colnames: &Vec<String>) {
    for (i, name) in colnames.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!(" {} ", color_text(&format_field(&name, colwidths[i], Align::Center), Color::BoldWhite));
    }

    println!("");
    for (i, col) in colwidths.iter().enumerate() {
        if i > 0 {
            print!("{}", color_text("|", Color::BoldWhite));
        }

        print!("{}", color_text(&pad_gen(col+2, "-"), Color::BoldWhite));
    }

    println!("");
}

fn main() {
    let mut buf = String::new();
    let mut colnames: Vec<String> = Vec::new();
    let mut coldata: Vec<Vec<String>> = Vec::new();
    let mut colwidths: Vec<usize> = Vec::new();
    let mut coltypes: Vec<types::Type> = Vec::new();
    let mut args = std::env::args();

    if args.len() == 1 {
        println!("{} {}", color_text("error:", Color::BoldRed), color_text("a DBURI is required!", Color::BoldWhite));
        std::process::exit(1);
    }

    let connstr: String = args.nth(1).unwrap();
    io::stdin().read_to_string(&mut buf);

    let conn = Connection::connect(&connstr as &str, SslMode::None).unwrap();
    let res = &conn.query(&mut buf, &[]).unwrap();
    let numcols = res.columns().len();

    for col in res.columns() {
        let colname = String::from(col.name());
        colwidths.push(colname.len());
        colnames.push(colname);
        coltypes.push(col.type_().clone());
    }

    for row in res.iter() {
        let mut colvals: Vec<String> = Vec::new();

        for i in 0..numcols {
            let ret = row.get_bytes(i);
            let col = if ret.is_some() { parse_result(&row, &coltypes, i) } else { String::from("") };

            if colwidths[i] < col.len() {
                colwidths[i] = col.len();
            }

            colvals.push(col);
        }

        coldata.push(colvals);
    }

    print_header(&colwidths, &colnames);
    for rowdata in coldata {
        print_row(&coltypes, &colwidths, &rowdata);
    }
}
<|endoftext|>