<commit_before>use std::time::Duration;
use std::{collections::HashMap, net::SocketAddr};

use anyhow::Result;
use crossbeam_channel::Sender;
use laminar::Packet;

use zombenum_shared::components::{Component, GameEntityId, PlayerId};
use zombenum_shared::messages::server::*;

/// This struct is used to accumulate all information that should be sent to users.
/// Each field is a collection of updates sorted by user id.
pub struct ScheduledUpdates {
    /// New entities.
    /// These have to be transmitted reliably.
    pub added_entities: HashMap<PlayerId, Vec<Vec<Component>>>,
    /// Critical components.
    /// These have to be transmitted reliably.
    pub critical_components: HashMap<PlayerId, Vec<(GameEntityId, Component)>>,
    /// Uncritical components.
    /// These updates will be sent, but can go missing.
    /// This is usually stuff that's rapidly updated all the time.
    pub uncritical_components: HashMap<PlayerId, Vec<(GameEntityId, Component)>>,
}

impl ScheduledUpdates {
    pub fn new() -> ScheduledUpdates {
        ScheduledUpdates {
            added_entities: HashMap::new(),
            critical_components: HashMap::new(),
            uncritical_components: HashMap::new(),
        }
    }

    pub fn add_critical_component(
        &mut self,
        player_id: PlayerId,
        entity_id: GameEntityId,
        component: Component,
    ) {
        let components = self
            .critical_components
            .entry(player_id)
            .or_insert(Vec::new());
        components.push((entity_id, component));
    }
}

/// Send all updates to their respective clients.
pub fn send_server_updates(
    sender: &Sender<Packet>,
    connected_users: &HashMap<SocketAddr, PlayerId>,
    session_time: Duration,
    scheduled_updates: &ScheduledUpdates,
) -> Result<()> {
    let mut reliable_messages: HashMap<PlayerId, ServerMessage> = HashMap::new();

    // Handle all new entities
    for (player_id, entities) in scheduled_updates.added_entities.iter() {
        // These entities should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected uesrs and add these entities to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for entity in entities {
                    entry.new_entities.push(entity.clone())
                }
            }

            continue;
        }

        // Get the user
        let entry = reliable_messages
            .entry(player_id.clone())
            .or_insert(ServerMessage::new(session_time));

        for entity in entities {
            entry.new_entities.push(entity.clone())
        }
    }

    // Handle all critical components
    for (player_id, components) in scheduled_updates.critical_components.iter() {
        // These components should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = reliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all critical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = reliable_messages.get(player_id) {
            sender.send(Packet::reliable_ordered(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    let mut unreliable_messages: HashMap<PlayerId, ServerMessage> = HashMap::new();

    // Handle all non-critical components
    for (player_id, components) in scheduled_updates.uncritical_components.iter() {
        // These components should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = unreliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = unreliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all uncritical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = unreliable_messages.get(player_id) {
            sender.send(Packet::reliable_ordered(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    Ok(())
}
<commit_msg>Fix copy-paste error and properly send uncritical stuff as unrealiable_sequenced<commit_after>use std::time::Duration;
use std::{collections::HashMap, net::SocketAddr};

use anyhow::Result;
use crossbeam_channel::Sender;
use laminar::Packet;

use zombenum_shared::components::{Component, GameEntityId, PlayerId};
use zombenum_shared::messages::server::*;

/// This struct is used to accumulate all information that should be sent to users.
/// Each field is a collection of updates sorted by user id.
pub struct ScheduledUpdates {
    /// New entities.
    /// These have to be transmitted reliably.
    pub added_entities: HashMap<PlayerId, Vec<Vec<Component>>>,
    /// Critical components.
    /// These have to be transmitted reliably.
    pub critical_components: HashMap<PlayerId, Vec<(GameEntityId, Component)>>,
    /// Uncritical components.
    /// These updates will be sent, but can go missing.
    /// This is usually stuff that's rapidly updated all the time.
    pub uncritical_components: HashMap<PlayerId, Vec<(GameEntityId, Component)>>,
}

impl ScheduledUpdates {
    pub fn new() -> ScheduledUpdates {
        ScheduledUpdates {
            added_entities: HashMap::new(),
            critical_components: HashMap::new(),
            uncritical_components: HashMap::new(),
        }
    }

    pub fn add_critical_component(
        &mut self,
        player_id: PlayerId,
        entity_id: GameEntityId,
        component: Component,
    ) {
        let components = self
            .critical_components
            .entry(player_id)
            .or_insert(Vec::new());
        components.push((entity_id, component));
    }
}

/// Send all updates to their respective clients.
pub fn send_server_updates(
    sender: &Sender<Packet>,
    connected_users: &HashMap<SocketAddr, PlayerId>,
    session_time: Duration,
    scheduled_updates: &ScheduledUpdates,
) -> Result<()> {
    let mut reliable_messages: HashMap<PlayerId, ServerMessage> = HashMap::new();

    // Handle all new entities
    for (player_id, entities) in scheduled_updates.added_entities.iter() {
        // These entities should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected uesrs and add these entities to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for entity in entities {
                    entry.new_entities.push(entity.clone())
                }
            }

            continue;
        }

        // Get the user
        let entry = reliable_messages
            .entry(player_id.clone())
            .or_insert(ServerMessage::new(session_time));

        for entity in entities {
            entry.new_entities.push(entity.clone())
        }
    }

    // Handle all critical components
    for (player_id, components) in scheduled_updates.critical_components.iter() {
        // These components should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = reliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = reliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all critical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = reliable_messages.get(player_id) {
            sender.send(Packet::reliable_ordered(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    let mut unreliable_messages: HashMap<PlayerId, ServerMessage> = HashMap::new();

    // Handle all non-critical components
    for (player_id, components) in scheduled_updates.uncritical_components.iter() {
        // These components should be sent to all users
        if *player_id == PlayerId::all_users() {
            // Iterate over all connected users and add these components to their message
            for player_id in connected_users.values() {
                let entry = unreliable_messages
                    .entry(player_id.clone())
                    .or_insert(ServerMessage::new(session_time));

                for component in components {
                    entry.changed_components.push(component.clone())
                }
            }

            continue;
        }

        for component in components {
            let entry = unreliable_messages
                .entry(player_id.clone())
                .or_insert(ServerMessage::new(session_time));

            entry.changed_components.push(component.clone())
        }
    }

    // Send all uncritical messages
    for (addr, player_id) in connected_users {
        if let Some(message) = unreliable_messages.get(player_id) {
            sender.send(Packet::unreliable_sequenced(
                *addr,
                bincode::serialize(message)?,
                None,
            ))?;
        };
    }

    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>Turns out I don't have an appropriate output device.<commit_after><|endoftext|>


<commit_before>use hir::{Adt, Either, PathResolution};
use ra_syntax::AstNode;
use test_utils::tested_by;

use crate::completion::{CompletionContext, Completions};

pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
    let path = match &ctx.path_prefix {
        Some(path) => path.clone(),
        _ => return,
    };
    let def = match dbg!(ctx.analyzer.resolve_hir_path(ctx.db, &path)) {
        Some(PathResolution::Def(def)) => def,
        _ => return,
    };
    match def {
        hir::ModuleDef::Module(module) => {
            let module_scope = module.scope(ctx.db);
            for (name, res) in module_scope.entries() {
                if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.take_types() {
                    if ctx.use_item_syntax.is_some() {
                        tested_by!(dont_complete_primitive_in_use);
                        continue;
                    }
                }
                if Some(module) == ctx.module {
                    if let Some(import) = res.import {
                        if let Either::A(use_tree) = module.import_source(ctx.db, import) {
                            if use_tree.syntax().text_range().contains_inclusive(ctx.offset) {
                                // for `use self::foo<|>`, don't suggest `foo` as a completion
                                tested_by!(dont_complete_current_use);
                                continue;
                            }
                        }
                    }
                }
                acc.add_resolution(ctx, name.to_string(), &res.def.into());
            }
        }
        hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => {
            if let hir::ModuleDef::Adt(Adt::Enum(e)) = def {
                for variant in e.variants(ctx.db) {
                    acc.add_enum_variant(ctx, variant);
                }
            }
            let ty = match def {
                hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
                hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
                _ => unreachable!(),
            };
            let krate = ctx.module.and_then(|m| m.krate(ctx.db));
            if let Some(krate) = krate {
                ty.iterate_impl_items(ctx.db, krate, |item| {
                    match item {
                        hir::ImplItem::Method(func) => {
                            let data = func.data(ctx.db);
                            if !data.has_self_param() {
                                acc.add_function(ctx, func);
                            }
                        }
                        hir::ImplItem::Const(ct) => acc.add_const(ctx, ct),
                        hir::ImplItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
                    }
                    None::<()>
                });
            }
        }
        _ => return,
    };
}

#[cfg(test)]
mod tests {
    use test_utils::covers;

    use crate::completion::{do_completion, CompletionItem, CompletionKind};
    use insta::assert_debug_snapshot;

    fn do_reference_completion(code: &str) -> Vec<CompletionItem> {
        do_completion(code, CompletionKind::Reference)
    }

    #[test]
    fn dont_complete_current_use() {
        covers!(dont_complete_current_use);
        let completions = do_completion(r"use self::foo<|>;", CompletionKind::Reference);
        assert!(completions.is_empty());
    }

    #[test]
    fn dont_complete_current_use_in_braces_with_glob() {
        let completions = do_completion(
            r"
            mod foo { pub struct S; }
            use self::{foo::*, bar<|>};
            ",
            CompletionKind::Reference,
        );
        assert_eq!(completions.len(), 2);
    }

    #[test]
    fn dont_complete_primitive_in_use() {
        covers!(dont_complete_primitive_in_use);
        let completions = do_completion(r"use self::<|>;", CompletionKind::BuiltinType);
        assert!(completions.is_empty());
    }

    #[test]
    fn completes_primitives() {
        let completions =
            do_completion(r"fn main() { let _: <|> = 92; }", CompletionKind::BuiltinType);
        assert_eq!(completions.len(), 17);
    }

    #[test]
    fn completes_mod_with_docs() {
        assert_debug_snapshot!(
            do_reference_completion(
                r"
                use self::my<|>;

                /// Some simple
                /// docs describing `mod my`.
                mod my {
                    struct Bar;
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "my",
        source_range: [27; 29),
        delete: [27; 29),
        insert: "my",
        kind: Module,
        documentation: Documentation(
            "Some simple\ndocs describing `mod my`.",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_use_item_starting_with_self() {
        assert_debug_snapshot!(
            do_reference_completion(
                r"
                use self::m::<|>;

                mod m {
                    struct Bar;
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "Bar",
        source_range: [30; 30),
        delete: [30; 30),
        insert: "Bar",
        kind: Struct,
    },
]"###
        );
    }

    #[test]
    fn completes_use_item_starting_with_crate() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                mod foo;
                struct Spam;
                //- /foo.rs
                use crate::Sp<|>
                "
            ),
            @r###"[
    CompletionItem {
        label: "Spam",
        source_range: [11; 13),
        delete: [11; 13),
        insert: "Spam",
        kind: Struct,
    },
    CompletionItem {
        label: "foo",
        source_range: [11; 13),
        delete: [11; 13),
        insert: "foo",
        kind: Module,
    },
]"###
        );
    }

    #[test]
    fn completes_nested_use_tree() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                mod foo;
                struct Spam;
                //- /foo.rs
                use crate::{Sp<|>};
                "
            ),
            @r###"[
    CompletionItem {
        label: "Spam",
        source_range: [12; 14),
        delete: [12; 14),
        insert: "Spam",
        kind: Struct,
    },
    CompletionItem {
        label: "foo",
        source_range: [12; 14),
        delete: [12; 14),
        insert: "foo",
        kind: Module,
    },
]"###
        );
    }

    #[test]
    fn completes_deeply_nested_use_tree() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                mod foo;
                pub mod bar {
                    pub mod baz {
                        pub struct Spam;
                    }
                }
                //- /foo.rs
                use crate::{bar::{baz::Sp<|>}};
                "
            ),
            @r###"[
    CompletionItem {
        label: "Spam",
        source_range: [23; 25),
        delete: [23; 25),
        insert: "Spam",
        kind: Struct,
    },
]"###
        );
    }

    #[test]
    fn completes_enum_variant() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// An enum
                enum E {
                    /// Foo Variant
                    Foo,
                    /// Bar Variant with i32
                    Bar(i32)
                }
                fn foo() { let _ = E::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "Bar",
        source_range: [116; 116),
        delete: [116; 116),
        insert: "Bar",
        kind: EnumVariant,
        detail: "(i32)",
        documentation: Documentation(
            "Bar Variant with i32",
        ),
    },
    CompletionItem {
        label: "Foo",
        source_range: [116; 116),
        delete: [116; 116),
        insert: "Foo",
        kind: EnumVariant,
        detail: "()",
        documentation: Documentation(
            "Foo Variant",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_enum_variant_with_details() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                struct S { field: u32 }
                /// An enum
                enum E {
                    /// Foo Variant (empty)
                    Foo,
                    /// Bar Variant with i32 and u32
                    Bar(i32, u32),
                    ///
                    S(S),
                }
                fn foo() { let _ = E::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "Bar",
        source_range: [180; 180),
        delete: [180; 180),
        insert: "Bar",
        kind: EnumVariant,
        detail: "(i32, u32)",
        documentation: Documentation(
            "Bar Variant with i32 and u32",
        ),
    },
    CompletionItem {
        label: "Foo",
        source_range: [180; 180),
        delete: [180; 180),
        insert: "Foo",
        kind: EnumVariant,
        detail: "()",
        documentation: Documentation(
            "Foo Variant (empty)",
        ),
    },
    CompletionItem {
        label: "S",
        source_range: [180; 180),
        delete: [180; 180),
        insert: "S",
        kind: EnumVariant,
        detail: "(S)",
        documentation: Documentation(
            "",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_struct_associated_method() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// A Struct
                struct S;

                impl S {
                    /// An associated method
                    fn m() { }
                }

                fn foo() { let _ = S::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "m",
        source_range: [100; 100),
        delete: [100; 100),
        insert: "m()$0",
        kind: Function,
        detail: "fn m()",
        documentation: Documentation(
            "An associated method",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_struct_associated_const() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// A Struct
                struct S;

                impl S {
                    /// An associated const
                    const C: i32 = 42;
                }

                fn foo() { let _ = S::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "C",
        source_range: [107; 107),
        delete: [107; 107),
        insert: "C",
        kind: Const,
        detail: "const C: i32 = 42;",
        documentation: Documentation(
            "An associated const",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_struct_associated_type() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// A Struct
                struct S;

                impl S {
                    /// An associated type
                    type T = i32;
                }

                fn foo() { let _ = S::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "T",
        source_range: [101; 101),
        delete: [101; 101),
        insert: "T",
        kind: TypeAlias,
        detail: "type T = i32;",
        documentation: Documentation(
            "An associated type",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_enum_associated_method() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// An enum
                enum S {};

                impl S {
                    /// An associated method
                    fn m() { }
                }

                fn foo() { let _ = S::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "m",
        source_range: [100; 100),
        delete: [100; 100),
        insert: "m()$0",
        kind: Function,
        detail: "fn m()",
        documentation: Documentation(
            "An associated method",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_union_associated_method() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// A union
                union U {};

                impl U {
                    /// An associated method
                    fn m() { }
                }

                fn foo() { let _ = U::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "m",
        source_range: [101; 101),
        delete: [101; 101),
        insert: "m()$0",
        kind: Function,
        detail: "fn m()",
        documentation: Documentation(
            "An associated method",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_use_paths_across_crates() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /main.rs
                use foo::<|>;

                //- /foo/lib.rs
                pub mod bar {
                    pub struct S;
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "bar",
        source_range: [9; 9),
        delete: [9; 9),
        insert: "bar",
        kind: Module,
    },
]"###
        );
    }

    #[test]
    fn completes_type_alias() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                struct S;
                impl S { fn foo() {} }
                type T = S;
                impl T { fn bar() {} }

                fn main() {
                    T::<|>;
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "bar",
        source_range: [185; 185),
        delete: [185; 185),
        insert: "bar()$0",
        kind: Function,
        detail: "fn bar()",
    },
    CompletionItem {
        label: "foo",
        source_range: [185; 185),
        delete: [185; 185),
        insert: "foo()$0",
        kind: Function,
        detail: "fn foo()",
    },
]"###
        );
    }

    #[test]
    fn completes_qualified_macros() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                #[macro_export]
                macro_rules! foo {
                    () => {}
                }

                fn main() {
                    let _ = crate::<|>
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "foo!",
        source_range: [179; 179),
        delete: [179; 179),
        insert: "foo!($0)",
        kind: Macro,
        detail: "#[macro_export]\nmacro_rules! foo",
    },
    CompletionItem {
        label: "main",
        source_range: [179; 179),
        delete: [179; 179),
        insert: "main()$0",
        kind: Function,
        detail: "fn main()",
    },
]"###
        );
    }
}
<commit_msg>Remove a dbg!<commit_after>use hir::{Adt, Either, PathResolution};
use ra_syntax::AstNode;
use test_utils::tested_by;

use crate::completion::{CompletionContext, Completions};

pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) {
    let path = match &ctx.path_prefix {
        Some(path) => path.clone(),
        _ => return,
    };
    let def = match ctx.analyzer.resolve_hir_path(ctx.db, &path) {
        Some(PathResolution::Def(def)) => def,
        _ => return,
    };
    match def {
        hir::ModuleDef::Module(module) => {
            let module_scope = module.scope(ctx.db);
            for (name, res) in module_scope.entries() {
                if let Some(hir::ModuleDef::BuiltinType(..)) = res.def.take_types() {
                    if ctx.use_item_syntax.is_some() {
                        tested_by!(dont_complete_primitive_in_use);
                        continue;
                    }
                }
                if Some(module) == ctx.module {
                    if let Some(import) = res.import {
                        if let Either::A(use_tree) = module.import_source(ctx.db, import) {
                            if use_tree.syntax().text_range().contains_inclusive(ctx.offset) {
                                // for `use self::foo<|>`, don't suggest `foo` as a completion
                                tested_by!(dont_complete_current_use);
                                continue;
                            }
                        }
                    }
                }
                acc.add_resolution(ctx, name.to_string(), &res.def.into());
            }
        }
        hir::ModuleDef::Adt(_) | hir::ModuleDef::TypeAlias(_) => {
            if let hir::ModuleDef::Adt(Adt::Enum(e)) = def {
                for variant in e.variants(ctx.db) {
                    acc.add_enum_variant(ctx, variant);
                }
            }
            let ty = match def {
                hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
                hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
                _ => unreachable!(),
            };
            let krate = ctx.module.and_then(|m| m.krate(ctx.db));
            if let Some(krate) = krate {
                ty.iterate_impl_items(ctx.db, krate, |item| {
                    match item {
                        hir::ImplItem::Method(func) => {
                            let data = func.data(ctx.db);
                            if !data.has_self_param() {
                                acc.add_function(ctx, func);
                            }
                        }
                        hir::ImplItem::Const(ct) => acc.add_const(ctx, ct),
                        hir::ImplItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
                    }
                    None::<()>
                });
            }
        }
        _ => return,
    };
}

#[cfg(test)]
mod tests {
    use test_utils::covers;

    use crate::completion::{do_completion, CompletionItem, CompletionKind};
    use insta::assert_debug_snapshot;

    fn do_reference_completion(code: &str) -> Vec<CompletionItem> {
        do_completion(code, CompletionKind::Reference)
    }

    #[test]
    fn dont_complete_current_use() {
        covers!(dont_complete_current_use);
        let completions = do_completion(r"use self::foo<|>;", CompletionKind::Reference);
        assert!(completions.is_empty());
    }

    #[test]
    fn dont_complete_current_use_in_braces_with_glob() {
        let completions = do_completion(
            r"
            mod foo { pub struct S; }
            use self::{foo::*, bar<|>};
            ",
            CompletionKind::Reference,
        );
        assert_eq!(completions.len(), 2);
    }

    #[test]
    fn dont_complete_primitive_in_use() {
        covers!(dont_complete_primitive_in_use);
        let completions = do_completion(r"use self::<|>;", CompletionKind::BuiltinType);
        assert!(completions.is_empty());
    }

    #[test]
    fn completes_primitives() {
        let completions =
            do_completion(r"fn main() { let _: <|> = 92; }", CompletionKind::BuiltinType);
        assert_eq!(completions.len(), 17);
    }

    #[test]
    fn completes_mod_with_docs() {
        assert_debug_snapshot!(
            do_reference_completion(
                r"
                use self::my<|>;

                /// Some simple
                /// docs describing `mod my`.
                mod my {
                    struct Bar;
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "my",
        source_range: [27; 29),
        delete: [27; 29),
        insert: "my",
        kind: Module,
        documentation: Documentation(
            "Some simple\ndocs describing `mod my`.",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_use_item_starting_with_self() {
        assert_debug_snapshot!(
            do_reference_completion(
                r"
                use self::m::<|>;

                mod m {
                    struct Bar;
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "Bar",
        source_range: [30; 30),
        delete: [30; 30),
        insert: "Bar",
        kind: Struct,
    },
]"###
        );
    }

    #[test]
    fn completes_use_item_starting_with_crate() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                mod foo;
                struct Spam;
                //- /foo.rs
                use crate::Sp<|>
                "
            ),
            @r###"[
    CompletionItem {
        label: "Spam",
        source_range: [11; 13),
        delete: [11; 13),
        insert: "Spam",
        kind: Struct,
    },
    CompletionItem {
        label: "foo",
        source_range: [11; 13),
        delete: [11; 13),
        insert: "foo",
        kind: Module,
    },
]"###
        );
    }

    #[test]
    fn completes_nested_use_tree() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                mod foo;
                struct Spam;
                //- /foo.rs
                use crate::{Sp<|>};
                "
            ),
            @r###"[
    CompletionItem {
        label: "Spam",
        source_range: [12; 14),
        delete: [12; 14),
        insert: "Spam",
        kind: Struct,
    },
    CompletionItem {
        label: "foo",
        source_range: [12; 14),
        delete: [12; 14),
        insert: "foo",
        kind: Module,
    },
]"###
        );
    }

    #[test]
    fn completes_deeply_nested_use_tree() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                mod foo;
                pub mod bar {
                    pub mod baz {
                        pub struct Spam;
                    }
                }
                //- /foo.rs
                use crate::{bar::{baz::Sp<|>}};
                "
            ),
            @r###"[
    CompletionItem {
        label: "Spam",
        source_range: [23; 25),
        delete: [23; 25),
        insert: "Spam",
        kind: Struct,
    },
]"###
        );
    }

    #[test]
    fn completes_enum_variant() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// An enum
                enum E {
                    /// Foo Variant
                    Foo,
                    /// Bar Variant with i32
                    Bar(i32)
                }
                fn foo() { let _ = E::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "Bar",
        source_range: [116; 116),
        delete: [116; 116),
        insert: "Bar",
        kind: EnumVariant,
        detail: "(i32)",
        documentation: Documentation(
            "Bar Variant with i32",
        ),
    },
    CompletionItem {
        label: "Foo",
        source_range: [116; 116),
        delete: [116; 116),
        insert: "Foo",
        kind: EnumVariant,
        detail: "()",
        documentation: Documentation(
            "Foo Variant",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_enum_variant_with_details() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                struct S { field: u32 }
                /// An enum
                enum E {
                    /// Foo Variant (empty)
                    Foo,
                    /// Bar Variant with i32 and u32
                    Bar(i32, u32),
                    ///
                    S(S),
                }
                fn foo() { let _ = E::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "Bar",
        source_range: [180; 180),
        delete: [180; 180),
        insert: "Bar",
        kind: EnumVariant,
        detail: "(i32, u32)",
        documentation: Documentation(
            "Bar Variant with i32 and u32",
        ),
    },
    CompletionItem {
        label: "Foo",
        source_range: [180; 180),
        delete: [180; 180),
        insert: "Foo",
        kind: EnumVariant,
        detail: "()",
        documentation: Documentation(
            "Foo Variant (empty)",
        ),
    },
    CompletionItem {
        label: "S",
        source_range: [180; 180),
        delete: [180; 180),
        insert: "S",
        kind: EnumVariant,
        detail: "(S)",
        documentation: Documentation(
            "",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_struct_associated_method() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// A Struct
                struct S;

                impl S {
                    /// An associated method
                    fn m() { }
                }

                fn foo() { let _ = S::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "m",
        source_range: [100; 100),
        delete: [100; 100),
        insert: "m()$0",
        kind: Function,
        detail: "fn m()",
        documentation: Documentation(
            "An associated method",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_struct_associated_const() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// A Struct
                struct S;

                impl S {
                    /// An associated const
                    const C: i32 = 42;
                }

                fn foo() { let _ = S::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "C",
        source_range: [107; 107),
        delete: [107; 107),
        insert: "C",
        kind: Const,
        detail: "const C: i32 = 42;",
        documentation: Documentation(
            "An associated const",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_struct_associated_type() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// A Struct
                struct S;

                impl S {
                    /// An associated type
                    type T = i32;
                }

                fn foo() { let _ = S::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "T",
        source_range: [101; 101),
        delete: [101; 101),
        insert: "T",
        kind: TypeAlias,
        detail: "type T = i32;",
        documentation: Documentation(
            "An associated type",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_enum_associated_method() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// An enum
                enum S {};

                impl S {
                    /// An associated method
                    fn m() { }
                }

                fn foo() { let _ = S::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "m",
        source_range: [100; 100),
        delete: [100; 100),
        insert: "m()$0",
        kind: Function,
        detail: "fn m()",
        documentation: Documentation(
            "An associated method",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_union_associated_method() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /lib.rs
                /// A union
                union U {};

                impl U {
                    /// An associated method
                    fn m() { }
                }

                fn foo() { let _ = U::<|> }
                "
            ),
            @r###"[
    CompletionItem {
        label: "m",
        source_range: [101; 101),
        delete: [101; 101),
        insert: "m()$0",
        kind: Function,
        detail: "fn m()",
        documentation: Documentation(
            "An associated method",
        ),
    },
]"###
        );
    }

    #[test]
    fn completes_use_paths_across_crates() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                //- /main.rs
                use foo::<|>;

                //- /foo/lib.rs
                pub mod bar {
                    pub struct S;
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "bar",
        source_range: [9; 9),
        delete: [9; 9),
        insert: "bar",
        kind: Module,
    },
]"###
        );
    }

    #[test]
    fn completes_type_alias() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                struct S;
                impl S { fn foo() {} }
                type T = S;
                impl T { fn bar() {} }

                fn main() {
                    T::<|>;
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "bar",
        source_range: [185; 185),
        delete: [185; 185),
        insert: "bar()$0",
        kind: Function,
        detail: "fn bar()",
    },
    CompletionItem {
        label: "foo",
        source_range: [185; 185),
        delete: [185; 185),
        insert: "foo()$0",
        kind: Function,
        detail: "fn foo()",
    },
]"###
        );
    }

    #[test]
    fn completes_qualified_macros() {
        assert_debug_snapshot!(
            do_reference_completion(
                "
                #[macro_export]
                macro_rules! foo {
                    () => {}
                }

                fn main() {
                    let _ = crate::<|>
                }
                "
            ),
            @r###"[
    CompletionItem {
        label: "foo!",
        source_range: [179; 179),
        delete: [179; 179),
        insert: "foo!($0)",
        kind: Macro,
        detail: "#[macro_export]\nmacro_rules! foo",
    },
    CompletionItem {
        label: "main",
        source_range: [179; 179),
        delete: [179; 179),
        insert: "main()$0",
        kind: Function,
        detail: "fn main()",
    },
]"###
        );
    }
}
<|endoftext|>


<commit_before>use crate::draw::drawing::DrawingContext;
use crate::draw::primitive::Primitive;
use crate::draw::properties::spatial::{self, dimension, orientation, position};
use crate::draw::properties::{
    ColorScalar, Draw, Drawn, LinSrgba, SetColor, SetDimensions, SetOrientation, SetPosition,
};
use crate::draw::{self, theme, Drawing, IntoDrawn};
use crate::geom::{self, Vector2};
use crate::math::BaseFloat;
use crate::text::{self, Align, Font, FontSize, Justify, Layout, Scalar, Wrap};

/// Properties related to drawing the **Text** primitive.
#[derive(Clone, Debug)]
pub struct Text<S = geom::scalar::Default> {
    spatial: spatial::Properties<S>,
    style: Style,
    // The byte range into the `Draw` context's text buffer.
    text: std::ops::Range<usize>,
}

/// Styling properties for the **Text** primitive.
#[derive(Clone, Debug, Default)]
pub struct Style {
    pub color: Option<LinSrgba>,
    pub layout: text::layout::Builder,
}

/// The drawing context for the **Text** primitive.
pub type DrawingText<'a, S = geom::scalar::Default> = Drawing<'a, Text<S>, S>;

impl<S> Text<S> {
    /// Begin drawing some text.
    pub fn new(ctxt: DrawingContext<S>, text: &str) -> Self {
        let start = ctxt.text_buffer.len();
        ctxt.text_buffer.push_str(text);
        let end = ctxt.text_buffer.len();
        let text = start..end;
        let spatial = Default::default();
        let style = Default::default();
        Text {
            spatial,
            style,
            text,
        }
    }

    // Apply the given function to the inner text layout.
    fn map_layout<F>(mut self, map: F) -> Self
    where
        F: FnOnce(text::layout::Builder) -> text::layout::Builder,
    {
        self.style.layout = map(self.style.layout);
        self
    }

    /// The font size to use for the text.
    pub fn font_size(self, size: FontSize) -> Self {
        self.map_layout(|l| l.font_size(size))
    }

    /// Specify whether or not text should be wrapped around some width and how to do so.
    ///
    /// The default value is `DEFAULT_LINE_WRAP`.
    pub fn line_wrap(self, line_wrap: Option<Wrap>) -> Self {
        self.map_layout(|l| l.line_wrap(line_wrap))
    }

    /// Specify that the **Text** should not wrap lines around the width.
    ///
    /// Shorthand for `builder.line_wrap(None)`.
    pub fn no_line_wrap(self) -> Self {
        self.map_layout(|l| l.no_line_wrap())
    }

    /// Line wrap the **Text** at the beginning of the first word that exceeds the width.
    ///
    /// Shorthand for `builder.line_wrap(Some(Wrap::Whitespace))`.
    pub fn wrap_by_word(self) -> Self {
        self.map_layout(|l| l.wrap_by_word())
    }

    /// Line wrap the **Text** at the beginning of the first character that exceeds the width.
    ///
    /// Shorthand for `builder.line_wrap(Some(Wrap::Character))`.
    pub fn wrap_by_character(self) -> Self {
        self.map_layout(|l| l.wrap_by_character())
    }

    /// A method for specifying the `Font` used for displaying the `Text`.
    pub fn font(self, font: Font) -> Self {
        self.map_layout(|l| l.font(font))
    }

    /// Describe the end along the *x* axis to which the text should be aligned.
    pub fn justify(self, justify: Justify) -> Self {
        self.map_layout(|l| l.justify(justify))
    }

    /// Align the text to the left of its bounding **Rect**'s *x* axis range.
    pub fn left_justify(self) -> Self {
        self.map_layout(|l| l.left_justify())
    }

    /// Align the text to the middle of its bounding **Rect**'s *x* axis range.
    pub fn center_justify(self) -> Self {
        self.map_layout(|l| l.center_justify())
    }

    /// Align the text to the right of its bounding **Rect**'s *x* axis range.
    pub fn right_justify(self) -> Self {
        self.map_layout(|l| l.right_justify())
    }

    /// Specify how much vertical space should separate each line of text.
    pub fn line_spacing(self, spacing: Scalar) -> Self {
        self.map_layout(|l| l.line_spacing(spacing))
    }

    /// Specify how the whole text should be aligned along the y axis of its bounding rectangle
    pub fn y_align(self, align: Align) -> Self {
        self.map_layout(|l| l.y_align(align))
    }

    /// Align the top edge of the text with the top edge of its bounding rectangle.
    pub fn align_top(self) -> Self {
        self.map_layout(|l| l.align_top())
    }

    /// Align the middle of the text with the middle of the bounding rect along the y axis..
    ///
    /// This is the default behaviour.
    pub fn align_middle_y(self) -> Self {
        self.map_layout(|l| l.align_middle_y())
    }

    /// Align the bottom edge of the text with the bottom edge of its bounding rectangle.
    pub fn align_bottom(self) -> Self {
        self.map_layout(|l| l.align_bottom())
    }

    /// Set all the parameters via an existing `Layout`
    pub fn layout(self, layout: &Layout) -> Self {
        self.map_layout(|l| l.layout(layout))
    }

    /// Specify the entire styling for the **Text**.
    pub fn with_style(mut self, style: Style) -> Self {
        self.style = style;
        self
    }
}

impl<'a, S> DrawingText<'a, S>
where
    S: BaseFloat,
{
    /// The font size to use for the text.
    pub fn font_size(self, size: text::FontSize) -> Self {
        self.map_ty(|ty| ty.font_size(size))
    }

    /// Specify that the **Text** should not wrap lines around the width.
    pub fn no_line_wrap(self) -> Self {
        self.map_ty(|ty| ty.no_line_wrap())
    }

    /// Line wrap the **Text** at the beginning of the first word that exceeds the width.
    pub fn wrap_by_word(self) -> Self {
        self.map_ty(|ty| ty.wrap_by_word())
    }

    /// Line wrap the **Text** at the beginning of the first character that exceeds the width.
    pub fn wrap_by_character(self) -> Self {
        self.map_ty(|ty| ty.wrap_by_character())
    }

    /// A method for specifying the `Font` used for displaying the `Text`.
    pub fn font(self, font: text::Font) -> Self {
        self.map_ty(|ty| ty.font(font))
    }

    /// Build the **Text** with the given **Style**.
    pub fn with_style(self, style: Style) -> Self {
        self.map_ty(|ty| ty.with_style(style))
    }

    /// Describe the end along the *x* axis to which the text should be aligned.
    pub fn justify(self, justify: text::Justify) -> Self {
        self.map_ty(|ty| ty.justify(justify))
    }

    /// Align the text to the left of its bounding **Rect**'s *x* axis range.
    pub fn left_justify(self) -> Self {
        self.map_ty(|ty| ty.left_justify())
    }

    /// Align the text to the middle of its bounding **Rect**'s *x* axis range.
    pub fn center_justify(self) -> Self {
        self.map_ty(|ty| ty.center_justify())
    }

    /// Align the text to the right of its bounding **Rect**'s *x* axis range.
    pub fn right_justify(self) -> Self {
        self.map_ty(|ty| ty.right_justify())
    }

    /// Specify how much vertical space should separate each line of text.
    pub fn line_spacing(self, spacing: text::Scalar) -> Self {
        self.map_ty(|ty| ty.line_spacing(spacing))
    }

    /// Specify how the whole text should be aligned along the y axis of its bounding rectangle
    pub fn y_align_text(self, align: Align) -> Self {
        self.map_ty(|ty| ty.y_align(align))
    }

    /// Align the top edge of the text with the top edge of its bounding rectangle.
    pub fn align_text_top(self) -> Self {
        self.map_ty(|ty| ty.align_top())
    }

    /// Align the middle of the text with the middle of the bounding rect along the y axis..
    ///
    /// This is the default behaviour.
    pub fn align_text_middle_y(self) -> Self {
        self.map_ty(|ty| ty.align_middle_y())
    }

    /// Align the bottom edge of the text with the bottom edge of its bounding rectangle.
    pub fn align_text_bottom(self) -> Self {
        self.map_ty(|ty| ty.align_bottom())
    }

    /// Set all the parameters via an existing `Layout`
    pub fn layout(self, layout: &Layout) -> Self {
        self.map_ty(|ty| ty.layout(layout))
    }
}

impl<S> IntoDrawn<S> for Text<S>
where
    S: BaseFloat,
{
    type Vertices = draw::properties::VerticesFromRanges;
    type Indices = draw::properties::IndicesFromRange;
    fn into_drawn(self, mut draw: Draw<S>) -> Drawn<S, Self::Vertices, Self::Indices> {
        let Text {
            spatial,
            style,
            text,
        } = self;
        let Style { color, layout } = style;
        let layout = layout.build();
        let (maybe_x, maybe_y, maybe_z) = spatial.dimensions.to_scalars(&draw);
        assert!(
            maybe_z.is_none(),
            "z dimension support for text is unimplemented"
        );
        let w = maybe_x
            .map(|s| <f32 as crate::math::NumCast>::from(s).unwrap())
            .unwrap_or(200.0);
        let h = maybe_y
            .map(|s| <f32 as crate::math::NumCast>::from(s).unwrap())
            .unwrap_or(200.0);
        let rect: geom::Rect = geom::Rect::from_wh(Vector2 { x: w, y: h });
        let color = color.unwrap_or_else(|| draw.theme().fill_lin_srgba(&theme::Primitive::Text));
        let path = draw.drawing_context(|ctxt| {
            let DrawingContext {
                mesh,
                fill_tessellator,
                path_event_buffer,
                text_buffer,
                glyph_cache,
            } = ctxt;
            let text_str = &text_buffer[text.clone()];
            let text = text::text(text_str).layout(&layout).build(rect);

            // TODO:
            // - Using `Path` is very slow - we should be caching glyphs.
            // - Can't do the CPU raster of the text here due to not knowing the DPI.
            // - We don't know the DPI until we finally draw to the frame.
            // - We should switch `Draw` to yield "primitives" rather than directly yielding
            //   vertices and indices. This way we can handle the text raster later on and can
            //   continue to ignore information about the window and DPI until finally drawing to
            //   the frame.
            use draw::primitive::path::PathInit;
            let path: PathInit<S> = Default::default();
            let mut empty_text = String::new();
            let ctxt = DrawingContext {
                mesh,
                fill_tessellator,
                path_event_buffer,
                glyph_cache,
                text_buffer: &mut empty_text,
            };
            let path = path.fill().color(color).events(ctxt, text.path_events());
            path
        });
        path.into_drawn(draw)
    }
}

impl<S> SetOrientation<S> for Text<S> {
    fn properties(&mut self) -> &mut orientation::Properties<S> {
        SetOrientation::properties(&mut self.spatial)
    }
}

impl<S> SetPosition<S> for Text<S> {
    fn properties(&mut self) -> &mut position::Properties<S> {
        SetPosition::properties(&mut self.spatial)
    }
}

impl<S> SetDimensions<S> for Text<S> {
    fn properties(&mut self) -> &mut dimension::Properties<S> {
        SetDimensions::properties(&mut self.spatial)
    }
}

impl<S> SetColor<ColorScalar> for Text<S> {
    fn rgba_mut(&mut self) -> &mut Option<LinSrgba> {
        SetColor::rgba_mut(&mut self.style.color)
    }
}

// Primitive conversions.

impl<S> From<Text<S>> for Primitive<S> {
    fn from(prim: Text<S>) -> Self {
        Primitive::Text(prim)
    }
}

impl<S> Into<Option<Text<S>>> for Primitive<S> {
    fn into(self) -> Option<Text<S>> {
        match self {
            Primitive::Text(prim) => Some(prim),
            _ => None,
        }
    }
}
<commit_msg>Fix an issue where text position and orientation went unused<commit_after>use crate::draw::drawing::DrawingContext;
use crate::draw::primitive::Primitive;
use crate::draw::properties::spatial::{self, dimension, orientation, position};
use crate::draw::properties::{
    ColorScalar, Draw, Drawn, LinSrgba, SetColor, SetDimensions, SetOrientation, SetPosition,
};
use crate::draw::{self, theme, Drawing, IntoDrawn};
use crate::geom::{self, Vector2};
use crate::math::BaseFloat;
use crate::text::{self, Align, Font, FontSize, Justify, Layout, Scalar, Wrap};

/// Properties related to drawing the **Text** primitive.
#[derive(Clone, Debug)]
pub struct Text<S = geom::scalar::Default> {
    spatial: spatial::Properties<S>,
    style: Style,
    // The byte range into the `Draw` context's text buffer.
    text: std::ops::Range<usize>,
}

/// Styling properties for the **Text** primitive.
#[derive(Clone, Debug, Default)]
pub struct Style {
    pub color: Option<LinSrgba>,
    pub layout: text::layout::Builder,
}

/// The drawing context for the **Text** primitive.
pub type DrawingText<'a, S = geom::scalar::Default> = Drawing<'a, Text<S>, S>;

impl<S> Text<S> {
    /// Begin drawing some text.
    pub fn new(ctxt: DrawingContext<S>, text: &str) -> Self {
        let start = ctxt.text_buffer.len();
        ctxt.text_buffer.push_str(text);
        let end = ctxt.text_buffer.len();
        let text = start..end;
        let spatial = Default::default();
        let style = Default::default();
        Text {
            spatial,
            style,
            text,
        }
    }

    // Apply the given function to the inner text layout.
    fn map_layout<F>(mut self, map: F) -> Self
    where
        F: FnOnce(text::layout::Builder) -> text::layout::Builder,
    {
        self.style.layout = map(self.style.layout);
        self
    }

    /// The font size to use for the text.
    pub fn font_size(self, size: FontSize) -> Self {
        self.map_layout(|l| l.font_size(size))
    }

    /// Specify whether or not text should be wrapped around some width and how to do so.
    ///
    /// The default value is `DEFAULT_LINE_WRAP`.
    pub fn line_wrap(self, line_wrap: Option<Wrap>) -> Self {
        self.map_layout(|l| l.line_wrap(line_wrap))
    }

    /// Specify that the **Text** should not wrap lines around the width.
    ///
    /// Shorthand for `builder.line_wrap(None)`.
    pub fn no_line_wrap(self) -> Self {
        self.map_layout(|l| l.no_line_wrap())
    }

    /// Line wrap the **Text** at the beginning of the first word that exceeds the width.
    ///
    /// Shorthand for `builder.line_wrap(Some(Wrap::Whitespace))`.
    pub fn wrap_by_word(self) -> Self {
        self.map_layout(|l| l.wrap_by_word())
    }

    /// Line wrap the **Text** at the beginning of the first character that exceeds the width.
    ///
    /// Shorthand for `builder.line_wrap(Some(Wrap::Character))`.
    pub fn wrap_by_character(self) -> Self {
        self.map_layout(|l| l.wrap_by_character())
    }

    /// A method for specifying the `Font` used for displaying the `Text`.
    pub fn font(self, font: Font) -> Self {
        self.map_layout(|l| l.font(font))
    }

    /// Describe the end along the *x* axis to which the text should be aligned.
    pub fn justify(self, justify: Justify) -> Self {
        self.map_layout(|l| l.justify(justify))
    }

    /// Align the text to the left of its bounding **Rect**'s *x* axis range.
    pub fn left_justify(self) -> Self {
        self.map_layout(|l| l.left_justify())
    }

    /// Align the text to the middle of its bounding **Rect**'s *x* axis range.
    pub fn center_justify(self) -> Self {
        self.map_layout(|l| l.center_justify())
    }

    /// Align the text to the right of its bounding **Rect**'s *x* axis range.
    pub fn right_justify(self) -> Self {
        self.map_layout(|l| l.right_justify())
    }

    /// Specify how much vertical space should separate each line of text.
    pub fn line_spacing(self, spacing: Scalar) -> Self {
        self.map_layout(|l| l.line_spacing(spacing))
    }

    /// Specify how the whole text should be aligned along the y axis of its bounding rectangle
    pub fn y_align(self, align: Align) -> Self {
        self.map_layout(|l| l.y_align(align))
    }

    /// Align the top edge of the text with the top edge of its bounding rectangle.
    pub fn align_top(self) -> Self {
        self.map_layout(|l| l.align_top())
    }

    /// Align the middle of the text with the middle of the bounding rect along the y axis..
    ///
    /// This is the default behaviour.
    pub fn align_middle_y(self) -> Self {
        self.map_layout(|l| l.align_middle_y())
    }

    /// Align the bottom edge of the text with the bottom edge of its bounding rectangle.
    pub fn align_bottom(self) -> Self {
        self.map_layout(|l| l.align_bottom())
    }

    /// Set all the parameters via an existing `Layout`
    pub fn layout(self, layout: &Layout) -> Self {
        self.map_layout(|l| l.layout(layout))
    }

    /// Specify the entire styling for the **Text**.
    pub fn with_style(mut self, style: Style) -> Self {
        self.style = style;
        self
    }
}

impl<'a, S> DrawingText<'a, S>
where
    S: BaseFloat,
{
    /// The font size to use for the text.
    pub fn font_size(self, size: text::FontSize) -> Self {
        self.map_ty(|ty| ty.font_size(size))
    }

    /// Specify that the **Text** should not wrap lines around the width.
    pub fn no_line_wrap(self) -> Self {
        self.map_ty(|ty| ty.no_line_wrap())
    }

    /// Line wrap the **Text** at the beginning of the first word that exceeds the width.
    pub fn wrap_by_word(self) -> Self {
        self.map_ty(|ty| ty.wrap_by_word())
    }

    /// Line wrap the **Text** at the beginning of the first character that exceeds the width.
    pub fn wrap_by_character(self) -> Self {
        self.map_ty(|ty| ty.wrap_by_character())
    }

    /// A method for specifying the `Font` used for displaying the `Text`.
    pub fn font(self, font: text::Font) -> Self {
        self.map_ty(|ty| ty.font(font))
    }

    /// Build the **Text** with the given **Style**.
    pub fn with_style(self, style: Style) -> Self {
        self.map_ty(|ty| ty.with_style(style))
    }

    /// Describe the end along the *x* axis to which the text should be aligned.
    pub fn justify(self, justify: text::Justify) -> Self {
        self.map_ty(|ty| ty.justify(justify))
    }

    /// Align the text to the left of its bounding **Rect**'s *x* axis range.
    pub fn left_justify(self) -> Self {
        self.map_ty(|ty| ty.left_justify())
    }

    /// Align the text to the middle of its bounding **Rect**'s *x* axis range.
    pub fn center_justify(self) -> Self {
        self.map_ty(|ty| ty.center_justify())
    }

    /// Align the text to the right of its bounding **Rect**'s *x* axis range.
    pub fn right_justify(self) -> Self {
        self.map_ty(|ty| ty.right_justify())
    }

    /// Specify how much vertical space should separate each line of text.
    pub fn line_spacing(self, spacing: text::Scalar) -> Self {
        self.map_ty(|ty| ty.line_spacing(spacing))
    }

    /// Specify how the whole text should be aligned along the y axis of its bounding rectangle
    pub fn y_align_text(self, align: Align) -> Self {
        self.map_ty(|ty| ty.y_align(align))
    }

    /// Align the top edge of the text with the top edge of its bounding rectangle.
    pub fn align_text_top(self) -> Self {
        self.map_ty(|ty| ty.align_top())
    }

    /// Align the middle of the text with the middle of the bounding rect along the y axis..
    ///
    /// This is the default behaviour.
    pub fn align_text_middle_y(self) -> Self {
        self.map_ty(|ty| ty.align_middle_y())
    }

    /// Align the bottom edge of the text with the bottom edge of its bounding rectangle.
    pub fn align_text_bottom(self) -> Self {
        self.map_ty(|ty| ty.align_bottom())
    }

    /// Set all the parameters via an existing `Layout`
    pub fn layout(self, layout: &Layout) -> Self {
        self.map_ty(|ty| ty.layout(layout))
    }
}

impl<S> IntoDrawn<S> for Text<S>
where
    S: BaseFloat,
{
    type Vertices = draw::properties::VerticesFromRanges;
    type Indices = draw::properties::IndicesFromRange;
    fn into_drawn(self, mut draw: Draw<S>) -> Drawn<S, Self::Vertices, Self::Indices> {
        let Text {
            spatial,
            style,
            text,
        } = self;
        let Style { color, layout } = style;
        let layout = layout.build();
        let (maybe_x, maybe_y, maybe_z) = spatial.dimensions.to_scalars(&draw);
        assert!(
            maybe_z.is_none(),
            "z dimension support for text is unimplemented"
        );
        let w = maybe_x
            .map(|s| <f32 as crate::math::NumCast>::from(s).unwrap())
            .unwrap_or(200.0);
        let h = maybe_y
            .map(|s| <f32 as crate::math::NumCast>::from(s).unwrap())
            .unwrap_or(200.0);
        let rect: geom::Rect = geom::Rect::from_wh(Vector2 { x: w, y: h });
        let color = color.unwrap_or_else(|| draw.theme().fill_lin_srgba(&theme::Primitive::Text));
        let path = draw.drawing_context(|ctxt| {
            let DrawingContext {
                mesh,
                fill_tessellator,
                path_event_buffer,
                text_buffer,
                glyph_cache,
            } = ctxt;
            let text_str = &text_buffer[text.clone()];
            let text = text::text(text_str).layout(&layout).build(rect);

            // TODO:
            // - Using `Path` is very slow - we should be caching glyphs.
            // - Can't do the CPU raster of the text here due to not knowing the DPI.
            // - We don't know the DPI until we finally draw to the frame.
            // - We should switch `Draw` to yield "primitives" rather than directly yielding
            //   vertices and indices. This way we can handle the text raster later on and can
            //   continue to ignore information about the window and DPI until finally drawing to
            //   the frame.
            use draw::primitive::path::PathInit;
            let path: PathInit<S> = Default::default();
            let mut empty_text = String::new();
            let ctxt = DrawingContext {
                mesh,
                fill_tessellator,
                path_event_buffer,
                glyph_cache,
                text_buffer: &mut empty_text,
            };
            let mut path = path.fill().color(color).events(ctxt, text.path_events());
            *SetPosition::properties(&mut path) = spatial.position;
            *SetOrientation::properties(&mut path) = spatial.orientation;
            path
        });
        path.into_drawn(draw)
    }
}

impl<S> SetOrientation<S> for Text<S> {
    fn properties(&mut self) -> &mut orientation::Properties<S> {
        SetOrientation::properties(&mut self.spatial)
    }
}

impl<S> SetPosition<S> for Text<S> {
    fn properties(&mut self) -> &mut position::Properties<S> {
        SetPosition::properties(&mut self.spatial)
    }
}

impl<S> SetDimensions<S> for Text<S> {
    fn properties(&mut self) -> &mut dimension::Properties<S> {
        SetDimensions::properties(&mut self.spatial)
    }
}

impl<S> SetColor<ColorScalar> for Text<S> {
    fn rgba_mut(&mut self) -> &mut Option<LinSrgba> {
        SetColor::rgba_mut(&mut self.style.color)
    }
}

// Primitive conversions.

impl<S> From<Text<S>> for Primitive<S> {
    fn from(prim: Text<S>) -> Self {
        Primitive::Text(prim)
    }
}

impl<S> Into<Option<Text<S>>> for Primitive<S> {
    fn into(self) -> Option<Text<S>> {
        match self {
            Primitive::Text(prim) => Some(prim),
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>extern crate cursive;

use cursive::{Cursive, Printer};
use cursive::traits::*;
use cursive::event::{Event, EventResult};

fn main() {
    let mut siv = Cursive::new();

    siv.add_layer(KeyCodeView::new(10).fixed_size((30, 10)));

    siv.run();
}

struct KeyCodeView {
    history: Vec<String>,
    size: usize,
}

impl KeyCodeView {
    fn new(size: usize) -> Self {
        KeyCodeView {
            history: Vec::new(),
            size: size,
        }
    }
}

impl View for KeyCodeView {
    fn draw(&self, printer: &Printer) {
        for (y, line) in self.history.iter().enumerate() {
            printer.print((0, y), line);
        }
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        let line = format!("{:?}", event);
        self.history.push(line);

        while self.history.len() > self.size {
            self.history.remove(0);
        }

        EventResult::Consumed(None)
    }
}
<commit_msg>Larger window for key_codes example<commit_after>extern crate cursive;

use cursive::{Cursive, Printer};
use cursive::traits::*;
use cursive::event::{Event, EventResult};

fn main() {
    let mut siv = Cursive::new();

    siv.add_layer(KeyCodeView::new(10).fixed_size((70, 10)));

    siv.run();
}

struct KeyCodeView {
    history: Vec<String>,
    size: usize,
}

impl KeyCodeView {
    fn new(size: usize) -> Self {
        KeyCodeView {
            history: Vec::new(),
            size: size,
        }
    }
}

impl View for KeyCodeView {
    fn draw(&self, printer: &Printer) {
        for (y, line) in self.history.iter().enumerate() {
            printer.print((0, y), line);
        }
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        let line = format!("{:?}", event);
        self.history.push(line);

        while self.history.len() > self.size {
            self.history.remove(0);
        }

        EventResult::Consumed(None)
    }
}
<|endoftext|>


<commit_before>use std::io::net::ip::{Ipv4Addr, SocketAddr};

mod libtorresmo {
    extern crate time;

    use std::io::net::udp::UdpSocket;
    use std::io::net::ip::SocketAddr;
    use std::io::IoResult;
    use std::mem::{to_be32, to_be16, transmute};
    use std::rand::random;

    #[allow(dead_code,non_camel_case_types)]
    enum UtpPacketType {
        ST_DATA  = 0,
        ST_FIN   = 1,
        ST_STATE = 2,
        ST_RESET = 3,
        ST_SYN   = 4,
    }

    #[allow(dead_code)]
    struct UtpPacketHeader {
        type_ver: u8, // type: u4, ver: u4
        extension: u8,
        connection_id: u16,
        timestamp_microseconds: u32,
        timestamp_difference_microseconds: u32,
        wnd_size: u32,
        seq_nr: u16,
        ack_nr: u16,
    }

    impl UtpPacketHeader {
        fn bytes(&self) -> &[u8] {
            unsafe {
                let buf: &[u8, ..20] = transmute(self);
                return buf.as_slice();
            }
        }

        fn len(&self) -> uint {
            static HEADER_SIZE: uint = 20;
            return HEADER_SIZE;
        }
    }

    #[allow(dead_code)]
    struct UtpPacket {
        header: UtpPacketHeader,
        payload: Vec<u8>,
    }

    impl UtpPacket {
        /// Constructs a new, empty UtpPacket.
        fn new() -> UtpPacket {
            UtpPacket {
                header: UtpPacketHeader {
                    type_ver: ST_DATA as u8 << 4 | 1,
                    extension: 0,
                    connection_id: 0,
                    timestamp_microseconds: 0,
                    timestamp_difference_microseconds: 0,
                    wnd_size: 0,
                    seq_nr: 0,
                    ack_nr: 0,
                },
                payload: Vec::new(),
            }
        }

        fn bytes(&self) -> Vec<u8> {
            let mut buf: Vec<u8> = Vec::with_capacity(self.len());
            buf.push_all(self.header.bytes());
            buf.push_all(self.payload.as_slice());
            return buf;
        }

        fn len(&self) -> uint {
            self.header.len() + self.payload.len()
        }
    }

    pub struct UtpSocket {
        socket: UdpSocket,
        seq_nr: u16,
    }

    impl UtpSocket {
        pub fn bind(addr: SocketAddr) -> IoResult<UtpSocket> {
            let skt = UdpSocket::bind(addr);
            match skt {
                Ok(x)  => Ok(UtpSocket { socket: x, seq_nr: 1 }),
                Err(e) => Err(e)
            }
        }

        pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
            let mut packet = UtpPacket::new();
            packet.payload = Vec::from_slice(buf);
            packet.header.seq_nr = to_be16(self.seq_nr);
            packet.header.connection_id = to_be16(random());
            let t = time::get_time();
            packet.header.timestamp_microseconds = to_be32((t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32);

            // Send packet
            let result = self.socket.sendto(packet.bytes().as_slice(), dst);

            self.seq_nr += 1;
            result
        }

        pub fn recvfrom(&mut self, buf: &mut[u8]) -> IoResult<(uint,SocketAddr)> {
            self.socket.recvfrom(buf)
        }
    }

    impl Clone for UtpSocket {
        fn clone(&self) -> UtpSocket {
            UtpSocket {
                socket: self.socket.clone(),
                seq_nr: self.seq_nr,
            }
        }
    }
}

fn main() {
    use libtorresmo::{UtpSocket};
    use std::from_str::FromStr;

    // Defaults
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();

    if args.len() > 1 {
        let ip = FromStr::from_str(args.get(1).as_slice()).unwrap();
        let port = FromStr::from_str(args.get(2).as_slice()).unwrap();
        addr = SocketAddr { ip: ip, port: port };
    }

    let mut buf = [0, ..512];
    let sock = UtpSocket::bind(addr).unwrap();
    println!("Serving on {}", addr);

    loop {
        let mut sock = sock.clone();
        match sock.recvfrom(buf) {
            Ok((_, src)) => {
                spawn(proc() {
                    let mut sock = sock;
                    let payload = String::from_str("Hello\n").into_bytes();

                    // Send uTP packet
                    let _ = sock.sendto(payload.as_slice(), src);
                })
            }
            Err(_) => {}
        }
    }
    drop(sock);
}
<commit_msg>Add client and server modes.<commit_after>use std::io::net::ip::{Ipv4Addr, SocketAddr};

mod libtorresmo {
    extern crate time;

    use std::io::net::udp::UdpSocket;
    use std::io::net::ip::SocketAddr;
    use std::io::IoResult;
    use std::mem::{to_be32, to_be16, transmute};
    use std::rand::random;

    #[allow(dead_code,non_camel_case_types)]
    enum UtpPacketType {
        ST_DATA  = 0,
        ST_FIN   = 1,
        ST_STATE = 2,
        ST_RESET = 3,
        ST_SYN   = 4,
    }

    #[allow(dead_code)]
    struct UtpPacketHeader {
        type_ver: u8, // type: u4, ver: u4
        extension: u8,
        connection_id: u16,
        timestamp_microseconds: u32,
        timestamp_difference_microseconds: u32,
        wnd_size: u32,
        seq_nr: u16,
        ack_nr: u16,
    }

    impl UtpPacketHeader {
        fn bytes(&self) -> &[u8] {
            unsafe {
                let buf: &[u8, ..20] = transmute(self);
                return buf.as_slice();
            }
        }

        fn len(&self) -> uint {
            static HEADER_SIZE: uint = 20;
            return HEADER_SIZE;
        }
    }

    #[allow(dead_code)]
    struct UtpPacket {
        header: UtpPacketHeader,
        payload: Vec<u8>,
    }

    impl UtpPacket {
        /// Constructs a new, empty UtpPacket.
        fn new() -> UtpPacket {
            UtpPacket {
                header: UtpPacketHeader {
                    type_ver: ST_DATA as u8 << 4 | 1,
                    extension: 0,
                    connection_id: 0,
                    timestamp_microseconds: 0,
                    timestamp_difference_microseconds: 0,
                    wnd_size: 0,
                    seq_nr: 0,
                    ack_nr: 0,
                },
                payload: Vec::new(),
            }
        }

        fn bytes(&self) -> Vec<u8> {
            let mut buf: Vec<u8> = Vec::with_capacity(self.len());
            buf.push_all(self.header.bytes());
            buf.push_all(self.payload.as_slice());
            return buf;
        }

        fn len(&self) -> uint {
            self.header.len() + self.payload.len()
        }
    }

    pub struct UtpSocket {
        socket: UdpSocket,
        seq_nr: u16,
    }

    impl UtpSocket {
        pub fn bind(addr: SocketAddr) -> IoResult<UtpSocket> {
            let skt = UdpSocket::bind(addr);
            match skt {
                Ok(x)  => Ok(UtpSocket { socket: x, seq_nr: 1 }),
                Err(e) => Err(e)
            }
        }

        pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
            let mut packet = UtpPacket::new();
            packet.payload = Vec::from_slice(buf);
            packet.header.seq_nr = to_be16(self.seq_nr);
            packet.header.connection_id = to_be16(random());
            let t = time::get_time();
            packet.header.timestamp_microseconds = to_be32((t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32);

            // Send packet
            let result = self.socket.sendto(packet.bytes().as_slice(), dst);

            self.seq_nr += 1;
            result
        }

        pub fn recvfrom(&mut self, buf: &mut[u8]) -> IoResult<(uint,SocketAddr)> {
            self.socket.recvfrom(buf)
        }
    }

    impl Clone for UtpSocket {
        fn clone(&self) -> UtpSocket {
            UtpSocket {
                socket: self.socket.clone(),
                seq_nr: self.seq_nr,
            }
        }
    }
}

fn usage() {
    println!("Usage: torresmo [-s|-c] <address> <port>");
}

fn main() {
    use libtorresmo::{UtpSocket};
    use std::from_str::FromStr;

    // Defaults
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();

    if args.len() == 4 {
        let ip = FromStr::from_str(args.get(2).as_slice()).unwrap();
        let port = FromStr::from_str(args.get(3).as_slice()).unwrap();
        addr = SocketAddr { ip: ip, port: port };
    }

    match args.get(1).as_slice() {
        "-s" => {
            let mut buf = [0, ..512];
            let sock = UtpSocket::bind(addr).unwrap();
            println!("Serving on {}", addr);

            loop {
                let mut sock = sock.clone();
                match sock.recvfrom(buf) {
                    Ok((_, src)) => {
                        spawn(proc() {
                            let mut sock = sock;
                            let payload = String::from_str("Hello\n").into_bytes();

                            // Send uTP packet
                            let _ = sock.sendto(payload.as_slice(), src);
                        })
                    }
                    Err(_) => {}
                }
            }
        }
        "-c" => {
            let mut sock = UtpSocket::bind(SocketAddr { ip: Ipv4Addr(127,0,0,1), port: std::rand::random() }).unwrap();
            let _ = sock.sendto([0], addr);
            drop(sock);
        }
        _ => usage(),
    }
}
<|endoftext|>


<commit_before>use std::fs;
use std::path::PathBuf;
use std::sync::Arc;

use config::Config;
use dir_pool::{DirPool, HeldDir};
use git::Git;
use github;

// clones git repos with given github session into a managed directory pool
pub struct GitCloneManager {
    dir_pool: Arc<DirPool>,
    github_session: Arc<github::api::Session>,
}

impl GitCloneManager {
    pub fn new(github_session: Arc<github::api::Session>, config: Arc<Config>) -> GitCloneManager {
        let clone_root_dir = config.main.clone_root_dir.to_string();

        GitCloneManager {
            dir_pool: Arc::new(DirPool::new(&clone_root_dir)),
            github_session: github_session.clone(),
        }
    }

    pub fn clone(&self, owner: &str, repo: &str) -> Result<HeldDir, String> {
        let held_clone_dir = self.dir_pool.take_directory(self.github_session.github_host(), owner, repo);
        try!(self.clone_repo(owner, repo, &held_clone_dir.dir()));

        Ok(held_clone_dir)
    }

    fn clone_repo(&self, owner: &str, repo: &str, clone_dir: &PathBuf) -> Result<(), String> {
        let url = format!("https://{}@{}/{}/{}",
                          self.github_session.user().login(),
                          self.github_session.github_host(),
                          owner,
                          repo);

        let git = Git::new(self.github_session.github_host(),
                           self.github_session.github_token(),
                           clone_dir);

        if clone_dir.join(".git").exists() {
            try!(git.run(&["fetch", "--prune"]));
        } else {
            if let Err(e) = fs::create_dir_all(&clone_dir) {
                return Err(format!("Error creating clone directory '{:?}': {}", clone_dir, e));
            }
            try!(git.run(&["clone", &url, "."]));
        }

        // always fetch latest tags
        try!(git.run(&["fetch", "--tags"]));
        // clean up state
        try!(git.clean());

        Ok(())
    }
}
<commit_msg>Prune old tags on fetch to avoid stale tags and bad versions (#118)<commit_after>use std::fs;
use std::path::PathBuf;
use std::sync::Arc;

use config::Config;
use dir_pool::{DirPool, HeldDir};
use git::Git;
use github;

// clones git repos with given github session into a managed directory pool
pub struct GitCloneManager {
    dir_pool: Arc<DirPool>,
    github_session: Arc<github::api::Session>,
}

impl GitCloneManager {
    pub fn new(github_session: Arc<github::api::Session>, config: Arc<Config>) -> GitCloneManager {
        let clone_root_dir = config.main.clone_root_dir.to_string();

        GitCloneManager {
            dir_pool: Arc::new(DirPool::new(&clone_root_dir)),
            github_session: github_session.clone(),
        }
    }

    pub fn clone(&self, owner: &str, repo: &str) -> Result<HeldDir, String> {
        let held_clone_dir = self.dir_pool.take_directory(self.github_session.github_host(), owner, repo);
        try!(self.clone_repo(owner, repo, &held_clone_dir.dir()));

        Ok(held_clone_dir)
    }

    fn clone_repo(&self, owner: &str, repo: &str, clone_dir: &PathBuf) -> Result<(), String> {
        let url = format!("https://{}@{}/{}/{}",
                          self.github_session.user().login(),
                          self.github_session.github_host(),
                          owner,
                          repo);

        let git = Git::new(self.github_session.github_host(),
                           self.github_session.github_token(),
                           clone_dir);

        if clone_dir.join(".git").exists() {
            // prune local tags deleted from remotes: important to avoid stale/bad version tags
            try!(git.run(&["fetch", "--prune", "+refs/tags/*:refs/tags/*"]));
        } else {
            if let Err(e) = fs::create_dir_all(&clone_dir) {
                return Err(format!("Error creating clone directory '{:?}': {}", clone_dir, e));
            }
            try!(git.run(&["clone", &url, "."]));
        }

        // always fetch latest tags
        try!(git.run(&["fetch", "--tags"]));
        // clean up state
        try!(git.clean());

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